@superdurable/dex-agents 0.5.0 → 0.6.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/README.md +110 -3
- package/dist/src/agent-approval-display.d.ts +135 -0
- package/dist/src/agent-approval-display.js +536 -0
- package/dist/src/agent-approval-display.js.map +1 -0
- package/dist/src/agent-framework-runner.d.ts +39 -2
- package/dist/src/agent-framework-runner.js.map +1 -1
- package/dist/src/agent-session-codecs.d.ts +3 -1
- package/dist/src/agent-session-codecs.js +31 -0
- package/dist/src/agent-session-codecs.js.map +1 -1
- package/dist/src/agent-session-flow.d.ts +23 -0
- package/dist/src/agent-session-flow.js +11 -0
- package/dist/src/agent-session-flow.js.map +1 -1
- package/dist/src/agent-session-persistence.d.ts +33 -0
- package/dist/src/agent-session-persistence.js +22 -1
- package/dist/src/agent-session-persistence.js.map +1 -1
- package/dist/src/agent-session-steps.js +22 -2
- package/dist/src/agent-session-steps.js.map +1 -1
- package/dist/src/agent-session-summary.d.ts +138 -0
- package/dist/src/agent-session-summary.js +151 -0
- package/dist/src/agent-session-summary.js.map +1 -0
- package/dist/src/agent-session-transitions.d.ts +9 -3
- package/dist/src/agent-session-transitions.js +37 -5
- package/dist/src/agent-session-transitions.js.map +1 -1
- package/dist/src/agent-session-values.d.ts +103 -1
- package/dist/src/agent-session-values.js.map +1 -1
- package/dist/src/builtin-loop/builtin-agent-session-flow.d.ts +9 -1
- package/dist/src/builtin-loop/builtin-agent-session-flow.js +5 -1
- package/dist/src/builtin-loop/builtin-agent-session-flow.js.map +1 -1
- package/dist/src/connectors/connector-tool-source.d.ts +2 -1
- package/dist/src/connectors/connector-tool-source.js +13 -1
- package/dist/src/connectors/connector-tool-source.js.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/mcp-tool-source.d.ts +27 -1
- package/dist/src/mcp/mcp-tool-source.js +52 -13
- package/dist/src/mcp/mcp-tool-source.js.map +1 -1
- package/dist/src/testing/private-dex-engine.d.ts +8 -0
- package/dist/src/testing/private-dex-engine.js +17 -1
- package/dist/src/testing/private-dex-engine.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -487,7 +487,8 @@ if (snapshot.plan?.status === "draft") {
|
|
|
487
487
|
never runs. It marks the plan `active`, writes `plan_execution_started`, and
|
|
488
488
|
starts an `executing` turn with every tool, whose user message is `[Dex] The
|
|
489
489
|
user approved plan revision <n>. Execute it and keep the task statuses
|
|
490
|
-
current with write_todos.`.
|
|
490
|
+
current with write_todos.`. The stored message has `origin`
|
|
491
|
+
`plan_execution`; see [User messages the session writes](#user-messages-the-session-writes).
|
|
491
492
|
- `buildPlanNote(plan, interactionMode)` returns the note that shows the model
|
|
492
493
|
the plan. The built-in loop adds it as user text before the turn's messages in every
|
|
493
494
|
model call, so the model always sees the latest plan.
|
|
@@ -1286,6 +1287,107 @@ does not turn this on; pass `configOverride: { activeStepSearchMode: agentSessio
|
|
|
1286
1287
|
`Client.updateFlowConfig` for a running session. See
|
|
1287
1288
|
[Find sessions that need a person](https://docs.superdurable.io/reference/agents/approvals#find-sessions).
|
|
1288
1289
|
|
|
1290
|
+
## Showing what an approval acts on
|
|
1291
|
+
|
|
1292
|
+
A tool approval can say what the call acts on and what it does. Its tool source returns an
|
|
1293
|
+
`AgentInterruptDisplay` `{ target, summary, preview? }` in `DeferredToolCall.approvalDisplay`, and the session
|
|
1294
|
+
stores it in `AgentInterrupt.display`, on the call's record as `approvalDisplay`, and in the `interrupt_raised`
|
|
1295
|
+
event. A queued ordered write raises its approval later with the display its source built when the model asked.
|
|
1296
|
+
|
|
1297
|
+
```ts
|
|
1298
|
+
const snapshot = await client.invokeRPC(flow.getAgentSnapshot, sessionId);
|
|
1299
|
+
for (const interrupt of snapshot.pendingInterrupts) {
|
|
1300
|
+
console.log(interrupt.display?.summary ?? interrupt.arguments);
|
|
1301
|
+
}
|
|
1302
|
+
```
|
|
1303
|
+
|
|
1304
|
+
- `ConnectorToolSource` and the CLI's connector tools build it with `buildConnectorToolApprovalDisplay`: the
|
|
1305
|
+
target is `<connector>/<connection>`, and the summary names the operation, the connection, and up to five short
|
|
1306
|
+
arguments, such as `Calls slack postChannelMessage with connection support-slack; channel: "#eng".`
|
|
1307
|
+
- The CLI's local file writes name the workspace path and carry a unified diff against the file as it is when the
|
|
1308
|
+
model asks; its header lines say so. Its shell commands name the working directory and the command with its
|
|
1309
|
+
inline credentials redacted and its control characters escaped, cut at 2 KiB; the full command is in the call's
|
|
1310
|
+
arguments.
|
|
1311
|
+
- A display never says how often the call runs or what it achieves, and never uses a tool's description as its
|
|
1312
|
+
effect.
|
|
1313
|
+
- Redaction in a display is best-effort hygiene, not a security boundary. The display's text comes from the call's
|
|
1314
|
+
arguments, which the session stores in full as before, and an agent can read a workspace file with its own tools.
|
|
1315
|
+
A credential-like argument (`isCredentialLikeName`) shows `<redacted>`, and `redactInlineCredentials` replaces
|
|
1316
|
+
common credential shapes: the value after a credential-like name, read as a shell word, a triple-quoted string, or
|
|
1317
|
+
a YAML block; `Authorization` and `Cookie` header values; URL passwords; `sshpass -p`; and common token shapes.
|
|
1318
|
+
It reads `\uXXXX`, `\xXX`, and `%XX` escapes to find credentials but changes no other text: escapes stay as
|
|
1319
|
+
written, and only the characters of each credential become `<redacted>`. It is conservative, so a generic
|
|
1320
|
+
`key=value` is redacted too, and the CLI leaves out a file preview whose text it changes. It finds common forms
|
|
1321
|
+
only, and Unicode lookalike letters are out of scope; `agents/conformance/approval_display.json` lists the cases
|
|
1322
|
+
both cores share.
|
|
1323
|
+
- The session cuts a target over `maxApprovalTargetBytes` (1 KiB) and a summary over `maxApprovalSummaryBytes`
|
|
1324
|
+
(2 KiB), ending them with `…`, and drops a preview over `maxApprovalPreviewBytes` (16 KiB). A tool without a
|
|
1325
|
+
display, and every approval a Worker before 0.6.0 raised, has `display` `null`: show the concrete arguments, not a
|
|
1326
|
+
guessed effect.
|
|
1327
|
+
|
|
1328
|
+
## User messages the session writes
|
|
1329
|
+
|
|
1330
|
+
Since 0.6.0, a stored `user` message that the session wrote itself, not a person, carries
|
|
1331
|
+
`AgentMessage.origin`. Show such a message as a session note, or hide it, never as text the user typed.
|
|
1332
|
+
|
|
1333
|
+
| `origin` | Message |
|
|
1334
|
+
| --- | --- |
|
|
1335
|
+
| `plan_execution` | The message with which `execute_plan` starts the turn, `buildPlanExecutionMessage(revision)` |
|
|
1336
|
+
| `turn_failure_note` | The note `RecordTurnFailure` stores for the model after a failed turn whose tools ran |
|
|
1337
|
+
| `turn_steered_note` | The note that lists the tool calls that ran before `steer_user_message` ended the turn |
|
|
1338
|
+
| `turn_cancelled_note` | The note that lists the tool calls that ran before `cancel_turn` ended the turn |
|
|
1339
|
+
|
|
1340
|
+
```ts
|
|
1341
|
+
const page = await client.invokeRPC(flow.listAgentMessages, sessionId, { beforeSequence: null, limit: 50 });
|
|
1342
|
+
for (const message of page.messages) {
|
|
1343
|
+
if (message.origin === "plan_execution") {
|
|
1344
|
+
console.log("Running the approved plan");
|
|
1345
|
+
} else if (message.origin === undefined && message.role === "user") {
|
|
1346
|
+
console.log(`> ${message.text ?? ""}`);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
```
|
|
1350
|
+
|
|
1351
|
+
- Only the session sets `origin`. `send_user_message`, the start input's initial message, and a runner's messages,
|
|
1352
|
+
such as a `decideTurnContinuation` message, have none.
|
|
1353
|
+
- The wire field is `origin`, `null` when absent; a decoded message omits it. Messages stored before 0.6.0 have
|
|
1354
|
+
none. A Worker before 0.6.0 ignores the field, and drops it when it moves the message into an archive chunk.
|
|
1355
|
+
- A later release may add values. The decoder keeps a value it does not know, so treat any `origin` as written by
|
|
1356
|
+
the session.
|
|
1357
|
+
|
|
1358
|
+
## Listing sessions
|
|
1359
|
+
|
|
1360
|
+
Since 0.6.0, a session can keep a summary that a session list needs: its title, the first 80 Unicode code points of
|
|
1361
|
+
the first user message; the time its latest turn started or ended; and its turn count. Turn it on with
|
|
1362
|
+
`summaryAttributesIndexed: true`; the adapter factories, such as `createBuiltinAgentSessionFlow`, take the same option.
|
|
1363
|
+
It is off by default, and `flow.options.summaryAttributesIndexed` tells whether a Flow keeps it. `listAgentSessions` reads one page of sessions in one `Client.searchFlows` call, without a snapshot
|
|
1364
|
+
per session and without a running Worker:
|
|
1365
|
+
|
|
1366
|
+
```ts
|
|
1367
|
+
const flow = createAgentSessionFlow(runner, "SupportAgent", { summaryAttributesIndexed: true });
|
|
1368
|
+
const page = await listAgentSessions(client, flow.getFlowType(), { pageSize: 50, titleSearch: "refund" });
|
|
1369
|
+
for (const session of sortAgentSessionsByLastActivity(page.sessions)) {
|
|
1370
|
+
console.log(session.sessionId, session.title ?? "—", session.lastActivityAt?.toISOString() ?? "—", session.turnCount);
|
|
1371
|
+
}
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
- Dex returns running sessions first, then the most recently closed and started ones. It cannot sort by last
|
|
1375
|
+
activity, so `sortAgentSessionsByLastActivity` sorts the sessions you loaded.
|
|
1376
|
+
- `titleSearch` matches whole words of the title, without case: `flaky` finds "Fix the flaky test", `flak` does not.
|
|
1377
|
+
Pass the same `titleSearch` with each `nextPageToken`.
|
|
1378
|
+
- A session without the option, or one that an earlier release started, lists without the summary, and a title search
|
|
1379
|
+
never finds it. An earlier session gains the last activity time and the turn count at its next turn on a Worker with
|
|
1380
|
+
the option. Show each missing value as a dash. Until a Worker with the option has started on the server, a title
|
|
1381
|
+
search throws `SessionTitleSearchUnavailableError`.
|
|
1382
|
+
- A session that fails because its state would exceed the server's limit can keep the values of its last turn start.
|
|
1383
|
+
- Privacy: the title is the user's own text, and anyone who can search the namespace's Flows reads it. Turn the option
|
|
1384
|
+
on only when the first message may be stored in the search index.
|
|
1385
|
+
- The three Attributes are indexed under `text1` (FULL_TEXT), `datetime1` (DATETIME), and `int1` (INT), the generic
|
|
1386
|
+
keys that every Flow type of a namespace shares. A Worker with the option registers them when it starts. With
|
|
1387
|
+
PostgreSQL search, a namespace has three keys of each of these types; the Worker fails to start with
|
|
1388
|
+
`FAILED_PRECONDITION` when the namespace registered one of these keys with another type, or when all three keys of
|
|
1389
|
+
the type are taken by other names. Search queries of other Flow types must filter on `FlowType`.
|
|
1390
|
+
|
|
1289
1391
|
## Showing sessions in Dex Web
|
|
1290
1392
|
|
|
1291
1393
|
Dex Web draws a session and offers its Actions from the session Flow
|
|
@@ -1418,6 +1520,9 @@ Do not repeat these tool calls unless the user asks again.
|
|
|
1418
1520
|
| `PlanExecutions` | ChannelMap, key = `planExecutionKey(revision)` (decimal) | `PlanExecutionRequest { revision }` |
|
|
1419
1521
|
| `PendingPlanExecution` | Attribute | `PlanExecutionRequest` that `execute_plan` accepted and `AwaitUserMessage` has not consumed |
|
|
1420
1522
|
| `ContextSummary` | Attribute | `ContextSummary`, set once the session compacts |
|
|
1523
|
+
| `AgentSessionTitle` | Attribute, indexed FULL_TEXT `text1`; only with `summaryAttributesIndexed` | string, the first user message's title; set by the first turn only |
|
|
1524
|
+
| `AgentSessionLastActivityAt` | Attribute, indexed DATETIME `datetime1`; only with `summaryAttributesIndexed` | string, RFC 3339 time the latest turn started or ended |
|
|
1525
|
+
| `AgentSessionTurnCount` | Attribute, indexed INT `int1`; only with `summaryAttributesIndexed` | int64, `AgentState.turnCount` as of the latest turn start or end |
|
|
1421
1526
|
| `AgentEvents` | Stream | `AgentEvent` |
|
|
1422
1527
|
|
|
1423
1528
|
`AgentState.status` is `waiting_for_user_message`, `running_model`,
|
|
@@ -1457,7 +1562,7 @@ IDs are `turn-<n>`, where `n` is `turn_count + 1` when the turn starts.
|
|
|
1457
1562
|
| `tool_call_deferred` | `{"tool_call_id","tool_name","effect","requires_approval"}`; the model asked for a call, which runs in its own Step |
|
|
1458
1563
|
| `tool_call_started` | `{"tool_call_id","tool_name"}` |
|
|
1459
1564
|
| `tool_call_finished` | `{"tool_call_id","tool_name","status"}`; the record became final, including a rejection |
|
|
1460
|
-
| `interrupt_raised` | `{"interrupt_id","kind","tool_call_id","tool_name","deadline","question","choices","allows_free_text"}` |
|
|
1565
|
+
| `interrupt_raised` | `{"interrupt_id","kind","tool_call_id","tool_name","deadline","question","choices","allows_free_text","display"}`; `display` is `{"target","summary","preview"}` or `null` |
|
|
1461
1566
|
| `interrupt_resolved` | `{"interrupt_id","kind","approved","answered","rejection_message","cancellation_reason"}`; `answered` is `true` only for an answered question, and `cancellation_reason` is `"steered"` or `"turn_cancelled"` when steering or cancellation removed the interrupt |
|
|
1462
1567
|
| `timer_started` | `{"tool_call_id","wait_until","reason"}` for a `durable_wait` call |
|
|
1463
1568
|
| `plan_updated` | `{"revision","status","task_count"}` after `write_todos` replaced the plan, or when an approval marks a draft `active` |
|
|
@@ -1551,7 +1656,9 @@ server is listed again in the background while its earlier tools are
|
|
|
1551
1656
|
returned. A server that cannot be listed is left out with a warning and is not
|
|
1552
1657
|
tried again for `listingFailureBackoffMs` (30 seconds), then in the
|
|
1553
1658
|
background, so one bad server never hides the others' tools or slows every
|
|
1554
|
-
model call.
|
|
1659
|
+
model call. The warnings go to `console.warn` unless `logWarning` sends them
|
|
1660
|
+
elsewhere, such as a log file; a `logWarning` that throws falls back to
|
|
1661
|
+
`console.warn`. One listing per server runs at a time. `listTools({ refresh: true
|
|
1555
1662
|
})` lists every server again now. `deferredToolCall` stores the
|
|
1556
1663
|
server, the tool's MCP name, and its task support on the call's record, so the
|
|
1557
1664
|
tool Step calls that server directly, without a listing; `callTool` finds the
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { AgentInterruptDisplay } from "./agent-session-values.js";
|
|
2
|
+
/**
|
|
3
|
+
* Largest {@link AgentInterruptDisplay.preview} the session stores, in UTF-8 bytes: 16 KiB. The session drops a
|
|
4
|
+
* longer preview and keeps the target and summary, because the display is stored on the call's record, on its
|
|
5
|
+
* interrupt, and in its `interrupt_raised` event.
|
|
6
|
+
* @since 0.6.0
|
|
7
|
+
*/
|
|
8
|
+
export declare const maxApprovalPreviewBytes = 16384;
|
|
9
|
+
/**
|
|
10
|
+
* Largest {@link AgentInterruptDisplay.target} the session stores, in UTF-8 bytes: 1 KiB. The session cuts a longer
|
|
11
|
+
* target and ends it with `…`.
|
|
12
|
+
* @since 0.6.0
|
|
13
|
+
*/
|
|
14
|
+
export declare const maxApprovalTargetBytes = 1024;
|
|
15
|
+
/**
|
|
16
|
+
* Largest {@link AgentInterruptDisplay.summary} the session stores, in UTF-8 bytes: 2 KiB. The session cuts a longer
|
|
17
|
+
* summary and ends it with `…`.
|
|
18
|
+
* @since 0.6.0
|
|
19
|
+
*/
|
|
20
|
+
export declare const maxApprovalSummaryBytes = 2048;
|
|
21
|
+
/**
|
|
22
|
+
* The text an {@link AgentInterruptDisplay} shows instead of a credential.
|
|
23
|
+
* @since 0.6.0
|
|
24
|
+
*/
|
|
25
|
+
export declare const redactedArgumentValue = "<redacted>";
|
|
26
|
+
/**
|
|
27
|
+
* Whether an argument, header, field, or variable name looks like it holds a credential, so a display shows its
|
|
28
|
+
* value as {@link redactedArgumentValue}.
|
|
29
|
+
*
|
|
30
|
+
* The name is split into words at `_`, `-`, `.`, and spaces, and again at camelCase boundaries, ignoring case, so
|
|
31
|
+
* `pAsSwOrD` is one word. It is a credential
|
|
32
|
+
* name when a word is one of `apikey`, `auth`, `authorization`, `bearer`, `cookie`, `cred`, `credential`, `dsn`,
|
|
33
|
+
* `jwt`, `key`, `otp`, `pass`, `passphrase`, `passwd`, `password`, `privatekey`, `pwd`, `secret`, `session`,
|
|
34
|
+
* `sessionid`, `signature`, or `token` (and the plural forms `apikeys`, `cookies`, `creds`, `credentials`,
|
|
35
|
+
* `passwords`, `secrets`, and `tokens`), when a word ends in `apikey`, `credential`, `credentials`, `passwd`,
|
|
36
|
+
* `password`, `secret`, `secrets`, `token`, or `tokens`, as in `PGPASSWORD`, or when it holds the words
|
|
37
|
+
* `connection string` or `conn str`. So
|
|
38
|
+
* `X-Api-Key`, `clientSecret`, `private_key`, `credentials`, and `DATABASE_CONNECTION_STRING` all match, and
|
|
39
|
+
* `channel`, `monkey`, `tokenizer`, and `author` do not. The Python core applies the same rule; the shared cases
|
|
40
|
+
* are in `agents/conformance/approval_display.json`.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* isCredentialLikeName("clientSecret"); // true
|
|
45
|
+
* isCredentialLikeName("channel"); // false
|
|
46
|
+
* ```
|
|
47
|
+
* @param name - The name to check.
|
|
48
|
+
* @returns `true` when the name looks like it holds a credential.
|
|
49
|
+
* @since 0.6.0
|
|
50
|
+
*/
|
|
51
|
+
export declare function isCredentialLikeName(name: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Replaces common credential shapes written inline in a text, such as a shell command or a file, with
|
|
54
|
+
* {@link redactedArgumentValue}, and leaves every other character as it is.
|
|
55
|
+
*
|
|
56
|
+
* It is best-effort hygiene that keeps common credentials out of an approval display, not a security boundary: a
|
|
57
|
+
* credential in a form it does not know, such as one spelled with Unicode lookalike letters, stays as it is, and the
|
|
58
|
+
* call's arguments still hold the full text.
|
|
59
|
+
*
|
|
60
|
+
* It reads `\uXXXX`, `\xXX`, and `%XX` escapes as the characters they stand for, so an escaped name such as
|
|
61
|
+
* `pass\u0077ord` or `%70assword` is found, but it returns the text with the escapes as written: only the characters
|
|
62
|
+
* of each credential found are replaced. It replaces private key blocks; the password of a URL such as
|
|
63
|
+
* `https://user:pass@host`; the password of `-u user:pass`, `--user`, `--proxy-user`, and `sshpass -p`; and the value
|
|
64
|
+
* after a name that {@link isCredentialLikeName} matches, in a `name=value` assignment, a `name: value` header or
|
|
65
|
+
* field, a JSON member, or a `--name value` flag, which covers query parameters such as `?token=…`. A value runs as a
|
|
66
|
+
* shell word: backslash escapes, line continuations, and adjacent quoted parts join it, escaped quotes stay inside a
|
|
67
|
+
* quoted part, and it ends at whitespace, `&`, `;`, `,`, `}`, `]`, or `)`; an unclosed quote runs to the end of its
|
|
68
|
+
* line. A triple-quoted value runs to its closing quotes, or to the end of the text, and a YAML block scalar after
|
|
69
|
+
* `name: |` or `name: >` covers its indented lines. The value of an `Authorization` or `Cookie` header runs to the end
|
|
70
|
+
* of its line, with folded and continued lines, and its scheme, such as `Bearer`, stays. A value that is exactly
|
|
71
|
+
* {@link redactedArgumentValue} stays. Outside a header, a token-shaped word after `Bearer`, `Basic`, or `Digest` is
|
|
72
|
+
* replaced, and so are common token shapes, such as AWS access key IDs and GitHub, Slack, GitLab, and OpenAI-style
|
|
73
|
+
* keys and JWTs. The rules are conservative: a generic `key=value` is replaced too. The Python core applies the same
|
|
74
|
+
* rules; the shared cases are in `agents/conformance/approval_display.json`.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* redactInlineCredentials('curl -H "Authorization: Bearer t1" https://api.example.com?token=t1');
|
|
79
|
+
* // 'curl -H "Authorization: Bearer <redacted>" https://api.example.com?token=<redacted>'
|
|
80
|
+
* redactInlineCredentials("printf '\\x41'"); // "printf '\\x41'", unchanged
|
|
81
|
+
* ```
|
|
82
|
+
* @param text - The text.
|
|
83
|
+
* @returns The text with each credential found replaced and nothing else changed.
|
|
84
|
+
* @since 0.6.0
|
|
85
|
+
*/
|
|
86
|
+
export declare function redactInlineCredentials(text: string): string;
|
|
87
|
+
/**
|
|
88
|
+
* The connector, connection, operation, and arguments of one connector tool call, for
|
|
89
|
+
* {@link buildConnectorToolApprovalDisplay}.
|
|
90
|
+
* @since 0.6.0
|
|
91
|
+
*/
|
|
92
|
+
export interface ConnectorToolApprovalDisplayInput {
|
|
93
|
+
/** The Connector ID, such as `slack`. */
|
|
94
|
+
readonly connectorId: string;
|
|
95
|
+
/** The connection's name, such as `support-slack`. */
|
|
96
|
+
readonly connectionName: string;
|
|
97
|
+
/** The operation the call runs, such as `postChannelMessage`. */
|
|
98
|
+
readonly operation: string;
|
|
99
|
+
/** The call's arguments as JSON text. */
|
|
100
|
+
readonly arguments: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Builds the approval display of one connector tool call from its operation, its connection, and its short
|
|
104
|
+
* arguments.
|
|
105
|
+
*
|
|
106
|
+
* The target is `<connectorId>/<connectionName>`. The summary names the operation and the connection and lists up to
|
|
107
|
+
* five top-level arguments in argument order: each string of at most 80 characters on one line, number, and boolean,
|
|
108
|
+
* as JSON. A credential-like argument (see {@link isCredentialLikeName}) shows {@link redactedArgumentValue} instead
|
|
109
|
+
* of its value, and string values and the connector, connection, and operation names have their inline credentials
|
|
110
|
+
* replaced (see {@link redactInlineCredentials}), as best-effort hygiene. Longer
|
|
111
|
+
* text, objects, and lists are left out; the approval UI shows them from the arguments. The summary never uses the
|
|
112
|
+
* operation's description, which says what the operation is for, not what this call does. `ConnectorToolSource` and
|
|
113
|
+
* the CLI's connector tools use it; a source of other connector tools may too.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const display = buildConnectorToolApprovalDisplay({
|
|
118
|
+
* connectorId: "slack",
|
|
119
|
+
* connectionName: "support-slack",
|
|
120
|
+
* operation: "postChannelMessage",
|
|
121
|
+
* arguments: '{"channel":"#eng","text":"Deploy is done"}',
|
|
122
|
+
* });
|
|
123
|
+
* // display.summary: 'Calls slack postChannelMessage with connection support-slack; channel: "#eng", text: "Deploy is done".'
|
|
124
|
+
* ```
|
|
125
|
+
* @param input - The call's connector, connection, operation, and arguments.
|
|
126
|
+
* @returns The display, with no preview.
|
|
127
|
+
* @since 0.6.0
|
|
128
|
+
*/
|
|
129
|
+
export declare function buildConnectorToolApprovalDisplay(input: ConnectorToolApprovalDisplayInput): AgentInterruptDisplay;
|
|
130
|
+
/**
|
|
131
|
+
* Returns the display the session stores for a call: `null` for none or one that is not a display; otherwise the
|
|
132
|
+
* target and summary cut to {@link maxApprovalTargetBytes} and {@link maxApprovalSummaryBytes}, and the preview, or
|
|
133
|
+
* `null` when it is over {@link maxApprovalPreviewBytes}.
|
|
134
|
+
*/
|
|
135
|
+
export declare function boundApprovalDisplay(display: unknown): AgentInterruptDisplay | null;
|