@byok-sdk/client 0.10.2 → 0.12.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 (57) hide show
  1. package/README.md +86 -6
  2. package/dist/adapters/claude/claude-adapter.d.ts +3 -2
  3. package/dist/adapters/claude/permission-mapping.d.ts +48 -1
  4. package/dist/adapters/claude/resolve-approval-mcp-bin.d.ts +3 -2
  5. package/dist/adapters/codex/permission-mapping.d.ts +16 -0
  6. package/dist/adapters/index.js +292 -23
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/adapters/mcp-tool-grants.d.ts +36 -0
  9. package/dist/adapters/pi/resolve-extensions.d.ts +4 -1
  10. package/dist/adapters/pi/subagents-policy-config.d.ts +7 -0
  11. package/dist/adapters/pi/subagents-policy-extension.js +137 -0
  12. package/dist/adapters/pi/subagents-policy-extension.js.map +1 -0
  13. package/dist/agent-home.d.ts +33 -0
  14. package/dist/agent-memory/index.d.ts +1 -1
  15. package/dist/agent-memory/index.js +12 -9
  16. package/dist/agent-memory/index.js.map +1 -1
  17. package/dist/bin/agent-memory-mcp-server.d.ts +2 -2
  18. package/dist/bin/agent-message-mcp-server.d.ts +0 -1
  19. package/dist/bin/byok-agent-memory-mcp.js +340 -7
  20. package/dist/bin/byok-agent-memory-mcp.js.map +1 -1
  21. package/dist/bin/byok-agent-message-mcp.js +331 -7
  22. package/dist/bin/byok-agent-message-mcp.js.map +1 -1
  23. package/dist/bin/byok-agent-team-mcp.d.ts +2 -0
  24. package/dist/bin/byok-agent-team-mcp.js +765 -0
  25. package/dist/bin/byok-agent-team-mcp.js.map +1 -0
  26. package/dist/bin/byok-agent.js +16413 -14479
  27. package/dist/bin/byok-agent.js.map +1 -1
  28. package/dist/bin/byok-approval-mcp.js +312 -45
  29. package/dist/bin/byok-approval-mcp.js.map +1 -1
  30. package/dist/bin/commands/team.d.ts +15 -0
  31. package/dist/bin/sdk-reserved-helper-runners.d.ts +2 -0
  32. package/dist/bin/team-mcp-server.d.ts +27 -0
  33. package/dist/bin/team-tmux-view.d.ts +19 -0
  34. package/dist/daemon/agent-egress-controller.d.ts +4 -0
  35. package/dist/daemon/agent-message-mcp-preflight.d.ts +17 -0
  36. package/dist/daemon/auth-manager.d.ts +20 -0
  37. package/dist/daemon/blob-client.d.ts +24 -6
  38. package/dist/daemon/connection-manager.d.ts +7 -0
  39. package/dist/daemon/control-protocol.d.ts +38 -0
  40. package/dist/daemon/create-daemon.d.ts +9 -0
  41. package/dist/daemon/device-credential-store.d.ts +16 -0
  42. package/dist/daemon/long-poll-transport.d.ts +3 -0
  43. package/dist/daemon/mcp-tools-probe.d.ts +105 -0
  44. package/dist/daemon/replay-cursor.d.ts +9 -0
  45. package/dist/daemon/resolve-agent-memory-mcp-bin.d.ts +2 -1
  46. package/dist/daemon/resolve-agent-message-mcp-bin.d.ts +2 -1
  47. package/dist/daemon/task-runner.d.ts +22 -1
  48. package/dist/daemon/team-workspace.d.ts +202 -0
  49. package/dist/daemon/toolset-registry.d.ts +0 -2
  50. package/dist/daemon/url.d.ts +7 -1
  51. package/dist/index.d.ts +8 -3
  52. package/dist/index.js +3611 -1364
  53. package/dist/index.js.map +1 -1
  54. package/dist/sdk-reserved-helper-host.d.ts +25 -0
  55. package/dist/sdk-reserved-mcp.d.ts +23 -0
  56. package/dist/types.d.ts +36 -0
  57. package/package.json +10 -5
