experimental-ash 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/docs/internals/context.md +6 -5
  3. package/dist/docs/internals/core-beliefs.md +2 -2
  4. package/dist/docs/internals/hooks.md +16 -11
  5. package/dist/docs/internals/mechanical-invariants.md +4 -4
  6. package/dist/docs/internals/testing.md +1 -1
  7. package/dist/docs/public/README.md +1 -1
  8. package/dist/docs/public/auth-and-route-protection.md +12 -3
  9. package/dist/docs/public/channels/{README.md → index.md} +2 -2
  10. package/dist/docs/public/channels/slack.md +3 -3
  11. package/dist/docs/public/cli-build-and-debugging.md +1 -1
  12. package/dist/docs/public/faqs.md +4 -5
  13. package/dist/docs/public/hooks.md +18 -23
  14. package/dist/docs/public/meta.json +4 -4
  15. package/dist/docs/public/sandbox.md +51 -30
  16. package/dist/docs/public/schedules.md +1 -1
  17. package/dist/docs/public/session-context.md +26 -28
  18. package/dist/docs/public/skills.md +3 -4
  19. package/dist/docs/public/subagents.md +1 -1
  20. package/dist/docs/public/tools.md +13 -17
  21. package/dist/docs/public/typescript-api.md +10 -11
  22. package/dist/src/channel/session.d.ts +3 -29
  23. package/dist/src/channel/session.js +1 -1
  24. package/dist/src/compiled/.vendor-stamp.json +2 -2
  25. package/dist/src/compiled/@vercel/sandbox/index.d.ts +11 -2
  26. package/dist/src/compiled/@vercel/sandbox/index.js +3 -3
  27. package/dist/src/compiled/@vercel/sandbox/package.json +1 -1
  28. package/dist/src/compiled/_chunks/node/{auth-ZhCJAHxl.js → auth-CVVvWjaK.js} +1 -1
  29. package/dist/src/compiled/_chunks/node/{version-D4IYmfaS.js → version-nR4RSpFw.js} +1 -1
  30. package/dist/src/context/build-callback-context.d.ts +8 -0
  31. package/dist/src/context/build-callback-context.js +1 -0
  32. package/dist/src/context/hook-lifecycle.js +1 -1
  33. package/dist/src/execution/node-step.js +1 -1
  34. package/dist/src/execution/sandbox/bash-tool.d.ts +2 -1
  35. package/dist/src/execution/sandbox/bash-tool.js +1 -1
  36. package/dist/src/execution/sandbox/bindings/vercel.d.ts +1 -1
  37. package/dist/src/execution/sandbox/glob-tool.d.ts +2 -1
  38. package/dist/src/execution/sandbox/glob-tool.js +3 -3
  39. package/dist/src/execution/sandbox/grep-tool.d.ts +2 -1
  40. package/dist/src/execution/sandbox/grep-tool.js +3 -3
  41. package/dist/src/execution/sandbox/read-file-tool.d.ts +2 -1
  42. package/dist/src/execution/sandbox/read-file-tool.js +1 -1
  43. package/dist/src/execution/sandbox/session.js +1 -1
  44. package/dist/src/execution/sandbox/write-file-tool.d.ts +2 -1
  45. package/dist/src/execution/sandbox/write-file-tool.js +1 -1
  46. package/dist/src/execution/tool-compaction.js +1 -1
  47. package/dist/src/harness/code-mode-approval.js +1 -1
  48. package/dist/src/harness/code-mode.js +1 -1
  49. package/dist/src/harness/tool-loop.js +1 -1
  50. package/dist/src/internal/application/package.js +1 -1
  51. package/dist/src/internal/logging.js +1 -1
  52. package/dist/src/internal/workflow-bundle/builder.js +2 -2
  53. package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/index.js +1 -1
  54. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/manager.js +1 -0
  55. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/worker-source.js +408 -0
  56. package/dist/src/packages/ash-scaffold/src/channels.js +2 -12
  57. package/dist/src/packages/ash-scaffold/src/pnpm-workspace.js +11 -0
  58. package/dist/src/packages/ash-scaffold/src/project.js +1 -1
  59. package/dist/src/packages/ash-scaffold/src/web-template.js +2 -2
  60. package/dist/src/public/channels/auth.d.ts +22 -11
  61. package/dist/src/public/channels/auth.js +1 -1
  62. package/dist/src/public/context/index.d.ts +3 -2
  63. package/dist/src/public/context/index.js +1 -1
  64. package/dist/src/public/definitions/callback-context.d.ts +22 -0
  65. package/dist/src/public/definitions/callback-context.js +1 -0
  66. package/dist/src/public/definitions/hook.d.ts +9 -49
  67. package/dist/src/public/definitions/sandbox.d.ts +1 -1
  68. package/dist/src/public/definitions/tool.d.ts +14 -15
  69. package/dist/src/public/hooks/index.d.ts +1 -1
  70. package/dist/src/public/sandbox/index.d.ts +1 -2
  71. package/dist/src/public/sandbox/index.js +1 -1
  72. package/dist/src/public/sandbox/vercel-sandbox.d.ts +4 -4
  73. package/dist/src/public/skills/index.d.ts +0 -1
  74. package/dist/src/public/skills/index.js +1 -1
  75. package/dist/src/public/tools/defaults.js +1 -1
  76. package/dist/src/public/tools/define-bash-tool.js +1 -1
  77. package/dist/src/public/tools/define-glob-tool.js +1 -1
  78. package/dist/src/public/tools/define-grep-tool.js +1 -1
  79. package/dist/src/public/tools/define-read-file-tool.js +1 -1
  80. package/dist/src/public/tools/define-write-file-tool.js +1 -1
  81. package/dist/src/public/tools/index.d.ts +2 -1
  82. package/dist/src/public/tools/internal.d.ts +4 -0
  83. package/dist/src/public/tools/internal.js +1 -1
  84. package/dist/src/runtime/framework-tools/bash.js +1 -1
  85. package/dist/src/runtime/framework-tools/connection-search.js +1 -1
  86. package/dist/src/runtime/framework-tools/connection-tools.js +1 -1
  87. package/dist/src/runtime/framework-tools/file-state.d.ts +2 -2
  88. package/dist/src/runtime/framework-tools/file-state.js +1 -1
  89. package/dist/src/runtime/framework-tools/glob.js +1 -1
  90. package/dist/src/runtime/framework-tools/grep.js +1 -1
  91. package/dist/src/runtime/framework-tools/read-file.js +2 -2
  92. package/dist/src/runtime/framework-tools/todo.js +1 -1
  93. package/dist/src/runtime/framework-tools/write-file.js +1 -1
  94. package/dist/src/runtime/governance/auth/oidc.js +1 -1
  95. package/dist/src/runtime/governance/auth/token-claims.d.ts +2 -0
  96. package/dist/src/runtime/governance/auth/token-claims.js +1 -1
  97. package/dist/src/runtime/governance/auth/types.d.ts +6 -0
  98. package/dist/src/runtime/types.d.ts +2 -2
  99. package/dist/src/shared/sandbox-session.d.ts +0 -17
  100. package/package.json +3 -3
  101. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/manager.js +0 -1
  102. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/worker-source.js +0 -1153
  103. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime-assets.js +0 -1
  104. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js +0 -0
  105. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/approval-response.js +0 -0
  106. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/code-mode-tool.js +0 -0
  107. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/continuation-capability.js +0 -0
  108. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/errors.js +0 -0
  109. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/fetch-policy.js +0 -0
  110. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/host-interrupt.js +0 -0
  111. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/interrupt-continuation.js +0 -0
  112. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/options.js +0 -0
  113. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/run-code-mode.js +0 -0
  114. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/runtime/max-workers.js +0 -0
  115. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/serialization.js +0 -0
  116. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/source-cache.js +0 -0
  117. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/telemetry.js +0 -0
  118. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/tool-invocation.js +0 -0
  119. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/tool-prompt.js +0 -0
