@canonmsg/agent-sdk 12.0.0 → 12.1.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 +97 -7
- package/dist/chunks/{chunk-FPQFTTND.js → chunk-7N6OPPW4.js} +1616 -1085
- package/dist/chunks/chunk-N722GWCP.js +4897 -0
- package/dist/chunks/{chunk-OLJ7H4E2.js → chunk-QZ4PPRQW.js} +6462 -6920
- package/dist/chunks/{mls-crypto-NZDNSPAO.js → mls-crypto-LMNQZOS6.js} +3 -3
- package/dist/cli.js +403 -29
- package/dist/drivers/claude.d.ts +8 -2
- package/dist/drivers/codex.d.ts +11 -2
- package/dist/drivers/connector.d.ts +34 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +26 -4
- package/dist/internal/backend-contracts/artifactActions.d.ts +0 -151
- package/dist/internal/backend-contracts/clientFloor.d.ts +41 -0
- package/dist/internal/backend-contracts/communication.d.ts +15 -0
- package/dist/internal/backend-contracts/connectorRelay.d.ts +179 -0
- package/dist/internal/backend-contracts/endpoint.d.ts +17 -0
- package/dist/internal/backend-contracts/endpointContentPolicy.d.ts +15 -4
- package/dist/internal/backend-contracts/index.d.ts +7 -1
- package/dist/internal/backend-contracts/media-url.d.ts +14 -0
- package/dist/internal/backend-contracts/message.d.ts +1 -1
- package/dist/internal/backend-contracts/mlsDevApplication.d.ts +90 -2
- package/dist/internal/backend-contracts/mlsDevCredential.d.ts +5 -2
- package/dist/internal/backend-contracts/mlsDevDeviceCustody.d.ts +2 -1
- package/dist/internal/backend-contracts/mlsDevEnrollment.d.ts +3 -2
- package/dist/internal/backend-contracts/mlsDevFeedReceipt.d.ts +43 -0
- package/dist/internal/backend-contracts/mlsDevGroup.d.ts +129 -5
- package/dist/internal/backend-contracts/mlsDevGroupFeed.d.ts +6 -2
- package/dist/internal/backend-contracts/mlsDevInteraction.d.ts +159 -0
- package/dist/internal/backend-contracts/mlsEnvironment.d.ts +35 -0
- package/dist/internal/backend-contracts/mlsPrincipalAlias.d.ts +23 -0
- package/dist/internal/backend-contracts/runtimeCardFields.d.ts +2 -2
- package/dist/internal/backend-contracts/upload-mime-types.d.ts +17 -0
- package/dist/internal/backend-contracts/verbContract.d.ts +15 -7
- package/dist/internal/backend-contracts/verbSchemas.d.ts +35 -25
- package/dist/internal/core/agent-profiles.d.ts +0 -4
- package/dist/internal/core/approval-format.d.ts +1 -5
- package/dist/internal/core/approval-types.d.ts +1 -2
- package/dist/internal/core/client.d.ts +2 -56
- package/dist/internal/core/constants.d.ts +0 -3
- package/dist/internal/core/endpoint-client.d.ts +14 -1
- package/dist/internal/core/execution-environment-mode.d.ts +0 -2
- package/dist/internal/core/gifs.d.ts +0 -6
- package/dist/internal/core/host-runtime.d.ts +2 -206
- package/dist/internal/core/index.d.ts +21 -60
- package/dist/internal/core/registration.d.ts +1 -17
- package/dist/internal/core/retry.d.ts +0 -9
- package/dist/internal/core/rtdb-rest.d.ts +0 -4
- package/dist/internal/core/runtime-cards.d.ts +0 -45
- package/dist/internal/core/runtime-descriptor.d.ts +1 -60
- package/dist/internal/core/runtime-presentation.d.ts +1 -27
- package/dist/internal/core/runtime-request-manager.d.ts +0 -1
- package/dist/internal/core/self-context.d.ts +0 -39
- package/dist/internal/core/silent-turn.d.ts +1 -38
- package/dist/internal/core/stream.d.ts +2 -1
- package/dist/internal/core/turn-protocol.d.ts +0 -5
- package/dist/internal/core/turn-verbosity.d.ts +0 -12
- package/dist/internal/core/types.d.ts +0 -111
- package/dist/internal/endpoint/engine.d.ts +31 -1
- package/dist/internal/endpoint/index.d.ts +1 -1
- package/dist/internal/endpoint/media.d.ts +5 -0
- package/dist/internal/endpoint/mls-crypto.d.ts +12 -5
- package/dist/internal/endpoint/mls-dev-client.d.ts +9 -1
- package/dist/internal/endpoint/mls-dev-device.d.ts +2 -0
- package/dist/internal/endpoint/mls-dev-groups.d.ts +65 -5
- package/dist/internal/endpoint/mls-dev-interactions.d.ts +99 -0
- package/dist/internal/endpoint/mls-dev-key-package-service.d.ts +13 -0
- package/dist/internal/endpoint/mls-dev-key-packages.d.ts +23 -3
- package/dist/internal/endpoint/mls-dev-text.d.ts +67 -0
- package/dist/internal/endpoint/mls-dev-transport.d.ts +2 -1
- package/dist/internal/endpoint/node-mls-custody-protocol.d.ts +5 -0
- package/dist/internal/endpoint/transport.d.ts +6 -1
- package/dist/media.js +2 -2
- package/dist/runner/errands.d.ts +118 -0
- package/dist/runner/mls.d.ts +97 -0
- package/dist/runner/relay.d.ts +87 -0
- package/dist/runner/runner.d.ts +61 -0
- package/dist/runner/types.d.ts +51 -4
- package/package.json +1 -1
- package/dist/chunks/chunk-6VK4UZHJ.js +0 -2806
- package/dist/internal/backend-contracts/workSessions.d.ts +0 -205
- package/dist/internal/core/agent-resolver.d.ts +0 -49
- package/dist/internal/core/agent-session.d.ts +0 -12
- package/dist/internal/core/artifacts.d.ts +0 -262
- package/dist/internal/core/attached-native-session.d.ts +0 -174
- package/dist/internal/core/attached-session-file-store.d.ts +0 -3
- package/dist/internal/core/control-poller.d.ts +0 -221
- package/dist/internal/core/exclusive-json-file-store.d.ts +0 -7
- package/dist/internal/core/execution-environment.d.ts +0 -55
- package/dist/internal/core/group-context.d.ts +0 -25
- package/dist/internal/core/inbound-frame.d.ts +0 -64
- package/dist/internal/core/local-runtime-catalog.d.ts +0 -131
- package/dist/internal/core/message-format.d.ts +0 -13
- package/dist/internal/core/native-session-interaction.d.ts +0 -44
- package/dist/internal/core/provenance.d.ts +0 -31
- package/dist/internal/core/registration-cli.d.ts +0 -40
- package/dist/internal/core/turn-output-controller.d.ts +0 -69
- package/dist/internal/core/typing-status-publisher.d.ts +0 -14
- package/dist/internal/core/work-session-provider.d.ts +0 -29
- package/dist/internal/core/workspace-discovery.d.ts +0 -17
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
MLS_DEV_DEVICE_HTTP_CONFIGURATION,
|
|
3
2
|
createMlsDevCredentialVerifier,
|
|
3
|
+
mlsDevDeviceHttpConfiguration,
|
|
4
4
|
parseMlsDevClientConfiguration
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7N6OPPW4.js";
|
|
6
6
|
export {
|
|
7
|
-
MLS_DEV_DEVICE_HTTP_CONFIGURATION,
|
|
8
7
|
createMlsDevCredentialVerifier,
|
|
8
|
+
mlsDevDeviceHttpConfiguration,
|
|
9
9
|
parseMlsDevClientConfiguration
|
|
10
10
|
};
|
package/dist/cli.js
CHANGED
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
MLS_SETUP_ACTIONS,
|
|
3
4
|
assertPrivateHome,
|
|
5
|
+
awaitErrand,
|
|
4
6
|
checkCodex,
|
|
5
7
|
claudeDriver,
|
|
6
8
|
codeDriver,
|
|
7
9
|
codexDriver,
|
|
10
|
+
connectorDriver,
|
|
8
11
|
createRunner,
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
errandJournal,
|
|
13
|
+
errandsDirectory,
|
|
14
|
+
loadClaudeQuery,
|
|
15
|
+
loadInstructions,
|
|
16
|
+
loadMlsDevConfiguration,
|
|
17
|
+
loadRelayConfiguration,
|
|
18
|
+
queueErrand,
|
|
19
|
+
readRelayCredential,
|
|
20
|
+
relayRunnerHome,
|
|
21
|
+
runMlsDevSetup,
|
|
22
|
+
runnerLockName,
|
|
23
|
+
startRelayChannel,
|
|
24
|
+
writeRelayCredential
|
|
25
|
+
} from "./chunks/chunk-N722GWCP.js";
|
|
11
26
|
import {
|
|
27
|
+
CanonApiError,
|
|
28
|
+
CanonClient,
|
|
29
|
+
acquireLock,
|
|
30
|
+
isProfileLocked,
|
|
12
31
|
loadProfiles,
|
|
13
|
-
|
|
14
|
-
|
|
32
|
+
readCliPackageVersion,
|
|
33
|
+
resolveCanonRuntimeConnection,
|
|
34
|
+
runCli,
|
|
35
|
+
verifyCanonRuntimeConnection
|
|
36
|
+
} from "./chunks/chunk-QZ4PPRQW.js";
|
|
15
37
|
import {
|
|
16
|
-
__name
|
|
17
|
-
|
|
38
|
+
__name,
|
|
39
|
+
isCanonClientVersion
|
|
40
|
+
} from "./chunks/chunk-7N6OPPW4.js";
|
|
18
41
|
|
|
19
42
|
// src/cli.ts
|
|
20
43
|
import { realpathSync } from "node:fs";
|
|
@@ -22,6 +45,18 @@ import { homedir, tmpdir } from "node:os";
|
|
|
22
45
|
import { dirname, join, resolve } from "node:path";
|
|
23
46
|
import { pathToFileURL } from "node:url";
|
|
24
47
|
import { parseArgs } from "node:util";
|
|
48
|
+
var RUNNER_VERSION = readCliPackageVersion(import.meta.url);
|
|
49
|
+
var RUNNER_CLIENT = isCanonClientVersion(RUNNER_VERSION) ? { kind: "runner", version: RUNNER_VERSION } : void 0;
|
|
50
|
+
function once(handler) {
|
|
51
|
+
let called = false;
|
|
52
|
+
return (error) => {
|
|
53
|
+
if (!called) {
|
|
54
|
+
called = true;
|
|
55
|
+
handler(error);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
__name(once, "once");
|
|
25
60
|
var HELP = `canon-agent: run a Canon agent on the unified runner
|
|
26
61
|
|
|
27
62
|
Usage:
|
|
@@ -31,9 +66,42 @@ Usage:
|
|
|
31
66
|
canon-agent run --driver codex [--cwd <dir>] [--model <id>] [--sandbox <mode>]
|
|
32
67
|
[--approval-policy <policy>] [--codex-path <path>] [--profile <name>]
|
|
33
68
|
[--environment <id>]
|
|
69
|
+
canon-agent run --driver connector --relay-config <path> --mls-dev-config <path>
|
|
70
|
+
[--profile <name>] [--environment <id>]
|
|
71
|
+
canon-agent mls --action <action> --mls-dev-config <path> [--room <id>]
|
|
72
|
+
[--relay-config <path>] [--profile <name>] [--environment <id>]
|
|
73
|
+
canon-agent tell --room <id> --text <text> (--agent <id> | --profile <name>)
|
|
74
|
+
[--environment <id>] [--wait]
|
|
75
|
+
canon-agent post --room <id> --text <text> (--agent <id> | --profile <name>)
|
|
76
|
+
[--environment <id>] [--wait]
|
|
77
|
+
canon-agent errand --to <room or contact id> --why <why> --text <instruction>
|
|
78
|
+
[--origin <room id>] (--agent <id> | --profile <name>)
|
|
79
|
+
[--environment <id>] [--wait]
|
|
80
|
+
canon-agent errands [--follow] [--cancel <errand id>] (--agent <id> | --profile <name>)
|
|
81
|
+
[--environment <id>]
|
|
82
|
+
|
|
83
|
+
Every run command also takes --mls-dev-config <path> (Dev only), which gives the agent
|
|
84
|
+
its MLS device so it can take part in encrypted rooms. Without it, the agent refuses
|
|
85
|
+
encrypted rooms and logs each one once.
|
|
86
|
+
|
|
87
|
+
Team rooms (an owner's agents working together): claude and codex also take
|
|
88
|
+
[--instructions <file>] [--trust-agent <agentId>]...; every run command takes
|
|
89
|
+
[--agent-turn-cap <n>] [--mention-alias <name>]..., which apply in encrypted rooms.
|
|
90
|
+
code, claude and codex take [--allow-session-for-destructive] for encrypted cards.
|
|
91
|
+
|
|
92
|
+
Errands: tell, post and errand direct a running agent from the machine it runs on:
|
|
93
|
+
whoever can write $CANON_HOME commands it, and the CLI itself uses no network. tell
|
|
94
|
+
leaves a private note for the agent's next turn in a room: never posted, it starts no
|
|
95
|
+
turn. post sends the text as the agent's own message, with no turn (encrypted in an
|
|
96
|
+
encrypted room). errand runs one owner-authorised turn that carries the instruction to
|
|
97
|
+
the recipient (a room the agent is in, or a new conversation with a person or agent),
|
|
98
|
+
reports to --origin, and tells later turns there why the agent came. What concerns an
|
|
99
|
+
encrypted room is reported only to an encrypted origin; otherwise the report stays
|
|
100
|
+
local (canon-agent errands). Canon's policies, blocks and rate limits apply as to any
|
|
101
|
+
message from the agent.
|
|
34
102
|
|
|
35
103
|
Flags:
|
|
36
|
-
--driver <name> The runtime driver: "code", "claude" or "
|
|
104
|
+
--driver <name> The runtime driver: "code", "claude", "codex" or "connector".
|
|
37
105
|
--module <path> code: an ES module whose default export answers a turn.
|
|
38
106
|
Its directory is one the agent may send files from.
|
|
39
107
|
--cwd <dir> claude, codex: the directory the runtime works in (default:
|
|
@@ -52,6 +120,64 @@ Flags:
|
|
|
52
120
|
Turns holding anyone else's message are always read-only,
|
|
53
121
|
approve nothing and get only Canon's tools.
|
|
54
122
|
--codex-path <path> codex: the Codex CLI (default: codex on the PATH).
|
|
123
|
+
--instructions <file> claude, codex: standing instructions from the owner (a role,
|
|
124
|
+
say), appended to the runtime's system or developer
|
|
125
|
+
instructions. A UTF-8 file of at most 32 KiB, owned by you
|
|
126
|
+
and not writable by others, read once at start; never sent
|
|
127
|
+
to Canon.
|
|
128
|
+
--trust-agent <id> claude, codex: an agent of the same owner whose messages count
|
|
129
|
+
as the owner's for tool use (repeat for several), only in a
|
|
130
|
+
room whose other members are all listed agents that Canon
|
|
131
|
+
confirms at each turn as active agents of this agent's
|
|
132
|
+
owner (and, in plaintext, only for a final that agent's own
|
|
133
|
+
runner marked as answering its owner). Otherwise they are
|
|
134
|
+
guarded like any other agent's. Approvals still go to the
|
|
135
|
+
owner.
|
|
136
|
+
--agent-turn-cap <n> Encrypted rooms: another agent's message wakes this agent only
|
|
137
|
+
when it @mentions it (by display name, id or an alias), at
|
|
138
|
+
most n times in a row per room until a person writes there
|
|
139
|
+
(default 6; 0: agents never wake it). Plaintext rooms
|
|
140
|
+
follow Canon's group rules.
|
|
141
|
+
--mention-alias <name> Encrypted rooms: another name that @mentions this agent, such
|
|
142
|
+
as its role (repeat for several).
|
|
143
|
+
--allow-session-for-destructive
|
|
144
|
+
Encrypted rooms: let the owner allow an action the runtime
|
|
145
|
+
marks destructive (Claude Code's default-to-no prompts,
|
|
146
|
+
Codex's risky commands and deletions) for the rest of the
|
|
147
|
+
session. Off by default: each such action asks.
|
|
148
|
+
--relay-config <path> connector (Dev only): run as Canon's class-C relay for one agent
|
|
149
|
+
connected through Canon's MCP connector. A private JSON file
|
|
150
|
+
naming the agent, where the channel to Canon's Functions
|
|
151
|
+
listens, and the path of the channel secret. Canon delivers
|
|
152
|
+
the relay's own credential over that channel when the owner
|
|
153
|
+
enables the relay (no API key is used); it is kept in
|
|
154
|
+
$CANON_HOME/relay. The relay serves only encrypted rooms,
|
|
155
|
+
which are then not end-to-end encrypted to that agent. With
|
|
156
|
+
"mls", it sets up the relay's device with that credential.
|
|
157
|
+
--mls-dev-config <p> The operator's MLS configuration: an absolute path to a private
|
|
158
|
+
JSON file with the Dev issuer pins and the custody helper (no
|
|
159
|
+
keys or credentials). Dev only.
|
|
160
|
+
--action <action> mls: status (public device state), provision (create the
|
|
161
|
+
portable vault, once), enroll, renew, publish (this device's
|
|
162
|
+
KeyPackage for --room) or refresh (catch up --room). It never
|
|
163
|
+
starts a model, and uses the same home as "run": stop the
|
|
164
|
+
agent first.
|
|
165
|
+
--room <id> mls: the encrypted room, for publish and refresh. tell, post:
|
|
166
|
+
the conversation.
|
|
167
|
+
--text <text> tell: the note. post: the message. errand: the instruction.
|
|
168
|
+
At most 32 KiB.
|
|
169
|
+
--to <id> errand: a conversation the agent is in, or else a person or
|
|
170
|
+
agent to start a new (plaintext) conversation with.
|
|
171
|
+
--why <why> errand: why the owner sends the agent (at most 4 KiB).
|
|
172
|
+
--origin <id> errand: the conversation the report goes to. A report about an
|
|
173
|
+
encrypted recipient goes only to an encrypted origin.
|
|
174
|
+
--follow errands: go on printing each change.
|
|
175
|
+
--cancel <id> errands: cancel that errand (Stop in its origin also stops it).
|
|
176
|
+
--agent <id> tell, post, errand, errands: the agent (or --profile).
|
|
177
|
+
--wait tell, post, errand: wait up to 30 s for the running agent to take
|
|
178
|
+
it (an errand: to finish its turn), print the outcome, and exit
|
|
179
|
+
1 unless it was accepted (a note kept, a post sent, an errand's
|
|
180
|
+
turn ended and any report it sent to --origin accepted).
|
|
55
181
|
--profile <name> A profile in $CANON_HOME/agents.json (key and endpoints).
|
|
56
182
|
--environment <id> canon-prod-v1 or canon-dev-v1 (default: CANON_ENVIRONMENT_ID).
|
|
57
183
|
--help, -h Show this help.
|
|
@@ -68,11 +194,19 @@ Environment:
|
|
|
68
194
|
|
|
69
195
|
SIGTERM or Ctrl-C stops taking messages, lets running turns finish for 10 seconds,
|
|
70
196
|
then stops them.`;
|
|
71
|
-
var DRIVERS = ["code", "claude", "codex", "hermes"];
|
|
72
|
-
var AVAILABLE = ["code", "claude", "codex"];
|
|
197
|
+
var DRIVERS = ["code", "claude", "codex", "hermes", "connector"];
|
|
198
|
+
var AVAILABLE = ["code", "claude", "codex", "connector"];
|
|
73
199
|
var PERMISSION_MODES = ["default", "acceptEdits", "bypassPermissions"];
|
|
74
200
|
var SANDBOXES = ["workspace-write", "read-only", "danger-full-access"];
|
|
75
201
|
var APPROVAL_POLICIES = ["on-request", "untrusted", "never"];
|
|
202
|
+
function teamOptions(values) {
|
|
203
|
+
const cap = values["agent-turn-cap"];
|
|
204
|
+
if (cap !== void 0 && (!/^\d{1,4}$/.test(cap) || Number(cap) > 1e3)) throw new UsageError("--agent-turn-cap must be a whole number from 0 to 1000.");
|
|
205
|
+
const aliases = values["mention-alias"] ?? [];
|
|
206
|
+
if (aliases.some((alias) => !alias.replace(/^@+/, "").trim())) throw new UsageError("--mention-alias needs a name.");
|
|
207
|
+
return { ...cap !== void 0 ? { agentTurnCap: Number(cap) } : {}, ...aliases.length ? { mentionAliases: aliases } : {} };
|
|
208
|
+
}
|
|
209
|
+
__name(teamOptions, "teamOptions");
|
|
76
210
|
var UsageError = class extends Error {
|
|
77
211
|
static {
|
|
78
212
|
__name(this, "UsageError");
|
|
@@ -86,12 +220,25 @@ async function main() {
|
|
|
86
220
|
throw new UsageError(error instanceof Error ? error.message : String(error));
|
|
87
221
|
}
|
|
88
222
|
const { values, positionals } = parsed;
|
|
89
|
-
if (positionals[0]
|
|
223
|
+
if (!["run", "mls", "tell", "post", "errand", "errands"].includes(positionals[0] ?? "") || positionals.length > 1) {
|
|
224
|
+
throw new UsageError('Expected the "run", "mls", "tell", "post", "errand" or "errands" command.');
|
|
225
|
+
}
|
|
226
|
+
if (positionals[0] === "mls") return mlsSetup(values);
|
|
227
|
+
if (positionals[0] === "errands") return errands(values);
|
|
228
|
+
if (positionals[0] === "tell" || positionals[0] === "post" || positionals[0] === "errand") return errand(positionals[0], values);
|
|
90
229
|
if (!values.driver) throw new UsageError("--driver is required.");
|
|
91
230
|
if (!AVAILABLE.includes(values.driver)) {
|
|
92
231
|
throw new Error(DRIVERS.includes(values.driver) ? `The "${values.driver}" driver is not yet available; ${AVAILABLE.join(", ")} run today.` : `Unknown driver "${values.driver}". Available: ${AVAILABLE.join(", ")}.`);
|
|
93
232
|
}
|
|
94
233
|
if (values.driver === "code" && !values.module) throw new UsageError("--driver code needs --module <path>.");
|
|
234
|
+
if (values.driver === "connector" !== !!values["relay-config"]) throw new UsageError("--relay-config goes with --driver connector, which needs it.");
|
|
235
|
+
if (values.driver === "connector" && !values["mls-dev-config"]) throw new UsageError("--driver connector needs --mls-dev-config <path>: the relay holds the agent's MLS device.");
|
|
236
|
+
if (!["claude", "codex"].includes(values.driver) && (values.instructions !== void 0 || values["trust-agent"]?.length)) {
|
|
237
|
+
throw new UsageError("--instructions and --trust-agent go with --driver claude or codex.");
|
|
238
|
+
}
|
|
239
|
+
const team = teamOptions(values);
|
|
240
|
+
if (values.driver === "connector" && values["allow-session-for-destructive"]) throw new UsageError("--allow-session-for-destructive goes with a driver that asks.");
|
|
241
|
+
if (values.driver === "connector") return runRelay(values, team);
|
|
95
242
|
const permissionMode = values["permission-mode"];
|
|
96
243
|
if (permissionMode !== void 0 && !PERMISSION_MODES.includes(permissionMode)) {
|
|
97
244
|
throw new UsageError(`--permission-mode must be one of ${PERMISSION_MODES.join(", ")}.`);
|
|
@@ -103,17 +250,13 @@ async function main() {
|
|
|
103
250
|
if (approvalPolicy !== void 0 && !APPROVAL_POLICIES.includes(approvalPolicy)) {
|
|
104
251
|
throw new UsageError(`--approval-policy must be one of ${APPROVAL_POLICIES.join(", ")}.`);
|
|
105
252
|
}
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
const home =
|
|
110
|
-
await
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
if (profile && profile.environmentId !== environmentId) {
|
|
114
|
-
throw new Error(`Profile "${values.profile}" belongs to ${profile.environmentId}, not ${environmentId}.`);
|
|
115
|
-
}
|
|
116
|
-
const apiKey = process.env.CANON_API_KEY || profile.apiKey;
|
|
253
|
+
const trustedAgents = values["trust-agent"] ?? [];
|
|
254
|
+
if (trustedAgents.some((id) => !/^[\w.:-]{1,200}$/.test(id))) throw new UsageError("--trust-agent takes an agent id.");
|
|
255
|
+
const instructions = values.instructions !== void 0 ? await loadInstructions(resolve(values.instructions)) : void 0;
|
|
256
|
+
const { environmentId, home, profile, apiKey } = await settings(values);
|
|
257
|
+
const mls = values["mls-dev-config"] ? await loadMlsDevConfiguration(values["mls-dev-config"], { environmentId }) : void 0;
|
|
258
|
+
const baseUrl = process.env.CANON_BASE_URL || profile?.baseUrl;
|
|
259
|
+
const streamUrl = process.env.CANON_STREAM_URL || profile?.streamUrl;
|
|
117
260
|
let driver;
|
|
118
261
|
if (values.driver === "claude") {
|
|
119
262
|
driver = claudeDriver({
|
|
@@ -121,7 +264,8 @@ async function main() {
|
|
|
121
264
|
query: await loadClaudeQuery(),
|
|
122
265
|
...values.model ? { model: values.model } : {},
|
|
123
266
|
...permissionMode ? { permissionMode } : {},
|
|
124
|
-
...values["claude-path"] ? { claudePath: resolve(values["claude-path"]) } : {}
|
|
267
|
+
...values["claude-path"] ? { claudePath: resolve(values["claude-path"]) } : {},
|
|
268
|
+
...instructions ? { instructions } : {}
|
|
125
269
|
});
|
|
126
270
|
} else if (values.driver === "codex") {
|
|
127
271
|
const codexPath = values["codex-path"] ? resolve(values["codex-path"]) : "codex";
|
|
@@ -131,7 +275,8 @@ async function main() {
|
|
|
131
275
|
codexPath,
|
|
132
276
|
...values.model ? { model: values.model } : {},
|
|
133
277
|
...sandbox ? { sandbox } : {},
|
|
134
|
-
...approvalPolicy ? { approvalPolicy } : {}
|
|
278
|
+
...approvalPolicy ? { approvalPolicy } : {},
|
|
279
|
+
...instructions ? { instructions } : {}
|
|
135
280
|
});
|
|
136
281
|
} else {
|
|
137
282
|
const modulePath = realpathSync(resolve(values.module));
|
|
@@ -144,10 +289,19 @@ async function main() {
|
|
|
144
289
|
environmentId,
|
|
145
290
|
home,
|
|
146
291
|
driver,
|
|
147
|
-
|
|
148
|
-
|
|
292
|
+
...mls ? { mls } : {},
|
|
293
|
+
baseUrl,
|
|
294
|
+
streamUrl,
|
|
295
|
+
...team,
|
|
296
|
+
...trustedAgents.length ? { trustedAgents } : {},
|
|
297
|
+
...values["allow-session-for-destructive"] ? { sessionApprovalForDestructive: true } : {},
|
|
298
|
+
...RUNNER_CLIENT ? { client: RUNNER_CLIENT } : {},
|
|
299
|
+
onFatal: once((error) => {
|
|
300
|
+
console.error(`canon-agent: ${error.message}`);
|
|
301
|
+
void runner.stop().catch(() => void 0).finally(() => process.exit(1));
|
|
302
|
+
})
|
|
149
303
|
});
|
|
150
|
-
stopOnSignals(runner);
|
|
304
|
+
stopOnSignals(() => runner.stop());
|
|
151
305
|
try {
|
|
152
306
|
await runner.start();
|
|
153
307
|
} catch (error) {
|
|
@@ -157,6 +311,100 @@ async function main() {
|
|
|
157
311
|
console.error(`canon-agent: running the ${values.driver} driver in ${environmentId}. Ctrl-C stops it.`);
|
|
158
312
|
}
|
|
159
313
|
__name(main, "main");
|
|
314
|
+
async function runRelay(values, team) {
|
|
315
|
+
const { environmentId, home, profile } = await settings(values, { key: false });
|
|
316
|
+
const relay = await loadRelayConfiguration(values["relay-config"], { environmentId });
|
|
317
|
+
const baseUrl = process.env.CANON_BASE_URL || profile?.baseUrl;
|
|
318
|
+
const streamUrl = process.env.CANON_STREAM_URL || profile?.streamUrl;
|
|
319
|
+
let current;
|
|
320
|
+
let latest;
|
|
321
|
+
let switching = Promise.resolve();
|
|
322
|
+
const switchTo = /* @__PURE__ */ __name((stored2, what) => {
|
|
323
|
+
latest = stored2;
|
|
324
|
+
switching = switching.then(() => runUnder(stored2)).catch((error) => {
|
|
325
|
+
console.error(`canon-agent: the relay could not start under ${what} (${error instanceof Error ? error.message : String(error)}); waiting for the owner to enable the relay again.`);
|
|
326
|
+
});
|
|
327
|
+
}, "switchTo");
|
|
328
|
+
const channel = await startRelayChannel({
|
|
329
|
+
agentId: relay.agentId,
|
|
330
|
+
secret: relay.secret,
|
|
331
|
+
host: relay.listen.host,
|
|
332
|
+
port: relay.listen.port,
|
|
333
|
+
// Durable before the channel confirms the delivery; the runner switches over once Canon has committed it.
|
|
334
|
+
onCredential: /* @__PURE__ */ __name((delivery) => switchTo(writeRelayCredential(home, relay, delivery), "its new credential"), "onCredential")
|
|
335
|
+
});
|
|
336
|
+
async function accepted(stored2) {
|
|
337
|
+
for (let attempt = 0; attempt < 60; attempt += 1) {
|
|
338
|
+
if (latest !== stored2) return false;
|
|
339
|
+
try {
|
|
340
|
+
await assertRelayAgent(relay, stored2, baseUrl, streamUrl);
|
|
341
|
+
return true;
|
|
342
|
+
} catch (error) {
|
|
343
|
+
if (!(error instanceof CanonApiError) || error.status !== 401) throw error;
|
|
344
|
+
}
|
|
345
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
346
|
+
}
|
|
347
|
+
throw new Error("Canon did not accept the relay's credential");
|
|
348
|
+
}
|
|
349
|
+
__name(accepted, "accepted");
|
|
350
|
+
async function runUnder(stored2) {
|
|
351
|
+
if (!await accepted(stored2)) return;
|
|
352
|
+
channel.serve(void 0);
|
|
353
|
+
await current?.stop();
|
|
354
|
+
current = void 0;
|
|
355
|
+
const mls = await loadMlsDevConfiguration(values["mls-dev-config"], { environmentId });
|
|
356
|
+
const driver = connectorDriver();
|
|
357
|
+
const runner = await createRunner({
|
|
358
|
+
apiKey: stored2.credential,
|
|
359
|
+
environmentId,
|
|
360
|
+
home: relayRunnerHome(home, stored2.installationId),
|
|
361
|
+
driver,
|
|
362
|
+
mls,
|
|
363
|
+
baseUrl,
|
|
364
|
+
streamUrl,
|
|
365
|
+
relay: true,
|
|
366
|
+
installationId: stored2.installationId,
|
|
367
|
+
...team,
|
|
368
|
+
...RUNNER_CLIENT ? { client: RUNNER_CLIENT } : {},
|
|
369
|
+
onFatal: once((error) => {
|
|
370
|
+
console.error(`canon-agent: ${error.message}`);
|
|
371
|
+
void Promise.resolve().then(() => channel.close()).then(() => runner.stop()).catch(() => void 0).finally(() => process.exit(1));
|
|
372
|
+
})
|
|
373
|
+
});
|
|
374
|
+
try {
|
|
375
|
+
await runner.start();
|
|
376
|
+
} catch (error) {
|
|
377
|
+
await runner.stop().catch(() => void 0);
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
380
|
+
current = runner;
|
|
381
|
+
channel.serve({ runner, inbox: driver.inbox }, stored2.grantId);
|
|
382
|
+
console.error(`canon-agent: relaying ${relay.agentId} under ${stored2.installationId} in ${environmentId}.`);
|
|
383
|
+
}
|
|
384
|
+
__name(runUnder, "runUnder");
|
|
385
|
+
stopOnSignals(async () => {
|
|
386
|
+
await channel.close();
|
|
387
|
+
latest = void 0;
|
|
388
|
+
await switching;
|
|
389
|
+
await current?.stop();
|
|
390
|
+
});
|
|
391
|
+
console.error(`canon-agent: relay channel for ${relay.agentId} listening on ${channel.url}. Ctrl-C stops it.`);
|
|
392
|
+
const stored = await readRelayCredential(home, relay);
|
|
393
|
+
if (stored) switchTo(stored, "its stored credential");
|
|
394
|
+
else console.error("canon-agent: waiting for Canon to deliver this relay's credential (the owner enables the relay for the connection).");
|
|
395
|
+
}
|
|
396
|
+
__name(runRelay, "runRelay");
|
|
397
|
+
async function assertRelayAgent(relay, stored, baseUrl, streamUrl) {
|
|
398
|
+
const connection = resolveCanonRuntimeConnection({ environmentId: relay.environmentId, apiBaseUrl: baseUrl, streamUrl });
|
|
399
|
+
const client = new CanonClient(stored.credential, connection.apiBaseUrl, { environmentId: relay.environmentId });
|
|
400
|
+
try {
|
|
401
|
+
const me = await client.getAgentMe();
|
|
402
|
+
if (me.agentId !== relay.agentId) throw new Error(`The relay credential names agent ${me.agentId}, but the relay configuration names ${relay.agentId}.`);
|
|
403
|
+
} finally {
|
|
404
|
+
await client.close();
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
__name(assertRelayAgent, "assertRelayAgent");
|
|
160
408
|
function parse() {
|
|
161
409
|
return parseArgs({
|
|
162
410
|
allowPositionals: true,
|
|
@@ -171,18 +419,144 @@ function parse() {
|
|
|
171
419
|
"claude-path": { type: "string" },
|
|
172
420
|
sandbox: { type: "string" },
|
|
173
421
|
"approval-policy": { type: "string" },
|
|
174
|
-
"codex-path": { type: "string" }
|
|
422
|
+
"codex-path": { type: "string" },
|
|
423
|
+
"mls-dev-config": { type: "string" },
|
|
424
|
+
action: { type: "string" },
|
|
425
|
+
room: { type: "string" },
|
|
426
|
+
"relay-config": { type: "string" },
|
|
427
|
+
instructions: { type: "string" },
|
|
428
|
+
"trust-agent": { type: "string", multiple: true },
|
|
429
|
+
"agent-turn-cap": { type: "string" },
|
|
430
|
+
"mention-alias": { type: "string", multiple: true },
|
|
431
|
+
"allow-session-for-destructive": { type: "boolean" },
|
|
432
|
+
text: { type: "string" },
|
|
433
|
+
agent: { type: "string" },
|
|
434
|
+
wait: { type: "boolean" },
|
|
435
|
+
to: { type: "string" },
|
|
436
|
+
why: { type: "string" },
|
|
437
|
+
origin: { type: "string" },
|
|
438
|
+
follow: { type: "boolean" },
|
|
439
|
+
cancel: { type: "string" }
|
|
175
440
|
}
|
|
176
441
|
});
|
|
177
442
|
}
|
|
178
443
|
__name(parse, "parse");
|
|
179
|
-
function
|
|
444
|
+
async function settings(values, { key = true } = {}) {
|
|
445
|
+
const environmentId = values.environment || process.env.CANON_ENVIRONMENT_ID;
|
|
446
|
+
if (!environmentId) throw new Error("CANON_ENVIRONMENT_ID (or --environment) is required.");
|
|
447
|
+
if (key && !values.profile && !process.env.CANON_API_KEY) throw new Error("CANON_API_KEY (or --profile <name>) is required.");
|
|
448
|
+
const home = resolve(process.env.CANON_HOME || join(homedir(), ".canon"));
|
|
449
|
+
await assertPrivateHome(home);
|
|
450
|
+
const profile = values.profile ? loadProfiles(home)[values.profile] : void 0;
|
|
451
|
+
if (values.profile && !profile) throw new Error(`No profile "${values.profile}" in ${join(home, "agents.json")}.`);
|
|
452
|
+
if (profile && profile.environmentId !== environmentId) {
|
|
453
|
+
throw new Error(`Profile "${values.profile}" belongs to ${profile.environmentId}, not ${environmentId}.`);
|
|
454
|
+
}
|
|
455
|
+
return { environmentId, home, profile, apiKey: process.env.CANON_API_KEY || profile?.apiKey || "" };
|
|
456
|
+
}
|
|
457
|
+
__name(settings, "settings");
|
|
458
|
+
async function mlsSetup(values) {
|
|
459
|
+
const action = values.action;
|
|
460
|
+
if (!action || !MLS_SETUP_ACTIONS.includes(action)) throw new UsageError(`--action must be one of ${MLS_SETUP_ACTIONS.join(", ")}.`);
|
|
461
|
+
if ((action === "publish" || action === "refresh") !== !!values.room) throw new UsageError("--room is needed for publish and refresh, and only for them.");
|
|
462
|
+
if (!values["mls-dev-config"]) throw new UsageError("--mls-dev-config <path> is required.");
|
|
463
|
+
const settled = await settings(values, { key: !values["relay-config"] });
|
|
464
|
+
const { environmentId, profile } = settled;
|
|
465
|
+
const relay = values["relay-config"] ? await loadRelayConfiguration(values["relay-config"], { environmentId }) : void 0;
|
|
466
|
+
const stored = relay ? await readRelayCredential(settled.home, relay) : void 0;
|
|
467
|
+
if (relay && !stored) {
|
|
468
|
+
throw new Error("This relay has no credential yet: start it (canon-agent run --driver connector) and have the owner enable the relay.");
|
|
469
|
+
}
|
|
470
|
+
const apiKey = stored ? stored.credential : settled.apiKey;
|
|
471
|
+
const home = stored ? relayRunnerHome(settled.home, stored.installationId) : settled.home;
|
|
472
|
+
const config = await loadMlsDevConfiguration(values["mls-dev-config"], { environmentId });
|
|
473
|
+
let client;
|
|
474
|
+
let lock;
|
|
475
|
+
try {
|
|
476
|
+
const connection = resolveCanonRuntimeConnection({
|
|
477
|
+
environmentId,
|
|
478
|
+
apiBaseUrl: process.env.CANON_BASE_URL || profile?.baseUrl,
|
|
479
|
+
streamUrl: process.env.CANON_STREAM_URL || profile?.streamUrl
|
|
480
|
+
});
|
|
481
|
+
await verifyCanonRuntimeConnection(connection);
|
|
482
|
+
client = new CanonClient(apiKey, connection.apiBaseUrl, {
|
|
483
|
+
environmentId,
|
|
484
|
+
streamUrl: connection.streamUrl,
|
|
485
|
+
stateDirectory: join(home, "endpoint"),
|
|
486
|
+
mlsDev: { configuration: config.configuration, custody: config.custody },
|
|
487
|
+
...stored ? { installationId: stored.installationId } : {},
|
|
488
|
+
...RUNNER_CLIENT ? { client: RUNNER_CLIENT } : {}
|
|
489
|
+
});
|
|
490
|
+
const me = await client.getAgentMe();
|
|
491
|
+
lock = acquireLock(runnerLockName(environmentId, me.agentId), home);
|
|
492
|
+
console.log(JSON.stringify(await runMlsDevSetup(await client.getEndpoint(), action, values.room, config.provision)));
|
|
493
|
+
} finally {
|
|
494
|
+
try {
|
|
495
|
+
await client?.close();
|
|
496
|
+
} finally {
|
|
497
|
+
try {
|
|
498
|
+
await config.close();
|
|
499
|
+
} finally {
|
|
500
|
+
lock?.release();
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
__name(mlsSetup, "mlsSetup");
|
|
506
|
+
async function errandHome(values) {
|
|
507
|
+
if (!values.agent && !values.profile) throw new UsageError("--agent <id> or --profile <name> names the agent.");
|
|
508
|
+
if (values.agent !== void 0 && (!/^[\w.:-]{1,200}$/.test(values.agent) || /^\.+$/.test(values.agent))) throw new UsageError("--agent takes an agent id.");
|
|
509
|
+
const { environmentId, home, profile } = await settings(values, { key: false });
|
|
510
|
+
if (values.agent && profile && profile.agentId !== values.agent) throw new UsageError("--agent and --profile name different agents.");
|
|
511
|
+
const agentId = values.agent ?? profile.agentId;
|
|
512
|
+
return { agentId, directory: errandsDirectory(home, environmentId, agentId), running: isProfileLocked(runnerLockName(environmentId, agentId), home).locked };
|
|
513
|
+
}
|
|
514
|
+
__name(errandHome, "errandHome");
|
|
515
|
+
async function errand(kind, values) {
|
|
516
|
+
const input = kind === "errand" ? { kind, to: values.to ?? "", why: values.why ?? "", text: values.text ?? "", ...values.origin ? { origin: values.origin } : {} } : { kind, conversationId: values.room ?? "", text: values.text ?? "" };
|
|
517
|
+
if (kind === "errand" && (!values.to || values.why === void 0)) throw new UsageError("errand needs --to <room or contact id> and --why <why>.");
|
|
518
|
+
if (kind !== "errand" && !values.room) throw new UsageError("--room <conversation id> is required.");
|
|
519
|
+
if (values.text === void 0) throw new UsageError("--text <text> is required.");
|
|
520
|
+
const { agentId, directory, running } = await errandHome(values);
|
|
521
|
+
const command = queueErrand(directory, input);
|
|
522
|
+
if (!running) console.error(`canon-agent: no runner of ${agentId} is running in this home; it takes the ${kind} when it starts.`);
|
|
523
|
+
await report(directory, command, !!values.wait, running);
|
|
524
|
+
}
|
|
525
|
+
__name(errand, "errand");
|
|
526
|
+
async function report(directory, command, wait, running) {
|
|
527
|
+
if (!wait) return console.log(JSON.stringify({ id: command.id, kind: command.kind, record: join(directory, "journal", `${command.id}.json`) }));
|
|
528
|
+
const { record: found, accepted } = await awaitErrand(directory, command, running ? 3e4 : 0);
|
|
529
|
+
const { text: _text, ...outcome } = found ?? { version: 1, id: command.id, status: "queued", updatedAt: command.createdAt };
|
|
530
|
+
console.log(JSON.stringify({ ...outcome, kind: command.kind }));
|
|
531
|
+
if (!accepted) process.exitCode = 1;
|
|
532
|
+
}
|
|
533
|
+
__name(report, "report");
|
|
534
|
+
async function errands(values) {
|
|
535
|
+
const { directory, running } = await errandHome(values);
|
|
536
|
+
if (values.cancel !== void 0) {
|
|
537
|
+
if (!/^[0-9a-f]{32}$/.test(values.cancel)) throw new UsageError("--cancel takes an errand id.");
|
|
538
|
+
return report(directory, queueErrand(directory, { kind: "cancel", errand: values.cancel }), running, running);
|
|
539
|
+
}
|
|
540
|
+
const journal = errandJournal(directory);
|
|
541
|
+
const shown = /* @__PURE__ */ new Map();
|
|
542
|
+
const show = /* @__PURE__ */ __name(() => {
|
|
543
|
+
for (const record of journal.list().filter((candidate) => candidate.kind === "errand").sort((a, b) => (a.createdAt ?? "").localeCompare(b.createdAt ?? "") || a.id.localeCompare(b.id))) {
|
|
544
|
+
if (shown.get(record.id) === record.updatedAt) continue;
|
|
545
|
+
shown.set(record.id, record.updatedAt);
|
|
546
|
+
console.log(JSON.stringify(record));
|
|
547
|
+
}
|
|
548
|
+
}, "show");
|
|
549
|
+
show();
|
|
550
|
+
if (values.follow) setInterval(show, 500);
|
|
551
|
+
}
|
|
552
|
+
__name(errands, "errands");
|
|
553
|
+
function stopOnSignals(stop) {
|
|
180
554
|
let stopping = false;
|
|
181
555
|
const onSignal = /* @__PURE__ */ __name((signal) => {
|
|
182
556
|
if (stopping) process.exit(1);
|
|
183
557
|
stopping = true;
|
|
184
558
|
console.error(`canon-agent: ${signal}, stopping.`);
|
|
185
|
-
|
|
559
|
+
stop().then(() => process.exit(0), (error) => {
|
|
186
560
|
console.error(`canon-agent: ${error instanceof Error ? error.message : String(error)}`);
|
|
187
561
|
process.exit(1);
|
|
188
562
|
});
|
package/dist/drivers/claude.d.ts
CHANGED
|
@@ -14,10 +14,16 @@ export interface ClaudeDriverOptions {
|
|
|
14
14
|
model?: string;
|
|
15
15
|
/**
|
|
16
16
|
* `default` (the default) puts every tool call Claude Code would ask about to the owner as a Canon approval.
|
|
17
|
-
* `acceptEdits` and `bypassPermissions` approve more on their own. In every mode, a turn holding
|
|
18
|
-
* may use only Canon's
|
|
17
|
+
* `acceptEdits` and `bypassPermissions` approve more on their own. In every mode, a turn holding a message from anyone
|
|
18
|
+
* but the owner or a confirmed trusted agent of the owner (`TurnInputMessage.trustedAgent`) may use only Canon's
|
|
19
|
+
* tools, AskUserQuestion and ToolSearch.
|
|
19
20
|
*/
|
|
20
21
|
permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions';
|
|
22
|
+
/**
|
|
23
|
+
* The owner's standing instructions for this agent (its role, say), appended to Claude Code's system prompt after
|
|
24
|
+
* Canon's own framing. At most 32 KiB; the CLI reads them from `--instructions <file>`. Never sent to Canon.
|
|
25
|
+
*/
|
|
26
|
+
instructions?: string;
|
|
21
27
|
/** A Claude Code executable to run instead of the one bundled with the SDK. */
|
|
22
28
|
claudePath?: string;
|
|
23
29
|
/** How long an interrupted Claude Code may take to stop before its process is closed (default 5 s). */
|
package/dist/drivers/codex.d.ts
CHANGED
|
@@ -8,9 +8,15 @@ export interface CodexDriverOptions {
|
|
|
8
8
|
sandbox?: 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
9
9
|
/**
|
|
10
10
|
* When Codex asks before acting in the owner's turns: `on-request` (the default), `untrusted` or `never`. Each request
|
|
11
|
-
* becomes a Canon approval. A turn holding anyone
|
|
11
|
+
* becomes a Canon approval. A turn holding a message from anyone but the owner or a confirmed trusted agent of the owner
|
|
12
|
+
* (`TurnInputMessage.trustedAgent`) is always read-only and approves nothing.
|
|
12
13
|
*/
|
|
13
14
|
approvalPolicy?: 'untrusted' | 'on-request' | 'never';
|
|
15
|
+
/**
|
|
16
|
+
* The owner's standing instructions for this agent (its role, say), appended to the thread's developer instructions
|
|
17
|
+
* after Canon's own framing. At most 32 KiB; the CLI reads them from `--instructions <file>`. Never sent to Canon.
|
|
18
|
+
*/
|
|
19
|
+
instructions?: string;
|
|
14
20
|
/** The Codex CLI (default: `codex` on the PATH). */
|
|
15
21
|
codexPath?: string;
|
|
16
22
|
/** How long an interrupted Codex may take to stop before its process is closed (default 5 s). */
|
|
@@ -23,7 +29,10 @@ export declare function checkCodex(codexPath?: string): string;
|
|
|
23
29
|
* Codex's requests to its client, from the turn's thread or a subagent's. Approvals are scoped to exactly what they
|
|
24
30
|
* allow: a session approval covers the same command with the same directory, network destination and permissions, the
|
|
25
31
|
* same set of files or the same MCP tool, never "commands". A request whose scope is not fully known is approved once.
|
|
26
|
-
*
|
|
32
|
+
* A command's, file change's or permission request's key is `exec`, `apply_patch` or `permissions` and a digest of what
|
|
33
|
+
* it covers (`callScope`), which the runner keeps as it is and the cards offer as one exact call; an MCP approval's key
|
|
34
|
+
* names its server and tool, all of whose calls it covers. `rpcId` is the request's own JSON-RPC id, the identity of a
|
|
35
|
+
* request that names no item.
|
|
27
36
|
*/
|
|
28
37
|
export declare function answerCodexRequest(turn: DriverTurn, method: string, params: Json, items: Map<string, Json>, rpcId: unknown): Promise<unknown>;
|
|
29
38
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ConnectorRelayAck, type ConnectorRelayClaim, type ConnectorRelayInputRef, type ConnectorRelaySettleOutcome } from '../internal/backend-contracts/index.js';
|
|
2
|
+
import { type RuntimeDriver } from '../runner/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The driver boundary (spec §11.3): what the relay channel calls on behalf of the remote assistant, through the
|
|
5
|
+
* connector's pickup tools. Each running turn is one pending input until the assistant claims it.
|
|
6
|
+
*/
|
|
7
|
+
export interface ConnectorInbox {
|
|
8
|
+
/** Unclaimed inputs in the room, oldest first. */
|
|
9
|
+
pending(conversationId: string, limit?: number): ConnectorRelayInputRef[];
|
|
10
|
+
/**
|
|
11
|
+
* The first claim gets `runAllowed` and the turn's input, once Canon confirms the agent may still act on it (its
|
|
12
|
+
* membership and the room's audience, read now, never from a hint); a repeat gets its state, never the input again.
|
|
13
|
+
* A claim that cannot be confirmed by `deadline` (epoch ms) is refused as busy and the input stays pending.
|
|
14
|
+
*/
|
|
15
|
+
claim(inputId: string, requestId: string, options?: {
|
|
16
|
+
deadline?: number;
|
|
17
|
+
}): Promise<ConnectorRelayClaim>;
|
|
18
|
+
/** The turn's one final. */
|
|
19
|
+
reply(inputId: string, requestId: string, text: string): ConnectorRelayAck;
|
|
20
|
+
/** `completed` or `no_reply`: a silent turn; `failed`: the runner's failure notice. */
|
|
21
|
+
settle(inputId: string, requestId: string, outcome: ConnectorRelaySettleOutcome): ConnectorRelayAck;
|
|
22
|
+
}
|
|
23
|
+
export interface ConnectorDriver extends RuntimeDriver {
|
|
24
|
+
readonly name: 'connector';
|
|
25
|
+
readonly inbox: ConnectorInbox;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `connector` driver: the runtime is an assistant its provider runs (ChatGPT, Claude.ai and the like), reached
|
|
29
|
+
* through Canon's remote MCP connector, so a turn waits, as one pending input, for the assistant to claim it and answer
|
|
30
|
+
* through the connector's pickup tools (spec §11.3). It keeps no timer: an assistant that never answers is the runner's
|
|
31
|
+
* no-progress deadline, which a claim restarts. It never calls Canon itself; the relay channel calls its inbox, and the
|
|
32
|
+
* runner confirms each claim with Canon.
|
|
33
|
+
*/
|
|
34
|
+
export declare function connectorDriver(): ConnectorDriver;
|