@agentteams/cli 0.1.99 → 0.1.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.eslintcache +1 -1
  2. package/README.md +0 -12
  3. package/dist/api/coaction.d.ts +1 -1
  4. package/dist/api/coaction.d.ts.map +1 -1
  5. package/dist/api/coaction.js +3 -1
  6. package/dist/api/coaction.js.map +1 -1
  7. package/dist/api/codeReview.d.ts +1 -0
  8. package/dist/api/codeReview.d.ts.map +1 -1
  9. package/dist/api/codeReview.js +6 -0
  10. package/dist/api/codeReview.js.map +1 -1
  11. package/dist/api/plan.d.ts +0 -5
  12. package/dist/api/plan.d.ts.map +1 -1
  13. package/dist/api/plan.js +0 -5
  14. package/dist/api/plan.js.map +1 -1
  15. package/dist/api/skill.d.ts +25 -0
  16. package/dist/api/skill.d.ts.map +1 -0
  17. package/dist/api/skill.js +40 -0
  18. package/dist/api/skill.js.map +1 -0
  19. package/dist/commands/codeReview.d.ts.map +1 -1
  20. package/dist/commands/codeReview.js +14 -1
  21. package/dist/commands/codeReview.js.map +1 -1
  22. package/dist/commands/convention.d.ts +6 -1
  23. package/dist/commands/convention.d.ts.map +1 -1
  24. package/dist/commands/convention.js +64 -16
  25. package/dist/commands/convention.js.map +1 -1
  26. package/dist/commands/index.d.ts.map +1 -1
  27. package/dist/commands/index.js +9 -0
  28. package/dist/commands/index.js.map +1 -1
  29. package/dist/commands/plan.d.ts +0 -12
  30. package/dist/commands/plan.d.ts.map +1 -1
  31. package/dist/commands/plan.js +1 -103
  32. package/dist/commands/plan.js.map +1 -1
  33. package/dist/commands/skill.d.ts +5 -0
  34. package/dist/commands/skill.d.ts.map +1 -0
  35. package/dist/commands/skill.js +251 -0
  36. package/dist/commands/skill.js.map +1 -0
  37. package/dist/mcp/guides.d.ts +1 -1
  38. package/dist/mcp/guides.d.ts.map +1 -1
  39. package/dist/mcp/guides.js +3 -1
  40. package/dist/mcp/guides.js.map +1 -1
  41. package/dist/mcp/localTools.d.ts.map +1 -1
  42. package/dist/mcp/localTools.js +1 -1
  43. package/dist/mcp/localTools.js.map +1 -1
  44. package/dist/mcp/tools.d.ts.map +1 -1
  45. package/dist/mcp/tools.js +5 -1
  46. package/dist/mcp/tools.js.map +1 -1
  47. package/dist/mcp/writeTools.d.ts.map +1 -1
  48. package/dist/mcp/writeTools.js +207 -0
  49. package/dist/mcp/writeTools.js.map +1 -1
  50. package/dist/program/codeReview.d.ts +1 -1
  51. package/dist/program/codeReview.d.ts.map +1 -1
  52. package/dist/program/codeReview.js +2 -1
  53. package/dist/program/codeReview.js.map +1 -1
  54. package/dist/program/index.d.ts.map +1 -1
  55. package/dist/program/index.js +2 -0
  56. package/dist/program/index.js.map +1 -1
  57. package/dist/program/plan.d.ts +1 -1
  58. package/dist/program/plan.d.ts.map +1 -1
  59. package/dist/program/plan.js +1 -12
  60. package/dist/program/plan.js.map +1 -1
  61. package/dist/program/shared.d.ts.map +1 -1
  62. package/dist/program/shared.js +5 -0
  63. package/dist/program/shared.js.map +1 -1
  64. package/dist/program/skill.d.ts +4 -0
  65. package/dist/program/skill.d.ts.map +1 -0
  66. package/dist/program/skill.js +48 -0
  67. package/dist/program/skill.js.map +1 -0
  68. package/dist/utils/skillPackage.d.ts +80 -0
  69. package/dist/utils/skillPackage.d.ts.map +1 -0
  70. package/dist/utils/skillPackage.js +287 -0
  71. package/dist/utils/skillPackage.js.map +1 -0
  72. package/package.json +2 -2
  73. package/dist/utils/planPreviewHtmlSafety.d.ts +0 -8
  74. package/dist/utils/planPreviewHtmlSafety.d.ts.map +0 -1
  75. package/dist/utils/planPreviewHtmlSafety.js +0 -40
  76. package/dist/utils/planPreviewHtmlSafety.js.map +0 -1
