@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,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The system prompt, layered. Every layer below is either read through the
|
|
3
|
+
* backend or rendered from something the runtime enforces, so what the model is
|
|
4
|
+
* told cannot drift from what the workspace serves or the machine permits.
|
|
5
|
+
*
|
|
6
|
+
* The full order the model sees, first to last:
|
|
7
|
+
*
|
|
8
|
+
* 1. `AGENTS.md` — the workspace's persona, read through the composite.
|
|
9
|
+
* 2. The consumer's `systemPrompt` option — appended after the persona.
|
|
10
|
+
* 3. The platform prompt — how to move and which tools are the runtime's own.
|
|
11
|
+
* It ships inside the code (`platform-prompt.md`, generated into
|
|
12
|
+
* `platform-prompt.generated.ts`); a workspace may override it at
|
|
13
|
+
* `.platform/system/GRAPH_STATE.md`. A plain agent has no machine for it to
|
|
14
|
+
* explain, so it gets no platform layer.
|
|
15
|
+
* 4. Workspace zones — rendered from the assembly's resolved mount table.
|
|
16
|
+
* 5. The workflow header — the spec's `title` and root `instructions`, and no
|
|
17
|
+
* state of the graph: the graph is disclosed only from where the agent
|
|
18
|
+
* stands, so it lives in layer 8 (see `workflow/render-prompt.ts`). This
|
|
19
|
+
* layer is therefore a function of the header alone and does not grow with
|
|
20
|
+
* the state count.
|
|
21
|
+
* 6. `WORKFLOW.md` — the optional prose addendum, HTML comments stripped.
|
|
22
|
+
* 7. Deep Agents' tool guidance — the file tools' and `write_todos`' sections,
|
|
23
|
+
* appended by their middleware.
|
|
24
|
+
* 8. The volatile "Current state" block — the current date and time, then the
|
|
25
|
+
* active state's instructions, skills, mounts, variables, argument
|
|
26
|
+
* constraints and its own outgoing transitions, appended per model call by
|
|
27
|
+
* the workflow middleware and never part of the cacheable prefix. The clock
|
|
28
|
+
* is here for the same reason everything else in this block is — it does not
|
|
29
|
+
* hold still — and is rounded to a ten-minute bucket so that it holds still
|
|
30
|
+
* for the calls of one turn (see `renderNow` in `workflow/governance.ts`).
|
|
31
|
+
*
|
|
32
|
+
* Layers 1–6 are what `resolveSystemPrompt` returns and the assembly hands to
|
|
33
|
+
* Deep Agents as `systemPrompt: { prefix, base: null }`. Deep Agents' own base
|
|
34
|
+
* prompt ("You are a Deep Agent…") is deliberately dropped: it is generic
|
|
35
|
+
* assistant guidance that contradicts layer 3 (it says to ask before acting and
|
|
36
|
+
* to yield only when the task is done; a governed session parks, waits and
|
|
37
|
+
* stops at human states). Layers 7–8 come from middleware.
|
|
38
|
+
*/
|
|
39
|
+
import { PLATFORM_PROMPT } from "./platform-prompt.generated.js";
|
|
40
|
+
import { renderWorkspaceZones } from "./workspace-prompt.js";
|
|
41
|
+
import { NO_MOUNTS } from "./zones.js";
|
|
42
|
+
/** Join the prompt layers, skipping absent ones. */
|
|
43
|
+
export function buildSystemPrompt(parts) {
|
|
44
|
+
return [
|
|
45
|
+
parts.agents?.trim(),
|
|
46
|
+
parts.extra?.trim(),
|
|
47
|
+
parts.platform?.trim(),
|
|
48
|
+
parts.workspace?.trim(),
|
|
49
|
+
parts.workflow?.trim(),
|
|
50
|
+
]
|
|
51
|
+
.filter(Boolean)
|
|
52
|
+
.join("\n\n");
|
|
53
|
+
}
|
|
54
|
+
/** The workspace's override when it serves one, else the bundled prompt. */
|
|
55
|
+
async function readPlatformPrompt(workspace, backendPath) {
|
|
56
|
+
if (backendPath === null)
|
|
57
|
+
return null;
|
|
58
|
+
return (await workspace.readText(backendPath)) || PLATFORM_PROMPT;
|
|
59
|
+
}
|
|
60
|
+
/** Load the prompt layers from the backend and merge them. */
|
|
61
|
+
export async function resolveSystemPrompt(workspace, opts) {
|
|
62
|
+
const agentsPath = opts.agentsPath ?? "AGENTS.md";
|
|
63
|
+
const [platform, agents] = await Promise.all([
|
|
64
|
+
readPlatformPrompt(workspace, opts.platformBackendPath),
|
|
65
|
+
workspace.readText(agentsPath),
|
|
66
|
+
]);
|
|
67
|
+
return buildSystemPrompt({
|
|
68
|
+
agents,
|
|
69
|
+
extra: opts.extra,
|
|
70
|
+
platform,
|
|
71
|
+
workspace: renderWorkspaceZones(opts.mountPrefixes ?? NO_MOUNTS),
|
|
72
|
+
workflow: opts.workflowPrompt ?? null,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/core/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAsB,MAAM,YAAY,CAAC;AAwC3D,oDAAoD;AACpD,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,OAAO;QACL,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE;QACpB,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE;QACnB,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;QACtB,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE;QACvB,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;KACvB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC;AAED,4EAA4E;AAC5E,KAAK,UAAU,kBAAkB,CAC/B,SAAoB,EACpB,WAA0B;IAE1B,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,eAAe,CAAC;AACpE,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAoB,EACpB,IAAgC;IAEhC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC;IAClD,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3C,kBAAkB,CAAC,SAAS,EAAE,IAAI,CAAC,mBAAmB,CAAC;QACvD,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC;KAC/B,CAAC,CAAC;IAEH,OAAO,iBAAiB,CAAC;QACvB,MAAM;QACN,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ;QACR,SAAS,EAAE,oBAAoB,CAAC,IAAI,CAAC,aAAa,IAAI,SAAS,CAAC;QAChE,QAAQ,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI;KACtC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session-id vocabulary: what makes an id able to own a session folder, and
|
|
3
|
+
* the error an id that cannot is refused with. Pure — it depends on nothing but
|
|
4
|
+
* the root-namespace classifier — so a browser-side host can refuse a bad id
|
|
5
|
+
* with the same words the runtime uses, before it reaches a store. The stores
|
|
6
|
+
* themselves live in `session-store.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { type MountPrefixes } from "./zones.js";
|
|
9
|
+
/**
|
|
10
|
+
* Directory name of the zero-config filesystem session store
|
|
11
|
+
* (`<workspace>/sessions`, one folder per session inside it). Physical detail
|
|
12
|
+
* only: it appears in no SDK-visible or agent-visible path.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DEFAULT_SESSIONS_DIR = "sessions";
|
|
15
|
+
/**
|
|
16
|
+
* Thrown when a `sessionId` cannot own a session folder: it would address storage
|
|
17
|
+
* outside the session zone (absolute or `..` traversal), or it collides with a name
|
|
18
|
+
* reserved at the workspace root. The latter matters because session state is
|
|
19
|
+
* addressed as `<sessionId>/…` at the root — a session called `skills` would route
|
|
20
|
+
* its own checkpoints into the authored `skills/` mount. Deletion is also the
|
|
21
|
+
* one session operation that touches real `node:fs` directly (bypassing the
|
|
22
|
+
* backend's virtual mode), so it must contain its target itself.
|
|
23
|
+
*/
|
|
24
|
+
export declare class SessionStoreIdError extends Error {
|
|
25
|
+
readonly sessionId: string;
|
|
26
|
+
constructor(sessionId: string, reason?: string);
|
|
27
|
+
}
|
|
28
|
+
/** Strip leading slashes to the store-relative form. */
|
|
29
|
+
export declare function storeRelativeSessionId(sessionId: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Why a session id cannot own a session folder, or `null` when it can: non-empty
|
|
32
|
+
* once leading slashes are stripped, free of `..` traversal segments, and with a
|
|
33
|
+
* first segment that is not reserved at the workspace root. Exposed so
|
|
34
|
+
* untrusted-id ingress points (the CLI, `invoke`, session handles, a host's own
|
|
35
|
+
* API) can reject a bad id up front with their own message, rather than relying
|
|
36
|
+
* on a store throwing deep inside a delete.
|
|
37
|
+
*/
|
|
38
|
+
export declare function sessionIdRejection(sessionId: string, mountPrefixes?: MountPrefixes): string | null;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session-id vocabulary: what makes an id able to own a session folder, and
|
|
3
|
+
* the error an id that cannot is refused with. Pure — it depends on nothing but
|
|
4
|
+
* the root-namespace classifier — so a browser-side host can refuse a bad id
|
|
5
|
+
* with the same words the runtime uses, before it reaches a store. The stores
|
|
6
|
+
* themselves live in `session-store.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { isReservedRootName } from "./zones.js";
|
|
9
|
+
/**
|
|
10
|
+
* Directory name of the zero-config filesystem session store
|
|
11
|
+
* (`<workspace>/sessions`, one folder per session inside it). Physical detail
|
|
12
|
+
* only: it appears in no SDK-visible or agent-visible path.
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_SESSIONS_DIR = "sessions";
|
|
15
|
+
/**
|
|
16
|
+
* Thrown when a `sessionId` cannot own a session folder: it would address storage
|
|
17
|
+
* outside the session zone (absolute or `..` traversal), or it collides with a name
|
|
18
|
+
* reserved at the workspace root. The latter matters because session state is
|
|
19
|
+
* addressed as `<sessionId>/…` at the root — a session called `skills` would route
|
|
20
|
+
* its own checkpoints into the authored `skills/` mount. Deletion is also the
|
|
21
|
+
* one session operation that touches real `node:fs` directly (bypassing the
|
|
22
|
+
* backend's virtual mode), so it must contain its target itself.
|
|
23
|
+
*/
|
|
24
|
+
export class SessionStoreIdError extends Error {
|
|
25
|
+
sessionId;
|
|
26
|
+
constructor(sessionId, reason = "it must stay within the session zone (no absolute paths or '..' traversal)") {
|
|
27
|
+
super(`Invalid session id ${JSON.stringify(sessionId)}: ${reason}.`);
|
|
28
|
+
this.sessionId = sessionId;
|
|
29
|
+
this.name = "SessionStoreIdError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Strip leading slashes to the store-relative form. */
|
|
33
|
+
export function storeRelativeSessionId(sessionId) {
|
|
34
|
+
return String(sessionId).replace(/^\/+/, "");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Why a session id cannot own a session folder, or `null` when it can: non-empty
|
|
38
|
+
* once leading slashes are stripped, free of `..` traversal segments, and with a
|
|
39
|
+
* first segment that is not reserved at the workspace root. Exposed so
|
|
40
|
+
* untrusted-id ingress points (the CLI, `invoke`, session handles, a host's own
|
|
41
|
+
* API) can reject a bad id up front with their own message, rather than relying
|
|
42
|
+
* on a store throwing deep inside a delete.
|
|
43
|
+
*/
|
|
44
|
+
export function sessionIdRejection(sessionId, mountPrefixes) {
|
|
45
|
+
const relative = storeRelativeSessionId(sessionId);
|
|
46
|
+
const segments = relative.split(/[\\/]+/);
|
|
47
|
+
if (relative === "")
|
|
48
|
+
return "it must not be empty";
|
|
49
|
+
if (segments.some((segment) => segment === "..")) {
|
|
50
|
+
return "it must stay within the session zone (no absolute paths or '..' traversal)";
|
|
51
|
+
}
|
|
52
|
+
// Session areas are the framework's own namespace, so they are always reserved.
|
|
53
|
+
// Mount names are workspace shape: reserved once the caller supplies the
|
|
54
|
+
// resolved mount keys (assembly does). Without it a colliding authored name
|
|
55
|
+
// still fails safely — the read-only mount refuses the write.
|
|
56
|
+
if (isReservedRootName(segments[0], mountPrefixes)) {
|
|
57
|
+
return `'${segments[0]}' is reserved at the workspace root (a session area or an authored mount)`;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=session-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-id.js","sourceRoot":"","sources":["../../src/core/session-id.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAsB,MAAM,YAAY,CAAC;AAEpE;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAEjC;IADX,YACW,SAAiB,EAC1B,MAAM,GAAG,4EAA4E;QAErF,KAAK,CAAC,sBAAsB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC;QAH5D,cAAS,GAAT,SAAS,CAAQ;QAI1B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,wDAAwD;AACxD,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,aAA6B;IAE7B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,sBAAsB,CAAC;IACnD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC;QACjD,OAAO,4EAA4E,CAAC;IACtF,CAAC;IACD,gFAAgF;IAChF,yEAAyE;IACzE,4EAA4E;IAC5E,8DAA8D;IAC9D,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC;QACnD,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,2EAA2E,CAAC;IACpG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type BackendProtocolV2 } from "deepagents";
|
|
2
|
+
import { DEFAULT_SESSIONS_DIR, SessionStoreIdError, sessionIdRejection } from "./session-id.js";
|
|
3
|
+
/**
|
|
4
|
+
* Consumer-owned physical storage for the session zone — the agent's workspace root.
|
|
5
|
+
*
|
|
6
|
+
* The ownership boundary: the SDK owns the *logical* session namespace — the
|
|
7
|
+
* per-session `<sessionId>/…` layout, reserved areas (`checkpoints/`,
|
|
8
|
+
* `artifacts/`, `scratchpad/`, `large_tool_results/`,
|
|
9
|
+
* `conversation_history/`), the session-agnostic `_specs/` prefix, session-scoped
|
|
10
|
+
* path routing, and lazy creation — while the consumer owns the *physical*
|
|
11
|
+
* storage: which backend, under what prefix/tenancy, how durable, and for how
|
|
12
|
+
* long. A `SessionStore` is that consumer-side choice, made explicitly (or by the
|
|
13
|
+
* documented zero-config default) and mounted exactly once.
|
|
14
|
+
*/
|
|
15
|
+
export { DEFAULT_SESSIONS_DIR, SessionStoreIdError, sessionIdRejection };
|
|
16
|
+
export interface SessionStoreCapabilities {
|
|
17
|
+
/** Whether the store can enumerate session folders (`sessions.list()`). */
|
|
18
|
+
list: boolean;
|
|
19
|
+
/** Whether the store can remove a session's content (`sessions.delete()`). */
|
|
20
|
+
delete: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface SessionStore {
|
|
23
|
+
/** Store flavor for diagnostics and error messages. */
|
|
24
|
+
kind: "filesystem" | "backend" | "memory";
|
|
25
|
+
/**
|
|
26
|
+
* Backend serving the session zone. The SDK wraps it in a `SessionZoneRouter`
|
|
27
|
+
* (session-scoped, id-free addressing) and mounts it on the workspace
|
|
28
|
+
* `CompositeBackend`; consumers never address it directly.
|
|
29
|
+
*/
|
|
30
|
+
backend: BackendProtocolV2;
|
|
31
|
+
capabilities: SessionStoreCapabilities;
|
|
32
|
+
/**
|
|
33
|
+
* Remove everything stored under a session's namespace. Returns whether
|
|
34
|
+
* anything was removed. Throws {@link SessionStoreCapabilityError} when the
|
|
35
|
+
* store cannot delete (see {@link SessionStoreCapabilities.delete}).
|
|
36
|
+
*/
|
|
37
|
+
deleteSession(sessionId: string): Promise<boolean>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Thrown at assembly when a custom authored `backend` is supplied without an
|
|
41
|
+
* explicit `sessionStore`. The runtime never silently runs without session-scoped
|
|
42
|
+
* routing and never silently writes session state to local disk beside a
|
|
43
|
+
* virtual workspace — the consumer must name the storage.
|
|
44
|
+
*/
|
|
45
|
+
export declare class SessionStoreRequiredError extends Error {
|
|
46
|
+
constructor();
|
|
47
|
+
}
|
|
48
|
+
/** Thrown when a session operation needs a capability the configured store lacks. */
|
|
49
|
+
export declare class SessionStoreCapabilityError extends Error {
|
|
50
|
+
readonly storeKind: string;
|
|
51
|
+
readonly capability: keyof SessionStoreCapabilities;
|
|
52
|
+
constructor(storeKind: string, capability: keyof SessionStoreCapabilities);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Local-directory session store: a filesystem backend rooted at `dir`, with full
|
|
56
|
+
* listing and deletion capabilities. The zero-config default is this store at
|
|
57
|
+
* `<workspaceRoot>/sessions`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createFilesystemSessionStore(options: {
|
|
60
|
+
dir: string;
|
|
61
|
+
}): SessionStore;
|
|
62
|
+
/**
|
|
63
|
+
* Session store over any {@link BackendProtocolV2} (object storage, database,
|
|
64
|
+
* remote). The `prefix` is the consumer's tenancy/layout concern: it is
|
|
65
|
+
* applied inside the store and never appears in SDK-visible or agent-visible
|
|
66
|
+
* paths. Deletion is available only when the consumer supplies a
|
|
67
|
+
* `deleteSession` implementation (the backend protocol models no delete);
|
|
68
|
+
* listing can be disabled for backends whose `ls` cannot enumerate folders.
|
|
69
|
+
*/
|
|
70
|
+
export declare function createBackendSessionStore(options: {
|
|
71
|
+
backend: BackendProtocolV2;
|
|
72
|
+
prefix?: string;
|
|
73
|
+
/** Remove `<prefix>/<sessionId>/…` from the underlying storage. */
|
|
74
|
+
deleteSession?: (sessionId: string) => Promise<boolean>;
|
|
75
|
+
/** Whether the backend's `ls` can enumerate session folders (default true). */
|
|
76
|
+
list?: boolean;
|
|
77
|
+
}): SessionStore;
|
|
78
|
+
/**
|
|
79
|
+
* Ephemeral in-memory session store for tests and throwaway sessions: Deep
|
|
80
|
+
* Agents' own `StoreBackend` over a LangGraph `InMemoryStore`, so nothing
|
|
81
|
+
* touches the filesystem or any external service, and everything vanishes with
|
|
82
|
+
* the process. Overwrites in place like every Deep Agents backend from
|
|
83
|
+
* deepagents 1.12.0 on; fully listable and deletable.
|
|
84
|
+
*/
|
|
85
|
+
export declare function createMemorySessionStore(): SessionStore;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { resolve, sep } from "node:path";
|
|
3
|
+
import { InMemoryStore } from "@langchain/langgraph-checkpoint";
|
|
4
|
+
import { FilesystemBackend, StoreBackend } from "deepagents";
|
|
5
|
+
import { mountSubtree } from "./path-mapping.js";
|
|
6
|
+
import { DEFAULT_SESSIONS_DIR, SessionStoreIdError, sessionIdRejection, storeRelativeSessionId as rel, } from "./session-id.js";
|
|
7
|
+
/**
|
|
8
|
+
* Consumer-owned physical storage for the session zone — the agent's workspace root.
|
|
9
|
+
*
|
|
10
|
+
* The ownership boundary: the SDK owns the *logical* session namespace — the
|
|
11
|
+
* per-session `<sessionId>/…` layout, reserved areas (`checkpoints/`,
|
|
12
|
+
* `artifacts/`, `scratchpad/`, `large_tool_results/`,
|
|
13
|
+
* `conversation_history/`), the session-agnostic `_specs/` prefix, session-scoped
|
|
14
|
+
* path routing, and lazy creation — while the consumer owns the *physical*
|
|
15
|
+
* storage: which backend, under what prefix/tenancy, how durable, and for how
|
|
16
|
+
* long. A `SessionStore` is that consumer-side choice, made explicitly (or by the
|
|
17
|
+
* documented zero-config default) and mounted exactly once.
|
|
18
|
+
*/
|
|
19
|
+
// The id vocabulary is pure and lives in `session-id.ts`; re-exported so the
|
|
20
|
+
// stores and the rule they enforce are reached from one module.
|
|
21
|
+
export { DEFAULT_SESSIONS_DIR, SessionStoreIdError, sessionIdRejection };
|
|
22
|
+
/**
|
|
23
|
+
* Thrown at assembly when a custom authored `backend` is supplied without an
|
|
24
|
+
* explicit `sessionStore`. The runtime never silently runs without session-scoped
|
|
25
|
+
* routing and never silently writes session state to local disk beside a
|
|
26
|
+
* virtual workspace — the consumer must name the storage.
|
|
27
|
+
*/
|
|
28
|
+
export class SessionStoreRequiredError extends Error {
|
|
29
|
+
constructor() {
|
|
30
|
+
super("A custom `backend` requires an explicit `sessionStore` for session state " +
|
|
31
|
+
"(checkpoints, artifacts, output, scratch). Pass one of: " +
|
|
32
|
+
"createFilesystemSessionStore({ dir }), createBackendSessionStore({ backend, prefix? }), " +
|
|
33
|
+
"or createMemorySessionStore().");
|
|
34
|
+
this.name = "SessionStoreRequiredError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Thrown when a session operation needs a capability the configured store lacks. */
|
|
38
|
+
export class SessionStoreCapabilityError extends Error {
|
|
39
|
+
storeKind;
|
|
40
|
+
capability;
|
|
41
|
+
constructor(storeKind, capability) {
|
|
42
|
+
super(`The configured ${storeKind} session store does not support '${capability}'. ` +
|
|
43
|
+
`Provide a store with that capability (e.g. createFilesystemSessionStore) to use it.`);
|
|
44
|
+
this.storeKind = storeKind;
|
|
45
|
+
this.capability = capability;
|
|
46
|
+
this.name = "SessionStoreCapabilityError";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Store-relative session id with traversal and reserved names contained: strips
|
|
51
|
+
* leading slashes, then rejects any id that would resolve outside its zone or
|
|
52
|
+
* shadow a reserved root name. Callers pass the id straight to `rmSync`/subtree
|
|
53
|
+
* deletion and to root-relative run paths, so this is the single point that keeps
|
|
54
|
+
* both inside the session zone.
|
|
55
|
+
*/
|
|
56
|
+
function containedSessionId(sessionId) {
|
|
57
|
+
const rejection = sessionIdRejection(sessionId);
|
|
58
|
+
if (rejection)
|
|
59
|
+
throw new SessionStoreIdError(sessionId, rejection);
|
|
60
|
+
return rel(sessionId);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Local-directory session store: a filesystem backend rooted at `dir`, with full
|
|
64
|
+
* listing and deletion capabilities. The zero-config default is this store at
|
|
65
|
+
* `<workspaceRoot>/sessions`.
|
|
66
|
+
*/
|
|
67
|
+
export function createFilesystemSessionStore(options) {
|
|
68
|
+
const dir = resolve(options.dir);
|
|
69
|
+
return {
|
|
70
|
+
kind: "filesystem",
|
|
71
|
+
backend: new FilesystemBackend({ rootDir: dir, virtualMode: true }),
|
|
72
|
+
capabilities: { list: true, delete: true },
|
|
73
|
+
async deleteSession(sessionId) {
|
|
74
|
+
const target = resolve(dir, containedSessionId(sessionId));
|
|
75
|
+
// Belt-and-suspenders: even with `..` rejected, assert the resolved path
|
|
76
|
+
// stays strictly under `dir` before touching real `fs`.
|
|
77
|
+
if (target !== dir && !target.startsWith(dir + sep)) {
|
|
78
|
+
throw new SessionStoreIdError(sessionId);
|
|
79
|
+
}
|
|
80
|
+
if (target === dir || !existsSync(target))
|
|
81
|
+
return false;
|
|
82
|
+
rmSync(target, { recursive: true, force: true });
|
|
83
|
+
return true;
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Session store over any {@link BackendProtocolV2} (object storage, database,
|
|
89
|
+
* remote). The `prefix` is the consumer's tenancy/layout concern: it is
|
|
90
|
+
* applied inside the store and never appears in SDK-visible or agent-visible
|
|
91
|
+
* paths. Deletion is available only when the consumer supplies a
|
|
92
|
+
* `deleteSession` implementation (the backend protocol models no delete);
|
|
93
|
+
* listing can be disabled for backends whose `ls` cannot enumerate folders.
|
|
94
|
+
*/
|
|
95
|
+
export function createBackendSessionStore(options) {
|
|
96
|
+
const prefix = options.prefix ? rel(options.prefix).replace(/\/+$/, "") : "";
|
|
97
|
+
const backend = prefix ? mountSubtree(options.backend, prefix) : options.backend;
|
|
98
|
+
const capabilities = {
|
|
99
|
+
list: options.list ?? true,
|
|
100
|
+
delete: options.deleteSession !== undefined,
|
|
101
|
+
};
|
|
102
|
+
return {
|
|
103
|
+
kind: "backend",
|
|
104
|
+
backend,
|
|
105
|
+
capabilities,
|
|
106
|
+
async deleteSession(sessionId) {
|
|
107
|
+
if (!options.deleteSession)
|
|
108
|
+
throw new SessionStoreCapabilityError("backend", "delete");
|
|
109
|
+
return options.deleteSession(sessionId);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Ephemeral in-memory session store for tests and throwaway sessions: Deep
|
|
115
|
+
* Agents' own `StoreBackend` over a LangGraph `InMemoryStore`, so nothing
|
|
116
|
+
* touches the filesystem or any external service, and everything vanishes with
|
|
117
|
+
* the process. Overwrites in place like every Deep Agents backend from
|
|
118
|
+
* deepagents 1.12.0 on; fully listable and deletable.
|
|
119
|
+
*/
|
|
120
|
+
export function createMemorySessionStore() {
|
|
121
|
+
const store = new InMemoryStore();
|
|
122
|
+
const namespace = ["sessions"];
|
|
123
|
+
const backend = new StoreBackend({ store, namespace });
|
|
124
|
+
return {
|
|
125
|
+
kind: "memory",
|
|
126
|
+
backend,
|
|
127
|
+
capabilities: { list: true, delete: true },
|
|
128
|
+
async deleteSession(sessionId) {
|
|
129
|
+
const id = containedSessionId(sessionId);
|
|
130
|
+
// Collect first, then delete: the store's pagination is by offset.
|
|
131
|
+
const keys = [];
|
|
132
|
+
const limit = 500;
|
|
133
|
+
for (let offset = 0;; offset += limit) {
|
|
134
|
+
const page = await store.search(namespace, { limit, offset });
|
|
135
|
+
for (const item of page) {
|
|
136
|
+
const key = String(item.key);
|
|
137
|
+
if (key === `/${id}` || key.startsWith(`/${id}/`) || key === id || key.startsWith(`${id}/`)) {
|
|
138
|
+
keys.push(key);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (page.length < limit)
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
await Promise.all(keys.map((key) => store.delete(namespace, key)));
|
|
145
|
+
return keys.length > 0;
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/core/session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { BackendProtocolV2 } from "deepagents";
|
|
2
|
+
/**
|
|
3
|
+
* The session zone — the agent's workspace **root**: durable per-session
|
|
4
|
+
* checkpoints, observability artifacts, the agent's `scratchpad/…` working area, the
|
|
5
|
+
* always-writable `scratchpad/…`, and the runtime's context-offload areas, all
|
|
6
|
+
* served by the configured session store as the default route of the workspace
|
|
7
|
+
* `CompositeBackend`.
|
|
8
|
+
*
|
|
9
|
+
* Three calling conventions share this one root, disambiguated by path shape
|
|
10
|
+
* rather than by whether a session happens to be bound:
|
|
11
|
+
*
|
|
12
|
+
* - **Runtime-internal, already-qualified paths** (e.g.
|
|
13
|
+
* `<sessionId>/checkpoints/cp-1.json`, built by `sessionPaths`) — the
|
|
14
|
+
* checkpoint saver and run-artifact writers address their own session's
|
|
15
|
+
* folder explicitly. These pass through unmodified, whether or not a session
|
|
16
|
+
* happens to be bound at the time (some, like the inner Deep Agent's own
|
|
17
|
+
* checkpoint writes, run *during* a bound turn; others, like
|
|
18
|
+
* `listSessions()`, run outside any turn).
|
|
19
|
+
* - **Session-agnostic reserved paths** (`_specs/<hash>.json`) — content
|
|
20
|
+
* addressed and shared by every session on the same spec version, so they
|
|
21
|
+
* resolve at the store root even while a session is bound.
|
|
22
|
+
* - **Agent-visible, id-free paths** (e.g. `scratchpad/notes.txt`) — issued by
|
|
23
|
+
* tool calls while a session's turn is executing. The currently bound
|
|
24
|
+
* session id (see {@link sessionScoped}) is prefixed on before delegating, and
|
|
25
|
+
* stripped back off the paths results carry, so the id never appears in an
|
|
26
|
+
* agent-visible listing.
|
|
27
|
+
*
|
|
28
|
+
* A path is treated as "already qualified" when it (ignoring a leading `/`)
|
|
29
|
+
* equals or starts with the bound session id — safe because internal callers
|
|
30
|
+
* only ever address their own currently-bound session's folder, and a session id
|
|
31
|
+
* may not collide with a reserved root name.
|
|
32
|
+
*/
|
|
33
|
+
export declare class SessionZoneRouter implements BackendProtocolV2 {
|
|
34
|
+
private readonly binding;
|
|
35
|
+
private readonly routed;
|
|
36
|
+
constructor(backend: BackendProtocolV2);
|
|
37
|
+
/**
|
|
38
|
+
* Bind id-free run-root addressing to `sessionId` for everything `fn` does
|
|
39
|
+
* (the binding propagates through async continuations, so a whole agent
|
|
40
|
+
* turn — including lifecycle hooks, sandboxed scripts, and the inner
|
|
41
|
+
* agent's own checkpoint writes — is covered by wrapping its `invoke`).
|
|
42
|
+
* Concurrent sessions each carry their own binding.
|
|
43
|
+
*/
|
|
44
|
+
sessionScoped<T>(sessionId: string, fn: () => Promise<T>): Promise<T>;
|
|
45
|
+
/** The session id bound to the current async context, if any. */
|
|
46
|
+
boundSessionId(): string | undefined;
|
|
47
|
+
ls(path: string): import("deepagents").MaybePromise<import("deepagents").LsResult>;
|
|
48
|
+
read(filePath: string, offset?: number, limit?: number): import("deepagents").MaybePromise<import("deepagents").ReadResult>;
|
|
49
|
+
readRaw(filePath: string): import("deepagents").MaybePromise<import("deepagents").ReadRawResult>;
|
|
50
|
+
grep(pattern: string, path?: string | null, glob?: string | null): import("deepagents").MaybePromise<import("deepagents").GrepResult>;
|
|
51
|
+
glob(pattern: string, path?: string): import("deepagents").MaybePromise<import("deepagents").GlobResult>;
|
|
52
|
+
write(filePath: string, content: string): import("deepagents").MaybePromise<import("deepagents").WriteResult>;
|
|
53
|
+
edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): import("deepagents").MaybePromise<import("deepagents").EditResult>;
|
|
54
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { mountSubtree } from "./path-mapping.js";
|
|
3
|
+
import { isSessionAgnosticPath } from "./zones.js";
|
|
4
|
+
/**
|
|
5
|
+
* The session zone — the agent's workspace **root**: durable per-session
|
|
6
|
+
* checkpoints, observability artifacts, the agent's `scratchpad/…` working area, the
|
|
7
|
+
* always-writable `scratchpad/…`, and the runtime's context-offload areas, all
|
|
8
|
+
* served by the configured session store as the default route of the workspace
|
|
9
|
+
* `CompositeBackend`.
|
|
10
|
+
*
|
|
11
|
+
* Three calling conventions share this one root, disambiguated by path shape
|
|
12
|
+
* rather than by whether a session happens to be bound:
|
|
13
|
+
*
|
|
14
|
+
* - **Runtime-internal, already-qualified paths** (e.g.
|
|
15
|
+
* `<sessionId>/checkpoints/cp-1.json`, built by `sessionPaths`) — the
|
|
16
|
+
* checkpoint saver and run-artifact writers address their own session's
|
|
17
|
+
* folder explicitly. These pass through unmodified, whether or not a session
|
|
18
|
+
* happens to be bound at the time (some, like the inner Deep Agent's own
|
|
19
|
+
* checkpoint writes, run *during* a bound turn; others, like
|
|
20
|
+
* `listSessions()`, run outside any turn).
|
|
21
|
+
* - **Session-agnostic reserved paths** (`_specs/<hash>.json`) — content
|
|
22
|
+
* addressed and shared by every session on the same spec version, so they
|
|
23
|
+
* resolve at the store root even while a session is bound.
|
|
24
|
+
* - **Agent-visible, id-free paths** (e.g. `scratchpad/notes.txt`) — issued by
|
|
25
|
+
* tool calls while a session's turn is executing. The currently bound
|
|
26
|
+
* session id (see {@link sessionScoped}) is prefixed on before delegating, and
|
|
27
|
+
* stripped back off the paths results carry, so the id never appears in an
|
|
28
|
+
* agent-visible listing.
|
|
29
|
+
*
|
|
30
|
+
* A path is treated as "already qualified" when it (ignoring a leading `/`)
|
|
31
|
+
* equals or starts with the bound session id — safe because internal callers
|
|
32
|
+
* only ever address their own currently-bound session's folder, and a session id
|
|
33
|
+
* may not collide with a reserved root name.
|
|
34
|
+
*/
|
|
35
|
+
export class SessionZoneRouter {
|
|
36
|
+
binding = new AsyncLocalStorage();
|
|
37
|
+
routed;
|
|
38
|
+
constructor(backend) {
|
|
39
|
+
this.routed = mountSubtree(backend, () => this.binding.getStore(), {
|
|
40
|
+
// Session-agnostic prefixes resolve to the run-store root whether or not a
|
|
41
|
+
// session is bound: a spec snapshot is shared across sessions, and the
|
|
42
|
+
// session index has to be readable before a session is chosen at all.
|
|
43
|
+
passthrough: (rel, prefix) => rel === prefix || rel.startsWith(`${prefix}/`) || isSessionAgnosticPath(rel),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Bind id-free run-root addressing to `sessionId` for everything `fn` does
|
|
48
|
+
* (the binding propagates through async continuations, so a whole agent
|
|
49
|
+
* turn — including lifecycle hooks, sandboxed scripts, and the inner
|
|
50
|
+
* agent's own checkpoint writes — is covered by wrapping its `invoke`).
|
|
51
|
+
* Concurrent sessions each carry their own binding.
|
|
52
|
+
*/
|
|
53
|
+
sessionScoped(sessionId, fn) {
|
|
54
|
+
return this.binding.run(sessionId, fn);
|
|
55
|
+
}
|
|
56
|
+
/** The session id bound to the current async context, if any. */
|
|
57
|
+
boundSessionId() {
|
|
58
|
+
return this.binding.getStore();
|
|
59
|
+
}
|
|
60
|
+
ls(path) {
|
|
61
|
+
return this.routed.ls(path);
|
|
62
|
+
}
|
|
63
|
+
read(filePath, offset, limit) {
|
|
64
|
+
return this.routed.read(filePath, offset, limit);
|
|
65
|
+
}
|
|
66
|
+
readRaw(filePath) {
|
|
67
|
+
return this.routed.readRaw(filePath);
|
|
68
|
+
}
|
|
69
|
+
grep(pattern, path, glob) {
|
|
70
|
+
return this.routed.grep(pattern, path, glob);
|
|
71
|
+
}
|
|
72
|
+
glob(pattern, path) {
|
|
73
|
+
return this.routed.glob(pattern, path);
|
|
74
|
+
}
|
|
75
|
+
write(filePath, content) {
|
|
76
|
+
return this.routed.write(filePath, content);
|
|
77
|
+
}
|
|
78
|
+
edit(filePath, oldString, newString, replaceAll) {
|
|
79
|
+
return this.routed.edit(filePath, oldString, newString, replaceAll);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=session-zone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-zone.js","sourceRoot":"","sources":["../../src/core/session-zone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,iBAAiB;IACX,OAAO,GAAG,IAAI,iBAAiB,EAAU,CAAC;IAC1C,MAAM,CAAoB;IAE3C,YAAY,OAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE;YACjE,2EAA2E;YAC3E,uEAAuE;YACvE,sEAAsE;YACtE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAC3B,GAAG,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,qBAAqB,CAAC,GAAG,CAAC;SAC/E,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,aAAa,CAAI,SAAiB,EAAE,EAAoB;QACtD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,iEAAiE;IACjE,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;IAED,EAAE,CAAC,IAAY;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,QAAgB,EAAE,MAAe,EAAE,KAAc;QACpD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,CAAC,QAAgB;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAoB,EAAE,IAAoB;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAa;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,QAAgB,EAAE,OAAe;QACrC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC,QAAgB,EAAE,SAAiB,EAAE,SAAiB,EAAE,UAAoB;QAC/E,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACtE,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SkillRegistry } from "./skills.js";
|
|
2
|
+
/**
|
|
3
|
+
* The model-facing account of the skills a state may use — rendered by the
|
|
4
|
+
* runtime rather than delegated to the upstream skills middleware.
|
|
5
|
+
*
|
|
6
|
+
* Upstream renders one section, once, from a whole source directory: its
|
|
7
|
+
* `sources` are fixed at construction and its result is cached in a closure, so
|
|
8
|
+
* nothing about it can vary per state. Under a governed workflow that is exactly
|
|
9
|
+
* the wrong shape — a state that may use one capability would be told about
|
|
10
|
+
* three, two of which the kernel refuses. So the runtime renders this instead,
|
|
11
|
+
* from the same resolved set the kernel enforces, into the **volatile** system
|
|
12
|
+
* block (see `workflow/middleware.ts`), which is where anything that changes
|
|
13
|
+
* with the state belongs.
|
|
14
|
+
*
|
|
15
|
+
* What it says is the Agent Skills progressive-disclosure contract itself and
|
|
16
|
+
* nothing more: the slug, what the skill is for, and where to read the rest.
|
|
17
|
+
*/
|
|
18
|
+
/** Heading of the rendered section, also the marker tests assert on. */
|
|
19
|
+
export declare const SKILLS_SECTION_HEADING = "Skills available in this state";
|
|
20
|
+
/**
|
|
21
|
+
* Render the section for one state's enabled skills, or `null` when the set is
|
|
22
|
+
* empty — a state that may use no skill gets no heading rather than an empty
|
|
23
|
+
* one, and therefore no invitation to go looking.
|
|
24
|
+
*
|
|
25
|
+
* `enabled` is the resolved slug order (see `WorkflowMachine.enabledSkills`), so
|
|
26
|
+
* the text is byte-identical on every model call of a turn and on every
|
|
27
|
+
* re-entry: a prompt section that reordered itself would churn the transcript
|
|
28
|
+
* for no reason. A slug with no registry entry is skipped rather than rendered
|
|
29
|
+
* as a bare name — the description is the whole value of disclosing it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function renderSkillsSection(enabled: readonly string[], registry: SkillRegistry): string | null;
|