eve 0.29.4 → 0.29.5

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 (128) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/src/channel/clear-session.d.ts +4 -0
  3. package/dist/src/channel/clear-session.js +1 -0
  4. package/dist/src/channel/compact-session.d.ts +4 -0
  5. package/dist/src/channel/compact-session.js +1 -0
  6. package/dist/src/channel/routes.d.ts +34 -6
  7. package/dist/src/channel/types.d.ts +61 -9
  8. package/dist/src/chunks/{use-eve-agent-8mofdZcO.js → use-eve-agent-BXMIf5fR.js} +85 -1
  9. package/dist/src/chunks/{use-eve-agent-bKJbH0k4.js → use-eve-agent-k-XHfrJT.js} +85 -1
  10. package/dist/src/cli/dev/tui/message-queue.d.ts +9 -13
  11. package/dist/src/cli/dev/tui/message-queue.js +1 -1
  12. package/dist/src/cli/dev/tui/prompt-commands.d.ts +13 -5
  13. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  14. package/dist/src/cli/dev/tui/runner.d.ts +7 -7
  15. package/dist/src/cli/dev/tui/runner.js +1 -1
  16. package/dist/src/cli/dev/tui/subagent-pump.d.ts +5 -5
  17. package/dist/src/cli/dev/tui/terminal-renderer.js +1 -1
  18. package/dist/src/client/agent-info-schema.d.ts +2 -2
  19. package/dist/src/client/agent-info-schema.js +1 -1
  20. package/dist/src/client/index.d.ts +1 -1
  21. package/dist/src/client/session.d.ts +15 -1
  22. package/dist/src/client/session.js +1 -1
  23. package/dist/src/client/types.d.ts +20 -0
  24. package/dist/src/compiler/extension-compatibility.d.ts +8 -8
  25. package/dist/src/compiler/extension-compatibility.js +1 -1
  26. package/dist/src/compiler/manifest.d.ts +11 -22
  27. package/dist/src/compiler/manifest.js +1 -1
  28. package/dist/src/compiler/normalize-agent-config.d.ts +3 -1
  29. package/dist/src/compiler/normalize-agent-config.js +1 -1
  30. package/dist/src/compiler/normalize-manifest.js +1 -1
  31. package/dist/src/compiler/normalize-subagent.d.ts +1 -0
  32. package/dist/src/compiler/normalize-subagent.js +1 -1
  33. package/dist/src/compiler/remote-agent-node.d.ts +3 -0
  34. package/dist/src/context/dynamic-subagent-lifecycle.d.ts +22 -0
  35. package/dist/src/context/dynamic-subagent-lifecycle.js +1 -0
  36. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  37. package/dist/src/context/keys.d.ts +13 -2
  38. package/dist/src/context/keys.js +1 -1
  39. package/dist/src/context/run-step.js +1 -1
  40. package/dist/src/execution/create-session-step.d.ts +2 -0
  41. package/dist/src/execution/create-session-step.js +1 -1
  42. package/dist/src/execution/delegation-tool.d.ts +3 -0
  43. package/dist/src/execution/delegation-tool.js +1 -0
  44. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  45. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
  46. package/dist/src/execution/effective-agent-config.d.ts +12 -0
  47. package/dist/src/execution/effective-agent-config.js +1 -0
  48. package/dist/src/execution/node-step.d.ts +4 -0
  49. package/dist/src/execution/node-step.js +1 -1
  50. package/dist/src/execution/runtime-context.d.ts +2 -0
  51. package/dist/src/execution/runtime-context.js +1 -1
  52. package/dist/src/execution/session-callback-request.d.ts +5 -0
  53. package/dist/src/execution/session-callback-request.js +1 -0
  54. package/dist/src/execution/session-delivery-hook.d.ts +1 -0
  55. package/dist/src/execution/session-delivery-hook.js +1 -1
  56. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  57. package/dist/src/execution/subagent-event-proxy-step.js +1 -1
  58. package/dist/src/execution/workflow-entry.js +1 -1
  59. package/dist/src/execution/workflow-runtime.d.ts +2 -0
  60. package/dist/src/execution/workflow-runtime.js +1 -1
  61. package/dist/src/execution/workflow-steps.js +1 -1
  62. package/dist/src/harness/agent-handles.d.ts +238 -0
  63. package/dist/src/harness/agent-handles.js +2 -0
  64. package/dist/src/harness/compaction.d.ts +1 -1
  65. package/dist/src/harness/compaction.js +1 -1
  66. package/dist/src/harness/tool-loop.js +2 -2
  67. package/dist/src/harness/types.d.ts +16 -0
  68. package/dist/src/internal/application/package.js +1 -1
  69. package/dist/src/internal/authored-definition/core.js +1 -1
  70. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  71. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +1 -1
  72. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  73. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  74. package/dist/src/internal/vercel-agent-summary.d.ts +1 -1
  75. package/dist/src/protocol/clear-session.d.ts +14 -0
  76. package/dist/src/protocol/clear-session.js +1 -0
  77. package/dist/src/protocol/compact-session.d.ts +14 -0
  78. package/dist/src/protocol/compact-session.js +1 -0
  79. package/dist/src/protocol/message.d.ts +19 -1
  80. package/dist/src/protocol/message.js +1 -1
  81. package/dist/src/protocol/routes.d.ts +10 -0
  82. package/dist/src/protocol/routes.js +1 -1
  83. package/dist/src/public/channels/eve.js +1 -1
  84. package/dist/src/public/channels/index.d.ts +1 -1
  85. package/dist/src/public/definitions/agent.d.ts +32 -1
  86. package/dist/src/public/definitions/agent.js +1 -1
  87. package/dist/src/public/definitions/channel.d.ts +5 -2
  88. package/dist/src/public/definitions/channel.js +1 -1
  89. package/dist/src/public/definitions/hook.d.ts +1 -0
  90. package/dist/src/public/definitions/tool.d.ts +4 -1
  91. package/dist/src/public/index.d.ts +1 -2
  92. package/dist/src/public/index.js +1 -1
  93. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +2 -18
  94. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -2
  95. package/dist/src/runtime/framework-tools/index.d.ts +7 -2
  96. package/dist/src/runtime/framework-tools/index.js +1 -1
  97. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  98. package/dist/src/runtime/resolve-agent.js +1 -1
  99. package/dist/src/runtime/resolve-dynamic-subagent.d.ts +12 -0
  100. package/dist/src/runtime/resolve-dynamic-subagent.js +1 -0
  101. package/dist/src/runtime/resolve-dynamic-tool.d.ts +15 -0
  102. package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
  103. package/dist/src/runtime/subagents/dynamic-agent-config.d.ts +22 -0
  104. package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -0
  105. package/dist/src/runtime/subagents/registry.d.ts +10 -2
  106. package/dist/src/runtime/subagents/registry.js +1 -1
  107. package/dist/src/runtime/types.d.ts +11 -2
  108. package/dist/src/setup/flows/registry.js +1 -1
  109. package/dist/src/setup/scaffold/create/project.js +1 -1
  110. package/dist/src/shared/agent-definition.d.ts +7 -0
  111. package/dist/src/shared/agent-turn-outcome.d.ts +47 -0
  112. package/dist/src/shared/agent-turn-outcome.js +1 -0
  113. package/dist/src/shared/dynamic-tool-definition.d.ts +1 -5
  114. package/dist/src/shared/dynamic-tool-definition.js +1 -1
  115. package/dist/src/svelte/index.js +1 -1
  116. package/dist/src/svelte/use-eve-agent.js +1 -1
  117. package/dist/src/vue/index.js +1 -1
  118. package/dist/src/vue/use-eve-agent.js +1 -1
  119. package/docs/channels/custom.mdx +41 -1
  120. package/docs/channels/eve.mdx +26 -1
  121. package/docs/concepts/default-harness.md +4 -0
  122. package/docs/guides/client/streaming.mdx +14 -0
  123. package/docs/guides/dev-tui.md +10 -7
  124. package/docs/guides/dynamic-capabilities.md +49 -6
  125. package/docs/reference/project-layout.md +1 -1
  126. package/docs/reference/typescript-api.md +48 -48
  127. package/docs/subagents.mdx +32 -2
  128. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # eve
