agents-inc 0.170.0 → 0.170.2

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 (163) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
  3. package/dist/chunk-2YA4DDRM.js.map +1 -0
  4. package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
  5. package/dist/chunk-3ED3KHHD.js.map +1 -0
  6. package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
  7. package/dist/chunk-5BNX73OU.js.map +1 -0
  8. package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
  9. package/dist/chunk-66AEVERM.js.map +1 -0
  10. package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
  11. package/dist/chunk-7C3PFRBU.js.map +1 -0
  12. package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
  13. package/dist/chunk-AUNRHWH4.js.map +1 -0
  14. package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
  15. package/dist/chunk-BBDGYJHX.js.map +1 -0
  16. package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
  17. package/dist/chunk-ELV5WDS3.js.map +1 -0
  18. package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
  19. package/dist/chunk-GAKVZNTX.js.map +1 -0
  20. package/dist/chunk-GEMW5RQ2.js +1169 -0
  21. package/dist/chunk-GEMW5RQ2.js.map +1 -0
  22. package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
  23. package/dist/chunk-GHHJYNAN.js.map +1 -0
  24. package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
  25. package/dist/chunk-HACRR422.js.map +1 -0
  26. package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
  27. package/dist/chunk-IWY5IR4F.js.map +1 -0
  28. package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
  29. package/dist/chunk-KIK5EZYD.js.map +1 -0
  30. package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
  31. package/dist/chunk-O4LN3HFI.js.map +1 -0
  32. package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
  33. package/dist/chunk-OCAVW6N5.js.map +1 -0
  34. package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
  35. package/dist/chunk-P6CYS4JK.js.map +1 -0
  36. package/dist/chunk-PLFANHRZ.js +35 -0
  37. package/dist/chunk-PLFANHRZ.js.map +1 -0
  38. package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
  39. package/dist/chunk-PMUZR4XO.js.map +1 -0
  40. package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
  41. package/dist/chunk-PSUTNOQ2.js.map +1 -0
  42. package/dist/chunk-RIK45Q4I.js +103 -0
  43. package/dist/chunk-RIK45Q4I.js.map +1 -0
  44. package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
  45. package/dist/chunk-THO7LO5B.js.map +1 -0
  46. package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
  47. package/dist/chunk-YGDWHDOY.js.map +1 -0
  48. package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
  49. package/dist/chunk-YXKTY5WM.js.map +1 -0
  50. package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
  51. package/dist/chunk-ZEGM3MVR.js.map +1 -0
  52. package/dist/commands/build/marketplace.js +46 -46
  53. package/dist/commands/build/marketplace.js.map +1 -1
  54. package/dist/commands/build/plugins.js +25 -28
  55. package/dist/commands/build/plugins.js.map +1 -1
  56. package/dist/commands/compile.js +87 -178
  57. package/dist/commands/compile.js.map +1 -1
  58. package/dist/commands/doctor.js +510 -360
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/edit.js +451 -357
  61. package/dist/commands/edit.js.map +1 -1
  62. package/dist/commands/eject.js +144 -125
  63. package/dist/commands/eject.js.map +1 -1
  64. package/dist/commands/init.js +20 -27
  65. package/dist/commands/list.js +39 -55
  66. package/dist/commands/list.js.map +1 -1
  67. package/dist/commands/new/marketplace.js +6 -11
  68. package/dist/commands/new/marketplace.js.map +1 -1
  69. package/dist/commands/search.js +35 -32
  70. package/dist/commands/search.js.map +1 -1
  71. package/dist/commands/share.js +17 -77
  72. package/dist/commands/share.js.map +1 -1
  73. package/dist/commands/uninstall.js +159 -222
  74. package/dist/commands/uninstall.js.map +1 -1
  75. package/dist/commands/update.js +9 -32
  76. package/dist/commands/update.js.map +1 -1
  77. package/dist/components/common/prompt-confirm.js +2 -2
  78. package/dist/components/common/removal-plan-confirm.js +2 -2
  79. package/dist/components/common/scroll-affordance.js +2 -2
  80. package/dist/components/common/select-list.js +2 -2
  81. package/dist/components/common/skill-agent-summary.js +4 -4
  82. package/dist/components/common/spinner.js +2 -4
  83. package/dist/components/common/summary-panel.js +5 -5
  84. package/dist/components/common/summary-panel.js.map +1 -1
  85. package/dist/config-exports.js +7 -3
  86. package/dist/config-exports.js.map +1 -1
  87. package/dist/hooks/init.js +18 -19
  88. package/dist/hooks/init.js.map +1 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/load-agent-defs-6QUUMGHK.js +14 -0
  91. package/dist/recompile-project-agents-I33KQJFB.js +65 -0
  92. package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
  93. package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
  94. package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
  95. package/dist/src/agents/developer/api-developer/playbook.md +2 -5
  96. package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
  97. package/dist/src/agents/developer/web-developer/playbook.md +2 -5
  98. package/dist/src/agents/meta/agent-summoner/output.md +2 -2
  99. package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
  100. package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  101. package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  102. package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  103. package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
  104. package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
  105. package/dist/src/agents/tester/api-tester/playbook.md +2 -0
  106. package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  107. package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
  108. package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
  109. package/dist/src/agents/tester/web-tester/playbook.md +2 -0
  110. package/package.json +9 -8
  111. package/src/agents/developer/ai-developer/playbook.md +2 -5
  112. package/src/agents/developer/api-developer/playbook.md +2 -5
  113. package/src/agents/developer/cli-developer/playbook.md +2 -5
  114. package/src/agents/developer/web-developer/playbook.md +2 -5
  115. package/src/agents/meta/agent-summoner/output.md +2 -2
  116. package/src/agents/meta/agent-summoner/playbook.md +1 -13
  117. package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  118. package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  119. package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  120. package/src/agents/tester/ai-tester/playbook.md +2 -0
  121. package/src/agents/tester/api-tester/critical-requirements.md +1 -2
  122. package/src/agents/tester/api-tester/playbook.md +2 -0
  123. package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  124. package/src/agents/tester/cli-tester/playbook.md +2 -0
  125. package/src/agents/tester/web-tester/critical-requirements.md +1 -2
  126. package/src/agents/tester/web-tester/playbook.md +2 -0
  127. package/src/schemas/project-config.schema.json +0 -3
  128. package/src/schemas/project-source-config.schema.json +0 -6
  129. package/dist/chunk-3G7X2WKI.js.map +0 -1
  130. package/dist/chunk-44TE3RKH.js.map +0 -1
  131. package/dist/chunk-4AAOOAIN.js.map +0 -1
  132. package/dist/chunk-52HDHJ7I.js.map +0 -1
  133. package/dist/chunk-6HNXYYVF.js +0 -373
  134. package/dist/chunk-6HNXYYVF.js.map +0 -1
  135. package/dist/chunk-6ZRH5RHC.js.map +0 -1
  136. package/dist/chunk-7RDMTR64.js.map +0 -1
  137. package/dist/chunk-BMRUNMPV.js.map +0 -1
  138. package/dist/chunk-CLPUWOSA.js +0 -46
  139. package/dist/chunk-CLPUWOSA.js.map +0 -1
  140. package/dist/chunk-F2BHT5C4.js.map +0 -1
  141. package/dist/chunk-F5EBEATU.js.map +0 -1
  142. package/dist/chunk-HED2DAXZ.js.map +0 -1
  143. package/dist/chunk-JFLVEFFP.js.map +0 -1
  144. package/dist/chunk-KOLDW6SF.js.map +0 -1
  145. package/dist/chunk-MQ6CGZNJ.js.map +0 -1
  146. package/dist/chunk-NCWDK6L7.js.map +0 -1
  147. package/dist/chunk-NEZ4OAOL.js.map +0 -1
  148. package/dist/chunk-NIHUOWE4.js +0 -106
  149. package/dist/chunk-NIHUOWE4.js.map +0 -1
  150. package/dist/chunk-NQW25DCF.js.map +0 -1
  151. package/dist/chunk-OYJQUA3D.js.map +0 -1
  152. package/dist/chunk-PJWGTNOX.js.map +0 -1
  153. package/dist/chunk-RIPSGNLU.js.map +0 -1
  154. package/dist/chunk-SZYQISA2.js.map +0 -1
  155. package/dist/chunk-USVBYQSQ.js.map +0 -1
  156. package/dist/chunk-V3KTSP3Q.js +0 -940
  157. package/dist/chunk-V3KTSP3Q.js.map +0 -1
  158. package/dist/chunk-WTWMGH2C.js.map +0 -1
  159. package/dist/load-agent-defs-YMDWBFDP.js +0 -14
  160. package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
  161. package/dist/source-loader-C5SQXZXI.js.map +0 -1
  162. /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
  163. /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
@@ -6,6 +6,7 @@ import {
6
6
  claudeStateFile,
7
7
  codexGlobalConfigFile,
8
8
  ensureDir,
9
+ extractFrontmatter,
9
10
  fileExists,
10
11
  glob,
11
12
  isHomeDirectory,
@@ -13,7 +14,7 @@ import {
13
14
  readFileOptional,
14
15
  unexpressibleOnCodexMessage,
15
16
  writeFile
16
- } from "./chunk-MQ6CGZNJ.js";
17
+ } from "./chunk-GAKVZNTX.js";
17
18
 
18
19
  // src/cli/lib/hosts/claude-project-trust.ts
19
20
  import path from "path";