@@ -162,7 +162,7 @@ When a schedule fires, the dispatcher takes one of two paths:
162
162
  2. The agent runs in **task mode** with the app principal.
163
163
  3. Output is discarded.
164
164
 
165
- In both cases, the schedule session uses the **app principal**: `getSession().auth.current` and `getSession().auth.initiator` are set to `"ash:app"` with `principalType: "runtime"`.
165
+ In both cases, the schedule session uses the **app principal**: `ctx.session.auth.current` and `ctx.session.auth.initiator` are set to `"ash:app"` with `principalType: "runtime"`.
166
166
 
167
167
  The session goes through the same durable runtime engine as any other Ash session.
168
168
 
@@ -1,42 +1,40 @@
1
1
  ---
2
2
  title: "Session Context"
3
- description: "Runtime helpers: getSession, getSandbox, getSkill, and defineState."
3
+ description: "Runtime helpers: ctx.session, ctx.getSandbox, ctx.getSkill, and defineState."
4
4
  ---
5
5
 
6
- Ash exposes runtime helpers for authored code:
6
+ Ash exposes runtime state through the `ctx` parameter passed to tool `execute`, hook handlers,
7
+ and channel event handlers:
7
8
 
8
- - `getSession()`
9
- - `getSandbox()`
10
- - `getSkill(identifier)`
11
- - `defineState(name, initial)` -- typed durable state with `get()` and `update()`
9
+ - `ctx.session` -- session metadata, turn, auth, and parent lineage
10
+ - `ctx.getSandbox()` -- live sandbox handle for the current agent
11
+ - `ctx.getSkill(identifier)` -- handle for a named skill visible to the current agent
12
+ - `defineState(name, initial)` -- typed durable state with `get()` and `update()` (imported from `"experimental-ash/context"`)
12
13
 
