Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/__tests__/docs-destination.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import os from 'node:os';
import path from 'node:path';
import { resolveDocsDestination } from '../resources/docs.js';
import type { LocalConfig, TeamaiConfig } from '../types.js';

function teamConfig(localDir: string): TeamaiConfig {
return { sharing: { docs: { localDir } } } as TeamaiConfig;
}

function localConfig(scope: 'user' | 'project', projectRoot?: string): LocalConfig {
return { scope, ...(projectRoot ? { projectRoot } : {}) } as LocalConfig;
}

describe('resolveDocsDestination', () => {
const homeDir = path.join(os.tmpdir(), 'teamai-docs-destination-home');

beforeEach(() => {
vi.stubEnv('HOME', homeDir);
});

afterEach(() => {
vi.unstubAllEnvs();
});

it('anchors a project-relative directory to the workspace root', () => {
const projectRoot = path.join(os.tmpdir(), 'teamai-docs-project');

expect(
resolveDocsDestination(teamConfig('./.teamai/docs'), localConfig('project', projectRoot)),
).toBe(path.resolve(projectRoot, '.teamai/docs'));
});

it('anchors a user-relative directory to the user home', () => {
expect(resolveDocsDestination(teamConfig('./.teamai/docs'), localConfig('user'))).toBe(
path.resolve(homeDir, '.teamai/docs'),
);
});

it('preserves project tilde and absolute destinations', () => {
const projectRoot = path.join(os.tmpdir(), 'teamai-docs-project');
const absolute = path.resolve(os.tmpdir(), 'teamai-docs-absolute');

expect(resolveDocsDestination(teamConfig('~/team-docs'), localConfig('project', projectRoot))).toBe(
path.join(projectRoot, 'team-docs'),
);
expect(resolveDocsDestination(teamConfig(absolute), localConfig('user'))).toBe(absolute);
});
});
5 changes: 3 additions & 2 deletions src/resources/docs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from 'node:path';
import fse from 'fs-extra';
import { ResourceHandler } from './base.js';
import type { ResourceItem, TeamaiConfig, LocalConfig } from '../types.js';
import { resolveBaseDir, type ResourceItem, type TeamaiConfig, type LocalConfig } from '../types.js';
import { expandHome, listFilesRecursive } from '../utils/fs.js';
import { log } from '../utils/logger.js';

Expand All @@ -15,7 +15,8 @@ export function resolveDocsDestination(teamConfig: TeamaiConfig, localConfig: Lo
if (localConfig.scope === 'project' && localConfig.projectRoot && localDir.startsWith('~/')) {
return path.join(localConfig.projectRoot, localDir.substring(2));
}
return expandHome(localDir);
const expanded = expandHome(localDir);
return path.isAbsolute(expanded) ? expanded : path.resolve(resolveBaseDir(localConfig), expanded);
}

export class DocsHandler extends ResourceHandler {
Expand Down
11 changes: 2 additions & 9 deletions src/uninstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
import { BUILTIN_RULE_NAMES } from './builtin-rules.js';
import { ruleStemFromFilename } from './resources/rule-format.js';
import { agentStemFromFilename } from './resources/agent-format.js';
import { resolveDocsDestination } from './resources/docs.js';
import { listTeamAgentDirs } from './resources/agents.js';
import { BUILTIN_AGENT_NAMES } from './builtin-agents.js';
import { BUILTIN_SKILL_NAMES } from './builtin-skills.js';
Expand Down Expand Up @@ -528,15 +529,7 @@ async function buildRemovalPlan(
}

// (f) Docs directory
const docsLocalDir = teamConfig.sharing.docs.localDir;
let docsDir: string;
if (localConfig.scope === 'project' && localConfig.projectRoot) {
docsDir = docsLocalDir.startsWith('~/')
? path.join(localConfig.projectRoot, docsLocalDir.substring(2))
: expandHome(docsLocalDir);
} else {
docsDir = expandHome(docsLocalDir);
}
const docsDir = resolveDocsDestination(teamConfig, localConfig);
if (await pathExists(docsDir)) {
plan.docsDir = docsDir;
}
Expand Down
Loading