2
2
 
3
+ ## 0.29.5
4
+
5
+ ### Patch Changes
6
+
7
+ - c0dc572: Rename the TUI `/new` command to `/reset` so session reset uses the same name across the client, HTTP, channel, and TUI APIs.
8
+ - 3dce30a: Add manual session compaction through custom-channel helpers, the eve HTTP client, and the `eve dev` TUI's `/compact` command. Compaction preserves the session, queues behind an active turn, and does not send synthetic model input.
9
+ - 910805e: Make a single `Esc` cancel the running turn in the eve dev TUI when no message is queued. Queued messages still use `Esc` to steer the oldest message into the next turn.
10
+ - 9c51755: Connection search and discovered connection tools now use the same `defineDynamic` and `defineTool` pipeline as authored tools. Dynamic tool maps now reject entries that omit `defineTool` instead of accepting unsupported raw objects.
11
+ - 84aa671: Clarify the dev TUI’s `/add` flow with consistent integration categories and category-specific browsing labels. MCP connections are now named explicitly, and the flow more clearly explains channels, extensions, and observability integrations.
12
+ - 0c28eb7: Allow declared subagents to export `defineDynamic` from `agent.ts`. Session and turn resolvers can now return an agent configuration to expose it or nil to omit it from direct and Workflow delegation.
13
+ - f3bb60d: Add manual session-context clearing through custom-channel helpers, the eve HTTP client, and the `eve dev` TUI's `/clear` command. Clearing removes model-message history while preserving the session, agent configuration, durable state, limits, and sandbox.
14
+ - ac7d3c6: Add `/cancel` to the eve dev TUI. The command cooperatively cancels a running turn from either the live streaming input or the idle prompt while preserving the session and settled context.
15
+
3
16
  ## 0.29.4
4
17
 
5
18
  ### Patch Changes
@@ -0,0 +1,4 @@
1
+ import type { ClearFn } from "#channel/routes.js";
2
+ import type { Runtime } from "#channel/types.js";
3
+ /** Builds a channel-scoped context-clear helper. */
4
+ export declare function createClearFn(runtime: Runtime, channelName: string): ClearFn;
@@ -0,0 +1 @@
1
+ function createClearFn(e,t){return async n=>await e.clearSession({continuationToken:`${t}:${n.continuationToken}`})}export{createClearFn};
@@ -0,0 +1,4 @@
1
+ import type { CompactFn } from "#channel/routes.js";
2
+ import type { Runtime } from "#channel/types.js";
3
+ /** Builds a channel-scoped manual compaction helper. */
4
+ export declare function createCompactFn(runtime: Runtime, channelName: string): CompactFn;
@@ -0,0 +1 @@
1
+ function createCompactFn(e,t){return async n=>await e.compactSession({continuationToken:`${t}:${n.continuationToken}`})}export{createCompactFn};
@@ -1,6 +1,6 @@
1
1
  import type { UserContent } from "ai";
2
2
  import type { CrossChannelReceiveFn } from "#channel/cross-channel-receive.js";
3
- import type { CancelTurnResult, SessionAuthContext, SessionCallback } from "#channel/types.js";
3
+ import type { CancelTurnResult, ClearSessionResult, CompactSessionResult, SessionAuthContext, SessionCallback } from "#channel/types.js";
4
4
  import type { InputResponse } from "#runtime/input/types.js";
5
5
  import type { Session } from "#channel/session.js";
6
6
  import type { RunMode } from "#shared/run-mode.js";
@@ -10,11 +10,13 @@ type WebSocketHeaders = Headers | readonly (readonly [string, string])[] | Recor
10
10
  /**
11
11
  * Second argument passed to every route handler. `send` starts or continues a
12
12
  * session on this channel; `cancel` stops the active turn on a session
13
- * addressed by continuation token; `reset` retires a session so its
14
- * token can start a fresh session; `getSession` looks one up by id; `receive`
15
- * hands inbound work to a different channel; `params` contains the matched
16
- * path parameters; `waitUntil` keeps background work alive past the response;
17
- * `requestIp` is the client IP, or `null` when the host cannot provide it.
13
+ * addressed by continuation token; `clear` removes its model-message history;
14
+ * `compact` summarizes its context without sending model input; `reset` retires
15
+ * a session so its token can start a fresh session; `getSession` looks one up by
16
+ * id; `receive` hands inbound work to a different channel; `params` contains
17
+ * the matched path parameters; `waitUntil` keeps background work alive past
18
+ * the response; `requestIp` is the client IP, or `null` when the host cannot
19
+ * provide it.
18
20
  */
