teamcast 0.9.2 → 0.9.3

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 (177) hide show
  1. package/dist/application/team.d.ts +0 -1
  2. package/dist/application/team.d.ts.map +1 -1
  3. package/dist/application/team.js +74 -6
  4. package/dist/application/team.js.map +1 -1
  5. package/dist/application/validate-team.d.ts +3 -2
  6. package/dist/application/validate-team.d.ts.map +1 -1
  7. package/dist/application/validate-team.js +12 -88
  8. package/dist/application/validate-team.js.map +1 -1
  9. package/dist/cli/diff.d.ts +2 -2
  10. package/dist/cli/diff.d.ts.map +1 -1
  11. package/dist/cli/diff.js +47 -50
  12. package/dist/cli/diff.js.map +1 -1
  13. package/dist/cli/errors.d.ts +7 -0
  14. package/dist/cli/errors.d.ts.map +1 -0
  15. package/dist/cli/errors.js +15 -0
  16. package/dist/cli/errors.js.map +1 -0
  17. package/dist/cli/explain.d.ts +2 -3
  18. package/dist/cli/explain.d.ts.map +1 -1
  19. package/dist/cli/explain.js +33 -37
  20. package/dist/cli/explain.js.map +1 -1
  21. package/dist/cli/generate.d.ts +4 -2
  22. package/dist/cli/generate.d.ts.map +1 -1
  23. package/dist/cli/generate.js +50 -54
  24. package/dist/cli/generate.js.map +1 -1
  25. package/dist/cli/import.d.ts +4 -2
  26. package/dist/cli/import.d.ts.map +1 -1
  27. package/dist/cli/import.js +92 -117
  28. package/dist/cli/import.js.map +1 -1
  29. package/dist/cli/index.js +8 -8
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/init.d.ts +7 -2
  32. package/dist/cli/init.d.ts.map +1 -1
  33. package/dist/cli/init.js +37 -44
  34. package/dist/cli/init.js.map +1 -1
  35. package/dist/cli/manage.d.ts +21 -2
  36. package/dist/cli/manage.d.ts.map +1 -1
  37. package/dist/cli/manage.js +159 -191
  38. package/dist/cli/manage.js.map +1 -1
  39. package/dist/cli/registrars/diff.d.ts +3 -0
  40. package/dist/cli/registrars/diff.d.ts.map +1 -0
  41. package/dist/cli/registrars/diff.js +10 -0
  42. package/dist/cli/registrars/diff.js.map +1 -0
  43. package/dist/cli/registrars/explain.d.ts +3 -0
  44. package/dist/cli/registrars/explain.d.ts.map +1 -0
  45. package/dist/cli/registrars/explain.js +10 -0
  46. package/dist/cli/registrars/explain.js.map +1 -0
  47. package/dist/cli/registrars/generate.d.ts +3 -0
  48. package/dist/cli/registrars/generate.d.ts.map +1 -0
  49. package/dist/cli/registrars/generate.js +11 -0
  50. package/dist/cli/registrars/generate.js.map +1 -0
  51. package/dist/cli/registrars/import.d.ts +3 -0
  52. package/dist/cli/registrars/import.d.ts.map +1 -0
  53. package/dist/cli/registrars/import.js +11 -0
  54. package/dist/cli/registrars/import.js.map +1 -0
  55. package/dist/cli/registrars/init.d.ts +3 -0
  56. package/dist/cli/registrars/init.d.ts.map +1 -0
  57. package/dist/cli/registrars/init.js +14 -0
  58. package/dist/cli/registrars/init.js.map +1 -0
  59. package/dist/cli/registrars/manage.d.ts +3 -0
  60. package/dist/cli/registrars/manage.d.ts.map +1 -0
  61. package/dist/cli/registrars/manage.js +54 -0
  62. package/dist/cli/registrars/manage.js.map +1 -0
  63. package/dist/cli/registrars/reset.d.ts +3 -0
  64. package/dist/cli/registrars/reset.d.ts.map +1 -0
  65. package/dist/cli/registrars/reset.js +19 -0
  66. package/dist/cli/registrars/reset.js.map +1 -0
  67. package/dist/cli/registrars/validate.d.ts +3 -0
  68. package/dist/cli/registrars/validate.d.ts.map +1 -0
  69. package/dist/cli/registrars/validate.js +12 -0
  70. package/dist/cli/registrars/validate.js.map +1 -0
  71. package/dist/cli/reset.d.ts +7 -2
  72. package/dist/cli/reset.d.ts.map +1 -1
  73. package/dist/cli/reset.js +60 -69
  74. package/dist/cli/reset.js.map +1 -1
  75. package/dist/cli/validate.d.ts +5 -2
  76. package/dist/cli/validate.d.ts.map +1 -1
  77. package/dist/cli/validate.js +33 -38
  78. package/dist/cli/validate.js.map +1 -1
  79. package/dist/generator/index.d.ts +0 -1
  80. package/dist/generator/index.d.ts.map +1 -1
  81. package/dist/generator/index.js +1 -3
  82. package/dist/generator/index.js.map +1 -1
  83. package/dist/importer/claude.d.ts +4 -0
  84. package/dist/importer/claude.d.ts.map +1 -0
  85. package/dist/importer/claude.js +51 -0
  86. package/dist/importer/claude.js.map +1 -0
  87. package/dist/importer/codex.d.ts +4 -0
  88. package/dist/importer/codex.d.ts.map +1 -0
  89. package/dist/importer/codex.js +50 -0
  90. package/dist/importer/codex.js.map +1 -0
  91. package/dist/importer/index.d.ts +11 -12
  92. package/dist/importer/index.d.ts.map +1 -1
  93. package/dist/importer/index.js +29 -501
  94. package/dist/importer/index.js.map +1 -1
  95. package/dist/importer/shared.d.ts +40 -0
  96. package/dist/importer/shared.d.ts.map +1 -0
  97. package/dist/importer/shared.js +373 -0
  98. package/dist/importer/shared.js.map +1 -0
  99. package/dist/importer/types.d.ts +16 -0
  100. package/dist/importer/types.d.ts.map +1 -0
  101. package/dist/importer/types.js +2 -0
  102. package/dist/importer/types.js.map +1 -0
  103. package/dist/index.d.ts +1 -1
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +19 -4
  106. package/dist/index.js.map +1 -1
  107. package/dist/manifest/defaults.d.ts.map +1 -1
  108. package/dist/manifest/defaults.js +76 -20
  109. package/dist/manifest/defaults.js.map +1 -1
  110. package/dist/manifest/normalize.d.ts.map +1 -1
  111. package/dist/manifest/normalize.js +9 -5
  112. package/dist/manifest/normalize.js.map +1 -1
  113. package/dist/manifest/targets.d.ts +11 -0
  114. package/dist/manifest/targets.d.ts.map +1 -0
  115. package/dist/manifest/targets.js +29 -0
  116. package/dist/manifest/targets.js.map +1 -0
  117. package/dist/manifest/types.d.ts +0 -2
  118. package/dist/manifest/types.d.ts.map +1 -1
  119. package/dist/manifest/types.js.map +1 -1
  120. package/dist/plugins/catalog.d.ts +10 -0
  121. package/dist/plugins/catalog.d.ts.map +1 -0
  122. package/dist/plugins/catalog.js +30 -0
  123. package/dist/plugins/catalog.js.map +1 -0
  124. package/dist/plugins/core/presets-plugin.d.ts +3 -0
  125. package/dist/plugins/core/presets-plugin.d.ts.map +1 -0
  126. package/dist/plugins/core/presets-plugin.js +10 -0
  127. package/dist/plugins/core/presets-plugin.js.map +1 -0
  128. package/dist/plugins/index.d.ts.map +1 -1
  129. package/dist/plugins/index.js +2 -1
  130. package/dist/plugins/index.js.map +1 -1
  131. package/dist/plugins/inject.d.ts +6 -2
  132. package/dist/plugins/inject.d.ts.map +1 -1
  133. package/dist/plugins/inject.js +41 -9
  134. package/dist/plugins/inject.js.map +1 -1
  135. package/dist/plugins/merge-policies.d.ts +1 -1
  136. package/dist/plugins/merge-policies.d.ts.map +1 -1
  137. package/dist/plugins/merge-policies.js +49 -15
  138. package/dist/plugins/merge-policies.js.map +1 -1
  139. package/dist/plugins/registry.d.ts +12 -6
  140. package/dist/plugins/registry.d.ts.map +1 -1
  141. package/dist/plugins/registry.js +34 -0
  142. package/dist/plugins/registry.js.map +1 -1
  143. package/dist/plugins/types.d.ts +8 -4
  144. package/dist/plugins/types.d.ts.map +1 -1
  145. package/dist/presets/index.d.ts +1 -0
  146. package/dist/presets/index.d.ts.map +1 -1
  147. package/dist/presets/index.js +62 -16
  148. package/dist/presets/index.js.map +1 -1
  149. package/dist/renderers/index.d.ts +1 -1
  150. package/dist/renderers/index.d.ts.map +1 -1
  151. package/dist/renderers/index.js +1 -6
  152. package/dist/renderers/index.js.map +1 -1
  153. package/dist/renderers/registry.d.ts +1 -0
  154. package/dist/renderers/registry.d.ts.map +1 -1
  155. package/dist/renderers/registry.js +21 -0
  156. package/dist/renderers/registry.js.map +1 -1
  157. package/dist/team-templates/presets.d.ts.map +1 -1
  158. package/dist/team-templates/presets.js +9 -5
  159. package/dist/team-templates/presets.js.map +1 -1
  160. package/dist/validator/reporter.d.ts +2 -0
  161. package/dist/validator/reporter.d.ts.map +1 -1
  162. package/dist/validator/reporter.js +38 -30
  163. package/dist/validator/reporter.js.map +1 -1
  164. package/dist/wizard/index.d.ts.map +1 -1
  165. package/dist/wizard/index.js +7 -6
  166. package/dist/wizard/index.js.map +1 -1
  167. package/dist/wizard/steps/agent-customization.d.ts.map +1 -1
  168. package/dist/wizard/steps/agent-customization.js +6 -9
  169. package/dist/wizard/steps/agent-customization.js.map +1 -1
  170. package/dist/wizard/steps/team-selection.js +2 -2
  171. package/dist/wizard/steps/team-selection.js.map +1 -1
  172. package/package.json +1 -1
  173. package/schema/teamcast.schema.json +0 -6
  174. package/templates/presets/feature-team.yaml +9 -9
  175. package/templates/presets/research-and-build.yaml +9 -9
  176. package/templates/presets/secure-dev.yaml +20 -20
  177. package/templates/presets/solo-dev.yaml +8 -8