package/README.md CHANGED
@@ -14,6 +14,31 @@ Provider
14
14
  credentials are not read by the dispatch plane; `@byok-sdk/keys` is a separate
15
15
  install and keeps a zero dependency edge to this package.
16
16
 
17
+ Single-file Bun/SEA products must explicitly re-enter SDK-reserved helpers
18
+ before their own CLI parser. The SDK owns the reserved subcommand and helper
19
+ implementation; the product does not resolve `dist/bin` paths:
20
+
21
+ ```ts
22
+ import { createDaemon, runSdkReservedHelperCommand } from '@byok-sdk/client';
23
+
24
+ if (await runSdkReservedHelperCommand()) process.exit(0);
25
+
26
+ const daemon = createDaemon({
27
+ // ...normal device, Agent-home, and egress configuration
28
+ sdkHelperHost: { mode: 'self-executable' },
29
+ });
30
+ ```
31
+
32
+ Normal Node/Bun source hosts omit `sdkHelperHost` and continue to use the
33
+ package's installed helper scripts. A required-message offer performs an exact
34
+ stdio MCP initialize/tools-list handshake before adapter preparation; an
35
+ unwired or unstartable single-file helper is declined before runtime execution.
36
+ For Codex 0.149+, the adapter additionally proves the native per-MCP-tool
37
+ approval contract before claim, then approves only the SDK-reserved
38
+ `byokagentmessage/send_agent_message` tool. The global Codex
39
+ `approval_policy=never` remains pinned and every other MCP/tool retains the
40
+ normal non-interactive fail-closed posture.
41
+
17
42
  Pi is a required exact npm dependency and runs as an external Node subprocess.
18
43
  For an authoritative BYOK `dispatchSelection`, configure `piByokLauncher` with
19
44
  the separately installed `byok-pi-provider-launcher`, the local non-secret
