@rome-os/app-runtime 0.2.2 → 0.3.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/dist/index.d.ts +382 -126
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/ipc.d.ts +0 -116
- package/dist/ipc.d.ts.map +0 -1
- package/dist/ipc.js +0 -402
- package/dist/ipc.js.map +0 -1
- package/dist/proxies.d.ts +0 -63
- package/dist/proxies.d.ts.map +0 -1
- package/dist/proxies.js +0 -92
- package/dist/proxies.js.map +0 -1
- package/dist/worker-rpc.d.ts +0 -35
- package/dist/worker-rpc.d.ts.map +0 -1
- package/dist/worker-rpc.js +0 -149
- package/dist/worker-rpc.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
import type { BetterSQLite3Database } from "drizzle-orm/better-sqlite3";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import type { JSONSchema } from "zod/v4/core";
|
|
3
4
|
export { z };
|
|
5
|
+
export type { JSONSchema };
|
|
4
6
|
export * from "./browser.js";
|
|
5
|
-
export { getWorkerRpc, isWorkerRpcResponse, WorkerRpcTimeoutError, WorkerRpcDisconnectError, setWorkerRpcInProcessDispatcher, type WorkerRpcInProcessDispatcher, type RpcResponseMessage, } from "./worker-rpc.js";
|
|
6
|
-
export { RoutineEngineProxy, EventBusProxy, EventCatalogProxy, AppManagerProxy, } from "./proxies.js";
|
|
7
|
-
export { IpcRpc, IpcRpcTimeoutError, IpcRpcDisconnectError, IpcStreamError, isIpcMessage, createWorkerProcessTransport, createChildProcessTransport, type IpcMessage, type IpcTransport, type IpcCallContext, type IpcInboundStream, type IpcOutboundStream, } from "./ipc.js";
|
|
8
|
-
import { IpcRpc } from "./ipc.js";
|
|
9
|
-
/**
|
|
10
|
-
* Lazy worker-side IpcRpc bound to the parent process IPC channel. Returns
|
|
11
|
-
* the same instance for the lifetime of the worker.
|
|
12
|
-
*/
|
|
13
|
-
export declare function getWorkerIpc(): IpcRpc;
|
|
14
7
|
export type SpanAttributes = Record<string, unknown>;
|
|
15
8
|
export interface TelemetryBridge {
|
|
16
9
|
withRomeSpan<T>(name: string, attrs: SpanAttributes, fn: () => Promise<T>): Promise<T>;
|
|
@@ -87,41 +80,182 @@ export type PreviewPayload = {
|
|
|
87
80
|
value: string;
|
|
88
81
|
}[];
|
|
89
82
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
/** Execution was suspended pending guardian approval; the action body has NOT
|
|
84
|
+
* run. When the guardian approves, core re-runs the action for real and the
|
|
85
|
+
* outcome arrives out-of-band (a new agent turn / webhook poll update). */
|
|
86
|
+
export interface PendingApproval {
|
|
87
|
+
approvalId: string;
|
|
88
|
+
actionName: string;
|
|
89
|
+
description: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Park the calling agent on a self-contained guardian input. When an
|
|
93
|
+
* agent-callable action returns this, the calling agent is told to wait (it
|
|
94
|
+
* does not receive data); the chat host mounts this app's own component as a
|
|
95
|
+
* first-class assistant block in the transcript (declared in app.yaml under
|
|
96
|
+
* `components:` and registered via the web SDK's `defineComponent`). Best for
|
|
97
|
+
* a structured question card (see the `ask-user` app). The thread is not
|
|
98
|
+
* locked; several inline components can be open at once.
|
|
99
|
+
*
|
|
100
|
+
* Resolves by posting an `interaction_result` (the produced artifact, or
|
|
101
|
+
* `{ dismissed: true }`) on the session, which re-drives the calling agent
|
|
102
|
+
* with a server-built outcome prompt. Control never leaves the calling agent —
|
|
103
|
+
* for a transfer of the floor to another agent, see {@link Handoff}.
|
|
104
|
+
*/
|
|
105
|
+
export interface PendingInteraction {
|
|
106
|
+
/** This app's id (owns the component to render). */
|
|
107
|
+
appId: string;
|
|
99
108
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* artifact back as an `interaction_result` on the parent session, which
|
|
105
|
-
* re-drives the calling agent with the outcome — the action body does NOT
|
|
106
|
-
* re-run. Generalizes `ask_user_question` so any app can extend it into an
|
|
107
|
-
* arbitrarily rich interactive flow.
|
|
109
|
+
* Human-readable rendering of what the component asks for. Only webchat can
|
|
110
|
+
* mount the component; on a messaging channel (or inside a subagent) the
|
|
111
|
+
* calling agent relays this text as prose and the guardian's reply arrives
|
|
112
|
+
* as the next turn.
|
|
108
113
|
*/
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
|
|
116
|
-
* guardian keeps using the same chat thread; their turns route to this agent
|
|
117
|
-
* (on the same webchat session) until the surface resolves, then route back
|
|
118
|
-
* to the calling agent. Omit for a surface that needs no conversation.
|
|
119
|
-
*/
|
|
120
|
-
agentName?: string;
|
|
121
|
-
/** Optional seed context passed through to the surface. */
|
|
122
|
-
payload?: Record<string, unknown>;
|
|
114
|
+
promptText: string;
|
|
115
|
+
render: {
|
|
116
|
+
kind: "inline";
|
|
117
|
+
/** Component id declared in app.yaml and registered via defineComponent. */
|
|
118
|
+
componentId: string;
|
|
119
|
+
/** Optional seed props handed to the component renderer. */
|
|
120
|
+
props?: Record<string, unknown>;
|
|
123
121
|
};
|
|
124
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Result contract of a handoff's child conversation — what the specialist
|
|
125
|
+
* agent must hand back before control returns to the caller.
|
|
126
|
+
*/
|
|
127
|
+
export interface HandbackSpec {
|
|
128
|
+
/**
|
|
129
|
+
* JSON Schema the handback artifact must satisfy. The specialist agent gets
|
|
130
|
+
* a `submit_output` tool AJV-validated against it; invalid submissions
|
|
131
|
+
* bounce back as tool errors until they conform.
|
|
132
|
+
*/
|
|
133
|
+
schema: Record<string, unknown>;
|
|
134
|
+
/**
|
|
135
|
+
* Optional action the host runs on each submission AFTER the schema passes,
|
|
136
|
+
* for app-specific semantic checks the schema can't express. It receives the
|
|
137
|
+
* candidate payload as its input and must return `{ valid: boolean,
|
|
138
|
+
* errors?: string[] }` in `data`. Invalid (or any validator failure —
|
|
139
|
+
* fail-closed) bounces the submission back to the agent with the errors.
|
|
140
|
+
* Must be read-only: it can run once per submission attempt.
|
|
141
|
+
*/
|
|
142
|
+
validate?: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Transfer the floor to another agent. When an agent-callable action returns
|
|
146
|
+
* this, the calling agent suspends and the host opens a dedicated child session
|
|
147
|
+
* the guardian collaborates in with `agentName` (see Workflow Studio's
|
|
148
|
+
* `design_workflow`). The parent thread is locked until control returns.
|
|
149
|
+
*
|
|
150
|
+
* The handoff itself mounts no app surface — the summoned agent brings one up on
|
|
151
|
+
* demand by calling the `show_app` action (e.g. Workflow Studio's author shows
|
|
152
|
+
* its live storyboard once there is a plan to preview). `appId` only names the
|
|
153
|
+
* app that owns the handoff (the host install-checks it).
|
|
154
|
+
*
|
|
155
|
+
* The handback: when `handback` is set, a schema-valid (and, if declared,
|
|
156
|
+
* app-validated) `submit_output` submission renders an approval card in the
|
|
157
|
+
* child session; guardian approval ends the handoff and posts the payload as
|
|
158
|
+
* an `interaction_result` on the parent session, re-driving the caller with a
|
|
159
|
+
* server-built outcome prompt (plus `handbackHint`). Dismissal hands control
|
|
160
|
+
* back with `{ dismissed: true }` and no artifact.
|
|
161
|
+
*/
|
|
162
|
+
export interface Handoff {
|
|
163
|
+
/** The app that owns this handoff (the host install-checks it). */
|
|
164
|
+
appId: string;
|
|
165
|
+
/**
|
|
166
|
+
* Off-webchat fallback. Only webchat can run a handoff; on a messaging
|
|
167
|
+
* channel (or inside a subagent) the calling agent relays this text as prose
|
|
168
|
+
* and the guardian's reply arrives as the next turn.
|
|
169
|
+
*/
|
|
170
|
+
promptText: string;
|
|
171
|
+
/**
|
|
172
|
+
* Agent the guardian collaborates with in the child session. Omit for a
|
|
173
|
+
* handoff that needs no conversation.
|
|
174
|
+
*/
|
|
175
|
+
agentName?: string;
|
|
176
|
+
/** Optional seed context (e.g. the opening summary). */
|
|
177
|
+
payload?: Record<string, unknown>;
|
|
178
|
+
/** Result contract the specialist must satisfy to hand control back. */
|
|
179
|
+
handback?: HandbackSpec;
|
|
180
|
+
/**
|
|
181
|
+
* Appended to the resolution prompt the resumed caller receives, so the
|
|
182
|
+
* caller learns its exact next step. The literal token `<childSessionId>` is
|
|
183
|
+
* substituted with the handoff's child session id by the host.
|
|
184
|
+
*/
|
|
185
|
+
handbackHint?: string;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Place one of this app's web widgets onto the guardian's workspace (the
|
|
189
|
+
* freegrid), WITHOUT parking the calling agent. Unlike {@link PendingInteraction}
|
|
190
|
+
* — which suspends the turn and waits for the guardian to resolve a surface —
|
|
191
|
+
* this is fire-and-forget: the widget is mounted as a side effect and the agent
|
|
192
|
+
* is told it succeeded and keeps going on the same turn. Use it to surface a
|
|
193
|
+
* read-only view the guardian can glance at (e.g. Workflow Studio's storyboard),
|
|
194
|
+
* not to collect input.
|
|
195
|
+
*
|
|
196
|
+
* Only takes effect on a webchat turn (the placement rides the turn's event
|
|
197
|
+
* stream to the browser). On a messaging channel or inside a subagent there is
|
|
198
|
+
* no workspace, so the calling agent is told the widget could not be shown.
|
|
199
|
+
*/
|
|
200
|
+
export interface PlaceWidget {
|
|
201
|
+
/** This app's id — the app whose web widget is mounted onto the freegrid. */
|
|
202
|
+
appId: string;
|
|
203
|
+
/**
|
|
204
|
+
* `true` scopes the placement to the current chat session: the widget is added
|
|
205
|
+
* to this session's layout and mounted with `?session=<id>`, so a session-keyed
|
|
206
|
+
* surface shows this conversation's state. `false` is a standing placement that
|
|
207
|
+
* persists across sessions (as on app install).
|
|
208
|
+
*/
|
|
209
|
+
sessionScoped: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Optional route within the app, e.g. `"orders/123"`. It rides the widget src
|
|
212
|
+
* as the path after the app id (`/full/apps/<appId>/orders/123`), which the
|
|
213
|
+
* host forwards to the app as `bootstrap.routePath` so the app's own router
|
|
214
|
+
* resolves it. An unknown route is the app's to handle (typically a not-found
|
|
215
|
+
* screen). This is *addressing*, not data: payloads belong in the app's own
|
|
216
|
+
* session storage, which the route reads on mount (keyed by `session` + `params`).
|
|
217
|
+
*/
|
|
218
|
+
route?: string;
|
|
219
|
+
/**
|
|
220
|
+
* Optional flat scalar parameters carried as query params on the widget src
|
|
221
|
+
* (`?orderId=123`). The app reads them off `window.location.search`. Values must
|
|
222
|
+
* be primitives so they serialize into the persisted placement and survive
|
|
223
|
+
* remount. Host-owned query keys (`session`, `interaction`) always win.
|
|
224
|
+
*/
|
|
225
|
+
params?: Record<string, string | number | boolean>;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The envelope every action returns, discriminated on `status`. This one type
|
|
229
|
+
* crosses every invocation boundary — agent↔action tool results, app↔app
|
|
230
|
+
* `runAction`, webhook invocation records — so the states are modeled as a union
|
|
231
|
+
* rather than independent flags: a result is exactly one of completed (`ok`),
|
|
232
|
+
* domain-rejected (`error`), suspended on approval, suspended on an inline
|
|
233
|
+
* guardian input (`pending_interaction`), suspended on a handoff to another agent
|
|
234
|
+
* (`handoff`), or completed-with-a-widget-placed (`place_widget`, which does NOT
|
|
235
|
+
* suspend). Infrastructure failures (handler throw, serialization, worker crash)
|
|
236
|
+
* are NOT `error` results — they surface as a thrown {@link ActionInvocationError}.
|
|
237
|
+
* The `error` variant is for domain rejections the caller can act on ("routine
|
|
238
|
+
* name already taken").
|
|
239
|
+
*/
|
|
240
|
+
export type ActionResult<T = unknown> = {
|
|
241
|
+
status: "ok";
|
|
242
|
+
data?: T;
|
|
243
|
+
} | {
|
|
244
|
+
status: "error";
|
|
245
|
+
error: string;
|
|
246
|
+
} | {
|
|
247
|
+
status: "pending_approval";
|
|
248
|
+
approval: PendingApproval;
|
|
249
|
+
} | {
|
|
250
|
+
status: "pending_interaction";
|
|
251
|
+
interaction: PendingInteraction;
|
|
252
|
+
} | {
|
|
253
|
+
status: "handoff";
|
|
254
|
+
handoff: Handoff;
|
|
255
|
+
} | {
|
|
256
|
+
status: "place_widget";
|
|
257
|
+
placement: PlaceWidget;
|
|
258
|
+
};
|
|
125
259
|
/**
|
|
126
260
|
* Build an {@link Action} from a Zod input schema. The schema is the single
|
|
127
261
|
* source of truth: it generates the model-facing JSON Schema (`inputSchema`),
|
|
@@ -246,42 +380,77 @@ export interface AgentLifecycleHookDeps {
|
|
|
246
380
|
appContext?: RomeAppContext;
|
|
247
381
|
agentRunner?: AgentRunnerInterface;
|
|
248
382
|
}
|
|
249
|
-
|
|
383
|
+
/** Turn bracketing: the first event of a turn's stream. */
|
|
384
|
+
export interface TurnStartMessage {
|
|
385
|
+
type: "turn_start";
|
|
386
|
+
turnId: string;
|
|
387
|
+
/** Session the turn runs on — stable across turns of a conversation. */
|
|
388
|
+
sessionId: string;
|
|
389
|
+
userPrompt: string;
|
|
390
|
+
}
|
|
391
|
+
/** Turn bracketing: the last event of a turn's stream, emitted after the
|
|
392
|
+
* terminal `result`/`error` block. */
|
|
393
|
+
export interface TurnEndMessage {
|
|
394
|
+
type: "turn_end";
|
|
395
|
+
turnId: string;
|
|
396
|
+
/** Turn outcome. `interrupted` means the user stopped the turn mid-flight;
|
|
397
|
+
* it takes precedence over `error` (an abort surfaced as an error block is
|
|
398
|
+
* still an interruption, not a failure). */
|
|
399
|
+
status: "completed" | "interrupted" | "error";
|
|
400
|
+
/** Turn wall-clock measured by the AgentSession. Distinct from
|
|
401
|
+
* `accounting.durationMs` on the terminal block, which is the
|
|
402
|
+
* provider's self-reported per-call duration. */
|
|
403
|
+
durationMs: number;
|
|
404
|
+
}
|
|
405
|
+
export interface TextMessage {
|
|
250
406
|
type: "text";
|
|
251
407
|
content: string;
|
|
252
|
-
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Incremental preview of an in-flight `text` block (provider streaming).
|
|
411
|
+
* Transient: the complete `text` block still follows, so consumers that
|
|
412
|
+
* only care about whole blocks (trace, persistence, accounting) must
|
|
413
|
+
* ignore this variant. Emitted only by providers that support partial
|
|
414
|
+
* output; absence degrades to whole-block delivery.
|
|
415
|
+
*/
|
|
416
|
+
export interface TextDeltaMessage {
|
|
417
|
+
type: "text_delta";
|
|
418
|
+
content: string;
|
|
419
|
+
}
|
|
420
|
+
export interface ThinkingMessage {
|
|
253
421
|
type: "thinking";
|
|
254
422
|
content: string;
|
|
255
|
-
}
|
|
423
|
+
}
|
|
424
|
+
export interface ToolUseMessage {
|
|
256
425
|
type: "tool_use";
|
|
257
426
|
id: string;
|
|
258
427
|
tool: string;
|
|
259
428
|
input: unknown;
|
|
260
429
|
startedAt?: string;
|
|
261
|
-
}
|
|
430
|
+
}
|
|
431
|
+
export interface ToolResultMessage {
|
|
262
432
|
type: "tool_result";
|
|
263
433
|
toolUseId: string;
|
|
264
434
|
tool: string;
|
|
265
435
|
output: unknown;
|
|
266
436
|
endedAt?: string;
|
|
267
|
-
}
|
|
437
|
+
}
|
|
438
|
+
/** Terminal content block: the agent's final answer for its turn.
|
|
439
|
+
* The turn boundary itself is the `turn_end` event that follows. */
|
|
440
|
+
export interface ResultMessage {
|
|
268
441
|
type: "result";
|
|
269
442
|
content: string;
|
|
443
|
+
/** Provider-reported usage for the agent that produced this block.
|
|
444
|
+
* Sub-agent terminals carry their own accounting. */
|
|
270
445
|
accounting?: AgentAccounting;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
/** Turn wall-clock; set only when `turnTerminal === true`. Separate
|
|
275
|
-
* from `accounting.durationMs`, which is the provider's per-call
|
|
276
|
-
* duration. */
|
|
277
|
-
turnDurationMs?: number;
|
|
278
|
-
} | {
|
|
446
|
+
}
|
|
447
|
+
/** Terminal content block: the turn failed. `turn_end` still follows. */
|
|
448
|
+
export interface ErrorMessage {
|
|
279
449
|
type: "error";
|
|
280
450
|
error: string;
|
|
281
451
|
accounting?: AgentAccounting;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
} | {
|
|
452
|
+
}
|
|
453
|
+
export interface SessionInitMessage {
|
|
285
454
|
type: "session_init";
|
|
286
455
|
sessionId: string;
|
|
287
456
|
systemPrompt?: string;
|
|
@@ -289,17 +458,19 @@ export type AgentMessage = {
|
|
|
289
458
|
projectPath?: string;
|
|
290
459
|
/** RFC 013: per-turn id allocated by AgentSession.sendTurn. */
|
|
291
460
|
turnId?: string;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Structured payload an agent submitted via its `outputSchema` (RFC 016
|
|
464
|
+
* §submit_output). Emitted by AgentSession only AFTER the payload has
|
|
465
|
+
* been schema-validated and accepted, so consumers can treat it as
|
|
466
|
+
* authoritative — distinct from the raw `tool_use` event for the
|
|
467
|
+
* underlying `submit_output` tool which represents the model's proposal.
|
|
468
|
+
*/
|
|
469
|
+
export interface StructuredOutputMessage {
|
|
300
470
|
type: "structured_output";
|
|
301
471
|
payload: unknown;
|
|
302
|
-
}
|
|
472
|
+
}
|
|
473
|
+
export type AgentMessage = TurnStartMessage | TurnEndMessage | TextMessage | TextDeltaMessage | ThinkingMessage | ToolUseMessage | ToolResultMessage | ResultMessage | ErrorMessage | SessionInitMessage | StructuredOutputMessage;
|
|
303
474
|
export type StreamAgentMessage = AgentMessage & {
|
|
304
475
|
agent?: string;
|
|
305
476
|
};
|
|
@@ -312,6 +483,12 @@ export interface ThreadContext {
|
|
|
312
483
|
threadType?: "private" | "group";
|
|
313
484
|
projectName?: string;
|
|
314
485
|
projectPath?: string;
|
|
486
|
+
/**
|
|
487
|
+
* Bond level of the message sender, when known. Lets turn-level logic tell the
|
|
488
|
+
* guardian apart from other trusted senders (inner-circle, acquaintance) who
|
|
489
|
+
* reach the same `<channel>:<thread>` trusted path.
|
|
490
|
+
*/
|
|
491
|
+
senderBondLevel?: string;
|
|
315
492
|
}
|
|
316
493
|
export interface RunParams {
|
|
317
494
|
agentName: string;
|
|
@@ -334,6 +511,27 @@ export interface ForkRunParams {
|
|
|
334
511
|
export interface AgentRunnerInterface {
|
|
335
512
|
run(params: RunParams): AsyncIterable<AgentMessage>;
|
|
336
513
|
runForked?(params: ForkRunParams): AsyncIterable<AgentMessage>;
|
|
514
|
+
/**
|
|
515
|
+
* Returns true when the agent with the given name is loaded in the catalog
|
|
516
|
+
* and can be invoked via `run`. Used by callers (e.g. the inbox message
|
|
517
|
+
* handler) to fall back gracefully when a channel is configured to route to
|
|
518
|
+
* an agent that has been uninstalled. Optional for backwards compatibility;
|
|
519
|
+
* implementations that don't provide it are treated as always-true by
|
|
520
|
+
* callers. May be async — the worker-side runner resolves the catalog over
|
|
521
|
+
* RPC, so callers must `await` the result.
|
|
522
|
+
*/
|
|
523
|
+
hasAgent?(name: string): boolean | Promise<boolean>;
|
|
524
|
+
/**
|
|
525
|
+
* Returns true when the named agent is allowed to call the named action —
|
|
526
|
+
* i.e. the action resolves through the agent's allow-list (or `*`, or a
|
|
527
|
+
* globally-granted action), the same resolution the agent session uses to
|
|
528
|
+
* gate tool calls. Lets callers (e.g. the inbox message handler) tailor
|
|
529
|
+
* guidance to what the routed agent can actually do, instead of assuming.
|
|
530
|
+
* Optional for backwards compatibility; implementations that don't provide
|
|
531
|
+
* it are treated as "cannot" by callers. May be async — the worker-side
|
|
532
|
+
* runner resolves the catalog over RPC, so callers must `await` the result.
|
|
533
|
+
*/
|
|
534
|
+
hasAction?(agentName: string, actionName: string): boolean | Promise<boolean>;
|
|
337
535
|
}
|
|
338
536
|
export interface Attachment {
|
|
339
537
|
type: "image" | "video" | "audio" | "document" | "sticker" | "location" | "contact";
|
|
@@ -385,26 +583,6 @@ export type MessagePart = {
|
|
|
385
583
|
actionName: string;
|
|
386
584
|
preview: PreviewPayload;
|
|
387
585
|
status: ApprovalCardStatus;
|
|
388
|
-
} | {
|
|
389
|
-
/**
|
|
390
|
-
* The model called the built-in `ask_user_question` MCP tool. The host
|
|
391
|
-
* channel (web chat today) snapshots the tool's input into this part so
|
|
392
|
-
* the question card renders as a first-class assistant message, not a
|
|
393
|
-
* detail buried inside the trace drawer.
|
|
394
|
-
*/
|
|
395
|
-
type: "ask_user_question_card";
|
|
396
|
-
toolUseId: string;
|
|
397
|
-
questions: AskUserQuestionDefinition[];
|
|
398
|
-
} | {
|
|
399
|
-
/**
|
|
400
|
-
* A user's reply to a previously rendered ask_user_question card. Lives
|
|
401
|
-
* inside a user-role webchat message so the UI can derive "this question
|
|
402
|
-
* was answered" by scanning subsequent messages for a matching
|
|
403
|
-
* toolUseId, instead of mutating any tool_use block in place.
|
|
404
|
-
*/
|
|
405
|
-
type: "user_answer";
|
|
406
|
-
toolUseId: string;
|
|
407
|
-
answers: UserAnswerEntry[];
|
|
408
586
|
} | {
|
|
409
587
|
/**
|
|
410
588
|
* An interactive "routine draft" the agent proposes mid-conversation.
|
|
@@ -417,6 +595,62 @@ export type MessagePart = {
|
|
|
417
595
|
type: "routine_draft_card";
|
|
418
596
|
toolUseId: string;
|
|
419
597
|
draft: RoutineDraftSpec;
|
|
598
|
+
} | {
|
|
599
|
+
/**
|
|
600
|
+
* A parked inline guardian input the agent is waiting on. The action that
|
|
601
|
+
* called for it returned a `pending_interaction` result; the webchat drain
|
|
602
|
+
* loop snapshots this part keyed by the tool call's id, and the host
|
|
603
|
+
* mounts the app's component in the transcript. The component lives in
|
|
604
|
+
* the app, not core.
|
|
605
|
+
*/
|
|
606
|
+
type: "pending_interaction";
|
|
607
|
+
toolUseId: string;
|
|
608
|
+
appId: string;
|
|
609
|
+
render: {
|
|
610
|
+
kind: "inline";
|
|
611
|
+
componentId: string;
|
|
612
|
+
props?: Record<string, unknown>;
|
|
613
|
+
};
|
|
614
|
+
} | {
|
|
615
|
+
/**
|
|
616
|
+
* A handoff in progress: the calling agent suspended and `agentName`
|
|
617
|
+
* holds the floor in `childSessionId` (the spawned design conversation),
|
|
618
|
+
* with the app's `surface` mounted as a side-by-side widget. The webchat
|
|
619
|
+
* drain loop snapshots this part keyed by the tool call's id.
|
|
620
|
+
*/
|
|
621
|
+
type: "handoff";
|
|
622
|
+
toolUseId: string;
|
|
623
|
+
appId: string;
|
|
624
|
+
surface: string;
|
|
625
|
+
agentName?: string;
|
|
626
|
+
payload?: Record<string, unknown>;
|
|
627
|
+
childSessionId?: string;
|
|
628
|
+
/** Mirrors {@link Handoff.handbackHint}; appended to the resolution
|
|
629
|
+
* prompt when the handoff resolves with an artifact. */
|
|
630
|
+
handbackHint?: string;
|
|
631
|
+
} | {
|
|
632
|
+
/**
|
|
633
|
+
* A schema-valid payload the specialist agent submitted via
|
|
634
|
+
* `submit_output` in a handoff child session that carries a handback
|
|
635
|
+
* contract. The host renders it as an approval card: Approve ends the
|
|
636
|
+
* handoff with `payload` as the output; "keep editing" feedback continues
|
|
637
|
+
* the conversation and a later submission supersedes this card.
|
|
638
|
+
*/
|
|
639
|
+
type: "submission_card";
|
|
640
|
+
payload: Record<string, unknown>;
|
|
641
|
+
} | {
|
|
642
|
+
/**
|
|
643
|
+
* Resolution of an inline interaction or a handoff — the single
|
|
644
|
+
* resolution part both suspension kinds share. Lives in a user-role
|
|
645
|
+
* webchat message so the UI derives "this resolved" by scanning for a
|
|
646
|
+
* matching toolUseId, and the server re-drives the calling agent with a
|
|
647
|
+
* server-built outcome prompt. `output` is the produced artifact (a
|
|
648
|
+
* handoff's approved handback payload, or an inline component's result),
|
|
649
|
+
* or `{ dismissed: true }`.
|
|
650
|
+
*/
|
|
651
|
+
type: "interaction_result";
|
|
652
|
+
toolUseId: string;
|
|
653
|
+
output: Record<string, unknown>;
|
|
420
654
|
};
|
|
421
655
|
/** The proposed routine, as snapshotted from the agent's `propose_routine`
|
|
422
656
|
* tool call. `name`/`trigger`/`actionName`/`args` are the create payload;
|
|
@@ -441,45 +675,20 @@ export interface RoutineDraftSpec {
|
|
|
441
675
|
/** Single argument object for the action. */
|
|
442
676
|
args: Record<string, unknown>;
|
|
443
677
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
text: string;
|
|
459
|
-
preview?: AskUserQuestionOptionPreview;
|
|
460
|
-
}
|
|
461
|
-
export interface AskUserQuestionOptionPreview {
|
|
462
|
-
url: string;
|
|
463
|
-
kind?: "image" | "video" | "html" | "csv";
|
|
464
|
-
alt?: string;
|
|
465
|
-
}
|
|
466
|
-
export type UserAnswerEntry = {
|
|
467
|
-
type: "single";
|
|
468
|
-
questionId: string;
|
|
469
|
-
selected: string;
|
|
470
|
-
selectedText?: string;
|
|
471
|
-
freeText?: string;
|
|
472
|
-
} | {
|
|
473
|
-
type: "multi";
|
|
474
|
-
questionId: string;
|
|
475
|
-
selected: string[];
|
|
476
|
-
selectedText?: string[];
|
|
477
|
-
freeText?: string;
|
|
478
|
-
} | {
|
|
479
|
-
type: "text";
|
|
480
|
-
questionId: string;
|
|
481
|
-
text: string;
|
|
482
|
-
};
|
|
678
|
+
/**
|
|
679
|
+
* Optional per-message routing overrides resolved by the channel adapter from
|
|
680
|
+
* its channel-level configuration. When present, the downstream message handler
|
|
681
|
+
* uses these to override the default trusted-path target agent. Untrusted
|
|
682
|
+
* messages still go through sentinel regardless.
|
|
683
|
+
*/
|
|
684
|
+
export interface MessageRouting {
|
|
685
|
+
/**
|
|
686
|
+
* Name of the agent to route this message to on the trusted path. Falls back
|
|
687
|
+
* to the default ("main") when undefined or when the named agent is not
|
|
688
|
+
* present in the catalog.
|
|
689
|
+
*/
|
|
690
|
+
agentName?: string;
|
|
691
|
+
}
|
|
483
692
|
export interface NormalizedMessage {
|
|
484
693
|
id: string;
|
|
485
694
|
channel: "telegram" | "telegram_user" | "whatsapp" | "wechat" | "webchat" | "discord";
|
|
@@ -492,6 +701,7 @@ export interface NormalizedMessage {
|
|
|
492
701
|
text: string;
|
|
493
702
|
attachments: Attachment[];
|
|
494
703
|
replyToMessageId?: string;
|
|
704
|
+
routing?: MessageRouting;
|
|
495
705
|
rawEvent: unknown;
|
|
496
706
|
}
|
|
497
707
|
export interface ChannelAdapter {
|
|
@@ -600,6 +810,20 @@ export interface RomeAppContext {
|
|
|
600
810
|
runAction(name: string, args: Record<string, unknown>): Promise<ActionResult>;
|
|
601
811
|
listRoutines(): Promise<Routine[]>;
|
|
602
812
|
}
|
|
813
|
+
export type ActionInvocationErrorCode = "not_found" | "unserializable" | "handler_error" | "worker_failure";
|
|
814
|
+
/**
|
|
815
|
+
* The single failure shape of `RomeAppContext.runAction`, RFC 030. Every
|
|
816
|
+
* invocation failure — unknown action, args/result that can't cross a process
|
|
817
|
+
* boundary, a throwing handler, a dead worker — surfaces as this type with the
|
|
818
|
+
* same fields regardless of which process the caller or callee ran in, so app
|
|
819
|
+
* code never branches on transport. Cancellation is the one pass-through: it
|
|
820
|
+
* is a control signal for the runtime, not a failure the app handles.
|
|
821
|
+
*/
|
|
822
|
+
export declare class ActionInvocationError extends Error {
|
|
823
|
+
readonly actionName: string;
|
|
824
|
+
readonly code: ActionInvocationErrorCode;
|
|
825
|
+
constructor(actionName: string, code: ActionInvocationErrorCode, message: string);
|
|
826
|
+
}
|
|
603
827
|
export type AppActionRuntimeDeps<TShared = Record<string, unknown>> = TShared & {
|
|
604
828
|
appContext: RomeAppContext;
|
|
605
829
|
};
|
|
@@ -741,6 +965,20 @@ export interface EventBusTrigger {
|
|
|
741
965
|
export interface EventCatalogEntry {
|
|
742
966
|
eventType: string;
|
|
743
967
|
appId: string;
|
|
968
|
+
/** JSON Schema for the event's payload — the same vocabulary action input
|
|
969
|
+
* schemas use. With `schemaOrigin: "observed"` it is inferred from the most
|
|
970
|
+
* recent non-empty emission, so it is a discovery aid for a consumer writing
|
|
971
|
+
* a routine `trigger.filter` (whose dot-paths read payload fields), **not** a
|
|
972
|
+
* contract: it reflects one observed payload, may omit optional keys, and
|
|
973
|
+
* deliberately carries no `required` (one sample can't establish
|
|
974
|
+
* requiredness). Absent until the type has been emitted with a non-empty
|
|
975
|
+
* payload. */
|
|
976
|
+
payloadSchema?: JSONSchema.ObjectSchema;
|
|
977
|
+
/** Where `payloadSchema` came from. `"observed"` = inferred from a real
|
|
978
|
+
* emission. `"declared"` is reserved for producer-authored schemas
|
|
979
|
+
* (pre-registration); a declared schema is authoritative and is never
|
|
980
|
+
* overwritten by an observed one. */
|
|
981
|
+
schemaOrigin?: "observed" | "declared";
|
|
744
982
|
}
|
|
745
983
|
export interface PollTrigger {
|
|
746
984
|
type: "poll";
|
|
@@ -812,9 +1050,28 @@ export interface EventCatalogReader {
|
|
|
812
1050
|
total: number;
|
|
813
1051
|
}>;
|
|
814
1052
|
}
|
|
1053
|
+
/** A Discord guild channel as enumerated by the running bot. */
|
|
1054
|
+
export interface DiscordGuildChannel {
|
|
1055
|
+
id: string;
|
|
1056
|
+
name: string;
|
|
1057
|
+
guildId: string;
|
|
1058
|
+
guildName: string;
|
|
1059
|
+
type: string;
|
|
1060
|
+
parentId?: string;
|
|
1061
|
+
}
|
|
1062
|
+
/** Control surface of the live Discord adapter (which runs in the main
|
|
1063
|
+
* process). Both operations tolerate the adapter not running: `reloadConfig`
|
|
1064
|
+
* is a no-op and `listChannels` returns `[]`, so callers can render a clean
|
|
1065
|
+
* "Discord not configured" outcome instead of handling transport errors. */
|
|
1066
|
+
export interface DiscordChannelControl {
|
|
1067
|
+
reloadConfig(): Promise<void>;
|
|
1068
|
+
listChannels(): Promise<DiscordGuildChannel[]>;
|
|
1069
|
+
}
|
|
815
1070
|
/** App lifecycle authority (create / install / uninstall / enable). Results are
|
|
816
1071
|
* app-local shapes the caller knows, so they cross this surface as `unknown` and
|
|
817
|
-
* the caller narrows — the SDK stays free of the concrete result types.
|
|
1072
|
+
* the caller narrows — the SDK stays free of the concrete result types.
|
|
1073
|
+
* `install` takes no appId: the daemon derives it from the source (manifest id
|
|
1074
|
+
* for local sources, listing slug for appstore) and returns it in the result. */
|
|
818
1075
|
export interface AppLifecycle {
|
|
819
1076
|
create(params: {
|
|
820
1077
|
appId: string;
|
|
@@ -822,7 +1079,6 @@ export interface AppLifecycle {
|
|
|
822
1079
|
template?: "default" | "workflow";
|
|
823
1080
|
}): Promise<unknown>;
|
|
824
1081
|
install(params: {
|
|
825
|
-
appId: string;
|
|
826
1082
|
source: unknown;
|
|
827
1083
|
enabled?: boolean;
|
|
828
1084
|
}): Promise<unknown>;
|