@@ -0,0 +1,50 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { createManifestForTarget } from '../manifest/normalize.js';
4
+ import { getTarget } from '../renderers/registry.js';
5
+ import { parseCodexAgentFile, parseCodexConfigEntries, } from './shared.js';
6
+ export function importFromCodexDir(cwd, projectName) {
7
+ const warnings = [];
8
+ const agents = {};
9
+ const targetContext = getTarget('codex');
10
+ const configPath = join(cwd, '.codex', 'config.toml');
11
+ if (!existsSync(configPath)) {
12
+ warnings.push({ file: configPath, message: 'No .codex/config.toml file found' });
13
+ }
14
+ else {
15
+ const entries = parseCodexConfigEntries(configPath);
16
+ for (const entry of entries) {
17
+ const agentPath = join(cwd, '.codex', entry.configPath);
18
+ if (!existsSync(agentPath)) {
19
+ warnings.push({ file: agentPath, message: `Missing config for agent "${entry.name}"` });
20
+ continue;
21
+ }
22
+ const result = parseCodexAgentFile(cwd, entry, targetContext);
23
+ agents[result.name] = result.agent;
24
+ warnings.push(...result.warnings);
25
+ }
26
+ }
27
+ if (Object.keys(agents).length === 0) {
28
+ warnings.push({ file: join(cwd, '.codex', 'agents'), message: 'No agent .toml files found in .codex/agents/' });
29
+ }
30
+ return {
31
+ team: createManifestForTarget({
32
+ version: '2',
33
+ project: { name: projectName },
34
+ agents,
35
+ settings: {
36
+ generateDocs: true,
37
+ generateLocalSettings: true,
38
+ },
39
+ }, 'codex'),
40
+ warnings,
41
+ };
42
+ }
43
+ export const codexImportHandler = {
44
+ targetName: 'codex',
45
+ detect(cwd) {
46
+ return existsSync(join(cwd, '.codex'));
47
+ },
48
+ importFromDir: importFromCodexDir,
49
+ };
50
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/importer/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAe,MAAM,IAAI,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAGrB,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,WAAmB;IACjE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,MAAM,aAAa,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC,CAAC;IACnF,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;QACpD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;YACxD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,6BAA6B,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;gBACxF,SAAS;YACX,CAAC;YAED,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;YACnC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,8CAA8C,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,uBAAuB,CAAC;YAC5B,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC9B,MAAM;YACN,QAAQ,EAAE;gBACR,YAAY,EAAE,IAAI;gBAClB,qBAAqB,EAAE,IAAI;aAC5B;SACF,EAAE,OAAO,CAAC;QACX,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAkB;IAC/C,UAAU,EAAE,OAAO;IACnB,MAAM,CAAC,GAAW;QAChB,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,aAAa,EAAE,kBAAkB;CAClC,CAAC"}
@@ -1,13 +1,12 @@
1
- import type { TeamCastManifest } from '../manifest/types.js';
2
- interface ImportWarning {
3
- file: string;
4
- message: string;
5
- }
6
- interface ImportResult {
7
- team: TeamCastManifest;
8
- warnings: ImportWarning[];
9
- }
10
- export declare function importFromClaudeDir(cwd: string, projectName: string): ImportResult;
11
- export declare function importFromCodexDir(cwd: string, projectName: string): ImportResult;
12
- export {};
1
+ import type { ManifestTargetName } from '../manifest/targets.js';
2
+ import { importFromClaudeDir } from './claude.js';
3
+ import { importFromCodexDir } from './codex.js';
4
+ import type { ImportHandler, ImportResult, ImportWarning } from './types.js';
5
+ export declare function registerImportHandler(handler: ImportHandler): void;
6
+ export declare function getImportHandler(targetName: ManifestTargetName): ImportHandler | undefined;
7
+ export declare function getImportHandlers(): ImportHandler[];
8
+ export declare function getDetectedImportHandlers(cwd: string): ImportHandler[];
9
+ export declare function importTargetFromDir(targetName: ManifestTargetName, cwd: string, projectName: string): ImportResult;
10
+ export { importFromClaudeDir, importFromCodexDir };
11
+ export type { ImportHandler, ImportResult, ImportWarning };
13
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/importer/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAY7D,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAuVD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,CAqFlF;AAuFD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,CA2DjF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/importer/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAuB,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAsB,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAe7E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAMlE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,GAAG,SAAS,CAG1F;AAED,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CAGnD;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE,CAEtE;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,kBAAkB,EAC9B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,GAClB,YAAY,CAMd;AAED,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -1,511 +1,39 @@
1
- import { readFileSync, readdirSync, existsSync } from 'fs';
2
- import { join, basename } from 'path';
3
- import { parse } from 'yaml';
4
- import { createClaudeTarget } from '../renderers/claude/index.js';
5
- import { createCodexTarget } from '../renderers/codex/index.js';
6
- const LEGACY_MODEL_ID_MAP = {
7
- 'claude-opus-4-6': 'opus',
8
- 'claude-sonnet-4-6': 'sonnet',
9
- 'claude-haiku-4-5-20251001': 'haiku',
10
- };
11
- function parseFrontmatter(content) {
12
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
13
- if (!match)
14
- return {};
15
- const parsed = parse(match[1]);
16
- if (parsed && typeof parsed === 'object') {
17
- return parsed;
1
+ import { claudeImportHandler, importFromClaudeDir } from './claude.js';
2
+ import { codexImportHandler, importFromCodexDir } from './codex.js';
3
+ const registry = new Map();
4
+ let builtinsRegistered = false;
5
+ function ensureBuiltinImportHandlersRegistered() {
6
+ if (builtinsRegistered) {
7
+ return;
18
8
  }
19
- return {};
9
+ registry.set('claude', claudeImportHandler);
10
+ registry.set('codex', codexImportHandler);
11
+ builtinsRegistered = true;
20
12
  }
21
- function extractBody(content) {
22
- const bodyMatch = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n\r?\n?([\s\S]*)/);
23
- if (!bodyMatch)
24
- return undefined;
25
- const body = bodyMatch[1].trim();
26
- return body || undefined;
27
- }
28
- function stripLegacyGeneratedSections(body) {
29
- if (!body)
30
- return undefined;
31
- let nextBody = body;
32
- const generatedSections = ['## Skills', '## Delegation', '## Constraints'];
33
- for (const section of generatedSections) {
34
- const sectionIndex = nextBody.indexOf(section);
35
- if (sectionIndex !== -1) {
36
- const nextSection = nextBody.indexOf('\n## ', sectionIndex + section.length);
37
- nextBody = nextSection !== -1
38
- ? nextBody.slice(0, sectionIndex) + nextBody.slice(nextSection)
39
- : nextBody.slice(0, sectionIndex);
40
- }
41
- }
42
- return nextBody.trim() || undefined;
43
- }
44
- function inferLegacyHandoffs(body) {
45
- if (!body?.includes('## Delegation'))
46
- return undefined;
47
- const match = body.match(/## Delegation\s+You can delegate tasks to the following agents:\s+([a-z0-9,\- ]+)\./i);
48
- if (!match)
49
- return undefined;
50
- const values = match[1]
51
- .split(',')
52
- .map((value) => value.trim())
53
- .filter(Boolean);
54
- return values.length > 0 ? values : undefined;
55
- }
56
- function resolveClaudeModel(modelValue) {
57
- if (typeof modelValue !== 'string' || modelValue.length === 0)
58
- return undefined;
59
- if (modelValue === 'opus' || modelValue === 'sonnet' || modelValue === 'haiku') {
60
- return modelValue;
61
- }
62
- return LEGACY_MODEL_ID_MAP[modelValue];
63
- }
64
- function isKnownTool(value, knownTools) {
65
- return knownTools.includes(value);
66
- }
67
- function parseToolList(value, knownTools) {
68
- const rawTools = Array.isArray(value)
69
- ? value.filter((item) => typeof item === 'string')
70
- : typeof value === 'string'
71
- ? value.split(',').map((item) => item.trim()).filter(Boolean)
72
- : [];
73
- if (rawTools.length === 0)
74
- return undefined;
75
- const tools = [];
76
- for (const raw of rawTools) {
77
- const canonical = raw === 'Task' ? 'Agent' : raw;
78
- if (isKnownTool(canonical, knownTools) && !tools.includes(canonical)) {
79
- tools.push(canonical);
80
- }
81
- }
82
- return tools.length > 0 ? tools : undefined;
83
- }
84
- function parseSkillList(value) {
85
- if (!Array.isArray(value))
86
- return undefined;
87
- const skills = value.filter((item) => typeof item === 'string' && item.length > 0);
88
- return skills.length > 0 ? skills : undefined;
89
- }
90
- function parsePermissionMode(value) {
91
- if (typeof value !== 'string')
92
- return undefined;
93
- const modes = ['default', 'acceptEdits', 'bypassPermissions', 'plan', 'dontAsk'];
94
- return modes.includes(value) ? value : undefined;
95
- }
96
- function parseMcpServers(value) {
97
- if (!Array.isArray(value))
98
- return undefined;
99
- const servers = value
100
- .filter((item) => typeof item === 'object' && item !== null)
101
- .map((item) => ({
102
- name: typeof item.name === 'string' ? item.name : '',
103
- url: typeof item.url === 'string' ? item.url : '',
104
- }))
105
- .filter((item) => item.name.length > 0 && item.url.length > 0);
106
- return servers.length > 0 ? servers : undefined;
107
- }
108
- function normalizeLineEndings(value) {
109
- return value.replace(/\r\n/g, '\n');
110
- }
111
- function escapeRegExp(value) {
112
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
113
- }
114
- function extractTomlString(content, key) {
115
- const match = content.match(new RegExp(`^${escapeRegExp(key)}\\s*=\\s*"((?:\\\\.|[^"])*)"`, 'm'));
116
- if (!match)
117
- return undefined;
118
- return match[1]
119
- .replace(/\\"/g, '"')
120
- .replace(/\\\\/g, '\\');
121
- }
122
- function extractTomlMultiline(content, key) {
123
- const match = content.match(new RegExp(`${escapeRegExp(key)}\\s*=\\s*"""\\n([\\s\\S]*?)\\n"""`));
124
- return match ? normalizeLineEndings(match[1]).trim() : undefined;
125
- }
126
- function extractMarkdownSection(content, heading) {
127
- const normalized = normalizeLineEndings(content);
128
- const match = normalized.match(new RegExp(`## ${escapeRegExp(heading)}\\n\\n([\\s\\S]*?)(?=\\n## |$)`));
129
- return match?.[1]?.trim() || undefined;
130
- }
131
- function parseCommaList(value) {
132
- if (!value)
133
- return undefined;
134
- const items = value
135
- .split(',')
136
- .map((entry) => entry.trim().replace(/\.$/, ''))
137
- .filter(Boolean);
138
- return items.length > 0 ? items : undefined;
139
- }
140
- function stripCodexGeneratedSections(body) {
141
- if (!body)
142
- return undefined;
143
- let nextBody = normalizeLineEndings(body);
144
- if (nextBody.startsWith('You are ')) {
145
- const firstBreak = nextBody.indexOf('\n\n');
146
- nextBody = firstBreak === -1 ? '' : nextBody.slice(firstBreak + 2);
147
- }
148
- for (const section of ['## Delegation', '## Allowed Tool Intents', '## Restricted Tool Intents', '## Skill Docs']) {
149
- const sectionIndex = nextBody.indexOf(section);
150
- if (sectionIndex !== -1) {
151
- const nextSection = nextBody.indexOf('\n## ', sectionIndex + section.length);
152
- nextBody = nextSection !== -1
153
- ? nextBody.slice(0, sectionIndex) + nextBody.slice(nextSection)
154
- : nextBody.slice(0, sectionIndex);
155
- }
156
- }
157
- return nextBody.trim() || undefined;
158
- }
159
- function parseCodexReasoningEffort(value) {
160
- if (!value)
161
- return undefined;
162
- if (value === 'low' || value === 'medium' || value === 'high' || value === 'xhigh') {
163
- return value;
164
- }
165
- return undefined;
166
- }
167
- function parseAgentFile(filePath, targetContext) {
168
- const warnings = [];
169
- const content = readFileSync(filePath, 'utf-8');
170
- const fields = parseFrontmatter(content);
171
- const fileName = basename(filePath, '.md');
172
- const name = typeof fields.name === 'string' && fields.name.length > 0 ? fields.name : fileName;
173
- const model = resolveClaudeModel(fields.model);
174
- const rawTools = parseToolList(fields.tools, targetContext.knownTools);
175
- const tools = rawTools
176
- ? (() => {
177
- const reverseMap = targetContext.reverseMapTools;
178
- if (reverseMap) {
179
- const { skills, remainingTools } = reverseMap(rawTools);
180
- return [...skills, ...remainingTools];
181
- }
182
- return rawTools;
183
- })()
184
- : undefined;
185
- const disallowedTools = parseToolList(fields.disallowedTools, targetContext.knownTools);
186
- const permissionMode = parsePermissionMode(fields.permissionMode);
187
- const maxTurns = typeof fields.maxTurns === 'number' ? fields.maxTurns : undefined;
188
- const background = typeof fields.background === 'boolean' ? fields.background : undefined;
189
- const skillDocs = parseSkillList(fields.skills);
190
- const mcpServers = parseMcpServers(fields.mcpServers);
191
- if (fields.model && !model) {
192
- warnings.push({ file: filePath, message: `Unknown model "${String(fields.model)}", skipping model field` });
193
- }
194
- if (fields.permissionMode && !permissionMode) {
195
- warnings.push({
196
- file: filePath,
197
- message: `Unknown permissionMode "${String(fields.permissionMode)}", skipping`,
198
- });
199
- }
200
- const originalBody = extractBody(content);
201
- const instructions = stripLegacyGeneratedSections(originalBody);
202
- const legacyHandoffs = inferLegacyHandoffs(originalBody);
203
- return {
204
- name,
205
- agent: {
206
- id: name,
207
- description: typeof fields.description === 'string' && fields.description.length > 0
208
- ? fields.description
209
- : `Imported from ${fileName}.md`,
210
- runtime: {
211
- model,
212
- tools,
213
- disallowedTools,
214
- permissionMode,
215
- maxTurns,
216
- skillDocs,
217
- mcpServers,
218
- background,
219
- },
220
- instructions: instructions
221
- ? [{ kind: 'behavior', content: instructions }]
222
- : [],
223
- metadata: legacyHandoffs?.length ? { handoffs: legacyHandoffs } : undefined,
224
- },
225
- warnings,
226
- };
227
- }
228
- function parseSettingsJson(filePath) {
229
- const warnings = [];
230
- const content = readFileSync(filePath, 'utf-8');
231
- let settings;
232
- try {
233
- settings = JSON.parse(content);
234
- }
235
- catch {
236
- warnings.push({ file: filePath, message: 'Failed to parse settings.json' });
237
- return { policies: {}, warnings };
238
- }
239
- const policies = {};
240
- const perms = typeof settings.permissions === 'object' && settings.permissions !== null
241
- ? settings.permissions
242
- : undefined;
243
- if (perms) {
244
- const allow = Array.isArray(perms.allow) ? perms.allow : undefined;
245
- const ask = Array.isArray(perms.ask) ? perms.ask : undefined;
246
- const deny = Array.isArray(perms.deny) ? perms.deny : undefined;
247
- policies.permissions = {};
248
- if (allow || ask || deny) {
249
- policies.permissions.rules = {};
250
- if (allow)
251
- policies.permissions.rules.allow = allow;
252
- if (ask)
253
- policies.permissions.rules.ask = ask;
254
- if (deny)
255
- policies.permissions.rules.deny = deny;
256
- }
257
- if (perms.defaultMode && typeof perms.defaultMode === 'string') {
258
- policies.permissions.defaultMode = perms.defaultMode;
259
- }
260
- }
261
- const sandbox = typeof settings.sandbox === 'object' && settings.sandbox !== null
262
- ? settings.sandbox
263
- : undefined;
264
- if (sandbox) {
265
- policies.sandbox = {};
266
- if (typeof sandbox.enabled === 'boolean')
267
- policies.sandbox.enabled = sandbox.enabled;
268
- if (typeof sandbox.autoAllowBashIfSandboxed === 'boolean') {
269
- policies.sandbox.autoAllowBash = sandbox.autoAllowBashIfSandboxed;
270
- }
271
- if (Array.isArray(sandbox.excludedCommands)) {
272
- policies.sandbox.excludedCommands = sandbox.excludedCommands;
273
- }
274
- const network = typeof sandbox.network === 'object' && sandbox.network !== null
275
- ? sandbox.network
276
- : undefined;
277
- if (network) {
278
- policies.sandbox.network = {};
279
- if (Array.isArray(network.allowUnixSockets)) {
280
- policies.sandbox.network.allowUnixSockets = network.allowUnixSockets;
281
- }
282
- if (typeof network.allowLocalBinding === 'boolean') {
283
- policies.sandbox.network.allowLocalBinding = network.allowLocalBinding;
284
- }
285
- }
286
- }
287
- const hooks = typeof settings.hooks === 'object' && settings.hooks !== null
288
- ? settings.hooks
289
- : undefined;
290
- if (hooks) {
291
- const parseHookEntries = (entries) => entries
292
- .filter((entry) => typeof entry === 'object' && entry !== null)
293
- .map((entry) => ({
294
- matcher: String(entry.matcher ?? ''),
295
- command: Array.isArray(entry.hooks)
296
- ? String(entry.hooks[0]?.command ?? '')
297
- : '',
298
- }))
299
- .filter((entry) => entry.matcher && entry.command);
300
- policies.hooks = {};
301
- if (Array.isArray(hooks.PreToolUse)) {
302
- policies.hooks.preToolUse = parseHookEntries(hooks.PreToolUse);
303
- }
304
- if (Array.isArray(hooks.PostToolUse)) {
305
- policies.hooks.postToolUse = parseHookEntries(hooks.PostToolUse);
306
- }
307
- if (Array.isArray(hooks.Notification)) {
308
- policies.hooks.notification = parseHookEntries(hooks.Notification);
309
- }
13
+ export function registerImportHandler(handler) {
14
+ ensureBuiltinImportHandlersRegistered();
15
+ if (registry.has(handler.targetName)) {
16
+ throw new Error(`Importer for target "${handler.targetName}" is already registered`);
310
17
  }
311
- return { policies, warnings };
18
+ registry.set(handler.targetName, handler);
312
19
  }
313
- export function importFromClaudeDir(cwd, projectName) {
314
- const warnings = [];
315
- const agents = {};
316
- const claudeTarget = createClaudeTarget();
317
- const agentsDir = join(cwd, '.claude', 'agents');
318
- if (existsSync(agentsDir)) {
319
- const files = readdirSync(agentsDir).filter((file) => file.endsWith('.md'));
320
- for (const file of files) {
321
- const filePath = join(agentsDir, file);
322
- const result = parseAgentFile(filePath, claudeTarget);
323
- agents[result.name] = result.agent;
324
- warnings.push(...result.warnings);
325
- }
326
- }
327
- if (Object.keys(agents).length === 0) {
328
- warnings.push({ file: agentsDir, message: 'No agent .md files found in .claude/agents/' });
329
- }
330
- let policies;
331
- const settingsPath = join(cwd, '.claude', 'settings.json');
332
- if (existsSync(settingsPath)) {
333
- const result = parseSettingsJson(settingsPath);
334
- policies = result.policies;
335
- warnings.push(...result.warnings);
336
- }
337
- const agentConfigs = {};
338
- for (const [id, coreAgent] of Object.entries(agents)) {
339
- agentConfigs[id] = {
340
- description: coreAgent.description,
341
- model: coreAgent.runtime.model,
342
- reasoning_effort: coreAgent.runtime.reasoningEffort,
343
- tools: coreAgent.runtime.tools,
344
- disallowed_tools: coreAgent.runtime.disallowedTools,
345
- permission_mode: coreAgent.runtime.permissionMode,
346
- skills: coreAgent.runtime.skillDocs,
347
- max_turns: coreAgent.runtime.maxTurns,
348
- mcp_servers: coreAgent.runtime.mcpServers,
349
- background: coreAgent.runtime.background,
350
- instruction_blocks: coreAgent.instructions,
351
- forge: coreAgent.metadata,
352
- };
353
- }
354
- return {
355
- team: {
356
- version: '2',
357
- project: { name: projectName },
358
- claude: {
359
- agents: agentConfigs,
360
- policies: policies ? {
361
- permissions: policies.permissions ? {
362
- rules: policies.permissions.rules ? {
363
- allow: policies.permissions.rules.allow,
364
- ask: policies.permissions.rules.ask,
365
- deny: policies.permissions.rules.deny,
366
- } : undefined,
367
- default_mode: policies.permissions.defaultMode,
368
- } : undefined,
369
- sandbox: policies.sandbox ? {
370
- enabled: policies.sandbox.enabled,
371
- auto_allow_bash: policies.sandbox.autoAllowBash,
372
- excluded_commands: policies.sandbox.excludedCommands,
373
- network: policies.sandbox.network ? {
374
- allow_unix_sockets: policies.sandbox.network.allowUnixSockets,
375
- allow_local_binding: policies.sandbox.network.allowLocalBinding,
376
- } : undefined,
377
- } : undefined,
378
- hooks: policies.hooks ? {
379
- pre_tool_use: policies.hooks.preToolUse,
380
- post_tool_use: policies.hooks.postToolUse,
381
- notification: policies.hooks.notification,
382
- } : undefined,
383
- } : undefined,
384
- settings: {
385
- generate_docs: true,
386
- generate_local_settings: true,
387
- },
388
- },
389
- },
390
- warnings,
391
- };
392
- }
393
- function parseCodexConfigEntries(filePath) {
394
- const content = normalizeLineEndings(readFileSync(filePath, 'utf-8'));
395
- const sectionRegex = /\[agents\.([^\]]+)\]\n([\s\S]*?)(?=\n\[agents\.|\s*$)/g;
396
- const entries = [];
397
- for (const match of content.matchAll(sectionRegex)) {
398
- const name = match[1];
399
- const block = match[2];
400
- const description = extractTomlString(block, 'description');
401
- const configPath = extractTomlString(block, 'config_file');
402
- if (description && configPath) {
403
- entries.push({ name, description, configPath });
404
- }
405
- }
406
- return entries;
20
+ export function getImportHandler(targetName) {
21
+ ensureBuiltinImportHandlersRegistered();
22
+ return registry.get(targetName);
407
23
  }
408
- function parseCodexToolList(value, knownTools) {
409
- const items = parseCommaList(value);
410
- if (!items)
411
- return undefined;
412
- const tools = items.filter((item) => knownTools.includes(item));
413
- return tools.length > 0 ? tools : undefined;
24
+ export function getImportHandlers() {
25
+ ensureBuiltinImportHandlersRegistered();
26
+ return Array.from(registry.values());
414
27
  }
415
- function parseCodexAgentFile(cwd, entry, targetContext) {
416
- const warnings = [];
417
- const filePath = join(cwd, '.codex', entry.configPath);
418
- const content = normalizeLineEndings(readFileSync(filePath, 'utf-8'));
419
- const developerInstructions = extractTomlMultiline(content, 'developer_instructions');
420
- const delegation = extractMarkdownSection(developerInstructions ?? '', 'Delegation');
421
- const allowedToolIntents = extractMarkdownSection(developerInstructions ?? '', 'Allowed Tool Intents');
422
- const restrictedToolIntents = extractMarkdownSection(developerInstructions ?? '', 'Restricted Tool Intents');
423
- const skillDocsSection = extractMarkdownSection(developerInstructions ?? '', 'Skill Docs');
424
- const reasoningEffort = parseCodexReasoningEffort(extractTomlString(content, 'model_reasoning_effort'));
425
- if (extractTomlString(content, 'model_reasoning_effort') && !reasoningEffort) {
426
- warnings.push({
427
- file: filePath,
428
- message: `Unknown reasoning effort "${String(extractTomlString(content, 'model_reasoning_effort'))}", skipping`,
429
- });
430
- }
431
- const handoffs = parseCommaList(delegation?.replace(/^You may delegate to:\s*/i, ''));
432
- const tools = parseCodexToolList(allowedToolIntents, targetContext.knownTools);
433
- const disallowedTools = parseCodexToolList(restrictedToolIntents?.replace(/^Avoid using:\s*/i, ''), targetContext.knownTools);
434
- const skillDocs = parseCommaList(skillDocsSection?.replace(/^Follow these local skills when relevant:\s*/i, ''));
435
- return {
436
- name: entry.name,
437
- agent: {
438
- id: entry.name,
439
- description: entry.description,
440
- runtime: {
441
- model: extractTomlString(content, 'model'),
442
- reasoningEffort,
443
- tools,
444
- disallowedTools,
445
- skillDocs,
446
- },
447
- instructions: stripCodexGeneratedSections(developerInstructions)
448
- ? [{ kind: 'behavior', content: stripCodexGeneratedSections(developerInstructions) }]
449
- : [],
450
- metadata: handoffs?.length ? { handoffs } : undefined,
451
- },
452
- warnings,
453
- };
28
+ export function getDetectedImportHandlers(cwd) {
29
+ return getImportHandlers().filter((handler) => handler.detect(cwd));
454
30
  }
455
- export function importFromCodexDir(cwd, projectName) {
456
- const warnings = [];
457
- const agents = {};
458
- const codexTarget = createCodexTarget();
459
- const configPath = join(cwd, '.codex', 'config.toml');
460
- if (!existsSync(configPath)) {
461
- warnings.push({ file: configPath, message: 'No .codex/config.toml file found' });
462
- }
463
- else {
464
- const entries = parseCodexConfigEntries(configPath);
465
- for (const entry of entries) {
466
- const agentPath = join(cwd, '.codex', entry.configPath);
467
- if (!existsSync(agentPath)) {
468
- warnings.push({ file: agentPath, message: `Missing config for agent "${entry.name}"` });
469
- continue;
470
- }
471
- const result = parseCodexAgentFile(cwd, entry, codexTarget);
472
- agents[result.name] = result.agent;
473
- warnings.push(...result.warnings);
474
- }
475
- }
476
- if (Object.keys(agents).length === 0) {
477
- warnings.push({ file: join(cwd, '.codex', 'agents'), message: 'No agent .toml files found in .codex/agents/' });
478
- }
479
- const agentConfigs = {};
480
- for (const [id, coreAgent] of Object.entries(agents)) {
481
- agentConfigs[id] = {
482
- description: coreAgent.description,
483
- model: coreAgent.runtime.model,
484
- reasoning_effort: coreAgent.runtime.reasoningEffort,
485
- tools: coreAgent.runtime.tools,
486
- disallowed_tools: coreAgent.runtime.disallowedTools,
487
- permission_mode: coreAgent.runtime.permissionMode,
488
- skills: coreAgent.runtime.skillDocs,
489
- max_turns: coreAgent.runtime.maxTurns,
490
- mcp_servers: coreAgent.runtime.mcpServers,
491
- background: coreAgent.runtime.background,
492
- instruction_blocks: coreAgent.instructions,
493
- forge: coreAgent.metadata,
494
- };
31
+ export function importTargetFromDir(targetName, cwd, projectName) {
32
+ const handler = getImportHandler(targetName);
33
+ if (!handler) {
34
+ throw new Error(`Importer not found for target "${targetName}"`);
495
35
  }
496
- return {
497
- team: {
498
- version: '2',
499
- project: { name: projectName },
500
- codex: {
501
- agents: agentConfigs,
502
- settings: {
503
- generate_docs: true,
504
- generate_local_settings: true,
505
- },
506
- },
507
- },
508
- warnings,
509
- };
36
+ return handler.importFromDir(cwd, projectName);
510
37
  }
38
+ export { importFromClaudeDir, importFromCodexDir };
511
39
  //# sourceMappingURL=index.js.map