@@ -0,0 +1,48 @@
1
+ import { CONVENTION_HINT, executeCommand, handleError, printCommandResult } from './shared.js';
2
+ import { addOutputOptions } from './options/output.js';
3
+ /** 액션 인벤토리: list/show/download/status/create/update/delete. */
4
+ export function registerSkillCommand(program) {
5
+ const root = program
6
+ .command('skill')
7
+ .description('Manage project skill packages')
8
+ .addHelpText('after', CONVENTION_HINT);
9
+ const addLeaf = (name, description, configure = (command) => command) => {
10
+ const command = addOutputOptions(configure(root.command(name).description(description))).addHelpText('after', CONVENTION_HINT);
11
+ command.action(async (options) => {
12
+ try {
13
+ const { outputFile, verbose, ...actionOptions } = options;
14
+ const result = await executeCommand('skill', name, {
15
+ ...actionOptions,
16
+ cwd: actionOptions.cwd ?? process.cwd(),
17
+ });
18
+ printCommandResult({ result, resource: 'skill', action: name, outputFile, verbose });
19
+ }
20
+ catch (error) {
21
+ console.error(handleError(error));
22
+ process.exit(1);
23
+ }
24
+ });
25
+ return command;
26
+ };
27
+ const addCwd = (command) => command.option('--cwd <path>', 'Working directory (defaults to current)');
28
+ const addPackageSource = (command) => addCwd(command)
29
+ .option('--dir <path>', 'Skill package directory (contains SKILL.md)')
30
+ .option('-f, --file <path>', 'Path to SKILL.md (its parent directory is the package root)')
31
+ .option('--apply', 'Apply the change on the server (default: dry-run)', false);
32
+ addLeaf('list', 'List project skills', (command) => addCwd(command)
33
+ .option('--search <keyword>', 'Filter by keyword')
34
+ .option('--page <number>', 'Page number')
35
+ .option('--page-size <number>', 'Page size'));
36
+ addLeaf('show', 'Show one skill', (command) => addCwd(command).option('--id <id>', 'Skill ID'));
37
+ addLeaf('download', 'Sync every skill package into .agentteams/skills/', (command) => addCwd(command)
38
+ .option('--skill-targets <targets>', "Mirror targets: comma-separated list of agents,claude,github or 'none' (default: detected from marker directories)")
39
+ .option('--commit-mirrors', 'Do not add mirror directories to .gitignore', false));
40
+ addLeaf('status', 'Show which skill packages are new, updated, or deleted', (command) => addCwd(command));
41
+ addLeaf('create', 'Create a skill from a local package directory', (command) => addPackageSource(command)
42
+ .option('--slug <slug>', 'Package slug (defaults to the directory name)')
43
+ .option('--repository-id <id>', 'Link the skill to a repository')
44
+ .option('--scope <scope>', 'PROJECT or PERSONAL'));
45
+ addLeaf('update', 'Replace a skill package from a local directory', (command) => addPackageSource(command).option('--id <id>', 'Skill ID').option('--scope <scope>', 'PROJECT or PERSONAL'));
46
+ addLeaf('delete', 'Delete a skill', (command) => addCwd(command).option('--id <id>', 'Skill ID').option('--apply', 'Apply the deletion on the server', false));
47
+ }
48
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/program/skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Skill 패키지의 로컬 소유권과 원자적 교체. `.agentteams/skills/<slug>/`의 유일한 소유자는
3
+ * 이 모듈이며, `convention download`의 카테고리 sweep은 이 디렉터리를 건드리지 않는다.
4
+ *
5
+ * 계약(진입 파일, 허용 디렉터리, 크기 상한)의 SSOT는 서버가 배포하는 skill-package-guide.md다.
6
+ * CLI는 같은 규칙을 API 호출 **전에** 한 번 더 적용해, 잘못된 패키지가 네트워크를 타기 전에
7
+ * 사용자에게 이유를 알려준다. 최종 판정은 여전히 서버가 한다.
8
+ */
9
+ /** `.agentteams` 아래 스킬 패키지 루트 디렉터리 이름. */
10
+ export declare const SKILL_PACKAGE_DIR = "skills";
11
+ /** 스킬 manifest 파일명. conventions.manifest.json 스키마는 건드리지 않는다(D7). */
12
+ export declare const SKILL_MANIFEST_FILE = "skills.manifest.json";
13
+ export declare const SKILL_ENTRY_FILE = "SKILL.md";
14
+ export declare const SKILL_RESOURCE_DIRS: readonly ["references", "scripts"];
15
+ export declare const SKILL_LIMITS: {
16
+ readonly entryFileBytes: number;
17
+ readonly resourceFileBytes: number;
18
+ readonly fileCount: 50;
19
+ readonly totalBytes: number;
20
+ readonly pathLength: 200;
21
+ };
22
+ export type SkillPackageFile = {
23
+ relativePath: string;
24
+ content: string;
25
+ };
26
+ /** mirror 대상. 값은 `--skill-targets` 토큰과 1:1로 대응한다. */
27
+ export declare const SKILL_MIRROR_TARGETS: readonly ["agents", "claude", "github"];
28
+ export type SkillMirrorTarget = (typeof SKILL_MIRROR_TARGETS)[number];
29
+ export declare const SKILL_TARGETS_NONE = "none";
30
+ export type SkillManifestEntry = {
31
+ skillId: string;
32
+ slug: string;
33
+ version: string;
34
+ /** 프로젝트 루트 기준 상대 경로. 이 목록에 있는 파일만 CLI가 지운다. */
35
+ mirrorPaths: string[];
36
+ };
37
+ export type SkillDownloadManifestV1 = {
38
+ version: 1;
39
+ generatedAt: string;
40
+ entries: SkillManifestEntry[];
41
+ };
42
+ export declare class SkillPackageError extends Error {
43
+ constructor(message: string);
44
+ }
45
+ export declare const skillPackageRoot: (projectRoot: string) => string;
46
+ export declare const skillManifestPath: (projectRoot: string) => string;
47
+ /**
48
+ * `--skill-targets` 파싱. 문법은 `--agent-files`와 같다: 콤마 구분 목록 또는 `none`.
49
+ * 지정하지 않으면 null을 돌려주고, 호출부가 마커 탐지 기본값을 쓴다.
50
+ */
51
+ export declare const parseSkillTargetsOption: (raw: unknown) => SkillMirrorTarget[] | null;
52
+ /** 마커가 실재하는 클라이언트만 고른다. `.agents`는 마커 없이도 항상 포함된다. */
53
+ export declare const detectSkillMirrorTargets: (projectRoot: string) => SkillMirrorTarget[];
54
+ export declare const mirrorDirFor: (projectRoot: string, target: SkillMirrorTarget, slug: string) => string;
55
+ export declare const computeSkillVersion: (files: {
56
+ relativePath: string;
57
+ content: string;
58
+ }[]) => string;
59
+ /** 패키지 계약을 로컬에서 먼저 적용한다. 실패 사유는 서버 메시지와 같은 축을 쓴다. */
60
+ export declare const validateSkillPackageFiles: (files: SkillPackageFile[]) => void;
61
+ /**
62
+ * 로컬 디렉터리에서 패키지 파일을 모은다. symlink는 따라가지 않는다 — 링크가 패키지 밖을
63
+ * 가리키면 저장소 밖 파일이 업로드된다.
64
+ */
65
+ export declare const collectSkillPackageFiles: (packageDir: string) => SkillPackageFile[];
66
+ export declare const readSkillManifest: (projectRoot: string) => SkillDownloadManifestV1;
67
+ export declare const writeSkillManifest: (projectRoot: string, manifest: SkillDownloadManifestV1) => void;
68
+ /**
69
+ * 임시 디렉터리에 전부 쓴 뒤 한 번에 교체한다. 쓰기 도중 실패하면 기존 디렉터리는
70
+ * byte-for-byte 그대로 남는다 — 부분 적용된 패키지는 "설치됐지만 깨진" 상태를 만든다.
71
+ */
72
+ export declare const writePackageAtomically: (targetDir: string, files: SkillPackageFile[]) => void;
73
+ /** manifest에 기록된 경로만 지운다. 사용자가 mirror 디렉터리에 둔 파일은 건드리지 않는다. */
74
+ export declare const removeManifestPaths: (projectRoot: string, relativePaths: string[]) => void;
75
+ /**
76
+ * mirror 디렉터리를 `.gitignore`에 넣는다. mirror는 `.agentteams/skills/`에서 파생된 사본이라
77
+ * 커밋 대상이 아니다. `--commit-mirrors`를 준 프로젝트는 이 호출을 건너뛴다.
78
+ */
79
+ export declare const ensureMirrorGitignore: (projectRoot: string, targets: SkillMirrorTarget[]) => void;
80
+ //# sourceMappingURL=skillPackage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillPackage.d.ts","sourceRoot":"","sources":["../../src/utils/skillPackage.ts"],"names":[],"mappings":"AAaA;;;;;;;GAOG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAC3C,eAAO,MAAM,mBAAmB,oCAAqC,CAAC;AAEtE,eAAO,MAAM,YAAY;;;;;;CAMf,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,yCAA0C,CAAC;AAC5E,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACtE,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAgBzC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,CAAC,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,KAAG,MAA6D,CAAC;AAErH,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,MAA+D,CAAC;AAExH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,KAAK,OAAO,KAAG,iBAAiB,EAAE,GAAG,IAmC5E,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,wBAAwB,GAAI,aAAa,MAAM,KAAG,iBAAiB,EAW/E,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,EAAE,QAAQ,iBAAiB,EAAE,MAAM,MAAM,KAAG,MACzC,CAAC;AAIpD,eAAO,MAAM,mBAAmB,GAAI,OAAO;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,KAAG,MAUxF,CAAC;AA0BF,qDAAqD;AACrD,eAAO,MAAM,yBAAyB,GAAI,OAAO,gBAAgB,EAAE,KAAG,IAwCrE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,YAAY,MAAM,KAAG,gBAAgB,EA2B7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,uBAiBvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,aAAa,MAAM,EAAE,UAAU,uBAAuB,KAAG,IAI3F,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,OAAO,gBAAgB,EAAE,KAAG,IAsCrF,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,EAAE,eAAe,MAAM,EAAE,KAAG,IASlF,CAAC;AAIF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,MAAM,EAAE,SAAS,iBAAiB,EAAE,KAAG,IAiBzF,CAAC"}
@@ -0,0 +1,287 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync, } from 'node:fs';
3
+ import { dirname, join, relative, resolve, sep } from 'node:path';
4
+ /**
5
+ * Skill 패키지의 로컬 소유권과 원자적 교체. `.agentteams/skills/<slug>/`의 유일한 소유자는
6
+ * 이 모듈이며, `convention download`의 카테고리 sweep은 이 디렉터리를 건드리지 않는다.
7
+ *
8
+ * 계약(진입 파일, 허용 디렉터리, 크기 상한)의 SSOT는 서버가 배포하는 skill-package-guide.md다.
9
+ * CLI는 같은 규칙을 API 호출 **전에** 한 번 더 적용해, 잘못된 패키지가 네트워크를 타기 전에
10
+ * 사용자에게 이유를 알려준다. 최종 판정은 여전히 서버가 한다.
11
+ */
12
+ /** `.agentteams` 아래 스킬 패키지 루트 디렉터리 이름. */
13
+ export const SKILL_PACKAGE_DIR = 'skills';
14
+ /** 스킬 manifest 파일명. conventions.manifest.json 스키마는 건드리지 않는다(D7). */
15
+ export const SKILL_MANIFEST_FILE = 'skills.manifest.json';
16
+ export const SKILL_ENTRY_FILE = 'SKILL.md';
17
+ export const SKILL_RESOURCE_DIRS = ['references', 'scripts'];
18
+ export const SKILL_LIMITS = {
19
+ entryFileBytes: 64 * 1024,
20
+ resourceFileBytes: 256 * 1024,
21
+ fileCount: 50,
22
+ totalBytes: 2 * 1024 * 1024,
23
+ pathLength: 200,
24
+ };
25
+ /** mirror 대상. 값은 `--skill-targets` 토큰과 1:1로 대응한다. */
26
+ export const SKILL_MIRROR_TARGETS = ['agents', 'claude', 'github'];
27
+ export const SKILL_TARGETS_NONE = 'none';
28
+ /**
29
+ * mirror 경로와 게이팅 규칙.
30
+ *
31
+ * `.agents/`는 벤더 중립 경로라 항상 쓴다(COPILOT_CLI·AMP·CODEX·OPENCODE·GROK_BUILD가 직접
32
+ * 읽는다 — 2026-08-15 프로브 실측. 판정 근거는 skill-package-guide.md §4).
33
+ * 나머지 둘은 해당 클라이언트의 마커 디렉터리가 **실재할 때만** 쓴다. 마커도 없는데 디렉터리를
34
+ * 만들면 그 저장소는 쓰지도 않는 도구를 위해 설정된 것처럼 보인다.
35
+ */
36
+ const MIRROR_SPECS = {
37
+ agents: { dir: join('.agents', 'skills'), markerDir: null },
38
+ claude: { dir: join('.claude', 'skills'), markerDir: '.claude' },
39
+ github: { dir: join('.github', 'skills'), markerDir: '.github' },
40
+ };
41
+ export class SkillPackageError extends Error {
42
+ constructor(message) {
43
+ super(message);
44
+ this.name = 'SkillPackageError';
45
+ }
46
+ }
47
+ export const skillPackageRoot = (projectRoot) => join(projectRoot, '.agentteams', SKILL_PACKAGE_DIR);
48
+ export const skillManifestPath = (projectRoot) => join(projectRoot, '.agentteams', SKILL_MANIFEST_FILE);
49
+ /**
50
+ * `--skill-targets` 파싱. 문법은 `--agent-files`와 같다: 콤마 구분 목록 또는 `none`.
51
+ * 지정하지 않으면 null을 돌려주고, 호출부가 마커 탐지 기본값을 쓴다.
52
+ */
53
+ export const parseSkillTargetsOption = (raw) => {
54
+ if (raw === undefined || raw === null)
55
+ return null;
56
+ if (typeof raw !== 'string') {
57
+ throw new SkillPackageError(`Invalid --skill-targets value. Expected a comma-separated list or '${SKILL_TARGETS_NONE}'.`);
58
+ }
59
+ const tokens = raw
60
+ .split(',')
61
+ .map((token) => token.trim())
62
+ .filter((token) => token.length > 0);
63
+ if (tokens.length === 0)
64
+ return null;
65
+ if (tokens.some((token) => token.toLowerCase() === SKILL_TARGETS_NONE)) {
66
+ if (tokens.length > 1) {
67
+ throw new SkillPackageError(`Invalid --skill-targets value: '${SKILL_TARGETS_NONE}' cannot be combined with other targets.`);
68
+ }
69
+ return [];
70
+ }
71
+ const selected = [];
72
+ for (const token of tokens) {
73
+ const match = SKILL_MIRROR_TARGETS.find((value) => value === token.toLowerCase());
74
+ if (!match) {
75
+ throw new SkillPackageError(`Unknown --skill-targets value: '${token}'. Valid values: ${SKILL_MIRROR_TARGETS.join(', ')}, ${SKILL_TARGETS_NONE}.`);
76
+ }
77
+ if (!selected.includes(match))
78
+ selected.push(match);
79
+ }
80
+ return selected;
81
+ };
82
+ /** 마커가 실재하는 클라이언트만 고른다. `.agents`는 마커 없이도 항상 포함된다. */
83
+ export const detectSkillMirrorTargets = (projectRoot) => {
84
+ return SKILL_MIRROR_TARGETS.filter((target) => {
85
+ const { markerDir } = MIRROR_SPECS[target];
86
+ if (!markerDir)
87
+ return true;
88
+ const markerPath = join(projectRoot, markerDir);
89
+ try {
90
+ return lstatSync(markerPath).isDirectory();
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ });
96
+ };
97
+ export const mirrorDirFor = (projectRoot, target, slug) => join(projectRoot, MIRROR_SPECS[target].dir, slug);
98
+ const sha256 = (content) => createHash('sha256').update(content, 'utf8').digest('hex');
99
+ export const computeSkillVersion = (files) => {
100
+ const normalized = [...files]
101
+ .map((file) => ({ relativePath: file.relativePath, hash: sha256(file.content) }))
102
+ .sort((left, right) => left.relativePath === right.relativePath ? 0 : left.relativePath < right.relativePath ? -1 : 1)
103
+ .map((file) => `${file.relativePath}:${file.hash}`)
104
+ .join('\n');
105
+ return sha256(normalized);
106
+ };
107
+ const assertSafeRelativePath = (relativePath) => {
108
+ if (relativePath.length === 0 || relativePath.length > SKILL_LIMITS.pathLength) {
109
+ throw new SkillPackageError(`Invalid path length: ${relativePath}`);
110
+ }
111
+ if (relativePath.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(relativePath) || relativePath.includes('\\')) {
112
+ throw new SkillPackageError(`Path must be relative and use "/" as the separator: ${relativePath}`);
113
+ }
114
+ const segments = relativePath.split('/');
115
+ if (segments.some((segment) => segment === '..' || segment === '.' || segment === '')) {
116
+ throw new SkillPackageError(`Path must be normalized and must not traverse upward: ${relativePath}`);
117
+ }
118
+ if (segments.length === 1) {
119
+ if (relativePath !== SKILL_ENTRY_FILE) {
120
+ throw new SkillPackageError(`The only file allowed at the package root is ${SKILL_ENTRY_FILE}: ${relativePath}`);
121
+ }
122
+ return;
123
+ }
124
+ if (!SKILL_RESOURCE_DIRS.includes(segments[0])) {
125
+ throw new SkillPackageError(`Resource files must live under ${SKILL_RESOURCE_DIRS.join('/ or ')}/: ${relativePath}`);
126
+ }
127
+ };
128
+ /** 패키지 계약을 로컬에서 먼저 적용한다. 실패 사유는 서버 메시지와 같은 축을 쓴다. */
129
+ export const validateSkillPackageFiles = (files) => {
130
+ if (files.length === 0) {
131
+ throw new SkillPackageError(`A skill package must contain ${SKILL_ENTRY_FILE}`);
132
+ }
133
+ if (files.length > SKILL_LIMITS.fileCount) {
134
+ throw new SkillPackageError(`A skill package may contain at most ${SKILL_LIMITS.fileCount} files`);
135
+ }
136
+ const seen = new Set();
137
+ const seenLower = new Map();
138
+ let totalBytes = 0;
139
+ for (const file of files) {
140
+ assertSafeRelativePath(file.relativePath);
141
+ if (seen.has(file.relativePath)) {
142
+ throw new SkillPackageError(`Duplicate path: ${file.relativePath}`);
143
+ }
144
+ const lower = file.relativePath.toLowerCase();
145
+ const collision = seenLower.get(lower);
146
+ if (collision) {
147
+ throw new SkillPackageError(`Paths collide case-insensitively: ${collision} vs ${file.relativePath}`);
148
+ }
149
+ seen.add(file.relativePath);
150
+ seenLower.set(lower, file.relativePath);
151
+ const sizeBytes = Buffer.byteLength(file.content, 'utf8');
152
+ const limit = file.relativePath === SKILL_ENTRY_FILE ? SKILL_LIMITS.entryFileBytes : SKILL_LIMITS.resourceFileBytes;
153
+ if (sizeBytes > limit) {
154
+ throw new SkillPackageError(`${file.relativePath} exceeds ${limit} bytes`);
155
+ }
156
+ totalBytes += sizeBytes;
157
+ }
158
+ if (!seen.has(SKILL_ENTRY_FILE)) {
159
+ throw new SkillPackageError(`A skill package must contain ${SKILL_ENTRY_FILE}`);
160
+ }
161
+ if (totalBytes > SKILL_LIMITS.totalBytes) {
162
+ throw new SkillPackageError(`The package exceeds ${SKILL_LIMITS.totalBytes} bytes in total`);
163
+ }
164
+ };
165
+ /**
166
+ * 로컬 디렉터리에서 패키지 파일을 모은다. symlink는 따라가지 않는다 — 링크가 패키지 밖을
167
+ * 가리키면 저장소 밖 파일이 업로드된다.
168
+ */
169
+ export const collectSkillPackageFiles = (packageDir) => {
170
+ const rootPath = resolve(packageDir);
171
+ const files = [];
172
+ const walk = (currentDir) => {
173
+ for (const entry of readdirSync(currentDir, { withFileTypes: true })) {
174
+ const absolutePath = join(currentDir, entry.name);
175
+ const relativePath = relative(rootPath, absolutePath).split(sep).join('/');
176
+ if (entry.isSymbolicLink()) {
177
+ throw new SkillPackageError(`Symlinks are not allowed inside a skill package: ${relativePath}`);
178
+ }
179
+ if (entry.isDirectory()) {
180
+ walk(absolutePath);
181
+ continue;
182
+ }
183
+ if (!entry.isFile()) {
184
+ continue;
185
+ }
186
+ files.push({ relativePath, content: readFileSync(absolutePath, 'utf8') });
187
+ }
188
+ };
189
+ walk(rootPath);
190
+ validateSkillPackageFiles(files);
191
+ return files;
192
+ };
193
+ export const readSkillManifest = (projectRoot) => {
194
+ const path = skillManifestPath(projectRoot);
195
+ if (!existsSync(path)) {
196
+ return { version: 1, generatedAt: new Date().toISOString(), entries: [] };
197
+ }
198
+ try {
199
+ const parsed = JSON.parse(readFileSync(path, 'utf8'));
200
+ if (parsed.version !== 1 || !Array.isArray(parsed.entries)) {
201
+ return { version: 1, generatedAt: new Date().toISOString(), entries: [] };
202
+ }
203
+ return parsed;
204
+ }
205
+ catch {
206
+ // 손상된 manifest는 "아무것도 소유하지 않은 상태"로 다룬다. 여기서 실패로 끝내면
207
+ // 사용자가 파일을 손으로 고치기 전까지 동기화가 막힌다.
208
+ return { version: 1, generatedAt: new Date().toISOString(), entries: [] };
209
+ }
210
+ };
211
+ export const writeSkillManifest = (projectRoot, manifest) => {
212
+ const path = skillManifestPath(projectRoot);
213
+ mkdirSync(dirname(path), { recursive: true });
214
+ writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
215
+ };
216
+ /**
217
+ * 임시 디렉터리에 전부 쓴 뒤 한 번에 교체한다. 쓰기 도중 실패하면 기존 디렉터리는
218
+ * byte-for-byte 그대로 남는다 — 부분 적용된 패키지는 "설치됐지만 깨진" 상태를 만든다.
219
+ */
220
+ export const writePackageAtomically = (targetDir, files) => {
221
+ const stagingDir = `${targetDir}.staging-${process.pid}`;
222
+ const backupDir = `${targetDir}.backup-${process.pid}`;
223
+ rmSync(stagingDir, { recursive: true, force: true });
224
+ mkdirSync(stagingDir, { recursive: true });
225
+ try {
226
+ for (const file of files) {
227
+ assertSafeRelativePath(file.relativePath);
228
+ const destination = join(stagingDir, ...file.relativePath.split('/'));
229
+ mkdirSync(dirname(destination), { recursive: true });
230
+ writeFileSync(destination, file.content, 'utf8');
231
+ }
232
+ }
233
+ catch (error) {
234
+ rmSync(stagingDir, { recursive: true, force: true });
235
+ throw error;
236
+ }
237
+ const hadPrevious = existsSync(targetDir);
238
+ if (hadPrevious) {
239
+ rmSync(backupDir, { recursive: true, force: true });
240
+ renameSync(targetDir, backupDir);
241
+ }
242
+ try {
243
+ mkdirSync(dirname(targetDir), { recursive: true });
244
+ renameSync(stagingDir, targetDir);
245
+ }
246
+ catch (error) {
247
+ // 교체 자체가 실패하면 백업을 되돌려 이전 상태를 복원한다.
248
+ if (hadPrevious && !existsSync(targetDir)) {
249
+ renameSync(backupDir, targetDir);
250
+ }
251
+ rmSync(stagingDir, { recursive: true, force: true });
252
+ throw error;
253
+ }
254
+ rmSync(backupDir, { recursive: true, force: true });
255
+ };
256
+ /** manifest에 기록된 경로만 지운다. 사용자가 mirror 디렉터리에 둔 파일은 건드리지 않는다. */
257
+ export const removeManifestPaths = (projectRoot, relativePaths) => {
258
+ for (const relativePath of relativePaths) {
259
+ const absolutePath = join(projectRoot, ...relativePath.split('/'));
260
+ // 프로젝트 루트를 벗어나는 기록은 무시한다(손상되거나 조작된 manifest 방어).
261
+ if (!resolve(absolutePath).startsWith(resolve(projectRoot) + sep)) {
262
+ continue;
263
+ }
264
+ rmSync(absolutePath, { recursive: true, force: true });
265
+ }
266
+ };
267
+ const GITIGNORE_MARKER = '# AgentTeams skill mirrors (generated — do not edit)';
268
+ /**
269
+ * mirror 디렉터리를 `.gitignore`에 넣는다. mirror는 `.agentteams/skills/`에서 파생된 사본이라
270
+ * 커밋 대상이 아니다. `--commit-mirrors`를 준 프로젝트는 이 호출을 건너뛴다.
271
+ */
272
+ export const ensureMirrorGitignore = (projectRoot, targets) => {
273
+ if (targets.length === 0) {
274
+ return;
275
+ }
276
+ const gitignorePath = join(projectRoot, '.gitignore');
277
+ const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : '';
278
+ const wanted = targets.map((target) => `${MIRROR_SPECS[target].dir.split(sep).join('/')}/`);
279
+ const missing = wanted.filter((entry) => !existing.split(/\r?\n/).some((line) => line.trim() === entry));
280
+ if (missing.length === 0) {
281
+ return;
282
+ }
283
+ const block = existing.includes(GITIGNORE_MARKER) ? missing.join('\n') : [GITIGNORE_MARKER, ...missing].join('\n');
284
+ const separator = existing.length === 0 || existing.endsWith('\n') ? '' : '\n';
285
+ writeFileSync(gitignorePath, `${existing}${separator}${block}\n`, 'utf8');
286
+ };
287
+ //# sourceMappingURL=skillPackage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillPackage.js","sourceRoot":"","sources":["../../src/utils/skillPackage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentteams/cli",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "description": "CLI tool for AgentTeams API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,7 +42,7 @@
42
42
  "node": ">=20.12.0"
43
43
  },
