@canonmsg/agent-sdk 11.2.1 → 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.
Files changed (181) hide show
  1. package/README.md +248 -523
  2. package/dist/chunks/chunk-7N6OPPW4.js +5430 -0
  3. package/dist/chunks/chunk-N722GWCP.js +4897 -0
  4. package/dist/chunks/chunk-QZ4PPRQW.js +14247 -0
  5. package/dist/chunks/mls-crypto-LMNQZOS6.js +10 -0
  6. package/dist/cli.js +572 -0
  7. package/dist/drivers/claude.d.ts +42 -0
  8. package/dist/drivers/code.d.ts +18 -0
  9. package/dist/drivers/codex.d.ts +46 -0
  10. package/dist/drivers/connector.d.ts +34 -0
  11. package/dist/index.d.ts +20 -25
  12. package/dist/index.js +91 -13
  13. package/dist/internal/backend-contracts/agentBehaviorPolicy.d.ts +122 -0
  14. package/dist/internal/backend-contracts/agentDirectory.d.ts +32 -0
  15. package/dist/internal/backend-contracts/agentOrigin.d.ts +23 -0
  16. package/dist/internal/backend-contracts/agentSearch.d.ts +17 -0
  17. package/dist/internal/backend-contracts/api-origins.generated.d.ts +4 -0
  18. package/dist/internal/backend-contracts/apiErrors.d.ts +1 -0
  19. package/dist/internal/backend-contracts/artifactActions.d.ts +8 -0
  20. package/dist/internal/backend-contracts/artifacts.d.ts +386 -0
  21. package/dist/internal/backend-contracts/clientFloor.d.ts +41 -0
  22. package/dist/internal/backend-contracts/communication.d.ts +146 -0
  23. package/dist/internal/backend-contracts/connectorRelay.d.ts +179 -0
  24. package/dist/internal/backend-contracts/conversationMembership.d.ts +28 -0
  25. package/dist/internal/backend-contracts/deliveryObservation.d.ts +23 -0
  26. package/dist/internal/backend-contracts/diffRedaction.d.ts +6 -0
  27. package/dist/internal/backend-contracts/endpoint-unread.d.ts +4 -0
  28. package/dist/internal/backend-contracts/endpoint.d.ts +120 -0
  29. package/dist/internal/backend-contracts/endpointContentPolicy.d.ts +48 -0
  30. package/dist/internal/backend-contracts/environment.d.ts +20 -0
  31. package/dist/internal/backend-contracts/externalInbound.d.ts +24 -0
  32. package/dist/internal/backend-contracts/firestoreValues.d.ts +9 -0
  33. package/dist/internal/backend-contracts/index.d.ts +54 -0
  34. package/dist/internal/backend-contracts/media-url.d.ts +20 -0
  35. package/dist/internal/backend-contracts/media.d.ts +51 -0
  36. package/dist/internal/backend-contracts/mediaDelivery.d.ts +46 -0
  37. package/dist/internal/backend-contracts/mediaTransferProtocol.d.ts +17 -0
  38. package/dist/internal/backend-contracts/membershipChange.d.ts +21 -0
  39. package/dist/internal/backend-contracts/message.d.ts +86 -0
  40. package/dist/internal/backend-contracts/messageText.d.ts +6 -0
  41. package/dist/internal/backend-contracts/mlsDevApplication.d.ts +161 -0
  42. package/dist/internal/backend-contracts/mlsDevCredential.d.ts +78 -0
  43. package/dist/internal/backend-contracts/mlsDevCredentialReconciliation.d.ts +45 -0
  44. package/dist/internal/backend-contracts/mlsDevDeviceCustody.d.ts +52 -0
  45. package/dist/internal/backend-contracts/mlsDevEnrollment.d.ts +75 -0
  46. package/dist/internal/backend-contracts/mlsDevFeedReceipt.d.ts +43 -0
  47. package/dist/internal/backend-contracts/mlsDevGroup.d.ts +321 -0
  48. package/dist/internal/backend-contracts/mlsDevGroupFeed.d.ts +51 -0
  49. package/dist/internal/backend-contracts/mlsDevInteraction.d.ts +159 -0
  50. package/dist/internal/backend-contracts/mlsDevKeyPackage.d.ts +42 -0
  51. package/dist/internal/backend-contracts/mlsDevKeyPackages.d.ts +55 -0
  52. package/dist/internal/backend-contracts/mlsEnvironment.d.ts +35 -0
  53. package/dist/internal/backend-contracts/mlsPrincipalAlias.d.ts +23 -0
  54. package/dist/internal/backend-contracts/moderation.d.ts +7 -0
  55. package/dist/internal/backend-contracts/plaintextProcessors.d.ts +63 -0
  56. package/dist/internal/backend-contracts/preparedContent.d.ts +54 -0
  57. package/dist/internal/backend-contracts/replyAuthority.d.ts +14 -0
  58. package/dist/internal/backend-contracts/runtimeCardFields.d.ts +66 -0
  59. package/dist/internal/backend-contracts/runtimeCardStorage.d.ts +3 -0
  60. package/dist/internal/backend-contracts/runtimeDescriptor.d.ts +88 -0
  61. package/dist/internal/backend-contracts/selfContext.d.ts +9 -0
  62. package/dist/internal/backend-contracts/turnProtocol.d.ts +43 -0
  63. package/dist/internal/backend-contracts/upload-mime-types.d.ts +17 -0
  64. package/dist/internal/backend-contracts/verbContract.d.ts +856 -0
  65. package/dist/internal/backend-contracts/verbSchemas.d.ts +1717 -0
  66. package/dist/internal/backend-contracts/verbWire.d.ts +493 -0
  67. package/dist/internal/backend-contracts/webAuth.d.ts +8 -0
  68. package/dist/internal/core/agent-profiles.d.ts +65 -0
  69. package/dist/internal/core/approval-format.d.ts +22 -0
  70. package/dist/internal/core/approval-manager.d.ts +43 -0
  71. package/dist/internal/core/approval-types.d.ts +73 -0
  72. package/dist/internal/core/base-url.d.ts +1 -0
  73. package/dist/internal/core/cli-metadata.d.ts +13 -0
  74. package/dist/internal/core/client.d.ts +432 -0
  75. package/dist/internal/core/completed-output-journal.d.ts +39 -0
  76. package/dist/internal/core/constants.d.ts +1 -0
  77. package/dist/internal/core/endpoint-client.d.ts +56 -0
  78. package/dist/internal/core/execution-environment-mode.d.ts +6 -0
  79. package/dist/internal/core/gifs.d.ts +29 -0
  80. package/dist/internal/core/host-runtime.d.ts +53 -0
  81. package/dist/internal/core/index.d.ts +68 -0
  82. package/dist/internal/core/node-media.d.ts +6 -0
  83. package/dist/internal/core/policy.d.ts +2 -0
  84. package/dist/internal/core/registration-profile.d.ts +10 -0
  85. package/dist/internal/core/registration-session.d.ts +55 -0
  86. package/dist/internal/core/registration.d.ts +5 -0
  87. package/dist/internal/core/retry.d.ts +113 -0
  88. package/dist/internal/core/rtdb-rest.d.ts +141 -0
  89. package/dist/internal/core/runtime-cards.d.ts +286 -0
  90. package/dist/internal/core/runtime-descriptor.d.ts +16 -0
  91. package/dist/internal/core/runtime-endpoints.d.ts +26 -0
  92. package/dist/internal/core/runtime-heartbeat.d.ts +29 -0
  93. package/dist/internal/core/runtime-presentation.d.ts +9 -0
  94. package/dist/internal/core/runtime-request-manager.d.ts +283 -0
  95. package/dist/internal/core/runtime-state-publisher.d.ts +42 -0
  96. package/dist/internal/core/self-context.d.ts +22 -0
  97. package/dist/internal/core/silent-turn.d.ts +49 -0
  98. package/dist/internal/core/stream.d.ts +78 -0
  99. package/dist/internal/core/turn-protocol.d.ts +28 -0
  100. package/dist/internal/core/turn-verbosity.d.ts +85 -0
  101. package/dist/internal/core/types.d.ts +964 -0
  102. package/dist/internal/core/unified-diff.d.ts +35 -0
  103. package/dist/internal/endpoint/artifact-images.d.ts +60 -0
  104. package/dist/internal/endpoint/artifact-reducer.d.ts +35 -0
  105. package/dist/internal/endpoint/artifact-views.d.ts +113 -0
  106. package/dist/internal/endpoint/artifacts.d.ts +75 -0
  107. package/dist/internal/endpoint/delivery.d.ts +47 -0
  108. package/dist/internal/endpoint/engine.d.ts +249 -0
  109. package/dist/internal/endpoint/ephemeral.d.ts +8 -0
  110. package/dist/internal/endpoint/events.d.ts +32 -0
  111. package/dist/internal/endpoint/external-inbound.d.ts +36 -0
  112. package/dist/internal/endpoint/handoff.d.ts +50 -0
  113. package/dist/internal/endpoint/history.d.ts +22 -0
  114. package/dist/internal/endpoint/image-generation-errors.d.ts +2 -0
  115. package/dist/internal/endpoint/inbound.d.ts +29 -0
  116. package/dist/internal/endpoint/index.d.ts +32 -0
  117. package/dist/internal/endpoint/media.d.ts +177 -0
  118. package/dist/internal/endpoint/migration.d.ts +50 -0
  119. package/dist/internal/endpoint/mls-crypto.d.ts +32 -0
  120. package/dist/internal/endpoint/mls-dev-client.d.ts +52 -0
  121. package/dist/internal/endpoint/mls-dev-device.d.ts +69 -0
  122. package/dist/internal/endpoint/mls-dev-groups.d.ts +174 -0
  123. package/dist/internal/endpoint/mls-dev-interactions.d.ts +99 -0
  124. package/dist/internal/endpoint/mls-dev-key-package-service.d.ts +46 -0
  125. package/dist/internal/endpoint/mls-dev-key-packages.d.ts +62 -0
  126. package/dist/internal/endpoint/mls-dev-text.d.ts +67 -0
  127. package/dist/internal/endpoint/mls-dev-transport.d.ts +38 -0
  128. package/dist/internal/endpoint/node-mls-custody-protocol.d.ts +29 -0
  129. package/dist/internal/endpoint/node-mls-custody.d.ts +15 -0
  130. package/dist/internal/endpoint/node.d.ts +7 -0
  131. package/dist/internal/endpoint/observe-query.d.ts +17 -0
  132. package/dist/internal/endpoint/portable-node-mls-custody.d.ts +23 -0
  133. package/dist/internal/endpoint/queue.d.ts +22 -0
  134. package/dist/internal/endpoint/recovery.d.ts +27 -0
  135. package/dist/internal/endpoint/retention.d.ts +7 -0
  136. package/dist/internal/endpoint/store.d.ts +22 -0
  137. package/dist/internal/endpoint/sync.d.ts +33 -0
  138. package/dist/internal/endpoint/transient-publisher.d.ts +8 -0
  139. package/dist/internal/endpoint/transport.d.ts +63 -0
  140. package/dist/media.d.ts +1 -1
  141. package/dist/media.js +42 -541
  142. package/dist/runner/errands.d.ts +118 -0
  143. package/dist/runner/mls.d.ts +97 -0
  144. package/dist/runner/relay.d.ts +87 -0
  145. package/dist/runner/runner.d.ts +98 -0
  146. package/dist/runner/types.d.ts +215 -0
  147. package/package.json +18 -5
  148. package/dist/attached-session.d.ts +0 -58
  149. package/dist/attached-session.js +0 -638
  150. package/dist/bounded-file-read.d.ts +0 -14
  151. package/dist/bounded-file-read.js +0 -34
  152. package/dist/canon-agent.d.ts +0 -236
  153. package/dist/canon-agent.js +0 -2531
  154. package/dist/debouncer.d.ts +0 -18
  155. package/dist/debouncer.js +0 -133
  156. package/dist/inbound-handoff.d.ts +0 -6
  157. package/dist/inbound-handoff.js +0 -17
  158. package/dist/managed-session-host.d.ts +0 -27
  159. package/dist/managed-session-host.js +0 -195
  160. package/dist/managed-session-setup.d.ts +0 -99
  161. package/dist/managed-session-setup.js +0 -234
  162. package/dist/realtime.d.ts +0 -62
  163. package/dist/realtime.js +0 -193
  164. package/dist/runtime-card.d.ts +0 -48
  165. package/dist/runtime-card.js +0 -64
  166. package/dist/session-manager.d.ts +0 -77
  167. package/dist/session-manager.js +0 -285
  168. package/dist/turn-streaming-request.d.ts +0 -17
  169. package/dist/turn-streaming-request.js +0 -22
  170. package/dist/turn-verbosity-option.d.ts +0 -33
  171. package/dist/turn-verbosity-option.js +0 -23
  172. package/dist/types.d.ts +0 -387
  173. package/dist/types.js +0 -1
  174. package/dist/work-session-coordination.d.ts +0 -21
  175. package/dist/work-session-coordination.js +0 -53
  176. package/dist/work-session-host.d.ts +0 -31
  177. package/dist/work-session-host.js +0 -617
  178. package/dist/work-session-interactions.d.ts +0 -12
  179. package/dist/work-session-interactions.js +0 -173
  180. package/dist/work-session-state.d.ts +0 -36
  181. package/dist/work-session-state.js +0 -62
