@stratusagent/core 0.11.6 → 0.11.8
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 +563 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +856 -107
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -151,9 +151,11 @@ export interface Message {
|
|
|
151
151
|
toolCalls?: ToolCall[];
|
|
152
152
|
toolResult?: ToolResult;
|
|
153
153
|
/**
|
|
154
|
-
* Images sent with a user message
|
|
155
|
-
*
|
|
156
|
-
*
|
|
154
|
+
* Images sent with a user message, or returned by a tool call (moved
|
|
155
|
+
* here off `ToolResult.images` as the result is recorded). Present only
|
|
156
|
+
* on `user` and `tool` messages that carried one; a provider that can
|
|
157
|
+
* show the model an image sends these alongside the text, and one that
|
|
158
|
+
* cannot names them instead.
|
|
157
159
|
*/
|
|
158
160
|
images?: ImageAttachment[];
|
|
159
161
|
/**
|
|
@@ -169,6 +171,44 @@ export interface Message {
|
|
|
169
171
|
* — the boundary provenance draws, here at the point text enters.
|
|
170
172
|
*/
|
|
171
173
|
overheard?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Appended by `observe`, so it started no turn. `overheard` alone cannot
|
|
176
|
+
* say so: a turn dispatched with `addressed: false` is overheard too, and
|
|
177
|
+
* is a turn. Present only when true; a message observed before this was
|
|
178
|
+
* recorded reads as a turn, which errs toward attributing nothing to an
|
|
179
|
+
* earlier one (`isLatestTurn`).
|
|
180
|
+
*/
|
|
181
|
+
observed?: boolean;
|
|
182
|
+
/**
|
|
183
|
+
* The caller's idempotency key for the dispatch that brought this user
|
|
184
|
+
* message (`RunInput.idempotencyKey`). Written in the same save as the
|
|
185
|
+
* message, so a key is never durable without its message or the other
|
|
186
|
+
* way round; `workItemState` reads it back.
|
|
187
|
+
*/
|
|
188
|
+
idempotencyKey?: string;
|
|
189
|
+
/**
|
|
190
|
+
* Why the turn this user message started failed, written by
|
|
191
|
+
* `recordTurnFailure` in the save that fails it. The session's
|
|
192
|
+
* `lastError` is the latest turn's and the next turn replaces it; this
|
|
193
|
+
* stays, so `turnFailureFor` can answer for any turn a key names.
|
|
194
|
+
*/
|
|
195
|
+
turnError?: string;
|
|
196
|
+
/**
|
|
197
|
+
* This message's turn was continued once after the process running it
|
|
198
|
+
* died (`AgentRunner.continueTurn`). A host fails a second such turn
|
|
199
|
+
* instead of continuing it again: a turn that takes the process down
|
|
200
|
+
* with it would otherwise do so on every start. Present only when true.
|
|
201
|
+
*/
|
|
202
|
+
continuedAfterCrash?: boolean;
|
|
203
|
+
/**
|
|
204
|
+
* The turn this message started could reach a provider that runs its own
|
|
205
|
+
* tool loop (a harness): what that turn did is not all in this
|
|
206
|
+
* transcript, so a crash mid-turn cannot be continued from it. Recorded
|
|
207
|
+
* at accept time, because the runtime a crashed turn ran on is not the
|
|
208
|
+
* one a restart resolves if the configuration changed in between.
|
|
209
|
+
* Present only when true; see `RunInput.hostedLoop`.
|
|
210
|
+
*/
|
|
211
|
+
hostedLoop?: boolean;
|
|
172
212
|
}
|
|
173
213
|
export interface AgentDescriptor {
|
|
174
214
|
id: string;
|
|
@@ -368,7 +408,48 @@ export interface ToolResult {
|
|
|
368
408
|
* already hold hostile page content. A new result always carries one.
|
|
369
409
|
*/
|
|
370
410
|
trust?: TrustLevel;
|
|
411
|
+
/**
|
|
412
|
+
* Images the call handed back through `ExecutionContext.attachImage` — a
|
|
413
|
+
* screenshot, an image file read from disk. In flight only: the runner
|
|
414
|
+
* moves them onto the tool message's `images` as it records the result,
|
|
415
|
+
* so they are stored, budgeted, and trimmed exactly as a user message's
|
|
416
|
+
* images are, and never serialized into the message content or carried
|
|
417
|
+
* on a bus event.
|
|
418
|
+
*/
|
|
419
|
+
images?: ImageAttachment[];
|
|
371
420
|
}
|
|
421
|
+
/**
|
|
422
|
+
* What the model is told about a result labelled `external`, said once
|
|
423
|
+
* here rather than left for each tool to word — a third-party plugin or an
|
|
424
|
+
* MCP server never has to know the convention for its output to carry it.
|
|
425
|
+
*/
|
|
426
|
+
export declare const UNTRUSTED_TOOL_RESULT_NOTE: string;
|
|
427
|
+
/**
|
|
428
|
+
* The text a provider hands the model for a tool result — the one
|
|
429
|
+
* serialization every provider and harness bridge uses, so the trust label
|
|
430
|
+
* reaches the model the same way whichever one carries the turn.
|
|
431
|
+
*
|
|
432
|
+
* An `external` result is wrapped in `{ untrusted, untrustedNote, output }`,
|
|
433
|
+
* the vocabulary `web.search` already used in-band. This marks the boundary
|
|
434
|
+
* and nothing more: a model can still follow text inside the envelope, and
|
|
435
|
+
* it is not a prompt-injection defence. Only `external` is wrapped, not
|
|
436
|
+
* `unknown`: `shell.run` declares `unknown`, and a marker on every command's
|
|
437
|
+
* output would teach the model that the marker is noise. A failed result is
|
|
438
|
+
* wrapped too, because the executor labels failures — a fetched server's
|
|
439
|
+
* error text is that server's text.
|
|
440
|
+
*
|
|
441
|
+
* The envelope is applied whatever the output already says, including
|
|
442
|
+
* `web.search`'s own `untrusted: true`. Skipping on a field of the output
|
|
443
|
+
* would let the output decide whether it is marked, and the output is the
|
|
444
|
+
* party not trusted; the repetition costs a sentence.
|
|
445
|
+
*
|
|
446
|
+
* Never mutates the result: the transcript, the dashboard, and the control
|
|
447
|
+
* API read the raw output. Deterministic for a given result, so a replayed
|
|
448
|
+
* transcript is byte-identical and the prompt cache holds. `Tool failed`
|
|
449
|
+
* stays unpunctuated because the API providers replay it from persisted
|
|
450
|
+
* transcripts, where a changed byte is a cache miss.
|
|
451
|
+
*/
|
|
452
|
+
export declare const renderToolResultContent: (result: Pick<ToolResult, "ok" | "output" | "error" | "trust">) => string;
|
|
372
453
|
export type ProviderPart = {
|
|
373
454
|
type: 'text';
|
|
374
455
|
text: string;
|
|
@@ -379,7 +460,8 @@ export type ProviderPart = {
|
|
|
379
460
|
/**
|
|
380
461
|
* A streamed fragment of an in-progress provider response. Text deltas carry
|
|
381
462
|
* output as it is generated; tool-call deltas announce that the model has
|
|
382
|
-
* started emitting a call (input may still be incomplete)
|
|
463
|
+
* started emitting a call (input may still be incomplete); thinking and
|
|
464
|
+
* progress deltas carry nothing but the fact of activity. A reset delta
|
|
383
465
|
* tells consumers to DISCARD every fragment streamed so far for this
|
|
384
466
|
* response — emitted when a provider abandons a partial attempt (e.g. a
|
|
385
467
|
* fallback wrapper retrying after the primary failed mid-stream), so
|
|
@@ -400,6 +482,16 @@ export type ProviderDelta = {
|
|
|
400
482
|
*/
|
|
401
483
|
| {
|
|
402
484
|
type: 'thinking';
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* The provider is working on this response and has nothing to show for
|
|
488
|
+
* it yet: a retry it is waiting out, a context compaction, a message
|
|
489
|
+
* boundary. Content-free like `thinking`, and for the same reader — an
|
|
490
|
+
* activity watchdog that would otherwise take a busy provider for a
|
|
491
|
+
* stalled one. A renderer has nothing to draw for it.
|
|
492
|
+
*/
|
|
493
|
+
| {
|
|
494
|
+
type: 'progress';
|
|
403
495
|
} | {
|
|
404
496
|
type: 'reset';
|
|
405
497
|
/**
|
|
@@ -1391,6 +1483,13 @@ export declare class InMemoryAgentMemoryStore implements AgentMemoryStore {
|
|
|
1391
1483
|
* Resolves named credentials for an agent. Implementations must enforce the
|
|
1392
1484
|
* agent's `credentials` allowlist so secrets stay scoped per agent.
|
|
1393
1485
|
*/
|
|
1486
|
+
/** Whose a named credential is: one agent's own, or the whole fleet's. */
|
|
1487
|
+
export type CredentialScope = 'agent' | 'shared';
|
|
1488
|
+
/**
|
|
1489
|
+
* How a credential request reaches a person: a form in the conversation's
|
|
1490
|
+
* own channel, or a one-time link the agent passes on.
|
|
1491
|
+
*/
|
|
1492
|
+
export type CredentialDelivery = 'form' | 'link';
|
|
1394
1493
|
export interface CredentialResolver {
|
|
1395
1494
|
resolve(agent: AgentDefinition, name: string): Promise<string | undefined>;
|
|
1396
1495
|
}
|
|
@@ -1499,6 +1598,99 @@ export declare const uncachedInputTokens: (total: number, ...cached: Array<numbe
|
|
|
1499
1598
|
* nothing at all.
|
|
1500
1599
|
*/
|
|
1501
1600
|
export declare const totalTokenUsage: (records: readonly TokenUsage[]) => TokenUsage | undefined;
|
|
1601
|
+
/**
|
|
1602
|
+
* Facts about how an agent is run that only the host knows, told to the
|
|
1603
|
+
* agent so it does not have to guess them.
|
|
1604
|
+
*
|
|
1605
|
+
* It does guess otherwise, and guesses wrong: an agent asked to reread its
|
|
1606
|
+
* soul after an edit answered that it had none, because there was no
|
|
1607
|
+
* `SOUL.md` in its workspace, which is where other agent runtimes keep one.
|
|
1608
|
+
* Handed in by the host rather than written into the soul because the
|
|
1609
|
+
* paths are the host's to own, and a copy in every soul would go stale the
|
|
1610
|
+
* next time the layout moved, the way the workspace already did once.
|
|
1611
|
+
*/
|
|
1612
|
+
export interface AgentRuntimeContext {
|
|
1613
|
+
/** Absolute path of the soul file this agent's persona was loaded from. */
|
|
1614
|
+
soulPath?: string;
|
|
1615
|
+
/**
|
|
1616
|
+
* True when the host reads the soul again before every turn, so an edit
|
|
1617
|
+
* reaches the agent's next reply. The daemon does; a one-shot run reads
|
|
1618
|
+
* it once, and leaving this out says nothing either way.
|
|
1619
|
+
*/
|
|
1620
|
+
soulReloads?: boolean;
|
|
1621
|
+
/** Where this agent's files go: `AgentWorkspaces.forAgent`. */
|
|
1622
|
+
workspace?: string;
|
|
1623
|
+
/**
|
|
1624
|
+
* The language the agent writes in, as a tag `isLanguageTag` accepts,
|
|
1625
|
+
* already resolved by the host: the soul's `language:`, then the config
|
|
1626
|
+
* file's. Absent means {@link DEFAULT_LANGUAGE}. Rendered in the reply
|
|
1627
|
+
* section rather than here, so a host that says nothing else still gets
|
|
1628
|
+
* the default rule.
|
|
1629
|
+
*/
|
|
1630
|
+
language?: string;
|
|
1631
|
+
/**
|
|
1632
|
+
* What the host has configured to answer as this agent, and what it has
|
|
1633
|
+
* observed: `onFallback` is true once this conversation has switched to
|
|
1634
|
+
* the fallback, which is sticky, so a model asked what it is can tell a
|
|
1635
|
+
* configured default from the one actually answering. The fallback
|
|
1636
|
+
* wrapper sets it on the request it hands the fallback mid-turn, so the
|
|
1637
|
+
* model that took over is not told it is the default.
|
|
1638
|
+
*/
|
|
1639
|
+
model?: AgentModelContext;
|
|
1640
|
+
/**
|
|
1641
|
+
* Who can read this conversation, as the channel that carried the turn
|
|
1642
|
+
* reported it on the turn's metadata (`conversationContextFrom`). Per
|
|
1643
|
+
* turn rather than read off the session, so a thread that started before
|
|
1644
|
+
* this existed, or a channel that grew since, is described as it is now.
|
|
1645
|
+
*/
|
|
1646
|
+
conversation?: ConversationContext;
|
|
1647
|
+
}
|
|
1648
|
+
/**
|
|
1649
|
+
* What kind of room a conversation is: one person, a few, a closed
|
|
1650
|
+
* channel, or one the whole workspace can read. An agent that did not
|
|
1651
|
+
* know told a person in a Slack DM they were "talking on the terminal",
|
|
1652
|
+
* and would have posted the same reply to a thousand-person channel.
|
|
1653
|
+
*/
|
|
1654
|
+
export type ConversationKind = 'direct' | 'group' | 'private' | 'public';
|
|
1655
|
+
export interface ConversationContext {
|
|
1656
|
+
kind: ConversationKind;
|
|
1657
|
+
/** Members as the channel counts them, the agent included. */
|
|
1658
|
+
members?: number;
|
|
1659
|
+
/**
|
|
1660
|
+
* Who a direct message is with. It reaches the system prompt, so a
|
|
1661
|
+
* channel sets it only for someone the operator vouched for (a Slack
|
|
1662
|
+
* principal), never from a name anyone could have typed.
|
|
1663
|
+
*/
|
|
1664
|
+
with?: string;
|
|
1665
|
+
/** The turn is a reply in a thread rather than the channel itself. */
|
|
1666
|
+
thread?: boolean;
|
|
1667
|
+
/**
|
|
1668
|
+
* People outside this workspace read it too: a Slack Connect channel,
|
|
1669
|
+
* or one shared across an organization's workspaces. Never set for a
|
|
1670
|
+
* direct message.
|
|
1671
|
+
*/
|
|
1672
|
+
shared?: boolean;
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* The metadata key a channel adapter records a turn's room under: a
|
|
1676
|
+
* `ConversationContext`-shaped object, read back by
|
|
1677
|
+
* `conversationContextFrom`.
|
|
1678
|
+
*/
|
|
1679
|
+
export declare const CONVERSATION_METADATA_KEY = "conversation";
|
|
1680
|
+
/**
|
|
1681
|
+
* The room a turn's metadata describes, keeping only what is safe to put
|
|
1682
|
+
* in front of the model, or undefined when it describes none.
|
|
1683
|
+
*/
|
|
1684
|
+
export declare const conversationContextFrom: (metadata: JsonObject | undefined) => ConversationContext | undefined;
|
|
1685
|
+
export interface AgentModelContext {
|
|
1686
|
+
provider: string;
|
|
1687
|
+
model?: string;
|
|
1688
|
+
fallback?: {
|
|
1689
|
+
provider: string;
|
|
1690
|
+
model: string;
|
|
1691
|
+
};
|
|
1692
|
+
onFallback?: boolean;
|
|
1693
|
+
}
|
|
1502
1694
|
export interface ProviderRequest {
|
|
1503
1695
|
/**
|
|
1504
1696
|
* The live session. **Persistable**: a provider that saves it, or hands
|
|
@@ -1551,6 +1743,12 @@ export interface ProviderRequest {
|
|
|
1551
1743
|
* the model decides a description is relevant.
|
|
1552
1744
|
*/
|
|
1553
1745
|
skills?: SkillDescriptor[];
|
|
1746
|
+
/**
|
|
1747
|
+
* What the host can say about how this agent is run: where its soul and
|
|
1748
|
+
* workspace are. Rendered as the `runtime` section; see
|
|
1749
|
+
* {@link AgentRuntimeContext}.
|
|
1750
|
+
*/
|
|
1751
|
+
runtime?: AgentRuntimeContext;
|
|
1554
1752
|
/**
|
|
1555
1753
|
* Streaming sink. Adapters that stream call this per fragment and MUST
|
|
1556
1754
|
* await the returned promise before the next call (backpressure); the
|
|
@@ -1657,7 +1855,29 @@ export interface ExecutionContext {
|
|
|
1657
1855
|
* no sink gets whatever `outputTrust` declares.
|
|
1658
1856
|
*/
|
|
1659
1857
|
markTrust?: (trust: TrustLevel) => void;
|
|
1858
|
+
/**
|
|
1859
|
+
* Hand the model an image with this call's result — a screenshot a tool
|
|
1860
|
+
* took, an image file it read — so the agent can actually look at it
|
|
1861
|
+
* rather than be told a path. Checked as it is attached: a format the
|
|
1862
|
+
* model APIs refuse, an image over `IMAGE_ATTACHMENT_MAX_BYTES` or
|
|
1863
|
+
* `IMAGE_ATTACHMENT_MAX_DIMENSION`, bytes that are not the image they
|
|
1864
|
+
* claim to be, or more than `IMAGE_ATTACHMENTS_MAX_TOTAL_BYTES` in one
|
|
1865
|
+
* call throws, so the tool can say so in its own result. Absent when the
|
|
1866
|
+
* host cannot carry images; a tool then says it has no way to show one.
|
|
1867
|
+
*
|
|
1868
|
+
* The result's trust label covers the image too: a screenshot of a web
|
|
1869
|
+
* page is the page's content.
|
|
1870
|
+
*/
|
|
1871
|
+
attachImage?: (image: ImageAttachment) => void;
|
|
1660
1872
|
}
|
|
1873
|
+
/**
|
|
1874
|
+
* Collects what a tool attaches through `ExecutionContext.attachImage`,
|
|
1875
|
+
* held to the limits that sink documents.
|
|
1876
|
+
*/
|
|
1877
|
+
export declare const createImageCollector: () => {
|
|
1878
|
+
attach: (image: ImageAttachment) => void;
|
|
1879
|
+
images: () => ImageAttachment[];
|
|
1880
|
+
};
|
|
1661
1881
|
export interface Tool {
|
|
1662
1882
|
name: string;
|
|
1663
1883
|
description?: string;
|
|
@@ -1842,6 +2062,82 @@ export interface PendingApprovalRecord {
|
|
|
1842
2062
|
* cannot disagree on which message is "the reply".
|
|
1843
2063
|
*/
|
|
1844
2064
|
export declare const latestTurnReply: (session: Pick<Session, "messages">) => string | undefined;
|
|
2065
|
+
/**
|
|
2066
|
+
* Whether a session's transcript already ends in the turn's answer: its
|
|
2067
|
+
* last response holds no tool call, so the loop owed the model nothing more
|
|
2068
|
+
* and only the save marking the turn completed is missing. A continuation
|
|
2069
|
+
* then completes it without a provider call.
|
|
2070
|
+
*
|
|
2071
|
+
* Judged on the last response as a whole: a response's parts are saved
|
|
2072
|
+
* together and its tool results after them all, so the trailing run of
|
|
2073
|
+
* assistant messages is that one response. Any call in it — even one
|
|
2074
|
+
* followed by text, which a provider may send in that order — means the
|
|
2075
|
+
* model is owed another turn. Read it before `reconcileInterruptedToolCalls`
|
|
2076
|
+
* splices results in.
|
|
2077
|
+
*/
|
|
2078
|
+
export declare const lastResponseIsAnswer: (session: Pick<Session, "messages">) => boolean;
|
|
2079
|
+
/**
|
|
2080
|
+
* The end of a turn that answered: marked completed in one save, then
|
|
2081
|
+
* announced. The runner's loop ends here, and so does a turn whose answer
|
|
2082
|
+
* a process saved and then died before marking it completed — which needs
|
|
2083
|
+
* no provider and no current agent definition to finish, so a host can do
|
|
2084
|
+
* it with only its store and bus (`lastResponseIsAnswer` says when).
|
|
2085
|
+
*/
|
|
2086
|
+
export declare const completeAnsweredTurn: (finished: Session, store: SessionStore, bus: EventBus) => Promise<Session>;
|
|
2087
|
+
/**
|
|
2088
|
+
* The longest idempotency key a dispatch accepts. Here rather than in the
|
|
2089
|
+
* gateway that enforces it, because a channel composing keys from ids it
|
|
2090
|
+
* does not bound (an agent's, a platform's) has to fit them to it.
|
|
2091
|
+
*/
|
|
2092
|
+
export declare const MAX_IDEMPOTENCY_KEY_LENGTH = 256;
|
|
2093
|
+
/**
|
|
2094
|
+
* The reply of the turn a keyed message started (`Message.idempotencyKey`),
|
|
2095
|
+
* where `latestTurnReply` is the newest turn's. A repeated dispatch resolves
|
|
2096
|
+
* with the session as it stands, which may have moved on since: an adapter
|
|
2097
|
+
* answering a redelivered message reads the reply here, or it would answer
|
|
2098
|
+
* the old message with a newer turn's words. Undefined when no message
|
|
2099
|
+
* carries the key, or its turn produced no text.
|
|
2100
|
+
*/
|
|
2101
|
+
export declare const turnReplyFor: (session: Pick<Session, "messages">, idempotencyKey: string) => string | undefined;
|
|
2102
|
+
/**
|
|
2103
|
+
* The files the turn a keyed message started produced (`filePathsOf` over
|
|
2104
|
+
* its tool results), the other half of what `turnReplyFor` reads. A
|
|
2105
|
+
* channel uploads a turn's files as the results arrive, so an adapter
|
|
2106
|
+
* answering a repeat of a finished turn — no events, only the session —
|
|
2107
|
+
* has this and nothing else to find them by.
|
|
2108
|
+
*
|
|
2109
|
+
* A path, not the bytes: the transcript never held them. `producedAt` is
|
|
2110
|
+
* when the result naming it was recorded, so a reader can refuse a path
|
|
2111
|
+
* that has been written since — by now it may hold a later turn's file.
|
|
2112
|
+
*/
|
|
2113
|
+
export declare const turnFilesFor: (session: Pick<Session, "messages">, idempotencyKey: string) => Array<{
|
|
2114
|
+
path: string;
|
|
2115
|
+
producedAt: string;
|
|
2116
|
+
}>;
|
|
2117
|
+
/**
|
|
2118
|
+
* Fail a session's in-flight turn: `status` and `lastError`, and the error
|
|
2119
|
+
* on the turn's own user message (`Message.turnError`), where the next
|
|
2120
|
+
* turn cannot overwrite it. The one write every path that fails a turn
|
|
2121
|
+
* makes — the runner's and the gateway's sweeps — so `turnFailureFor`
|
|
2122
|
+
* reads the same record whichever failed it. In flight, the turn's message
|
|
2123
|
+
* is the session's newest user message (`observe` refuses to append).
|
|
2124
|
+
*/
|
|
2125
|
+
export declare const recordTurnFailure: (session: Session, error: string) => void;
|
|
2126
|
+
/**
|
|
2127
|
+
* Whether the keyed message started the session's latest turn. A message
|
|
2128
|
+
* `observe` appended since started no turn and is passed over
|
|
2129
|
+
* (`Message.observed`); every other user message, keyed or not, addressed
|
|
2130
|
+
* or not, started one.
|
|
2131
|
+
*/
|
|
2132
|
+
export declare const isLatestTurn: (session: Pick<Session, "messages">, idempotencyKey: string) => boolean;
|
|
2133
|
+
/**
|
|
2134
|
+
* Why the turn a keyed message started failed, or undefined if it did not.
|
|
2135
|
+
* Read from the message (`recordTurnFailure`), so a turn the session has
|
|
2136
|
+
* moved on from still answers. A transcript written before turns carried
|
|
2137
|
+
* their own failure has only the session's, which is the keyed turn's
|
|
2138
|
+
* while it is the latest (`isLatestTurn`).
|
|
2139
|
+
*/
|
|
2140
|
+
export declare const turnFailureFor: (session: Pick<Session, "messages" | "status" | "lastError">, idempotencyKey: string) => string | undefined;
|
|
1845
2141
|
/**
|
|
1846
2142
|
* A user message's text as a prompt should carry it. The one place an
|
|
1847
2143
|
* overheard message is framed, so the API providers' per-message blocks
|
|
@@ -1877,6 +2173,22 @@ export declare const promptTextOf: (message: Pick<Message, "content" | "overhear
|
|
|
1877
2173
|
* as the answer rather than as a broken endpoint.
|
|
1878
2174
|
*/
|
|
1879
2175
|
export declare const isUnaddressedTurn: (session: Pick<Session, "messages">) => boolean;
|
|
2176
|
+
/**
|
|
2177
|
+
* Where the dispatch carrying `idempotencyKey` stands in this session:
|
|
2178
|
+
* `undefined` if no message carries the key, `unfinished` if its message
|
|
2179
|
+
* is the one the session's in-flight turn is on, `finished` otherwise.
|
|
2180
|
+
*
|
|
2181
|
+
* Derived, never recorded separately, which is what makes it exact. The
|
|
2182
|
+
* keyed message is written in the same save that sets the status to
|
|
2183
|
+
* `running` (accepted and started are one write), and the save that moves
|
|
2184
|
+
* the status off `running` or `pending_approval` is the turn's final one,
|
|
2185
|
+
* so `finished` is written in the same transaction as the final save by
|
|
2186
|
+
* construction. While a turn is in flight its message is the session's
|
|
2187
|
+
* newest user message — `observe` refuses to append during one, and the
|
|
2188
|
+
* runner's wrap-up notes never reach the store — the same reading
|
|
2189
|
+
* `isUnaddressedTurn` relies on.
|
|
2190
|
+
*/
|
|
2191
|
+
export declare const workItemState: (session: Pick<Session, "messages" | "status">, idempotencyKey: string) => "unfinished" | "finished" | undefined;
|
|
1880
2192
|
export declare const markPromptDelivered: <T>(error: T) => T;
|
|
1881
2193
|
export declare const promptWasDelivered: (error: unknown) => boolean;
|
|
1882
2194
|
export interface PromptTextOptions {
|
|
@@ -2069,6 +2381,54 @@ export type StratusEvent = {
|
|
|
2069
2381
|
reason: ApprovalResolutionReason;
|
|
2070
2382
|
/** Who decided, when a person did. Channel-native id (a Slack user). */
|
|
2071
2383
|
actor?: string;
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2386
|
+
* An agent asked for a named credential it does not hold
|
|
2387
|
+
* (`credential.request`), and it has already been put to someone: a form
|
|
2388
|
+
* in the conversation it asked in (`via: 'form'`), or a one-time link the
|
|
2389
|
+
* agent was handed to pass on (`via: 'link'`). The request is delivered
|
|
2390
|
+
* first and announced after, so this is a record of a question that was
|
|
2391
|
+
* asked, never a request for someone to render one. Nothing about it is
|
|
2392
|
+
* a secret, and nothing that answers it ever travels on the bus. `scope` is whose the key would be: the
|
|
2393
|
+
* agent's own (`agent`, the default) or the fleet's (`shared`).
|
|
2394
|
+
*
|
|
2395
|
+
* `metadata` is the session's, for the same reason an approval request
|
|
2396
|
+
* carries it: it says which conversation to ask in.
|
|
2397
|
+
*/
|
|
2398
|
+
| {
|
|
2399
|
+
type: 'credential.requested';
|
|
2400
|
+
sessionId: string;
|
|
2401
|
+
agentId: string;
|
|
2402
|
+
requestId: string;
|
|
2403
|
+
name: string;
|
|
2404
|
+
scope: CredentialScope;
|
|
2405
|
+
/** The agent's own words on what it needs the key for. Untrusted text. */
|
|
2406
|
+
reason?: string;
|
|
2407
|
+
/** How it was put to someone. Absent from hosts before links existed, which only had forms. */
|
|
2408
|
+
via?: CredentialDelivery;
|
|
2409
|
+
metadata?: JsonObject;
|
|
2410
|
+
}
|
|
2411
|
+
/**
|
|
2412
|
+
* A requested credential was stored for the agent that asked, and granted
|
|
2413
|
+
* to it. Names only; the value went to the credential store and nowhere
|
|
2414
|
+
* else.
|
|
2415
|
+
*
|
|
2416
|
+
* Emitted once the key is stored, whether or not the grant then landed:
|
|
2417
|
+
* a key added from a chat is a change on disk, and a shared one is
|
|
2418
|
+
* already usable by every agent granted that name, so it is recorded even
|
|
2419
|
+
* when the soul write failed. `grantError` says it did, and why.
|
|
2420
|
+
*/
|
|
2421
|
+
| {
|
|
2422
|
+
type: 'credential.provided';
|
|
2423
|
+
sessionId: string;
|
|
2424
|
+
agentId: string;
|
|
2425
|
+
requestId: string;
|
|
2426
|
+
name: string;
|
|
2427
|
+
scope: CredentialScope;
|
|
2428
|
+
/** Who provided it. Channel-native id (a Slack user). */
|
|
2429
|
+
actor?: string;
|
|
2430
|
+
/** Set when the key was stored but could not be added to the soul. */
|
|
2431
|
+
grantError?: string;
|
|
2072
2432
|
} | {
|
|
2073
2433
|
type: 'session.completed';
|
|
2074
2434
|
sessionId: string;
|
|
@@ -2421,6 +2781,29 @@ export interface AgentWorkspaces {
|
|
|
2421
2781
|
*/
|
|
2422
2782
|
all(): Promise<readonly string[]>;
|
|
2423
2783
|
}
|
|
2784
|
+
/**
|
|
2785
|
+
* Where one plugin keeps durable state of its own, answered by the host.
|
|
2786
|
+
*
|
|
2787
|
+
* A seam for the reason {@link AgentWorkspaces} is one: the layout is the
|
|
2788
|
+
* host's to own. A plugin that needs to remember something across restarts
|
|
2789
|
+
* — a channel's read position in a store it does not own, a cursor into a
|
|
2790
|
+
* vendor's event log — would otherwise join a path onto `~/.stratus` itself,
|
|
2791
|
+
* and every plugin doing so is one more copy of the layout to find when it
|
|
2792
|
+
* moves. Per plugin, never per agent: what a plugin remembers is its own,
|
|
2793
|
+
* and it makes whatever structure it needs beneath this.
|
|
2794
|
+
*/
|
|
2795
|
+
export interface PluginStateDirectory {
|
|
2796
|
+
/**
|
|
2797
|
+
* The directory, created and with its permissions settled, for a caller
|
|
2798
|
+
* about to write. Private to the daemon's user, because what a plugin
|
|
2799
|
+
* keeps is the daemon's business, and a plugin cannot be expected to know
|
|
2800
|
+
* the mode the rest of the state is held to.
|
|
2801
|
+
*
|
|
2802
|
+
* Asked per write rather than captured at setup: a daemon runs for weeks,
|
|
2803
|
+
* and the directory can be removed or replaced with a link under it.
|
|
2804
|
+
*/
|
|
2805
|
+
prepare(): string;
|
|
2806
|
+
}
|
|
2424
2807
|
export interface MemoryRegistrationHandle {
|
|
2425
2808
|
register(contribution: MemoryStoreContribution): void;
|
|
2426
2809
|
}
|
|
@@ -2471,6 +2854,15 @@ export interface PluginContext {
|
|
|
2471
2854
|
* read as though it did.
|
|
2472
2855
|
*/
|
|
2473
2856
|
workspaces?: AgentWorkspaces;
|
|
2857
|
+
/**
|
|
2858
|
+
* Where this plugin may keep durable state. See {@link PluginStateDirectory}.
|
|
2859
|
+
*
|
|
2860
|
+
* A host that omits it gives the plugin nowhere to remember anything
|
|
2861
|
+
* across a restart. Such a plugin must say what it gives up — a channel
|
|
2862
|
+
* that cannot store its read position cannot promise a message is handled
|
|
2863
|
+
* once — and must never choose a directory of its own instead.
|
|
2864
|
+
*/
|
|
2865
|
+
stateDirectory?: PluginStateDirectory;
|
|
2474
2866
|
/**
|
|
2475
2867
|
* The host's log, for what a plugin has to say after `setup` returns —
|
|
2476
2868
|
* a server that dropped, a reconnect that failed. The daemon's is the
|
|
@@ -2549,6 +2941,15 @@ export interface SkillDescriptor {
|
|
|
2549
2941
|
* else, per turn and in memory.
|
|
2550
2942
|
*/
|
|
2551
2943
|
export interface Skill extends SkillDescriptor {
|
|
2944
|
+
/**
|
|
2945
|
+
* Ships with Stratus and is enabled for every agent, whatever its soul's
|
|
2946
|
+
* `skills:` says. Reserved for the system's own documentation (the
|
|
2947
|
+
* `stratus` skill; `SkillRegistry.register` refuses it on any other id): a skill from anywhere else changing how an agent
|
|
2948
|
+
* behaves is opted into, but an agent that cannot read how the system it
|
|
2949
|
+
* runs in works guesses instead, the way one suggested `passEnv` for a
|
|
2950
|
+
* secret after reading the install around it.
|
|
2951
|
+
*/
|
|
2952
|
+
builtin?: boolean;
|
|
2552
2953
|
/**
|
|
2553
2954
|
* Toolset globs this skill expects (`browser.*`, `fs.read`). Advisory: a
|
|
2554
2955
|
* skill is prose and degrades, so an agent enabling one without the tools
|
|
@@ -2633,6 +3034,12 @@ export declare class SkillRegistry {
|
|
|
2633
3034
|
* A read already underway keeps the promise it holds either way. `next`
|
|
2634
3035
|
* is consumed — emptied, not shared — so nothing can go on mutating this
|
|
2635
3036
|
* registry through it.
|
|
3037
|
+
*
|
|
3038
|
+
* A built-in skill serving now is never dropped by the swap: a `next`
|
|
3039
|
+
* without one (its file unreadable mid-reload) keeps the one serving,
|
|
3040
|
+
* and a bare alias `next` gave its id yields to it. A reload is
|
|
3041
|
+
* all-or-nothing for what it read; it must not take away from every
|
|
3042
|
+
* agent the one skill no soul can opt back into.
|
|
2636
3043
|
*/
|
|
2637
3044
|
replaceWith(next: SkillRegistry): void;
|
|
2638
3045
|
describe(): SkillDescriptor[];
|
|
@@ -2644,6 +3051,12 @@ export declare class SkillRegistry {
|
|
|
2644
3051
|
read(id: string): Promise<string>;
|
|
2645
3052
|
}
|
|
2646
3053
|
export declare const SKILL_READ_TOOL_NAME = "skill.read";
|
|
3054
|
+
/**
|
|
3055
|
+
* The built-in skill's id: how Stratus works, enabled for every agent.
|
|
3056
|
+
* Reserved, so an operator directory or a plugin cannot put a different
|
|
3057
|
+
* procedure under the name every agent is pointed at.
|
|
3058
|
+
*/
|
|
3059
|
+
export declare const STRATUS_SKILL_ID = "stratus";
|
|
2647
3060
|
export interface SkillReadToolOptions {
|
|
2648
3061
|
/**
|
|
2649
3062
|
* Which `skills:` entries the session's agent is held to. Defaults to the
|
|
@@ -2727,6 +3140,43 @@ export declare const renderMemorySection: (memory: readonly MemoryEntry[] | Memo
|
|
|
2727
3140
|
* here may ever include a body.
|
|
2728
3141
|
*/
|
|
2729
3142
|
export declare const renderSkillsSection: (skills: readonly SkillDescriptor[] | undefined) => string | undefined;
|
|
3143
|
+
/**
|
|
3144
|
+
* The language agents write in when nothing says otherwise: American
|
|
3145
|
+
* English. A soul's `language:` and the config file's `language` override
|
|
3146
|
+
* it; see `resolveRuntimeConfig`, which decides between those two.
|
|
3147
|
+
*/
|
|
3148
|
+
export declare const DEFAULT_LANGUAGE = "en-US";
|
|
3149
|
+
/** Whether a `language` setting is a BCP 47 tag; see `canonicalLanguageTag`. */
|
|
3150
|
+
export declare const isLanguageTag: (value: unknown) => value is string;
|
|
3151
|
+
/**
|
|
3152
|
+
* How to reply, told to every agent before its persona.
|
|
3153
|
+
*
|
|
3154
|
+
* Models default to the long, headed, bulleted answer, and an agent is read
|
|
3155
|
+
* mostly in chat, often on a phone, where that is the wrong shape. Souls
|
|
3156
|
+
* were each growing their own copy of these rules, so they live here once.
|
|
3157
|
+
* Short must not turn into incomplete, so the same section says a requested
|
|
3158
|
+
* deliverable arrives whole and a blocker is always said. A long one goes
|
|
3159
|
+
* where the reader can open it: an agent on Slack that answers with a path
|
|
3160
|
+
* on the daemon's disk has handed over nothing, so when sharing is not
|
|
3161
|
+
* possible the content itself goes in the reply.
|
|
3162
|
+
*
|
|
3163
|
+
* The accuracy rules are here for the same reason, each after an incident:
|
|
3164
|
+
* an agent with no Slack tool insisted it had no Slack connection, and
|
|
3165
|
+
* agents reported work as done that had only been drafted. The language
|
|
3166
|
+
* rule is here because the default persona is not: a custom soul replaces
|
|
3167
|
+
* it, and an agent wrote "favour" and "licence" into American website copy
|
|
3168
|
+
* because nothing shared said which English. A pasted British paragraph is
|
|
3169
|
+
* not a setting, so the rule says a task or a client's style guide decides
|
|
3170
|
+
* one deliverable and nothing is inferred from source text.
|
|
3171
|
+
*
|
|
3172
|
+
* The last sentence lets the soul and the person override length, format,
|
|
3173
|
+
* and language, and deliberately nothing else: a style preference never
|
|
3174
|
+
* changes what an agent may do, and "be brief" must not read as "skip the
|
|
3175
|
+
* blocker". Written without em dashes on purpose: a model imitates the
|
|
3176
|
+
* prose it is prompted with, and a rule against them set in them undoes
|
|
3177
|
+
* itself.
|
|
3178
|
+
*/
|
|
3179
|
+
export declare const renderReplySection: (language: string | undefined) => string;
|
|
2730
3180
|
/**
|
|
2731
3181
|
* Where the conversation is happening, for a session a channel started.
|
|
2732
3182
|
*
|
|
@@ -2734,11 +3184,39 @@ export declare const renderSkillsSection: (skills: readonly SkillDescriptor[] |
|
|
|
2734
3184
|
* dispatches (`slack` today). Without this the agent could not tell: an
|
|
2735
3185
|
* agent with no Slack tool, asked about an attachment in a Slack DM, told
|
|
2736
3186
|
* the person it had "no Slack connection at all" and argued the point.
|
|
2737
|
-
*
|
|
2738
|
-
*
|
|
3187
|
+
* The channel is read from the session, so sessions opened before this
|
|
3188
|
+
* existed get it too; the room (`ConversationContext`) comes per turn from
|
|
3189
|
+
* the runtime, falling back to what the session's first turn recorded, so
|
|
3190
|
+
* an agent in a Slack DM no longer tells the person they are "talking on
|
|
3191
|
+
* the terminal". The name must look like a channel
|
|
2739
3192
|
* id, since it is interpolated into the prompt.
|
|
3193
|
+
*
|
|
3194
|
+
* What it says about attachments is what the adapter writes into the
|
|
3195
|
+
* message, not a promise that they arrive: it used to say that what people
|
|
3196
|
+
* attach "reaches you", which read as though every file's contents did,
|
|
3197
|
+
* when most reach the turn as a name only. The Slack adapter marks each
|
|
3198
|
+
* file as read, shown, or unread with its reason; the section sends the
|
|
3199
|
+
* model to that note and nowhere else.
|
|
2740
3200
|
*/
|
|
2741
|
-
export declare const renderChannelSection: (session: Pick<Session, "metadata"
|
|
3201
|
+
export declare const renderChannelSection: (session: Pick<Session, "metadata">, conversation?: ConversationContext) => string | undefined;
|
|
3202
|
+
/**
|
|
3203
|
+
* How this agent is run, for a host that said (see
|
|
3204
|
+
* {@link AgentRuntimeContext}).
|
|
3205
|
+
*
|
|
3206
|
+
* It says the soul is already in the prompt as firmly as it says where the
|
|
3207
|
+
* file is. An agent told only a path treats it as something to go and read,
|
|
3208
|
+
* and it usually cannot: the soul sits beside its state directory, outside
|
|
3209
|
+
* any root an operator hands `tool-fs`, and it has to stay there, since
|
|
3210
|
+
* the soul is what grants the agent its tools and credentials.
|
|
3211
|
+
*
|
|
3212
|
+
* Credentials get the same treatment, and for the same reason: an agent
|
|
3213
|
+
* whose operator had stored a shared key went looking through its files and
|
|
3214
|
+
* its environment for it. A named credential only ever reaches a plugin tool
|
|
3215
|
+
* that declared it, so the section names what the soul grants and says there
|
|
3216
|
+
* is nothing to find. Names only; a value never comes near a prompt.
|
|
3217
|
+
* Written without em dashes for the reason the reply section is.
|
|
3218
|
+
*/
|
|
3219
|
+
export declare const renderRuntimeSection: (runtime: AgentRuntimeContext | undefined, agent: Pick<AgentDefinition, "credentials">) => string | undefined;
|
|
2742
3220
|
export interface SystemPromptOptions {
|
|
2743
3221
|
/** Host-level preamble, rendered before the agent's own persona. */
|
|
2744
3222
|
preamble?: string;
|
|
@@ -2749,12 +3227,12 @@ export interface SystemPromptOptions {
|
|
|
2749
3227
|
* Which part of what an agent is told a section is.
|
|
2750
3228
|
*
|
|
2751
3229
|
* The distinction a caller actually needs is stable versus volatile:
|
|
2752
|
-
* `preamble`, `replies`, `persona`, `channel`, and `skills` are byte-identical across every turn of
|
|
3230
|
+
* `preamble`, `replies`, `persona`, `runtime`, `channel`, and `skills` are byte-identical across every turn of
|
|
2753
3231
|
* an agent's life, while `memory` is rewritten whenever the agent remembers
|
|
2754
3232
|
* anything. A provider that caches its request prefix has to place those two
|
|
2755
3233
|
* groups differently, and it cannot tell them apart from rendered strings.
|
|
2756
3234
|
*/
|
|
2757
|
-
export type SystemPromptSectionKind = 'preamble' | 'replies' | 'persona' | 'channel' | 'memory' | 'skills';
|
|
3235
|
+
export type SystemPromptSectionKind = 'preamble' | 'replies' | 'persona' | 'runtime' | 'channel' | 'memory' | 'skills';
|
|
2758
3236
|
export interface SystemPromptSection {
|
|
2759
3237
|
kind: SystemPromptSectionKind;
|
|
2760
3238
|
text: string;
|
|
@@ -2773,11 +3251,11 @@ export interface SystemPromptSection {
|
|
|
2773
3251
|
* The order is the order. This is the one rule about what an agent is told;
|
|
2774
3252
|
* `renderSystemPromptSections` is the same rule with the labels dropped.
|
|
2775
3253
|
*/
|
|
2776
|
-
export declare const renderSystemPromptParts: (request: Pick<ProviderRequest, "session" | "memory" | "skills">, options?: SystemPromptOptions) => SystemPromptSection[];
|
|
3254
|
+
export declare const renderSystemPromptParts: (request: Pick<ProviderRequest, "session" | "memory" | "skills" | "runtime">, options?: SystemPromptOptions) => SystemPromptSection[];
|
|
2777
3255
|
/** The sections as plain strings, in the same order. */
|
|
2778
|
-
export declare const renderSystemPromptSections: (request: Pick<ProviderRequest, "session" | "memory" | "skills">, options?: SystemPromptOptions) => string[];
|
|
3256
|
+
export declare const renderSystemPromptSections: (request: Pick<ProviderRequest, "session" | "memory" | "skills" | "runtime">, options?: SystemPromptOptions) => string[];
|
|
2779
3257
|
/** The sections joined the way single-string providers send them. */
|
|
2780
|
-
export declare const renderSystemPrompt: (request: Pick<ProviderRequest, "session" | "memory" | "skills">, options?: SystemPromptOptions) => string | undefined;
|
|
3258
|
+
export declare const renderSystemPrompt: (request: Pick<ProviderRequest, "session" | "memory" | "skills" | "runtime">, options?: SystemPromptOptions) => string | undefined;
|
|
2781
3259
|
/**
|
|
2782
3260
|
* The two producer channels, collected for one call: the tool's standing
|
|
2783
3261
|
* `outputTrust` declaration and whatever the tool marks through the
|
|
@@ -2889,7 +3367,31 @@ export interface RunInput {
|
|
|
2889
3367
|
* attachments instead, as an overheard one does.
|
|
2890
3368
|
*/
|
|
2891
3369
|
addressed?: boolean;
|
|
3370
|
+
/**
|
|
3371
|
+
* The caller's name for this dispatch, stored on the user message
|
|
3372
|
+
* (`Message.idempotencyKey`) in the same write as the message itself.
|
|
3373
|
+
* The runner only records it; refusing a repeat is the host's job — see
|
|
3374
|
+
* `workItemState` and the gateway's `DispatchInput.idempotencyKey`.
|
|
3375
|
+
*/
|
|
3376
|
+
idempotencyKey?: string;
|
|
3377
|
+
/**
|
|
3378
|
+
* Whether this turn may run on a provider that hosts its own tool loop,
|
|
3379
|
+
* stored on the user message (`Message.hostedLoop`). The host knows what
|
|
3380
|
+
* it resolved for the turn; the runner only records it.
|
|
3381
|
+
*/
|
|
3382
|
+
hostedLoop?: boolean;
|
|
2892
3383
|
metadata?: JsonObject;
|
|
3384
|
+
/**
|
|
3385
|
+
* What the host can say about how this agent is run, rendered as the
|
|
3386
|
+
* `runtime` section; see {@link AgentRuntimeContext}. Omitted, the
|
|
3387
|
+
* section is not rendered.
|
|
3388
|
+
*
|
|
3389
|
+
* Per run rather than a runner option, because the answer belongs to the
|
|
3390
|
+
* snapshot the host dispatched with: a daemon that re-reads the roster
|
|
3391
|
+
* between two awaits would otherwise tell an agent running on one soul
|
|
3392
|
+
* file that another file is its soul.
|
|
3393
|
+
*/
|
|
3394
|
+
runtime?: AgentRuntimeContext;
|
|
2893
3395
|
/** Aborting fails the turn cleanly; see RunAbortedError. */
|
|
2894
3396
|
signal?: AbortSignal;
|
|
2895
3397
|
}
|
|
@@ -2900,6 +3402,10 @@ export interface ResumeInput {
|
|
|
2900
3402
|
images?: ImageAttachment[];
|
|
2901
3403
|
/** See `RunInput.addressed`. */
|
|
2902
3404
|
addressed?: boolean;
|
|
3405
|
+
/** See `RunInput.idempotencyKey`. */
|
|
3406
|
+
idempotencyKey?: string;
|
|
3407
|
+
/** See `RunInput.hostedLoop`. */
|
|
3408
|
+
hostedLoop?: boolean;
|
|
2903
3409
|
/**
|
|
2904
3410
|
* This turn's metadata — read for the sender's trust
|
|
2905
3411
|
* (`SENDER_TRUST_METADATA_KEY`) and not merged into the session's. The
|
|
@@ -2908,6 +3414,8 @@ export interface ResumeInput {
|
|
|
2908
3414
|
* trust.
|
|
2909
3415
|
*/
|
|
2910
3416
|
metadata?: JsonObject;
|
|
3417
|
+
/** See `RunInput.runtime`. */
|
|
3418
|
+
runtime?: AgentRuntimeContext;
|
|
2911
3419
|
/** Aborting fails the turn cleanly; see RunAbortedError. */
|
|
2912
3420
|
signal?: AbortSignal;
|
|
2913
3421
|
}
|
|
@@ -3104,6 +3612,30 @@ export declare class AgentRunner {
|
|
|
3104
3612
|
*/
|
|
3105
3613
|
private labelLegacySession;
|
|
3106
3614
|
resume(input: ResumeInput): Promise<Session>;
|
|
3615
|
+
/**
|
|
3616
|
+
* Picks up a turn whose process died while it was `running`: its user
|
|
3617
|
+
* message is durable and its reply is not. Nothing is appended — the turn
|
|
3618
|
+
* already has its message — so this is `resume` without the input.
|
|
3619
|
+
* Dangling tool calls are closed as interrupted, telling the model they
|
|
3620
|
+
* may not have run rather than running them again, and the loop goes back
|
|
3621
|
+
* to the provider with the transcript as it stands.
|
|
3622
|
+
*
|
|
3623
|
+
* A transcript that already ends in the reply (the response was saved,
|
|
3624
|
+
* and the process died before the save that marks the turn completed) is
|
|
3625
|
+
* completed as it stands, with no provider call: asking again would send
|
|
3626
|
+
* a second answer to one message.
|
|
3627
|
+
*
|
|
3628
|
+
* Marks the turn's message `continuedAfterCrash` in its first save, so a
|
|
3629
|
+
* host can refuse to do this twice. Resolves `undefined` when the session
|
|
3630
|
+
* is missing or no longer `running`. Never for a turn parked on a human:
|
|
3631
|
+
* `recoverPendingApproval` re-enters the parked call, which reconciling
|
|
3632
|
+
* here would close.
|
|
3633
|
+
*/
|
|
3634
|
+
continueTurn(sessionId: string, options?: {
|
|
3635
|
+
/** See `RunInput.runtime`. */
|
|
3636
|
+
runtime?: AgentRuntimeContext;
|
|
3637
|
+
signal?: AbortSignal;
|
|
3638
|
+
}): Promise<Session | undefined>;
|
|
3107
3639
|
/**
|
|
3108
3640
|
* A message reaching the session with no turn run on it: something said
|
|
3109
3641
|
* in a conversation the agent is in, to somebody else. Appended and
|
|
@@ -3122,11 +3654,18 @@ export declare class AgentRunner {
|
|
|
3122
3654
|
*/
|
|
3123
3655
|
observe(input: ObserveInput): Promise<Session>;
|
|
3124
3656
|
/**
|
|
3125
|
-
*
|
|
3126
|
-
*
|
|
3127
|
-
*
|
|
3128
|
-
*
|
|
3129
|
-
*
|
|
3657
|
+
* Adds a synthetic failed result for every tool call that has none — the
|
|
3658
|
+
* durable trace of a turn interrupted between the call's save and its
|
|
3659
|
+
* result's. The model sees an honest record ("interrupted, never ran to
|
|
3660
|
+
* completion") instead of a wire-format violation, and a resume can
|
|
3661
|
+
* decide to retry rather than assume the side effect landed.
|
|
3662
|
+
*
|
|
3663
|
+
* Placed where an uninterrupted turn would have written it: after the
|
|
3664
|
+
* whole response the call came in — every assistant message that one
|
|
3665
|
+
* save wrote — and after any results already recorded for it. Directly
|
|
3666
|
+
* after the call would split a response whose text followed its call, and
|
|
3667
|
+
* a provider replaying the response's raw turn (which already holds that
|
|
3668
|
+
* text) would then send the text a second time.
|
|
3130
3669
|
*/
|
|
3131
3670
|
private reconcileInterruptedToolCalls;
|
|
3132
3671
|
/**
|
|
@@ -3163,11 +3702,14 @@ export declare class AgentRunner {
|
|
|
3163
3702
|
* the allowlist actually granted (canonical before alias) — the id the
|
|
3164
3703
|
* model is told is the id `skill.read` will accept.
|
|
3165
3704
|
*
|
|
3166
|
-
*
|
|
3167
|
-
*
|
|
3705
|
+
* A built-in skill is in it for every agent; otherwise it is empty for
|
|
3706
|
+
* an agent whose soul has no `skills:` key, which is what keys both
|
|
3707
|
+
* `skill.read` gates: no skills, no reader.
|
|
3168
3708
|
*/
|
|
3169
3709
|
private enabledSkillsFor;
|
|
3170
3710
|
private executeTurns;
|
|
3711
|
+
/** See `completeAnsweredTurn`; the loop's end and `continueTurn`'s. */
|
|
3712
|
+
private completeTurn;
|
|
3171
3713
|
/**
|
|
3172
3714
|
* Finishes a turn that was parked on a human when the process died.
|
|
3173
3715
|
*
|
|
@@ -3188,6 +3730,8 @@ export declare class AgentRunner {
|
|
|
3188
3730
|
* about at all, so they still face the policy normally.
|
|
3189
3731
|
*/
|
|
3190
3732
|
denyPending?: boolean;
|
|
3733
|
+
/** See `RunInput.runtime`. */
|
|
3734
|
+
runtime?: AgentRuntimeContext;
|
|
3191
3735
|
signal?: AbortSignal;
|
|
3192
3736
|
}): Promise<Session | undefined>;
|
|
3193
3737
|
/**
|