@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.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/agent.d.ts +174 -0
- package/dist/agent.js +140 -0
- package/dist/agent.js.map +1 -0
- package/dist/assembly/compose.d.ts +170 -0
- package/dist/assembly/compose.js +391 -0
- package/dist/assembly/compose.js.map +1 -0
- package/dist/assembly/delegation-registry.d.ts +5 -0
- package/dist/assembly/delegation-registry.js +118 -0
- package/dist/assembly/delegation-registry.js.map +1 -0
- package/dist/assembly/index.d.ts +192 -0
- package/dist/assembly/index.js +265 -0
- package/dist/assembly/index.js.map +1 -0
- package/dist/assembly/plain.d.ts +7 -0
- package/dist/assembly/plain.js +41 -0
- package/dist/assembly/plain.js.map +1 -0
- package/dist/authoring-skill/archmax-harness/README.md +76 -0
- package/dist/authoring-skill/archmax-harness/SKILL.md +241 -0
- package/dist/authoring-skill/archmax-harness/references/backend-integration.md +626 -0
- package/dist/authoring-skill/archmax-harness/references/cases.md +41 -0
- package/dist/authoring-skill/archmax-harness/references/diagnostics.md +51 -0
- package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +1070 -0
- package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +82 -0
- package/dist/authoring-skill/archmax-harness/references/wiring.md +101 -0
- package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +1631 -0
- package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +241 -0
- package/dist/behaviour/support.d.ts +232 -0
- package/dist/behaviour/support.js +339 -0
- package/dist/behaviour/support.js.map +1 -0
- package/dist/cli/banner.d.ts +11 -0
- package/dist/cli/banner.js +29 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +33 -0
- package/dist/cli/bootstrap.js +153 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/command.d.ts +39 -0
- package/dist/cli/command.js +97 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/state-flow.d.ts +46 -0
- package/dist/cli/state-flow.js +268 -0
- package/dist/cli/state-flow.js.map +1 -0
- package/dist/cli/style.d.ts +41 -0
- package/dist/cli/style.js +64 -0
- package/dist/cli/style.js.map +1 -0
- package/dist/cli/turn.d.ts +41 -0
- package/dist/cli/turn.js +161 -0
- package/dist/cli/turn.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +426 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/code-description.d.ts +22 -0
- package/dist/core/code-description.js +38 -0
- package/dist/core/code-description.js.map +1 -0
- package/dist/core/deepagents.d.ts +183 -0
- package/dist/core/deepagents.js +128 -0
- package/dist/core/deepagents.js.map +1 -0
- package/dist/core/events.d.ts +350 -0
- package/dist/core/events.js +205 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/frontmatter.d.ts +15 -0
- package/dist/core/frontmatter.js +32 -0
- package/dist/core/frontmatter.js.map +1 -0
- package/dist/core/listing-redact.d.ts +37 -0
- package/dist/core/listing-redact.js +88 -0
- package/dist/core/listing-redact.js.map +1 -0
- package/dist/core/match.d.ts +26 -0
- package/dist/core/match.js +75 -0
- package/dist/core/match.js.map +1 -0
- package/dist/core/message-readers.d.ts +84 -0
- package/dist/core/message-readers.js +159 -0
- package/dist/core/message-readers.js.map +1 -0
- package/dist/core/messages.d.ts +49 -0
- package/dist/core/messages.js +85 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/mount-prompt.d.ts +28 -0
- package/dist/core/mount-prompt.js +55 -0
- package/dist/core/mount-prompt.js.map +1 -0
- package/dist/core/mount-redact.d.ts +28 -0
- package/dist/core/mount-redact.js +32 -0
- package/dist/core/mount-redact.js.map +1 -0
- package/dist/core/mounts.d.ts +88 -0
- package/dist/core/mounts.js +147 -0
- package/dist/core/mounts.js.map +1 -0
- package/dist/core/path-mapping.d.ts +52 -0
- package/dist/core/path-mapping.js +113 -0
- package/dist/core/path-mapping.js.map +1 -0
- package/dist/core/platform-prompt.generated.d.ts +2 -0
- package/dist/core/platform-prompt.generated.js +4 -0
- package/dist/core/platform-prompt.generated.js.map +1 -0
- package/dist/core/prompt.d.ts +42 -0
- package/dist/core/prompt.js +75 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/session-id.d.ts +38 -0
- package/dist/core/session-id.js +61 -0
- package/dist/core/session-id.js.map +1 -0
- package/dist/core/session-store.d.ts +85 -0
- package/dist/core/session-store.js +149 -0
- package/dist/core/session-store.js.map +1 -0
- package/dist/core/session-zone.d.ts +54 -0
- package/dist/core/session-zone.js +82 -0
- package/dist/core/session-zone.js.map +1 -0
- package/dist/core/skill-prompt.d.ts +31 -0
- package/dist/core/skill-prompt.js +54 -0
- package/dist/core/skill-prompt.js.map +1 -0
- package/dist/core/skill-redact.d.ts +15 -0
- package/dist/core/skill-redact.js +27 -0
- package/dist/core/skill-redact.js.map +1 -0
- package/dist/core/skills.d.ts +172 -0
- package/dist/core/skills.js +214 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/tool-mocks.d.ts +23 -0
- package/dist/core/tool-mocks.js +39 -0
- package/dist/core/tool-mocks.js.map +1 -0
- package/dist/core/tool-telemetry.d.ts +16 -0
- package/dist/core/tool-telemetry.js +40 -0
- package/dist/core/tool-telemetry.js.map +1 -0
- package/dist/core/usage.d.ts +114 -0
- package/dist/core/usage.js +226 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/core/workspace-context.d.ts +136 -0
- package/dist/core/workspace-context.js +178 -0
- package/dist/core/workspace-context.js.map +1 -0
- package/dist/core/workspace-prompt.d.ts +7 -0
- package/dist/core/workspace-prompt.js +102 -0
- package/dist/core/workspace-prompt.js.map +1 -0
- package/dist/core/workspace-router.d.ts +61 -0
- package/dist/core/workspace-router.js +145 -0
- package/dist/core/workspace-router.js.map +1 -0
- package/dist/core/workspace.d.ts +85 -0
- package/dist/core/workspace.js +193 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/core/zones.d.ts +181 -0
- package/dist/core/zones.js +202 -0
- package/dist/core/zones.js.map +1 -0
- package/dist/env.d.ts +99 -0
- package/dist/env.js +271 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +265 -0
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/kernel.d.ts +192 -0
- package/dist/kernel/kernel.js +751 -0
- package/dist/kernel/kernel.js.map +1 -0
- package/dist/lifecycle/hook-shape.d.ts +44 -0
- package/dist/lifecycle/hook-shape.js +66 -0
- package/dist/lifecycle/hook-shape.js.map +1 -0
- package/dist/lifecycle/runner.d.ts +177 -0
- package/dist/lifecycle/runner.js +372 -0
- package/dist/lifecycle/runner.js.map +1 -0
- package/dist/lifecycle/transcript.d.ts +27 -0
- package/dist/lifecycle/transcript.js +43 -0
- package/dist/lifecycle/transcript.js.map +1 -0
- package/dist/machine/allow.d.ts +65 -0
- package/dist/machine/allow.js +107 -0
- package/dist/machine/allow.js.map +1 -0
- package/dist/machine/delegation.d.ts +9 -0
- package/dist/machine/delegation.js +10 -0
- package/dist/machine/delegation.js.map +1 -0
- package/dist/machine/diagnostic.d.ts +14 -0
- package/dist/machine/diagnostic.js +2 -0
- package/dist/machine/diagnostic.js.map +1 -0
- package/dist/machine/lint-spec.d.ts +4 -0
- package/dist/machine/lint-spec.js +266 -0
- package/dist/machine/lint-spec.js.map +1 -0
- package/dist/machine/load-spec.d.ts +90 -0
- package/dist/machine/load-spec.js +120 -0
- package/dist/machine/load-spec.js.map +1 -0
- package/dist/machine/machine.d.ts +273 -0
- package/dist/machine/machine.js +551 -0
- package/dist/machine/machine.js.map +1 -0
- package/dist/machine/mount-grants.d.ts +25 -0
- package/dist/machine/mount-grants.js +24 -0
- package/dist/machine/mount-grants.js.map +1 -0
- package/dist/machine/slug.d.ts +14 -0
- package/dist/machine/slug.js +17 -0
- package/dist/machine/slug.js.map +1 -0
- package/dist/machine/spec-schema.d.ts +662 -0
- package/dist/machine/spec-schema.js +717 -0
- package/dist/machine/spec-schema.js.map +1 -0
- package/dist/machine/tool-names.d.ts +98 -0
- package/dist/machine/tool-names.js +144 -0
- package/dist/machine/tool-names.js.map +1 -0
- package/dist/machine/triggers.d.ts +114 -0
- package/dist/machine/triggers.js +165 -0
- package/dist/machine/triggers.js.map +1 -0
- package/dist/machine/types.d.ts +186 -0
- package/dist/machine/types.js +12 -0
- package/dist/machine/types.js.map +1 -0
- package/dist/machine/validate-spec.d.ts +42 -0
- package/dist/machine/validate-spec.js +29 -0
- package/dist/machine/validate-spec.js.map +1 -0
- package/dist/machine/variables.d.ts +196 -0
- package/dist/machine/variables.js +415 -0
- package/dist/machine/variables.js.map +1 -0
- package/dist/public/cli.d.ts +15 -0
- package/dist/public/cli.js +14 -0
- package/dist/public/cli.js.map +1 -0
- package/dist/public/messages.d.ts +33 -0
- package/dist/public/messages.js +33 -0
- package/dist/public/messages.js.map +1 -0
- package/dist/public/sandbox.d.ts +99 -0
- package/dist/public/sandbox.js +32 -0
- package/dist/public/sandbox.js.map +1 -0
- package/dist/public/spec.d.ts +147 -0
- package/dist/public/spec.js +149 -0
- package/dist/public/spec.js.map +1 -0
- package/dist/public/testing.d.ts +71 -0
- package/dist/public/testing.js +39 -0
- package/dist/public/testing.js.map +1 -0
- package/dist/rubrics/rubrics.d.ts +135 -0
- package/dist/rubrics/rubrics.js +145 -0
- package/dist/rubrics/rubrics.js.map +1 -0
- package/dist/runtime/contract.d.ts +73 -0
- package/dist/runtime/contract.js +96 -0
- package/dist/runtime/contract.js.map +1 -0
- package/dist/sandbox/assets/parts/core.js +22 -0
- package/dist/sandbox/assets/parts/lifecycle-hook.js +47 -0
- package/dist/sandbox/bridge.d.ts +16 -0
- package/dist/sandbox/bridge.js +95 -0
- package/dist/sandbox/bridge.js.map +1 -0
- package/dist/sandbox/executor.d.ts +46 -0
- package/dist/sandbox/executor.js +119 -0
- package/dist/sandbox/executor.js.map +1 -0
- package/dist/sandbox/imports.d.ts +33 -0
- package/dist/sandbox/imports.js +67 -0
- package/dist/sandbox/imports.js.map +1 -0
- package/dist/sandbox/prelude.d.ts +12 -0
- package/dist/sandbox/prelude.js +51 -0
- package/dist/sandbox/prelude.js.map +1 -0
- package/dist/sandbox/ptc-gateway.d.ts +104 -0
- package/dist/sandbox/ptc-gateway.js +167 -0
- package/dist/sandbox/ptc-gateway.js.map +1 -0
- package/dist/sandbox/runtime.d.ts +59 -0
- package/dist/sandbox/runtime.js +51 -0
- package/dist/sandbox/runtime.js.map +1 -0
- package/dist/sandbox/tools.d.ts +34 -0
- package/dist/sandbox/tools.js +147 -0
- package/dist/sandbox/tools.js.map +1 -0
- package/dist/sessions/operations.d.ts +79 -0
- package/dist/sessions/operations.js +121 -0
- package/dist/sessions/operations.js.map +1 -0
- package/dist/sessions/resolve.d.ts +97 -0
- package/dist/sessions/resolve.js +145 -0
- package/dist/sessions/resolve.js.map +1 -0
- package/dist/sessions/resume.d.ts +242 -0
- package/dist/sessions/resume.js +288 -0
- package/dist/sessions/resume.js.map +1 -0
- package/dist/sessions/scope.d.ts +99 -0
- package/dist/sessions/scope.js +145 -0
- package/dist/sessions/scope.js.map +1 -0
- package/dist/sessions/summary.d.ts +65 -0
- package/dist/sessions/summary.js +56 -0
- package/dist/sessions/summary.js.map +1 -0
- package/dist/testing/assertions.d.ts +30 -0
- package/dist/testing/assertions.js +231 -0
- package/dist/testing/assertions.js.map +1 -0
- package/dist/testing/case-document.d.ts +141 -0
- package/dist/testing/case-document.js +51 -0
- package/dist/testing/case-document.js.map +1 -0
- package/dist/testing/case-schema.d.ts +29 -0
- package/dist/testing/case-schema.js +519 -0
- package/dist/testing/case-schema.js.map +1 -0
- package/dist/testing/discovery.d.ts +10 -0
- package/dist/testing/discovery.js +24 -0
- package/dist/testing/discovery.js.map +1 -0
- package/dist/testing/driver.d.ts +78 -0
- package/dist/testing/driver.js +117 -0
- package/dist/testing/driver.js.map +1 -0
- package/dist/testing/grade.d.ts +116 -0
- package/dist/testing/grade.js +261 -0
- package/dist/testing/grade.js.map +1 -0
- package/dist/testing/interpreter.d.ts +55 -0
- package/dist/testing/interpreter.js +103 -0
- package/dist/testing/interpreter.js.map +1 -0
- package/dist/testing/mock-middleware.d.ts +5 -0
- package/dist/testing/mock-middleware.js +33 -0
- package/dist/testing/mock-middleware.js.map +1 -0
- package/dist/testing/runner.d.ts +205 -0
- package/dist/testing/runner.js +266 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/target.d.ts +27 -0
- package/dist/testing/target.js +21 -0
- package/dist/testing/target.js.map +1 -0
- package/dist/validate/validate.d.ts +41 -0
- package/dist/validate/validate.js +669 -0
- package/dist/validate/validate.js.map +1 -0
- package/dist/workflow/agent-tools.d.ts +10 -0
- package/dist/workflow/agent-tools.js +10 -0
- package/dist/workflow/agent-tools.js.map +1 -0
- package/dist/workflow/checkpointer.d.ts +52 -0
- package/dist/workflow/checkpointer.js +200 -0
- package/dist/workflow/checkpointer.js.map +1 -0
- package/dist/workflow/control-tools.d.ts +174 -0
- package/dist/workflow/control-tools.js +468 -0
- package/dist/workflow/control-tools.js.map +1 -0
- package/dist/workflow/governance.d.ts +104 -0
- package/dist/workflow/governance.js +546 -0
- package/dist/workflow/governance.js.map +1 -0
- package/dist/workflow/middleware.d.ts +85 -0
- package/dist/workflow/middleware.js +283 -0
- package/dist/workflow/middleware.js.map +1 -0
- package/dist/workflow/on-error.d.ts +25 -0
- package/dist/workflow/on-error.js +58 -0
- package/dist/workflow/on-error.js.map +1 -0
- package/dist/workflow/parks.d.ts +46 -0
- package/dist/workflow/parks.js +513 -0
- package/dist/workflow/parks.js.map +1 -0
- package/dist/workflow/paths.d.ts +67 -0
- package/dist/workflow/paths.js +108 -0
- package/dist/workflow/paths.js.map +1 -0
- package/dist/workflow/prompt-cache.d.ts +70 -0
- package/dist/workflow/prompt-cache.js +103 -0
- package/dist/workflow/prompt-cache.js.map +1 -0
- package/dist/workflow/prompt-pruning.d.ts +20 -0
- package/dist/workflow/prompt-pruning.js +83 -0
- package/dist/workflow/prompt-pruning.js.map +1 -0
- package/dist/workflow/render-prompt.d.ts +45 -0
- package/dist/workflow/render-prompt.js +140 -0
- package/dist/workflow/render-prompt.js.map +1 -0
- package/dist/workflow/runtime-config.d.ts +7 -0
- package/dist/workflow/runtime-config.js +9 -0
- package/dist/workflow/runtime-config.js.map +1 -0
- package/dist/workflow/session-artifacts.d.ts +90 -0
- package/dist/workflow/session-artifacts.js +134 -0
- package/dist/workflow/session-artifacts.js.map +1 -0
- package/dist/workflow/session-view.d.ts +31 -0
- package/dist/workflow/session-view.js +94 -0
- package/dist/workflow/session-view.js.map +1 -0
- package/dist/workflow/snapshot.d.ts +14 -0
- package/dist/workflow/snapshot.js +97 -0
- package/dist/workflow/snapshot.js.map +1 -0
- package/dist/workflow/state.d.ts +347 -0
- package/dist/workflow/state.js +322 -0
- package/dist/workflow/state.js.map +1 -0
- package/dist/workflow/sub-workflow.d.ts +174 -0
- package/dist/workflow/sub-workflow.js +392 -0
- package/dist/workflow/sub-workflow.js.map +1 -0
- package/dist/workflow/tool-service.d.ts +48 -0
- package/dist/workflow/tool-service.js +291 -0
- package/dist/workflow/tool-service.js.map +1 -0
- package/dist/workflow/turn-boundary.d.ts +39 -0
- package/dist/workflow/turn-boundary.js +128 -0
- package/dist/workflow/turn-boundary.js.map +1 -0
- package/dist/workflow/turn-runner.d.ts +40 -0
- package/dist/workflow/turn-runner.js +122 -0
- package/dist/workflow/turn-runner.js.map +1 -0
- package/dist/workflow/workflow-tools.d.ts +46 -0
- package/dist/workflow/workflow-tools.js +90 -0
- package/dist/workflow/workflow-tools.js.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The model-facing account of the governed mounts a state may reach — the mount
|
|
3
|
+
* twin of `renderSkillsSection`, and in the **volatile** system block for the
|
|
4
|
+
* same reason: what varies with the state cannot live in the cacheable prefix.
|
|
5
|
+
*
|
|
6
|
+
* The static "Workspace zones" section therefore names ungoverned mounts only
|
|
7
|
+
* (see {@link renderWorkspaceZones}), and this names what this state was given.
|
|
8
|
+
* A state that reaches none gets no heading rather than an empty one, and
|
|
9
|
+
* therefore no invitation to go looking.
|
|
10
|
+
*/
|
|
11
|
+
/** Heading of the rendered section, also the marker tests assert on. */
|
|
12
|
+
export const MOUNTS_SECTION_HEADING = "Mounts available in this state";
|
|
13
|
+
/**
|
|
14
|
+
* Render the section for one state's enabled governed mounts, or `null` when the
|
|
15
|
+
* set is empty.
|
|
16
|
+
*
|
|
17
|
+
* `enabled` is the resolved name order (see `WorkflowMachine.enabledMounts`),
|
|
18
|
+
* sorted here so the text is stable under a spec edit that only reorders a
|
|
19
|
+
* list — a prompt section that reordered itself would churn the transcript for
|
|
20
|
+
* no reason. Each name is printed as the agent addresses it: a directory mount
|
|
21
|
+
* with a trailing slash, a file mount by its exact path, read-only or read/write
|
|
22
|
+
* per `writable` — the state's own posture (`WorkflowMachine.mountWritable`),
|
|
23
|
+
* which a grant's `access: read` may have narrowed below the host's. A mount the
|
|
24
|
+
* host declared unsearchable gets a browse-only note, so the model lists and
|
|
25
|
+
* reads it rather than searching it; every other line is unchanged.
|
|
26
|
+
*/
|
|
27
|
+
export function renderMountsSection(enabled, mounts, writable) {
|
|
28
|
+
const files = new Set(mounts.files);
|
|
29
|
+
const bullets = [...enabled].sort().map((name) => {
|
|
30
|
+
const address = files.has(name) ? name : `${name}/`;
|
|
31
|
+
// The state's own posture, not the table's: a grant may narrow a writable
|
|
32
|
+
// mount to reads here, and the prompt has to say what this state can do.
|
|
33
|
+
const posture = writable(name)
|
|
34
|
+
? "read/write — write there directly when the work belongs there, no less " +
|
|
35
|
+
"freely than in your own working area; the write is checked against this " +
|
|
36
|
+
"state's tool rules like any other"
|
|
37
|
+
: "read-only — read it freely, writes there are blocked";
|
|
38
|
+
const browse = mounts.unsearchable.includes(name)
|
|
39
|
+
? " Browse only: list and read it directly. Searches from the root leave it out, " +
|
|
40
|
+
"and a search addressed at it is answered by the mount itself."
|
|
41
|
+
: "";
|
|
42
|
+
return `- **\`${address}\`** — ${posture}.${browse}`;
|
|
43
|
+
});
|
|
44
|
+
if (bullets.length === 0)
|
|
45
|
+
return null;
|
|
46
|
+
return [
|
|
47
|
+
`## ${MOUNTS_SECTION_HEADING}`,
|
|
48
|
+
"",
|
|
49
|
+
...bullets,
|
|
50
|
+
"",
|
|
51
|
+
`Only these mounts are reachable from this state: every other mount's files are blocked ` +
|
|
52
|
+
`here, whatever an earlier state could read.`,
|
|
53
|
+
].join("\n");
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=mount-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-prompt.js","sourceRoot":"","sources":["../../src/core/mount-prompt.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAA0B,EAC1B,MAAqB,EACrB,QAAmC;IAEnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;QACpD,0EAA0E;QAC1E,yEAAyE;QACzE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC;YAC5B,CAAC,CAAC,yEAAyE;gBACzE,0EAA0E;gBAC1E,mCAAmC;YACrC,CAAC,CAAC,sDAAsD,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC/C,CAAC,CAAC,gFAAgF;gBAChF,+DAA+D;YACjE,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,SAAS,OAAO,UAAU,OAAO,IAAI,MAAM,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO;QACL,MAAM,sBAAsB,EAAE;QAC9B,EAAE;QACF,GAAG,OAAO;QACV,EAAE;QACF,yFAAyF;YACvF,6CAA6C;KAChD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type MountPrefixes } from "./zones.js";
|
|
2
|
+
/**
|
|
3
|
+
* Keep a mount the state cannot reach out of a *listing* — the mounts half of
|
|
4
|
+
* the shared listing filter (`core/listing-redact.ts`, which carries the
|
|
5
|
+
* reasoning and the line shapes), and the twin of `redactDisabledSkills`.
|
|
6
|
+
*
|
|
7
|
+
* The workspace root listing is the case that matters most: a governed mount the
|
|
8
|
+
* state does not have would otherwise appear at the root as a directory the
|
|
9
|
+
* agent then cannot read, which reads to a model as a broken workspace rather
|
|
10
|
+
* than as a capability it was not given.
|
|
11
|
+
*/
|
|
12
|
+
/** What a state may see of the mount table: the kernel's decision, as data. */
|
|
13
|
+
export interface MountVisibility {
|
|
14
|
+
/** The **governed** mounts this state enables (`WorkflowMachine.enabledMounts`). */
|
|
15
|
+
readonly enabled: readonly string[];
|
|
16
|
+
/** Every mount name denied here, governed or not (`forbiddenMounts`). */
|
|
17
|
+
readonly forbidden: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Drop from `text` every line under a mount this state cannot see: a governed
|
|
21
|
+
* mount no list enabled, or any mount a `forbid` names. A path under no mount,
|
|
22
|
+
* and a path under an ungoverned mount nothing denies, is kept — that mount is
|
|
23
|
+
* visible in every state.
|
|
24
|
+
*
|
|
25
|
+
* Returns the text unchanged when nothing was hidden, so a result the filter has
|
|
26
|
+
* no opinion about is passed through by identity rather than rebuilt.
|
|
27
|
+
*/
|
|
28
|
+
export declare function redactHiddenMounts(text: string, visibility: MountVisibility, mounts: MountPrefixes): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { redactListing } from "./listing-redact.js";
|
|
2
|
+
import { mountNameOf } from "./zones.js";
|
|
3
|
+
/**
|
|
4
|
+
* Drop from `text` every line under a mount this state cannot see: a governed
|
|
5
|
+
* mount no list enabled, or any mount a `forbid` names. A path under no mount,
|
|
6
|
+
* and a path under an ungoverned mount nothing denies, is kept — that mount is
|
|
7
|
+
* visible in every state.
|
|
8
|
+
*
|
|
9
|
+
* Returns the text unchanged when nothing was hidden, so a result the filter has
|
|
10
|
+
* no opinion about is passed through by identity rather than rebuilt.
|
|
11
|
+
*/
|
|
12
|
+
export function redactHiddenMounts(text, visibility, mounts) {
|
|
13
|
+
if (!text)
|
|
14
|
+
return text;
|
|
15
|
+
const enabled = new Set(visibility.enabled);
|
|
16
|
+
const forbidden = new Set(visibility.forbidden);
|
|
17
|
+
const hidden = (name) => forbidden.has(name) || (mounts.governed.includes(name) && !enabled.has(name));
|
|
18
|
+
// Nothing to hide: every mount the table serves is reachable from here.
|
|
19
|
+
const names = [...mounts.dirs, ...mounts.files];
|
|
20
|
+
if (!names.some(hidden))
|
|
21
|
+
return text;
|
|
22
|
+
return redactListing(text, (path) => mountNameOf(canonical(path), mounts), hidden);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A result line's path in the form `mountNameOf` classifies: leading slashes
|
|
26
|
+
* stripped, the shape the tools print (`/catalogs/eu/skus.csv`) reduced to the
|
|
27
|
+
* shape the mount table holds.
|
|
28
|
+
*/
|
|
29
|
+
function canonical(path) {
|
|
30
|
+
return path.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=mount-redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-redact.js","sourceRoot":"","sources":["../../src/core/mount-redact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAC;AAqB7D;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,UAA2B,EAC3B,MAAqB;IAErB,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAC9B,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,wEAAwE;IACxE,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type BackendProtocolV2 } from "deepagents";
|
|
2
|
+
import { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, NO_MOUNTS, type AuthoringPrefix, type MountPrefixes } from "./zones.js";
|
|
3
|
+
/**
|
|
4
|
+
* Authored mounts, expressed in the framework's own vocabulary: a
|
|
5
|
+
* {@link CompositeBackend}-style route table of ordinary backends the consumer
|
|
6
|
+
* composes. The runtime owns only the **default route** — the session store, which
|
|
7
|
+
* must catch the runtime's fixed offload paths — and mounts this table beside it.
|
|
8
|
+
*
|
|
9
|
+
* A backend rooted *at* the mounted directory needs no path adaptation: the
|
|
10
|
+
* composite strips the route prefix before delegating and re-applies it to result
|
|
11
|
+
* paths. A consumer serving several mounts from one backend rebases with
|
|
12
|
+
* `mountSubtree` (exported from `core/path-mapping.ts`).
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* A mount: a backend (read-only), or a backend with its write posture and its
|
|
16
|
+
* governance declared.
|
|
17
|
+
*
|
|
18
|
+
* `governed: true` says the spec decides which **states** may see this mount:
|
|
19
|
+
* it is closed by default and reachable only where a `mounts` list enables it,
|
|
20
|
+
* exactly as a skill bundle is. An ungoverned mount (the default, and every
|
|
21
|
+
* existing table) is visible in every state, and only a `mounts.forbid` takes
|
|
22
|
+
* it away. The consumer owns which backend serves a mount, its write posture
|
|
23
|
+
* and whether it is governed; the spec owns which states enable it, and neither
|
|
24
|
+
* is inferred from the other.
|
|
25
|
+
*
|
|
26
|
+
* `searchable: false` says the runtime must never search this mount on its own
|
|
27
|
+
* initiative: a root-wide `grep` or `glob` leaves it out, so a backend that
|
|
28
|
+
* refuses searches (a remote folder a search would download) cannot fail every
|
|
29
|
+
* root-wide search. A search the agent addresses at the mount still reaches the
|
|
30
|
+
* backend, whose own answer — matches or refusal — is returned verbatim. The
|
|
31
|
+
* flag is inert on a file mount, which is never searched as a tree.
|
|
32
|
+
*/
|
|
33
|
+
export type MountSpec = BackendProtocolV2 | {
|
|
34
|
+
backend: BackendProtocolV2;
|
|
35
|
+
readOnly?: boolean;
|
|
36
|
+
governed?: boolean;
|
|
37
|
+
searchable?: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** One resolved mount: its normalized key, backend, write posture and governance. */
|
|
40
|
+
export interface ResolvedMount {
|
|
41
|
+
/** Directory mounts keep their trailing slash; file mounts have none. */
|
|
42
|
+
key: string;
|
|
43
|
+
/** Key without leading slash or trailing slash — the reserved root name. */
|
|
44
|
+
name: string;
|
|
45
|
+
backend: BackendProtocolV2;
|
|
46
|
+
readOnly: boolean;
|
|
47
|
+
isDir: boolean;
|
|
48
|
+
/** Whether the spec's `mounts` lists decide which states may reach it. */
|
|
49
|
+
governed: boolean;
|
|
50
|
+
/** Whether a root-wide search may fan out into it (`true` unless declared otherwise). */
|
|
51
|
+
searchable: boolean;
|
|
52
|
+
}
|
|
53
|
+
export { NO_MOUNTS, type MountPrefixes };
|
|
54
|
+
/**
|
|
55
|
+
* Thrown when a declared mount key would shadow a run area or serve an
|
|
56
|
+
* authoring-plane prefix to the agent. A declared route is the consumer's wiring
|
|
57
|
+
* rather than incidental noise, so it fails loudly instead of being skipped.
|
|
58
|
+
*/
|
|
59
|
+
export declare class MountCollisionError extends Error {
|
|
60
|
+
readonly key: string;
|
|
61
|
+
constructor(key: string);
|
|
62
|
+
}
|
|
63
|
+
export { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, type AuthoringPrefix, };
|
|
64
|
+
/**
|
|
65
|
+
* Canonical mount key: one leading slash, collapsed separators, trailing slash
|
|
66
|
+
* preserved (it is what distinguishes a directory mount from a file mount).
|
|
67
|
+
*/
|
|
68
|
+
export declare function normalizeMountKey(key: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Resolve a consumer's mount table into the composite routes and the prefixes
|
|
71
|
+
* governance classifies against. Throws {@link MountCollisionError} when a key
|
|
72
|
+
* would shadow a run area or name an {@link AUTHORING_PREFIXES} prefix.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveMounts(table?: Record<string, MountSpec>): {
|
|
75
|
+
mounts: ResolvedMount[];
|
|
76
|
+
prefixes: MountPrefixes;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The conventional mount table for a filesystem workspace: each authored
|
|
80
|
+
* directory as a {@link FilesystemBackend} rooted at itself, plus `AGENTS.md`
|
|
81
|
+
* served from the workspace root by exact path.
|
|
82
|
+
*
|
|
83
|
+
* This is a **default value**, applied only when the consumer supplies no table
|
|
84
|
+
* on the default backend — not framework law. Nothing in the framework
|
|
85
|
+
* classifies, validates, or enforces against these names; spread it to extend
|
|
86
|
+
* (`{ ...defaultMounts(root), "/templates/": … }`) or ignore it entirely.
|
|
87
|
+
*/
|
|
88
|
+
export declare function defaultMounts(rootDir: string): Record<string, MountSpec>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { FilesystemBackend } from "deepagents";
|
|
3
|
+
import { normalizeRelPath } from "./workspace.js";
|
|
4
|
+
import { PLATFORM_PROMPT_PATH } from "../workflow/paths.js";
|
|
5
|
+
import { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, NO_MOUNTS, sessionAreaNames, } from "./zones.js";
|
|
6
|
+
// The classification input type lives with the classifier (`core/zones.ts`);
|
|
7
|
+
// re-exported here so consumers reach the whole mount vocabulary from one module.
|
|
8
|
+
export { NO_MOUNTS };
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when a declared mount key would shadow a run area or serve an
|
|
11
|
+
* authoring-plane prefix to the agent. A declared route is the consumer's wiring
|
|
12
|
+
* rather than incidental noise, so it fails loudly instead of being skipped.
|
|
13
|
+
*/
|
|
14
|
+
export class MountCollisionError extends Error {
|
|
15
|
+
key;
|
|
16
|
+
constructor(key) {
|
|
17
|
+
const name = key.replace(/^\/+|\/+$/g, "");
|
|
18
|
+
// The collision is with the key's *first* segment, so a nested key
|
|
19
|
+
// (`/workflows/order-lookup/`) is named for the prefix it reaches into.
|
|
20
|
+
const top = name.split("/")[0] ?? "";
|
|
21
|
+
const plane = isAuthoringPrefix(top) ? top : null;
|
|
22
|
+
super(plane
|
|
23
|
+
? `Mount '${key}' would serve the authoring plane to the agent. ` +
|
|
24
|
+
`'${plane}/' holds ${describeAuthoringPrefix(plane)}; the runtime ` +
|
|
25
|
+
`reads them through the authoring backend, and no agent tool may address them. ` +
|
|
26
|
+
`Configure them with the 'authoring' option instead of mounting them.`
|
|
27
|
+
: `Mount '${key}' collides with the run area '${top}/', which the ` +
|
|
28
|
+
`session store owns at the workspace root. Mount it under a different key.`);
|
|
29
|
+
this.key = key;
|
|
30
|
+
this.name = "MountCollisionError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const SESSION_AREA_SET = new Set(sessionAreaNames());
|
|
34
|
+
// The authoring prefixes are root-namespace vocabulary and live with the rest of
|
|
35
|
+
// it in `core/zones.ts`; re-exported here so consumers reach the whole mount
|
|
36
|
+
// vocabulary from one module.
|
|
37
|
+
export { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, };
|
|
38
|
+
/**
|
|
39
|
+
* Canonical mount key: one leading slash, collapsed separators, trailing slash
|
|
40
|
+
* preserved (it is what distinguishes a directory mount from a file mount).
|
|
41
|
+
*/
|
|
42
|
+
export function normalizeMountKey(key) {
|
|
43
|
+
const isDir = /\/\s*$/.test(key);
|
|
44
|
+
const rel = normalizeRelPath(key).replace(/\/+$/, "");
|
|
45
|
+
return `/${rel}${isDir ? "/" : ""}`;
|
|
46
|
+
}
|
|
47
|
+
function specParts(spec) {
|
|
48
|
+
if (typeof spec === "object" && spec !== null && "backend" in spec) {
|
|
49
|
+
return {
|
|
50
|
+
backend: spec.backend,
|
|
51
|
+
readOnly: spec.readOnly ?? true,
|
|
52
|
+
governed: spec.governed ?? false,
|
|
53
|
+
searchable: spec.searchable ?? true,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return { backend: spec, readOnly: true, governed: false, searchable: true };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve a consumer's mount table into the composite routes and the prefixes
|
|
60
|
+
* governance classifies against. Throws {@link MountCollisionError} when a key
|
|
61
|
+
* would shadow a run area or name an {@link AUTHORING_PREFIXES} prefix.
|
|
62
|
+
*/
|
|
63
|
+
export function resolveMounts(table = {}) {
|
|
64
|
+
const mounts = [];
|
|
65
|
+
for (const [rawKey, spec] of Object.entries(table)) {
|
|
66
|
+
const key = normalizeMountKey(rawKey);
|
|
67
|
+
const name = key.replace(/^\/+|\/+$/g, "");
|
|
68
|
+
if (name === "")
|
|
69
|
+
continue;
|
|
70
|
+
// The *first* segment decides: a key several levels down the reserved
|
|
71
|
+
// prefix is the same exposure as the prefix itself, so `/workflows/x/`
|
|
72
|
+
// fails exactly as `/workflows/` does.
|
|
73
|
+
const [top = ""] = name.split("/");
|
|
74
|
+
if (SESSION_AREA_SET.has(top) || isAuthoringPrefix(top)) {
|
|
75
|
+
throw new MountCollisionError(key);
|
|
76
|
+
}
|
|
77
|
+
const { backend, readOnly, governed, searchable } = specParts(spec);
|
|
78
|
+
mounts.push({
|
|
79
|
+
key,
|
|
80
|
+
name,
|
|
81
|
+
backend,
|
|
82
|
+
readOnly,
|
|
83
|
+
isDir: key.endsWith("/"),
|
|
84
|
+
governed,
|
|
85
|
+
searchable,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
mounts,
|
|
90
|
+
prefixes: {
|
|
91
|
+
dirs: mounts.filter((m) => m.isDir).map((m) => m.name),
|
|
92
|
+
files: mounts.filter((m) => !m.isDir).map((m) => m.name),
|
|
93
|
+
writable: mounts.filter((m) => !m.readOnly).map((m) => m.name),
|
|
94
|
+
governed: mounts.filter((m) => m.governed).map((m) => m.name),
|
|
95
|
+
// Only a directory is ever searched as a tree, so the flag on a file
|
|
96
|
+
// mount is recorded on the resolved mount but classifies nothing.
|
|
97
|
+
unsearchable: mounts.filter((m) => m.isDir && !m.searchable).map((m) => m.name),
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Conventional authored directories — a default value, never a constraint.
|
|
103
|
+
*
|
|
104
|
+
* Deliberately short, and deliberately missing every {@link AUTHORING_PREFIXES}
|
|
105
|
+
* prefix. That plane is not workspace furniture the agent browses: it is what the
|
|
106
|
+
* runtime enforces the run *with*, served by the authoring backend and reachable by
|
|
107
|
+
* no tool call. `workflows/` holds the spec — its grading rubrics included, so a run
|
|
108
|
+
* cannot read the criteria it is judged against — plus the prose addendum, the hook
|
|
109
|
+
* scripts, and the cases grading the run.
|
|
110
|
+
*
|
|
111
|
+
* What ships in a skill bundle is the other kind of script — the ones the *agent*
|
|
112
|
+
* runs with `archmax_run` — together with the data a state reads
|
|
113
|
+
* (`skills/<name>/scripts/…`, `skills/<name>/assets/…`), reaching the agent through
|
|
114
|
+
* the `skills/` mount, which also lets a state scope execution to one capability
|
|
115
|
+
* (`skills/triage/scripts/**`).
|
|
116
|
+
*
|
|
117
|
+
* None of the conventional mounts is `governed`: a zero-config workspace's
|
|
118
|
+
* content is visible in every state, exactly as it was before the `mounts`
|
|
119
|
+
* block existed.
|
|
120
|
+
*/
|
|
121
|
+
const CONVENTIONAL_DIRS = [
|
|
122
|
+
"skills",
|
|
123
|
+
PLATFORM_PROMPT_PATH.split("/")[0], // `.platform` — the runtime reads its prompt from here
|
|
124
|
+
];
|
|
125
|
+
/** Conventional authored root files, mounted by exact path. */
|
|
126
|
+
const CONVENTIONAL_FILES = ["AGENTS.md"];
|
|
127
|
+
/**
|
|
128
|
+
* The conventional mount table for a filesystem workspace: each authored
|
|
129
|
+
* directory as a {@link FilesystemBackend} rooted at itself, plus `AGENTS.md`
|
|
130
|
+
* served from the workspace root by exact path.
|
|
131
|
+
*
|
|
132
|
+
* This is a **default value**, applied only when the consumer supplies no table
|
|
133
|
+
* on the default backend — not framework law. Nothing in the framework
|
|
134
|
+
* classifies, validates, or enforces against these names; spread it to extend
|
|
135
|
+
* (`{ ...defaultMounts(root), "/templates/": … }`) or ignore it entirely.
|
|
136
|
+
*/
|
|
137
|
+
export function defaultMounts(rootDir) {
|
|
138
|
+
const fs = (dir) => new FilesystemBackend({ rootDir: dir, virtualMode: true });
|
|
139
|
+
const table = {};
|
|
140
|
+
for (const dir of CONVENTIONAL_DIRS)
|
|
141
|
+
table[`/${dir}/`] = fs(join(rootDir, dir));
|
|
142
|
+
// Root files live in the workspace root itself, addressed by their exact key.
|
|
143
|
+
for (const file of CONVENTIONAL_FILES)
|
|
144
|
+
table[`/${file}`] = fs(rootDir);
|
|
145
|
+
return table;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=mounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mounts.js","sourceRoot":"","sources":["../../src/core/mounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { BackendProtocolV2 } from "deepagents";
|
|
2
|
+
/**
|
|
3
|
+
* Bidirectional path mapping for a backend served under a prefix.
|
|
4
|
+
*
|
|
5
|
+
* Three places in the runtime delegate to a backend whose paths are shifted by
|
|
6
|
+
* a prefix, and all three need the *same* two-way mapping:
|
|
7
|
+
*
|
|
8
|
+
* - **Authored mounts** — `CompositeBackend` strips the route prefix before
|
|
9
|
+
* delegating (`/skills/x` → `/x`) and re-prepends it to the paths it returns.
|
|
10
|
+
* A one-way prepending wrapper therefore double-prefixes every listed path
|
|
11
|
+
* (`/skills/skills/x`); the outbound half is what keeps the round trip honest.
|
|
12
|
+
* - **The session store's tenancy prefix** — consumer-owned layout that must never
|
|
13
|
+
* appear in an SDK-visible or agent-visible path, including result paths.
|
|
14
|
+
* - **The session zone's session binding** — the bound session id must not appear in
|
|
15
|
+
* agent-visible listings, so it is stripped on the way out.
|
|
16
|
+
*
|
|
17
|
+
* Inbound: `/x` → `/<prefix>/x`. Outbound: every `path` a result carries
|
|
18
|
+
* (`ls`/`glob` entries, `grep` matches, `write`/`edit` results) is mapped back.
|
|
19
|
+
* A result path that does not start with the prefix is left untouched — the
|
|
20
|
+
* inner backend is free to report paths we did not ask about.
|
|
21
|
+
*/
|
|
22
|
+
/** The prefix in effect for a call: a fixed string, or resolved per call. */
|
|
23
|
+
export type PrefixResolver = () => string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Wrap `backend` so it is addressed under `prefix` from the outside, mapping
|
|
26
|
+
* paths in both directions. `prefix` may be a resolver, returning `undefined`
|
|
27
|
+
* when no prefix applies for this call (the session zone outside a bound session) —
|
|
28
|
+
* in which case paths pass through unchanged.
|
|
29
|
+
*
|
|
30
|
+
* `passthrough` marks inbound paths that are already expressed in the inner
|
|
31
|
+
* backend's terms and must not be prefixed (e.g. runtime-internal
|
|
32
|
+
* session-qualified paths, cross-session `_specs/…`). Their result paths are left
|
|
33
|
+
* unmapped as well, since they were never shifted.
|
|
34
|
+
*/
|
|
35
|
+
export declare function mountSubtree(backend: BackendProtocolV2, prefix: string | PrefixResolver, options?: {
|
|
36
|
+
passthrough?: (relPath: string, prefix: string) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Refuse `write`/`edit` at the mount instead of delegating. Read-only is a
|
|
39
|
+
* property of the mount, so an authored mount cannot be written through even
|
|
40
|
+
* by a caller that bypasses governance — the kernel's `zone.read-only` rule
|
|
41
|
+
* remains the agent-facing diagnostic, not the only enforcement.
|
|
42
|
+
*/
|
|
43
|
+
readOnly?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Route prefix a composite stripped before delegating, re-applied when a
|
|
46
|
+
* read-only refusal names the rejected path. Without it the refusal reports
|
|
47
|
+
* the stripped key (`/orders.json`) rather than the path the caller sent
|
|
48
|
+
* (`data/orders.json`) — pointing an agent at a path it never asked about,
|
|
49
|
+
* which is exactly the confusion that makes it retry with invented paths.
|
|
50
|
+
*/
|
|
51
|
+
displayPrefix?: string;
|
|
52
|
+
}): BackendProtocolV2;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { normalizeRelPath } from "./workspace.js";
|
|
2
|
+
function relPrefix(prefix) {
|
|
3
|
+
return normalizeRelPath(prefix).replace(/\/+$/, "");
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Wrap `backend` so it is addressed under `prefix` from the outside, mapping
|
|
7
|
+
* paths in both directions. `prefix` may be a resolver, returning `undefined`
|
|
8
|
+
* when no prefix applies for this call (the session zone outside a bound session) —
|
|
9
|
+
* in which case paths pass through unchanged.
|
|
10
|
+
*
|
|
11
|
+
* `passthrough` marks inbound paths that are already expressed in the inner
|
|
12
|
+
* backend's terms and must not be prefixed (e.g. runtime-internal
|
|
13
|
+
* session-qualified paths, cross-session `_specs/…`). Their result paths are left
|
|
14
|
+
* unmapped as well, since they were never shifted.
|
|
15
|
+
*/
|
|
16
|
+
export function mountSubtree(backend, prefix, options = {}) {
|
|
17
|
+
const resolvePrefix = typeof prefix === "function" ? () => optionalRel(prefix()) : () => relPrefix(prefix);
|
|
18
|
+
const passthrough = options.passthrough;
|
|
19
|
+
/**
|
|
20
|
+
* The refused path in workspace terms — the spelling the caller would use to
|
|
21
|
+
* address it — so the diagnostic names the path that was actually rejected.
|
|
22
|
+
*/
|
|
23
|
+
const displayPath = (path) => {
|
|
24
|
+
const rel = normalizeRelPath(path);
|
|
25
|
+
const prefix = relPrefix(options.displayPrefix ?? "");
|
|
26
|
+
if (!prefix)
|
|
27
|
+
return rel === "" ? path : rel;
|
|
28
|
+
return rel === "" ? prefix : `${prefix}/${rel}`;
|
|
29
|
+
};
|
|
30
|
+
const readOnlyError = (op, path) => ({
|
|
31
|
+
error: `Cannot ${op} '${displayPath(path)}': it is served by a read-only mount. ` +
|
|
32
|
+
`Only run state is writable in this workspace.`,
|
|
33
|
+
});
|
|
34
|
+
/** The prefix to apply to `path`, or `undefined` when it passes through. */
|
|
35
|
+
const prefixFor = (path) => {
|
|
36
|
+
const active = resolvePrefix();
|
|
37
|
+
if (!active)
|
|
38
|
+
return undefined;
|
|
39
|
+
if (passthrough?.(normalizeRelPath(path), active))
|
|
40
|
+
return undefined;
|
|
41
|
+
return active;
|
|
42
|
+
};
|
|
43
|
+
const mapIn = (path, active) => {
|
|
44
|
+
if (!active)
|
|
45
|
+
return path;
|
|
46
|
+
const hadSlash = path.startsWith("/");
|
|
47
|
+
const rel = normalizeRelPath(path);
|
|
48
|
+
const joined = rel === "" ? active : `${active}/${rel}`;
|
|
49
|
+
return hadSlash || path === "" ? `/${joined}` : joined;
|
|
50
|
+
};
|
|
51
|
+
const mapOut = (path, active) => {
|
|
52
|
+
if (!active)
|
|
53
|
+
return path;
|
|
54
|
+
const hadSlash = path.startsWith("/");
|
|
55
|
+
const rel = normalizeRelPath(path);
|
|
56
|
+
if (rel !== active && !rel.startsWith(`${active}/`))
|
|
57
|
+
return path;
|
|
58
|
+
const stripped = rel === active ? "" : rel.slice(active.length + 1);
|
|
59
|
+
return hadSlash ? `/${stripped}` : stripped;
|
|
60
|
+
};
|
|
61
|
+
const mapFiles = (files, active) => files?.map((file) => ({ ...file, path: mapOut(file.path, active) }));
|
|
62
|
+
return {
|
|
63
|
+
async ls(path) {
|
|
64
|
+
const active = prefixFor(path);
|
|
65
|
+
const res = await backend.ls(mapIn(path, active));
|
|
66
|
+
const files = mapFiles(res.files, active);
|
|
67
|
+
return files ? { ...res, files } : res;
|
|
68
|
+
},
|
|
69
|
+
read(filePath, offset, limit) {
|
|
70
|
+
return backend.read(mapIn(filePath, prefixFor(filePath)), offset, limit);
|
|
71
|
+
},
|
|
72
|
+
readRaw(filePath) {
|
|
73
|
+
return backend.readRaw(mapIn(filePath, prefixFor(filePath)));
|
|
74
|
+
},
|
|
75
|
+
async grep(pattern, path, glob) {
|
|
76
|
+
const target = path ?? "";
|
|
77
|
+
const active = prefixFor(target);
|
|
78
|
+
const searchPath = path == null && !active ? path : mapIn(target, active);
|
|
79
|
+
const res = await backend.grep(pattern, searchPath, glob);
|
|
80
|
+
const matches = res.matches?.map((match) => ({ ...match, path: mapOut(match.path, active) }));
|
|
81
|
+
return matches ? { ...res, matches } : res;
|
|
82
|
+
},
|
|
83
|
+
async glob(pattern, path) {
|
|
84
|
+
const target = path ?? "";
|
|
85
|
+
const active = prefixFor(target);
|
|
86
|
+
const searchPath = path === undefined && !active ? undefined : mapIn(target, active);
|
|
87
|
+
const res = await backend.glob(pattern, searchPath);
|
|
88
|
+
const files = mapFiles(res.files, active);
|
|
89
|
+
return files ? { ...res, files } : res;
|
|
90
|
+
},
|
|
91
|
+
async write(filePath, content) {
|
|
92
|
+
if (options.readOnly)
|
|
93
|
+
return readOnlyError("write", filePath);
|
|
94
|
+
const active = prefixFor(filePath);
|
|
95
|
+
const res = await backend.write(mapIn(filePath, active), content);
|
|
96
|
+
return res.path === undefined ? res : { ...res, path: mapOut(res.path, active) };
|
|
97
|
+
},
|
|
98
|
+
async edit(filePath, oldString, newString, replaceAll) {
|
|
99
|
+
if (options.readOnly)
|
|
100
|
+
return readOnlyError("edit", filePath);
|
|
101
|
+
const active = prefixFor(filePath);
|
|
102
|
+
const res = await backend.edit(mapIn(filePath, active), oldString, newString, replaceAll);
|
|
103
|
+
return res.path === undefined ? res : { ...res, path: mapOut(res.path, active) };
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function optionalRel(prefix) {
|
|
108
|
+
if (prefix == null)
|
|
109
|
+
return undefined;
|
|
110
|
+
const rel = relPrefix(prefix);
|
|
111
|
+
return rel === "" ? undefined : rel;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=path-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-mapping.js","sourceRoot":"","sources":["../../src/core/path-mapping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Generated from platform-prompt.md by scripts/generate-platform-prompt.mjs. Do not edit.
|
|
2
|
+
/** The bundled platform prompt: how to move through the graph and which tools are the runtime's. */
|
|
3
|
+
export const PLATFORM_PROMPT = "# Graph state execution\n\nYou run inside a **declarative workflow graph**: you occupy one **state** at a\ntime, and that state's spec governs which tools you may call and which files you\nmay read or write.\n\n## How you move\n\n1. **Name the run first.** Before anything else in your first turn, call\n **`archmax_set_variables({ \"variables\": { \"title\": \"<a few words>\" } })`** — see\n \"Naming the run\" below.\n2. Do the current state's work. `scratchpad/` is always open, so it is where a\n file goes when nothing else was named — but it is a default, not a limit: when\n the state's instructions or its listed mounts name a writable place, write\n there instead of copying into `scratchpad/`.\n3. Call **`archmax_advance({ \"to\": \"<next>\", \"reason\": \"<one sentence>\" })`**,\n choosing `to` from the transitions listed under \"Current state\" and using\n their descriptions to decide. `to` takes the target's **slug** — the\n backticked token on the transition line. A parenthesized note carries the\n edge's declared type (`approve`, `reject`, `refine`), whether the target is a\n **human decision node**, and whether it is **terminal**. A state with no\n transitions says so: that is where the run ends, so finish its work and stop.\n4. The runtime validates the edge, runs this state's `after` hook and then the\n target's `before` hook — either may send you back to correct or veto the\n move — and only then unlocks the next state's tools.\n\n**One transition per message.** A second `archmax_advance` alongside the first is\nrefused. Chain states over successive turns, never in a single message.\n\n**A conversation keeps its position.** A message arriving after your last turn\nleaves you in the state that turn ended in, not at the beginning. When that state\ncannot serve what was asked — no transition from here reaches it, or an earlier\nturn took a wrong path — call **`archmax_reset({ \"reason\": \"<one sentence>\" })`**\nto return to the state the conversation began in. It is available in every state\nand moves the state machine, not the history: the conversation and everything\nwritten so far are kept.\n\n**A terminal state never serves a follow-up.** A reply, a correction or a new\nrequest landing on a run that was *already sitting* in a terminal state is work\nthis run has no path to do: reset **before** answering it, or you skip every state\nthe answer depends on. Two things are not follow-ups — a run you parked with\n`archmax_wait`, which resumes where it was on purpose, and a terminal state you\nwere routed into *this turn*, by your own `archmax_advance` or by a person's\ndecision, which is the work you were sent there to do: do it, then stop. Never\nreset out of a state you just arrived in, and never `archmax_wait` for the runtime\nto move you — it already has.\n\n### Waiting for something to arrive\n\nIf this state cannot continue without something from **outside the run** — an\nevent, a callback, a webhook, a reply someone sends in their own time — call\n**`archmax_wait({ \"reason\": \"<what you are waiting for>\" })`** and stop, instead of\nending your turn. You resume in **this same state**, with what arrived in your\ntranscript and any values it carried in the variables. Waiting for a *time*\nrather than an event? Add `\"until\": \"1d\"` (a duration or an ISO-8601 instant) so\nwhoever wakes you knows when; an earlier event still resumes you.\n\n`archmax_wait` holds you where you are and moves nothing, so it is never how you\nget a person to decide, approve, sign off, review, or choose between options.\nThat belongs to a **human decision node** — a state the author declared for it,\nwhich you reach the ordinary way with `archmax_advance`. The runtime parks the run\nthere and presents the options by itself: do the work that state's transitions\nrequire, advance into the node, and stop. Never advance out of one yourself, and\nnever `archmax_wait` in front of one to ask for the decision the node exists to\ncollect.\n\nSo: something has to **come to this state** → `archmax_wait`. Someone has to\n**decide** → `archmax_advance` into the human node.\n\n### The state you are in\n\nThe active state's **`instructions`** arrive under a \"Current state\" heading —\nfollow them; the transitions listed there are for choosing where to go next. You\nare shown the edges leading out of the state you are in and nothing else of the\ngraph: there is no map of the workflow to consult, and a state you cannot advance\nto is one you cannot name. Do not guess at slugs, and do not treat a state named\nanywhere else — in a message, a file, or your own earlier turns — as somewhere you\ncan move to. When the state may use skills, they are listed under \"Skills\navailable in this state\", each naming the `SKILL.md` to read first.\n\n**`before`/`after` hooks** run on their own, without you calling them. They may\napprove, ask you to correct your answer, or block the run: fix the work rather\nthan arguing with it.\n\n## Tools\n\nTool access is **closed by default**: you see exactly the active state's surface,\nand a state's entry may also narrow a tool's permitted *arguments* (e.g.\n`write_file` to one path). Tools whose names start with `archmax_` are the\nruntime's own controls — movement, reset, waiting, the sandbox, and the run's\nvariables (`archmax_get_variables` / `archmax_set_variables`); everything else acts\non the workspace or on the systems this workspace integrates. A blocked call names\nthe tool, the state, and the policy — fix the call, or advance if you are done.\n\n**Write code instead of many calls.** **`archmax_eval({ \"code\": \"…\" })`** —\navailable in every state — evaluates JavaScript in a sandbox where `tools.*`\ncalls the same tools you have, governed exactly as your own calls are. Reach for\nit by default whenever the work is a loop, a filter, arithmetic, or more than\nabout two calls whose results feed each other: it is one round trip instead of\nmany, and **only your last expression and whatever you `console.log` come back to\nyou**, so the bulk of what those tools returned never enters the conversation and\nis never re-sent on later calls. The REPL keeps its state between calls, so a\nvalue or helper from one is still in scope in the next. Your code cannot read the\nrun's variables: interpolate a scalar one into it with `${{name}}` (below), and\nuse **`archmax_run({ \"file_path\": \"…\" })`** — also in every state — when the code\nneeds whole structured values, which an authored script receives as\n`args.variables`. It runs the same way, subject to any path constraint the state\nplaces on it.\n\n**Naming the run.** `title` is a reserved run variable holding a short label for\nthe task you are doing — one line, a handful of words, enough that someone\nscanning a list of runs knows which one this is:\n\n```\narchmax_set_variables({ \"variables\": { \"title\": \"Refund for order A-1042\" } })\n```\n\nThis is step 1 above, and it is not optional. Write it from whatever the request\nalready tells you, **before** the current state's own work and before any other\ntool call — it is a label, not a plan, so never investigate or read anything to\nproduce one, and it still goes first when the state's instructions tell you to do\nsomething else first. Update it with the same call whenever the task turns into\nsomething the old title no longer describes; a small refinement of the same task\ndoes not need one. Never pass `lock` with it: the title has to stay correctable\nfor the whole run, so that call is refused.\n\n**Reference a run variable instead of retyping it.** Anywhere a tool argument is\ntext, `${{name}}` (or `${{name.path.to.value}}`) is replaced with that variable's\nvalue before the call runs. A reference may sit **inside** a longer string and\nrepeat:\n\n```\n\"Thanks — your refund is on its way.\n\n--- Original message ---\n\n${{inbound.text}}\"\n```\n\nPrefer the reference to writing the value out. It is what you spend tokens on and\nwhat stays in the transcript — the full value goes to the tool and no further —\nand unlike a retyped copy it cannot paraphrase, truncate or mistype.\n`archmax_get_variables` shows what is set; a reference that does not resolve\nrefuses the call and tells you why, so fix it and retry. To write the characters\n`${{…}}` literally, double the dollar: `$${{name}}`.\n";
|
|
4
|
+
//# sourceMappingURL=platform-prompt.generated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-prompt.generated.js","sourceRoot":"","sources":["../../src/core/platform-prompt.generated.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,oGAAoG;AACpG,MAAM,CAAC,MAAM,eAAe,GAAW,qsQAAqsQ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Workspace } from "./workspace.js";
|
|
2
|
+
import { type MountPrefixes } from "./zones.js";
|
|
3
|
+
export interface ResolveSystemPromptOptions {
|
|
4
|
+
/** Workspace-relative path to AGENTS.md (default: `AGENTS.md`). */
|
|
5
|
+
agentsPath?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Where a workspace may override the platform prompt (normally
|
|
8
|
+
* `PLATFORM_PROMPT_PATH`); the bundled prompt applies when nothing is served
|
|
9
|
+
* there. `null` leaves the platform layer out — a plain agent has no machine
|
|
10
|
+
* for it to explain.
|
|
11
|
+
*/
|
|
12
|
+
platformBackendPath: string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Pre-assembled workflow prompt text: the spec-rendered workflow header
|
|
15
|
+
* followed by any `WORKFLOW.md` prose addendum (the caller composes both —
|
|
16
|
+
* see `renderWorkflowPrompt` — because it already holds the loaded spec and
|
|
17
|
+
* body; this module never re-reads the workflow files). Carries no state of
|
|
18
|
+
* the graph; `renderStateGraph` renders that per model call.
|
|
19
|
+
*/
|
|
20
|
+
workflowPrompt?: string | null;
|
|
21
|
+
/**
|
|
22
|
+
* The assembly's resolved mount keys. The workspace-zones section is rendered
|
|
23
|
+
* from these, so what the prompt says the agent has cannot drift from what the
|
|
24
|
+
* workspace serves. Omitted: no mounts are described.
|
|
25
|
+
*/
|
|
26
|
+
mountPrefixes?: MountPrefixes;
|
|
27
|
+
/** Extra text appended after AGENTS.md. */
|
|
28
|
+
extra?: string;
|
|
29
|
+
}
|
|
30
|
+
/** The layers `buildSystemPrompt` joins, in the order listed at the top of this module. */
|
|
31
|
+
export interface SystemPromptParts {
|
|
32
|
+
agents?: string | null;
|
|
33
|
+
extra?: string;
|
|
34
|
+
platform?: string | null;
|
|
35
|
+
/** The workspace-zones section, rendered from the resolved mount table. */
|
|
36
|
+
workspace?: string | null;
|
|
37
|
+
workflow?: string | null;
|
|
38
|
+
}
|
|
39
|
+
/** Join the prompt layers, skipping absent ones. */
|
|
40
|
+
export declare function buildSystemPrompt(parts: SystemPromptParts): string;
|
|
41
|
+
/** Load the prompt layers from the backend and merge them. */
|
|
42
|
+
export declare function resolveSystemPrompt(workspace: Workspace, opts: ResolveSystemPromptOptions): Promise<string>;
|