13
14
  These APIs work only inside active authored runtime execution such as tools, channel event
14
15
  handlers, and authored hooks. They throw when called outside a managed context.
15
16
 
16
- ## `getSession()`
17
+ ## `ctx.session`
17
18
 
18
- Use `getSession()` when you need durable runtime metadata about the current execution.
19
+ Use `ctx.session` when you need durable runtime metadata about the current execution.
19
20
 
20
21
  `agent/tools/who_called_me.ts`
21
22
 
22
23
  ```ts
23
- import { getSession } from "experimental-ash/context";
24
24
  import { defineTool } from "experimental-ash/tools";
25
25
  import { z } from "zod";
26
26
 
27
27
  export default defineTool({
28
28
  description: "Return the active session metadata.",
29
29
  inputSchema: z.object({}),
30
- async execute() {
31
- const session = getSession();
32
-
30
+ async execute(_input, ctx) {
33
31
  return {
34
- sessionId: session.sessionId,
35
- turnId: session.turn.id,
36
- turnSequence: session.turn.sequence,
37
- currentCaller: session.auth.current?.principalId,
38
- initiator: session.auth.initiator?.principalId,
39
- parentSessionId: session.parent?.sessionId,
32
+ sessionId: ctx.session.id,
33
+ turnId: ctx.session.turn.id,
34
+ turnSequence: ctx.session.turn.sequence,
35
+ currentCaller: ctx.session.auth.current?.principalId,
36
+ initiator: ctx.session.auth.initiator?.principalId,
37
+ parentSessionId: ctx.session.parent?.id,
40
38
  };
41
39
  },
42
40
  });
@@ -46,7 +44,7 @@ Public session fields:
46
44
 
47
45
  - `auth.current`
48
46
  - `auth.initiator`
49
- - `sessionId`
47
+ - `id`
50
48
  - `turn.id`
51
49
  - `turn.sequence`
52
50
  - optional `parent`
@@ -59,13 +57,13 @@ Important behavior:
59
57
  - top-level schedule sessions expose the framework app principal (`principalId: "ash:app"`, `principalType: "runtime"`)
60
58
  - `parent` is present for child subagent sessions
61
59
 
62
- ## `getSandbox()`
60
+ ## `ctx.getSandbox()`
63
61
 
64
- `getSandbox()` returns a live handle for the current agent's sandbox.
62
+ `ctx.getSandbox()` returns a live handle for the current agent's sandbox.
65
63
 
66
64
  ```ts