@@ -21,8 +22,7 @@ import { realpath } from "fs/promises";
21
22
  import { z } from "zod";
22
23
  var claudeStateSchema = z.object({ projects: z.record(z.string(), z.unknown()) });
23
24
  var trustedProjectSchema = z.object({ hasTrustDialogAccepted: z.literal(true) });
24
- var STOP_HOOK_LINE = /^hooks:\s*\{.*"(Stop|SubagentStop)":\[\{/m;
25
- var FRONTMATTER_FENCE = "---";
25
+ var declaredHooksSchema = z.object({ hooks: z.record(z.string(), z.array(z.unknown())) });
26
26
  var GIT_ENTRY = ".git";
27
27
  var GITDIR_PREFIX = "gitdir:";
28
28
  var COMMONDIR_FILE = "commondir";
@@ -31,16 +31,16 @@ var WORKTREES_DIR = "worktrees";
31
31
  async function claudeCompileNotices(provider, projectDir) {
32
32
  if (provider !== "claude") return [];
33
33
  if (isHomeDirectory(projectDir)) return [];
34
- const withAStopHook = await projectAgentsWithAStopHook(projectDir);
35
- if (withAStopHook.length === 0) return [];
34
+ const agentsWithHooks = await countProjectAgentsDeclaringHooks(projectDir);
35
+ if (agentsWithHooks === 0) return [];
36
36
  const trust = await claudeTrustOf(projectDir);
37
37
  switch (trust.kind) {
38
38
  case "trusted":
39
39
  return [];
40
40
  case "asks":
41
- return [claudeProjectNeedsTrustMessage(projectDir, withAStopHook.length)];
41
+ return [claudeProjectNeedsTrustMessage(projectDir, agentsWithHooks)];
42
42
  case "never asks":
43
- return [claudeProjectNeverAskedMessage(trust.recordKey, withAStopHook.length)];
43
+ return [claudeProjectNeverAskedMessage(trust.recordKey, agentsWithHooks)];
44
44
  default: {
45
45
  const _exhaustive = trust;
46
46
  return _exhaustive;
@@ -48,13 +48,13 @@ async function claudeCompileNotices(provider, projectDir) {
48
48
  }
49
49
  }
50
50
  function claudeProjectNeedsTrustMessage(projectDir, count) {
51
- return `Claude Code runs a project sub-agent's completion gate (its Stop hook \u2014 the project's typecheck, unless the sub-agent declares its own) only once you trust the folder: open Claude Code in ${projectDir} and accept the trust prompt. Until then, ${completionGates(count)} will not run, and nothing will say so.`;
51
+ return `Claude Code runs a project sub-agent's hooks only once you trust the folder: open Claude Code in ${projectDir} and accept the trust prompt. Until then, ${hooksOf(count)} will not run, and nothing will say so.`;
52
52
  }
53
53
  function claudeProjectNeverAskedMessage(recordKey, count) {
54
- return `Claude Code runs ${completionGates(count)} only once you trust the folder, and will not ask here: set projects[${JSON.stringify(recordKey)}].hasTrustDialogAccepted to true in ${claudeStateFile()}.`;
54
+ return `Claude Code runs ${hooksOf(count)} only once you trust the folder, and will not ask here: set projects[${JSON.stringify(recordKey)}].hasTrustDialogAccepted to true in ${claudeStateFile()}.`;
55
55
  }
56
- function completionGates(count) {
57
- return count === 1 ? "1 sub-agent's completion gate" : `${count} sub-agents' completion gates`;
56
+ function hooksOf(count) {
57
+ return count === 1 ? "1 sub-agent's hooks" : `${count} sub-agents' hooks`;
58
58
  }
59
59
  async function claudeTrustOf(projectDir) {
60
60
  const [isTrusted, repositoryRoot] = await Promise.all([
@@ -122,23 +122,22 @@ async function realpathOrUndefined(file) {
122
122
  return void 0;
123
123
  }
124
124
  }
125
- async function projectAgentsWithAStopHook(projectDir) {
125
+ async function countProjectAgentsDeclaringHooks(projectDir) {
126
126
  const dir = agentsDir("claude", "project", projectDir);
127
127
  const files = await glob(agentCodec("claude").listGlob, dir);
128
- const carriers = await Promise.all(
129
- files.map(async (file) => await carriesAStopHook(path.join(dir, file)) ? [file] : [])
130
- );
131
- return carriers.flat();
128
+ const agents = await Promise.all(files.map((file) => readFile(path.join(dir, file))));
129
+ return agents.filter(declaresAHook).length;
132
130
  }
133
- async function carriesAStopHook(agentFile) {
134
- const [, frontmatter = ""] = (await readFile(agentFile)).split(FRONTMATTER_FENCE);
135
- return STOP_HOOK_LINE.test(frontmatter);
131
+ function declaresAHook(agentMarkdown) {
132
+ const frontmatter = declaredHooksSchema.safeParse(extractFrontmatter(agentMarkdown));
133
+ return frontmatter.success && Object.values(frontmatter.data.hooks).some((definitions) => definitions.length > 0);
136
134
  }
137
135
 
138
136
  // src/cli/lib/hosts/codex-project-trust.ts
139
137
  import path2 from "path";
140
138
  var TRUST_KEY = "trust_level";
141
139
  var TRUSTED = "trusted";
140
+ var TRUST_ASSIGNMENT = `${TRUST_KEY} = "${TRUSTED}"`;
142
141
  async function trustCodexProject(projectDir) {
143
142
  const configFile = codexGlobalConfigFile();
144
143
  const dir = path2.resolve(projectDir);
@@ -151,7 +150,7 @@ async function trustCodexProject(projectDir) {
151
150
  return { kind: "trusted now", configFile };
152
151
  }
153
152
  function codexProjectTrustMessage(projectDir, trust) {
154
- const table = `[projects."${path2.resolve(projectDir)}"]`;
153
+ const table = projectTableHeader(path2.resolve(projectDir));
155
154
  switch (trust.kind) {
156
155
  case "already trusted":
157
156
  return void 0;
@@ -166,15 +165,21 @@ function codexProjectTrustMessage(projectDir, trust) {
166
165
  }
167
166
  }
168
167
  function declaresTrust(config, projectDir) {
168
+ return linesForProject(config, projectDir).includes(TRUST_ASSIGNMENT);
169
+ }
170
+ var TRUST_LEVEL_LINE = new RegExp(`^${TRUST_KEY}\\s*=\\s*"([^"]*)"$`);
171
+ function declaredLevel(config, projectDir) {
172
+ return linesForProject(config, projectDir).map((line) => TRUST_LEVEL_LINE.exec(line)?.[1]).find((level) => level !== void 0);
173
+ }
174
+ function linesForProject(config, projectDir) {
169
175
  const lines = config.split("\n").map((line) => line.trim());
170
- return trustsUnderTableHeader(lines, projectDir) || lines.includes(dottedTrustLine(projectDir));
176
+ const dottedPrefix = `projects."${projectDir}".`;
177
+ const dotted = lines.filter((line) => line.startsWith(dottedPrefix)).map((line) => line.slice(dottedPrefix.length));
178
+ return [...linesUnderProjectTable(lines, projectDir), ...dotted];
171
179
  }
172
- function trustsUnderTableHeader(lines, projectDir) {
180
+ function linesUnderProjectTable(lines, projectDir) {
173
181
  const header = lines.indexOf(projectTableHeader(projectDir));
174
- if (header === -1) return false;
175
- return linesUnderTableHeader(lines, header).includes(trustAssignment());
176
- }
177
- function linesUnderTableHeader(lines, header) {
182
+ if (header === -1) return [];
178
183
  const after = lines.slice(header + 1);
179
184
  const nextTable = after.findIndex(opensATable);
180
185
  return nextTable === -1 ? after : after.slice(0, nextTable);
@@ -185,32 +190,15 @@ function opensATable(line) {
185
190
  function projectTableHeader(projectDir) {
186
191
  return `[projects."${projectDir}"]`;
187
192
  }
188
- function dottedTrustLine(projectDir) {
189
- return `projects."${projectDir}".${trustAssignment()}`;
190
- }
191
- function trustAssignment() {
192
- return `${TRUST_KEY} = "${TRUSTED}"`;
193
- }
194
- var TRUST_LEVEL_LINE = new RegExp(`^${TRUST_KEY}\\s*=\\s*"([^"]*)"$`);
195
- function declaredLevel(config, projectDir) {
196
- const lines = config.split("\n").map((line) => line.trim());
197
- const header = lines.indexOf(projectTableHeader(projectDir));
198
- const underHeader = header === -1 ? [] : linesUnderTableHeader(lines, header);
199
- const dottedPrefix = `projects."${projectDir}".`;
200
- const dotted = lines.filter((line) => line.startsWith(dottedPrefix)).map((line) => line.slice(dottedPrefix.length));
201
- return [...underHeader, ...dotted].map((line) => TRUST_LEVEL_LINE.exec(line)?.[1]).find((level) => level !== void 0);
202
- }
203
193
  function withTrustFor(config, projectDir) {
204
194
  const lines = config.split("\n");
205
195
  const header = lines.findIndex((line) => line.trim() === projectTableHeader(projectDir));
206
196
  if (header !== -1) {
207
- return [...lines.slice(0, header + 1), trustAssignment(), ...lines.slice(header + 1)].join(
208
- "\n"
209
- );
197
+ return [...lines.slice(0, header + 1), TRUST_ASSIGNMENT, ...lines.slice(header + 1)].join("\n");
210
198
  }
211
199
  const theirs = config.trimEnd();
212
200
  const table = `${projectTableHeader(projectDir)}
213
- ${trustAssignment()}
201
+ ${TRUST_ASSIGNMENT}
214
202
  `;
215
203
  return theirs === "" ? table : `${theirs}
216
204
 
@@ -247,4 +235,4 @@ async function hostCompileNotices(provider, projectDir) {
247
235
  export {
248
236
  hostCompileNotices
249
237
  };
250
- //# sourceMappingURL=chunk-F5EBEATU.js.map
238
+ //# sourceMappingURL=chunk-PSUTNOQ2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/hosts/claude-project-trust.ts","../src/cli/lib/hosts/codex-project-trust.ts","../src/cli/lib/hosts/codex-compile-notices.ts","../src/cli/lib/hosts/host-compile-notices.ts"],"sourcesContent":["import path from \"path\";\nimport { realpath } from \"fs/promises\";\n\nimport { z } from \"zod\";\n\nimport { agentCodec, agentsDir, claudeStateFile } from \"../installation/install-layout.js\";\nimport { isHomeDirectory } from \"../installation/is-home-directory.js\";\nimport { fileExists, glob, readFile, readFileOptional } from \"../../utils/fs.js\";\nimport { extractFrontmatter } from \"../../utils/frontmatter.js\";\nimport type { Provider } from \"../../consts.js\";\n\n/**\n * Warns when Claude Code will drop a project sub-agent's hooks, on every event: project hooks run\n * only once `~/.claude.json` records `projects[<key>].hasTrustDialogAccepted`, keyed by the git\n * repository root (a linked worktree's main checkout). Reads that state, never writes it.\n */\n\nconst claudeStateSchema = z.object({ projects: z.record(z.string(), z.unknown()) });\n\nconst trustedProjectSchema = z.object({ hasTrustDialogAccepted: z.literal(true) });\n\n/** Claude Code reads only a top-level `hooks:` key: event name to its definitions. */\nconst declaredHooksSchema = z.object({ hooks: z.record(z.string(), z.array(z.unknown())) });\n\nconst GIT_ENTRY = \".git\";\nconst GITDIR_PREFIX = \"gitdir:\";\nconst COMMONDIR_FILE = \"commondir\";\nconst BACK_LINK_FILE = \"gitdir\";\nconst WORKTREES_DIR = \"worktrees\";\n\n/** \"never asks\": a folder above is trusted, so no prompt appears and only the record can fix it. */\ntype ClaudeTrust =\n | { readonly kind: \"trusted\" }\n | { readonly kind: \"asks\" }\n | { readonly kind: \"never asks\"; readonly recordKey: string };\n\ntype TrustRecord = (folder: string) => boolean;\n\n/** Empty from the home directory: `~/.claude/agents/` is trusted unconditionally. */\nexport async function claudeCompileNotices(\n provider: Provider,\n projectDir: string,\n): Promise<string[]> {\n if (provider !== \"claude\") return [];\n if (isHomeDirectory(projectDir)) return [];\n\n const agentsWithHooks = await countProjectAgentsDeclaringHooks(projectDir);\n if (agentsWithHooks === 0) return [];\n\n const trust = await claudeTrustOf(projectDir);\n switch (trust.kind) {\n case \"trusted\":\n return [];\n case \"asks\":\n return [claudeProjectNeedsTrustMessage(projectDir, agentsWithHooks)];\n case \"never asks\":\n return [claudeProjectNeverAskedMessage(trust.recordKey, agentsWithHooks)];\n default: {\n const _exhaustive: never = trust;\n return _exhaustive;\n }\n }\n}\n\nexport function claudeProjectNeedsTrustMessage(projectDir: string, count: number): string {\n return (\n `Claude Code runs a project sub-agent's hooks only once you trust the folder: open Claude ` +\n `Code in ${projectDir} and accept the trust prompt. Until then, ${hooksOf(count)} will not ` +\n `run, and nothing will say so.`\n );\n}\n\nexport function claudeProjectNeverAskedMessage(recordKey: string, count: number): string {\n return (\n `Claude Code runs ${hooksOf(count)} only once you trust the folder, and will not ask here: ` +\n `set projects[${JSON.stringify(recordKey)}].hasTrustDialogAccepted to true in ` +\n `${claudeStateFile()}.`\n );\n}\n\nfunction hooksOf(count: number): string {\n return count === 1 ? \"1 sub-agent's hooks\" : `${count} sub-agents' hooks`;\n}\n\nasync function claudeTrustOf(projectDir: string): Promise<ClaudeTrust> {\n const [isTrusted, repositoryRoot] = await Promise.all([\n trustRecord(),\n gitRepositoryRoot(projectDir),\n ]);\n const recordKey =\n repositoryRoot === undefined ? projectDir : await canonicalRepositoryRoot(repositoryRoot);\n if (isTrusted(recordKey)) return { kind: \"trusted\" };\n\n const promptSuppressed = foldersUpTo(projectDir, repositoryRoot).some(isTrusted);\n return promptSuppressed ? { kind: \"never asks\", recordKey } : { kind: \"asks\" };\n}\n\n/** Unreadable counts as untrusted: a wrong \"untrusted\" costs one line of advice. */\nasync function trustRecord(): Promise<TrustRecord> {\n const stateFile = claudeStateFile();\n if (!(await fileExists(stateFile))) return () => false;\n\n const state = claudeStateSchema.safeParse(parsedOrUndefined(await readFile(stateFile)));\n if (!state.success) return () => false;\n\n const { projects } = state.data;\n return (folder) => trustedProjectSchema.safeParse(projects[folder]).success;\n}\n\nfunction parsedOrUndefined(json: string): unknown {\n try {\n return JSON.parse(json);\n } catch {\n return undefined;\n }\n}\n\nfunction foldersUpTo(folder: string, top?: string): string[] {\n const parent = path.dirname(folder);\n if (folder === top || parent === folder) return [folder];\n return [folder, ...foldersUpTo(parent, top)];\n}\n\nasync function gitRepositoryRoot(folder: string): Promise<string | undefined> {\n const candidates = foldersUpTo(folder);\n const holdsGit = await Promise.all(\n candidates.map((candidate) => fileExists(path.join(candidate, GIT_ENTRY))),\n );\n return candidates.find((_, index) => holdsGit[index]);\n}\n\n/**\n * A linked worktree (`.git` file pointing into `<main>/.git/worktrees/`, which points back) is\n * keyed by its main checkout; anything else by `root` itself.\n */\nasync function canonicalRepositoryRoot(root: string): Promise<string> {\n // A `.git` directory reads as empty, as a missing file does.\n const pointer = (await readFileOptional(path.join(root, GIT_ENTRY))).trim();\n if (!pointer.startsWith(GITDIR_PREFIX)) return root;\n\n const gitDir = path.resolve(root, pointer.slice(GITDIR_PREFIX.length).trim());\n const [commonDir, backLink] = await Promise.all([\n pathRecordedIn(gitDir, COMMONDIR_FILE),\n pathRecordedIn(gitDir, BACK_LINK_FILE),\n ]);\n const isLinkedWorktree =\n path.dirname(gitDir) === path.join(commonDir, WORKTREES_DIR) &&\n (await pointsBackAt(backLink, root));\n if (!isLinkedWorktree) return root;\n\n // A worktree of a bare repository is keyed by the bare repository's own folder.\n return path.basename(commonDir) === GIT_ENTRY ? path.dirname(commonDir) : commonDir;\n}\n\nasync function pathRecordedIn(dir: string, file: string): Promise<string> {\n return path.resolve(dir, (await readFileOptional(path.join(dir, file))).trim());\n}\n\nasync function pointsBackAt(backLink: string, root: string): Promise<boolean> {\n const [linked, realRoot] = await Promise.all([\n realpathOrUndefined(backLink),\n realpathOrUndefined(root),\n ]);\n return realRoot !== undefined && linked === path.join(realRoot, GIT_ENTRY);\n}\n\nasync function realpathOrUndefined(file: string): Promise<string | undefined> {\n try {\n return await realpath(file);\n } catch {\n return undefined;\n }\n}\n\nasync function countProjectAgentsDeclaringHooks(projectDir: string): Promise<number> {\n const dir = agentsDir(\"claude\", \"project\", projectDir);\n const files = await glob(agentCodec(\"claude\").listGlob, dir);\n const agents = await Promise.all(files.map((file) => readFile(path.join(dir, file))));\n return agents.filter(declaresAHook).length;\n}\n\n/** An event with no definition runs nothing, so it is not a hook to warn about. */\nfunction declaresAHook(agentMarkdown: string): boolean {\n const frontmatter = declaredHooksSchema.safeParse(extractFrontmatter(agentMarkdown));\n return (\n frontmatter.success &&\n Object.values(frontmatter.data.hooks).some((definitions) => definitions.length > 0)\n );\n}\n","import path from \"path\";\n\nimport { codexGlobalConfigFile } from \"../installation/install-layout.js\";\nimport { ensureDir, fileExists, readFile, writeFile } from \"../../utils/fs.js\";\n\n/**\n * Codex reads `<project>/.codex/agents/*.toml` only while the GLOBAL `config.toml` holds\n * `[projects.\"<abs path>\"] trust_level = \"trusted\"`, failing silently otherwise. The install writes\n * that entry and says so, but never overrides a level the user already set.\n */\n\nconst TRUST_KEY = \"trust_level\";\nconst TRUSTED = \"trusted\";\nconst TRUST_ASSIGNMENT = `${TRUST_KEY} = \"${TRUSTED}\"`;\n\nexport type CodexProjectTrust =\n | { readonly kind: \"already trusted\" }\n | { readonly kind: \"trusted now\"; readonly configFile: string }\n | {\n readonly kind: \"left as the user set it\";\n readonly configFile: string;\n readonly level: string;\n };\n\n/**\n * Merged into the user's file, never rewritten: a second table for the same path would make Codex\n * refuse the whole file. `path.resolve` gives the one spelling Codex matches (no trailing slash).\n */\nexport async function trustCodexProject(projectDir: string): Promise<CodexProjectTrust> {\n const configFile = codexGlobalConfigFile();\n const dir = path.resolve(projectDir);\n const config = (await fileExists(configFile)) ? await readFile(configFile) : \"\";\n\n if (declaresTrust(config, dir)) return { kind: \"already trusted\" };\n\n const level = declaredLevel(config, dir);\n if (level !== undefined) return { kind: \"left as the user set it\", configFile, level };\n\n await ensureDir(path.dirname(configFile));\n await writeFile(configFile, withTrustFor(config, dir));\n return { kind: \"trusted now\", configFile };\n}\n\nexport function codexProjectTrustMessage(\n projectDir: string,\n trust: CodexProjectTrust,\n): string | undefined {\n const table = projectTableHeader(path.resolve(projectDir));\n\n switch (trust.kind) {\n case \"already trusted\":\n return undefined;\n case \"trusted now\":\n return (\n `Trusted this project in your Codex configuration, so Codex reads its sub-agents: added ` +\n `${table} with ${TRUST_KEY} = \"${TRUSTED}\" to ${trust.configFile}.`\n );\n case \"left as the user set it\":\n return (\n `Codex reads this project's sub-agents only once it is trusted, and ${trust.configFile} ` +\n `sets ${TRUST_KEY} = \"${trust.level}\" under ${table}. Left as you set it — change it to ` +\n `\"${TRUSTED}\" for Codex to read them.`\n );\n default: {\n const _exhaustive: never = trust;\n return _exhaustive;\n }\n }\n}\n\n/** Hand-read, not TOML-parsed; any other spelling reads as untrusted, the safe direction. */\nfunction declaresTrust(config: string, projectDir: string): boolean {\n return linesForProject(config, projectDir).includes(TRUST_ASSIGNMENT);\n}\n\nconst TRUST_LEVEL_LINE = new RegExp(`^${TRUST_KEY}\\\\s*=\\\\s*\"([^\"]*)\"$`);\n\n/** The user's own `trust_level` for this project, which is never overwritten. */\nfunction declaredLevel(config: string, projectDir: string): string | undefined {\n return linesForProject(config, projectDir)\n .map((line) => TRUST_LEVEL_LINE.exec(line)?.[1])\n .find((level) => level !== undefined);\n}\n\n/** Trimmed: the lines under the project's table header, then its dotted keys with the prefix cut. */\nfunction linesForProject(config: string, projectDir: string): string[] {\n const lines = config.split(\"\\n\").map((line) => line.trim());\n const dottedPrefix = `projects.\"${projectDir}\".`;\n const dotted = lines\n .filter((line) => line.startsWith(dottedPrefix))\n .map((line) => line.slice(dottedPrefix.length));\n\n return [...linesUnderProjectTable(lines, projectDir), ...dotted];\n}\n\nfunction linesUnderProjectTable(lines: readonly string[], projectDir: string): readonly string[] {\n const header = lines.indexOf(projectTableHeader(projectDir));\n if (header === -1) return [];\n\n const after = lines.slice(header + 1);\n const nextTable = after.findIndex(opensATable);\n return nextTable === -1 ? after : after.slice(0, nextTable);\n}\n\nfunction opensATable(line: string): boolean {\n return line.startsWith(\"[\");\n}\n\nfunction projectTableHeader(projectDir: string): string {\n return `[projects.\"${projectDir}\"]`;\n}\n\nfunction withTrustFor(config: string, projectDir: string): string {\n const lines = config.split(\"\\n\");\n const header = lines.findIndex((line) => line.trim() === projectTableHeader(projectDir));\n\n if (header !== -1) {\n return [...lines.slice(0, header + 1), TRUST_ASSIGNMENT, ...lines.slice(header + 1)].join(\"\\n\");\n }\n\n const theirs = config.trimEnd();\n const table = `${projectTableHeader(projectDir)}\\n${TRUST_ASSIGNMENT}\\n`;\n return theirs === \"\" ? table : `${theirs}\\n\\n${table}`;\n}\n","import {\n agentsLeftOutOfCodexMessage,\n unexpressibleOnCodexMessage,\n} from \"@workspace/compile/agent-source\";\n\nimport { codexProjectTrustMessage, trustCodexProject } from \"./codex-project-trust.js\";\nimport { agentCodec, agentsDir } from \"../installation/install-layout.js\";\nimport { glob } from \"../../utils/fs.js\";\nimport type { Provider } from \"../../consts.js\";\n\n/** Once per run, not per sub-agent or scope: each notice is true of the whole installation. */\nexport async function codexCompileNotices(\n provider: Provider,\n projectDir: string,\n): Promise<string[]> {\n if (provider !== \"codex\") return [];\n\n return [\n agentsLeftOutOfCodexMessage(),\n unexpressibleOnCodexMessage(),\n ...(await trustNotice(projectDir)),\n ];\n}\n\n/** Only when role files exist: trusting a project with nothing for Codex to read grants nothing. */\nasync function trustNotice(projectDir: string): Promise<string[]> {\n if (!(await holdsProjectRoles(projectDir))) return [];\n\n const said = codexProjectTrustMessage(projectDir, await trustCodexProject(projectDir));\n return said === undefined ? [] : [said];\n}\n\nasync function holdsProjectRoles(projectDir: string): Promise<boolean> {\n const roles = await glob(agentCodec(\"codex\").listGlob, agentsDir(\"codex\", \"project\", projectDir));\n\n return roles.length > 0;\n}\n","import { claudeCompileNotices } from \"./claude-project-trust.js\";\nimport { codexCompileNotices } from \"./codex-compile-notices.js\";\nimport type { Provider } from \"../../consts.js\";\n\n/** The one source `init` and `compile` share, so they cannot say different things. */\nexport async function hostCompileNotices(\n provider: Provider,\n projectDir: string,\n): Promise<string[]> {\n return [\n ...(await codexCompileNotices(provider, projectDir)),\n ...(await claudeCompileNotices(provider, projectDir)),\n ];\n}\n"],"mappings":"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","names":["path","path"]}
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ isActiveAt,
4
+ isGlobalTombstone
5
+ } from "./chunk-7C3PFRBU.js";
6
+
7
+ // src/cli/lib/configuration/scope-diff.ts
8
+ import { partition } from "remeda";
9
+ function computeScopeDiff(input) {
10
+ const { currentSkills, currentAgents, installedSkillConfigs, installedAgentConfigs, isInitMode } = input;
11
+ const skills = diffRoster(currentSkills, installedSkillConfigs, (skill) => skill.id, isInitMode);
12
+ const agents = diffRoster(
13
+ currentAgents,
14
+ installedAgentConfigs,
15
+ (agent) => agent.name,
16
+ isInitMode
17
+ );
18
+ const skillRow = skillRowClassifier(installedSkillConfigs);
19
+ const agentRow = agentRowClassifier(installedAgentConfigs);
20
+ const projectSkillRows = rowsOf(skills.project, skillRow, toRemovedSkillRow);
21
+ const globalSkillRows = rowsOf(skills.global, skillRow, toRemovedSkillRow);
22
+ const projectAgentRows = rowsOf(agents.project, agentRow, toRemovedAgentRow);
23
+ const globalAgentRows = rowsOf(agents.global, agentRow, toRemovedAgentRow);
24
+ const hasContent = [projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows].some(
25
+ (rows) => rows.length > 0
26
+ );
27
+ return { projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows, hasContent };
28
+ }
29
+ function diffRoster(current, installed, identityOf, isInitMode) {
30
+ const activeBaseline = (installed ?? []).filter((entry) => !entry.excluded);
31
+ const vacated = vacatedInstalls(activeBaseline, current, identityOf);
32
+ const projectEntries = current.filter((entry) => isActiveAt(entry, "project"));
33
+ const claimedByProject = new Set(projectEntries.map(identityOf));
34
+ const [inheritedGlobals, removedGlobals] = partition(
35
+ vacated.filter((entry) => entry.scope === "global"),
36
+ (entry) => claimedByProject.has(identityOf(entry))
37
+ );
38
+ return {
39
+ project: {
40
+ listed: projectEntries,
41
+ removed: vacated.filter((entry) => entry.scope === "project")
42
+ },
43
+ global: {
44
+ listed: [
45
+ ...current.filter((entry) => isActiveAt(entry, "global")),
46
+ ...inheritedGlobals,
47
+ ...current.filter(isGlobalTombstone)
48
+ ],
49
+ removed: isInitMode ? [] : removedGlobals
50
+ }
51
+ };
52
+ }
53
+ function vacatedInstalls(activeBaseline, current, identityOf) {
54
+ const slotOf = (entry) => slotKey(identityOf(entry), entry.scope);
55
+ const occupiedSlots = new Set(current.map(slotOf));
56
+ return activeBaseline.filter((install) => !occupiedSlots.has(slotOf(install)));
57
+ }
58
+ function rowsOf(entries, toRow, toRemovedRow) {
59
+ return [...entries.listed.map(toRow), ...entries.removed.map(toRemovedRow)];
60
+ }
61
+ function slotKey(identity, scope) {
62
+ return `${identity}:${scope}`;
63
+ }
64
+ function formatScopeTag(scope) {
65
+ return scope === "global" ? "[G]" : "[P]";
66
+ }
67
+ function skillRowClassifier(installed) {
68
+ const installedSlots = installed ? new Set(installed.map((skill) => slotKey(skill.id, skill.scope))) : null;
69
+ const installedOriginBySlot = installed ? new Map(
70
+ installed.filter((skill) => !skill.excluded).map((skill) => [slotKey(skill.id, skill.scope), skill.origin])
71
+ ) : null;
72
+ return (skill) => classifySkillDiffRow(skill, installedSlots, installedOriginBySlot);
73
+ }
74
+ function agentRowClassifier(installed) {
75
+ const installedSlots = installed ? new Set(installed.map((agent) => slotKey(agent.name, agent.scope))) : null;
76
+ return (agent) => classifyAgentDiffRow(agent, installedSlots);
77
+ }
78
+ function classifySkillDiffRow(skill, installedSlots, installedOriginBySlot) {
79
+ const slot = slotKey(skill.id, skill.scope);
80
+ const isNew = installedSlots === null || !installedSlots.has(slot);
81
+ const installedOrigin = installedOriginBySlot?.get(slot);
82
+ const modeChanged = !isNew && installedOrigin != null && installedOrigin !== skill.origin;
83
+ if (modeChanged) {
84
+ return { id: skill.id, source: skill.origin, status: "mode-changed" };
85
+ }
86
+ return { id: skill.id, source: skill.origin, status: isNew ? "added" : "unchanged" };
87
+ }
88
+ function classifyAgentDiffRow(agent, installedSlots) {
89
+ const isNew = installedSlots === null || !installedSlots.has(slotKey(agent.name, agent.scope));
90
+ return { name: agent.name, status: isNew ? "added" : "unchanged" };
91
+ }
92
+ function toRemovedSkillRow(skill) {
93
+ return { id: skill.id, source: skill.origin, status: "removed" };
94
+ }
95
+ function toRemovedAgentRow(agent) {
96
+ return { name: agent.name, status: "removed" };
97
+ }
98
+
99
+ export {
100
+ computeScopeDiff,
101
+ formatScopeTag
102
+ };
103
+ //# sourceMappingURL=chunk-RIK45Q4I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/configuration/scope-diff.ts"],"sourcesContent":["import { partition } from \"remeda\";\nimport type { AgentScopeConfig, SkillConfig, SkillScope } from \"../../types/config\";\nimport type { AgentName, SkillId } from \"../../types/index\";\nimport { isActiveAt, isGlobalTombstone, type ScopedEntry } from \"./scope-predicates\";\n\nexport type ScopeDiffInput = {\n currentSkills: SkillConfig[];\n currentAgents: AgentScopeConfig[];\n installedSkillConfigs: SkillConfig[] | null;\n installedAgentConfigs: AgentScopeConfig[] | null;\n isInitMode: boolean;\n};\n\nexport type DiffRowStatus = \"added\" | \"mode-changed\" | \"removed\" | \"unchanged\";\n\nexport type SkillDiffRow = {\n id: SkillId;\n source: string;\n status: DiffRowStatus;\n};\n\nexport type AgentDiffRow = {\n name: AgentName;\n status: Exclude<DiffRowStatus, \"mode-changed\">;\n};\n\nexport type ScopeDiff = {\n projectSkillRows: SkillDiffRow[];\n globalSkillRows: SkillDiffRow[];\n projectAgentRows: AgentDiffRow[];\n globalAgentRows: AgentDiffRow[];\n hasContent: boolean;\n};\n\n/** One scope's share of a roster's diff: the entries listed with a status, then the removals. */\ntype ScopeEntries<Entry> = { listed: Entry[]; removed: Entry[] };\n\ntype RosterDiff<Entry> = Record<SkillScope, ScopeEntries<Entry>>;\n\n/**\n * A tombstone occupies its (id, scope) slot without filling it: it silences a global install at\n * project scope. Slot checks count tombstones; removal and `~` read the active baseline only.\n */\nexport function computeScopeDiff(input: ScopeDiffInput): ScopeDiff {\n const { currentSkills, currentAgents, installedSkillConfigs, installedAgentConfigs, isInitMode } =\n input;\n\n const skills = diffRoster(currentSkills, installedSkillConfigs, (skill) => skill.id, isInitMode);\n const agents = diffRoster(\n currentAgents,\n installedAgentConfigs,\n (agent) => agent.name,\n isInitMode,\n );\n const skillRow = skillRowClassifier(installedSkillConfigs);\n const agentRow = agentRowClassifier(installedAgentConfigs);\n\n const projectSkillRows = rowsOf(skills.project, skillRow, toRemovedSkillRow);\n const globalSkillRows = rowsOf(skills.global, skillRow, toRemovedSkillRow);\n const projectAgentRows = rowsOf(agents.project, agentRow, toRemovedAgentRow);\n const globalAgentRows = rowsOf(agents.global, agentRow, toRemovedAgentRow);\n\n const hasContent = [projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows].some(\n (rows) => rows.length > 0,\n );\n\n return { projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows, hasContent };\n}\n\nfunction diffRoster<Entry extends ScopedEntry>(\n current: Entry[],\n installed: Entry[] | null,\n identityOf: (entry: Entry) => string,\n isInitMode: boolean,\n): RosterDiff<Entry> {\n // The installs the baseline actually records; tombstones are not installs.\n const activeBaseline = (installed ?? []).filter((entry) => !entry.excluded);\n const vacated = vacatedInstalls(activeBaseline, current, identityOf);\n const projectEntries = current.filter((entry) => isActiveAt(entry, \"project\"));\n const claimedByProject = new Set(projectEntries.map(identityOf));\n // A vacated global the project claims is inherited: listed once under Global, never removed.\n const [inheritedGlobals, removedGlobals] = partition(\n vacated.filter((entry) => entry.scope === \"global\"),\n (entry) => claimedByProject.has(identityOf(entry)),\n );\n\n return {\n project: {\n listed: projectEntries,\n removed: vacated.filter((entry) => entry.scope === \"project\"),\n },\n global: {\n listed: [\n ...current.filter((entry) => isActiveAt(entry, \"global\")),\n ...inheritedGlobals,\n ...current.filter(isGlobalTombstone),\n ],\n removed: isInitMode ? [] : removedGlobals,\n },\n };\n}\n\n/** Baseline installs whose slot nothing in current, active or tombstone, occupies. */\nfunction vacatedInstalls<Entry extends ScopedEntry>(\n activeBaseline: Entry[],\n current: Entry[],\n identityOf: (entry: Entry) => string,\n): Entry[] {\n const slotOf = (entry: Entry) => slotKey(identityOf(entry), entry.scope);\n const occupiedSlots = new Set(current.map(slotOf));\n return activeBaseline.filter((install) => !occupiedSlots.has(slotOf(install)));\n}\n\nfunction rowsOf<Entry, Row>(\n entries: ScopeEntries<Entry>,\n toRow: (entry: Entry) => Row,\n toRemovedRow: (entry: Entry) => Row,\n): Row[] {\n return [...entries.listed.map(toRow), ...entries.removed.map(toRemovedRow)];\n}\n\n/** The `(id, scope)` SLOT key this module diffs on, rather than the id alone. */\nfunction slotKey(identity: string, scope: SkillScope | undefined): string {\n return `${identity}:${scope}`;\n}\n\nexport function formatScopeTag(scope: SkillScope): \"[G]\" | \"[P]\" {\n return scope === \"global\" ? \"[G]\" : \"[P]\";\n}\n\nfunction skillRowClassifier(installed: SkillConfig[] | null): (skill: SkillConfig) => SkillDiffRow {\n const installedSlots = installed\n ? new Set(installed.map((skill) => slotKey(skill.id, skill.scope)))\n : null;\n const installedOriginBySlot = installed\n ? new Map(\n installed\n .filter((skill) => !skill.excluded)\n .map((skill) => [slotKey(skill.id, skill.scope), skill.origin]),\n )\n : null;\n return (skill) => classifySkillDiffRow(skill, installedSlots, installedOriginBySlot);\n}\n\nfunction agentRowClassifier(\n installed: AgentScopeConfig[] | null,\n): (agent: AgentScopeConfig) => AgentDiffRow {\n const installedSlots = installed\n ? new Set(installed.map((agent) => slotKey(agent.name, agent.scope)))\n : null;\n return (agent) => classifyAgentDiffRow(agent, installedSlots);\n}\n\n/** Compares `origin`, which is where a skill's install mode is recorded. */\nfunction classifySkillDiffRow(\n skill: SkillConfig,\n installedSlots: Set<string> | null,\n installedOriginBySlot: Map<string, string> | null,\n): SkillDiffRow {\n const slot = slotKey(skill.id, skill.scope);\n const isNew = installedSlots === null || !installedSlots.has(slot);\n const installedOrigin = installedOriginBySlot?.get(slot);\n const modeChanged = !isNew && installedOrigin != null && installedOrigin !== skill.origin;\n if (modeChanged) {\n return { id: skill.id, source: skill.origin, status: \"mode-changed\" };\n }\n return { id: skill.id, source: skill.origin, status: isNew ? \"added\" : \"unchanged\" };\n}\n\nfunction classifyAgentDiffRow(\n agent: AgentScopeConfig,\n installedSlots: Set<string> | null,\n): AgentDiffRow {\n const isNew = installedSlots === null || !installedSlots.has(slotKey(agent.name, agent.scope));\n return { name: agent.name, status: isNew ? \"added\" : \"unchanged\" };\n}\n\nfunction toRemovedSkillRow(skill: SkillConfig): SkillDiffRow {\n return { id: skill.id, source: skill.origin, status: \"removed\" };\n}\n\nfunction toRemovedAgentRow(agent: AgentScopeConfig): AgentDiffRow {\n return { name: agent.name, status: \"removed\" };\n}\n"],"mappings":"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","names":[]}
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- getAgentDefinitions
4
- } from "./chunk-3G7X2WKI.js";
3
+ getLocalAgentDefinitions
4
+ } from "./chunk-5BNX73OU.js";
5
5
  import {
6
6
  loadMergedAgents
7
- } from "./chunk-MQ6CGZNJ.js";
7
+ } from "./chunk-GAKVZNTX.js";
8
8
 
9
9
  // src/cli/lib/operations/project/load-agent-defs.ts
10
10
  async function loadAgentDefs() {
11
- const agentSourcePaths = await getAgentDefinitions();
11
+ const agentSourcePaths = await getLocalAgentDefinitions();
12
12
  const agents = await loadMergedAgents(agentSourcePaths.sourcePath);
13
13
  return {
14
14
  agents,
@@ -20,4 +20,4 @@ async function loadAgentDefs() {
20
20
  export {
21
21
  loadAgentDefs
22
22
  };
23
- //# sourceMappingURL=chunk-HED2DAXZ.js.map
23
+ //# sourceMappingURL=chunk-THO7LO5B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/operations/project/load-agent-defs.ts"],"sourcesContent":["import { getLocalAgentDefinitions } from \"../../agents/index.js\";\nimport { loadMergedAgents } from \"../../loading/index.js\";\nimport type { AgentDefinition, AgentName, AgentSourcePaths } from \"../../../types/index.js\";\n\nexport type AgentDefs = {\n /** The CLI's own sub-agent definitions; nothing a marketplace declares. */\n agents: Partial<Record<AgentName, AgentDefinition>>;\n sourcePath: string;\n agentSourcePaths: AgentSourcePaths;\n};\n\n/**\n * The single definition of which sub-agents exist, shared by every compile pass and every\n * emitted `AgentName` union; a marketplace's sub-agents are never included.\n */\nexport async function loadAgentDefs(): Promise<AgentDefs> {\n const agentSourcePaths = await getLocalAgentDefinitions();\n const agents = await loadMergedAgents(agentSourcePaths.sourcePath);\n\n return {\n agents,\n sourcePath: agentSourcePaths.sourcePath,\n agentSourcePaths,\n };\n}\n"],"mappings":";;;;;;;;;AAeA,eAAsB,gBAAoC;AACxD,QAAM,mBAAmB,MAAM,yBAAyB;AACxD,QAAM,SAAS,MAAM,iBAAiB,iBAAiB,UAAU;AAEjE,SAAO;AAAA,IACL;AAAA,IACA,YAAY,iBAAiB;AAAA,IAC7B;AAAA,EACF;AACF;","names":[]}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateText
4
- } from "./chunk-MQ6CGZNJ.js";
4
+ } from "./chunk-AUNRHWH4.js";
5
5
  import {
6
6
  seedPayloadSchema
7
- } from "./chunk-PJWGTNOX.js";
7
+ } from "./chunk-7C3PFRBU.js";
8
8
 
9
9
  // ../../node_modules/hono/dist/utils/cookie.js
10
10
  var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
@@ -334,12 +334,15 @@ var createApiClient = ({
334
334
  return hc(baseUrl, {
335
335
  headers,
336
336
  init: { credentials },
337
- // Spread rather than named. Under `exactOptionalPropertyTypes` hc's
338
- // optional `fetch` does not accept an explicit `undefined`, so writing
339
- // `fetch,` here is a TS2379 whenever a caller omits one.
337
+ // `exactOptionalPropertyTypes` rejects an explicit undefined `fetch`.
340
338
  ...fetch2 && { fetch: fetch2 }
341
339
  });
342
340
  };
341
+ var WHOLE_SECONDS = /^[1-9]\d*$/;
342
+ var retryAfterSeconds = ({ headers }) => {
343
+ const stated = headers.get("retry-after");
344
+ return stated !== null && WHOLE_SECONDS.test(stated) ? Number(stated) : null;
345
+ };
343
346
 
344
347
  // src/cli/lib/seed/fetch-seed.ts
345
348
  var SEED_API_URL = process.env.AGENTS_INC_API_URL ?? "https://api.agentsinc.sh";
@@ -353,10 +356,8 @@ var EXPLANATION_BUDGET = 120;
353
356
  var QUOTABLE_TYPE = "text/plain";
354
357
  var NO_SUCH_CONFIG = 404;
355
358
  async function fetchSeedConfig(id) {
356
- let response;
357
- try {
358
- response = await store.configs[":id"].$get({ param: { id: encodeURIComponent(id) } });
359
- } catch {
359
+ const response = await requestFromStore(id);
360
+ if (response === null) {
360
361
  return { ok: false, error: `Could not reach ${SEED_API_URL} \u2014 check your connection.` };
361
362
  }
362
363
  if (response.status === NO_SUCH_CONFIG) {
@@ -365,10 +366,24 @@ async function fetchSeedConfig(id) {
365
366
  if (!response.ok) {
366
367
  return { ok: false, error: await refusalMessage(response) };
367
368
  }
368
- let body;
369
+ return payloadIn(await jsonBodyOrUndefined(response), id);
370
+ }
371
+ async function requestFromStore(id) {
369
372
  try {
370
- body = await response.json();
373
+ return await store.configs[":id"].$get({ param: { id: encodeURIComponent(id) } });
371
374
  } catch {
375
+ return null;
376
+ }
377
+ }
378
+ async function jsonBodyOrUndefined(response) {
379
+ try {
380
+ return await response.json();
381
+ } catch {
382
+ return void 0;
383
+ }
384
+ }
385
+ function payloadIn(body, id) {
386
+ if (body === void 0) {
372
387
  return { ok: false, error: "The configuration store returned something that is not JSON." };
373
388
  }
374
389
  const parsed = seedPayloadSchema.safeParse(body);
@@ -404,8 +419,11 @@ function explanationOf(body) {
404
419
  }
405
420
 
406
421
  export {
422
+ retryAfterSeconds,
407
423
  SEED_API_URL,
408
424
  SEED_USER_AGENT,
409
- fetchSeedConfig
425
+ fetchSeedConfig,
426
+ jsonBodyOrUndefined,
427
+ arrivedAsText
410
428
  };
411
- //# sourceMappingURL=chunk-OYJQUA3D.js.map
429
+ //# sourceMappingURL=chunk-YGDWHDOY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/hono/dist/utils/cookie.js","../../../node_modules/hono/dist/client/utils.js","../../../node_modules/hono/dist/client/client.js","../../api/src/client.ts","../src/cli/lib/seed/fetch-seed.ts"],"sourcesContent":["// src/utils/cookie.ts\nimport { decodeURIComponent_, tryDecode } from \"./url.js\";\nvar algorithm = { name: \"HMAC\", hash: \"SHA-256\" };\nvar getCryptoKey = async (secret) => {\n const secretBuf = typeof secret === \"string\" ? new TextEncoder().encode(secret) : secret;\n return await crypto.subtle.importKey(\"raw\", secretBuf, algorithm, false, [\"sign\", \"verify\"]);\n};\nvar makeSignature = async (value, secret) => {\n const key = await getCryptoKey(secret);\n const signature = await crypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value));\n return btoa(String.fromCharCode(...new Uint8Array(signature)));\n};\nvar verifySignature = async (base64Signature, value, secret) => {\n try {\n const signatureBinStr = atob(base64Signature);\n const signature = new Uint8Array(signatureBinStr.length);\n for (let i = 0, len = signatureBinStr.length; i < len; i++) {\n signature[i] = signatureBinStr.charCodeAt(i);\n }\n return await crypto.subtle.verify(algorithm, secret, signature, new TextEncoder().encode(value));\n } catch {\n return false;\n }\n};\nvar validCookieNameRegEx = /^[\\w!#$%&'*.^`|~+-]+$/;\nvar relaxedCookieNameRegEx = /^[!#-:<>-[\\]-~]+$/;\nvar validCookieValueRegEx = /^[ !#-:<-[\\]-~]*$/;\nvar trimCookieWhitespace = (value) => {\n let start = 0;\n let end = value.length;\n while (start < end) {\n const charCode = value.charCodeAt(start);\n if (charCode !== 32 && charCode !== 9) {\n break;\n }\n start++;\n }\n while (end > start) {\n const charCode = value.charCodeAt(end - 1);\n if (charCode !== 32 && charCode !== 9) {\n break;\n }\n end--;\n }\n return start === 0 && end === value.length ? value : value.slice(start, end);\n};\nvar parse = (cookie, name) => {\n if (name && cookie.indexOf(name) === -1) {\n return {};\n }\n const pairs = cookie.split(\";\");\n const parsedCookie = /* @__PURE__ */ Object.create(null);\n for (const pairStr of pairs) {\n const valueStartPos = pairStr.indexOf(\"=\");\n if (valueStartPos === -1) {\n continue;\n }\n const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos));\n if (name && name !== cookieName || !relaxedCookieNameRegEx.test(cookieName) || cookieName in parsedCookie) {\n continue;\n }\n let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1));\n if (cookieValue.startsWith('\"') && cookieValue.endsWith('\"')) {\n cookieValue = cookieValue.slice(1, -1);\n }\n if (validCookieValueRegEx.test(cookieValue)) {\n parsedCookie[cookieName] = cookieValue.indexOf(\"%\") !== -1 ? tryDecode(cookieValue, decodeURIComponent_) : cookieValue;\n if (name) {\n break;\n }\n }\n }\n return parsedCookie;\n};\nvar parseSigned = async (cookie, secret, name) => {\n const parsedCookie = /* @__PURE__ */ Object.create(null);\n const secretKey = await getCryptoKey(secret);\n for (const [key, value] of Object.entries(parse(cookie, name))) {\n const signatureStartPos = value.lastIndexOf(\".\");\n if (signatureStartPos < 1) {\n continue;\n }\n const signedValue = value.substring(0, signatureStartPos);\n const signature = value.substring(signatureStartPos + 1);\n if (signature.length !== 44 || !signature.endsWith(\"=\")) {\n continue;\n }\n const isVerified = await verifySignature(signature, signedValue, secretKey);\n parsedCookie[key] = isVerified ? signedValue : false;\n }\n return parsedCookie;\n};\nvar _serialize = (name, value, opt = {}) => {\n if (!validCookieNameRegEx.test(name)) {\n throw new Error(\"Invalid cookie name\");\n }\n let cookie = `${name}=${value}`;\n if (name.startsWith(\"__Secure-\") && !opt.secure) {\n throw new Error(\"__Secure- Cookie must have Secure attributes\");\n }\n if (name.startsWith(\"__Host-\")) {\n if (!opt.secure) {\n throw new Error(\"__Host- Cookie must have Secure attributes\");\n }\n if (opt.path !== \"/\") {\n throw new Error('__Host- Cookie must have Path attributes with \"/\"');\n }\n if (opt.domain) {\n throw new Error(\"__Host- Cookie must not have Domain attributes\");\n }\n }\n for (const key of [\"domain\", \"path\", \"sameSite\", \"priority\"]) {\n if (opt[key] && /[;\\r\\n]/.test(opt[key])) {\n throw new Error(`${key} must not contain \";\", \"\\\\r\", or \"\\\\n\"`);\n }\n }\n if (opt && typeof opt.maxAge === \"number\" && opt.maxAge >= 0) {\n if (opt.maxAge > 3456e4) {\n throw new Error(\n \"Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.\"\n );\n }\n cookie += `; Max-Age=${opt.maxAge | 0}`;\n }\n if (opt.domain && opt.prefix !== \"host\") {\n cookie += `; Domain=${opt.domain}`;\n }\n if (opt.path) {\n cookie += `; Path=${opt.path}`;\n }\n if (opt.expires) {\n if (opt.expires.getTime() - Date.now() > 3456e7) {\n throw new Error(\n \"Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.\"\n );\n }\n cookie += `; Expires=${opt.expires.toUTCString()}`;\n }\n if (opt.httpOnly) {\n cookie += \"; HttpOnly\";\n }\n if (opt.secure) {\n cookie += \"; Secure\";\n }\n if (opt.sameSite) {\n cookie += `; SameSite=${opt.sameSite.charAt(0).toUpperCase() + opt.sameSite.slice(1)}`;\n }\n if (opt.priority) {\n cookie += `; Priority=${opt.priority.charAt(0).toUpperCase() + opt.priority.slice(1)}`;\n }\n if (opt.partitioned) {\n if (!opt.secure) {\n throw new Error(\"Partitioned Cookie must have Secure attributes\");\n }\n cookie += \"; Partitioned\";\n }\n return cookie;\n};\nvar serialize = (name, value, opt) => {\n value = encodeURIComponent(value);\n return _serialize(name, value, opt);\n};\nvar serializeSigned = async (name, value, secret, opt = {}) => {\n const signature = await makeSignature(value, secret);\n value = `${value}.${signature}`;\n value = encodeURIComponent(value);\n return _serialize(name, value, opt);\n};\nexport {\n parse,\n parseSigned,\n serialize,\n serializeSigned\n};\n","// src/client/utils.ts\nimport { fetchRP, DetailedError } from \"./fetch-result-please.js\";\nvar mergePath = (base, path) => {\n base = base.replace(/\\/+$/, \"\");\n base = base + \"/\";\n path = path.replace(/^\\/+/, \"\");\n return base + path;\n};\nvar replaceUrlParam = (urlString, params) => {\n for (const [k, v] of Object.entries(params)) {\n const reg = new RegExp(\"/:\" + k + \"(?:{[^/]+})?\\\\??(?=/|$)\");\n urlString = urlString.replace(reg, v ? `/${v}` : \"\");\n }\n return urlString;\n};\nvar buildSearchParams = (query) => {\n const searchParams = new URLSearchParams();\n for (const [k, v] of Object.entries(query)) {\n if (v === void 0) {\n continue;\n }\n if (Array.isArray(v)) {\n for (const v2 of v) {\n searchParams.append(k, v2);\n }\n } else {\n searchParams.set(k, v);\n }\n }\n return searchParams;\n};\nvar replaceUrlProtocol = (urlString, protocol) => {\n switch (protocol) {\n case \"ws\":\n return urlString.replace(/^http/, \"ws\");\n case \"http\":\n return urlString.replace(/^ws/, \"http\");\n }\n};\nvar removeIndexString = (urlString) => {\n if (/^https?:\\/\\/[^\\/]+?\\/index(?=\\?|$)/.test(urlString)) {\n return urlString.replace(/\\/index(?=\\?|$)/, \"/\");\n }\n return urlString.replace(/\\/index(?=\\?|$)/, \"\");\n};\nfunction isObject(item) {\n return typeof item === \"object\" && item !== null && !Array.isArray(item);\n}\nfunction deepMerge(target, source) {\n if (!isObject(target) && !isObject(source)) {\n return source;\n }\n const merged = { ...target };\n for (const key in source) {\n const value = source[key];\n if (isObject(merged[key]) && isObject(value)) {\n merged[key] = deepMerge(merged[key], value);\n } else {\n merged[key] = value;\n }\n }\n return merged;\n}\nasync function parseResponse(fetchRes) {\n return fetchRP(fetchRes);\n}\nexport {\n DetailedError,\n buildSearchParams,\n deepMerge,\n mergePath,\n parseResponse,\n removeIndexString,\n replaceUrlParam,\n replaceUrlProtocol\n};\n","// src/client/client.ts\nimport { serialize } from \"../utils/cookie.js\";\nimport {\n buildSearchParams,\n deepMerge,\n mergePath,\n removeIndexString,\n replaceUrlParam,\n replaceUrlProtocol\n} from \"./utils.js\";\nvar createProxy = (callback, path) => {\n const proxy = new Proxy(() => {\n }, {\n get(_obj, key) {\n if (typeof key !== \"string\" || key === \"then\") {\n return void 0;\n }\n return createProxy(callback, [...path, key]);\n },\n apply(_1, _2, args) {\n return callback({\n path,\n args\n });\n }\n });\n return proxy;\n};\nvar ClientRequestImpl = class {\n url;\n method;\n buildSearchParams;\n queryParams = void 0;\n pathParams = {};\n rBody;\n cType = void 0;\n constructor(url, method, options) {\n this.url = url;\n this.method = method;\n this.buildSearchParams = options.buildSearchParams;\n }\n fetch = async (args, opt) => {\n if (args) {\n if (args.query) {\n this.queryParams = this.buildSearchParams(args.query);\n }\n if (args.form) {\n const form = new FormData();\n for (const [k, v] of Object.entries(args.form)) {\n if (v === void 0) {\n continue;\n }\n if (Array.isArray(v)) {\n for (const v2 of v) {\n form.append(k, v2);\n }\n } else {\n form.append(k, v);\n }\n }\n this.rBody = form;\n }\n if (args.json) {\n this.rBody = JSON.stringify(args.json);\n this.cType = \"application/json\";\n }\n if (args.param) {\n this.pathParams = args.param;\n }\n }\n let methodUpperCase = this.method.toUpperCase();\n const headerValues = {\n ...args?.header,\n ...typeof opt?.headers === \"function\" ? await opt.headers() : opt?.headers\n };\n if (args?.cookie) {\n const cookies = [];\n for (const [key, value] of Object.entries(args.cookie)) {\n cookies.push(serialize(key, value, { path: \"/\" }));\n }\n headerValues[\"Cookie\"] = cookies.join(\",\");\n }\n if (this.cType) {\n headerValues[\"Content-Type\"] = this.cType;\n }\n const headers = new Headers(headerValues ?? void 0);\n let url = this.url;\n url = removeIndexString(url);\n url = replaceUrlParam(url, this.pathParams);\n if (this.queryParams) {\n url = url + \"?\" + this.queryParams.toString();\n }\n methodUpperCase = this.method.toUpperCase();\n const setBody = !(methodUpperCase === \"GET\" || methodUpperCase === \"HEAD\");\n return (opt?.fetch || fetch)(url, {\n body: setBody ? this.rBody : void 0,\n method: methodUpperCase,\n headers,\n ...opt?.init\n });\n };\n};\nvar hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {\n const buildSearchParamsOption = options?.buildSearchParams ?? buildSearchParams;\n const parts = [...opts.path];\n const lastParts = parts.slice(-3).reverse();\n if (lastParts[0] === \"toString\") {\n if (lastParts[1] === \"name\") {\n return lastParts[2] || \"\";\n }\n return proxyCallback.toString();\n }\n if (lastParts[0] === \"valueOf\") {\n if (lastParts[1] === \"name\") {\n return lastParts[2] || \"\";\n }\n return proxyCallback;\n }\n let method = \"\";\n if (/^\\$/.test(lastParts[0])) {\n const last = parts.pop();\n if (last) {\n method = last.replace(/^\\$/, \"\");\n }\n }\n const path = parts.join(\"/\");\n const url = mergePath(baseUrl, path);\n if (method === \"url\" || method === \"path\") {\n let result = url;\n if (opts.args[0]) {\n if (opts.args[0].param) {\n result = replaceUrlParam(url, opts.args[0].param);\n }\n if (opts.args[0].query) {\n result = result + \"?\" + buildSearchParamsOption(opts.args[0].query).toString();\n }\n }\n result = removeIndexString(result);\n if (method === \"url\") {\n return new URL(result);\n }\n return result.slice(baseUrl.replace(/\\/+$/, \"\").length).replace(/^\\/?/, \"/\");\n }\n if (method === \"ws\") {\n const webSocketUrl = replaceUrlProtocol(\n opts.args[0] && opts.args[0].param ? replaceUrlParam(url, opts.args[0].param) : url,\n \"ws\"\n );\n const targetUrl = new URL(webSocketUrl);\n const queryParams = opts.args[0]?.query;\n if (queryParams) {\n Object.entries(queryParams).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((item) => targetUrl.searchParams.append(key, item));\n } else {\n targetUrl.searchParams.set(key, value);\n }\n });\n }\n const establishWebSocket = (...args) => {\n if (options?.webSocket !== void 0 && typeof options.webSocket === \"function\") {\n return options.webSocket(...args);\n }\n return new WebSocket(...args);\n };\n return establishWebSocket(targetUrl.toString());\n }\n const req = new ClientRequestImpl(url, method, {\n buildSearchParams: buildSearchParamsOption\n });\n if (method) {\n options ??= {};\n const reqOptions = { ...opts.args[1] };\n const baseHeaders = options.headers;\n const reqHeaders = reqOptions.headers;\n if (baseHeaders && reqHeaders) {\n reqOptions.headers = async () => ({\n ...typeof baseHeaders === \"function\" ? await baseHeaders() : baseHeaders,\n ...typeof reqHeaders === \"function\" ? await reqHeaders() : reqHeaders\n });\n }\n const args = deepMerge(options, reqOptions);\n return req.fetch(opts.args[0], args);\n }\n return req;\n}, []);\nexport {\n hc\n};\n","import { hc } from \"hono/client\"\n\nimport type { AppType } from \"server\"\n\n// `import type` keeps worker code out of both consumers' bundles.\n\n/** No `same-origin`: the session cookie is set by a different origin. */\nexport type ApiCredentials = \"include\" | \"omit\"\n\n/** `credentials` defaults to `\"include\"`; without the cookie requests are silently anonymous. */\nexport type ApiRequestPolicy = {\n headers?: Record<string, string>\n credentials?: ApiCredentials\n}\n\nexport type ApiClientOptions = ApiRequestPolicy & {\n /** No default: a wrong guess is a silent wrong API. */\n baseUrl: string\n /** Test seam; hc calls `(opt?.fetch || fetch)(url, ...)`. */\n fetch?: typeof globalThis.fetch\n}\n\ntype ResolvedPolicy = {\n headers: Record<string, string>\n credentials: ApiCredentials\n}\n\nconst resolvePolicy = ({\n headers = {},\n credentials = \"include\",\n}: ApiRequestPolicy): ResolvedPolicy => ({ headers, credentials })\n\n/**\n * The policy as a `RequestInit`, for paths `AppType` does not describe (Better Auth's routes).\n * Spread it last over a caller's init so the cookie cannot be dropped.\n */\nexport const apiRequestInit = (policy: ApiRequestPolicy): RequestInit =>\n resolvePolicy(policy)\n\n/**\n * hc spreads `init` last, so `headers` there would replace hc's JSON content type; headers go\n * through hc's merged `headers` option and `init` carries only `credentials`.\n */\nexport const createApiClient = ({\n baseUrl,\n fetch,\n ...policy\n}: ApiClientOptions) => {\n const { headers, credentials } = resolvePolicy(policy)\n\n return hc<AppType>(baseUrl, {\n headers,\n init: { credentials },\n // `exactOptionalPropertyTypes` rejects an explicit undefined `fetch`.\n ...(fetch && { fetch }),\n })\n}\n\nexport type ApiClient = ReturnType<typeof createApiClient>\n\nconst WHOLE_SECONDS = /^[1-9]\\d*$/\n\n/** Seconds from a 429's `retry-after`, or `null`; HTTP-date form is not read. */\nexport const retryAfterSeconds = ({ headers }: { headers: Headers }) => {\n const stated = headers.get(\"retry-after\")\n\n return stated !== null && WHOLE_SECONDS.test(stated) ? Number(stated) : null\n}\n","import { createApiClient } from \"@workspace/api\";\nimport { seedPayloadSchema, type SeedPayload } from \"@workspace/matrix/seed\";\n\nimport { truncateText } from \"../../utils/string.js\";\n\n/** Overridable so tests never touch the network. */\nexport const SEED_API_URL = process.env.AGENTS_INC_API_URL ?? \"https://api.agentsinc.sh\";\n\n/** Lets the worker tell an install from someone opening a share link. */\nexport const SEED_USER_AGENT = \"agents-inc-cli\";\n\n// `credentials: \"omit\"`: the shared default `include` is for the editor's cookie session.\nconst store = createApiClient({\n baseUrl: SEED_API_URL,\n headers: { accept: \"application/json\", \"user-agent\": SEED_USER_AGENT },\n credentials: \"omit\",\n});\n\n/** This route's refusals are one short line each; this holds the longest four times over. */\nconst EXPLANATION_BUDGET = 120;\n\nconst QUOTABLE_TYPE = \"text/plain\";\n\nconst NO_SUCH_CONFIG = 404;\n\nexport type FetchSeedResult = { ok: true; payload: SeedPayload } | { ok: false; error: string };\n\nexport async function fetchSeedConfig(id: string): Promise<FetchSeedResult> {\n const response = await requestFromStore(id);\n if (response === null) {\n return { ok: false, error: `Could not reach ${SEED_API_URL} — check your connection.` };\n }\n\n // Not quoted: the store's 404 text does not name the id the caller typed.\n if (response.status === NO_SUCH_CONFIG) {\n return { ok: false, error: `No configuration found for id '${id}'.` };\n }\n if (!response.ok) {\n return { ok: false, error: await refusalMessage(response) };\n }\n\n return payloadIn(await jsonBodyOrUndefined(response), id);\n}\n\n/** Null where the store could not be reached at all. */\nasync function requestFromStore(id: string): Promise<Response | null> {\n try {\n // hono substitutes path params verbatim, so a `/` or `?` in an id would address another route.\n return await store.configs[\":id\"].$get({ param: { id: encodeURIComponent(id) } });\n } catch {\n return null;\n }\n}\n\n/** Undefined where the body is not JSON, which no JSON document parses to. */\nexport async function jsonBodyOrUndefined(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch {\n return undefined;\n }\n}\n\nfunction payloadIn(body: unknown, id: string): FetchSeedResult {\n if (body === undefined) {\n return { ok: false, error: \"The configuration store returned something that is not JSON.\" };\n }\n\n const parsed = seedPayloadSchema.safeParse(body);\n if (!parsed.success) {\n // The store validated it on the way in, so the contract moved; the causes are indistinguishable\n // here and re-sharing fixes all of them.\n return {\n ok: false,\n error: `Configuration '${id}' is not in a format this version of the CLI can install. Shared ids are never migrated — re-share the configuration to mint a current one, or update the CLI if that id came from a newer version.`,\n };\n }\n\n return { ok: true, payload: parsed.data };\n}\n\n/** This route refuses with plain `c.text`, so unlike `publish-seed.ts` there is no envelope to parse. */\nasync function refusalMessage(response: Response): Promise<string> {\n const refused = `Fetching configuration failed (HTTP ${response.status}).`;\n const explanation = explanationOf(await refusalBody(response));\n\n return explanation === undefined ? refused : `${refused} The store said: ${explanation}`;\n}\n\n/** Never throws: draining can fail mid-body, and the status then stands alone. */\nasync function refusalBody(response: Response): Promise<string | undefined> {\n if (!arrivedAsText(response)) return undefined;\n\n try {\n return await response.text();\n } catch {\n return undefined;\n }\n}\n\n/** Anything not `text/plain` came from a proxy or gateway in the store's place, not the store. */\nexport function arrivedAsText(response: Response): boolean {\n return (response.headers.get(\"content-type\") ?? \"\").startsWith(QUOTABLE_TYPE);\n}\n\nfunction explanationOf(body: string | undefined): string | undefined {\n if (body === undefined) return undefined;\n\n const said = body.trim();\n if (said === \"\") return undefined;\n\n return truncateText(said, EXPLANATION_BUDGET);\n}\n"],"mappings":"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","names":["fetch"]}