@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.
- package/README.md +86 -6
- package/dist/adapters/claude/claude-adapter.d.ts +3 -2
- package/dist/adapters/claude/permission-mapping.d.ts +48 -1
- package/dist/adapters/claude/resolve-approval-mcp-bin.d.ts +3 -2
- package/dist/adapters/codex/permission-mapping.d.ts +16 -0
- package/dist/adapters/index.js +292 -23
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/mcp-tool-grants.d.ts +36 -0
- package/dist/adapters/pi/resolve-extensions.d.ts +4 -1
- package/dist/adapters/pi/subagents-policy-config.d.ts +7 -0
- package/dist/adapters/pi/subagents-policy-extension.js +137 -0
- package/dist/adapters/pi/subagents-policy-extension.js.map +1 -0
- package/dist/agent-home.d.ts +33 -0
- package/dist/agent-memory/index.d.ts +1 -1
- package/dist/agent-memory/index.js +12 -9
- package/dist/agent-memory/index.js.map +1 -1
- package/dist/bin/agent-memory-mcp-server.d.ts +2 -2
- package/dist/bin/agent-message-mcp-server.d.ts +0 -1
- package/dist/bin/byok-agent-memory-mcp.js +340 -7
- package/dist/bin/byok-agent-memory-mcp.js.map +1 -1
- package/dist/bin/byok-agent-message-mcp.js +331 -7
- package/dist/bin/byok-agent-message-mcp.js.map +1 -1
- package/dist/bin/byok-agent-team-mcp.d.ts +2 -0
- package/dist/bin/byok-agent-team-mcp.js +765 -0
- package/dist/bin/byok-agent-team-mcp.js.map +1 -0
- package/dist/bin/byok-agent.js +16413 -14479
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/bin/byok-approval-mcp.js +312 -45
- package/dist/bin/byok-approval-mcp.js.map +1 -1
- package/dist/bin/commands/team.d.ts +15 -0
- package/dist/bin/sdk-reserved-helper-runners.d.ts +2 -0
- package/dist/bin/team-mcp-server.d.ts +27 -0
- package/dist/bin/team-tmux-view.d.ts +19 -0
- package/dist/daemon/agent-egress-controller.d.ts +4 -0
- package/dist/daemon/agent-message-mcp-preflight.d.ts +17 -0
- package/dist/daemon/auth-manager.d.ts +20 -0
- package/dist/daemon/blob-client.d.ts +24 -6
- package/dist/daemon/connection-manager.d.ts +7 -0
- package/dist/daemon/control-protocol.d.ts +38 -0
- package/dist/daemon/create-daemon.d.ts +9 -0
- package/dist/daemon/device-credential-store.d.ts +16 -0
- package/dist/daemon/long-poll-transport.d.ts +3 -0
- package/dist/daemon/mcp-tools-probe.d.ts +105 -0
- package/dist/daemon/replay-cursor.d.ts +9 -0
- package/dist/daemon/resolve-agent-memory-mcp-bin.d.ts +2 -1
- package/dist/daemon/resolve-agent-message-mcp-bin.d.ts +2 -1
- package/dist/daemon/task-runner.d.ts +22 -1
- package/dist/daemon/team-workspace.d.ts +202 -0
- package/dist/daemon/toolset-registry.d.ts +0 -2
- package/dist/daemon/url.d.ts +7 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +3611 -1364
- package/dist/index.js.map +1 -1
- package/dist/sdk-reserved-helper-host.d.ts +25 -0
- package/dist/sdk-reserved-mcp.d.ts +23 -0
- package/dist/types.d.ts +36 -0
- package/package.json +10 -5
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { McpStdioServerConfig, McpToolsetToolObservation } from '../types';
|
|
2
|
+
/** One projected toolset server and the exact tool names observed on it. */
|
|
3
|
+
export interface McpToolsetGrant {
|
|
4
|
+
readonly server: string;
|
|
5
|
+
readonly tools: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/** Static grant candidates for exactly the SDK-owned pre-grantable servers present in one task. */
|
|
8
|
+
export declare function resolveReservedMcpToolGrants(servers: Readonly<Record<string, McpStdioServerConfig>> | undefined): readonly McpToolsetGrant[];
|
|
9
|
+
export type McpToolsetGrantResolution = {
|
|
10
|
+
ok: true;
|
|
11
|
+
grants: readonly McpToolsetGrant[];
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
reason: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Pair every projected (non-reserved) MCP server with the tool names the
|
|
18
|
+
* daemon actually observed on it, or fail closed.
|
|
19
|
+
*
|
|
20
|
+
* Both runtimes this SDK drives non-interactively refuse an MCP tool call
|
|
21
|
+
* that was not pre-granted — claude auto-denies it under `--permission-mode
|
|
22
|
+
* default` and under `acceptEdits`, codex rejects it under
|
|
23
|
+
* `approval_policy=never` — so a projected toolset is only genuinely usable
|
|
24
|
+
* if the adapter can name its tools in the runtime's own grant surface. That
|
|
25
|
+
* makes an unobserved server an inexpressible policy, not a smaller one: the
|
|
26
|
+
* task would claim, spawn a model, and then be told it may not call the very
|
|
27
|
+
* tools it was offered for. Rejecting before spawn is the same fail-closed
|
|
28
|
+
* posture the permission mappers already take for an inexpressible
|
|
29
|
+
* `denyTools` or `network` constraint.
|
|
30
|
+
*
|
|
31
|
+
* Reserved SDK servers are deliberately absent from the result: each carries
|
|
32
|
+
* a fixed grant its own protocol defines, never an observed one.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveMcpToolsetGrants(servers: Readonly<Record<string, McpStdioServerConfig>> | undefined, observation: McpToolsetToolObservation | undefined): McpToolsetGrantResolution;
|
|
35
|
+
/** Order-independent identity of one grant set, for adapters that must prove start() received the authority prepare() was admitted with. */
|
|
36
|
+
export declare function grantFingerprint(grants: readonly McpToolsetGrant[]): string;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export interface ResolvedPiExtensions {
|
|
2
2
|
readonly webAccess: string;
|
|
3
3
|
readonly mcpAdapter: string;
|
|
4
|
+
readonly subagentsPolicy: string;
|
|
5
|
+
readonly subagents: string;
|
|
6
|
+
readonly todo: string;
|
|
4
7
|
}
|
|
5
8
|
/**
|
|
6
|
-
* Resolve the
|
|
9
|
+
* Resolve the Pi extensions shipped as required `@byok-sdk/client`
|
|
7
10
|
* dependencies. Pi receives explicit extension paths so runtime behavior is
|
|
8
11
|
* pinned to this package graph rather than a user's mutable global Pi package
|
|
9
12
|
* settings.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const BYOK_PI_PERMISSION_MODE = "BYOK_PI_PERMISSION_MODE";
|
|
2
|
+
/** SDK-owned extension tools that do not mutate the task workspace. */
|
|
3
|
+
export declare const BYOK_PI_READONLY_PARENT_TOOLS: readonly ['subagent', 'todo'];
|
|
4
|
+
/** Child tools retained when a readonly parent delegates through pi-subagents. */
|
|
5
|
+
export declare const BYOK_PI_READONLY_SUBAGENT_TOOLS: readonly ['read', 'grep', 'find', 'ls'];
|
|
6
|
+
/** Package-provided read-only roles; writer and ambient custom roles stay unavailable. */
|
|
7
|
+
export declare const BYOK_PI_READONLY_SUBAGENT_AGENTS: readonly ['reviewer', 'oracle', 'codex-exec', 'claude-code', 'cursor-agent'];
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
|
|
3
|
+
// ../../node_modules/.bun/pi-subagents@0.60.0+ba57dcb6e433cb73/node_modules/pi-subagents/src/runs/shared/capability-ceiling.ts
|
|
4
|
+
var SUBAGENT_CAPABILITY_CEILING_VERSION = 1;
|
|
5
|
+
var SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY = "pi-subagents.capability-ceiling.v1";
|
|
6
|
+
function registry() {
|
|
7
|
+
const key = Symbol.for(SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY);
|
|
8
|
+
const store = globalThis;
|
|
9
|
+
const existing = store[key];
|
|
10
|
+
if (existing instanceof Map) return existing;
|
|
11
|
+
const created = /* @__PURE__ */ new Map();
|
|
12
|
+
store[key] = created;
|
|
13
|
+
return created;
|
|
14
|
+
}
|
|
15
|
+
function validateText(value, field) {
|
|
16
|
+
if (typeof value !== "string" || !value.trim() || /[\u0000-\u001f\u007f]/u.test(value) || Buffer.byteLength(value.trim(), "utf8") > 256) {
|
|
17
|
+
throw new Error(`Invalid capability ceiling ${field}; expected a non-empty string without control characters (max 256 UTF-8 bytes).`);
|
|
18
|
+
}
|
|
19
|
+
return value.trim();
|
|
20
|
+
}
|
|
21
|
+
function normalizeCeiling(ceiling) {
|
|
22
|
+
if (!ceiling || typeof ceiling !== "object" || Array.isArray(ceiling)) throw new Error("Invalid capability ceiling; expected an object.");
|
|
23
|
+
const hasAllowedTools = Object.hasOwn(ceiling, "allowedTools");
|
|
24
|
+
const hasAllowedAgents = Object.hasOwn(ceiling, "allowedAgents");
|
|
25
|
+
const hasDenyExtensions = Object.hasOwn(ceiling, "denyExtensions");
|
|
26
|
+
if (!hasAllowedTools && !hasAllowedAgents && !hasDenyExtensions) throw new Error("Invalid capability ceiling; expected allowedTools, allowedAgents, or denyExtensions.");
|
|
27
|
+
if (hasDenyExtensions && typeof ceiling.denyExtensions !== "boolean") throw new Error("Invalid capability ceiling denyExtensions; expected a boolean.");
|
|
28
|
+
const normalizeList = (field, pattern) => {
|
|
29
|
+
if (!Object.hasOwn(ceiling, field)) return void 0;
|
|
30
|
+
const values = ceiling[field];
|
|
31
|
+
if (!Array.isArray(values)) throw new Error(`Invalid capability ceiling ${field}; expected an array.`);
|
|
32
|
+
if (values.length > 256) throw new Error(`Invalid capability ceiling ${field}; expected at most 256 names.`);
|
|
33
|
+
return [...new Set(values.map((entry) => {
|
|
34
|
+
const name = validateText(entry, `${field} entry`);
|
|
35
|
+
if (!pattern.test(name)) throw new Error(`Invalid capability ceiling ${field} entry '${name}'.`);
|
|
36
|
+
if (Buffer.byteLength(name, "utf8") > 128) throw new Error(`Invalid capability ceiling ${field} entry '${name}'; max 128 UTF-8 bytes.`);
|
|
37
|
+
return name;
|
|
38
|
+
}))].sort();
|
|
39
|
+
};
|
|
40
|
+
const allowedTools = normalizeList("allowedTools", /^[A-Za-z0-9_.:-]+$/u);
|
|
41
|
+
const allowedAgents = normalizeList("allowedAgents", /^[A-Za-z0-9_.:-]+$/u);
|
|
42
|
+
return {
|
|
43
|
+
version: SUBAGENT_CAPABILITY_CEILING_VERSION,
|
|
44
|
+
...allowedTools !== void 0 ? { allowedTools } : {},
|
|
45
|
+
...allowedAgents !== void 0 ? { allowedAgents } : {},
|
|
46
|
+
denyExtensions: ceiling.denyExtensions === true,
|
|
47
|
+
sources: []
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function registerSubagentCapabilityCeiling(options) {
|
|
51
|
+
const sessionId = validateText(options.sessionId, "sessionId");
|
|
52
|
+
const source = validateText(options.source, "source");
|
|
53
|
+
let normalized = normalizeCeiling(options.ceiling);
|
|
54
|
+
const token = Symbol(source);
|
|
55
|
+
const store = registry();
|
|
56
|
+
let session = store.get(sessionId);
|
|
57
|
+
if (!session) {
|
|
58
|
+
session = /* @__PURE__ */ new Map();
|
|
59
|
+
store.set(sessionId, session);
|
|
60
|
+
}
|
|
61
|
+
const setRegistration = () => {
|
|
62
|
+
normalized = normalizeCeiling(normalized);
|
|
63
|
+
normalized.sources = [source];
|
|
64
|
+
session.set(token, { source, ceiling: normalized });
|
|
65
|
+
};
|
|
66
|
+
setRegistration();
|
|
67
|
+
let disposed = false;
|
|
68
|
+
return {
|
|
69
|
+
update(ceiling) {
|
|
70
|
+
if (disposed) throw new Error("Cannot update a disposed capability ceiling handle.");
|
|
71
|
+
normalized = normalizeCeiling(ceiling);
|
|
72
|
+
normalized.sources = [source];
|
|
73
|
+
session.set(token, { source, ceiling: normalized });
|
|
74
|
+
},
|
|
75
|
+
dispose() {
|
|
76
|
+
if (disposed) return;
|
|
77
|
+
disposed = true;
|
|
78
|
+
session.delete(token);
|
|
79
|
+
if (session.size === 0) store.delete(sessionId);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/adapters/pi/subagents-policy-config.ts
|
|
85
|
+
var BYOK_PI_PERMISSION_MODE = "BYOK_PI_PERMISSION_MODE";
|
|
86
|
+
var BYOK_PI_READONLY_SUBAGENT_TOOLS = ["read", "grep", "find", "ls"];
|
|
87
|
+
var BYOK_PI_READONLY_SUBAGENT_AGENTS = [
|
|
88
|
+
"reviewer",
|
|
89
|
+
"oracle",
|
|
90
|
+
"codex-exec",
|
|
91
|
+
"claude-code",
|
|
92
|
+
"cursor-agent"
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
// src/adapters/pi/subagents-policy-extension.ts
|
|
96
|
+
function permissionMode() {
|
|
97
|
+
const mode = process.env[BYOK_PI_PERMISSION_MODE];
|
|
98
|
+
if (mode === "auto" || mode === "readonly") return mode;
|
|
99
|
+
throw new Error(`${BYOK_PI_PERMISSION_MODE} must be "auto" or "readonly"`);
|
|
100
|
+
}
|
|
101
|
+
function registerByokSubagentsPolicy(pi) {
|
|
102
|
+
const mode = permissionMode();
|
|
103
|
+
let ceiling;
|
|
104
|
+
pi.on("session_start", (_event, ctx) => {
|
|
105
|
+
ceiling?.dispose();
|
|
106
|
+
ceiling = void 0;
|
|
107
|
+
if (mode === "auto") return;
|
|
108
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
109
|
+
if (!sessionId) throw new Error("readonly Pi subagent policy requires an authoritative session id");
|
|
110
|
+
ceiling = registerSubagentCapabilityCeiling({
|
|
111
|
+
sessionId,
|
|
112
|
+
source: "byok-sdk-readonly",
|
|
113
|
+
ceiling: {
|
|
114
|
+
allowedTools: BYOK_PI_READONLY_SUBAGENT_TOOLS,
|
|
115
|
+
allowedAgents: BYOK_PI_READONLY_SUBAGENT_AGENTS,
|
|
116
|
+
denyExtensions: true
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
pi.on("tool_call", (event) => {
|
|
121
|
+
if (mode === "readonly" && event.toolName === "subagent" && ceiling === void 0) {
|
|
122
|
+
return {
|
|
123
|
+
block: true,
|
|
124
|
+
terminate: true,
|
|
125
|
+
reason: "readonly Pi subagent capability ceiling is unavailable"
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
pi.on("session_shutdown", () => {
|
|
130
|
+
ceiling?.dispose();
|
|
131
|
+
ceiling = void 0;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export { registerByokSubagentsPolicy as default };
|
|
136
|
+
//# sourceMappingURL=subagents-policy-extension.js.map
|
|
137
|
+
//# sourceMappingURL=subagents-policy-extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../node_modules/.bun/pi-subagents@0.60.0+ba57dcb6e433cb73/node_modules/pi-subagents/src/runs/shared/capability-ceiling.ts","../../../src/adapters/pi/subagents-policy-config.ts","../../../src/adapters/pi/subagents-policy-extension.ts"],"names":[],"mappings":";;;AAEO,IAAM,mCAAA,GAAsC,CAAA;AAC5C,IAAM,wCAAA,GAA2C,oCAAA;AA4CxD,SAAS,QAAA,GAAqB;AAC7B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,CAAI,wCAAwC,CAAA;AAC/D,EAAA,MAAM,KAAA,GAAQ,UAAA;AACd,EAAA,MAAM,QAAA,GAAW,MAAM,GAAG,CAAA;AAC1B,EAAA,IAAI,QAAA,YAAoB,KAAK,OAAO,QAAA;AACpC,EAAA,MAAM,OAAA,uBAAwB,GAAA,EAAI;AAClC,EAAA,KAAA,CAAM,GAAG,CAAA,GAAI,OAAA;AACb,EAAA,OAAO,OAAA;AACR;AAEA,SAAS,YAAA,CAAa,OAAgB,KAAA,EAAuB;AAC5D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,IAAA,MAAU,wBAAA,CAAyB,IAAA,CAAK,KAAK,CAAA,IAAK,OAAO,UAAA,CAAW,KAAA,CAAM,MAAK,EAAG,MAAM,IAAI,GAAA,EAAK;AACxI,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,KAAK,CAAA,+EAAA,CAAiF,CAAA;AAAA,EACrI;AACA,EAAA,OAAO,MAAM,IAAA,EAAK;AACnB;AAEA,SAAS,iBAAiB,OAAA,EAAuE;AAChG,EAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,iDAAiD,CAAA;AACxI,EAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,cAAc,CAAA;AAC7D,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,eAAe,CAAA;AAC/D,EAAA,MAAM,iBAAA,GAAoB,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,gBAAgB,CAAA;AACjE,EAAA,IAAI,CAAC,mBAAmB,CAAC,gBAAA,IAAoB,CAAC,iBAAA,EAAmB,MAAM,IAAI,KAAA,CAAM,sFAAsF,CAAA;AACvK,EAAA,IAAI,iBAAA,IAAqB,OAAO,OAAA,CAAQ,cAAA,KAAmB,WAAW,MAAM,IAAI,MAAM,gEAAgE,CAAA;AACtJ,EAAA,MAAM,aAAA,GAAgB,CAAC,KAAA,EAAyC,OAAA,KAA0C;AACzG,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,KAAK,GAAG,OAAO,MAAA;AAC3C,IAAA,MAAM,MAAA,GAAS,QAAQ,KAAK,CAAA;AAC5B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,QAAS,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,KAAK,CAAA,oBAAA,CAAsB,CAAA;AACrG,IAAA,IAAI,MAAA,CAAO,SAAS,GAAA,EAAK,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,KAAK,CAAA,6BAAA,CAA+B,CAAA;AAC3G,IAAA,OAAO,CAAC,GAAG,IAAI,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACxC,MAAA,MAAM,IAAA,GAAO,YAAA,CAAa,KAAA,EAAO,CAAA,EAAG,KAAK,CAAA,MAAA,CAAQ,CAAA;AACjD,MAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,KAAK,CAAA,QAAA,EAAW,IAAI,CAAA,EAAA,CAAI,CAAA;AAC/F,MAAA,IAAI,MAAA,CAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA,GAAI,GAAA,EAAK,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,KAAK,CAAA,QAAA,EAAW,IAAI,CAAA,uBAAA,CAAyB,CAAA;AACtI,MAAA,OAAO,IAAA;AAAA,IACR,CAAC,CAAC,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,EACX,CAAA;AACA,EAAA,MAAM,YAAA,GAAe,aAAA,CAAc,cAAA,EAAgB,qBAAqB,CAAA;AACxE,EAAA,MAAM,aAAA,GAAgB,aAAA,CAAc,eAAA,EAAiB,qBAAqB,CAAA;AAC1E,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,mCAAA;AAAA,IACT,GAAI,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,KAAiB,EAAC;AAAA,IACrD,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,KAAkB,EAAC;AAAA,IACvD,cAAA,EAAgB,QAAQ,cAAA,KAAmB,IAAA;AAAA,IAC3C,SAAS;AAAC,GACX;AACD;AAaO,SAAS,kCAAkC,OAAA,EAAoF;AACrI,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,OAAA,CAAQ,SAAA,EAAW,WAAW,CAAA;AAC7D,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AACpD,EAAA,IAAI,UAAA,GAAa,gBAAA,CAAiB,OAAA,CAAQ,OAAO,CAAA;AACjD,EAAA,MAAM,KAAA,GAAQ,OAAO,MAAM,CAAA;AAC3B,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,IAAI,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,SAAS,CAAA;AACjC,EAAA,IAAI,CAAC,OAAA,EAAS;AACb,IAAA,OAAA,uBAAc,GAAA,EAAI;AAClB,IAAA,KAAA,CAAM,GAAA,CAAI,WAAW,OAAO,CAAA;AAAA,EAC7B;AACA,EAAA,MAAM,kBAAkB,MAAM;AAC7B,IAAA,UAAA,GAAa,iBAAiB,UAAU,CAAA;AACxC,IAAA,UAAA,CAAW,OAAA,GAAU,CAAC,MAAM,CAAA;AAC5B,IAAA,OAAA,CAAS,IAAI,KAAA,EAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,YAAY,CAAA;AAAA,EACpD,CAAA;AACA,EAAA,eAAA,EAAgB;AAChB,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,OAAO;AAAA,IACN,OAAO,OAAA,EAAS;AACf,MAAA,IAAI,QAAA,EAAU,MAAM,IAAI,KAAA,CAAM,qDAAqD,CAAA;AACnF,MAAA,UAAA,GAAa,iBAAiB,OAAO,CAAA;AACrC,MAAA,UAAA,CAAW,OAAA,GAAU,CAAC,MAAM,CAAA;AAC5B,MAAA,OAAA,CAAS,IAAI,KAAA,EAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,YAAY,CAAA;AAAA,IACpD,CAAA;AAAA,IACA,OAAA,GAAU;AACT,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,OAAA,CAAS,OAAO,KAAK,CAAA;AACrB,MAAA,IAAI,OAAA,CAAS,IAAA,KAAS,CAAA,EAAG,KAAA,CAAM,OAAO,SAAS,CAAA;AAAA,IAChD;AAAA,GACD;AACD;;;ACzIO,IAAM,uBAAA,GAA0B,yBAAA;AAMhC,IAAM,+BAAA,GAAkC,CAAC,MAAA,EAAQ,MAAA,EAAQ,QAAQ,IAAI,CAAA;AAGrE,IAAM,gCAAA,GAAmC;AAAA,EAC9C,UAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA;;;ACJA,SAAS,cAAA,GAAsC;AAC7C,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,uBAAuB,CAAA;AAChD,EAAA,IAAI,IAAA,KAAS,MAAA,IAAU,IAAA,KAAS,UAAA,EAAY,OAAO,IAAA;AACnD,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,uBAAuB,CAAA,6BAAA,CAA+B,CAAA;AAC3E;AAMe,SAAR,4BAA6C,EAAA,EAAwB;AAC1E,EAAA,MAAM,OAAO,cAAA,EAAe;AAC5B,EAAA,IAAI,OAAA;AAEJ,EAAA,EAAA,CAAG,EAAA,CAAG,eAAA,EAAiB,CAAC,MAAA,EAAQ,GAAA,KAAQ;AACtC,IAAA,OAAA,EAAS,OAAA,EAAQ;AACjB,IAAA,OAAA,GAAU,MAAA;AACV,IAAA,IAAI,SAAS,MAAA,EAAQ;AAErB,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,cAAA,CAAe,YAAA,EAAa;AAClD,IAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,MAAM,kEAAkE,CAAA;AAClG,IAAA,OAAA,GAAU,iCAAA,CAAkC;AAAA,MAC1C,SAAA;AAAA,MACA,MAAA,EAAQ,mBAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,YAAA,EAAc,+BAAA;AAAA,QACd,aAAA,EAAe,gCAAA;AAAA,QACf,cAAA,EAAgB;AAAA;AAClB,KACD,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,EAAA,CAAG,EAAA,CAAG,WAAA,EAAa,CAAC,KAAA,KAAU;AAC5B,IAAA,IAAI,SAAS,UAAA,IAAc,KAAA,CAAM,QAAA,KAAa,UAAA,IAAc,YAAY,MAAA,EAAW;AACjF,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,IAAA;AAAA,QACP,SAAA,EAAW,IAAA;AAAA,QACX,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,EAAA,CAAG,EAAA,CAAG,oBAAoB,MAAM;AAC9B,IAAA,OAAA,EAAS,OAAA,EAAQ;AACjB,IAAA,OAAA,GAAU,MAAA;AAAA,EACZ,CAAC,CAAA;AACH","file":"subagents-policy-extension.js","sourcesContent":["import { Buffer } from \"node:buffer\";\n\nexport const SUBAGENT_CAPABILITY_CEILING_VERSION = 1 as const;\nexport const SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY = \"pi-subagents.capability-ceiling.v1\";\nexport const SUBAGENT_CAPABILITY_CEILING_ENV = \"PI_SUBAGENT_CAPABILITY_CEILING_V1\";\n\nexport type SubagentCapabilityCeiling =\n\t| { allowedTools: readonly string[]; allowedAgents?: readonly string[]; denyExtensions?: boolean }\n\t| { allowedTools?: readonly string[]; allowedAgents?: readonly string[]; denyExtensions: boolean }\n\t| { allowedTools?: readonly string[]; allowedAgents: readonly string[]; denyExtensions?: boolean };\n\nexport interface ResolvedSubagentCapabilityCeiling {\n\tversion: typeof SUBAGENT_CAPABILITY_CEILING_VERSION;\n\tallowedTools?: string[];\n\tallowedAgents?: string[];\n\tdenyExtensions: boolean;\n\tsources: string[];\n}\n\nexport interface SubagentCapabilityAudit {\n\tceiling: ResolvedSubagentCapabilityCeiling;\n\trequestedTools?: string[];\n\teffectiveTools: string[];\n\tremovedTools: string[];\n\tinternalTools: string[];\n\textensionsDenied: boolean;\n\tremovedExtensionCount: number;\n\trequestedMcpToolCount: number;\n\teffectiveMcpTools: string[];\n\tagentAllowed: boolean;\n\tagentRestrictionSources?: string[];\n}\n\nexport interface RegisterSubagentCapabilityCeilingOptions {\n\tsessionId: string;\n\tsource: string;\n\tceiling: SubagentCapabilityCeiling;\n}\n\nexport interface SubagentCapabilityCeilingHandle {\n\tupdate(ceiling: SubagentCapabilityCeiling): void;\n\tdispose(): void;\n}\n\ntype Registration = { source: string; ceiling: ResolvedSubagentCapabilityCeiling };\ntype Registry = Map<string, Map<symbol, Registration>>;\n\nfunction registry(): Registry {\n\tconst key = Symbol.for(SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY);\n\tconst store = globalThis as typeof globalThis & { [key: symbol]: unknown };\n\tconst existing = store[key];\n\tif (existing instanceof Map) return existing as Registry;\n\tconst created: Registry = new Map();\n\tstore[key] = created;\n\treturn created;\n}\n\nfunction validateText(value: unknown, field: string): string {\n\tif (typeof value !== \"string\" || !value.trim() || /[\\u0000-\\u001f\\u007f]/u.test(value) || Buffer.byteLength(value.trim(), \"utf8\") > 256) {\n\t\tthrow new Error(`Invalid capability ceiling ${field}; expected a non-empty string without control characters (max 256 UTF-8 bytes).`);\n\t}\n\treturn value.trim();\n}\n\nfunction normalizeCeiling(ceiling: SubagentCapabilityCeiling): ResolvedSubagentCapabilityCeiling {\n\tif (!ceiling || typeof ceiling !== \"object\" || Array.isArray(ceiling)) throw new Error(\"Invalid capability ceiling; expected an object.\");\n\tconst hasAllowedTools = Object.hasOwn(ceiling, \"allowedTools\");\n\tconst hasAllowedAgents = Object.hasOwn(ceiling, \"allowedAgents\");\n\tconst hasDenyExtensions = Object.hasOwn(ceiling, \"denyExtensions\");\n\tif (!hasAllowedTools && !hasAllowedAgents && !hasDenyExtensions) throw new Error(\"Invalid capability ceiling; expected allowedTools, allowedAgents, or denyExtensions.\");\n\tif (hasDenyExtensions && typeof ceiling.denyExtensions !== \"boolean\") throw new Error(\"Invalid capability ceiling denyExtensions; expected a boolean.\");\n\tconst normalizeList = (field: \"allowedTools\" | \"allowedAgents\", pattern: RegExp): string[] | undefined => {\n\t\tif (!Object.hasOwn(ceiling, field)) return undefined;\n\t\tconst values = ceiling[field];\n\t\tif (!Array.isArray(values)) throw new Error(`Invalid capability ceiling ${field}; expected an array.`);\n\t\tif (values.length > 256) throw new Error(`Invalid capability ceiling ${field}; expected at most 256 names.`);\n\t\treturn [...new Set(values.map((entry) => {\n\t\t\tconst name = validateText(entry, `${field} entry`);\n\t\t\tif (!pattern.test(name)) throw new Error(`Invalid capability ceiling ${field} entry '${name}'.`);\n\t\t\tif (Buffer.byteLength(name, \"utf8\") > 128) throw new Error(`Invalid capability ceiling ${field} entry '${name}'; max 128 UTF-8 bytes.`);\n\t\t\treturn name;\n\t\t}))].sort();\n\t};\n\tconst allowedTools = normalizeList(\"allowedTools\", /^[A-Za-z0-9_.:-]+$/u);\n\tconst allowedAgents = normalizeList(\"allowedAgents\", /^[A-Za-z0-9_.:-]+$/u);\n\treturn {\n\t\tversion: SUBAGENT_CAPABILITY_CEILING_VERSION,\n\t\t...(allowedTools !== undefined ? { allowedTools } : {}),\n\t\t...(allowedAgents !== undefined ? { allowedAgents } : {}),\n\t\tdenyExtensions: ceiling.denyExtensions === true,\n\t\tsources: [],\n\t};\n}\n\nexport function parseSubagentCapabilityCeiling(value: unknown, field = \"capability ceiling\"): ResolvedSubagentCapabilityCeiling {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`Invalid ${field}; expected an object.`);\n\tconst record = value as Record<string, unknown>;\n\tif (record.version !== SUBAGENT_CAPABILITY_CEILING_VERSION) throw new Error(`Invalid ${field} version.`);\n\tconst normalized = normalizeCeiling(record as SubagentCapabilityCeiling);\n\tconst sources = record.sources;\n\tif (!Array.isArray(sources) || sources.some((source) => typeof source !== \"string\")) throw new Error(`Invalid ${field} sources; expected an array of strings.`);\n\tnormalized.sources = [...new Set(sources.map((source) => validateText(source, `${field} source`)))].sort();\n\treturn normalized;\n}\n\nexport function registerSubagentCapabilityCeiling(options: RegisterSubagentCapabilityCeilingOptions): SubagentCapabilityCeilingHandle {\n\tconst sessionId = validateText(options.sessionId, \"sessionId\");\n\tconst source = validateText(options.source, \"source\");\n\tlet normalized = normalizeCeiling(options.ceiling);\n\tconst token = Symbol(source);\n\tconst store = registry();\n\tlet session = store.get(sessionId);\n\tif (!session) {\n\t\tsession = new Map();\n\t\tstore.set(sessionId, session);\n\t}\n\tconst setRegistration = () => {\n\t\tnormalized = normalizeCeiling(normalized);\n\t\tnormalized.sources = [source];\n\t\tsession!.set(token, { source, ceiling: normalized });\n\t};\n\tsetRegistration();\n\tlet disposed = false;\n\treturn {\n\t\tupdate(ceiling) {\n\t\t\tif (disposed) throw new Error(\"Cannot update a disposed capability ceiling handle.\");\n\t\t\tnormalized = normalizeCeiling(ceiling);\n\t\t\tnormalized.sources = [source];\n\t\t\tsession!.set(token, { source, ceiling: normalized });\n\t\t},\n\t\tdispose() {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tsession!.delete(token);\n\t\t\tif (session!.size === 0) store.delete(sessionId);\n\t\t},\n\t};\n}\n\nexport function intersectSubagentCapabilityCeilings(...ceilings: Array<ResolvedSubagentCapabilityCeiling | undefined>): ResolvedSubagentCapabilityCeiling | undefined {\n\tconst active = ceilings.filter((ceiling): ceiling is ResolvedSubagentCapabilityCeiling => ceiling !== undefined);\n\tif (active.length === 0) return undefined;\n\tconst intersectLists = (field: \"allowedTools\" | \"allowedAgents\"): string[] | undefined => {\n\t\tconst definedLists = active.filter((ceiling) => ceiling[field] !== undefined).map((ceiling) => new Set(ceiling[field]));\n\t\tif (definedLists.length === 0) return undefined;\n\t\treturn [...definedLists[0]!].filter((entry) => definedLists.every((list) => list.has(entry))).sort();\n\t};\n\tconst allowedTools = intersectLists(\"allowedTools\");\n\tconst allowedAgents = intersectLists(\"allowedAgents\");\n\treturn {\n\t\tversion: SUBAGENT_CAPABILITY_CEILING_VERSION,\n\t\t...(allowedTools !== undefined ? { allowedTools } : {}),\n\t\t...(allowedAgents !== undefined ? { allowedAgents } : {}),\n\t\tdenyExtensions: active.some((ceiling) => ceiling.denyExtensions),\n\t\tsources: [...new Set(active.flatMap((ceiling) => ceiling.sources))].sort(),\n\t};\n}\n\nexport function resolveSubagentCapabilityCeiling(sessionId: string | undefined, inherited?: ResolvedSubagentCapabilityCeiling): ResolvedSubagentCapabilityCeiling | undefined {\n\tconst active: ResolvedSubagentCapabilityCeiling[] = [];\n\tif (sessionId) {\n\t\tconst registrations = registry().get(sessionId);\n\t\tif (registrations) active.push(...Array.from(registrations.values(), ({ ceiling }) => ceiling));\n\t}\n\treturn intersectSubagentCapabilityCeilings(inherited, ...active);\n}\n\nexport function resolveCurrentSubagentCapabilityCeiling(sessionId: string | undefined): ResolvedSubagentCapabilityCeiling | undefined {\n\treturn resolveSubagentCapabilityCeiling(sessionId, decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]));\n}\n\nexport function isAgentAllowedByCapabilityCeiling(agentName: string, ceiling: ResolvedSubagentCapabilityCeiling | undefined): boolean {\n\treturn ceiling?.allowedAgents === undefined || ceiling.allowedAgents.includes(agentName);\n}\n\nexport function capabilityCeilingAgentRestrictionMessage(agentName: string, ceiling: ResolvedSubagentCapabilityCeiling | undefined): string | undefined {\n\tif (isAgentAllowedByCapabilityCeiling(agentName, ceiling)) return undefined;\n\tconst sources = ceiling?.sources.length ? ceiling.sources.join(\", \") : \"unknown source\";\n\tconst allowed = ceiling?.allowedAgents?.length ? ceiling.allowedAgents.join(\", \") : \"(none)\";\n\treturn `Capability ceiling from ${sources} does not allow agent '${agentName}'. Allowed agents: ${allowed}.`;\n}\n\nexport function assertAgentAllowedByCapabilityCeiling(agentName: string, ceiling: ResolvedSubagentCapabilityCeiling | undefined): void {\n\tconst message = capabilityCeilingAgentRestrictionMessage(agentName, ceiling);\n\tif (message) throw new Error(message);\n}\n\nexport function capabilityCeilingAgentRestrictionSources(ceiling: ResolvedSubagentCapabilityCeiling | undefined): string[] | undefined {\n\treturn ceiling?.allowedAgents === undefined ? undefined : [...ceiling.sources];\n}\n\nexport function encodeSubagentCapabilityCeiling(ceiling: ResolvedSubagentCapabilityCeiling | undefined): string | undefined {\n\tif (!ceiling) return undefined;\n\treturn Buffer.from(JSON.stringify(ceiling), \"utf8\").toString(\"base64url\");\n}\n\nexport function decodeSubagentCapabilityCeiling(value: string | undefined): ResolvedSubagentCapabilityCeiling | undefined {\n\tif (value === undefined || value === \"\") return undefined;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(Buffer.from(value, \"base64url\").toString(\"utf8\"));\n\t} catch (error) {\n\t\tthrow new Error(`Invalid inherited capability ceiling: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed) || (parsed as { version?: unknown }).version !== SUBAGENT_CAPABILITY_CEILING_VERSION) {\n\t\tthrow new Error(\"Invalid inherited capability ceiling version.\");\n\t}\n\treturn parseSubagentCapabilityCeiling(parsed, \"inherited capability ceiling\");\n}\n","export const BYOK_PI_PERMISSION_MODE = 'BYOK_PI_PERMISSION_MODE';\n\n/** SDK-owned extension tools that do not mutate the task workspace. */\nexport const BYOK_PI_READONLY_PARENT_TOOLS = ['subagent', 'todo'] as const;\n\n/** Child tools retained when a readonly parent delegates through pi-subagents. */\nexport const BYOK_PI_READONLY_SUBAGENT_TOOLS = ['read', 'grep', 'find', 'ls'] as const;\n\n/** Package-provided read-only roles; writer and ambient custom roles stay unavailable. */\nexport const BYOK_PI_READONLY_SUBAGENT_AGENTS = [\n 'reviewer',\n 'oracle',\n 'codex-exec',\n 'claude-code',\n 'cursor-agent',\n] as const;\n","import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport {\n registerSubagentCapabilityCeiling,\n type SubagentCapabilityCeilingHandle,\n} from 'pi-subagents/capability-ceiling';\nimport {\n BYOK_PI_PERMISSION_MODE,\n BYOK_PI_READONLY_SUBAGENT_AGENTS,\n BYOK_PI_READONLY_SUBAGENT_TOOLS,\n} from './subagents-policy-config';\n\nfunction permissionMode(): 'auto' | 'readonly' {\n const mode = process.env[BYOK_PI_PERMISSION_MODE];\n if (mode === 'auto' || mode === 'readonly') return mode;\n throw new Error(`${BYOK_PI_PERMISSION_MODE} must be \"auto\" or \"readonly\"`);\n}\n\n/**\n * Keep pi-subagents available in every Pi session without letting a readonly\n * parent widen its task contract through a child process.\n */\nexport default function registerByokSubagentsPolicy(pi: ExtensionAPI): void {\n const mode = permissionMode();\n let ceiling: SubagentCapabilityCeilingHandle | undefined;\n\n pi.on('session_start', (_event, ctx) => {\n ceiling?.dispose();\n ceiling = undefined;\n if (mode === 'auto') return;\n\n const sessionId = ctx.sessionManager.getSessionId();\n if (!sessionId) throw new Error('readonly Pi subagent policy requires an authoritative session id');\n ceiling = registerSubagentCapabilityCeiling({\n sessionId,\n source: 'byok-sdk-readonly',\n ceiling: {\n allowedTools: BYOK_PI_READONLY_SUBAGENT_TOOLS,\n allowedAgents: BYOK_PI_READONLY_SUBAGENT_AGENTS,\n denyExtensions: true,\n },\n });\n });\n\n pi.on('tool_call', (event) => {\n if (mode === 'readonly' && event.toolName === 'subagent' && ceiling === undefined) {\n return {\n block: true,\n terminate: true,\n reason: 'readonly Pi subagent capability ceiling is unavailable',\n };\n }\n });\n\n pi.on('session_shutdown', () => {\n ceiling?.dispose();\n ceiling = undefined;\n });\n}\n"]}
|
package/dist/agent-home.d.ts
CHANGED
|
@@ -73,6 +73,14 @@ export interface AgentHomeBinding {
|
|
|
73
73
|
readonly resolution: AgentHomeResolution;
|
|
74
74
|
readonly lease: AgentHomeLease;
|
|
75
75
|
}
|
|
76
|
+
export interface AgentHomeExecutionLease extends AgentHomeLease {
|
|
77
|
+
/** Fresh tasks are task-keyed until the runtime returns its durable session id. */
|
|
78
|
+
bindSession(sessionRef: string): Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
export interface AgentHomeExecutionBinding {
|
|
81
|
+
readonly resolution: AgentHomeResolution;
|
|
82
|
+
readonly lease: AgentHomeExecutionLease;
|
|
83
|
+
}
|
|
76
84
|
export declare function validateAgentRef(value: unknown): AgentRef;
|
|
77
85
|
/**
|
|
78
86
|
* SDK-owned deterministic Agent-home layout. The downstream supplies exactly
|
|
@@ -112,11 +120,29 @@ export declare class AgentHomeLeaseManager {
|
|
|
112
120
|
acquire(resolution: AgentHomeResolution): Promise<AgentHomeLease>;
|
|
113
121
|
private openLeaseMarker;
|
|
114
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Session-scoped execution leases share one process-owned home marker. The
|
|
125
|
+
* marker remains until the final session exits, so relocation still sees the
|
|
126
|
+
* Agent home as active, while different sessions no longer exclude each other.
|
|
127
|
+
*/
|
|
128
|
+
export declare class AgentHomeExecutionLeaseManager {
|
|
129
|
+
private readonly manager;
|
|
130
|
+
private static readonly groups;
|
|
131
|
+
private static readonly queues;
|
|
132
|
+
constructor(manager: AgentHomeLeaseManager);
|
|
133
|
+
acquire(resolution: AgentHomeResolution, input: {
|
|
134
|
+
readonly taskId: string;
|
|
135
|
+
readonly sessionRef?: string;
|
|
136
|
+
}): Promise<AgentHomeExecutionLease>;
|
|
137
|
+
mutate<T>(binding: AgentHomeExecutionBinding, operation: () => Promise<T>): Promise<T>;
|
|
138
|
+
private exclusive;
|
|
139
|
+
}
|
|
115
140
|
/** Coordinates SDK-owned initialization, optional projection, and the lease. */
|
|
116
141
|
export declare class AgentHomeManager {
|
|
117
142
|
readonly layout: AgentHomeLayout;
|
|
118
143
|
readonly projection?: AgentHomeProjection;
|
|
119
144
|
readonly leaseManager: AgentHomeLeaseManager;
|
|
145
|
+
readonly executionLeaseManager: AgentHomeExecutionLeaseManager;
|
|
120
146
|
constructor(options: {
|
|
121
147
|
hostStorageRoot: string;
|
|
122
148
|
projection?: AgentHomeProjection;
|
|
@@ -129,8 +155,15 @@ export declare class AgentHomeManager {
|
|
|
129
155
|
preflightSync(): void;
|
|
130
156
|
/** Resolve and lease without applying downstream projection side effects. */
|
|
131
157
|
acquire(agentRef: AgentRef): Promise<AgentHomeBinding>;
|
|
158
|
+
acquireExecution(agentRef: AgentRef, input: {
|
|
159
|
+
readonly taskId: string;
|
|
160
|
+
readonly sessionRef?: string;
|
|
161
|
+
}): Promise<AgentHomeExecutionBinding>;
|
|
132
162
|
/** Initialize only after any requested session exact-match has succeeded. */
|
|
133
163
|
initialize(binding: AgentHomeBinding): Promise<void>;
|
|
164
|
+
initializeExecution(binding: AgentHomeExecutionBinding): Promise<void>;
|
|
165
|
+
mutateExecution<T>(binding: AgentHomeExecutionBinding, operation: () => Promise<T>): Promise<T>;
|
|
166
|
+
private initializeResolved;
|
|
134
167
|
supportsTaskFreeProjection(): boolean;
|
|
135
168
|
/**
|
|
136
169
|
* Apply one task-free projection under the same canonical-home writer lease
|
|
@@ -80,7 +80,7 @@ export type { AgentMemoryFilesystem } from '../daemon/agent-memory-filesystem';
|
|
|
80
80
|
export type { AgentMemoryFilesystemFileState } from '../daemon/agent-memory-filesystem';
|
|
81
81
|
/** Product-owned deployment pointer to the helper binary; the SDK never searches PATH. */
|
|
82
82
|
export type { AgentMemoryFilesystemHelperConfig } from '../daemon/agent-memory-filesystem';
|
|
83
|
-
/** Serves `
|
|
83
|
+
/** Serves `memory_recall`/`memory_save` as a stdio MCP server over host-provided streams. */
|
|
84
84
|
export { serveAgentMemoryMcpOverStdio } from '../bin/agent-memory-mcp-server';
|
|
85
85
|
/** MCP tool name a host must allowlist for reads. */
|
|
86
86
|
export { AGENT_MEMORY_RECALL_TOOL_NAME } from '../bin/agent-memory-mcp-server';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
2
|
import { constants, existsSync, promises } from 'fs';
|
|
3
3
|
import path2 from 'path';
|
|
4
4
|
import '@byok-sdk/protocol';
|
|
@@ -292,21 +292,24 @@ async function recordAuditWarning(context, kind, values) {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
var agentMemoryHomeQueues = /* @__PURE__ */ new Map();
|
|
295
|
-
async function
|
|
296
|
-
const previous =
|
|
295
|
+
async function exclusiveAgentMemoryHomeQueue(queues, home, fn) {
|
|
296
|
+
const previous = queues.get(home) ?? Promise.resolve();
|
|
297
297
|
let release;
|
|
298
298
|
const next = new Promise((resolve) => {
|
|
299
299
|
release = resolve;
|
|
300
300
|
});
|
|
301
|
-
|
|
301
|
+
queues.set(home, next);
|
|
302
302
|
await previous;
|
|
303
303
|
try {
|
|
304
304
|
return await fn();
|
|
305
305
|
} finally {
|
|
306
306
|
release();
|
|
307
|
-
if (
|
|
307
|
+
if (queues.get(home) === next) queues.delete(home);
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
+
async function exclusiveAgentMemoryHome(home, fn) {
|
|
311
|
+
return exclusiveAgentMemoryHomeQueue(agentMemoryHomeQueues, home, fn);
|
|
312
|
+
}
|
|
310
313
|
var AgentMemoryService = class {
|
|
311
314
|
constructor(input) {
|
|
312
315
|
this.input = input;
|
|
@@ -678,8 +681,8 @@ var AgentMemoryFilesystemHelperClient = class _AgentMemoryFilesystemHelperClient
|
|
|
678
681
|
async function openAgentMemoryFilesystemHelper(input) {
|
|
679
682
|
return AgentMemoryFilesystemHelperClient.open(input);
|
|
680
683
|
}
|
|
681
|
-
var AGENT_MEMORY_RECALL_TOOL_NAME = "
|
|
682
|
-
var AGENT_MEMORY_SAVE_TOOL_NAME = "
|
|
684
|
+
var AGENT_MEMORY_RECALL_TOOL_NAME = "memory_recall";
|
|
685
|
+
var AGENT_MEMORY_SAVE_TOOL_NAME = "memory_save";
|
|
683
686
|
function record(value) {
|
|
684
687
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
685
688
|
}
|
|
@@ -710,11 +713,11 @@ async function handleAgentMemoryMcpRequest(request, deps) {
|
|
|
710
713
|
if (!params || !args || typeof params.name !== "string") return invalid(id, "memory tool input must be an object");
|
|
711
714
|
try {
|
|
712
715
|
if (params.name === AGENT_MEMORY_RECALL_TOOL_NAME) {
|
|
713
|
-
if (Object.keys(args).some((key) => key !== "path" && key !== "ifRevision") || typeof args.path !== "string" || args.ifRevision !== void 0 && typeof args.ifRevision !== "string") return invalid(id, "
|
|
716
|
+
if (Object.keys(args).some((key) => key !== "path" && key !== "ifRevision") || typeof args.path !== "string" || args.ifRevision !== void 0 && typeof args.ifRevision !== "string") return invalid(id, "memory_recall accepts only path and optional ifRevision");
|
|
714
717
|
return success(id, await deps.recall({ path: args.path, ...args.ifRevision === void 0 ? {} : { ifRevision: args.ifRevision } }));
|
|
715
718
|
}
|
|
716
719
|
if (params.name === AGENT_MEMORY_SAVE_TOOL_NAME) {
|
|
717
|
-
if (Object.keys(args).some((key) => key !== "op" && key !== "path" && key !== "expectedRevision" && key !== "content") || args.op !== "replace" && args.op !== "delete" || typeof args.path !== "string" || typeof args.expectedRevision !== "string" || args.op === "replace" && typeof args.content !== "string" || args.op === "delete" && args.content !== void 0) return invalid(id, "
|
|
720
|
+
if (Object.keys(args).some((key) => key !== "op" && key !== "path" && key !== "expectedRevision" && key !== "content") || args.op !== "replace" && args.op !== "delete" || typeof args.path !== "string" || typeof args.expectedRevision !== "string" || args.op === "replace" && typeof args.content !== "string" || args.op === "delete" && args.content !== void 0) return invalid(id, "memory_save requires replace|delete, path, expectedRevision, and content only for replace");
|
|
718
721
|
const content = args.content;
|
|
719
722
|
return success(id, await deps.save({ op: args.op, path: args.path, expectedRevision: args.expectedRevision, ...typeof content === "string" ? { content } : {} }));
|
|
720
723
|
}
|