@rarebit-one/harness-kernel 0.5.1
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/LICENSE +21 -0
- package/README.md +286 -0
- package/dist/agent.d.ts +71 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +258 -0
- package/dist/agent.js.map +1 -0
- package/dist/connectors/mcpClient.d.ts +22 -0
- package/dist/connectors/mcpClient.d.ts.map +1 -0
- package/dist/connectors/mcpClient.js +63 -0
- package/dist/connectors/mcpClient.js.map +1 -0
- package/dist/context/types.d.ts +68 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +43 -0
- package/dist/context/types.js.map +1 -0
- package/dist/engines/capability.d.ts +67 -0
- package/dist/engines/capability.d.ts.map +1 -0
- package/dist/engines/capability.js +73 -0
- package/dist/engines/capability.js.map +1 -0
- package/dist/engines/capabilityEmissions.d.ts +27 -0
- package/dist/engines/capabilityEmissions.d.ts.map +1 -0
- package/dist/engines/capabilityEmissions.js +37 -0
- package/dist/engines/capabilityEmissions.js.map +1 -0
- package/dist/engines/capabilityMcp.d.ts +23 -0
- package/dist/engines/capabilityMcp.d.ts.map +1 -0
- package/dist/engines/capabilityMcp.js +36 -0
- package/dist/engines/capabilityMcp.js.map +1 -0
- package/dist/engines/capabilityStdio.d.ts +46 -0
- package/dist/engines/capabilityStdio.d.ts.map +1 -0
- package/dist/engines/capabilityStdio.js +39 -0
- package/dist/engines/capabilityStdio.js.map +1 -0
- package/dist/engines/claudeCode.d.ts +73 -0
- package/dist/engines/claudeCode.d.ts.map +1 -0
- package/dist/engines/claudeCode.js +100 -0
- package/dist/engines/claudeCode.js.map +1 -0
- package/dist/engines/claudeCodeDriver.d.ts +14 -0
- package/dist/engines/claudeCodeDriver.d.ts.map +1 -0
- package/dist/engines/claudeCodeDriver.js +90 -0
- package/dist/engines/claudeCodeDriver.js.map +1 -0
- package/dist/engines/codex.d.ts +72 -0
- package/dist/engines/codex.d.ts.map +1 -0
- package/dist/engines/codex.js +157 -0
- package/dist/engines/codex.js.map +1 -0
- package/dist/engines/codexDriver.d.ts +43 -0
- package/dist/engines/codexDriver.d.ts.map +1 -0
- package/dist/engines/codexDriver.js +110 -0
- package/dist/engines/codexDriver.js.map +1 -0
- package/dist/engines/connectorMcp.d.ts +60 -0
- package/dist/engines/connectorMcp.d.ts.map +1 -0
- package/dist/engines/connectorMcp.js +137 -0
- package/dist/engines/connectorMcp.js.map +1 -0
- package/dist/engines/index.d.ts +33 -0
- package/dist/engines/index.d.ts.map +1 -0
- package/dist/engines/index.js +29 -0
- package/dist/engines/index.js.map +1 -0
- package/dist/engines/native.d.ts +55 -0
- package/dist/engines/native.d.ts.map +1 -0
- package/dist/engines/native.js +117 -0
- package/dist/engines/native.js.map +1 -0
- package/dist/engines/types.d.ts +107 -0
- package/dist/engines/types.d.ts.map +1 -0
- package/dist/engines/types.js +2 -0
- package/dist/engines/types.js.map +1 -0
- package/dist/events.d.ts +211 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +69 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/loop.d.ts +132 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +77 -0
- package/dist/loop.js.map +1 -0
- package/dist/models/chat.d.ts +65 -0
- package/dist/models/chat.d.ts.map +1 -0
- package/dist/models/chat.js +66 -0
- package/dist/models/chat.js.map +1 -0
- package/dist/models/middleware.d.ts +63 -0
- package/dist/models/middleware.d.ts.map +1 -0
- package/dist/models/middleware.js +139 -0
- package/dist/models/middleware.js.map +1 -0
- package/dist/models/registry.d.ts +78 -0
- package/dist/models/registry.d.ts.map +1 -0
- package/dist/models/registry.js +0 -0
- package/dist/models/registry.js.map +1 -0
- package/dist/models/types.d.ts +149 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +64 -0
- package/dist/models/types.js.map +1 -0
- package/dist/primitives/codeExec.d.ts +25 -0
- package/dist/primitives/codeExec.d.ts.map +1 -0
- package/dist/primitives/codeExec.js +69 -0
- package/dist/primitives/codeExec.js.map +1 -0
- package/dist/primitives/download.d.ts +19 -0
- package/dist/primitives/download.d.ts.map +1 -0
- package/dist/primitives/download.js +113 -0
- package/dist/primitives/download.js.map +1 -0
- package/dist/primitives/fs.d.ts +5 -0
- package/dist/primitives/fs.d.ts.map +1 -0
- package/dist/primitives/fs.js +59 -0
- package/dist/primitives/fs.js.map +1 -0
- package/dist/primitives/http.d.ts +100 -0
- package/dist/primitives/http.d.ts.map +1 -0
- package/dist/primitives/http.js +257 -0
- package/dist/primitives/http.js.map +1 -0
- package/dist/providers/anthropic.d.ts +15 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +90 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/clientOptions.d.ts +14 -0
- package/dist/providers/clientOptions.d.ts.map +1 -0
- package/dist/providers/clientOptions.js +26 -0
- package/dist/providers/clientOptions.js.map +1 -0
- package/dist/providers/index.d.ts +24 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +51 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/mock.d.ts +25 -0
- package/dist/providers/mock.d.ts.map +1 -0
- package/dist/providers/mock.js +85 -0
- package/dist/providers/mock.js.map +1 -0
- package/dist/providers/openai.d.ts +32 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +118 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openrouter.d.ts +29 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +35 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/types.d.ts +60 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/routing/staticResolver.d.ts +41 -0
- package/dist/routing/staticResolver.d.ts.map +1 -0
- package/dist/routing/staticResolver.js +67 -0
- package/dist/routing/staticResolver.js.map +1 -0
- package/dist/routing/types.d.ts +72 -0
- package/dist/routing/types.d.ts.map +1 -0
- package/dist/routing/types.js +11 -0
- package/dist/routing/types.js.map +1 -0
- package/dist/secrets.d.ts +8 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +14 -0
- package/dist/secrets.js.map +1 -0
- package/dist/tools/metadata.d.ts +93 -0
- package/dist/tools/metadata.d.ts.map +1 -0
- package/dist/tools/metadata.js +49 -0
- package/dist/tools/metadata.js.map +1 -0
- package/dist/tools/modelTool.d.ts +35 -0
- package/dist/tools/modelTool.d.ts.map +1 -0
- package/dist/tools/modelTool.js +37 -0
- package/dist/tools/modelTool.js.map +1 -0
- package/dist/tools/registry.d.ts +65 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +166 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
2
|
+
import type { ConnectorConfig } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* The client identity announced to every MCP server we connect to, suffixed
|
|
5
|
+
* with the connector's own name. Servers use it for logging and telemetry.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MCP_CLIENT_NAME = "harness-kernel";
|
|
8
|
+
/** A live MCP connection, narrowed to what the tool registry needs. */
|
|
9
|
+
export interface McpConnection {
|
|
10
|
+
listTools(): Promise<unknown>;
|
|
11
|
+
callTool(name: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/** Connect to an MCP connector using the transport implied by its config. */
|
|
15
|
+
export declare function connectMcp(config: ConnectorConfig): Promise<McpConnection>;
|
|
16
|
+
/**
|
|
17
|
+
* Connect over an arbitrary transport. Exposed so tests (and future callers) can
|
|
18
|
+
* supply an in-memory transport pair without spawning a process or hitting the
|
|
19
|
+
* network.
|
|
20
|
+
*/
|
|
21
|
+
export declare function connectWithTransport(name: string, transport: Transport): Promise<McpConnection>;
|
|
22
|
+
//# sourceMappingURL=mcpClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpClient.d.ts","sourceRoot":"","sources":["../../src/connectors/mcpClient.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD;;;GAGG;AACH,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAE/C,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACxE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAwCD,6EAA6E;AAC7E,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAEhF;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,aAAa,CAAC,CASxB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
5
|
+
/**
|
|
6
|
+
* The client identity announced to every MCP server we connect to, suffixed
|
|
7
|
+
* with the connector's own name. Servers use it for logging and telemetry.
|
|
8
|
+
*/
|
|
9
|
+
export const MCP_CLIENT_NAME = "harness-kernel";
|
|
10
|
+
/** Bearer auth is attached as a request header for the HTTP-family transports. */
|
|
11
|
+
function bearerInit(config) {
|
|
12
|
+
if (config.auth?.type === "bearer" && config.auth.token) {
|
|
13
|
+
return { requestInit: { headers: { Authorization: `Bearer ${config.auth.token}` } } };
|
|
14
|
+
}
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
function buildTransport(config) {
|
|
18
|
+
switch (config.transport) {
|
|
19
|
+
case "stdio": {
|
|
20
|
+
if (!config.command) {
|
|
21
|
+
throw new Error(`connector ${config.name}: stdio transport requires a command`);
|
|
22
|
+
}
|
|
23
|
+
// stdio servers receive credentials via env, not headers.
|
|
24
|
+
const env = config.auth?.type === "bearer" && config.auth.token
|
|
25
|
+
? { ...getDefaultEnvironment(), MCP_AUTH_TOKEN: config.auth.token }
|
|
26
|
+
: undefined;
|
|
27
|
+
return new StdioClientTransport({ command: config.command, args: config.args ?? [], env });
|
|
28
|
+
}
|
|
29
|
+
case "streamable_http": {
|
|
30
|
+
if (!config.endpoint) {
|
|
31
|
+
throw new Error(`connector ${config.name}: streamable_http transport requires an endpoint`);
|
|
32
|
+
}
|
|
33
|
+
return new StreamableHTTPClientTransport(new URL(config.endpoint), bearerInit(config));
|
|
34
|
+
}
|
|
35
|
+
case "sse": {
|
|
36
|
+
if (!config.endpoint) {
|
|
37
|
+
throw new Error(`connector ${config.name}: sse transport requires an endpoint`);
|
|
38
|
+
}
|
|
39
|
+
return new SSEClientTransport(new URL(config.endpoint), bearerInit(config));
|
|
40
|
+
}
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`connector ${config.name}: unknown transport ${String(config.transport)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Connect to an MCP connector using the transport implied by its config. */
|
|
46
|
+
export async function connectMcp(config) {
|
|
47
|
+
return connectWithTransport(config.name, buildTransport(config));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Connect over an arbitrary transport. Exposed so tests (and future callers) can
|
|
51
|
+
* supply an in-memory transport pair without spawning a process or hitting the
|
|
52
|
+
* network.
|
|
53
|
+
*/
|
|
54
|
+
export async function connectWithTransport(name, transport) {
|
|
55
|
+
const client = new Client({ name: `${MCP_CLIENT_NAME}/${name}`, version: "0.1.0" });
|
|
56
|
+
await client.connect(transport);
|
|
57
|
+
return {
|
|
58
|
+
listTools: () => client.listTools(),
|
|
59
|
+
callTool: (toolName, args = {}) => client.callTool({ name: toolName, arguments: args }),
|
|
60
|
+
close: () => client.close(),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=mcpClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpClient.js","sourceRoot":"","sources":["../../src/connectors/mcpClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { WorkflowDefinition } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pluggable context assembly.
|
|
4
|
+
*
|
|
5
|
+
* A run's context started life as a single pre-assembled string on the run
|
|
6
|
+
* spec. That works when context is one static thing, and stops working the
|
|
7
|
+
* moment it isn't: a live perception feed, a retrieval index, and a file
|
|
8
|
+
* excerpt are three sources with different latencies and different failure
|
|
9
|
+
* modes, and none of them should have to be flattened by the caller before the
|
|
10
|
+
* kernel will accept them.
|
|
11
|
+
*
|
|
12
|
+
* So the string becomes a chain. Providers are asked in parallel for fragments;
|
|
13
|
+
* fragments are ordered and rendered into the prompt. A private real-time
|
|
14
|
+
* source plugs in here without the kernel knowing anything about it.
|
|
15
|
+
*/
|
|
16
|
+
/** One piece of assembled context. */
|
|
17
|
+
export interface ContextFragment {
|
|
18
|
+
/** Which provider produced it — rendered as the section heading. */
|
|
19
|
+
source: string;
|
|
20
|
+
text: string;
|
|
21
|
+
/** Higher sorts first. Defaults to 0; ties keep provider order. */
|
|
22
|
+
priority?: number;
|
|
23
|
+
/** Free-form detail for callers that post-process fragments. */
|
|
24
|
+
meta?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* What a provider is told about the run. A narrow, read-only view — every field
|
|
28
|
+
* is optional so an engine's own richer run spec structurally satisfies it
|
|
29
|
+
* without the kernel having to convert between them.
|
|
30
|
+
*/
|
|
31
|
+
export interface ContextSpec {
|
|
32
|
+
runId?: string;
|
|
33
|
+
workspaceId?: string;
|
|
34
|
+
workflowPath?: string;
|
|
35
|
+
/** The prepared working tree, for providers that read from disk. */
|
|
36
|
+
workdir?: string;
|
|
37
|
+
inputs?: Record<string, unknown>;
|
|
38
|
+
workflow?: WorkflowDefinition;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A source of run context. Implementations should be cheap to construct and do
|
|
42
|
+
* their work in `assemble`, which may be called concurrently with other
|
|
43
|
+
* providers.
|
|
44
|
+
*/
|
|
45
|
+
export interface ContextProvider {
|
|
46
|
+
readonly name: string;
|
|
47
|
+
assemble(spec: ContextSpec): Promise<ContextFragment[]>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Ask every provider for fragments and return them in render order.
|
|
51
|
+
*
|
|
52
|
+
* Providers run **in parallel** — they are independent sources and a slow one
|
|
53
|
+
* shouldn't serialise behind the others. A provider that throws is logged and
|
|
54
|
+
* skipped rather than failing the run: context is additive by nature, and
|
|
55
|
+
* losing one optional source is not a reason to abandon work that the remaining
|
|
56
|
+
* sources can still support. (This is the one place the kernel degrades instead
|
|
57
|
+
* of failing loud, and it is deliberate — a *missing model* is a broken run,
|
|
58
|
+
* a missing context fragment is a thinner prompt.)
|
|
59
|
+
*/
|
|
60
|
+
export declare function assembleContext(providers: ContextProvider[], spec: ContextSpec, log?: (line: string) => void): Promise<ContextFragment[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Render fragments into the prompt text an engine embeds. Each fragment becomes
|
|
63
|
+
* a titled section so the model can tell sources apart; an empty list renders
|
|
64
|
+
* as an empty string, which keeps a provider-less run byte-identical to one
|
|
65
|
+
* that never had providers.
|
|
66
|
+
*/
|
|
67
|
+
export declare function renderContext(fragments: ContextFragment[]): string;
|
|
68
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErD;;;;;;;;;;;;;GAaG;AAEH,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;CACxD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,eAAe,EAAE,EAC5B,IAAI,EAAE,WAAW,EACjB,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAe,GACrC,OAAO,CAAC,eAAe,EAAE,CAAC,CAsB5B;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,MAAM,CAElE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask every provider for fragments and return them in render order.
|
|
3
|
+
*
|
|
4
|
+
* Providers run **in parallel** — they are independent sources and a slow one
|
|
5
|
+
* shouldn't serialise behind the others. A provider that throws is logged and
|
|
6
|
+
* skipped rather than failing the run: context is additive by nature, and
|
|
7
|
+
* losing one optional source is not a reason to abandon work that the remaining
|
|
8
|
+
* sources can still support. (This is the one place the kernel degrades instead
|
|
9
|
+
* of failing loud, and it is deliberate — a *missing model* is a broken run,
|
|
10
|
+
* a missing context fragment is a thinner prompt.)
|
|
11
|
+
*/
|
|
12
|
+
export async function assembleContext(providers, spec, log = () => { }) {
|
|
13
|
+
const settled = await Promise.allSettled(providers.map((p) => p.assemble(spec)));
|
|
14
|
+
const fragments = [];
|
|
15
|
+
settled.forEach((outcome, index) => {
|
|
16
|
+
const provider = providers[index];
|
|
17
|
+
if (!provider)
|
|
18
|
+
return;
|
|
19
|
+
if (outcome.status === "fulfilled") {
|
|
20
|
+
fragments.push(...outcome.value);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const reason = outcome.reason;
|
|
24
|
+
const message = reason instanceof Error ? reason.message : String(reason);
|
|
25
|
+
log(`context provider ${provider.name} failed: ${message}`);
|
|
26
|
+
});
|
|
27
|
+
// Stable sort by descending priority: providers that declare nothing keep the
|
|
28
|
+
// order they were registered in.
|
|
29
|
+
return fragments
|
|
30
|
+
.map((fragment, index) => ({ fragment, index }))
|
|
31
|
+
.sort((a, b) => (b.fragment.priority ?? 0) - (a.fragment.priority ?? 0) || a.index - b.index)
|
|
32
|
+
.map(({ fragment }) => fragment);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Render fragments into the prompt text an engine embeds. Each fragment becomes
|
|
36
|
+
* a titled section so the model can tell sources apart; an empty list renders
|
|
37
|
+
* as an empty string, which keeps a provider-less run byte-identical to one
|
|
38
|
+
* that never had providers.
|
|
39
|
+
*/
|
|
40
|
+
export function renderContext(fragments) {
|
|
41
|
+
return fragments.map((f) => `### ${f.source}\n${f.text}`).join("\n\n");
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"AAqDA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAA4B,EAC5B,IAAiB,EACjB,MAA8B,GAAG,EAAE,GAAE,CAAC;IAEtC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAEhF,MAAM,SAAS,GAAsB,EAAE,CAAA;IACvC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,CAAC,QAAQ;YAAE,OAAM;QACrB,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACnC,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;YAChC,OAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAY,OAAO,CAAC,MAAM,CAAA;QACtC,MAAM,OAAO,GAAG,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACzE,GAAG,CAAC,oBAAoB,QAAQ,CAAC,IAAI,YAAY,OAAO,EAAE,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,8EAA8E;IAC9E,iCAAiC;IACjC,OAAO,SAAS;SACb,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;SAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SAC5F,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAA;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAA4B;IACxD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AACxE,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* The standing, workspace-scoped authority an engine grants an in-run agent,
|
|
4
|
+
* uniformly regardless of engine. It is bound to exactly ONE run: that run's
|
|
5
|
+
* workspace id and its sandbox working tree.
|
|
6
|
+
*
|
|
7
|
+
* The agent can NEVER name another workspace: the context is fixed at
|
|
8
|
+
* construction and every capability defensively rejects a mismatching
|
|
9
|
+
* `workspace_id`. That invariant is enforced here, by {@link denyCrossWorkspace}
|
|
10
|
+
* and {@link resolveWithin}, and both are exported so an application building
|
|
11
|
+
* its own capabilities inherits exactly the same guarantees rather than
|
|
12
|
+
* reimplementing them slightly differently.
|
|
13
|
+
*
|
|
14
|
+
* The kernel defines only the capabilities that carry no product semantics
|
|
15
|
+
* (currently {@link writeFileCapability}). What an application emits — an
|
|
16
|
+
* issue, a piece of knowledge — is the application's vocabulary and lives
|
|
17
|
+
* there, injected into the engines through their capability-tool seams.
|
|
18
|
+
*/
|
|
19
|
+
export interface CapabilityContext {
|
|
20
|
+
/** The one workspace this authority is scoped to (the run's own). */
|
|
21
|
+
workspaceId: string;
|
|
22
|
+
/** The run's sandbox working tree; write_file lands here → captured by the change set. */
|
|
23
|
+
workdir: string;
|
|
24
|
+
}
|
|
25
|
+
/** The uniform result of a capability call, JSON-encoded back to the agent. */
|
|
26
|
+
export interface CapabilityResult {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
error?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A transport-neutral capability: name + description + a Zod raw shape (the
|
|
32
|
+
* advertised input schema) + a handler over RAW input. The handler — not the
|
|
33
|
+
* transport — is the security boundary: it does its own coercion and enforces
|
|
34
|
+
* the workspace scope, so the guarantees hold identically whether the tool is
|
|
35
|
+
* reached via the Claude Code SDK MCP server, a codex `config.toml` stdio server,
|
|
36
|
+
* or a direct call in a test.
|
|
37
|
+
*/
|
|
38
|
+
export interface CapabilityTool {
|
|
39
|
+
name: string;
|
|
40
|
+
description: string;
|
|
41
|
+
/** Zod raw shape advertised to the model; note it deliberately omits `workspace_id`. */
|
|
42
|
+
schema: z.ZodRawShape;
|
|
43
|
+
handler(input: Record<string, unknown>): Promise<CapabilityResult>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reject any call that names a workspace other than the one this authority is
|
|
47
|
+
* bound to. `workspace_id` is NOT part of any tool's advertised schema, so a
|
|
48
|
+
* well-behaved agent never sends it; this is defense-in-depth against a
|
|
49
|
+
* programmatic or adversarial caller trying to redirect an emit cross-workspace.
|
|
50
|
+
* Returns an error result to short-circuit, or null when the call may proceed.
|
|
51
|
+
*/
|
|
52
|
+
export declare function denyCrossWorkspace(input: Record<string, unknown>, workspaceId: string): CapabilityResult | null;
|
|
53
|
+
/** Lexical guard: refuse a relative path that escapes the sandbox via `..` or is absolute. */
|
|
54
|
+
export declare function resolveWithin(dir: string, relPath: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* The generic sandbox-write capability: put a UTF-8 file into THIS run's working
|
|
57
|
+
* tree. It stays in the kernel because it carries no product semantics — it
|
|
58
|
+
* touches only the workspace scope and the workdir, and the change is picked up
|
|
59
|
+
* by whatever diffs the tree afterwards. Nothing about it is specific to what a
|
|
60
|
+
* given application does with the result.
|
|
61
|
+
*
|
|
62
|
+
* Application-specific capabilities (emitting an issue, promoting knowledge)
|
|
63
|
+
* live in the application and are composed alongside this one — see
|
|
64
|
+
* `capabilityToolsFor` on the engines.
|
|
65
|
+
*/
|
|
66
|
+
export declare function writeFileCapability(ctx: CapabilityContext): CapabilityTool;
|
|
67
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/engines/capability.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,wFAAwF;IACxF,MAAM,EAAE,CAAC,CAAC,WAAW,CAAA;IACrB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;CACnE;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,WAAW,EAAE,MAAM,GAClB,gBAAgB,GAAG,IAAI,CAQzB;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAOlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,iBAAiB,GAAG,cAAc,CA4B1E"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const str = (v) => (typeof v === "string" ? v : "");
|
|
5
|
+
/**
|
|
6
|
+
* Reject any call that names a workspace other than the one this authority is
|
|
7
|
+
* bound to. `workspace_id` is NOT part of any tool's advertised schema, so a
|
|
8
|
+
* well-behaved agent never sends it; this is defense-in-depth against a
|
|
9
|
+
* programmatic or adversarial caller trying to redirect an emit cross-workspace.
|
|
10
|
+
* Returns an error result to short-circuit, or null when the call may proceed.
|
|
11
|
+
*/
|
|
12
|
+
export function denyCrossWorkspace(input, workspaceId) {
|
|
13
|
+
for (const key of ["workspace_id", "workspaceId"]) {
|
|
14
|
+
const v = input[key];
|
|
15
|
+
if (typeof v === "string" && v !== workspaceId) {
|
|
16
|
+
return { ok: false, error: `cross-workspace operation denied (bound to ${workspaceId})` };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
/** Lexical guard: refuse a relative path that escapes the sandbox via `..` or is absolute. */
|
|
22
|
+
export function resolveWithin(dir, relPath) {
|
|
23
|
+
const base = path.resolve(dir);
|
|
24
|
+
const target = path.resolve(base, relPath);
|
|
25
|
+
if (target !== base && !target.startsWith(base + path.sep)) {
|
|
26
|
+
throw new Error(`path escapes sandbox: ${relPath}`);
|
|
27
|
+
}
|
|
28
|
+
return target;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The generic sandbox-write capability: put a UTF-8 file into THIS run's working
|
|
32
|
+
* tree. It stays in the kernel because it carries no product semantics — it
|
|
33
|
+
* touches only the workspace scope and the workdir, and the change is picked up
|
|
34
|
+
* by whatever diffs the tree afterwards. Nothing about it is specific to what a
|
|
35
|
+
* given application does with the result.
|
|
36
|
+
*
|
|
37
|
+
* Application-specific capabilities (emitting an issue, promoting knowledge)
|
|
38
|
+
* live in the application and are composed alongside this one — see
|
|
39
|
+
* `capabilityToolsFor` on the engines.
|
|
40
|
+
*/
|
|
41
|
+
export function writeFileCapability(ctx) {
|
|
42
|
+
return {
|
|
43
|
+
name: "write_file",
|
|
44
|
+
description: "Write a UTF-8 file into THIS run's workspace sandbox (creating parent directories). The " +
|
|
45
|
+
"change is captured in the run's change set and committed to the workspace after the run, " +
|
|
46
|
+
"honoring the approval gate. Paths are relative to the workspace root; escaping it is refused.",
|
|
47
|
+
schema: {
|
|
48
|
+
path: z.string().describe("Workspace-relative file path."),
|
|
49
|
+
content: z.string().describe("UTF-8 file content."),
|
|
50
|
+
},
|
|
51
|
+
handler: async (input) => {
|
|
52
|
+
const denied = denyCrossWorkspace(input, ctx.workspaceId);
|
|
53
|
+
if (denied)
|
|
54
|
+
return denied;
|
|
55
|
+
const rel = str(input.path);
|
|
56
|
+
if (!rel)
|
|
57
|
+
return { ok: false, error: "path is required" };
|
|
58
|
+
if (typeof input.content !== "string")
|
|
59
|
+
return { ok: false, error: "content is required" };
|
|
60
|
+
let target;
|
|
61
|
+
try {
|
|
62
|
+
target = resolveWithin(ctx.workdir, rel);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
66
|
+
}
|
|
67
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
68
|
+
await writeFile(target, input.content);
|
|
69
|
+
return { ok: true };
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../../src/engines/capability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The out-of-process emissions file.
|
|
3
|
+
*
|
|
4
|
+
* An external-process engine (codex / a CLI) cannot share memory with the run
|
|
5
|
+
* that spawned it, so the runner-hosted stdio capability server persists what
|
|
6
|
+
* the run emitted to a JSON file OUTSIDE the sandbox tree — where the change
|
|
7
|
+
* set will not capture it — and the engine reads it back afterwards. That round
|
|
8
|
+
* trip is the whole mechanism, and it is generic.
|
|
9
|
+
*
|
|
10
|
+
* What it carries is **not** the kernel's business. This module moves an opaque
|
|
11
|
+
* JSON value; it does not know or check its shape. It previously declared an
|
|
12
|
+
* `Emissions { issues, knowledge }` interface, which put one application's run
|
|
13
|
+
* protocol inside the kernel — `write_file` changes are still excluded on
|
|
14
|
+
* purpose, because those DO belong in the tree and travel via the change set.
|
|
15
|
+
*/
|
|
16
|
+
/** Persist the current emissions (the stdio server rewrites the full state per call). */
|
|
17
|
+
export declare function writeEmissions(file: string, emissions: unknown): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Read back what the capability server persisted.
|
|
20
|
+
*
|
|
21
|
+
* Returns `undefined` for an absent or malformed file rather than an empty
|
|
22
|
+
* object: "nothing was written" and "something was written and it was empty"
|
|
23
|
+
* are different facts, and a defaulted `{}` would erase the difference. The
|
|
24
|
+
* caller casts to whatever its own capability surface agreed to write.
|
|
25
|
+
*/
|
|
26
|
+
export declare function readEmissions(file: string): Promise<unknown>;
|
|
27
|
+
//# sourceMappingURL=capabilityEmissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityEmissions.d.ts","sourceRoot":"","sources":["../../src/engines/capabilityEmissions.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH,yFAAyF;AACzF,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMlE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
/**
|
|
3
|
+
* The out-of-process emissions file.
|
|
4
|
+
*
|
|
5
|
+
* An external-process engine (codex / a CLI) cannot share memory with the run
|
|
6
|
+
* that spawned it, so the runner-hosted stdio capability server persists what
|
|
7
|
+
* the run emitted to a JSON file OUTSIDE the sandbox tree — where the change
|
|
8
|
+
* set will not capture it — and the engine reads it back afterwards. That round
|
|
9
|
+
* trip is the whole mechanism, and it is generic.
|
|
10
|
+
*
|
|
11
|
+
* What it carries is **not** the kernel's business. This module moves an opaque
|
|
12
|
+
* JSON value; it does not know or check its shape. It previously declared an
|
|
13
|
+
* `Emissions { issues, knowledge }` interface, which put one application's run
|
|
14
|
+
* protocol inside the kernel — `write_file` changes are still excluded on
|
|
15
|
+
* purpose, because those DO belong in the tree and travel via the change set.
|
|
16
|
+
*/
|
|
17
|
+
/** Persist the current emissions (the stdio server rewrites the full state per call). */
|
|
18
|
+
export async function writeEmissions(file, emissions) {
|
|
19
|
+
await writeFile(file, JSON.stringify(emissions));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Read back what the capability server persisted.
|
|
23
|
+
*
|
|
24
|
+
* Returns `undefined` for an absent or malformed file rather than an empty
|
|
25
|
+
* object: "nothing was written" and "something was written and it was empty"
|
|
26
|
+
* are different facts, and a defaulted `{}` would erase the difference. The
|
|
27
|
+
* caller casts to whatever its own capability surface agreed to write.
|
|
28
|
+
*/
|
|
29
|
+
export async function readEmissions(file) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(await readFile(file, "utf8"));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=capabilityEmissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityEmissions.js","sourceRoot":"","sources":["../../src/engines/capabilityEmissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEtD;;;;;;;;;;;;;;GAcG;AAEH,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,SAAkB;IACnE,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAA;AAClD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { McpSdkServerConfigWithInstance } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import type { CapabilityTool } from "./capability.js";
|
|
3
|
+
/**
|
|
4
|
+
* The MCP server name the kernel-hosted capability surface is registered under.
|
|
5
|
+
* Tools are therefore reachable by the model as `mcp__workspace__<tool>` — see
|
|
6
|
+
* {@link capabilityToolIds}. It names what the authority is scoped to (the run's
|
|
7
|
+
* workspace), not who is hosting it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CAPABILITY_SERVER_NAME = "workspace";
|
|
10
|
+
/** Fully-qualified tool ids the Agent SDK exposes for a capability server. */
|
|
11
|
+
export declare function capabilityToolIds(tools: CapabilityTool[]): string[];
|
|
12
|
+
/**
|
|
13
|
+
* Wrap the transport-neutral {@link CapabilityTool}s in an in-process Anthropic
|
|
14
|
+
* Agent SDK MCP server, so the Claude Code engine gets the exact same
|
|
15
|
+
* workspace-scoped authority the native engine has — no separate process, no
|
|
16
|
+
* network. The SDK is imported lazily (this module is only reached from the
|
|
17
|
+
* Claude Code driver, which never runs on a warm shared host).
|
|
18
|
+
*
|
|
19
|
+
* The capability handler is the security boundary; this adapter only marshals
|
|
20
|
+
* the SDK's parsed args into it and JSON-encodes the result back to the model.
|
|
21
|
+
*/
|
|
22
|
+
export declare function capabilitySdkServer(tools: CapabilityTool[]): Promise<McpSdkServerConfigWithInstance>;
|
|
23
|
+
//# sourceMappingURL=capabilityMcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityMcp.d.ts","sourceRoot":"","sources":["../../src/engines/capabilityMcp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAA;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,cAAc,CAAA;AAEjD,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,CAEnE;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,cAAc,EAAE,GACtB,OAAO,CAAC,8BAA8B,CAAC,CAezC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MCP server name the kernel-hosted capability surface is registered under.
|
|
3
|
+
* Tools are therefore reachable by the model as `mcp__workspace__<tool>` — see
|
|
4
|
+
* {@link capabilityToolIds}. It names what the authority is scoped to (the run's
|
|
5
|
+
* workspace), not who is hosting it.
|
|
6
|
+
*/
|
|
7
|
+
export const CAPABILITY_SERVER_NAME = "workspace";
|
|
8
|
+
/** Fully-qualified tool ids the Agent SDK exposes for a capability server. */
|
|
9
|
+
export function capabilityToolIds(tools) {
|
|
10
|
+
return tools.map((t) => `mcp__${CAPABILITY_SERVER_NAME}__${t.name}`);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Wrap the transport-neutral {@link CapabilityTool}s in an in-process Anthropic
|
|
14
|
+
* Agent SDK MCP server, so the Claude Code engine gets the exact same
|
|
15
|
+
* workspace-scoped authority the native engine has — no separate process, no
|
|
16
|
+
* network. The SDK is imported lazily (this module is only reached from the
|
|
17
|
+
* Claude Code driver, which never runs on a warm shared host).
|
|
18
|
+
*
|
|
19
|
+
* The capability handler is the security boundary; this adapter only marshals
|
|
20
|
+
* the SDK's parsed args into it and JSON-encodes the result back to the model.
|
|
21
|
+
*/
|
|
22
|
+
export async function capabilitySdkServer(tools) {
|
|
23
|
+
const { createSdkMcpServer, tool } = await import("@anthropic-ai/claude-agent-sdk");
|
|
24
|
+
return createSdkMcpServer({
|
|
25
|
+
name: CAPABILITY_SERVER_NAME,
|
|
26
|
+
version: "0.1.0",
|
|
27
|
+
tools: tools.map((cap) => tool(cap.name, cap.description, cap.schema, async (args) => {
|
|
28
|
+
const result = await cap.handler(args);
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
31
|
+
...(result.ok ? {} : { isError: true }),
|
|
32
|
+
};
|
|
33
|
+
})),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=capabilityMcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityMcp.js","sourceRoot":"","sources":["../../src/engines/capabilityMcp.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAA;AAEjD,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,sBAAsB,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;AACtE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAuB;IAEvB,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAA;IACnF,OAAO,kBAAkB,CAAC;QACxB,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACzD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YACtC,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzD,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;aACxC,CAAA;QACH,CAAC,CAAC,CACH;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
3
|
+
import type { CapabilityTool } from "./capability.js";
|
|
4
|
+
/**
|
|
5
|
+
* Hosts a capability surface as a standalone MCP server over an arbitrary
|
|
6
|
+
* transport — for engines that run as an EXTERNAL process (codex, or any CLI)
|
|
7
|
+
* and reach the run's authority through a configured stdio MCP server rather
|
|
8
|
+
* than an in-process SDK server.
|
|
9
|
+
*
|
|
10
|
+
* This is the generic mechanism only. It does not know which capabilities it is
|
|
11
|
+
* serving or what a call means: the tools are handed in, and `afterCall` is the
|
|
12
|
+
* hook an application uses to persist whatever the call accumulated, since a
|
|
13
|
+
* child process cannot share memory with the run that spawned it.
|
|
14
|
+
*
|
|
15
|
+
* Because the tool set is injected, the application owns the entrypoint script
|
|
16
|
+
* that the external engine spawns — a child process cannot be handed a closure.
|
|
17
|
+
* Build the server there and connect it with {@link serveCapability}.
|
|
18
|
+
*/
|
|
19
|
+
export interface CapabilityStdioOptions {
|
|
20
|
+
/** The capabilities to expose. Order is preserved in the advertised list. */
|
|
21
|
+
tools: CapabilityTool[];
|
|
22
|
+
/**
|
|
23
|
+
* Run after every handler call, successful or not. The usual job is to flush
|
|
24
|
+
* accumulated state to a file outside the sandbox so the spawning process can
|
|
25
|
+
* read it once the child exits.
|
|
26
|
+
*/
|
|
27
|
+
afterCall?: () => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/** The spawn contract an external engine fills in via the environment. */
|
|
30
|
+
export interface CapabilityStdioConfig {
|
|
31
|
+
workspaceId: string;
|
|
32
|
+
workdir: string;
|
|
33
|
+
/** Absolute path (OUTSIDE the sandbox) where a run's emissions are persisted. */
|
|
34
|
+
emissionsFile: string;
|
|
35
|
+
}
|
|
36
|
+
/** Build the capability MCP server for external-process hosting (not yet connected). */
|
|
37
|
+
export declare function buildCapabilityStdioServer(options: CapabilityStdioOptions): McpServer;
|
|
38
|
+
/** Connect a built capability server over the given transport (stdio in production). */
|
|
39
|
+
export declare function serveCapability(options: CapabilityStdioOptions, transport?: Transport): Promise<McpServer>;
|
|
40
|
+
/**
|
|
41
|
+
* Read the spawn contract from the environment the spawning engine sets. The
|
|
42
|
+
* variable names are part of that contract — see the codex engine, which writes
|
|
43
|
+
* them into the config it hands the external process.
|
|
44
|
+
*/
|
|
45
|
+
export declare function capabilityStdioConfigFromEnv(): CapabilityStdioConfig;
|
|
46
|
+
//# sourceMappingURL=capabilityStdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityStdio.d.ts","sourceRoot":"","sources":["../../src/engines/capabilityStdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGrD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,sBAAsB;IACrC,6EAA6E;IAC7E,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAChC;AAED,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,iFAAiF;IACjF,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,wFAAwF;AACxF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,sBAAsB,GAAG,SAAS,CAkBrF;AAED,wFAAwF;AACxF,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,GAAE,SAAsC,GAChD,OAAO,CAAC,SAAS,CAAC,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,qBAAqB,CAQpE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { CAPABILITY_SERVER_NAME } from "./capabilityMcp.js";
|
|
4
|
+
/** Build the capability MCP server for external-process hosting (not yet connected). */
|
|
5
|
+
export function buildCapabilityStdioServer(options) {
|
|
6
|
+
const server = new McpServer({ name: CAPABILITY_SERVER_NAME, version: "0.1.0" });
|
|
7
|
+
for (const cap of options.tools) {
|
|
8
|
+
server.registerTool(cap.name, { description: cap.description, inputSchema: cap.schema }, async (args) => {
|
|
9
|
+
const result = await cap.handler(args);
|
|
10
|
+
await options.afterCall?.();
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
13
|
+
...(result.ok ? {} : { isError: true }),
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return server;
|
|
18
|
+
}
|
|
19
|
+
/** Connect a built capability server over the given transport (stdio in production). */
|
|
20
|
+
export async function serveCapability(options, transport = new StdioServerTransport()) {
|
|
21
|
+
const server = buildCapabilityStdioServer(options);
|
|
22
|
+
await server.connect(transport);
|
|
23
|
+
return server;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read the spawn contract from the environment the spawning engine sets. The
|
|
27
|
+
* variable names are part of that contract — see the codex engine, which writes
|
|
28
|
+
* them into the config it hands the external process.
|
|
29
|
+
*/
|
|
30
|
+
export function capabilityStdioConfigFromEnv() {
|
|
31
|
+
const workspaceId = process.env.HARNESS_WORKSPACE_ID;
|
|
32
|
+
const workdir = process.env.HARNESS_WORKDIR;
|
|
33
|
+
const emissionsFile = process.env.HARNESS_EMISSIONS_FILE;
|
|
34
|
+
if (!workspaceId || !workdir || !emissionsFile) {
|
|
35
|
+
throw new Error("HARNESS_WORKSPACE_ID, HARNESS_WORKDIR and HARNESS_EMISSIONS_FILE are required");
|
|
36
|
+
}
|
|
37
|
+
return { workspaceId, workdir, emissionsFile };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=capabilityStdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityStdio.js","sourceRoot":"","sources":["../../src/engines/capabilityStdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAGhF,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAoC3D,wFAAwF;AACxF,MAAM,UAAU,0BAA0B,CAAC,OAA+B;IACxE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAEhF,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,CAAC,YAAY,CACjB,GAAG,CAAC,IAAI,EACR,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,EACzD,KAAK,EAAE,IAA6B,EAAE,EAAE;YACtC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YACtC,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,CAAA;YAC3B,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;aACxC,CAAA;QACH,CAAC,CACF,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+B,EAC/B,YAAuB,IAAI,oBAAoB,EAAE;IAEjD,MAAM,MAAM,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAA;IAClD,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC/B,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAA;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAA;IAC3C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAA;IACxD,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAA;IAClG,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,CAAA;AAChD,CAAC"}
|