@@ -64,9 +89,31 @@ createDaemon({
64
89
  ```
65
90
 
66
91
  The map accepts only `command` and `args`; put OAuth tokens, cookies, and other
67
- secrets behind the local MCP process's own credential broker. Toolset offers
68
- for Pi or Codex are declined because those adapters do not yet expose a strict
69
- task-scoped MCP configuration boundary.
92
+ secrets behind the local MCP process's own credential broker.
93
+
94
+ A projected toolset must also be *callable*, and neither runtime grants an MCP
95
+ tool implicitly: Claude auto-denies an ungranted `mcp__<server>__<tool>` call
96
+ under `--permission-mode default` and under `acceptEdits`, and Codex refuses
97
+ every MCP tool call under its pinned `approval_policy=never`. So before an
98
+ adapter is asked to admit a toolset offer, the daemon starts each projected
99
+ server and reads that server's own `tools/list` answer. Those observed names —
100
+ never a configured value, never a wildcard — are what each adapter grants:
101
+
102
+ - Claude: `--allowedTools mcp__<server>__<tool>,…` under `readonly` and
103
+ `auto`, alongside the unchanged `--tools` (so `readonly` with
104
+ `allowTools: []` still runs with every built-in disabled). `confirm` and
105
+ `plan` never pre-grant: `confirm`'s approval channel must see each call, and
106
+ `plan` promises not to execute one.
107
+ - Codex: `mcp_servers.<server>.enabled_tools` plus
108
+ `mcp_servers.<server>.tools.<tool>.approval_mode="approve"` for exactly
109
+ those tools. Global `approval_policy=never` and the mode's `sandbox_mode`
110
+ stay untouched, and Codex older than 0.149 is rejected before spawn.
111
+
112
+ A projected server that cannot start, or that lists no tools, is declined
113
+ pre-claim and retryably, rather than claimed and handed a toolset the model can
114
+ list but never call. A server that answers with a tool name that cannot be
115
+ expressed as a runtime grant is declined permanently (`retryable: false`), with
116
+ the server and the offending tool named in the decline.
70
117
 
71
118
  The daemon derives one sorted `configuredToolsets` snapshot from this
72
119
  validated registry. Only those logical IDs are advertised in `conn.hello`
@@ -128,9 +175,21 @@ strict Agent execution has one workspace authority and never falls back to a
128
175
  task-scoped Git workspace.
129
176
 
130
177
  Successful startup with this configuration advertises `agent-home-contract`. Agent offers are distinct
131
- from legacy task offers and fail closed when identity, profile revision,
132
- session/runtime/cwd evidence, or the one-writer lease does not match. Agent
133
- files other than the SDK-reserved `.byok` namespace are opaque; there is no
178
+ from legacy task offers and fail closed when identity, profile revision, or
179
+ session/runtime/cwd evidence does not match. Within one daemon process,
180
+ execution leases are scoped to `(agentId, sessionRef)`: different sessions of
181
+ one Agent may run concurrently in the same canonical home, while the same
182
+ session remains serialized. Fresh
183
+ tasks bind their task-scoped admission lease to the runtime-created session
184
+ before the SDK exposes that session. Shared `.byok` metadata mutations use a
185
+ short per-home gate. Agent-memory hosted projection serializes the complete
186
+ close-time outbox transaction per home because its durable outbox is one CAS
187
+ authority; the publish wait remains timeout-bounded and does not serialize the
188
+ sessions' runtime execution. The process-owned home activity marker remains
189
+ held until the final active session exits so relocation stays fail-closed. A
190
+ second daemon process remains excluded by that marker; cross-process session
191
+ multiplexing is not provided. Agent files
192
+ other than the SDK-reserved `.byok` namespace are opaque; there is no
134
193
  required `artifacts/` directory and the client does not parse or index their
135
194
  contents.
136
195
 
@@ -261,4 +320,25 @@ OS-backed refresh-token custody, a PKCE desktop Google OAuth flow, exact domain
261
320
  policy, a real read-only Gmail metadata adapter, and a closed metadata-only MCP
262
321
  result.
263
322
 
323
+ ## Local TeamWorkspace and tmux communication pane
324
+
325
+ `byok-agent team` provides one local-only broadcast channel for Pi, Claude,
326
+ and Codex harnesses. The daemon owns durable ordered messages, member receipts,
327
+ quotas, and short-lived member leases under `<storeDir>/team-workspaces/v1`.
328
+ `team join` prints the exact `byokagentteam` stdio MCP configuration for a
329
+ member; model tool inputs never contain workspace or sender identity.
330
+
331
+ ```bash
332
+ byok-agent team create dev --members pi,claude,codex --config /absolute/agent.json
333
+ byok-agent team join dev --member pi --config /absolute/agent.json
334
+ byok-agent team open dev --tmux-bin /opt/homebrew/bin/tmux --config /absolute/agent.json
335
+ ```
336
+
337
+ The tmux view has one explicit native dependency: tmux must be installed and
338
+ its absolute executable path supplied with `--tmux-bin`. It is intentionally
339
+ not an npm dependency and is not required to run the daemon, MCP channel, or
340
+ plain watcher. Native Windows returns `unsupported_platform` for the tmux view.
341
+ The launcher never uses `send-keys` or `capture-pane`; tmux displays the
342
+ daemon-owned stream but is never message transport or protocol authority.
343
+
264
344
  MIT licensed. Node.js 22.22.0 or newer.
@@ -2,8 +2,9 @@ import { type RuntimeAdapter, type RuntimeDetectResult, type RuntimeAdapterPrepa
2
2
  import { type ResolvedBin } from './resolve-bin';
3
3
  import { type ResolvedApprovalMcpBin } from './resolve-approval-mcp-bin';
4
4
  import { type SpawnFn } from './process-client';
5
- /** The MCP server NAME this adapter registers `byok-approval-mcp` under in the generated `--mcp-config` (arbitrary, local to this file) — combined with {@link APPROVAL_TOOL_NAME} (imported, single-sourced from `bin/approval-mcp-server.ts` so the two can never independently drift) to form the `mcp__<server>__<tool>` identifier `--permission-prompt-tool` expects. */
6
- export declare const APPROVAL_MCP_SERVER_NAME = "byokapproval";
5
+ import { APPROVAL_MCP_SERVER_NAME } from '../../sdk-reserved-mcp';
6
+ /** The MCP server NAME this adapter registers `byok-approval-mcp` under in the generated `--mcp-config` — combined with {@link APPROVAL_TOOL_NAME} (single-sourced from `bin/approval-mcp-server.ts` so the two can never independently drift) to form the `mcp__<server>__<tool>` identifier `--permission-prompt-tool` expects. Defined in `sdk-reserved-mcp.ts` beside the other SDK-owned server names, and re-exported from here, its original home, so the host-config rejection and the toolset-grant rule read one list. */
7
+ export { APPROVAL_MCP_SERVER_NAME };
7
8
  export interface ClaudeAdapterOptions {
8
9
  /** Override bin resolution — tests substitute the fake-claude fixture script. */
9
10
  resolveBin?: () => ResolvedBin;
@@ -1,4 +1,5 @@
1
1
  import type { PermissionPolicy } from '@byok-sdk/protocol';
2
+ import type { McpToolsetGrant } from '../mcp-tool-grants';
2
3
  export interface ClaudePermissionMapping {
3
4
  ok: boolean;
4
5
  /** CLI args to append to `claude -p ...`. Only meaningful when `ok` is true. */
@@ -131,6 +132,52 @@ export interface ClaudePermissionMapping {
131
132
  * "default set minus these" this mapper can construct. Refusing is the
132
133
  * fail-closed choice over guessing a set that might not match reality.
133
134
  *
135
+ * ## Projected MCP toolset tools: `--allowedTools`, and ONLY for them
136
+ *
137
+ * The two flags above govern claude's BUILT-IN tools. A projected host
138
+ * toolset arrives by a third path entirely — `--mcp-config` (see
139
+ * `claude-adapter.ts`) — and empirically it is granted by neither: on the
140
+ * installed 2.1.251 binary, a `mcp__<server>__<tool>` call is auto-denied
141
+ * (`system:permission_denied`, `permission_denials` populated) under
142
+ * `--permission-mode default` AND under `--permission-mode acceptEdits`,
143
+ * whether or not `--tools` is present. `acceptEdits`' documented breadth
144
+ * (which really does cover Write and Bash — see `auto` above) stops at
145
+ * claude's own built-ins; MCP tools are never implicitly permitted.
146
+ *
147
+ * So a projected toolset is only actually callable if its tools appear in
148
+ * `--allowedTools`. Live-verified against 2.1.251 against a one-tool stdio
149
+ * echo server: with `--permission-mode default --tools "" --mcp-config …
150
+ * --strict-mcp-config`, `tools/list` reached the server and `tools/call`
151
+ * never did; appending `--allowedTools mcp__saleskoprobe__echo` (nothing
152
+ * else changed) produced `permission_denials: []`, a real `tools/call` on
153
+ * the server, and the tool's own result — while `system/init` still
154
+ * reported `tools: ["mcp__saleskoprobe__echo"]`, i.e. `--tools ""` kept
155
+ * every built-in disabled. This is the one use of `--allowedTools` this
156
+ * mapper makes, and it is a PERMISSION pre-grant (what the flag genuinely
157
+ * is), never a capability restriction (what the findings above prove it is
158
+ * not): the capability surface is still fixed by `--tools` alone.
159
+ *
160
+ * Which modes receive the grant, and why the others deliberately do not:
161
+ *
162
+ * - `readonly` and `auto`: granted. Both auto-deny MCP calls without it
163
+ * (live-confirmed above for each), so withholding it would offer a task
164
+ * a toolset it can list and never call. Nothing is widened: the granted
165
+ * identifiers are exactly the tools the daemon OBSERVED on exactly the
166
+ * servers this task projected (`daemon/mcp-tools-probe.ts`), an unobserved
167
+ * name is never granted, and no server-scoped `mcp__<server>` wildcard is
168
+ * ever emitted (that form was never verified, and it would silently grant
169
+ * tools a server adds later).
170
+ * - `confirm`: NOT granted, deliberately. Confirm's whole point is that a
171
+ * human answers each call through `--permission-prompt-tool`; a pre-grant
172
+ * would resolve those calls before the channel ever sees them, silently
173
+ * removing the decision the caller asked for.
174
+ * - `plan`: NOT granted, deliberately. Plan mode's contract is that the
175
+ * mutating call never actually runs. This SDK cannot know whether an
176
+ * opaque host toolset tool mutates anything, so pre-granting one would
177
+ * turn plan into an executing mode for exactly the tools it knows least
178
+ * about. A plan-mode task that needs its toolset callable belongs in
179
+ * `readonly`.
180
+ *
134
181
  * `network: false` fails closed for the same reason as pi: no verified
135
182
  * network sandbox exists for claude's Bash tool either (`claude --help`
136
183
  * exposes no network/sandbox flag at all) — this was not independently
@@ -139,4 +186,4 @@ export interface ClaudePermissionMapping {
139
186
  * task didn't run), but is the same conservative, precedent-consistent
140
187
  * default pi already applies for an unverifiable constraint.
141
188
  */
142
- export declare function mapPermissionPolicyToClaudeArgs(policy: PermissionPolicy): ClaudePermissionMapping;
189
+ export declare function mapPermissionPolicyToClaudeArgs(policy: PermissionPolicy, toolsetGrants?: readonly McpToolsetGrant[]): ClaudePermissionMapping;
@@ -1,7 +1,8 @@
1
+ import { type SdkHelperHostConfig } from '../../sdk-reserved-helper-host';
1
2
  export interface ResolvedApprovalMcpBin {
2
3
  command: string;
3
4
  args: string[];
4
- source: 'env' | 'dist';
5
+ source: 'env' | 'dist' | 'host';
5
6
  }
6
7
  /**
7
8
  * Resolve `byok-approval-mcp` — the small stdio MCP server
@@ -42,4 +43,4 @@ export interface ResolvedApprovalMcpBin {
42
43
  * (see `claude-adapter.test.ts`), exactly like `BYOK_CLAUDE_BIN` already
43
44
  * does for the real `claude` binary.
44
45
  */
45
- export declare function resolveApprovalMcpBin(): ResolvedApprovalMcpBin;
46
+ export declare function resolveApprovalMcpBin(host?: SdkHelperHostConfig): ResolvedApprovalMcpBin;
@@ -103,5 +103,21 @@ export interface CodexPermissionMapping {
103
103
  * `~/.codex/config.toml` default is more permissive than anything this
104
104
  * adapter should ever grant implicitly. Every invocation pins both keys
105
105
  * explicitly so behavior never depends on the end user's own codex config.
106
+ * Codex 0.149's per-MCP-tool approval setting is a separate, narrower
107
+ * control: `codex-adapter.ts` uses it for the SDK-reserved
108
+ * `byokagentmessage/send_agent_message` terminal protocol tool, and for the
109
+ * tools of the MCP servers a task's own `requiredToolsets` projected — each
110
+ * with an exact `enabled_tools` allowlist naming those tools and nothing
111
+ * else. Global approval stays `never` and `sandbox_mode` is untouched, so
112
+ * shell/file authority remains exactly what the mode above selected.
113
+ * Without that grant a projected toolset is dead weight: `approval_policy=
114
+ * never` refuses every MCP tool call outright ("MCP tool call requires
115
+ * approval, but approval policy is never"), under `workspace-write` and
116
+ * `read-only` alike, so the model can list a toolset's tools and never call
117
+ * one. The granted names are only ever the ones the daemon OBSERVED via
118
+ * `tools/list` on that exact server (`daemon/mcp-tools-probe.ts`) — never a
119
+ * configured value, never a wildcard, and never
120
+ * `default_tools_approval_mode`, which codex reads back happily but which
121
+ * was empirically ineffective under `approval_policy=never` on 0.149.0.
106
122
  */
107
123
  export declare function mapPermissionPolicyToCodexArgs(policy: PermissionPolicy): CodexPermissionMapping;