67
- const sandbox = await getSandbox();
68
- const result = await sandbox.runCommand("pnpm test");
65
+ const sandbox = await ctx.getSandbox();
66
+ const result = await sandbox.run({ command: "pnpm test" });
69
67
  ```
70
68
 
71
69
  Important behavior:
@@ -81,12 +79,12 @@ child process.
81
79
 
82
80
  See [Sandboxes](./sandbox.md) for lifecycle details.
83
81
 
84
- ## `getSkill(identifier)`
82
+ ## `ctx.getSkill(identifier)`
85
83
 
86
- `getSkill(identifier)` returns a handle for a named skill visible to the current agent.
84
+ `ctx.getSkill(identifier)` returns a handle for a named skill visible to the current agent.
87
85
 
88
86
  ```ts
89
- const skill = getSkill("research");
87
+ const skill = ctx.getSkill("research");
90
88
  const notes = await skill.file("references/checklist.md").text();
91
89
  ```
92
90
 
@@ -151,7 +149,7 @@ import { budget } from "../lib/budget.js";
151
149
 
152
150
  export default defineHook({
153
151
  lifecycle: {
154
- turn() {
152
+ turn(ctx) {
155
153
  // Reset budget each turn
156
154
  budget.update(() => ({ count: 0, cap: 25 }));
157
155
  },
@@ -175,7 +173,7 @@ export default defineHook({
175
173
 
176
174
  Safe places:
177
175
 
178
- - inside `defineTool(...).execute(...)`
176
+ - inside `defineTool(...).execute(input, ctx)`
179
177
  - inside authored callbacks Ash runs inside the runtime
180
178
  - after asynchronous boundaries inside the same authored execution chain
181
179
 
@@ -77,18 +77,17 @@ Packaged skills are useful when you want files like:
77
77
  - `scripts/`
78
78
  - example inputs or templates
79
79
 
80
- Inside authored runtime code, you can read those packaged files through `getSkill(identifier)`.
80
+ Inside authored runtime code, you can read those packaged files through `ctx.getSkill(identifier)`.
81
81
 
82
82
  ```ts
83
- import { getSkill } from "experimental-ash/skills";
84
83
  import { defineTool } from "experimental-ash/tools";
85
84
  import { z } from "zod";
86
85
 