44
44
  "dependencies": {
45
- "@agentteams/context-tools": "0.1.7",
45
+ "@agentteams/context-tools": "0.1.8",
46
46
  "@clack/prompts": "^1.4.0",
47
47
  "@modelcontextprotocol/server": "2.0.0",
48
48
  "axios": "^1.16.1",
@@ -1,8 +0,0 @@
1
- export type PlanPreviewHtmlSafetyResult = {
2
- ok: true;
3
- } | {
4
- ok: false;
5
- reasons: string[];
6
- };
7
- export declare const validatePlanPreviewHtmlSafety: (html: string) => PlanPreviewHtmlSafetyResult;
8
- //# sourceMappingURL=planPreviewHtmlSafety.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"planPreviewHtmlSafety.d.ts","sourceRoot":"","sources":["../../src/utils/planPreviewHtmlSafety.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,2BAA2B,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAU1F,eAAO,MAAM,6BAA6B,GAAI,MAAM,MAAM,KAAG,2BAqC5D,CAAC"}
@@ -1,40 +0,0 @@
1
- const hasRemoteDependency = (html) => {
2
- return (/\b(?:src|href)\s*=\s*["']https?:\/\//i.test(html) ||
3
- /@import\s+(?:url\()?["']?https?:\/\//i.test(html) ||
4
- /url\(\s*["']?https?:\/\//i.test(html));
5
- };
6
- export const validatePlanPreviewHtmlSafety = (html) => {
7
- const reasons = [];
8
- const trimmedHtml = typeof html === 'string' ? html.trim() : '';
9
- const lowerHtml = trimmedHtml.toLowerCase();
10
- if (trimmedHtml.length === 0) {
11
- reasons.push('HTML content is empty');
12
- }
13
- if (/<script\b/i.test(trimmedHtml)) {
14
- reasons.push('script tags are not allowed');
15
- }
16
- if (/\son[a-z]+\s*=/i.test(trimmedHtml)) {
17
- reasons.push('inline event handlers are not allowed');
18
- }
19
- if (/<form\b/i.test(trimmedHtml)) {
20
- reasons.push('form elements are not allowed');
21
- }
22
- if (hasRemoteDependency(trimmedHtml)) {
23
- reasons.push('remote assets and CSS imports are not allowed');
24
- }
25
- if (!/:root\b/i.test(trimmedHtml)) {
26
- reasons.push('theme CSS must define :root tokens');
27
- }
28
- if (!/--text\b/i.test(trimmedHtml) || !/var\(\s*--text\s*\)/i.test(trimmedHtml)) {
29
- reasons.push('theme CSS must define and use --text via var(--text)');
30
- }
31
- if (!/@media\s*\(\s*prefers-color-scheme\s*:\s*dark\s*\)/i.test(trimmedHtml) &&
32
- !/\[data-theme\s*=\s*["']?night["']?\]/i.test(trimmedHtml)) {
33
- reasons.push('theme CSS must include a dark mode rule using prefers-color-scheme or [data-theme="night"]');
34
- }
35
- if (!/body[^{]*\{[^}]*background(?:-color)?\s*:\s*transparent\b/is.test(lowerHtml)) {
36
- reasons.push('theme CSS must keep body background transparent');
37
- }
38
- return reasons.length === 0 ? { ok: true } : { ok: false, reasons };
39
- };
40
- //# sourceMappingURL=planPreviewHtmlSafety.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"planPreviewHtmlSafety.js","sourceRoot":"","sources":["../../src/utils/planPreviewHtmlSafety.ts"],"names":[],"mappings":"AAEA,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAW,EAAE;IACpD,OAAO,CACL,uCAAuC,CAAC,IAAI,CAAC,IAAI,CAAC;QAClD,uCAAuC,CAAC,IAAI,CAAC,IAAI,CAAC;QAClD,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CACvC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,IAAY,EAA+B,EAAE;IACzF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAE5C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IACvE,CAAC;IACD,IACE,CAAC,qDAAqD,CAAC,IAAI,CAAC,WAAW,CAAC;QACxE,CAAC,uCAAuC,CAAC,IAAI,CAAC,WAAW,CAAC,EAC1D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;IAC7G,CAAC;IACD,IAAI,CAAC,6DAA6D,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACtE,CAAC,CAAC"}