@@ -0,0 +1,10 @@
1
+ import {
2
+ createMlsDevCredentialVerifier,
3
+ mlsDevDeviceHttpConfiguration,
4
+ parseMlsDevClientConfiguration
5
+ } from "./chunk-7N6OPPW4.js";
6
+ export {
7
+ createMlsDevCredentialVerifier,
8
+ mlsDevDeviceHttpConfiguration,
9
+ parseMlsDevClientConfiguration
10
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,572 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ MLS_SETUP_ACTIONS,
4
+ assertPrivateHome,
5
+ awaitErrand,
6
+ checkCodex,
7
+ claudeDriver,
8
+ codeDriver,
9
+ codexDriver,
10
+ connectorDriver,
11
+ createRunner,
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";
26
+ import {
27
+ CanonApiError,
28
+ CanonClient,
29
+ acquireLock,
30
+ isProfileLocked,
31
+ loadProfiles,
32
+ readCliPackageVersion,
33
+ resolveCanonRuntimeConnection,
34
+ runCli,
35
+ verifyCanonRuntimeConnection
36
+ } from "./chunks/chunk-QZ4PPRQW.js";
37
+ import {
38
+ __name,
39
+ isCanonClientVersion
40
+ } from "./chunks/chunk-7N6OPPW4.js";
41
+
42
+ // src/cli.ts
43
+ import { realpathSync } from "node:fs";
44
+ import { homedir, tmpdir } from "node:os";
45
+ import { dirname, join, resolve } from "node:path";
46
+ import { pathToFileURL } from "node:url";
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");
60
+ var HELP = `canon-agent: run a Canon agent on the unified runner
61
+
62
+ Usage:
63
+ canon-agent run --driver code --module <path> [--profile <name>] [--environment <id>]
64
+ canon-agent run --driver claude [--cwd <dir>] [--model <id>] [--permission-mode <mode>]
65
+ [--claude-path <path>] [--profile <name>] [--environment <id>]
66
+ canon-agent run --driver codex [--cwd <dir>] [--model <id>] [--sandbox <mode>]
67
+ [--approval-policy <policy>] [--codex-path <path>] [--profile <name>]
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.
102
+
103
+ Flags:
104
+ --driver <name> The runtime driver: "code", "claude", "codex" or "connector".
105
+ --module <path> code: an ES module whose default export answers a turn.
106
+ Its directory is one the agent may send files from.
107
+ --cwd <dir> claude, codex: the directory the runtime works in (default:
108
+ the current one). The agent may send files from it.
109
+ --model <id> claude, codex: the model (default: the runtime's).
110
+ --permission-mode <m> claude: "default" puts each tool call Claude Code would ask
111
+ about to Canon as an approval; "acceptEdits" and
112
+ "bypassPermissions" allow more without asking, and then
113
+ only the owner's messages may lead to tool use.
114
+ --claude-path <path> claude: a Claude Code executable to use instead of the
115
+ SDK's bundled one.
116
+ --sandbox <mode> codex: "workspace-write" (default), "read-only" or
117
+ "danger-full-access", for the owner's turns.
118
+ --approval-policy <p> codex: "on-request" (default), "untrusted" or "never": when
119
+ Codex asks the owner (as a Canon approval) before acting.
120
+ Turns holding anyone else's message are always read-only,
121
+ approve nothing and get only Canon's tools.
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).
181
+ --profile <name> A profile in $CANON_HOME/agents.json (key and endpoints).
182
+ --environment <id> canon-prod-v1 or canon-dev-v1 (default: CANON_ENVIRONMENT_ID).
183
+ --help, -h Show this help.
184
+ --version, -V Show the package version.
185
+
186
+ Environment:
187
+ CANON_API_KEY The agent's key (or use --profile).
188
+ CANON_ENVIRONMENT_ID Required; a profile from another environment is refused.
189
+ CANON_HOME Agent state, default ~/.canon. It must be private (0700).
190
+ ANTHROPIC_API_KEY claude: use this API key instead of a Claude subscription
191
+ login. The claude driver needs @anthropic-ai/claude-agent-sdk.
192
+ OPENAI_API_KEY codex: use this API key instead of Codex's own login, unless
193
+ Codex is configured for another model provider.
194
+
195
+ SIGTERM or Ctrl-C stops taking messages, lets running turns finish for 10 seconds,
196
+ then stops them.`;
197
+ var DRIVERS = ["code", "claude", "codex", "hermes", "connector"];
198
+ var AVAILABLE = ["code", "claude", "codex", "connector"];
199
+ var PERMISSION_MODES = ["default", "acceptEdits", "bypassPermissions"];
200
+ var SANDBOXES = ["workspace-write", "read-only", "danger-full-access"];
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");
210
+ var UsageError = class extends Error {
211
+ static {
212
+ __name(this, "UsageError");
213
+ }
214
+ };
215
+ async function main() {
216
+ let parsed;
217
+ try {
218
+ parsed = parse();
219
+ } catch (error) {
220
+ throw new UsageError(error instanceof Error ? error.message : String(error));
221
+ }
222
+ const { values, positionals } = parsed;
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);
229
+ if (!values.driver) throw new UsageError("--driver is required.");
230
+ if (!AVAILABLE.includes(values.driver)) {
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(", ")}.`);
232
+ }
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);
242
+ const permissionMode = values["permission-mode"];
243
+ if (permissionMode !== void 0 && !PERMISSION_MODES.includes(permissionMode)) {
244
+ throw new UsageError(`--permission-mode must be one of ${PERMISSION_MODES.join(", ")}.`);
245
+ }
246
+ const { sandbox, "approval-policy": approvalPolicy } = values;
247
+ if (sandbox !== void 0 && !SANDBOXES.includes(sandbox)) {
248
+ throw new UsageError(`--sandbox must be one of ${SANDBOXES.join(", ")}.`);
249
+ }
250
+ if (approvalPolicy !== void 0 && !APPROVAL_POLICIES.includes(approvalPolicy)) {
251
+ throw new UsageError(`--approval-policy must be one of ${APPROVAL_POLICIES.join(", ")}.`);
252
+ }
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;
260
+ let driver;
261
+ if (values.driver === "claude") {
262
+ driver = claudeDriver({
263
+ cwd: resolve(values.cwd ?? "."),
264
+ query: await loadClaudeQuery(),
265
+ ...values.model ? { model: values.model } : {},
266
+ ...permissionMode ? { permissionMode } : {},
267
+ ...values["claude-path"] ? { claudePath: resolve(values["claude-path"]) } : {},
268
+ ...instructions ? { instructions } : {}
269
+ });
270
+ } else if (values.driver === "codex") {
271
+ const codexPath = values["codex-path"] ? resolve(values["codex-path"]) : "codex";
272
+ checkCodex(codexPath);
273
+ driver = codexDriver({
274
+ cwd: resolve(values.cwd ?? "."),
275
+ codexPath,
276
+ ...values.model ? { model: values.model } : {},
277
+ ...sandbox ? { sandbox } : {},
278
+ ...approvalPolicy ? { approvalPolicy } : {},
279
+ ...instructions ? { instructions } : {}
280
+ });
281
+ } else {
282
+ const modulePath = realpathSync(resolve(values.module));
283
+ const handler = (await import(pathToFileURL(modulePath).href)).default;
284
+ if (typeof handler !== "function") throw new Error(`${values.module} must export a turn handler as its default export.`);
285
+ driver = codeDriver(handler, { outboundFiles: { roots: [dirname(modulePath), realpathSync(tmpdir())] } });
286
+ }
287
+ const runner = await createRunner({
288
+ apiKey,
289
+ environmentId,
290
+ home,
291
+ driver,
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
+ })
303
+ });
304
+ stopOnSignals(() => runner.stop());
305
+ try {
306
+ await runner.start();
307
+ } catch (error) {
308
+ await runner.stop().catch(() => void 0);
309
+ throw error;
310
+ }
311
+ console.error(`canon-agent: running the ${values.driver} driver in ${environmentId}. Ctrl-C stops it.`);
312
+ }
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");
408
+ function parse() {
409
+ return parseArgs({
410
+ allowPositionals: true,
411
+ options: {
412
+ driver: { type: "string" },
413
+ module: { type: "string" },
414
+ profile: { type: "string" },
415
+ environment: { type: "string" },
416
+ cwd: { type: "string" },
417
+ model: { type: "string" },
418
+ "permission-mode": { type: "string" },
419
+ "claude-path": { type: "string" },
420
+ sandbox: { type: "string" },
421
+ "approval-policy": { 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" }
440
+ }
441
+ });
442
+ }
443
+ __name(parse, "parse");
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) {
554
+ let stopping = false;
555
+ const onSignal = /* @__PURE__ */ __name((signal) => {
556
+ if (stopping) process.exit(1);
557
+ stopping = true;
558
+ console.error(`canon-agent: ${signal}, stopping.`);
559
+ stop().then(() => process.exit(0), (error) => {
560
+ console.error(`canon-agent: ${error instanceof Error ? error.message : String(error)}`);
561
+ process.exit(1);
562
+ });
563
+ }, "onSignal");
564
+ process.on("SIGTERM", onSignal);
565
+ process.on("SIGINT", onSignal);
566
+ }
567
+ __name(stopOnSignals, "stopOnSignals");
568
+ runCli(import.meta.url, main, (error) => {
569
+ console.error(`canon-agent: ${error instanceof Error ? error.message : String(error)}`);
570
+ if (error instanceof UsageError) console.error(HELP.split("\n\nFlags:")[0]);
571
+ process.exit(1);
572
+ }, { name: "canon-agent", help: HELP });
@@ -0,0 +1,42 @@
1
+ import { type RuntimeDriver } from '../runner/types.js';
2
+ /** The Claude Agent SDK's `query()` as the driver uses it: one prompt, one native turn. */
3
+ export type ClaudeQuery = (params: {
4
+ prompt: string;
5
+ options: Record<string, unknown>;
6
+ }) => AsyncIterable<unknown> & {
7
+ interrupt(): Promise<void>;
8
+ close(): void;
9
+ };
10
+ export interface ClaudeDriverOptions {
11
+ /** The directory Claude Code works in. The agent may also send files from it. */
12
+ cwd: string;
13
+ /** A model id; Claude Code's default otherwise. */
14
+ model?: string;
15
+ /**
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 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.
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;
27
+ /** A Claude Code executable to run instead of the one bundled with the SDK. */
28
+ claudePath?: string;
29
+ /** How long an interrupted Claude Code may take to stop before its process is closed (default 5 s). */
30
+ interruptGraceMs?: number;
31
+ /** The SDK's `query()` (see `loadClaudeQuery`), loaded on the first turn when unset; tests pass a stand-in. */
32
+ query?: ClaudeQuery;
33
+ }
34
+ /** Loads the SDK's `query()`; it is an optional peer dependency, installed by whoever runs the `claude` driver. */
35
+ export declare function loadClaudeQuery(): Promise<ClaudeQuery>;
36
+ /**
37
+ * Runs each turn as one Claude Agent SDK `query()` that resumes the room's native session, whose id the runner keeps in
38
+ * the driver state. Canon's tools reach Claude only through the runner's per-turn MCP server; Stop interrupts the native
39
+ * turn and closes its process if it does not stop. One process per session at a time: a room's next turn starts only
40
+ * after the previous one has exited.
41
+ */
42
+ export declare function claudeDriver(options: ClaudeDriverOptions): RuntimeDriver;
@@ -0,0 +1,18 @@
1
+ import type { ActivityEvent, AskAnswer, AskRequest, DriverCapabilities, DriverResult, DriverState, RuntimeDriver, TurnInput, TurnTools } from '../runner/types.js';
2
+ /** The `DriverTurn` an in-process handler sees, with friendlier names. */
3
+ export interface CodeTurn {
4
+ readonly input: TurnInput;
5
+ readonly prompt: string;
6
+ readonly files: readonly string[];
7
+ readonly signal: AbortSignal;
8
+ /** The full visible answer so far; a preview, never the final. */
9
+ stream(text: string): void;
10
+ activity(event: ActivityEvent): void;
11
+ ask(request: AskRequest): Promise<AskAnswer>;
12
+ readonly state: DriverState;
13
+ readonly tools: TurnTools;
14
+ }
15
+ /** Return the turn's one final: text, `null` for deliberate silence, or text with files. */
16
+ export type CodeHandler = (turn: CodeTurn) => Promise<string | null | DriverResult> | string | null | DriverResult;
17
+ /** Runs a turn as an in-process function. The runner owns every Canon behaviour around it. */
18
+ export declare function codeDriver(handler: CodeHandler, capabilities?: Partial<DriverCapabilities>): RuntimeDriver;