@archmax-ai/harness 0.0.0

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 (351) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/dist/agent.d.ts +174 -0
  4. package/dist/agent.js +140 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/assembly/compose.d.ts +170 -0
  7. package/dist/assembly/compose.js +391 -0
  8. package/dist/assembly/compose.js.map +1 -0
  9. package/dist/assembly/delegation-registry.d.ts +5 -0
  10. package/dist/assembly/delegation-registry.js +118 -0
  11. package/dist/assembly/delegation-registry.js.map +1 -0
  12. package/dist/assembly/index.d.ts +192 -0
  13. package/dist/assembly/index.js +265 -0
  14. package/dist/assembly/index.js.map +1 -0
  15. package/dist/assembly/plain.d.ts +7 -0
  16. package/dist/assembly/plain.js +41 -0
  17. package/dist/assembly/plain.js.map +1 -0
  18. package/dist/authoring-skill/archmax-harness/README.md +76 -0
  19. package/dist/authoring-skill/archmax-harness/SKILL.md +241 -0
  20. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +626 -0
  21. package/dist/authoring-skill/archmax-harness/references/cases.md +41 -0
  22. package/dist/authoring-skill/archmax-harness/references/diagnostics.md +51 -0
  23. package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +1070 -0
  24. package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +82 -0
  25. package/dist/authoring-skill/archmax-harness/references/wiring.md +101 -0
  26. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +1631 -0
  27. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +241 -0
  28. package/dist/behaviour/support.d.ts +232 -0
  29. package/dist/behaviour/support.js +339 -0
  30. package/dist/behaviour/support.js.map +1 -0
  31. package/dist/cli/banner.d.ts +11 -0
  32. package/dist/cli/banner.js +29 -0
  33. package/dist/cli/banner.js.map +1 -0
  34. package/dist/cli/bootstrap.d.ts +33 -0
  35. package/dist/cli/bootstrap.js +153 -0
  36. package/dist/cli/bootstrap.js.map +1 -0
  37. package/dist/cli/command.d.ts +39 -0
  38. package/dist/cli/command.js +97 -0
  39. package/dist/cli/command.js.map +1 -0
  40. package/dist/cli/state-flow.d.ts +46 -0
  41. package/dist/cli/state-flow.js +268 -0
  42. package/dist/cli/state-flow.js.map +1 -0
  43. package/dist/cli/style.d.ts +41 -0
  44. package/dist/cli/style.js +64 -0
  45. package/dist/cli/style.js.map +1 -0
  46. package/dist/cli/turn.d.ts +41 -0
  47. package/dist/cli/turn.js +161 -0
  48. package/dist/cli/turn.js.map +1 -0
  49. package/dist/cli.d.ts +10 -0
  50. package/dist/cli.js +426 -0
  51. package/dist/cli.js.map +1 -0
  52. package/dist/core/code-description.d.ts +22 -0
  53. package/dist/core/code-description.js +38 -0
  54. package/dist/core/code-description.js.map +1 -0
  55. package/dist/core/deepagents.d.ts +183 -0
  56. package/dist/core/deepagents.js +128 -0
  57. package/dist/core/deepagents.js.map +1 -0
  58. package/dist/core/events.d.ts +350 -0
  59. package/dist/core/events.js +205 -0
  60. package/dist/core/events.js.map +1 -0
  61. package/dist/core/frontmatter.d.ts +15 -0
  62. package/dist/core/frontmatter.js +32 -0
  63. package/dist/core/frontmatter.js.map +1 -0
  64. package/dist/core/listing-redact.d.ts +37 -0
  65. package/dist/core/listing-redact.js +88 -0
  66. package/dist/core/listing-redact.js.map +1 -0
  67. package/dist/core/match.d.ts +26 -0
  68. package/dist/core/match.js +75 -0
  69. package/dist/core/match.js.map +1 -0
  70. package/dist/core/message-readers.d.ts +84 -0
  71. package/dist/core/message-readers.js +159 -0
  72. package/dist/core/message-readers.js.map +1 -0
  73. package/dist/core/messages.d.ts +49 -0
  74. package/dist/core/messages.js +85 -0
  75. package/dist/core/messages.js.map +1 -0
  76. package/dist/core/mount-prompt.d.ts +28 -0
  77. package/dist/core/mount-prompt.js +55 -0
  78. package/dist/core/mount-prompt.js.map +1 -0
  79. package/dist/core/mount-redact.d.ts +28 -0
  80. package/dist/core/mount-redact.js +32 -0
  81. package/dist/core/mount-redact.js.map +1 -0
  82. package/dist/core/mounts.d.ts +88 -0
  83. package/dist/core/mounts.js +147 -0
  84. package/dist/core/mounts.js.map +1 -0
  85. package/dist/core/path-mapping.d.ts +52 -0
  86. package/dist/core/path-mapping.js +113 -0
  87. package/dist/core/path-mapping.js.map +1 -0
  88. package/dist/core/platform-prompt.generated.d.ts +2 -0
  89. package/dist/core/platform-prompt.generated.js +4 -0
  90. package/dist/core/platform-prompt.generated.js.map +1 -0
  91. package/dist/core/prompt.d.ts +42 -0
  92. package/dist/core/prompt.js +75 -0
  93. package/dist/core/prompt.js.map +1 -0
  94. package/dist/core/session-id.d.ts +38 -0
  95. package/dist/core/session-id.js +61 -0
  96. package/dist/core/session-id.js.map +1 -0
  97. package/dist/core/session-store.d.ts +85 -0
  98. package/dist/core/session-store.js +149 -0
  99. package/dist/core/session-store.js.map +1 -0
  100. package/dist/core/session-zone.d.ts +54 -0
  101. package/dist/core/session-zone.js +82 -0
  102. package/dist/core/session-zone.js.map +1 -0
  103. package/dist/core/skill-prompt.d.ts +31 -0
  104. package/dist/core/skill-prompt.js +54 -0
  105. package/dist/core/skill-prompt.js.map +1 -0
  106. package/dist/core/skill-redact.d.ts +15 -0
  107. package/dist/core/skill-redact.js +27 -0
  108. package/dist/core/skill-redact.js.map +1 -0
  109. package/dist/core/skills.d.ts +172 -0
  110. package/dist/core/skills.js +214 -0
  111. package/dist/core/skills.js.map +1 -0
  112. package/dist/core/tool-mocks.d.ts +23 -0
  113. package/dist/core/tool-mocks.js +39 -0
  114. package/dist/core/tool-mocks.js.map +1 -0
  115. package/dist/core/tool-telemetry.d.ts +16 -0
  116. package/dist/core/tool-telemetry.js +40 -0
  117. package/dist/core/tool-telemetry.js.map +1 -0
  118. package/dist/core/usage.d.ts +114 -0
  119. package/dist/core/usage.js +226 -0
  120. package/dist/core/usage.js.map +1 -0
  121. package/dist/core/workspace-context.d.ts +136 -0
  122. package/dist/core/workspace-context.js +178 -0
  123. package/dist/core/workspace-context.js.map +1 -0
  124. package/dist/core/workspace-prompt.d.ts +7 -0
  125. package/dist/core/workspace-prompt.js +102 -0
  126. package/dist/core/workspace-prompt.js.map +1 -0
  127. package/dist/core/workspace-router.d.ts +61 -0
  128. package/dist/core/workspace-router.js +145 -0
  129. package/dist/core/workspace-router.js.map +1 -0
  130. package/dist/core/workspace.d.ts +85 -0
  131. package/dist/core/workspace.js +193 -0
  132. package/dist/core/workspace.js.map +1 -0
  133. package/dist/core/zones.d.ts +181 -0
  134. package/dist/core/zones.js +202 -0
  135. package/dist/core/zones.js.map +1 -0
  136. package/dist/env.d.ts +99 -0
  137. package/dist/env.js +271 -0
  138. package/dist/env.js.map +1 -0
  139. package/dist/index.d.ts +265 -0
  140. package/dist/index.js +197 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/kernel/kernel.d.ts +192 -0
  143. package/dist/kernel/kernel.js +751 -0
  144. package/dist/kernel/kernel.js.map +1 -0
  145. package/dist/lifecycle/hook-shape.d.ts +44 -0
  146. package/dist/lifecycle/hook-shape.js +66 -0
  147. package/dist/lifecycle/hook-shape.js.map +1 -0
  148. package/dist/lifecycle/runner.d.ts +177 -0
  149. package/dist/lifecycle/runner.js +372 -0
  150. package/dist/lifecycle/runner.js.map +1 -0
  151. package/dist/lifecycle/transcript.d.ts +27 -0
  152. package/dist/lifecycle/transcript.js +43 -0
  153. package/dist/lifecycle/transcript.js.map +1 -0
  154. package/dist/machine/allow.d.ts +65 -0
  155. package/dist/machine/allow.js +107 -0
  156. package/dist/machine/allow.js.map +1 -0
  157. package/dist/machine/delegation.d.ts +9 -0
  158. package/dist/machine/delegation.js +10 -0
  159. package/dist/machine/delegation.js.map +1 -0
  160. package/dist/machine/diagnostic.d.ts +14 -0
  161. package/dist/machine/diagnostic.js +2 -0
  162. package/dist/machine/diagnostic.js.map +1 -0
  163. package/dist/machine/lint-spec.d.ts +4 -0
  164. package/dist/machine/lint-spec.js +266 -0
  165. package/dist/machine/lint-spec.js.map +1 -0
  166. package/dist/machine/load-spec.d.ts +90 -0
  167. package/dist/machine/load-spec.js +120 -0
  168. package/dist/machine/load-spec.js.map +1 -0
  169. package/dist/machine/machine.d.ts +273 -0
  170. package/dist/machine/machine.js +551 -0
  171. package/dist/machine/machine.js.map +1 -0
  172. package/dist/machine/mount-grants.d.ts +25 -0
  173. package/dist/machine/mount-grants.js +24 -0
  174. package/dist/machine/mount-grants.js.map +1 -0
  175. package/dist/machine/slug.d.ts +14 -0
  176. package/dist/machine/slug.js +17 -0
  177. package/dist/machine/slug.js.map +1 -0
  178. package/dist/machine/spec-schema.d.ts +662 -0
  179. package/dist/machine/spec-schema.js +717 -0
  180. package/dist/machine/spec-schema.js.map +1 -0
  181. package/dist/machine/tool-names.d.ts +98 -0
  182. package/dist/machine/tool-names.js +144 -0
  183. package/dist/machine/tool-names.js.map +1 -0
  184. package/dist/machine/triggers.d.ts +114 -0
  185. package/dist/machine/triggers.js +165 -0
  186. package/dist/machine/triggers.js.map +1 -0
  187. package/dist/machine/types.d.ts +186 -0
  188. package/dist/machine/types.js +12 -0
  189. package/dist/machine/types.js.map +1 -0
  190. package/dist/machine/validate-spec.d.ts +42 -0
  191. package/dist/machine/validate-spec.js +29 -0
  192. package/dist/machine/validate-spec.js.map +1 -0
  193. package/dist/machine/variables.d.ts +196 -0
  194. package/dist/machine/variables.js +415 -0
  195. package/dist/machine/variables.js.map +1 -0
  196. package/dist/public/cli.d.ts +15 -0
  197. package/dist/public/cli.js +14 -0
  198. package/dist/public/cli.js.map +1 -0
  199. package/dist/public/messages.d.ts +33 -0
  200. package/dist/public/messages.js +33 -0
  201. package/dist/public/messages.js.map +1 -0
  202. package/dist/public/sandbox.d.ts +99 -0
  203. package/dist/public/sandbox.js +32 -0
  204. package/dist/public/sandbox.js.map +1 -0
  205. package/dist/public/spec.d.ts +147 -0
  206. package/dist/public/spec.js +149 -0
  207. package/dist/public/spec.js.map +1 -0
  208. package/dist/public/testing.d.ts +71 -0
  209. package/dist/public/testing.js +39 -0
  210. package/dist/public/testing.js.map +1 -0
  211. package/dist/rubrics/rubrics.d.ts +135 -0
  212. package/dist/rubrics/rubrics.js +145 -0
  213. package/dist/rubrics/rubrics.js.map +1 -0
  214. package/dist/runtime/contract.d.ts +73 -0
  215. package/dist/runtime/contract.js +96 -0
  216. package/dist/runtime/contract.js.map +1 -0
  217. package/dist/sandbox/assets/parts/core.js +22 -0
  218. package/dist/sandbox/assets/parts/lifecycle-hook.js +47 -0
  219. package/dist/sandbox/bridge.d.ts +16 -0
  220. package/dist/sandbox/bridge.js +95 -0
  221. package/dist/sandbox/bridge.js.map +1 -0
  222. package/dist/sandbox/executor.d.ts +46 -0
  223. package/dist/sandbox/executor.js +119 -0
  224. package/dist/sandbox/executor.js.map +1 -0
  225. package/dist/sandbox/imports.d.ts +33 -0
  226. package/dist/sandbox/imports.js +67 -0
  227. package/dist/sandbox/imports.js.map +1 -0
  228. package/dist/sandbox/prelude.d.ts +12 -0
  229. package/dist/sandbox/prelude.js +51 -0
  230. package/dist/sandbox/prelude.js.map +1 -0
  231. package/dist/sandbox/ptc-gateway.d.ts +104 -0
  232. package/dist/sandbox/ptc-gateway.js +167 -0
  233. package/dist/sandbox/ptc-gateway.js.map +1 -0
  234. package/dist/sandbox/runtime.d.ts +59 -0
  235. package/dist/sandbox/runtime.js +51 -0
  236. package/dist/sandbox/runtime.js.map +1 -0
  237. package/dist/sandbox/tools.d.ts +34 -0
  238. package/dist/sandbox/tools.js +147 -0
  239. package/dist/sandbox/tools.js.map +1 -0
  240. package/dist/sessions/operations.d.ts +79 -0
  241. package/dist/sessions/operations.js +121 -0
  242. package/dist/sessions/operations.js.map +1 -0
  243. package/dist/sessions/resolve.d.ts +97 -0
  244. package/dist/sessions/resolve.js +145 -0
  245. package/dist/sessions/resolve.js.map +1 -0
  246. package/dist/sessions/resume.d.ts +242 -0
  247. package/dist/sessions/resume.js +288 -0
  248. package/dist/sessions/resume.js.map +1 -0
  249. package/dist/sessions/scope.d.ts +99 -0
  250. package/dist/sessions/scope.js +145 -0
  251. package/dist/sessions/scope.js.map +1 -0
  252. package/dist/sessions/summary.d.ts +65 -0
  253. package/dist/sessions/summary.js +56 -0
  254. package/dist/sessions/summary.js.map +1 -0
  255. package/dist/testing/assertions.d.ts +30 -0
  256. package/dist/testing/assertions.js +231 -0
  257. package/dist/testing/assertions.js.map +1 -0
  258. package/dist/testing/case-document.d.ts +141 -0
  259. package/dist/testing/case-document.js +51 -0
  260. package/dist/testing/case-document.js.map +1 -0
  261. package/dist/testing/case-schema.d.ts +29 -0
  262. package/dist/testing/case-schema.js +519 -0
  263. package/dist/testing/case-schema.js.map +1 -0
  264. package/dist/testing/discovery.d.ts +10 -0
  265. package/dist/testing/discovery.js +24 -0
  266. package/dist/testing/discovery.js.map +1 -0
  267. package/dist/testing/driver.d.ts +78 -0
  268. package/dist/testing/driver.js +117 -0
  269. package/dist/testing/driver.js.map +1 -0
  270. package/dist/testing/grade.d.ts +116 -0
  271. package/dist/testing/grade.js +261 -0
  272. package/dist/testing/grade.js.map +1 -0
  273. package/dist/testing/interpreter.d.ts +55 -0
  274. package/dist/testing/interpreter.js +103 -0
  275. package/dist/testing/interpreter.js.map +1 -0
  276. package/dist/testing/mock-middleware.d.ts +5 -0
  277. package/dist/testing/mock-middleware.js +33 -0
  278. package/dist/testing/mock-middleware.js.map +1 -0
  279. package/dist/testing/runner.d.ts +205 -0
  280. package/dist/testing/runner.js +266 -0
  281. package/dist/testing/runner.js.map +1 -0
  282. package/dist/testing/target.d.ts +27 -0
  283. package/dist/testing/target.js +21 -0
  284. package/dist/testing/target.js.map +1 -0
  285. package/dist/validate/validate.d.ts +41 -0
  286. package/dist/validate/validate.js +669 -0
  287. package/dist/validate/validate.js.map +1 -0
  288. package/dist/workflow/agent-tools.d.ts +10 -0
  289. package/dist/workflow/agent-tools.js +10 -0
  290. package/dist/workflow/agent-tools.js.map +1 -0
  291. package/dist/workflow/checkpointer.d.ts +52 -0
  292. package/dist/workflow/checkpointer.js +200 -0
  293. package/dist/workflow/checkpointer.js.map +1 -0
  294. package/dist/workflow/control-tools.d.ts +174 -0
  295. package/dist/workflow/control-tools.js +468 -0
  296. package/dist/workflow/control-tools.js.map +1 -0
  297. package/dist/workflow/governance.d.ts +104 -0
  298. package/dist/workflow/governance.js +546 -0
  299. package/dist/workflow/governance.js.map +1 -0
  300. package/dist/workflow/middleware.d.ts +85 -0
  301. package/dist/workflow/middleware.js +283 -0
  302. package/dist/workflow/middleware.js.map +1 -0
  303. package/dist/workflow/on-error.d.ts +25 -0
  304. package/dist/workflow/on-error.js +58 -0
  305. package/dist/workflow/on-error.js.map +1 -0
  306. package/dist/workflow/parks.d.ts +46 -0
  307. package/dist/workflow/parks.js +513 -0
  308. package/dist/workflow/parks.js.map +1 -0
  309. package/dist/workflow/paths.d.ts +67 -0
  310. package/dist/workflow/paths.js +108 -0
  311. package/dist/workflow/paths.js.map +1 -0
  312. package/dist/workflow/prompt-cache.d.ts +70 -0
  313. package/dist/workflow/prompt-cache.js +103 -0
  314. package/dist/workflow/prompt-cache.js.map +1 -0
  315. package/dist/workflow/prompt-pruning.d.ts +20 -0
  316. package/dist/workflow/prompt-pruning.js +83 -0
  317. package/dist/workflow/prompt-pruning.js.map +1 -0
  318. package/dist/workflow/render-prompt.d.ts +45 -0
  319. package/dist/workflow/render-prompt.js +140 -0
  320. package/dist/workflow/render-prompt.js.map +1 -0
  321. package/dist/workflow/runtime-config.d.ts +7 -0
  322. package/dist/workflow/runtime-config.js +9 -0
  323. package/dist/workflow/runtime-config.js.map +1 -0
  324. package/dist/workflow/session-artifacts.d.ts +90 -0
  325. package/dist/workflow/session-artifacts.js +134 -0
  326. package/dist/workflow/session-artifacts.js.map +1 -0
  327. package/dist/workflow/session-view.d.ts +31 -0
  328. package/dist/workflow/session-view.js +94 -0
  329. package/dist/workflow/session-view.js.map +1 -0
  330. package/dist/workflow/snapshot.d.ts +14 -0
  331. package/dist/workflow/snapshot.js +97 -0
  332. package/dist/workflow/snapshot.js.map +1 -0
  333. package/dist/workflow/state.d.ts +347 -0
  334. package/dist/workflow/state.js +322 -0
  335. package/dist/workflow/state.js.map +1 -0
  336. package/dist/workflow/sub-workflow.d.ts +174 -0
  337. package/dist/workflow/sub-workflow.js +392 -0
  338. package/dist/workflow/sub-workflow.js.map +1 -0
  339. package/dist/workflow/tool-service.d.ts +48 -0
  340. package/dist/workflow/tool-service.js +291 -0
  341. package/dist/workflow/tool-service.js.map +1 -0
  342. package/dist/workflow/turn-boundary.d.ts +39 -0
  343. package/dist/workflow/turn-boundary.js +128 -0
  344. package/dist/workflow/turn-boundary.js.map +1 -0
  345. package/dist/workflow/turn-runner.d.ts +40 -0
  346. package/dist/workflow/turn-runner.js +122 -0
  347. package/dist/workflow/turn-runner.js.map +1 -0
  348. package/dist/workflow/workflow-tools.d.ts +46 -0
  349. package/dist/workflow/workflow-tools.js +90 -0
  350. package/dist/workflow/workflow-tools.js.map +1 -0
  351. package/package.json +119 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The model-facing account of the skills a state may use — rendered by the