87
86
  export default defineTool({
88
87
  description: "Load a packaged skill reference file.",
89
88
  inputSchema: z.object({}),
90
- async execute() {
91
- const research = getSkill("research");
89
+ async execute(_input, ctx) {
90
+ const research = ctx.getSkill("research");
92
91
  return await research.file("references/checklist.md").text();
93
92
  },
94
93
  });
@@ -108,7 +108,7 @@ Subagent execution gets:
108
108
  - its own tools
109
109
  - its own sandbox (independent of the parent's sandbox)
110
110
  - its own `skills/` set (independent of the parent's skills)
111
- - immediate parent lineage in `getSession().parent`
111
+ - immediate parent lineage in `ctx.session.parent`
112
112
 
113
113
  Skills and sandboxes do not cross the parent/child boundary. The subagent only sees skills
114
114
  authored under `agent/subagents/<id>/skills/`; skills under the root `agent/skills/` are not
@@ -13,7 +13,6 @@ back.
13
13
  `agent/tools/get_weather.ts`
14
14
 
15
15
  ```ts
16
- import { getSession } from "experimental-ash/context";
17
16
  import { defineTool } from "experimental-ash/tools";
18
17
  import { z } from "zod";
19
18
 
@@ -22,12 +21,10 @@ export default defineTool({
22
21
  inputSchema: z.object({
23
22
  city: z.string(),
24
23
  }),
25
- async execute(input) {
26
- const session = getSession();
27
-
24
+ async execute(input, ctx) {
28
25
  return {
29
26
  city: input.city,
30
- sessionId: session.sessionId,
27
+ sessionId: ctx.session.id,
31
28
  temperatureF: 72,
32
29
  };
33
30
  },
@@ -40,17 +37,17 @@ There is no `name` override and no compile-time normalization — if you want a
40
37
  identifier, name the file in snake_case.
41
38
 
42
39
  `defineTool`, `disableTool`, `defineBashTool`, `defineReadFileTool`, and `defineWriteFileTool` live on the `experimental-ash/tools` subpath.
43
- Runtime context helpers (`getSession`, `defineState`) live on `experimental-ash/context`.
44
- `getSandbox` lives on `experimental-ash/sandbox` and `getSkill` lives on `experimental-ash/skills`.
40
+ `defineState` lives on `experimental-ash/context`. Session metadata, sandbox access, and skill access
41
+ are available through the `ctx` parameter passed to `execute`.
45
42
 
46
43
  ## What A Tool Definition Needs
47
44
 
48
45
  - a filename slug under `agent/tools/` (this is the model-facing tool name)
49
46
  - `description`
50
47
  - `inputSchema` — a Zod schema (or any Standard Schema). Required, matching the AI SDK's `Tool` contract. For a tool with no input, pass `z.object({})`.
51
- - `execute(input, options?)` — the tool's implementation. `options` provides `toolCallId`, `messages`, and `abortSignal` from the AI SDK.
48
+ - `execute(input, ctx)` — the tool's implementation. `ctx` provides session metadata, sandbox access, and skill access.
52
49
 
53
- The AI SDK uses `inputSchema` to validate and transform model input (including Zod defaults) and to type `execute(input)`.
50
+ The AI SDK uses `inputSchema` to validate and transform model input (including Zod defaults) and to type the `input` parameter in `execute(input, ctx)`.
54
51
 
55
52
  ## Schemas
56
53
 
@@ -75,14 +72,13 @@ export default defineTool({
75
72
 
76
73
  ## Runtime Helpers Inside Tools
77
74
 
78
- Tools are the most common place to use Ash's runtime helpers:
75
+ The `ctx` parameter passed to `execute` is the primary way to access runtime state:
79
76
 
80
- - `getSession()` for session, turn, auth, and parent lineage data
81
- - `getSandbox()` for the live sandbox handle
82
- - `getSkill(identifier)` for reading skill metadata and packaged skill files
77
+ - `ctx.session` for session metadata, turn, auth, and parent lineage data
78
+ - `ctx.getSandbox()` for the live sandbox handle
79
+ - `ctx.getSkill(identifier)` for reading skill metadata and packaged skill files
83
80
 
84
- Those APIs only work inside active authored runtime execution. They throw during top-level module
85
- evaluation.
81
+ These are available inside `execute` and other active authored runtime execution contexts.
86
82
 
87
83
  ## When A Tool Runs
88
84
 
@@ -131,9 +127,9 @@ import { bash } from "experimental-ash/tools/defaults";
131
127
 
132
128
  export default defineTool({
133
129
  ...bash,
134
- async execute(input) {
130
+ async execute(input, ctx) {
135
131
  console.log("[bash]", input);
136
- return bash.execute(input);
132
+ return bash.execute(input, ctx);
137
133
  },
138
134
  });
139
135
  ```
@@ -50,11 +50,12 @@ Most apps use `defineAgent`, `defineTool`, and `defineSandbox` the most.
50
50
 
51
51
  ## Runtime Helpers
52
52
 
53
- Each runtime accessor lives on the subpath that owns its concern:
53
+ Session metadata, sandbox access, and skill access are available through the `ctx` parameter
54
+ passed to tool `execute`, hook handlers, and channel event handlers:
54
55
 
55
- - `getSession()` - current session, turn, auth, and optional parent lineage (`experimental-ash/context`)
56
- - `getSandbox()` - live sandbox handle for the current agent (`experimental-ash/sandbox`)
57
- - `getSkill(identifier)` - handle for a named skill visible to the current agent (`experimental-ash/skills`)
56
+ - `ctx.session` - current session, turn, auth, and optional parent lineage
57
+ - `ctx.getSandbox()` - live sandbox handle for the current agent
58
+ - `ctx.getSkill(identifier)` - handle for a named skill visible to the current agent
58
59
  - `defineState(name, initial)` - typed durable state with `get()` and `update()` (`experimental-ash/context`)
59
60
 
60
61
  Related exported types by subpath:
@@ -154,7 +155,7 @@ Channel types exported from `experimental-ash/channels`:
154
155
  - `POST` - route helper for POST endpoints
155
156
  - `GET` - route helper for GET endpoints
156
157
  - `Session` - session handle returned by `send()`
157
- - `SessionHandle` - read-only session handle from `getSession()`
158
+ - `SessionHandle` - read-only session handle available as `ctx.session`
158
159
  - `SendOptions` - options for `send(message, options)`
159
160
 
160
161
  `RunMode` is explicit: `"conversation"` sessions may wait for follow-up input, while `"task"`
@@ -199,14 +200,12 @@ Event handlers on the channel config receive typed event data:
199
200
  ### Typed Tool
200
201
 
201
202
  ```ts
202
- import { getSession } from "experimental-ash/context";
203
203
  import { defineTool } from "experimental-ash/tools";
204
204
  ```
205
205
 
206
206
  ### Sandbox Access
207
207
 
208
208
  ```ts
209
- import { getSandbox } from "experimental-ash/sandbox";
210
209
  import { defineTool } from "experimental-ash/tools";
211
210
  import { defineBashTool } from "experimental-ash/tools";
212
211
  ```
@@ -214,7 +213,7 @@ import { defineBashTool } from "experimental-ash/tools";
214
213
  ### Skill Access
215
214
 
216
215
  ```ts
217
- import { defineSkill, getSkill } from "experimental-ash/skills";
216
+ import { defineSkill } from "experimental-ash/skills";
218
217
  ```
219
218
 
220
219
  ### Wrapping Or Disabling A Framework Default
@@ -254,9 +253,9 @@ import { Braintrust } from "experimental-ash/evals/reporters";
254
253
  - `defineChannel` and channel factories -> [Channels](./channels/README.md)
255
254
  - `defineTool`, `disableTool`, `defineBashTool`, `defineReadFileTool`, `defineWriteFileTool`, and `experimental-ash/tools/defaults` -> [Tools](./tools.md)
256
255
  - `defineHook`, `HookContext`, and lifecycle/event types -> [Hooks](./hooks.md)
257
- - `defineSandbox` and `getSandbox` -> [Sandboxes](./sandbox.md)
258
- - `defineSkill` and `getSkill` -> [Skills](./skills.md)
259
- - `getSession` -> [Session Context](./session-context.md)
256
+ - `defineSandbox` and `ctx.getSandbox()` -> [Sandboxes](./sandbox.md)
257
+ - `defineSkill` and `ctx.getSkill()` -> [Skills](./skills.md)
258
+ - `ctx.session` -> [Session Context](./session-context.md)
260
259
  - subagents (authored with `defineAgent` under `subagents/<id>/agent.ts`) -> [Subagents](./subagents.md)
261
260
  - `defineSchedule` -> [Schedules](./schedules.md)
262
261
  - `defineEvalSuite`, loaders, reporters, and scorers -> [Evals](./evals.md)
@@ -1,6 +1,7 @@
1
1
  import type { ContextAccessor } from "#context/key.js";
2
2
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
3
- import type { Runtime, SessionAuthContext } from "#channel/types.js";
3
+ import type { Runtime } from "#channel/types.js";
4
+ import type { SessionAuth } from "#context/keys.js";
4
5
  export interface Session {
5
6
  readonly id: string;
6
7
  readonly continuationToken: string;
@@ -18,35 +19,8 @@ export interface Session {
18
19
  */
19
20
  export interface SessionHandle {
20
21
  readonly id: string;
21
- /**
22
- * Runtime-scoped continuation token (`<channelName>:<channel-local-token>`).
23
- */
24
22
  readonly continuationToken: string;
25
- readonly auth: SessionAuthContext | null;
26
- readonly initiatorAuth: SessionAuthContext | null;
27
- /**
28
- * Re-key the session under a new continuation token.
29
- *
30
- * Use this when the channel's resume address depends on data
31
- * produced during the turn (e.g. Slack auto-anchoring its first
32
- * post adopts the post's `ts` as the thread root). Pass the
33
- * channel-local raw token, matching the token shape accepted by
34
- * route `send()`; the session handle preserves the current channel
35
- * namespace before writing to runtime context.
36
- *
37
- * Effects:
38
- *
39
- * - Updates `ContinuationTokenKey` in the active context to the
40
- * runtime-scoped token (`<channelName>:<rawToken>`).
41
- * - Causes the workflow runtime to dispose its current park hook
42
- * and register a new one at the new token at the next step
43
- * boundary, so follow-up `deliver` calls keyed under the new
44
- * token resume the same session.
45
- * - Idempotent — calling with the current token is a no-op.
46
- *
47
- * The session must already have a namespaced placeholder
48
- * continuation token so the handle can preserve the channel name.
49
- */
23
+ readonly auth: SessionAuth;
50
24
  setContinuationToken(rawToken: string): void;
51
25
  }
52
26
  export declare function createSession(id: string, continuationToken: string, runtime: Runtime): Session;
@@ -1 +1 @@
1
- import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return i.get(AuthKey)??null},get initiatorAuth(){return i.get(InitiatorAuthKey)??null},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
1
+ import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return{current:i.get(AuthKey)??null,initiator:i.get(InitiatorAuthKey)??null}},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
@@ -20,11 +20,11 @@
20
20
  "@standard-schema/spec": "1.1.0",
21
21
  "turndown": "7.2.4",
22
22
  "@vercel/oidc": "3.4.1",
23
- "@vercel/sandbox": "2.0.0",
23
+ "@vercel/sandbox": "2.0.1",
24
24
  "@workflow/core": "5.0.0-beta.7",
25
25
  "@workflow/errors": "5.0.0-beta.4",
26
26
  "zod": "4.4.3",
27
27
  "zod-validation-error": "5.0.0"
28
28
  },
29
- "scriptHash": "d4ce5a47e0f6620d682bfcba879a1eabaa5c61cc9c9cfe24e3a54c38aaf1edb0"
29
+ "scriptHash": "de60e990328c8664beec98bc5e81625ecdc0cdace1ba8bd8aa267bf9bea29af4"
30
30
  }
@@ -41,6 +41,7 @@ export interface SandboxCreateOptions {
41
41
  env?: Record<string, string> | undefined;
42
42
  name?: string | undefined;
43
43
  networkPolicy?: NetworkPolicy | undefined;
44
+ onResume?: ((sandbox: Sandbox) => Promise<void>) | undefined;
44
45
  persistent?: boolean | undefined;
45
46
  ports?: number[] | undefined;
46
47
  resources?: { vcpus?: number | undefined } | undefined;
@@ -52,6 +53,13 @@ export interface SandboxCreateOptions {
52
53
  timeout?: number | undefined;
53
54
  }
54
55
 
56
+ export interface SandboxGetOptions {
57
+ name: string;
58
+ onResume?: ((sandbox: Sandbox) => Promise<void>) | undefined;
59
+ resume?: boolean | undefined;
60
+ signal?: AbortSignal | undefined;
61
+ }
62
+
55
63
  export interface SandboxRunCommandParams {
56
64
  args?: readonly string[] | undefined;
57
65
  cmd: string;
@@ -95,9 +103,10 @@ export declare class Sandbox {
95
103
  status: string;
96
104
  tags?: Record<string, string> | undefined;
97
105
  static create(options?: SandboxCreateOptions): Promise<Sandbox>;
98
- static get(options: { name: string } | Record<string, unknown>): Promise<Sandbox>;
106
+ static get(options: SandboxGetOptions): Promise<Sandbox>;
99
107
  domain(port: number): string;
100
- readFileToBuffer(input: { path: string }): Promise<Buffer | Uint8Array | null>;
108
+ readFile(file: { path: string }): Promise<ReadableStream<Uint8Array> | null>;
109
+ readFileToBuffer(file: { path: string }): Promise<Buffer | null>;
101
110
  runCommand(input: SandboxRunCommandParams & { detached: true }): Promise<SandboxCommand>;
102
111
  runCommand(input: SandboxRunCommandParams): Promise<SandboxCommandFinished>;
103
112
  snapshot(options?: unknown): Promise<{ snapshotId: string }>;