19
21
  export interface RouteHandlerArgs<TState = undefined> {
20
22
  send: SendFn<TState>;
@@ -24,6 +26,8 @@ export interface RouteHandlerArgs<TState = undefined> {
24
26
  */
25
27
  resolveActiveSession: ResolveActiveSessionFn;
26
28
  cancel: CancelFn;
29
+ clear: ClearFn;
30
+ compact: CompactFn;
27
31
  reset: ResetFn;
28
32
  getSession: GetSessionFn;
29
33
  /**
@@ -119,6 +123,30 @@ export interface CancelOptions {
119
123
  * on the event stream.
120
124
  */
121
125
  export type CancelFn = (options: CancelOptions) => Promise<CancelTurnResult>;
126
+ /** Options for {@link CompactFn}. */
127
+ export interface CompactOptions {
128
+ /** Channel-local raw token, in the same format accepted by {@link SendFn}. */
129
+ readonly continuationToken: string;
130
+ }
131
+ /**
132
+ * Queues context compaction for the session owning a continuation token.
133
+ * Never sends model input or starts a new session. An accepted request returns
134
+ * to `session.waiting`; successful compaction emits `compaction.requested`
135
+ * followed by `compaction.completed` on the session stream.
136
+ */
137
+ export type CompactFn = (options: CompactOptions) => Promise<CompactSessionResult>;
138
+ /** Options for {@link ClearFn}. */
139
+ export interface ClearOptions {
140
+ /** Channel-local raw token, in the same format accepted by {@link SendFn}. */
141
+ readonly continuationToken: string;
142
+ }
143
+ /**
144
+ * Queues removal of the model-message history for the session owning a
145
+ * continuation token. Preserves the session, agent configuration, durable
146
+ * state, limits, and sandbox. Completion is `context.cleared` followed by
147
+ * `session.waiting` on the session stream.
148
+ */
149
+ export type ClearFn = (options: ClearOptions) => Promise<ClearSessionResult>;
122
150
  /** Options for {@link ResetFn}. */
123
151
  export interface ResetOptions {
124
152
  /** Channel-local raw token, in the same format accepted by {@link SendFn}. */
@@ -27,6 +27,28 @@ export interface CancelTurnResult {
27
27
  */
28
28
  readonly reason?: string;
29
29
  }
30
+ /** Identifies the continuation hook whose durable session should compact. */
31
+ export interface CompactSessionInput {
32
+ readonly continuationToken: string;
33
+ }
34
+ /** Result of queueing manual context compaction for a session. */
35
+ export type CompactSessionResult = {
36
+ readonly status: "accepted";
37
+ readonly sessionId: string;
38
+ } | {
39
+ readonly status: "no_active_session";
40
+ };
41
+ /** Identifies the continuation hook whose durable session should clear context. */
42
+ export interface ClearSessionInput {
43
+ readonly continuationToken: string;
44
+ }
45
+ /** Result of queueing a manual context clear for a session. */
46
+ export type ClearSessionResult = {
47
+ readonly status: "accepted";
48
+ readonly sessionId: string;
49
+ } | {
50
+ readonly status: "no_active_session";
51
+ };
30
52
  /** Identifies a session to transition permanently to a terminal state. */
31
53
  export interface TerminateSessionInput {
32
54
  /** Human-readable reason recorded on the terminal workflow transition. */
@@ -100,6 +122,18 @@ export interface SessionAuthContext {
100
122
  * interface: the runtime always writes events itself.
101
123
  */
102
124
  export type EventEmitFn = (event: UnstampedMessageStreamEvent) => Promise<void>;
125
+ /** Framework-internal caller waiting for one delegated conversation turn. */
126
+ export interface TurnCaller {
127
+ readonly callId: string;
128
+ readonly subagentName: string;
129
+ readonly replyTo: {
130
+ readonly kind: "hook";
131
+ readonly token: string;
132
+ } | {
133
+ readonly kind: "callback";
134
+ readonly url: string;
135
+ };
136
+ }
103
137
  /**
104
138
  * Base deliver payload crossing the runtime boundary.
105
139
  *
@@ -122,12 +156,13 @@ export interface DeliverPayload {
122
156
  /**
123
157
  * Deliver payload sent through the workflow `resumeHook`.
124
158
  *
125
- * Wraps the raw {@link DeliverPayload} with an optional auth update so
126
- * deliver-time auth crosses the durable hook boundary without a process-local
127
- * side-channel.
159
+ * Wraps the raw {@link DeliverPayload} with optional auth and turn-caller
160
+ * metadata so both cross the durable hook boundary outside adapter-owned data.
128
161
  */
129
162
  export interface DeliverHookPayload {
130
163
  readonly auth?: SessionAuthContext | null;
164
+ /** Delegated caller waiting for this turn's settled result. */
165
+ readonly caller?: TurnCaller;
131
166
  /** Inbound channel request id used only for workflow attributes. */
132
167
  readonly requestId?: string;
133
168
  readonly kind: "deliver";
@@ -137,6 +172,14 @@ export interface DeliverHookPayload {
137
172
  export interface SessionTimeoutHookPayload {
138
173
  readonly kind: "session-timeout";
139
174
  }
175
+ /** Requests a context compaction without delivering model input. */
176
+ export interface CompactSessionHookPayload {
177
+ readonly kind: "compact";
178
+ }
179
+ /** Requests a context clear without delivering model input. */
180
+ export interface ClearSessionHookPayload {
181
+ readonly kind: "clear";
182
+ }
140
183
  /**
141
184
  * Runtime-action results resumed back into a parked parent workflow.
142
185
  */
@@ -192,13 +235,15 @@ export interface SubagentAuthorizationEventHookPayload {
192
235
  /**
193
236
  * Serializable payload sent through the workflow `resumeHook`.
194
237
  */
195
- export type HookPayload = DeliverHookPayload | RuntimeActionResultHookPayload | SessionTimeoutHookPayload | SubagentAuthorizationEventHookPayload | SubagentInputRequestHookPayload;
238
+ export type HookPayload = ClearSessionHookPayload | CompactSessionHookPayload | DeliverHookPayload | RuntimeActionResultHookPayload | SessionTimeoutHookPayload | SubagentAuthorizationEventHookPayload | SubagentInputRequestHookPayload;
196
239
  /**
197
- * Terminal callback metadata attached to a session at creation.
240
+ * Initial caller callback attached to a delegated session at creation.
198
241
  *
199
242
  * `url` is the absolute callback endpoint. `token` is the capability token
200
243
  * embedded in the framework-owned callback route. `callId` and `subagentName`
201
- * correlate the callee's terminal callback to the pending parent tool call.
244
+ * correlate the callee's result to the pending tool call. Task sessions send a
245
+ * terminal session result. Conversation sessions use this as their first turn's
246
+ * caller; each continuation supplies the caller for that turn.
202
247
  */
203
248
  export interface SessionCallback {
204
249
  readonly callId: string;
@@ -265,8 +310,9 @@ export interface RunInput {
265
310
  */
266
311
  readonly title?: string;
267
312
  /**
268
- * Optional terminal callback. When present, the runtime posts a single
269
- * callback when the session completes or fails.
313
+ * Optional caller callback. Task sessions post when the session completes or
314
+ * fails. Conversation sessions use it for the first turn; continuations carry
315
+ * the caller for their own turn.
270
316
  */
271
317
  readonly callback?: SessionCallback;
272
318
  /**
@@ -312,12 +358,14 @@ export interface RunInput {
312
358
  }
313
359
  export interface DeliverInput {
314
360
  /**
315
- * Authenticated caller principal for this follow-up message.
361
+ * Authenticated principal for this follow-up message.
316
362
  * May differ from the session initiator when different users send
317
363
  * messages to the same session. The runtime updates `AuthKey` from
318
364
  * this field before calling the adapter's hooks.
319
365
  */
320
366
  readonly auth?: SessionAuthContext | null;
367
+ /** Delegated caller waiting for this turn's settled result. */
368
+ readonly caller?: TurnCaller;
321
369
  /** Inbound channel request id used to correlate workflow attributes. */
322
370
  readonly requestId?: string;
323
371
  readonly continuationToken: string;
@@ -364,6 +412,10 @@ export interface Runtime {
364
412
  run(input: RunInput): Promise<RunHandle>;
365
413
  /** Requests cancellation of a session's in-flight turn. */
366
414
  cancelTurn(input: CancelTurnInput): Promise<CancelTurnResult>;
415
+ /** Queues context compaction on the session owning a continuation token. */
416
+ compactSession(input: CompactSessionInput): Promise<CompactSessionResult>;
417
+ /** Queues a context clear on the session owning a continuation token. */
418
+ clearSession(input: ClearSessionInput): Promise<ClearSessionResult>;
367
419
  /** Terminally retires a session and releases its non-retained continuation hooks. */
368
420
  terminateSession(input: TerminateSessionInput): Promise<TerminateSessionResult>;
369
421
  /**
@@ -7,6 +7,8 @@ const EVE_HEALTH_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/health`;
7
7
  const EVE_INFO_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/info`;
8
8
  const EVE_CREATE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
9
9
  const EVE_RESET_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/reset`;
10
+ const EVE_COMPACT_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/compact`;
11
+ const EVE_CLEAR_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/clear`;
10
12
  const EVE_CONTINUE_SESSION_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId`;
11
13
  const EVE_MESSAGE_STREAM_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/stream`;
12
14
  const EVE_CANCEL_TURN_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`;
@@ -118,7 +120,7 @@ const schedule = entry.extend({
118
120
  markdown: z.string().optional()
119
121
  });
120
122
  const subagent = entry.extend({
121
- description: z.string(),
123
+ description: z.string().optional(),
122
124
  entryPath: z.string(),
123
125
  nodeId: z.string(),
124
126
  rootPath: z.string(),
@@ -383,6 +385,28 @@ const CancelTurnResponseSchema = z.object({
383
385
  status: z.enum(["accepted", "no_active_turn"])
384
386
  });
385
387
 
388
+ //#endregion
389
+ //#region src/protocol/clear-session.ts
390
+ const ClearResponseSchema = z.discriminatedUnion("status", [z.object({
391
+ ok: z.literal(true),
392
+ sessionId: z.string().min(1),
393
+ status: z.literal("accepted")
394
+ }), z.object({
395
+ ok: z.literal(true),
396
+ status: z.literal("no_active_session")
397
+ })]);
398
+
399
+ //#endregion
400
+ //#region src/protocol/compact-session.ts
401
+ const CompactResponseSchema = z.discriminatedUnion("status", [z.object({
402
+ ok: z.literal(true),
403
+ sessionId: z.string().min(1),
404
+ status: z.literal("accepted")
405
+ }), z.object({
406
+ ok: z.literal(true),
407
+ status: z.literal("no_active_session")
408
+ })]);
409
+
386
410
  //#endregion
387
411
  //#region src/protocol/reset-session.ts
388
412
  const ResetResponseSchema = z.discriminatedUnion("status", [z.object({
@@ -882,6 +906,66 @@ var ClientSession = class {
882
906
  status: result.data.status
883
907
  };
884
908
  }
909
+ async clear() {
910
+ const state = this.#state;
911
+ const continuationToken = state.continuationToken;
912
+ if (continuationToken === void 0) {
913
+ if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before clearing.");
914
+ return { status: "no_active_session" };
915
+ }
916
+ const url = createClientUrl(this.#context.host, EVE_CLEAR_SESSION_ROUTE_PATH);
917
+ const headers = await this.#context.resolveHeaders();
918
+ headers.set("content-type", "application/json");
919
+ const response = await fetch(url, withRedirectPolicy$1({
920
+ body: JSON.stringify({ continuationToken }),
921
+ headers,
922
+ method: "POST"
923
+ }, this.#context.redirect));
924
+ const body = await response.text();
925
+ if (!response.ok) throw new ClientError(response.status, body, response.headers);
926
+ let payload;
927
+ try {
928
+ payload = JSON.parse(body);
929
+ } catch {
930
+ throw new Error(`Clear route returned invalid JSON (${response.status}).`);
931
+ }
932
+ const result = ClearResponseSchema.safeParse(payload);
933
+ if (!result.success || result.data.status === "accepted" && state.sessionId !== void 0 && result.data.sessionId !== state.sessionId) throw new Error(`Clear route returned an invalid response (${response.status}).`);
934
+ return result.data.status === "accepted" ? {
935
+ sessionId: result.data.sessionId,
936
+ status: "accepted"
937
+ } : { status: "no_active_session" };
938
+ }
939
+ async compact() {
940
+ const state = this.#state;
941
+ const continuationToken = state.continuationToken;
942
+ if (continuationToken === void 0) {
943
+ if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before compacting.");
944
+ return { status: "no_active_session" };
945
+ }
946
+ const url = createClientUrl(this.#context.host, EVE_COMPACT_SESSION_ROUTE_PATH);
947
+ const headers = await this.#context.resolveHeaders();
948
+ headers.set("content-type", "application/json");
949
+ const response = await fetch(url, withRedirectPolicy$1({
950
+ body: JSON.stringify({ continuationToken }),
951
+ headers,
952
+ method: "POST"
953
+ }, this.#context.redirect));
954
+ const body = await response.text();
955
+ if (!response.ok) throw new ClientError(response.status, body, response.headers);
956
+ let payload;
957
+ try {
958
+ payload = JSON.parse(body);
959
+ } catch {
960
+ throw new Error(`Compact route returned invalid JSON (${response.status}).`);
961
+ }
962
+ const result = CompactResponseSchema.safeParse(payload);
963
+ if (!result.success || result.data.status === "accepted" && state.sessionId !== void 0 && result.data.sessionId !== state.sessionId) throw new Error(`Compact route returned an invalid response (${response.status}).`);
964
+ return result.data.status === "accepted" ? {
965
+ sessionId: result.data.sessionId,
966
+ status: "accepted"
967
+ } : { status: "no_active_session" };
968
+ }
885
969
  async reset() {
886
970
  const state = this.#state;
887
971
  const continuationToken = state.continuationToken;
@@ -7,6 +7,8 @@ const EVE_HEALTH_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/health`;
7
7
  const EVE_INFO_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/info`;
8
8
  const EVE_CREATE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
9
9
  const EVE_RESET_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/reset`;
10
+ const EVE_COMPACT_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/compact`;
11
+ const EVE_CLEAR_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/clear`;
10
12
  const EVE_CONTINUE_SESSION_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId`;
11
13
  const EVE_MESSAGE_STREAM_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/stream`;
12
14
  const EVE_CANCEL_TURN_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`;
@@ -118,7 +120,7 @@ const schedule = entry.extend({
118
120
  markdown: z.string().optional()
119
121
  });
120
122
  const subagent = entry.extend({
121
- description: z.string(),
123
+ description: z.string().optional(),
122
124
  entryPath: z.string(),
123
125
  nodeId: z.string(),
124
126
  rootPath: z.string(),
@@ -383,6 +385,28 @@ const CancelTurnResponseSchema = z.object({
383
385
  status: z.enum(["accepted", "no_active_turn"])
384
386
  });
385
387
 
388
+ //#endregion
389
+ //#region src/protocol/clear-session.ts
390
+ const ClearResponseSchema = z.discriminatedUnion("status", [z.object({
391
+ ok: z.literal(true),
392
+ sessionId: z.string().min(1),
393
+ status: z.literal("accepted")
394
+ }), z.object({
395
+ ok: z.literal(true),
396
+ status: z.literal("no_active_session")
397
+ })]);
398
+
399
+ //#endregion
400
+ //#region src/protocol/compact-session.ts
401
+ const CompactResponseSchema = z.discriminatedUnion("status", [z.object({
402
+ ok: z.literal(true),
403
+ sessionId: z.string().min(1),
404
+ status: z.literal("accepted")
405
+ }), z.object({
406
+ ok: z.literal(true),
407
+ status: z.literal("no_active_session")
408
+ })]);
409
+
386
410
  //#endregion
387
411
  //#region src/protocol/reset-session.ts
388
412
  const ResetResponseSchema = z.discriminatedUnion("status", [z.object({
@@ -882,6 +906,66 @@ var ClientSession = class {
882
906
  status: result.data.status
883
907
  };
884
908
  }
909
+ async clear() {
910
+ const state = this.#state;
911
+ const continuationToken = state.continuationToken;
912
+ if (continuationToken === void 0) {
913
+ if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before clearing.");
914
+ return { status: "no_active_session" };
915
+ }
916
+ const url = createClientUrl(this.#context.host, EVE_CLEAR_SESSION_ROUTE_PATH);
917
+ const headers = await this.#context.resolveHeaders();
918
+ headers.set("content-type", "application/json");
919
+ const response = await fetch(url, withRedirectPolicy$1({
920
+ body: JSON.stringify({ continuationToken }),
921
+ headers,
922
+ method: "POST"
923
+ }, this.#context.redirect));
924
+ const body = await response.text();
925
+ if (!response.ok) throw new ClientError(response.status, body, response.headers);
926
+ let payload;
927
+ try {
928
+ payload = JSON.parse(body);
929
+ } catch {
930
+ throw new Error(`Clear route returned invalid JSON (${response.status}).`);
931
+ }
932
+ const result = ClearResponseSchema.safeParse(payload);
933
+ if (!result.success || result.data.status === "accepted" && state.sessionId !== void 0 && result.data.sessionId !== state.sessionId) throw new Error(`Clear route returned an invalid response (${response.status}).`);
934
+ return result.data.status === "accepted" ? {
935
+ sessionId: result.data.sessionId,
936
+ status: "accepted"
937
+ } : { status: "no_active_session" };
938
+ }
939
+ async compact() {
940
+ const state = this.#state;
941
+ const continuationToken = state.continuationToken;
942
+ if (continuationToken === void 0) {
943
+ if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before compacting.");
944
+ return { status: "no_active_session" };
945
+ }
946
+ const url = createClientUrl(this.#context.host, EVE_COMPACT_SESSION_ROUTE_PATH);
947
+ const headers = await this.#context.resolveHeaders();
948
+ headers.set("content-type", "application/json");
949
+ const response = await fetch(url, withRedirectPolicy$1({
950
+ body: JSON.stringify({ continuationToken }),
951
+ headers,
952
+ method: "POST"
953
+ }, this.#context.redirect));
954
+ const body = await response.text();
955
+ if (!response.ok) throw new ClientError(response.status, body, response.headers);
956
+ let payload;
957
+ try {
958
+ payload = JSON.parse(body);
959
+ } catch {
960
+ throw new Error(`Compact route returned invalid JSON (${response.status}).`);
961
+ }
962
+ const result = CompactResponseSchema.safeParse(payload);
963
+ if (!result.success || result.data.status === "accepted" && state.sessionId !== void 0 && result.data.sessionId !== state.sessionId) throw new Error(`Compact route returned an invalid response (${response.status}).`);
964
+ return result.data.status === "accepted" ? {
965
+ sessionId: result.data.sessionId,
966
+ status: "accepted"
967
+ } : { status: "no_active_session" };
968
+ }
885
969
  async reset() {
886
970
  const state = this.#state;
887
971
  const continuationToken = state.continuationToken;
@@ -7,8 +7,8 @@
7
7
  * the next turn's message. Esc pops the oldest message to steer the
8
8
  * conversation instead of waiting: the renderer requests cooperative turn
9
9
  * cancellation and the runner submits the popped message as the next turn.
10
- * Esc on an empty queue arms cancellation; a second Esc cancels the turn
11
- * without a replacement message.
10
+ * `/cancel` requests cancellation directly. Esc on an empty queue cancels the
11
+ * turn immediately without a replacement message.
12
12
  *
13
13
  * The renderer owns lifecycle (keys, cancel requests, when the runner drains
14
14
  * the queue); this module only holds the queue state machine and paints rows.
@@ -24,9 +24,7 @@ export type MessageQueueEscapeOutcome =
24
24
  * into the same staged steer payload and re-request cancellation.
25
25
  */
26
26
  "steer"
27
- /** Queue empty: cancellation armed; the next Esc cancels. */
28
- | "armed"
29
- /** Second Esc on an empty queue — the caller should cancel the turn. */
27
+ /** Empty queue — the caller should cancel the turn. */
30
28
  | "cancel";
31
29
  /** Read-only projection consumed by {@link renderMessageQueueRows}. */
32
30
  export interface MessageQueueView {
@@ -34,27 +32,25 @@ export interface MessageQueueView {
34
32
  readonly full: boolean;
35
33
  /** A popped message is staged and turn cancellation was requested. */
36
34
  readonly steering: boolean;
37
- /** First Esc on an empty queue landed; the next one cancels. */
38
- readonly armed: boolean;
39
- /** Esc Esc on an empty queue landed; cancellation was requested. */
35
+ /** Esc on an empty queue landed; cancellation was requested. */
40
36
  readonly cancelling: boolean;
41
37
  }
42
38
  export declare class MessageQueue {
43
39
  #private;
44
40
  get size(): number;
45
41
  get full(): boolean;
46
- /** True when nothing is queued, staged, armed, or cancelling. */
42
+ /** True when nothing is queued, staged, or cancelling. */
47
43
  get idle(): boolean;
48
44
  /** Queues one message; returns false (draft stays put) when full. */
49
45
  enqueue(message: string): boolean;
50
46
  /**
51
47
  * Applies one Esc press. Pops the oldest queued message into the staged
52
- * steer payload while any remain; with an empty queue, arms and then
53
- * requests cancellation.
48
+ * steer payload while any remain; with an empty queue, requests
49
+ * cancellation immediately.
54
50
  */
55
51
  handleEscape(): MessageQueueEscapeOutcome;
56
- /** Any non-Esc activity backs out of the armed press-again state. */
57
- disarm(): void;
52
+ /** Marks a direct cancellation request without consuming queued messages. */
53
+ requestCancellation(): void;
58
54
  /** Clears per-turn Esc state when a new stream starts rendering. */
59
55
  beginTurn(): void;
60
56
  /**
@@ -1 +1 @@
1
- import"./rail.js";import{clipVisible,stripTerminalControls}from"#cli/ui/terminal-text.js";const MESSAGE_QUEUE_LIMIT=5;var MessageQueue=class{#e=[];#t;#n=!1;#r=!1;get size(){return this.#e.length}get full(){return this.#e.length>=5}get idle(){return this.#e.length===0&&this.#t===void 0&&!this.#n&&!this.#r}enqueue(e){return this.full?!1:(this.#e.push(e),this.#n=!1,!0)}handleEscape(){let e=this.#e.shift();return e===void 0?this.#t===void 0?this.#n?(this.#r=!0,`cancel`):(this.#n=!0,`armed`):`steer`:(this.#t=joinMessages(this.#t,e),`steer`)}disarm(){this.#n=!1}beginTurn(){this.#n=!1,this.#r=!1}takePrompt(){this.#n=!1,this.#r=!1;let e=this.#t;return e===void 0?this.#i():(this.#t=void 0,e)}restoreDraft(){this.#n=!1,this.#r=!1;let e=this.#t;return this.#t=void 0,joinOptionalMessages(e,this.#i())}reset(){this.#e=[],this.#t=void 0,this.#n=!1,this.#r=!1}view(){return{messages:[...this.#e],full:this.full,steering:this.#t!==void 0,armed:this.#n,cancelling:this.#r}}#i(){if(this.#e.length===0)return;let e=this.#e.reduce(joinOptionalMessages,void 0);return this.#e=[],e}};function joinMessages(e,t){return e===void 0?t:`${e}\n\n${t}`}function joinOptionalMessages(e,t){return t===void 0?e:joinMessages(e,t)}function renderMessageQueueRows(n){let{view:r,width:i,theme:a,working:o}=n,s=a.colors,c=a.glyph;if(r.messages.length===0&&!r.steering)return o?r.cancelling?[clipVisible(` ${s.yellow(c.dotActive)} ${s.dim(`Cancelling turn…`)}`,i)]:r.armed?[clipVisible(` ${s.yellow(c.dotActive)} ${s.dim(`Press esc again to cancel the turn`)}`,i)]:[]:[];let l=[clipVisible(` ${s.gray(c.arrowUp)} ${headerBody(r,o,a)}`,i)];for(let[n,a]of r.messages.entries()){let o=n===r.messages.length-1?c.corner:c.rule,u=firstLine(stripTerminalControls(a));l.push(clipVisible(` ${s.dim(o)} ${s.dim(u)}`,i))}return l}function headerBody(e,t,n){let r=n.colors,i=` ${n.glyph.dot} `,a=`${String(e.messages.length)}/5`;if(e.steering){let t=e.messages.length>0?`${i}${a} still queued`:``;return r.dim(`Steering — cancelling the running turn…${t}`)}let o=e.full?`${i}queue full`:``,s=t?`${i}esc steers with the next message`:``;return`${r.bold(`Queue`)} ${r.dim(`${a}${o}${s}`)}`}function firstLine(e){return e.split(/\r?\n/u,1)[0]??``}export{MESSAGE_QUEUE_LIMIT,MessageQueue,renderMessageQueueRows};
1
+ import"./rail.js";import{clipVisible,stripTerminalControls}from"#cli/ui/terminal-text.js";const MESSAGE_QUEUE_LIMIT=5;var MessageQueue=class{#e=[];#t;#n=!1;get size(){return this.#e.length}get full(){return this.#e.length>=5}get idle(){return this.#e.length===0&&this.#t===void 0&&!this.#n}enqueue(e){return this.full?!1:(this.#e.push(e),!0)}handleEscape(){let e=this.#e.shift();return e===void 0?this.#t===void 0?(this.#n=!0,`cancel`):`steer`:(this.#t=joinMessages(this.#t,e),`steer`)}requestCancellation(){this.#n=!0}beginTurn(){this.#n=!1}takePrompt(){this.#n=!1;let e=this.#t;return e===void 0?this.#r():(this.#t=void 0,e)}restoreDraft(){this.#n=!1;let e=this.#t;return this.#t=void 0,joinOptionalMessages(e,this.#r())}reset(){this.#e=[],this.#t=void 0,this.#n=!1}view(){return{messages:[...this.#e],full:this.full,steering:this.#t!==void 0,cancelling:this.#n}}#r(){if(this.#e.length===0)return;let e=this.#e.reduce(joinOptionalMessages,void 0);return this.#e=[],e}};function joinMessages(e,t){return e===void 0?t:`${e}\n\n${t}`}function joinOptionalMessages(e,t){return t===void 0?e:joinMessages(e,t)}function renderMessageQueueRows(n){let{view:r,width:i,theme:a,working:o}=n,s=a.colors,c=a.glyph;if(r.messages.length===0&&!r.steering)return o&&r.cancelling?[clipVisible(` ${s.yellow(c.dotActive)} ${s.dim(`Cancelling turn…`)}`,i)]:[];let l=[clipVisible(` ${s.gray(c.arrowUp)} ${headerBody(r,o,a)}`,i)];for(let[n,a]of r.messages.entries()){let o=n===r.messages.length-1?c.corner:c.rule,u=firstLine(stripTerminalControls(a));l.push(clipVisible(` ${s.dim(o)} ${s.dim(u)}`,i))}return l}function headerBody(e,t,n){let r=n.colors,i=` ${n.glyph.dot} `,a=`${String(e.messages.length)}/5`;if(e.steering){let t=e.messages.length>0?`${i}${a} still queued`:``;return r.dim(`Steering — cancelling the running turn…${t}`)}let o=e.full?`${i}queue full`:``,s=t?`${i}esc steers with the next message`:``;return`${r.bold(`Queue`)} ${r.dim(`${a}${o}${s}`)}`}function firstLine(e){return e.split(/\r?\n/u,1)[0]??``}export{MESSAGE_QUEUE_LIMIT,MessageQueue,renderMessageQueueRows};
@@ -2,7 +2,13 @@ export type PromptCommandExtensionName = "model" | "add" | "deploy" | "vc:instal
2
2
  type PromptCommandTarget = "local" | "remote";
3
3
  /** The slash commands the prompt accepts. */
4
4
  export type PromptCommand = {
5
- type: "new";
5
+ type: "reset";
6
+ } | {
7
+ type: "cancel";
8
+ } | {
9
+ type: "clear";
10
+ } | {
11
+ type: "compact";
6
12
  } | {
7
13
  type: "exit";
8
14
  } | {
@@ -41,10 +47,12 @@ export declare function promptCommandsFor(target: PromptCommandTarget): readonly
41
47
  /** Whether a command runs against this target — the one authority dispatch shares with discovery. */
42
48
  export declare function isPromptCommandAvailableFor(name: PromptCommandExtensionName, target: PromptCommandTarget): boolean;
43
49
  /**
44
- * Recognizes the slash commands the prompt accepts. `/new` clears the
45
- * session and transcript; `/exit` (and `/quit`) terminate the TUI like
46
- * Ctrl+C; extension commands are dispatched outside the runner. Anything
47
- * else — including unknown `/text` — is a normal message.
50
+ * Recognizes the slash commands the prompt accepts. `/reset` clears the
51
+ * session and transcript; `/cancel` stops the running turn; `/clear` clears
52
+ * context; `/compact` queues context compaction; `/exit` (and `/quit`)
53
+ * terminate the TUI like Ctrl+C; extension commands are dispatched outside
54
+ * the runner. Anything else — including unknown `/text` — is a normal
55
+ * message.
48
56
  */
49
57
  export declare function parsePromptCommand(prompt: string): PromptCommand | null;
50
58
  /** True for prompts that are commands, which never echo as user messages. */
@@ -1,2 +1,2 @@
1
- const PROMPT_COMMAND_DEFINITIONS=[{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`}),targets:[`local`,`remote`]},{name:`new`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`new`}),targets:[`local`,`remote`]},{name:`vc:install`,aliases:[],description:`Install the Vercel CLI`,takesArgument:!1,build:()=>({type:`extension`,name:`vc:install`,argument:``}),targets:[`local`,`remote`]},{name:`vc:login`,aliases:[],description:`Authenticate with Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`vc:login`,argument:``}),targets:[`local`,`remote`]},{name:`model`,aliases:[],description:`Configure the agent's model and provider`,argumentHint:`[provider/model]`,takesArgument:!0,build:e=>({type:`extension`,name:`model`,argument:e}),targets:[`local`]},{name:`loglevel`,aliases:[],description:`Show or hide captured stdout/stderr/sandbox logs`,argumentHint:`[all|stderr|sandbox|none]`,takesArgument:!0,build:e=>({type:`loglevel`,argument:e}),targets:[`local`,`remote`]},{name:`traces`,aliases:[],description:`Open the local trace viewer`,argumentHint:`[trace]`,takesArgument:!0,build:e=>({type:`traces`,argument:e}),targets:[`local`]},{name:`add`,aliases:[],description:`Browse and add registry integrations`,takesArgument:!1,build:()=>({type:`extension`,name:`add`,argument:``}),targets:[`local`]},{name:`deploy`,aliases:[],description:`Deploy the agent to Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`deploy`,argument:``}),targets:[`local`]},{name:`exit`,aliases:[`quit`],description:`Quit the TUI`,takesArgument:!1,build:()=>({type:`exit`}),targets:[`local`,`remote`]}],PROMPT_COMMANDS=PROMPT_COMMAND_DEFINITIONS;function promptCommandsFor(t){return PROMPT_COMMAND_DEFINITIONS.filter(e=>e.targets.some(e=>e===t))}function isPromptCommandAvailableFor(t,n){return(PROMPT_COMMAND_DEFINITIONS.find(e=>e.name===t)?.targets)?.includes(n)??!1}function parsePromptCommand(e){let n=e.trim();if(!n.startsWith(`/`))return null;for(let e of PROMPT_COMMANDS)for(let t of[e.name,...e.aliases]){let r=`/${t}`;if(n===r)return e.build(``);if(e.takesArgument&&n.startsWith(`${r} `))return e.build(n.slice(r.length).trim())}return null}function isPromptControlCommand(e){return parsePromptCommand(e)!==null}function formatPromptCommandHelp(e=PROMPT_COMMANDS){let n=e.map(e=>{let t=e.argumentHint===void 0?``:` ${e.argumentHint}`,n=e.aliases.map(e=>` (/${e})`).join(``);return{invocation:`/${e.name}${t}${n}`,description:e.description}}),r=Math.max(...n.map(e=>e.invocation.length))+2;return n.map(e=>e.invocation.padEnd(r)+e.description).join(`
1
+ const PROMPT_COMMAND_DEFINITIONS=[{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`}),targets:[`local`,`remote`]},{name:`reset`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`reset`}),targets:[`local`,`remote`]},{name:`cancel`,aliases:[],description:`Cancel the running turn`,takesArgument:!1,build:()=>({type:`cancel`}),targets:[`local`,`remote`]},{name:`clear`,aliases:[],description:`Clear the current session context`,takesArgument:!1,build:()=>({type:`clear`}),targets:[`local`,`remote`]},{name:`compact`,aliases:[],description:`Compact the current session context`,takesArgument:!1,build:()=>({type:`compact`}),targets:[`local`,`remote`]},{name:`vc:install`,aliases:[],description:`Install the Vercel CLI`,takesArgument:!1,build:()=>({type:`extension`,name:`vc:install`,argument:``}),targets:[`local`,`remote`]},{name:`vc:login`,aliases:[],description:`Authenticate with Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`vc:login`,argument:``}),targets:[`local`,`remote`]},{name:`model`,aliases:[],description:`Configure the agent's model and provider`,argumentHint:`[provider/model]`,takesArgument:!0,build:e=>({type:`extension`,name:`model`,argument:e}),targets:[`local`]},{name:`loglevel`,aliases:[],description:`Show or hide captured stdout/stderr/sandbox logs`,argumentHint:`[all|stderr|sandbox|none]`,takesArgument:!0,build:e=>({type:`loglevel`,argument:e}),targets:[`local`,`remote`]},{name:`traces`,aliases:[],description:`Open the local trace viewer`,argumentHint:`[trace]`,takesArgument:!0,build:e=>({type:`traces`,argument:e}),targets:[`local`]},{name:`add`,aliases:[],description:`Add an integration from the registry`,takesArgument:!1,build:()=>({type:`extension`,name:`add`,argument:``}),targets:[`local`]},{name:`deploy`,aliases:[],description:`Deploy the agent to Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`deploy`,argument:``}),targets:[`local`]},{name:`exit`,aliases:[`quit`],description:`Quit the TUI`,takesArgument:!1,build:()=>({type:`exit`}),targets:[`local`,`remote`]}],PROMPT_COMMANDS=PROMPT_COMMAND_DEFINITIONS;function promptCommandsFor(t){return PROMPT_COMMAND_DEFINITIONS.filter(e=>e.targets.some(e=>e===t))}function isPromptCommandAvailableFor(t,n){return(PROMPT_COMMAND_DEFINITIONS.find(e=>e.name===t)?.targets)?.includes(n)??!1}function parsePromptCommand(e){let n=e.trim();if(!n.startsWith(`/`))return null;for(let e of PROMPT_COMMANDS)for(let t of[e.name,...e.aliases]){let r=`/${t}`;if(n===r)return e.build(``);if(e.takesArgument&&n.startsWith(`${r} `))return e.build(n.slice(r.length).trim())}return null}function isPromptControlCommand(e){return parsePromptCommand(e)!==null}function formatPromptCommandHelp(e=PROMPT_COMMANDS){let n=e.map(e=>{let t=e.argumentHint===void 0?``:` ${e.argumentHint}`,n=e.aliases.map(e=>` (/${e})`).join(``);return{invocation:`/${e.name}${t}${n}`,description:e.description}}),r=Math.max(...n.map(e=>e.invocation.length))+2;return n.map(e=>e.invocation.padEnd(r)+e.description).join(`
2
2
  `)}export{PROMPT_COMMANDS,formatPromptCommandHelp,isPromptCommandAvailableFor,isPromptControlCommand,parsePromptCommand,promptCommandsFor};
@@ -23,11 +23,11 @@ export type AgentTUIStreamResult = {
23
23
  abort?: () => void;
24
24
  /**
25
25
  * Requests cooperative server-side cancellation of the streaming turn
26
- * (Esc Esc, or an Esc steer pop). Unlike {@link abort} — which drops the
27
- * client stream and forces a fresh session — the server settles the turn
28
- * as `turn.cancelled` → `session.waiting`, so the stream reaches its
29
- * boundary normally and the session keeps its context. Best-effort and
30
- * idempotent; scoped to the turn the user observed when its id is known.
26
+ * (`/cancel` or Esc, which steers when a message is queued). Unlike
27
+ * {@link abort} — which drops the client stream and forces a fresh session —
28
+ * the server settles the turn as `turn.cancelled` → `session.waiting`, so
29
+ * the stream reaches its boundary normally and the session keeps its context.
30
+ * Best-effort and idempotent; scoped to the turn the user observed when its id is known.
31
31
  */
32
32
  cancel?: () => void;
33
33
  turnState?: AgentTUITurnState;
@@ -202,7 +202,7 @@ export type AgentTUIRenderer = {
202
202
  /**
203
203
  * Reports the server session id backing the conversation — pushed by the
204
204
  * runner once a send is accepted, and overwritten when a later session's
205
- * turn is accepted. Deliberately sticky across `/new` and interrupt
205
+ * turn is accepted. Deliberately sticky across `/reset` and interrupt
206
206
  * recovery: the terminal renderer echoes the LAST session this TUI talked
207
207
  * to in the parting line on exit, so an interrupted conversation (whose
208
208
  * replacement session never ran a turn) can still be found again
@@ -265,7 +265,7 @@ export type AgentTUIRenderer = {
265
265
  /**
266
266
  * Clears the rendered transcript and resets per-conversation display
267
267
  * state, leaving the UI interactive on a fresh screen. Used by the
268
- * `/new` command to start a new session with a clean slate.
268
+ * `/reset` command to start a new session with a clean slate.
269
269
  */
270
270
  reset?(): void;
271
271
  /**