3
+ * runtime rather than delegated to the upstream skills middleware.
4
+ *
5
+ * Upstream renders one section, once, from a whole source directory: its
6
+ * `sources` are fixed at construction and its result is cached in a closure, so
7
+ * nothing about it can vary per state. Under a governed workflow that is exactly
8
+ * the wrong shape — a state that may use one capability would be told about
9
+ * three, two of which the kernel refuses. So the runtime renders this instead,
10
+ * from the same resolved set the kernel enforces, into the **volatile** system
11
+ * block (see `workflow/middleware.ts`), which is where anything that changes
12
+ * with the state belongs.
13
+ *
14
+ * What it says is the Agent Skills progressive-disclosure contract itself and
15
+ * nothing more: the slug, what the skill is for, and where to read the rest.
16
+ */
17
+ /** Heading of the rendered section, also the marker tests assert on. */
18
+ export const SKILLS_SECTION_HEADING = "Skills available in this state";
19
+ /**
20
+ * Render the section for one state's enabled skills, or `null` when the set is
21
+ * empty — a state that may use no skill gets no heading rather than an empty
22
+ * one, and therefore no invitation to go looking.
23
+ *
24
+ * `enabled` is the resolved slug order (see `WorkflowMachine.enabledSkills`), so
25
+ * the text is byte-identical on every model call of a turn and on every
26
+ * re-entry: a prompt section that reordered itself would churn the transcript
27
+ * for no reason. A slug with no registry entry is skipped rather than rendered
28
+ * as a bare name — the description is the whole value of disclosing it.
29
+ */
30
+ export function renderSkillsSection(enabled, registry) {
31
+ const skills = enabled
32
+ .map((slug) => registry.get(slug))
33
+ .filter((skill) => skill !== undefined);
34
+ if (skills.length === 0)
35
+ return null;
36
+ const bullets = skills.map((skill) => `- **\`${skill.slug}\`** — ${oneLine(skill.description)} Read \`${skill.skillFile}\` first.`);
37
+ return [
38
+ `## ${SKILLS_SECTION_HEADING}`,
39
+ "",
40
+ ...bullets,
41
+ "",
42
+ `Only these skills are reachable from this state: every other skill's files are blocked here, ` +
43
+ `whatever an earlier state could read.`,
44
+ ].join("\n");
45
+ }
46
+ /**
47
+ * Collapse a description to one line and end it with a sentence terminator, so a
48
+ * multi-line `description:` cannot break the bullet list it is rendered into.
49
+ */
50
+ function oneLine(description) {
51
+ const text = description.replace(/\s+/g, " ").trim();
52
+ return /[.!?]$/.test(text) ? text : `${text}.`;
53
+ }
54
+ //# sourceMappingURL=skill-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-prompt.js","sourceRoot":"","sources":["../../src/core/skill-prompt.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAEvE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAA0B,EAC1B,QAAuB;IAEvB,MAAM,MAAM,GAAG,OAAO;SACnB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;SACjC,MAAM,CAAC,CAAC,KAAK,EAA4B,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACpE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CACxB,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,KAAK,CAAC,IAAI,UAAU,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,KAAK,CAAC,SAAS,WAAW,CACxG,CAAC;IACF,OAAO;QACL,MAAM,sBAAsB,EAAE;QAC9B,EAAE;QACF,GAAG,OAAO;QACV,EAAE;QACF,+FAA+F;YAC7F,uCAAuC;KAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,WAAmB;IAClC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;AACjD,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type SkillPrefixes } from "./skills.js";
2
+ /**
3
+ * Keep a disabled skill out of a *listing*, not just out of a read — the skills
4
+ * half of the shared listing filter (`core/listing-redact.ts`, which carries the
5
+ * reasoning and the line shapes).
6
+ */
7
+ /**
8
+ * Drop from `text` every line about a skill bundle absent from `enabled`.
9
+ *
10
+ * Returns the text unchanged when nothing was hidden — including the whole
11
+ * no-skills and no-hidden-bundle cases — so a result the filter has no opinion
12
+ * about is passed through by identity rather than rebuilt.
13
+ */
14
+ export declare function redactDisabledSkills(text: string, enabled: readonly string[], skills: SkillPrefixes): string;
15
+ export { REDACTED_TOOLS } from "./listing-redact.js";
@@ -0,0 +1,27 @@
1
+ import { redactListing } from "./listing-redact.js";
2
+ import { skillOfPath } from "./skills.js";
3
+ /**
4
+ * Keep a disabled skill out of a *listing*, not just out of a read — the skills
5
+ * half of the shared listing filter (`core/listing-redact.ts`, which carries the
6
+ * reasoning and the line shapes).
7
+ */
8
+ /**
9
+ * Drop from `text` every line about a skill bundle absent from `enabled`.
10
+ *
11
+ * Returns the text unchanged when nothing was hidden — including the whole
12
+ * no-skills and no-hidden-bundle cases — so a result the filter has no opinion
13
+ * about is passed through by identity rather than rebuilt.
14
+ */
15
+ export function redactDisabledSkills(text, enabled, skills) {
16
+ if (skills.length === 0 || !text)
17
+ return text;
18
+ const allowed = new Set(enabled);
19
+ // Nothing to hide: every discovered bundle is enabled here.
20
+ if (skills.every((skill) => allowed.has(skill.slug)))
21
+ return text;
22
+ return redactListing(text, (path) => skillOfPath(path, skills), (slug) => !allowed.has(slug));
23
+ }
24
+ // The filtered tools are a property of the listing shapes, not of skills;
25
+ // re-exported here so existing callers reach it from either module.
26
+ export { REDACTED_TOOLS } from "./listing-redact.js";
27
+ //# sourceMappingURL=skill-redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-redact.js","sourceRoot":"","sources":["../../src/core/skill-redact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAE9D;;;;GAIG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,OAA0B,EAC1B,MAAqB;IAErB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,4DAA4D;IAC5D,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,OAAO,aAAa,CAClB,IAAI,EACJ,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,EACnC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAC7B,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,oEAAoE;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,172 @@
1
+ import { type WorkflowEventHandler } from "./events.js";
2
+ import { Workspace } from "./workspace.js";
3
+ /**
4
+ * The skill registry: what skills a workspace provides, resolved **once per
5
+ * assembly** from the declared skill sources and read through the backend like
6
+ * every other authored input.
7
+ *
8
+ * It exists because three components have to agree about the same three facts —
9
+ * which slugs exist, where each bundle lives, and what to say about it:
10
+ *
11
+ * - **disclosure** names the active state's skills in the prompt,
12
+ * - the **decision kernel** refuses a path inside a bundle the state does not
13
+ * enable,
14
+ * - **`archmax validate`** reports a `skills.allow` entry no bundle provides.
15
+ *
16
+ * Deriving all three from one resolved table is the same move the mount table
17
+ * makes (`core/mounts.ts` → {@link MountPrefixes}): a prompt cannot advertise a
18
+ * skill the kernel would refuse, and the validator cannot accept a slug the
19
+ * runtime would not find, because there is only one answer to look up.
20
+ *
21
+ * The framework therefore never names `skills/`. The **sources** are an
22
+ * assembly input, and what governance consumes is this table.
23
+ */
24
+ /** A discovered skill: its slug, what it is for, and where its bundle lives. */
25
+ export interface SkillDefinition {
26
+ /**
27
+ * The bundle's directory name — the token authors govern by, and the only one
28
+ * `skills.allow` accepts. Kept even when the bundle's `SKILL.md` `name:`
29
+ * disagrees: the path is what governance decides against, so the directory
30
+ * has the final say and the mismatch is reported instead of resolved.
31
+ */
32
+ slug: string;
33
+ /** The `description:` frontmatter field, as disclosed to the model. */
34
+ description: string;
35
+ /**
36
+ * Canonical, workspace-relative bundle path with no trailing slash
37
+ * (`skills/order-data`) — the prefix a governed path is matched against.
38
+ */
39
+ prefix: string;
40
+ /** Path of the bundle's `SKILL.md`, as the agent addresses it. */
41
+ skillFile: string;
42
+ }
43
+ /** Discovered skills by slug, in discovery order. */
44
+ export type SkillRegistry = ReadonlyMap<string, SkillDefinition>;
45
+ /**
46
+ * One skill's identity for path classification: the pair the kernel and the
47
+ * validator need, and nothing else. Prompt-facing fields are deliberately
48
+ * absent — a governance decision must not be able to depend on a description.
49
+ */
50
+ export interface SkillLocation {
51
+ readonly slug: string;
52
+ /** Canonical bundle prefix, no trailing slash. */
53
+ readonly prefix: string;
54
+ }
55
+ /**
56
+ * The resolved skill table governance classifies against — the {@link
57
+ * MountPrefixes} of skills. Ordered longest-prefix-first so a nested bundle
58
+ * (were a source ever to serve one) resolves to the innermost skill.
59
+ */
60
+ export type SkillPrefixes = readonly SkillLocation[];
61
+ /** No skills: no path lands inside a bundle, so the skill rule never fires. */
62
+ export declare const NO_SKILLS: SkillPrefixes;
63
+ /**
64
+ * The conventional skill source, matching the `skills/` key in
65
+ * {@link defaultMounts}. A **default value only**: it is the runtime option's
66
+ * default, never a name any governance module refers to.
67
+ */
68
+ export declare const DEFAULT_SKILL_SOURCES: readonly string[];
69
+ /** The Agent Skills bundle manifest, at the root of a skill directory. */
70
+ export declare const SKILL_FILE = "SKILL.md";
71
+ /** Structural inspection of a `SKILL.md`, for the loader and the validator. */
72
+ export interface SkillInspection {
73
+ /** The parsed definition, or null when a fatal problem was found. */
74
+ definition: Omit<SkillDefinition, "prefix" | "skillFile"> | null;
75
+ /** Problems that make the bundle unloadable — the runtime skips it. */
76
+ errors: string[];
77
+ /** Non-fatal advisories (e.g. `name:`/directory mismatch). */
78
+ warnings: string[];
79
+ }
80
+ /**
81
+ * Inspect a `SKILL.md` (YAML frontmatter + markdown body) without emitting
82
+ * events, so the runtime loader and the static validator agree about what is
83
+ * unloadable. `expectedDir` is the containing directory name — the slug.
84
+ *
85
+ * Deep Agents' own `parseSkillMetadata` is not reused: it takes a filesystem
86
+ * path and reads it with `fs`, while every authored input here arrives through
87
+ * the backend. What is shared instead are its Agent Skills limits
88
+ * (`MAX_SKILL_NAME_LENGTH`, `MAX_SKILL_DESCRIPTION_LENGTH`), so a bundle this
89
+ * loader accepts is one upstream's skills middleware would accept too.
90
+ *
91
+ * A `name:` that disagrees with the directory is a **warning, not an error**:
92
+ * the bundle still governs correctly (its path is unambiguous), and refusing to
93
+ * load it would take a capability away over a label. `validate` reports the same
94
+ * mismatch as an error, where an author is asking to be told.
95
+ */
96
+ export declare function inspectSkillMarkdown(raw: string, expectedDir: string): SkillInspection;
97
+ /**
98
+ * One problem found while discovering skills. Carries the severity a **static**
99
+ * check should report, which is not always the severity the runtime acts on: a
100
+ * bundle whose `name:` disagrees with its directory still loads and governs
101
+ * correctly (the path is unambiguous), so the runtime warns and keeps the
102
+ * capability — while `validate`, asked precisely to find that, errors.
103
+ *
104
+ * Structured rather than pre-formatted so the validator classifies by `kind`
105
+ * instead of matching on message text, and both paths report the same sentence.
106
+ */
107
+ export interface SkillIssue {
108
+ kind: "unloadable" | "name-mismatch" | "non-slug-dir" | "shadowed";
109
+ /** Severity for a static check; the runtime treats every issue as a warning. */
110
+ severity: "error" | "warning";
111
+ /** The bundle directory name the issue is about. */
112
+ slug: string;
113
+ message: string;
114
+ }
115
+ /**
116
+ * Read the skills served by `sources`, in order, through the workspace backend —
117
+ * never `fs`, and never upstream's filesystem-only `listSkills`, so a store or
118
+ * sandbox backend serves skills exactly as it serves everything else.
119
+ *
120
+ * Each source is accepted in either Agent Skills form, distinguished the way
121
+ * upstream distinguishes them — by whether the directory itself holds a
122
+ * `SKILL.md`:
123
+ *
124
+ * - a **parent directory** (`skills/`), whose every child bundle is loaded;
125
+ * - a **direct bundle** (`skills/order-data/`), loaded as one skill.
126
+ *
127
+ * A later source providing an already-discovered slug **shadows** it (upstream's
128
+ * documented last-one-wins precedence), reported as an issue: silently serving
129
+ * one of two bundles under one governed name is exactly the ambiguity a governed
130
+ * runtime should not keep to itself. A source that serves nothing is not a
131
+ * problem — it is a workspace without that kind of capability.
132
+ *
133
+ * The one discovery path, shared by the runtime ({@link discoverSkills}) and
134
+ * `archmax validate`, so the two cannot disagree about which skills exist.
135
+ */
136
+ export declare function inspectSkillSources(workspace: Workspace, sources?: readonly string[]): Promise<{
137
+ registry: SkillRegistry;
138
+ issues: SkillIssue[];
139
+ }>;
140
+ /**
141
+ * The runtime's discovery: {@link inspectSkillSources}, with every issue emitted
142
+ * as a warning on the event stream. Nothing here fails an assembly — a workspace
143
+ * with one malformed bundle still runs, with that capability missing and said so.
144
+ */
145
+ export declare function discoverSkills(workspace: Workspace, sources?: readonly string[], onEvent?: WorkflowEventHandler): Promise<SkillRegistry>;
146
+ /**
147
+ * Reduce a registry to the table governance classifies against, ordered so the
148
+ * longest prefix matches first.
149
+ */
150
+ export declare function skillPrefixes(registry: SkillRegistry): SkillPrefixes;
151
+ /**
152
+ * The slug of the skill bundle a path lands inside, or null when it lands in
153
+ * none — a path elsewhere in the workspace, *or* a path under a skill source
154
+ * that belongs to no bundle (a stray file beside the bundles). The latter is
155
+ * deliberately not this rule's business: it governs bundles, and the zone rules
156
+ * already govern the authored directory holding them.
157
+ *
158
+ * Canonicalizes first, so `./skills//order-data/x`, `skills/order-data/./x`, and
159
+ * `skills/other/../order-data/x` are all the one path the backend would resolve.
160
+ * A path that escapes the workspace root belongs to no bundle (and is refused
161
+ * elsewhere on its own terms).
162
+ */
163
+ export declare function skillOfPath(path: string, skills?: SkillPrefixes): string | null;
164
+ /**
165
+ * Whether a glob or path pattern can only ever match inside one skill bundle —
166
+ * the shape `validate` needs to spot a `tools.allow` entry that contradicts the
167
+ * state's enabled set. Returns the slug when the pattern's literal prefix
168
+ * (everything before its first wildcard) is already inside a bundle, else null:
169
+ * a broader pattern (`skills/**`) matches several bundles and is left to the
170
+ * runtime rule, which refuses the disabled ones call by call.
171
+ */
172
+ export declare function skillOfPattern(pattern: string, skills?: SkillPrefixes): string | null;
@@ -0,0 +1,214 @@
1
+ import { MAX_SKILL_DESCRIPTION_LENGTH, MAX_SKILL_NAME_LENGTH } from "deepagents";
2
+ import { createWorkflowEventEmitter, } from "./events.js";
3
+ import { parseFrontmatter } from "./frontmatter.js";
4
+ import { canonicalizeRelPath, dirName, normalizeRelPath } from "./workspace.js";
5
+ import { isSlug } from "../machine/slug.js";
6
+ /** No skills: no path lands inside a bundle, so the skill rule never fires. */
7
+ export const NO_SKILLS = [];
8
+ /**
9
+ * The conventional skill source, matching the `skills/` key in
10
+ * {@link defaultMounts}. A **default value only**: it is the runtime option's
11
+ * default, never a name any governance module refers to.
12
+ */
13
+ export const DEFAULT_SKILL_SOURCES = ["skills/"];
14
+ /** The Agent Skills bundle manifest, at the root of a skill directory. */
15
+ export const SKILL_FILE = "SKILL.md";
16
+ /**
17
+ * Inspect a `SKILL.md` (YAML frontmatter + markdown body) without emitting
18
+ * events, so the runtime loader and the static validator agree about what is
19
+ * unloadable. `expectedDir` is the containing directory name — the slug.
20
+ *
21
+ * Deep Agents' own `parseSkillMetadata` is not reused: it takes a filesystem
22
+ * path and reads it with `fs`, while every authored input here arrives through
23
+ * the backend. What is shared instead are its Agent Skills limits
24
+ * (`MAX_SKILL_NAME_LENGTH`, `MAX_SKILL_DESCRIPTION_LENGTH`), so a bundle this
25
+ * loader accepts is one upstream's skills middleware would accept too.
26
+ *
27
+ * A `name:` that disagrees with the directory is a **warning, not an error**:
28
+ * the bundle still governs correctly (its path is unambiguous), and refusing to
29
+ * load it would take a capability away over a label. `validate` reports the same
30
+ * mismatch as an error, where an author is asking to be told.
31
+ */
32
+ export function inspectSkillMarkdown(raw, expectedDir) {
33
+ const errors = [];
34
+ const warnings = [];
35
+ const fail = (message) => {
36
+ errors.push(message);
37
+ return { definition: null, errors, warnings };
38
+ };
39
+ if (raw.trim() === "")
40
+ return fail("file is empty");
41
+ const parsed = parseFrontmatter(raw);
42
+ if (!parsed)
43
+ return fail("no valid YAML frontmatter found");
44
+ if (!parsed.data || typeof parsed.data !== "object")
45
+ return fail("invalid YAML frontmatter");
46
+ const meta = parsed.data;
47
+ const description = meta.description;
48
+ if (description === undefined || description === null || String(description).trim() === "") {
49
+ return fail("missing required 'description'");
50
+ }
51
+ if (String(description).length > MAX_SKILL_DESCRIPTION_LENGTH) {
52
+ return fail(`'description' exceeds ${MAX_SKILL_DESCRIPTION_LENGTH} characters (Agent Skills limit)`);
53
+ }
54
+ if (meta.name !== undefined && String(meta.name).length > MAX_SKILL_NAME_LENGTH) {
55
+ return fail(`'name' exceeds ${MAX_SKILL_NAME_LENGTH} characters (Agent Skills limit)`);
56
+ }
57
+ if (meta.name !== undefined && String(meta.name) !== expectedDir) {
58
+ warnings.push(`Skill '${String(meta.name)}' should match directory name '${expectedDir}' — ` +
59
+ `'${expectedDir}' is the slug governance uses`);
60
+ }
61
+ if (!isSlug(expectedDir)) {
62
+ warnings.push(`Skill directory '${expectedDir}' is not a kebab-case slug, so no 'skills.allow' entry can name it`);
63
+ }
64
+ return {
65
+ definition: { slug: expectedDir, description: String(description).trim() },
66
+ errors,
67
+ warnings,
68
+ };
69
+ }
70
+ /** A source path, canonicalized: no leading slash, no trailing slash. */
71
+ function normalizeSource(source) {
72
+ return canonicalizeRelPath(source).path;
73
+ }
74
+ /**
75
+ * Read the skills served by `sources`, in order, through the workspace backend —
76
+ * never `fs`, and never upstream's filesystem-only `listSkills`, so a store or
77
+ * sandbox backend serves skills exactly as it serves everything else.
78
+ *
79
+ * Each source is accepted in either Agent Skills form, distinguished the way
80
+ * upstream distinguishes them — by whether the directory itself holds a
81
+ * `SKILL.md`:
82
+ *
83
+ * - a **parent directory** (`skills/`), whose every child bundle is loaded;
84
+ * - a **direct bundle** (`skills/order-data/`), loaded as one skill.
85
+ *
86
+ * A later source providing an already-discovered slug **shadows** it (upstream's
87
+ * documented last-one-wins precedence), reported as an issue: silently serving
88
+ * one of two bundles under one governed name is exactly the ambiguity a governed
89
+ * runtime should not keep to itself. A source that serves nothing is not a
90
+ * problem — it is a workspace without that kind of capability.
91
+ *
92
+ * The one discovery path, shared by the runtime ({@link discoverSkills}) and
93
+ * `archmax validate`, so the two cannot disagree about which skills exist.
94
+ */
95
+ export async function inspectSkillSources(workspace, sources = DEFAULT_SKILL_SOURCES) {
96
+ const registry = new Map();
97
+ const issues = [];
98
+ const load = async (prefix) => {
99
+ const slug = dirName(prefix);
100
+ if (!slug)
101
+ return;
102
+ const skillFile = `${prefix}/${SKILL_FILE}`;
103
+ const raw = await workspace.readText(skillFile);
104
+ if (raw == null)
105
+ return;
106
+ const { definition, errors, warnings } = inspectSkillMarkdown(raw, slug);
107
+ for (const message of errors) {
108
+ issues.push({
109
+ kind: "unloadable",
110
+ severity: "warning",
111
+ slug,
112
+ message: `Skipping skill '${slug}' at ${prefix}: ${message}`,
113
+ });
114
+ }
115
+ for (const message of warnings) {
116
+ issues.push({
117
+ kind: message.includes("kebab-case") ? "non-slug-dir" : "name-mismatch",
118
+ severity: "error",
119
+ slug,
120
+ message,
121
+ });
122
+ }
123
+ if (!definition)
124
+ return;
125
+ const shadowed = registry.get(slug);
126
+ if (shadowed && shadowed.prefix !== prefix) {
127
+ issues.push({
128
+ kind: "shadowed",
129
+ severity: "warning",
130
+ slug,
131
+ message: `Skill '${slug}' at ${prefix} shadows the one at ${shadowed.prefix}`,
132
+ });
133
+ }
134
+ registry.set(slug, { ...definition, prefix, skillFile });
135
+ };
136
+ for (const source of sources) {
137
+ const root = normalizeSource(source);
138
+ if (!root)
139
+ continue;
140
+ if (await workspace.exists(`${root}/${SKILL_FILE}`)) {
141
+ await load(root);
142
+ continue;
143
+ }
144
+ for (const entry of await workspace.listDir(root)) {
145
+ if (entry.is_dir === false)
146
+ continue;
147
+ const name = dirName(entry.path);
148
+ if (!name)
149
+ continue;
150
+ await load(`${root}/${name}`);
151
+ }
152
+ }
153
+ return { registry, issues };
154
+ }
155
+ /**
156
+ * The runtime's discovery: {@link inspectSkillSources}, with every issue emitted
157
+ * as a warning on the event stream. Nothing here fails an assembly — a workspace
158
+ * with one malformed bundle still runs, with that capability missing and said so.
159
+ */
160
+ export async function discoverSkills(workspace, sources = DEFAULT_SKILL_SOURCES, onEvent) {
161
+ const emit = createWorkflowEventEmitter(onEvent);
162
+ const { registry, issues } = await inspectSkillSources(workspace, sources);
163
+ for (const issue of issues) {
164
+ emit({ type: "warning", scope: "skills", message: issue.message });
165
+ }
166
+ return registry;
167
+ }
168
+ /**
169
+ * Reduce a registry to the table governance classifies against, ordered so the
170
+ * longest prefix matches first.
171
+ */
172
+ export function skillPrefixes(registry) {
173
+ return [...registry.values()]
174
+ .map(({ slug, prefix }) => ({ slug, prefix }))
175
+ .sort((a, b) => b.prefix.length - a.prefix.length || a.slug.localeCompare(b.slug));
176
+ }
177
+ /**
178
+ * The slug of the skill bundle a path lands inside, or null when it lands in
179
+ * none — a path elsewhere in the workspace, *or* a path under a skill source
180
+ * that belongs to no bundle (a stray file beside the bundles). The latter is
181
+ * deliberately not this rule's business: it governs bundles, and the zone rules
182
+ * already govern the authored directory holding them.
183
+ *
184
+ * Canonicalizes first, so `./skills//order-data/x`, `skills/order-data/./x`, and
185
+ * `skills/other/../order-data/x` are all the one path the backend would resolve.
186
+ * A path that escapes the workspace root belongs to no bundle (and is refused
187
+ * elsewhere on its own terms).
188
+ */
189
+ export function skillOfPath(path, skills = NO_SKILLS) {
190
+ if (skills.length === 0)
191
+ return null;
192
+ const { path: rel, escapes } = canonicalizeRelPath(path);
193
+ if (escapes || rel === "")
194
+ return null;
195
+ for (const { slug, prefix } of skills) {
196
+ if (rel === prefix || rel.startsWith(`${prefix}/`))
197
+ return slug;
198
+ }
199
+ return null;
200
+ }
201
+ /**
202
+ * Whether a glob or path pattern can only ever match inside one skill bundle —
203
+ * the shape `validate` needs to spot a `tools.allow` entry that contradicts the
204
+ * state's enabled set. Returns the slug when the pattern's literal prefix
205
+ * (everything before its first wildcard) is already inside a bundle, else null:
206
+ * a broader pattern (`skills/**`) matches several bundles and is left to the
207
+ * runtime rule, which refuses the disabled ones call by call.
208
+ */
209
+ export function skillOfPattern(pattern, skills = NO_SKILLS) {
210
+ const literal = normalizeRelPath(pattern).split(/[*?[{]/, 1)[0] ?? "";
211
+ const upToSegment = literal.slice(0, literal.lastIndexOf("/") + 1);
212
+ return skillOfPath(upToSegment, skills);
213
+ }
214
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface ToolMockSpec {
2
+ name: string;
3
+ whenInput?: Record<string, unknown>;
4
+ result: unknown;
5
+ }
6
+ /**
7
+ * The middleware name `createToolMockMiddleware()` registers under. Assembly
8
+ * detects the middleware by this name to stamp `capabilities.toolMocks` on the
9
+ * runtime it returns — which is what lets the case engine refuse a
10
+ * mock-declaring case against a target whose agent-initiated calls would not be
11
+ * intercepted.
12
+ */
13
+ export declare const TOOL_MOCK_MIDDLEWARE_NAME = "ToolMockMiddleware";
14
+ /** The mocks declared for this run, or none. */
15
+ export declare function readMocks(configurable: Record<string, unknown> | undefined): ToolMockSpec[];
16
+ /**
17
+ * The first mock matching this call by name and (optionally) a partial input
18
+ * match, or `undefined` when none does. Declaration order decides, so a test
19
+ * can shadow a broad mock with a narrower one declared earlier.
20
+ */
21
+ export declare function findMock(mocks: ToolMockSpec[], toolName: string, args: Record<string, unknown>): ToolMockSpec | undefined;
22
+ /** A mock's result as the string payload a tool call settles with. */
23
+ export declare function mockPayload(mock: ToolMockSpec): string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Declarative tool-mock matching, shared by the two places a mocked call can be
3
+ * intercepted: the tool-call middleware (agent-initiated calls) and the PTC
4
+ * gateway (calls scripts make through `tools.*`). Both read the same
5
+ * `__toolMocks` entry off the run's `configurable`, so a `mocks:` entry
6
+ * declared by a case means one thing whoever makes the call.
7
+ *
8
+ * Runtime-owned (not `testing/`) precisely because runtime code consumes it:
9
+ * the PTC gateway is runtime, and runtime never imports from testing modules.
10
+ * Input matching is the shared `partialMatch` — the same vocabulary a case's
11
+ * `calledTool.input` uses, so declaring a mock and asserting a call read alike.
12
+ */
13
+ import { partialMatch } from "./match.js";
14
+ /**
15
+ * The middleware name `createToolMockMiddleware()` registers under. Assembly
16
+ * detects the middleware by this name to stamp `capabilities.toolMocks` on the
17
+ * runtime it returns — which is what lets the case engine refuse a
18
+ * mock-declaring case against a target whose agent-initiated calls would not be
19
+ * intercepted.
20
+ */
21
+ export const TOOL_MOCK_MIDDLEWARE_NAME = "ToolMockMiddleware";
22
+ /** The mocks declared for this run, or none. */
23
+ export function readMocks(configurable) {
24
+ const raw = configurable?.__toolMocks;
25
+ return Array.isArray(raw) ? raw : [];
26
+ }
27
+ /**
28
+ * The first mock matching this call by name and (optionally) a partial input
29
+ * match, or `undefined` when none does. Declaration order decides, so a test
30
+ * can shadow a broad mock with a narrower one declared earlier.
31
+ */
32
+ export function findMock(mocks, toolName, args) {
33
+ return mocks.find((mock) => mock.name === toolName && (!mock.whenInput || partialMatch(mock.whenInput, args)));
34
+ }
35
+ /** A mock's result as the string payload a tool call settles with. */
36
+ export function mockPayload(mock) {
37
+ return typeof mock.result === "string" ? mock.result : JSON.stringify(mock.result ?? null);
38
+ }
39
+ //# sourceMappingURL=tool-mocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-mocks.js","sourceRoot":"","sources":["../../src/core/tool-mocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ1C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,oBAAoB,CAAC;AAE9D,gDAAgD;AAChD,MAAM,UAAU,SAAS,CAAC,YAAiD;IACzE,MAAM,GAAG,GAAG,YAAY,EAAE,WAAW,CAAC;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,GAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAqB,EACrB,QAAgB,EAChB,IAA6B;IAE7B,OAAO,KAAK,CAAC,IAAI,CACf,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAC5F,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;AAC7F,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared shaping for tool-call telemetry, so the two places that emit it — the
3
+ * tool-call middleware (agent-initiated calls) and the PTC gateway (calls
4
+ * scripts make through `tools.*`) — produce identically shaped events. A
5
+ * consumer must not be able to tell which path a `tool-result` came from except
6
+ * by its `origin`.
7
+ */
8
+ /** Size cap for the `tool-result` output preview; full outputs stay in messages. */
9
+ export declare const TOOL_OUTPUT_PREVIEW_CAP = 4096;
10
+ /** Flatten a tool call's settled value to a capped text preview. */
11
+ export declare function toolOutputPreview(value: unknown): {
12
+ output: string;
13
+ truncated: boolean;
14
+ };
15
+ /** A concise, single-value hint for a tool call (e.g. its `file_path`), for the CLI. */
16
+ export declare function toolCallDetail(args: Record<string, unknown>): string | undefined;
@@ -0,0 +1,40 @@
1
+ import { ToolMessage } from "@langchain/core/messages";
2
+ /**
3
+ * Shared shaping for tool-call telemetry, so the two places that emit it — the
4
+ * tool-call middleware (agent-initiated calls) and the PTC gateway (calls
5
+ * scripts make through `tools.*`) — produce identically shaped events. A
6
+ * consumer must not be able to tell which path a `tool-result` came from except
7
+ * by its `origin`.
8
+ */
9
+ /** Size cap for the `tool-result` output preview; full outputs stay in messages. */
10
+ export const TOOL_OUTPUT_PREVIEW_CAP = 4096;
11
+ /** Flatten a tool call's settled value to a capped text preview. */
12
+ export function toolOutputPreview(value) {
13
+ let text;
14
+ if (value instanceof ToolMessage) {
15
+ text = typeof value.content === "string" ? value.content : JSON.stringify(value.content) ?? "";
16
+ }
17
+ else if (typeof value === "string") {
18
+ text = value;
19
+ }
20
+ else {
21
+ try {
22
+ text = JSON.stringify(value) ?? String(value);
23
+ }
24
+ catch {
25
+ text = String(value);
26
+ }
27
+ }
28
+ const truncated = text.length > TOOL_OUTPUT_PREVIEW_CAP;
29
+ return { output: truncated ? text.slice(0, TOOL_OUTPUT_PREVIEW_CAP) : text, truncated };
30
+ }
31
+ /** A concise, single-value hint for a tool call (e.g. its `file_path`), for the CLI. */
32
+ export function toolCallDetail(args) {
33
+ for (const key of ["file_path", "path", "to", "pattern", "command", "url"]) {
34
+ const value = args[key];
35
+ if (typeof value === "string" && value.trim())
36
+ return value;
37
+ }
38
+ return undefined;
39
+ }
40
+ //# sourceMappingURL=tool-telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-telemetry.js","sourceRoot":"","sources":["../../src/core/tool-telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;;GAMG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C,oEAAoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,IAAY,CAAC;IACjB,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,IAAI,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACjG,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,IAAI,GAAG,KAAK,CAAC;IACf,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,uBAAuB,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;AAC1F,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,cAAc,CAAC,IAA6B;IAC1D,KAAK,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;YAAE,OAAO,KAAK,CAAC;IAC9D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}