@codeworksh/plugin 0.3.0-canary.72.1.gc93760de → 0.3.0-canary.79.1.g48358e0a
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/index.d.mts +2 -2
- package/index.mjs +1 -1
- package/mcp-DEWhnBQw.d.mts +122 -0
- package/package.json +7 -2
- package/plugin/mcp.d.mts +2 -0
- package/plugin/mcp.mjs +7 -0
- package/plugin/mcp.mjs.map +1 -0
- package/plugin/tool.d.mts +1 -1
- package/{plugin-XaYYRsX-.mjs → plugin-C3Qy4-Yx.mjs} +9 -3
- package/plugin-C3Qy4-Yx.mjs.map +1 -0
- package/{plugin-BhornEkR.d.mts → plugin-Cj56-eXk.d.mts} +17 -10
- package/plugin.d.mts +4 -3
- package/plugin.mjs +3 -2
- package/{settings-DGYWREuu.d.mts → settings-CxiAtEXT.d.mts} +22 -2
- package/settings.d.mts +2 -2
- package/settings.mjs +4 -0
- package/settings.mjs.map +1 -1
- package/tool/progress.d.mts +1 -1
- package/{tool-BRTCmPch.d.mts → tool-C7gcMoga.d.mts} +17 -3
- package/{tool-BZXrwclV.d.mts → tool-C9TzQ9nG.d.mts} +2 -2
- package/tool.d.mts +2 -2
- package/tool.mjs +30 -2
- package/tool.mjs.map +1 -1
- package/plugin-XaYYRsX-.mjs.map +0 -1
package/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { t as section_d_exports } from "./plugin/section.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as plugin_d_exports } from "./plugin-
|
|
2
|
+
import { b as tool_d_exports } from "./tool-C7gcMoga.mjs";
|
|
3
|
+
import { t as plugin_d_exports } from "./plugin-Cj56-eXk.mjs";
|
|
4
4
|
export { plugin_d_exports as Plugin, section_d_exports as Section, tool_d_exports as Tool };
|
package/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as plugin_exports } from "./plugin-
|
|
1
|
+
import { t as plugin_exports } from "./plugin-C3Qy4-Yx.mjs";
|
|
2
2
|
import { t as section_exports } from "./plugin/section.mjs";
|
|
3
3
|
import { t as tool_exports } from "./tool.mjs";
|
|
4
4
|
export { plugin_exports as Plugin, section_exports as Section, tool_exports as Tool };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
declare namespace mcp_d_exports {
|
|
2
|
+
export { Exposure, HttpServer, McpRegistry, OAuthConfig, Scope, ServerConfig, ServerPatch, StdioServer };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* MCP servers a session runs, as plugins see and edit them.
|
|
6
|
+
*
|
|
7
|
+
* The harness seeds the bucket from `mcp.json` (the user file, then the project's), `mcp` plugins
|
|
8
|
+
* edit it, and it freezes before the `tool` domain runs: the servers are settled before any tool
|
|
9
|
+
* exists. Only configuration lives here. Whether a server is connected changes on its own, at any
|
|
10
|
+
* moment, so it is never part of what a plugin reads during setup.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* How a server's tools reach the model.
|
|
14
|
+
*
|
|
15
|
+
* - `direct`: declared to the model like any other tool.
|
|
16
|
+
* - `codemode`: called from codemode scripts, never declared to the model.
|
|
17
|
+
* - `deferred`: declared once `toolsearch` loads them.
|
|
18
|
+
* - `hidden`: never offered to the model.
|
|
19
|
+
*
|
|
20
|
+
* Until codemode exists, `codemode` tools cannot be called. `codemode-deferred` in `mcp.json` is
|
|
21
|
+
* read as `codemode`.
|
|
22
|
+
*/
|
|
23
|
+
type Exposure = "direct" | "codemode" | "deferred" | "hidden";
|
|
24
|
+
/**
|
|
25
|
+
* Who shares one running instance of a server.
|
|
26
|
+
*
|
|
27
|
+
* - `session`: threads of one session at the same place share one.
|
|
28
|
+
* - `space`: sessions in the same space (sandbox and folder) share one.
|
|
29
|
+
* - `app`: every session shares one.
|
|
30
|
+
*/
|
|
31
|
+
type Scope = "session" | "space" | "app";
|
|
32
|
+
interface Base {
|
|
33
|
+
/** Default: `direct`. */
|
|
34
|
+
readonly exposure?: Exposure;
|
|
35
|
+
/**
|
|
36
|
+
* Exposure of single tools, overriding `exposure`. Keys are tool names as the server offers them,
|
|
37
|
+
* or patterns where `*` matches any characters. An exact name wins over patterns; among patterns
|
|
38
|
+
* the first match wins. `"exposure": "hidden"` with a few entries here exposes only those tools.
|
|
39
|
+
*/
|
|
40
|
+
readonly toolExposure?: Readonly<Record<string, Exposure>>;
|
|
41
|
+
/** `false` keeps the entry without connecting. Default: `true`. */
|
|
42
|
+
readonly enabled?: boolean;
|
|
43
|
+
/** Default: `session`. Share a server only when it is safe to share. */
|
|
44
|
+
readonly scope?: Scope;
|
|
45
|
+
/** Per-request timeout in seconds. Progress notifications from the server reset it. Default: 60. */
|
|
46
|
+
readonly timeout?: number;
|
|
47
|
+
/** What the server offers, in a sentence. */
|
|
48
|
+
readonly description?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A server the harness starts as a process on the host. `env` values may name environment
|
|
52
|
+
* variables (`${NAME}`) or be a command whose output is the value (`!command`).
|
|
53
|
+
*/
|
|
54
|
+
interface StdioServer extends Base {
|
|
55
|
+
readonly type?: "stdio";
|
|
56
|
+
/** One executable, not a shell command line. */
|
|
57
|
+
readonly command: string;
|
|
58
|
+
readonly args?: ReadonlyArray<string>;
|
|
59
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
60
|
+
/** Relative to the session's directory. */
|
|
61
|
+
readonly cwd?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* OAuth client settings, for servers that do not accept dynamic client registration or need a
|
|
65
|
+
* fixed redirect URI.
|
|
66
|
+
*/
|
|
67
|
+
interface OAuthConfig {
|
|
68
|
+
/** A pre-registered client id. Without it, the harness registers a client with the server. */
|
|
69
|
+
readonly clientId?: string;
|
|
70
|
+
/** Resolves like a header value. */
|
|
71
|
+
readonly clientSecret?: string;
|
|
72
|
+
/** Port of the loopback callback, for a client registered with a fixed redirect URI. */
|
|
73
|
+
readonly callbackPort?: number;
|
|
74
|
+
/**
|
|
75
|
+
* The redirect URI registered for `clientId`: `http` on `localhost`, `127.0.0.1` or `[::1]`.
|
|
76
|
+
* Without a port, the callback listens on `callbackPort` or a free port.
|
|
77
|
+
*/
|
|
78
|
+
readonly callbackUrl?: string;
|
|
79
|
+
/** Scopes to request, separated by spaces. Default: the scopes the server advertises. */
|
|
80
|
+
readonly scope?: string;
|
|
81
|
+
/** `client_name` sent with dynamic client registration. Default: `CodeWork`. */
|
|
82
|
+
readonly clientName?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Authorization server metadata (RFC 8414 or OpenID Connect discovery) to use instead of
|
|
85
|
+
* discovering it through the server. `https`, or `http` on a loopback host.
|
|
86
|
+
*/
|
|
87
|
+
readonly authServerMetadataUrl?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A Streamable HTTP server. `headers` values resolve like a stdio server's `env`.
|
|
91
|
+
*
|
|
92
|
+
* A server without an `Authorization` header or `auth` signs in with OAuth when it answers 401
|
|
93
|
+
* (`codework mcp login <name>`).
|
|
94
|
+
*/
|
|
95
|
+
interface HttpServer extends Base {
|
|
96
|
+
readonly type?: "http" | "streamable-http";
|
|
97
|
+
readonly url: string;
|
|
98
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
99
|
+
readonly oauth?: OAuthConfig;
|
|
100
|
+
/**
|
|
101
|
+
* Send a model provider's credential (its login token, else its API key) as the bearer instead
|
|
102
|
+
* of using OAuth. Only in the user `mcp.json`, and only to `https` URLs or loopback hosts.
|
|
103
|
+
*/
|
|
104
|
+
readonly auth?: {
|
|
105
|
+
readonly provider: string;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
type ServerConfig = StdioServer | HttpServer;
|
|
109
|
+
/** The settings a plugin can change on a server without restating where it runs. */
|
|
110
|
+
type ServerPatch = Pick<Base, "enabled" | "exposure" | "toolExposure" | "timeout" | "description">;
|
|
111
|
+
interface McpRegistry {
|
|
112
|
+
readonly list: () => ReadonlyArray<readonly [name: string, config: ServerConfig]>;
|
|
113
|
+
readonly get: (name: string) => ServerConfig | undefined;
|
|
114
|
+
/** Add a server or replace one. Throws on an invalid name or config. */
|
|
115
|
+
readonly set: (name: string, config: ServerConfig) => void;
|
|
116
|
+
/** Throws when no server has this name. */
|
|
117
|
+
readonly update: (name: string, patch: ServerPatch) => void;
|
|
118
|
+
readonly remove: (name: string) => void;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
export { Scope as a, StdioServer as c, OAuthConfig as i, mcp_d_exports as l, HttpServer as n, ServerConfig as o, McpRegistry as r, ServerPatch as s, Exposure as t };
|
|
122
|
+
//# sourceMappingURL=mcp-DEWhnBQw.d.mts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeworksh/plugin",
|
|
3
|
-
"version": "0.3.0-canary.
|
|
3
|
+
"version": "0.3.0-canary.79.1.g48358e0a",
|
|
4
4
|
"description": "SDK for building CodeWork plugins — the plugin, tool, and sandbox contracts shared with @codeworksh/harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -45,6 +45,11 @@
|
|
|
45
45
|
"import": "./plugin/prompt.mjs",
|
|
46
46
|
"default": "./plugin/prompt.mjs"
|
|
47
47
|
},
|
|
48
|
+
"./plugin/mcp": {
|
|
49
|
+
"types": "./plugin/mcp.d.mts",
|
|
50
|
+
"import": "./plugin/mcp.mjs",
|
|
51
|
+
"default": "./plugin/mcp.mjs"
|
|
52
|
+
},
|
|
48
53
|
"./plugin/section": {
|
|
49
54
|
"types": "./plugin/section.d.mts",
|
|
50
55
|
"import": "./plugin/section.mjs",
|
|
@@ -168,7 +173,7 @@
|
|
|
168
173
|
"uuidv7": "^1.2.1"
|
|
169
174
|
},
|
|
170
175
|
"peerDependencies": {
|
|
171
|
-
"@codeworksh/aikit": "0.12.1-canary.
|
|
176
|
+
"@codeworksh/aikit": "0.12.1-canary.79.1.g48358e0a",
|
|
172
177
|
"effect": "4.0.5"
|
|
173
178
|
}
|
|
174
179
|
}
|
package/plugin/mcp.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as Scope, c as StdioServer, i as OAuthConfig, n as HttpServer, o as ServerConfig, r as McpRegistry, s as ServerPatch, t as Exposure } from "../mcp-DEWhnBQw.mjs";
|
|
2
|
+
export { Exposure, HttpServer, McpRegistry, OAuthConfig, Scope, ServerConfig, ServerPatch, StdioServer };
|
package/plugin/mcp.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.mjs","names":[],"sources":["../../../src/plugin/mcp.ts"],"sourcesContent":["/**\n * MCP servers a session runs, as plugins see and edit them.\n *\n * The harness seeds the bucket from `mcp.json` (the user file, then the project's), `mcp` plugins\n * edit it, and it freezes before the `tool` domain runs: the servers are settled before any tool\n * exists. Only configuration lives here. Whether a server is connected changes on its own, at any\n * moment, so it is never part of what a plugin reads during setup.\n */\n\n/**\n * How a server's tools reach the model.\n *\n * - `direct`: declared to the model like any other tool.\n * - `codemode`: called from codemode scripts, never declared to the model.\n * - `deferred`: declared once `toolsearch` loads them.\n * - `hidden`: never offered to the model.\n *\n * Until codemode exists, `codemode` tools cannot be called. `codemode-deferred` in `mcp.json` is\n * read as `codemode`.\n */\nexport type Exposure = \"direct\" | \"codemode\" | \"deferred\" | \"hidden\";\n\n/**\n * Who shares one running instance of a server.\n *\n * - `session`: threads of one session at the same place share one.\n * - `space`: sessions in the same space (sandbox and folder) share one.\n * - `app`: every session shares one.\n */\nexport type Scope = \"session\" | \"space\" | \"app\";\n\ninterface Base {\n\t/** Default: `direct`. */\n\treadonly exposure?: Exposure;\n\t/**\n\t * Exposure of single tools, overriding `exposure`. Keys are tool names as the server offers them,\n\t * or patterns where `*` matches any characters. An exact name wins over patterns; among patterns\n\t * the first match wins. `\"exposure\": \"hidden\"` with a few entries here exposes only those tools.\n\t */\n\treadonly toolExposure?: Readonly<Record<string, Exposure>>;\n\t/** `false` keeps the entry without connecting. Default: `true`. */\n\treadonly enabled?: boolean;\n\t/** Default: `session`. Share a server only when it is safe to share. */\n\treadonly scope?: Scope;\n\t/** Per-request timeout in seconds. Progress notifications from the server reset it. Default: 60. */\n\treadonly timeout?: number;\n\t/** What the server offers, in a sentence. */\n\treadonly description?: string;\n}\n\n/**\n * A server the harness starts as a process on the host. `env` values may name environment\n * variables (`${NAME}`) or be a command whose output is the value (`!command`).\n */\nexport interface StdioServer extends Base {\n\treadonly type?: \"stdio\";\n\t/** One executable, not a shell command line. */\n\treadonly command: string;\n\treadonly args?: ReadonlyArray<string>;\n\treadonly env?: Readonly<Record<string, string>>;\n\t/** Relative to the session's directory. */\n\treadonly cwd?: string;\n}\n\n/**\n * OAuth client settings, for servers that do not accept dynamic client registration or need a\n * fixed redirect URI.\n */\nexport interface OAuthConfig {\n\t/** A pre-registered client id. Without it, the harness registers a client with the server. */\n\treadonly clientId?: string;\n\t/** Resolves like a header value. */\n\treadonly clientSecret?: string;\n\t/** Port of the loopback callback, for a client registered with a fixed redirect URI. */\n\treadonly callbackPort?: number;\n\t/**\n\t * The redirect URI registered for `clientId`: `http` on `localhost`, `127.0.0.1` or `[::1]`.\n\t * Without a port, the callback listens on `callbackPort` or a free port.\n\t */\n\treadonly callbackUrl?: string;\n\t/** Scopes to request, separated by spaces. Default: the scopes the server advertises. */\n\treadonly scope?: string;\n\t/** `client_name` sent with dynamic client registration. Default: `CodeWork`. */\n\treadonly clientName?: string;\n\t/**\n\t * Authorization server metadata (RFC 8414 or OpenID Connect discovery) to use instead of\n\t * discovering it through the server. `https`, or `http` on a loopback host.\n\t */\n\treadonly authServerMetadataUrl?: string;\n}\n\n/**\n * A Streamable HTTP server. `headers` values resolve like a stdio server's `env`.\n *\n * A server without an `Authorization` header or `auth` signs in with OAuth when it answers 401\n * (`codework mcp login <name>`).\n */\nexport interface HttpServer extends Base {\n\treadonly type?: \"http\" | \"streamable-http\";\n\treadonly url: string;\n\treadonly headers?: Readonly<Record<string, string>>;\n\treadonly oauth?: OAuthConfig;\n\t/**\n\t * Send a model provider's credential (its login token, else its API key) as the bearer instead\n\t * of using OAuth. Only in the user `mcp.json`, and only to `https` URLs or loopback hosts.\n\t */\n\treadonly auth?: { readonly provider: string };\n}\n\nexport type ServerConfig = StdioServer | HttpServer;\n\n/** The settings a plugin can change on a server without restating where it runs. */\nexport type ServerPatch = Pick<Base, \"enabled\" | \"exposure\" | \"toolExposure\" | \"timeout\" | \"description\">;\n\nexport interface McpRegistry {\n\treadonly list: () => ReadonlyArray<readonly [name: string, config: ServerConfig]>;\n\treadonly get: (name: string) => ServerConfig | undefined;\n\t/** Add a server or replace one. Throws on an invalid name or config. */\n\treadonly set: (name: string, config: ServerConfig) => void;\n\t/** Throws when no server has this name. */\n\treadonly update: (name: string, patch: ServerPatch) => void;\n\treadonly remove: (name: string) => void;\n}\n"],"mappings":""}
|
package/plugin/tool.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ToolAfterResult, c as ToolBeforeResult, d as ToolRegistry, f as ToolResultContent, i as ToolAfterFn, l as ToolDefPatch, n as ToolAddOptions, o as ToolBefore, r as ToolAfter, s as ToolBeforeFn, t as HookReturn, u as ToolRegistration } from "../tool-
|
|
1
|
+
import { a as ToolAfterResult, c as ToolBeforeResult, d as ToolRegistry, f as ToolResultContent, i as ToolAfterFn, l as ToolDefPatch, n as ToolAddOptions, o as ToolBefore, r as ToolAfter, s as ToolBeforeFn, t as HookReturn, u as ToolRegistration } from "../tool-C9TzQ9nG.mjs";
|
|
2
2
|
export { HookReturn, ToolAddOptions, ToolAfter, ToolAfterFn, ToolAfterResult, ToolBefore, ToolBeforeFn, ToolBeforeResult, ToolDefPatch, ToolRegistration, ToolRegistry, ToolResultContent };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { t as mcp_exports } from "./plugin/mcp.mjs";
|
|
2
3
|
import { t as prompt_exports } from "./plugin/prompt.mjs";
|
|
3
4
|
import { t as section_exports } from "./plugin/section.mjs";
|
|
4
5
|
import { t as tool_exports } from "./plugin/tool.mjs";
|
|
@@ -17,12 +18,16 @@ import { t as tool_exports } from "./plugin/tool.mjs";
|
|
|
17
18
|
* composition actually happens -- a plugin patching another's tool, or appending to the prompt a
|
|
18
19
|
* previous one rendered, is written next to it and deliberately after it.
|
|
19
20
|
*
|
|
21
|
+
* `mcp` runs first: the MCP servers a session runs are settled before any tool exists, because
|
|
22
|
+
* their tools join the tool registry before the `tool` domain starts.
|
|
23
|
+
*
|
|
20
24
|
* Kept as data so a later release can add a domain, or make the order configurable, without
|
|
21
25
|
* touching the loader: `{ tool: 1, skill: 2, prompt: 3 }` needs no code change here.
|
|
22
26
|
*/
|
|
23
27
|
const domains = {
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
mcp: 1,
|
|
29
|
+
tool: 2,
|
|
30
|
+
prompt: 3
|
|
26
31
|
};
|
|
27
32
|
/** Sort key for a plugin: its domain first, then where it was written. */
|
|
28
33
|
const rank = (kind) => domains[kind];
|
|
@@ -30,6 +35,7 @@ const define = (plugin) => plugin;
|
|
|
30
35
|
//#endregion
|
|
31
36
|
//#region src/plugin.ts
|
|
32
37
|
var plugin_exports = /* @__PURE__ */ __exportAll({
|
|
38
|
+
Mcp: () => mcp_exports,
|
|
33
39
|
Prompt: () => prompt_exports,
|
|
34
40
|
Section: () => section_exports,
|
|
35
41
|
Tool: () => tool_exports,
|
|
@@ -40,4 +46,4 @@ var plugin_exports = /* @__PURE__ */ __exportAll({
|
|
|
40
46
|
//#endregion
|
|
41
47
|
export { rank as i, define as n, domains as r, plugin_exports as t };
|
|
42
48
|
|
|
43
|
-
//# sourceMappingURL=plugin-
|
|
49
|
+
//# sourceMappingURL=plugin-C3Qy4-Yx.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-C3Qy4-Yx.mjs","names":[],"sources":["../../src/plugin/plugin.ts","../../src/plugin.ts"],"sourcesContent":["import type { Effect } from \"effect\";\nimport type { Definition } from \"../event.ts\";\nimport type { Service as LocationService } from \"../location.ts\";\nimport type { SandboxIO } from \"../sandbox/io.ts\";\nimport type { SharedPluginContext } from \"./context.ts\";\nimport type { PluginOptions } from \"./ref.ts\";\n\n/**\n * The domains a plugin can extend, and the order the harness runs them in.\n *\n * Order is declared, not positional. A plugin's place used to come from where its entry sat in\n * the `plugins` array, which is unknowable when the entry is written: a user's settings file and\n * a project's are edited by different people at different times, and neither can see the other's\n * order. Since a prompt plugin indexes the tools registered before it, that made a tool added\n * from settings invisible in the system prompt, with no way to fix it from a settings file.\n *\n * A plugin instead says which domain it extends, and the harness runs the domains in this order.\n * Entries within one domain keep the order they were written in, because that is where\n * composition actually happens -- a plugin patching another's tool, or appending to the prompt a\n * previous one rendered, is written next to it and deliberately after it.\n *\n * `mcp` runs first: the MCP servers a session runs are settled before any tool exists, because\n * their tools join the tool registry before the `tool` domain starts.\n *\n * Kept as data so a later release can add a domain, or make the order configurable, without\n * touching the loader: `{ tool: 1, skill: 2, prompt: 3 }` needs no code change here.\n */\nexport const domains = { mcp: 1, tool: 2, prompt: 3 } as const;\n\nexport type PluginKind = keyof typeof domains;\n\n/** Sort key for a plugin: its domain first, then where it was written. */\nexport const rank = (kind: PluginKind) => domains[kind];\n\nexport type Mount = SandboxIO.Provides | LocationService;\nexport interface Plugin {\n\treadonly id: string;\n\t/**\n\t * The domain this plugin extends, which decides when it runs: every `mcp` plugin is set up\n\t * before any `tool` plugin, and every `tool` plugin before any `prompt` plugin, whichever\n\t * settings layer each came from, so a prompt plugin always sees the complete tool set. Plugins within one domain run in the order they were\n\t * written.\n\t */\n\treadonly kind: PluginKind;\n\t/**\n\t * Event definitions this plugin publishes. Declared rather than registered at\n\t * runtime so they are known before the event system builds, and so a bad type\n\t * fails the boot instead of the first publish. Types must be namespaced\n\t * `plugin.<id>.*`.\n\t */\n\treadonly events?: ReadonlyArray<Definition>;\n\t/**\n\t * Off until a user asks for it. An `optIn` plugin is selected like any other but runs only\n\t * when a settings entry turns it on: `{ \"plugin\": \"<id>\", \"enabled\": true }`.\n\t */\n\treadonly optIn?: boolean;\n\t/**\n\t * `options` is this plugin's own configuration block, `{}` when its entry carried none.\n\t * Unvalidated: the harness never looks inside it, so a plugin checks whatever shape it\n\t * documents. It is a second argument rather than a context field so `ctx` stays one object\n\t * shared by every plugin in the turn.\n\t */\n\treadonly setup: (\n\t\tctx: SharedPluginContext,\n\t\toptions: PluginOptions,\n\t) => void | Promise<void> | Effect.Effect<void, unknown, Mount>;\n}\n\nexport const define = (plugin: Plugin): Plugin => plugin;\n","/**\n * The plugin authoring surface.\n *\n * Everything a third-party plugin needs to describe itself and to write into the harness during\n * `setup`, and nothing about how the harness finds, installs or runs it. Loading, the store and\n * the `.npmrc` anchoring stay in `@codeworksh/harness`, which imports this same module — so a\n * plugin and its host agree on one set of types rather than two that happen to match.\n */\nexport type { Config, Events, Paths, PromptResolver, SharedPluginContext } from \"./plugin/context.ts\";\nexport { define, domains, type Mount, type Plugin, type PluginKind, rank } from \"./plugin/plugin.ts\";\nexport * as Mcp from \"./plugin/mcp.ts\";\nexport * as Prompt from \"./plugin/prompt.ts\";\nexport * as Section from \"./plugin/section.ts\";\nexport type { PluginOptions, PluginPatch, PluginRef, PluginSpec } from \"./plugin/ref.ts\";\nexport type { PluginRegistry } from \"./plugin/registry.ts\";\nexport * as Tool from \"./plugin/tool.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAa,UAAU;CAAE,KAAK;CAAG,MAAM;CAAG,QAAQ;AAAE;;AAKpD,MAAa,QAAQ,SAAqB,QAAQ;AAoClD,MAAa,UAAU,WAA2B"}
|
|
@@ -2,10 +2,11 @@ import { i as Definition, o as Payload, r as Data, s as PublishOptions } from ".
|
|
|
2
2
|
import { n as SessionID, r as ThreadID } from "./ids-CpPeP5Ks.mjs";
|
|
3
3
|
import { o as Service, r as Info } from "./location-Q39els63.mjs";
|
|
4
4
|
import { f as io_d_exports, i as Identity, s as Provides } from "./io-Br9WZTsG.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { l as mcp_d_exports, r as McpRegistry } from "./mcp-DEWhnBQw.mjs";
|
|
6
|
+
import { i as Info$1 } from "./settings-CxiAtEXT.mjs";
|
|
6
7
|
import { t as section_d_exports } from "./plugin/section.mjs";
|
|
7
8
|
import { n as prompt_d_exports, t as PromptRegistry } from "./prompt-DWaA5ZXj.mjs";
|
|
8
|
-
import { d as ToolRegistry, p as tool_d_exports } from "./tool-
|
|
9
|
+
import { d as ToolRegistry, p as tool_d_exports } from "./tool-C9TzQ9nG.mjs";
|
|
9
10
|
import { Model } from "@codeworksh/aikit";
|
|
10
11
|
import { Effect } from "effect";
|
|
11
12
|
//#region src/plugin/registry.d.ts
|
|
@@ -17,6 +18,8 @@ import { Effect } from "effect";
|
|
|
17
18
|
* effective tool catalog and the final system prompt — is the harness's job, not the contract's.
|
|
18
19
|
*/
|
|
19
20
|
interface PluginRegistry {
|
|
21
|
+
/** Writable during the `mcp` domain only; later domains read the servers it settled. */
|
|
22
|
+
readonly mcp: McpRegistry;
|
|
20
23
|
readonly tools: ToolRegistry;
|
|
21
24
|
readonly prompt: PromptRegistry;
|
|
22
25
|
}
|
|
@@ -111,23 +114,27 @@ type PluginRef = PluginSpec | PluginPatch;
|
|
|
111
114
|
* composition actually happens -- a plugin patching another's tool, or appending to the prompt a
|
|
112
115
|
* previous one rendered, is written next to it and deliberately after it.
|
|
113
116
|
*
|
|
117
|
+
* `mcp` runs first: the MCP servers a session runs are settled before any tool exists, because
|
|
118
|
+
* their tools join the tool registry before the `tool` domain starts.
|
|
119
|
+
*
|
|
114
120
|
* Kept as data so a later release can add a domain, or make the order configurable, without
|
|
115
121
|
* touching the loader: `{ tool: 1, skill: 2, prompt: 3 }` needs no code change here.
|
|
116
122
|
*/
|
|
117
123
|
declare const domains: {
|
|
118
|
-
readonly
|
|
119
|
-
readonly
|
|
124
|
+
readonly mcp: 1;
|
|
125
|
+
readonly tool: 2;
|
|
126
|
+
readonly prompt: 3;
|
|
120
127
|
};
|
|
121
128
|
type PluginKind = keyof typeof domains;
|
|
122
129
|
/** Sort key for a plugin: its domain first, then where it was written. */
|
|
123
|
-
declare const rank: (kind: PluginKind) => 1 | 2;
|
|
130
|
+
declare const rank: (kind: PluginKind) => 1 | 2 | 3;
|
|
124
131
|
type Mount = Provides | Service;
|
|
125
132
|
interface Plugin {
|
|
126
133
|
readonly id: string;
|
|
127
134
|
/**
|
|
128
|
-
* The domain this plugin extends, which decides when it runs: every `
|
|
129
|
-
* before any `
|
|
130
|
-
* always sees the complete tool set. Plugins within one domain run in the order they were
|
|
135
|
+
* The domain this plugin extends, which decides when it runs: every `mcp` plugin is set up
|
|
136
|
+
* before any `tool` plugin, and every `tool` plugin before any `prompt` plugin, whichever
|
|
137
|
+
* settings layer each came from, so a prompt plugin always sees the complete tool set. Plugins within one domain run in the order they were
|
|
131
138
|
* written.
|
|
132
139
|
*/
|
|
133
140
|
readonly kind: PluginKind;
|
|
@@ -153,8 +160,8 @@ interface Plugin {
|
|
|
153
160
|
}
|
|
154
161
|
declare const define: (plugin: Plugin) => Plugin;
|
|
155
162
|
declare namespace plugin_d_exports {
|
|
156
|
-
export { Config, Events, Mount, Paths, Plugin, PluginKind, PluginOptions, PluginPatch, PluginRef, PluginRegistry, PluginSpec, prompt_d_exports as Prompt, PromptResolver, section_d_exports as Section, SharedPluginContext, tool_d_exports as Tool, define, domains, rank };
|
|
163
|
+
export { Config, Events, mcp_d_exports as Mcp, Mount, Paths, Plugin, PluginKind, PluginOptions, PluginPatch, PluginRef, PluginRegistry, PluginSpec, prompt_d_exports as Prompt, PromptResolver, section_d_exports as Section, SharedPluginContext, tool_d_exports as Tool, define, domains, rank };
|
|
157
164
|
}
|
|
158
165
|
//#endregion
|
|
159
166
|
export { PluginRegistry as _, define as a, PluginOptions as c, PluginSpec as d, Config as f, SharedPluginContext as g, PromptResolver as h, PluginKind as i, PluginPatch as l, Paths as m, Mount as n, domains as o, Events as p, Plugin as r, rank as s, plugin_d_exports as t, PluginRef as u };
|
|
160
|
-
//# sourceMappingURL=plugin-
|
|
167
|
+
//# sourceMappingURL=plugin-Cj56-eXk.d.mts.map
|
package/plugin.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { l as mcp_d_exports } from "./mcp-DEWhnBQw.mjs";
|
|
1
2
|
import { t as section_d_exports } from "./plugin/section.mjs";
|
|
2
3
|
import { n as prompt_d_exports } from "./prompt-DWaA5ZXj.mjs";
|
|
3
|
-
import { p as tool_d_exports } from "./tool-
|
|
4
|
-
import { _ as PluginRegistry, a as define, c as PluginOptions, d as PluginSpec, f as Config, g as SharedPluginContext, h as PromptResolver, i as PluginKind, l as PluginPatch, m as Paths, n as Mount, o as domains, p as Events, r as Plugin, s as rank, u as PluginRef } from "./plugin-
|
|
5
|
-
export { type Config, type Events, type Mount, type Paths, type Plugin, type PluginKind, type PluginOptions, type PluginPatch, type PluginRef, type PluginRegistry, type PluginSpec, prompt_d_exports as Prompt, type PromptResolver, section_d_exports as Section, type SharedPluginContext, tool_d_exports as Tool, define, domains, rank };
|
|
4
|
+
import { p as tool_d_exports } from "./tool-C9TzQ9nG.mjs";
|
|
5
|
+
import { _ as PluginRegistry, a as define, c as PluginOptions, d as PluginSpec, f as Config, g as SharedPluginContext, h as PromptResolver, i as PluginKind, l as PluginPatch, m as Paths, n as Mount, o as domains, p as Events, r as Plugin, s as rank, u as PluginRef } from "./plugin-Cj56-eXk.mjs";
|
|
6
|
+
export { type Config, type Events, mcp_d_exports as Mcp, type Mount, type Paths, type Plugin, type PluginKind, type PluginOptions, type PluginPatch, type PluginRef, type PluginRegistry, type PluginSpec, prompt_d_exports as Prompt, type PromptResolver, section_d_exports as Section, type SharedPluginContext, tool_d_exports as Tool, define, domains, rank };
|
package/plugin.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { i as rank, n as define, r as domains } from "./plugin-
|
|
1
|
+
import { i as rank, n as define, r as domains } from "./plugin-C3Qy4-Yx.mjs";
|
|
2
|
+
import { t as mcp_exports } from "./plugin/mcp.mjs";
|
|
2
3
|
import { t as prompt_exports } from "./plugin/prompt.mjs";
|
|
3
4
|
import { t as section_exports } from "./plugin/section.mjs";
|
|
4
5
|
import { t as tool_exports } from "./plugin/tool.mjs";
|
|
5
|
-
export { prompt_exports as Prompt, section_exports as Section, tool_exports as Tool, define, domains, rank };
|
|
6
|
+
export { mcp_exports as Mcp, prompt_exports as Prompt, section_exports as Section, tool_exports as Tool, define, domains, rank };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { o as ServerConfig } from "./mcp-DEWhnBQw.mjs";
|
|
1
2
|
import { Model } from "@codeworksh/aikit";
|
|
2
3
|
import { Schema } from "effect";
|
|
3
4
|
//#region src/settings.d.ts
|
|
@@ -106,6 +107,7 @@ declare const ModelEntry: Schema.decodeTo<Schema.declare<{
|
|
|
106
107
|
supportsThinkingLevel?: boolean;
|
|
107
108
|
supportsToolSearch?: boolean;
|
|
108
109
|
supportsAdditionalTools?: boolean;
|
|
110
|
+
supportsMidConvoSystemMessages?: boolean;
|
|
109
111
|
supportsStrictMode?: boolean;
|
|
110
112
|
supportsOpenAIGrammarTools?: boolean;
|
|
111
113
|
supportsThinkingTokenBudget?: boolean;
|
|
@@ -187,6 +189,7 @@ declare const ModelEntry: Schema.decodeTo<Schema.declare<{
|
|
|
187
189
|
supportsThinkingLevel?: boolean;
|
|
188
190
|
supportsToolSearch?: boolean;
|
|
189
191
|
supportsAdditionalTools?: boolean;
|
|
192
|
+
supportsMidConvoSystemMessages?: boolean;
|
|
190
193
|
supportsStrictMode?: boolean;
|
|
191
194
|
supportsOpenAIGrammarTools?: boolean;
|
|
192
195
|
supportsThinkingTokenBudget?: boolean;
|
|
@@ -365,6 +368,7 @@ declare const Patch: Schema.Struct<{
|
|
|
365
368
|
supportsThinkingLevel?: boolean;
|
|
366
369
|
supportsToolSearch?: boolean;
|
|
367
370
|
supportsAdditionalTools?: boolean;
|
|
371
|
+
supportsMidConvoSystemMessages?: boolean;
|
|
368
372
|
supportsStrictMode?: boolean;
|
|
369
373
|
supportsOpenAIGrammarTools?: boolean;
|
|
370
374
|
supportsThinkingTokenBudget?: boolean;
|
|
@@ -446,6 +450,7 @@ declare const Patch: Schema.Struct<{
|
|
|
446
450
|
supportsThinkingLevel?: boolean;
|
|
447
451
|
supportsToolSearch?: boolean;
|
|
448
452
|
supportsAdditionalTools?: boolean;
|
|
453
|
+
supportsMidConvoSystemMessages?: boolean;
|
|
449
454
|
supportsStrictMode?: boolean;
|
|
450
455
|
supportsOpenAIGrammarTools?: boolean;
|
|
451
456
|
supportsThinkingTokenBudget?: boolean;
|
|
@@ -560,6 +565,20 @@ interface DeclaredModel {
|
|
|
560
565
|
readonly entry: Model.Info;
|
|
561
566
|
readonly file: string;
|
|
562
567
|
}
|
|
568
|
+
/** One server from an `mcp.json`, and the file that defined it. */
|
|
569
|
+
interface McpServer {
|
|
570
|
+
readonly name: string;
|
|
571
|
+
readonly config: ServerConfig;
|
|
572
|
+
readonly file: string;
|
|
573
|
+
/** The project `mcp.json` whose entry overrides this user server's `enabled` or exposure. */
|
|
574
|
+
readonly override?: string;
|
|
575
|
+
}
|
|
576
|
+
/** The `mcp.json` layers: the user file, then the project's, whose entries replace same-named ones. */
|
|
577
|
+
interface McpSettings {
|
|
578
|
+
readonly servers: ReadonlyArray<McpServer>;
|
|
579
|
+
/** Files and entries that could not be used. Each is skipped; everything else still loads. */
|
|
580
|
+
readonly errors: ReadonlyArray<string>;
|
|
581
|
+
}
|
|
563
582
|
interface Info {
|
|
564
583
|
/**
|
|
565
584
|
* Plugin entries added to the harness selection, in order: every layer's entries, lowest
|
|
@@ -583,9 +602,10 @@ interface Info {
|
|
|
583
602
|
readonly toolExecution: ToolExecution;
|
|
584
603
|
};
|
|
585
604
|
readonly retry: RetryPolicy;
|
|
605
|
+
readonly mcp: McpSettings;
|
|
586
606
|
}
|
|
587
607
|
/** Let aikit supply model-aware generation defaults. */
|
|
588
608
|
declare const defaults: Info;
|
|
589
609
|
//#endregion
|
|
590
|
-
export {
|
|
591
|
-
//# sourceMappingURL=settings-
|
|
610
|
+
export { ToolExecution as _, KeyReference as a, requestFields as b, Model$1 as c, Patch as d, PluginEntry as f, ThinkingLevel as g, RetryPolicy as h, Info as i, ModelEntry as l, Retry as m, Declared as n, McpServer as o, PluginPatch as p, DeclaredModel as r, McpSettings as s, Block as t, ModelProtocol as u, defaults as v, keyName as y };
|
|
611
|
+
//# sourceMappingURL=settings-CxiAtEXT.d.mts.map
|
package/settings.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as
|
|
2
|
-
export { Block, Declared, DeclaredModel, Info, KeyReference, Model, ModelEntry, ModelProtocol, Patch, PluginEntry, PluginPatch, Retry, RetryPolicy, ThinkingLevel, ToolExecution, defaults, keyName, requestFields };
|
|
1
|
+
import { _ as ToolExecution, a as KeyReference, b as requestFields, c as Model, d as Patch, f as PluginEntry, g as ThinkingLevel, h as RetryPolicy, i as Info, l as ModelEntry, m as Retry, n as Declared, o as McpServer, p as PluginPatch, r as DeclaredModel, s as McpSettings, t as Block, u as ModelProtocol, v as defaults, y as keyName } from "./settings-CxiAtEXT.mjs";
|
|
2
|
+
export { Block, Declared, DeclaredModel, Info, KeyReference, McpServer, McpSettings, Model, ModelEntry, ModelProtocol, Patch, PluginEntry, PluginPatch, Retry, RetryPolicy, ThinkingLevel, ToolExecution, defaults, keyName, requestFields };
|
package/settings.mjs
CHANGED
package/settings.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.mjs","names":["AikitModel"],"sources":["../../src/settings.ts"],"sourcesContent":["import { Model as AikitModel, type Protocol } from \"@codeworksh/aikit\";\nimport { Effect, Schema, type SchemaAST, SchemaGetter, SchemaIssue } from \"effect\";\nimport { isAikitModelInfo, NonNegativeInt, validateAikitModelInfo } from \"./schema.ts\";\n\nexport const ThinkingLevel = Schema.Literals(Object.values(AikitModel.ThinkingLevelEnum));\nexport const ToolExecution = Schema.Literals([\"sequential\", \"parallel\"]);\nexport type ToolExecution = typeof ToolExecution.Type;\nconst Budgets = Schema.Record(\n\tSchema.Literals(Object.values(AikitModel.ThinkingLevelEnum).filter((level) => level !== \"off\")),\n\tSchema.optional(Schema.Finite),\n);\n\n/** Aikit does not export its request schema; keep this routing surface checked against its public types. */\nexport const requestFields = {\n\ttemperature: Schema.optional(Schema.Finite),\n\tmaxTokens: Schema.optional(Schema.Finite),\n\tcacheRetention: Schema.optional(Schema.Literals([\"none\", \"short\", \"long\"])),\n\theaders: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n\ttimeoutMs: Schema.optional(Schema.Finite),\n\tidleTimeoutMs: Schema.optional(Schema.Finite),\n\tmaxRetries: Schema.optional(Schema.Finite),\n\tmetadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n\tthinkingBudgets: Schema.optional(Budgets),\n\tbaseURL: Schema.optional(Schema.String),\n\tmethod: Schema.optional(Schema.Literals(Object.values(AikitModel.APIMethodEnum))),\n} satisfies Record<\n\t| Exclude<keyof Protocol.CommonOptions, \"signal\" | \"sessionId\" | \"reasoning\" | \"apiKey\" | \"onPayload\">\n\t| \"baseURL\"\n\t| \"method\",\n\tSchema.Top\n>;\n\n/**\n * An API key named, never written: `\"${NAME}\"`, read from the host process environment when the\n * model is called. Settings only ever hold the variable's name.\n */\nconst keyReference = /^\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}$/;\nconst keyReferenceError = 'apiKey must reference an environment variable, e.g. \"${OPENAI_API_KEY}\"';\nexport const KeyReference = Schema.String.check(\n\tSchema.makeFilter((value) => keyReference.test(value) || keyReferenceError),\n);\n\n/** The variable a `\"${NAME}\"` reference names. */\nexport const keyName = (reference: string): string => keyReference.exec(reference)?.[1] ?? reference;\n\nconst reserved = new Set([\n\t\"toolChoice\",\n\t\"activeTools\",\n\t\"provider\",\n\t\"id\",\n\t\"signal\",\n\t\"sessionId\",\n\t\"reasoning\",\n\t\"modelId\",\n\t\"onPayload\",\n\t\"api\",\n\t\"npm\",\n\t\"providerOptionsKey\",\n\t\"compat\",\n\t\"thinkingLevelMap\",\n]);\n\n/** The wire protocol a model speaks, which a catalog entry may have wrong for a local endpoint. */\nexport const ModelProtocol = Schema.Literals(Object.values(AikitModel.KnownProviderEnum));\n\nexport const Block = Schema.StructWithRest(\n\tSchema.Struct({\n\t\t...requestFields,\n\t\tprotocol: Schema.optional(ModelProtocol),\n\t\tthinkingLevel: Schema.optional(ThinkingLevel),\n\t\ttoolExecution: Schema.optional(ToolExecution),\n\t\tcontextWindow: Schema.optional(Schema.Finite),\n\t\t/** Which environment variable holds the key for this model: `\"${NAME}\"`. */\n\t\tapiKey: Schema.optional(KeyReference),\n\t\textras: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n\t}),\n\t[Schema.Record(Schema.String, Schema.Unknown)],\n).check(\n\tSchema.makeFilter(\n\t\t(value) => Object.keys(value).every((key) => !reserved.has(key)) || \"Reserved configuration key in model options\",\n\t),\n);\nexport type Block = typeof Block.Type;\n\nexport const Model = Schema.Struct({\n\tprovider: Schema.optional(Schema.String),\n\tid: Schema.optional(Schema.String),\n\tthinkingLevel: Schema.optional(ThinkingLevel),\n\ttoolExecution: Schema.optional(ToolExecution),\n\tthinkingBudgets: Schema.optional(Budgets),\n\toptions: Schema.optional(Block),\n\tproviderOptions: Schema.optional(Schema.Record(Schema.String, Schema.Record(Schema.String, Block))),\n});\nconst reasonOf = (cause: unknown): string => (cause instanceof Error ? cause.message : String(cause));\n\nconst decodeModelEntry = (value: unknown, options: SchemaAST.ParseOptions) =>\n\tEffect.try({\n\t\ttry: () => {\n\t\t\tconst entry = validateAikitModelInfo(value, \"models entry\");\n\t\t\tif (entry.provider.key !== undefined && !keyReference.test(entry.provider.key)) {\n\t\t\t\tthrow new Error(`models entry ${entry.provider.id}/${entry.id}: provider.key: ${keyReferenceError}`);\n\t\t\t}\n\t\t\treturn entry;\n\t\t},\n\t\tcatch: (cause) => new SchemaIssue.InvalidValue({ message: reasonOf(cause) }, value, options),\n\t});\n\n/**\n * A catalog entry in settings: an aikit `Model.Info`, read exactly like an entry of the generated\n * catalog. The one difference is `provider.key`, which must be a `\"${NAME}\"` reference.\n */\nexport const ModelEntry = Schema.Unknown.pipe(\n\tSchema.decodeTo(Schema.declare<AikitModel.Info>(isAikitModelInfo, { expected: \"aikit Model.Info\" }), {\n\t\tdecode: SchemaGetter.transformEffect(decodeModelEntry),\n\t\tencode: SchemaGetter.transformEffect(decodeModelEntry),\n\t}),\n);\nexport type ModelEntry = typeof ModelEntry.Type;\n\n/** A module to load: a path, a `file:` URL, or a package spec. */\nconst PluginReference = Schema.String.check(Schema.isNonEmpty());\n/**\n * Configuration for a plugin something else already selected, named by its ID (`plugin`) or by\n * its registered module string (`package`). It never loads anything: an entry naming a plugin\n * that is not in the selection is ignored.\n */\nconst config = {\n\tenabled: Schema.optional(Schema.Boolean),\n\toptions: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n};\nexport const PluginPatch = Schema.Union(\n\t[Schema.Struct({ plugin: PluginReference, ...config }), Schema.Struct({ package: PluginReference, ...config })],\n\t// `oneOf`, so an entry carrying both keys is a decode failure rather than one of them being\n\t// quietly dropped -- naming a plugin two ways at once says two different things.\n\t{ mode: \"oneOf\" },\n);\nexport const PluginEntry = Schema.Union([PluginReference, PluginPatch]);\nexport type PluginEntry = typeof PluginEntry.Type;\n\n/**\n * Agent-level retry of a turn whose provider request failed transiently (rate limit, overload,\n * 5xx, dropped connection). Delays double from `baseDelayMs` and stop growing at `maxDelayMs`;\n * a server that asks for a longer wait than `maxDelayMs` is not retried. `maxRetries: 0` is off.\n *\n * Separate from `model.options.maxRetries`, which retries inside the provider SDK and defaults to\n * 0 so that the two do not multiply, and so a quota error reaches the loop instead of being retried.\n */\nexport const Retry = Schema.Struct({\n\tmaxRetries: Schema.optional(NonNegativeInt),\n\tbaseDelayMs: Schema.optional(NonNegativeInt),\n\tmaxDelayMs: Schema.optional(NonNegativeInt),\n});\nexport interface RetryPolicy {\n\treadonly maxRetries: number;\n\treadonly baseDelayMs: number;\n\treadonly maxDelayMs: number;\n}\n\nexport const Patch = Schema.Struct({\n\t$schema: Schema.optional(Schema.String),\n\tplugins: Schema.optional(Schema.Array(PluginEntry)),\n\tmodel: Schema.optional(Model),\n\tmodels: Schema.optional(Schema.Array(ModelEntry)),\n\tretry: Schema.optional(Retry),\n});\nexport type Patch = typeof Patch.Type;\n\n/**\n * One plugin entry, and where it came from.\n *\n * Flattening every layer's `plugins` into one array loses the file that declared each entry, and\n * that cannot be recovered afterwards: two layers may declare the same string, so attribution is\n * genuinely gone rather than merely inconvenient. Three things need it -- anchoring a relative\n * path, naming the declaring layer in `plugin list`, and the missing-plugin diagnostic -- so the\n * loaded shape carries it from the start.\n *\n * In simple terms:\n * `written` - is what module the developer is declaring - what\n * `file` - where the module is being declared - where\n * `entry` - the resolved path of the module, relative to the `file`; especially needed for local.\n *\n * Example:\n * written: \"@acme/x@^1\"\n * entry: \"@acme/x@^1\"\n * file: \"/Users/me/.codework/settings.jsonc\"\n *\n * written: \"./plugins/mine.mjs\"\n * entry: \"/Users/me/.codework/plugins/mine.mjs\"\n * file: \"/Users/me/.codework/settings.jsonc\"\n */\nexport interface Declared {\n\t/** The entry exactly as the file spells it, which is the string a person will search for. */\n\treadonly written: PluginEntry;\n\t/** The same entry with any relative path anchored to the directory of its declaring file. */\n\treadonly entry: PluginEntry;\n\t/** The settings file that declared it. */\n\treadonly file: string;\n}\n\n/** A `models` entry, and the settings file that declared it. */\nexport interface DeclaredModel {\n\treadonly entry: AikitModel.Info;\n\treadonly file: string;\n}\n\nexport interface Info {\n\t/**\n\t * Plugin entries added to the harness selection, in order: every layer's entries, lowest\n\t * priority first, so a project's list extends the user's rather than replacing it.\n\t *\n\t * Anchored, and stripped of provenance: this is the list the loader consumes. {@link Info.declared}\n\t * is the same list with the file each entry came from.\n\t */\n\treadonly plugins: ReadonlyArray<PluginEntry>;\n\t/** {@link Info.plugins}, with the origin of each entry. Same order, same length. */\n\treadonly declared: ReadonlyArray<Declared>;\n\t/**\n\t * Catalog entries from every layer, lowest priority first. Applied over the generated catalog\n\t * in this order, so for one `provider.id` + `id` the last entry wins.\n\t */\n\treadonly models: ReadonlyArray<DeclaredModel>;\n\treadonly model: typeof Model.Type & {\n\t\treadonly provider: string;\n\t\treadonly id: string;\n\t\treadonly thinkingLevel: AikitModel.ThinkingLevel;\n\t\treadonly toolExecution: ToolExecution;\n\t};\n\treadonly retry: RetryPolicy;\n}\n\n/** Let aikit supply model-aware generation defaults. */\nexport const defaults: Info = {\n\tplugins: [],\n\tdeclared: [],\n\tmodels: [],\n\tmodel: {\n\t\tprovider: \"openai\",\n\t\tid: \"gpt-5.6-luna\",\n\t\tthinkingLevel: \"medium\",\n\t\ttoolExecution: \"sequential\",\n\t\toptions: { timeoutMs: 3_600_000, idleTimeoutMs: 300_000, maxRetries: 0 },\n\t},\n\tretry: { maxRetries: 3, baseDelayMs: 2_000, maxDelayMs: 60_000 },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"settings.mjs","names":["AikitModel"],"sources":["../../src/settings.ts"],"sourcesContent":["import { Model as AikitModel, type Protocol } from \"@codeworksh/aikit\";\nimport { Effect, Schema, type SchemaAST, SchemaGetter, SchemaIssue } from \"effect\";\nimport type { ServerConfig } from \"./plugin/mcp.ts\";\nimport { isAikitModelInfo, NonNegativeInt, validateAikitModelInfo } from \"./schema.ts\";\n\nexport const ThinkingLevel = Schema.Literals(Object.values(AikitModel.ThinkingLevelEnum));\nexport const ToolExecution = Schema.Literals([\"sequential\", \"parallel\"]);\nexport type ToolExecution = typeof ToolExecution.Type;\nconst Budgets = Schema.Record(\n\tSchema.Literals(Object.values(AikitModel.ThinkingLevelEnum).filter((level) => level !== \"off\")),\n\tSchema.optional(Schema.Finite),\n);\n\n/** Aikit does not export its request schema; keep this routing surface checked against its public types. */\nexport const requestFields = {\n\ttemperature: Schema.optional(Schema.Finite),\n\tmaxTokens: Schema.optional(Schema.Finite),\n\tcacheRetention: Schema.optional(Schema.Literals([\"none\", \"short\", \"long\"])),\n\theaders: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n\ttimeoutMs: Schema.optional(Schema.Finite),\n\tidleTimeoutMs: Schema.optional(Schema.Finite),\n\tmaxRetries: Schema.optional(Schema.Finite),\n\tmetadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n\tthinkingBudgets: Schema.optional(Budgets),\n\tbaseURL: Schema.optional(Schema.String),\n\tmethod: Schema.optional(Schema.Literals(Object.values(AikitModel.APIMethodEnum))),\n} satisfies Record<\n\t| Exclude<keyof Protocol.CommonOptions, \"signal\" | \"sessionId\" | \"reasoning\" | \"apiKey\" | \"onPayload\">\n\t| \"baseURL\"\n\t| \"method\",\n\tSchema.Top\n>;\n\n/**\n * An API key named, never written: `\"${NAME}\"`, read from the host process environment when the\n * model is called. Settings only ever hold the variable's name.\n */\nconst keyReference = /^\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}$/;\nconst keyReferenceError = 'apiKey must reference an environment variable, e.g. \"${OPENAI_API_KEY}\"';\nexport const KeyReference = Schema.String.check(\n\tSchema.makeFilter((value) => keyReference.test(value) || keyReferenceError),\n);\n\n/** The variable a `\"${NAME}\"` reference names. */\nexport const keyName = (reference: string): string => keyReference.exec(reference)?.[1] ?? reference;\n\nconst reserved = new Set([\n\t\"toolChoice\",\n\t\"activeTools\",\n\t\"provider\",\n\t\"id\",\n\t\"signal\",\n\t\"sessionId\",\n\t\"reasoning\",\n\t\"modelId\",\n\t\"onPayload\",\n\t\"api\",\n\t\"npm\",\n\t\"providerOptionsKey\",\n\t\"compat\",\n\t\"thinkingLevelMap\",\n]);\n\n/** The wire protocol a model speaks, which a catalog entry may have wrong for a local endpoint. */\nexport const ModelProtocol = Schema.Literals(Object.values(AikitModel.KnownProviderEnum));\n\nexport const Block = Schema.StructWithRest(\n\tSchema.Struct({\n\t\t...requestFields,\n\t\tprotocol: Schema.optional(ModelProtocol),\n\t\tthinkingLevel: Schema.optional(ThinkingLevel),\n\t\ttoolExecution: Schema.optional(ToolExecution),\n\t\tcontextWindow: Schema.optional(Schema.Finite),\n\t\t/** Which environment variable holds the key for this model: `\"${NAME}\"`. */\n\t\tapiKey: Schema.optional(KeyReference),\n\t\textras: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n\t}),\n\t[Schema.Record(Schema.String, Schema.Unknown)],\n).check(\n\tSchema.makeFilter(\n\t\t(value) => Object.keys(value).every((key) => !reserved.has(key)) || \"Reserved configuration key in model options\",\n\t),\n);\nexport type Block = typeof Block.Type;\n\nexport const Model = Schema.Struct({\n\tprovider: Schema.optional(Schema.String),\n\tid: Schema.optional(Schema.String),\n\tthinkingLevel: Schema.optional(ThinkingLevel),\n\ttoolExecution: Schema.optional(ToolExecution),\n\tthinkingBudgets: Schema.optional(Budgets),\n\toptions: Schema.optional(Block),\n\tproviderOptions: Schema.optional(Schema.Record(Schema.String, Schema.Record(Schema.String, Block))),\n});\nconst reasonOf = (cause: unknown): string => (cause instanceof Error ? cause.message : String(cause));\n\nconst decodeModelEntry = (value: unknown, options: SchemaAST.ParseOptions) =>\n\tEffect.try({\n\t\ttry: () => {\n\t\t\tconst entry = validateAikitModelInfo(value, \"models entry\");\n\t\t\tif (entry.provider.key !== undefined && !keyReference.test(entry.provider.key)) {\n\t\t\t\tthrow new Error(`models entry ${entry.provider.id}/${entry.id}: provider.key: ${keyReferenceError}`);\n\t\t\t}\n\t\t\treturn entry;\n\t\t},\n\t\tcatch: (cause) => new SchemaIssue.InvalidValue({ message: reasonOf(cause) }, value, options),\n\t});\n\n/**\n * A catalog entry in settings: an aikit `Model.Info`, read exactly like an entry of the generated\n * catalog. The one difference is `provider.key`, which must be a `\"${NAME}\"` reference.\n */\nexport const ModelEntry = Schema.Unknown.pipe(\n\tSchema.decodeTo(Schema.declare<AikitModel.Info>(isAikitModelInfo, { expected: \"aikit Model.Info\" }), {\n\t\tdecode: SchemaGetter.transformEffect(decodeModelEntry),\n\t\tencode: SchemaGetter.transformEffect(decodeModelEntry),\n\t}),\n);\nexport type ModelEntry = typeof ModelEntry.Type;\n\n/** A module to load: a path, a `file:` URL, or a package spec. */\nconst PluginReference = Schema.String.check(Schema.isNonEmpty());\n/**\n * Configuration for a plugin something else already selected, named by its ID (`plugin`) or by\n * its registered module string (`package`). It never loads anything: an entry naming a plugin\n * that is not in the selection is ignored.\n */\nconst config = {\n\tenabled: Schema.optional(Schema.Boolean),\n\toptions: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n};\nexport const PluginPatch = Schema.Union(\n\t[Schema.Struct({ plugin: PluginReference, ...config }), Schema.Struct({ package: PluginReference, ...config })],\n\t// `oneOf`, so an entry carrying both keys is a decode failure rather than one of them being\n\t// quietly dropped -- naming a plugin two ways at once says two different things.\n\t{ mode: \"oneOf\" },\n);\nexport const PluginEntry = Schema.Union([PluginReference, PluginPatch]);\nexport type PluginEntry = typeof PluginEntry.Type;\n\n/**\n * Agent-level retry of a turn whose provider request failed transiently (rate limit, overload,\n * 5xx, dropped connection). Delays double from `baseDelayMs` and stop growing at `maxDelayMs`;\n * a server that asks for a longer wait than `maxDelayMs` is not retried. `maxRetries: 0` is off.\n *\n * Separate from `model.options.maxRetries`, which retries inside the provider SDK and defaults to\n * 0 so that the two do not multiply, and so a quota error reaches the loop instead of being retried.\n */\nexport const Retry = Schema.Struct({\n\tmaxRetries: Schema.optional(NonNegativeInt),\n\tbaseDelayMs: Schema.optional(NonNegativeInt),\n\tmaxDelayMs: Schema.optional(NonNegativeInt),\n});\nexport interface RetryPolicy {\n\treadonly maxRetries: number;\n\treadonly baseDelayMs: number;\n\treadonly maxDelayMs: number;\n}\n\nexport const Patch = Schema.Struct({\n\t$schema: Schema.optional(Schema.String),\n\tplugins: Schema.optional(Schema.Array(PluginEntry)),\n\tmodel: Schema.optional(Model),\n\tmodels: Schema.optional(Schema.Array(ModelEntry)),\n\tretry: Schema.optional(Retry),\n});\nexport type Patch = typeof Patch.Type;\n\n/**\n * One plugin entry, and where it came from.\n *\n * Flattening every layer's `plugins` into one array loses the file that declared each entry, and\n * that cannot be recovered afterwards: two layers may declare the same string, so attribution is\n * genuinely gone rather than merely inconvenient. Three things need it -- anchoring a relative\n * path, naming the declaring layer in `plugin list`, and the missing-plugin diagnostic -- so the\n * loaded shape carries it from the start.\n *\n * In simple terms:\n * `written` - is what module the developer is declaring - what\n * `file` - where the module is being declared - where\n * `entry` - the resolved path of the module, relative to the `file`; especially needed for local.\n *\n * Example:\n * written: \"@acme/x@^1\"\n * entry: \"@acme/x@^1\"\n * file: \"/Users/me/.codework/settings.jsonc\"\n *\n * written: \"./plugins/mine.mjs\"\n * entry: \"/Users/me/.codework/plugins/mine.mjs\"\n * file: \"/Users/me/.codework/settings.jsonc\"\n */\nexport interface Declared {\n\t/** The entry exactly as the file spells it, which is the string a person will search for. */\n\treadonly written: PluginEntry;\n\t/** The same entry with any relative path anchored to the directory of its declaring file. */\n\treadonly entry: PluginEntry;\n\t/** The settings file that declared it. */\n\treadonly file: string;\n}\n\n/** A `models` entry, and the settings file that declared it. */\nexport interface DeclaredModel {\n\treadonly entry: AikitModel.Info;\n\treadonly file: string;\n}\n\n/** One server from an `mcp.json`, and the file that defined it. */\nexport interface McpServer {\n\treadonly name: string;\n\treadonly config: ServerConfig;\n\treadonly file: string;\n\t/** The project `mcp.json` whose entry overrides this user server's `enabled` or exposure. */\n\treadonly override?: string;\n}\n\n/** The `mcp.json` layers: the user file, then the project's, whose entries replace same-named ones. */\nexport interface McpSettings {\n\treadonly servers: ReadonlyArray<McpServer>;\n\t/** Files and entries that could not be used. Each is skipped; everything else still loads. */\n\treadonly errors: ReadonlyArray<string>;\n}\n\nexport interface Info {\n\t/**\n\t * Plugin entries added to the harness selection, in order: every layer's entries, lowest\n\t * priority first, so a project's list extends the user's rather than replacing it.\n\t *\n\t * Anchored, and stripped of provenance: this is the list the loader consumes. {@link Info.declared}\n\t * is the same list with the file each entry came from.\n\t */\n\treadonly plugins: ReadonlyArray<PluginEntry>;\n\t/** {@link Info.plugins}, with the origin of each entry. Same order, same length. */\n\treadonly declared: ReadonlyArray<Declared>;\n\t/**\n\t * Catalog entries from every layer, lowest priority first. Applied over the generated catalog\n\t * in this order, so for one `provider.id` + `id` the last entry wins.\n\t */\n\treadonly models: ReadonlyArray<DeclaredModel>;\n\treadonly model: typeof Model.Type & {\n\t\treadonly provider: string;\n\t\treadonly id: string;\n\t\treadonly thinkingLevel: AikitModel.ThinkingLevel;\n\t\treadonly toolExecution: ToolExecution;\n\t};\n\treadonly retry: RetryPolicy;\n\treadonly mcp: McpSettings;\n}\n\n/** Let aikit supply model-aware generation defaults. */\nexport const defaults: Info = {\n\tplugins: [],\n\tdeclared: [],\n\tmodels: [],\n\tmodel: {\n\t\tprovider: \"openai\",\n\t\tid: \"gpt-5.6-luna\",\n\t\tthinkingLevel: \"medium\",\n\t\ttoolExecution: \"sequential\",\n\t\toptions: { timeoutMs: 3_600_000, idleTimeoutMs: 300_000, maxRetries: 0 },\n\t},\n\tretry: { maxRetries: 3, baseDelayMs: 2_000, maxDelayMs: 60_000 },\n\tmcp: { servers: [], errors: [] },\n};\n"],"mappings":"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"}
|
package/tool/progress.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as ToolProgressPartial, S as ToolProgress, T as noop, w as make, x as IToolProgress } from "../tool-C7gcMoga.mjs";
|
|
2
2
|
export { IToolProgress, ToolProgress, ToolProgressPartial, make, noop };
|
|
@@ -26,7 +26,7 @@ declare const make$1: (report: IToolProgress["report"]) => Layer.Layer<ToolProgr
|
|
|
26
26
|
/** Drops every update — the default until the executor wires a live event sink. */
|
|
27
27
|
declare const noop: Layer.Layer<ToolProgress>;
|
|
28
28
|
declare namespace tool_d_exports {
|
|
29
|
-
export { AnyToolDef, AnyToolImpl, Handler, ModelContent, RegisteredTool, ToolCallContext, ToolDef, ToolExposure, ToolImpl, declared, define, implement, make, provide, register, toAikitTool, toProviderJsonSchema };
|
|
29
|
+
export { AnyToolDef, AnyToolImpl, Handler, ModelContent, RegisteredTool, ToolCallContext, ToolDef, ToolExposure, ToolImpl, declared, define, fromJsonSchema, implement, isFromJsonSchema, make, provide, register, toAikitTool, toProviderJsonSchema };
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* The tool definition + handler model.
|
|
@@ -160,6 +160,20 @@ declare const register: <Name extends string, Params extends Schema.Top, Success
|
|
|
160
160
|
* registry never has to unify anyone's `R`.
|
|
161
161
|
*/
|
|
162
162
|
declare const provide: <Name extends string, Params extends Schema.Top, Success extends Schema.Top, Failure extends Schema.Top, R>(impl: ToolImpl<Name, Params, Success, Failure, R | ToolProgress>, layer: Layer.Layer<R>) => RegisteredTool;
|
|
163
|
+
/**
|
|
164
|
+
* Parameters from a JSON Schema someone else wrote, such as an MCP server's `inputSchema`. The
|
|
165
|
+
* provider receives it exactly as written; arguments are validated against its Effect translation,
|
|
166
|
+
* `pattern`s included: the user chose the server. A schema the translation cannot express (an
|
|
167
|
+
* external `$ref`, a pattern invalid in Unicode mode) validates nothing, since rejecting arguments
|
|
168
|
+
* the schema allows would be worse than letting the server check them.
|
|
169
|
+
*/
|
|
170
|
+
declare const fromJsonSchema: (schema: Record<string, unknown>) => Schema.Top;
|
|
171
|
+
/**
|
|
172
|
+
* Whether `schema` came from {@link fromJsonSchema}. Its arguments are checked as JSON Schema checks
|
|
173
|
+
* them: a key a closed object does not declare is an error, not dropped, since the tool receives the
|
|
174
|
+
* arguments as written.
|
|
175
|
+
*/
|
|
176
|
+
declare const isFromJsonSchema: (schema: Schema.Top) => boolean;
|
|
163
177
|
/**
|
|
164
178
|
* Derive a provider-safe JSON Schema object from an Effect Schema. This is the
|
|
165
179
|
* single boundary that crosses into the provider wire; if a provider rejects a
|
|
@@ -173,5 +187,5 @@ declare const toProviderJsonSchema: (schema: Schema.Top) => Record<string, unkno
|
|
|
173
187
|
*/
|
|
174
188
|
declare const toAikitTool: (def: AnyToolDef) => Message.Tool;
|
|
175
189
|
//#endregion
|
|
176
|
-
export {
|
|
177
|
-
//# sourceMappingURL=tool-
|
|
190
|
+
export { ToolProgressPartial as C, ToolProgress as S, noop as T, register as _, RegisteredTool as a, tool_d_exports as b, ToolExposure as c, define as d, fromJsonSchema as f, provide as g, make as h, ModelContent as i, ToolImpl as l, isFromJsonSchema as m, AnyToolImpl as n, ToolCallContext as o, implement as p, Handler as r, ToolDef as s, AnyToolDef as t, declared as u, toAikitTool as v, make$1 as w, IToolProgress as x, toProviderJsonSchema as y };
|
|
191
|
+
//# sourceMappingURL=tool-C7gcMoga.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as RegisteredTool, i as ModelContent, t as AnyToolDef } from "./tool-
|
|
1
|
+
import { a as RegisteredTool, i as ModelContent, t as AnyToolDef } from "./tool-C7gcMoga.mjs";
|
|
2
2
|
import { Effect, Schema } from "effect";
|
|
3
3
|
declare namespace tool_d_exports {
|
|
4
4
|
export { HookReturn, ToolAddOptions, ToolAfter, ToolAfterFn, ToolAfterResult, ToolBefore, ToolBeforeFn, ToolBeforeResult, ToolDefPatch, ToolRegistration, ToolRegistry, ToolResultContent };
|
|
@@ -284,4 +284,4 @@ interface ToolRegistry {
|
|
|
284
284
|
}
|
|
285
285
|
//#endregion
|
|
286
286
|
export { ToolAfterResult as a, ToolBeforeResult as c, ToolRegistry as d, ToolResultContent as f, ToolAfterFn as i, ToolDefPatch as l, ToolAddOptions as n, ToolBefore as o, tool_d_exports as p, ToolAfter as r, ToolBeforeFn as s, HookReturn as t, ToolRegistration as u };
|
|
287
|
-
//# sourceMappingURL=tool-
|
|
287
|
+
//# sourceMappingURL=tool-C9TzQ9nG.d.mts.map
|
package/tool.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as
|
|
2
|
-
export { AnyToolDef, AnyToolImpl, Handler, ModelContent, RegisteredTool, ToolCallContext, ToolDef, ToolExposure, ToolImpl, declared, define, implement, make, provide, register, toAikitTool, toProviderJsonSchema };
|
|
1
|
+
import { _ as register, a as RegisteredTool, c as ToolExposure, d as define, f as fromJsonSchema, g as provide, h as make, i as ModelContent, l as ToolImpl, m as isFromJsonSchema, n as AnyToolImpl, o as ToolCallContext, p as implement, r as Handler, s as ToolDef, t as AnyToolDef, u as declared, v as toAikitTool, y as toProviderJsonSchema } from "./tool-C7gcMoga.mjs";
|
|
2
|
+
export { AnyToolDef, AnyToolImpl, Handler, ModelContent, RegisteredTool, ToolCallContext, ToolDef, ToolExposure, ToolImpl, declared, define, fromJsonSchema, implement, isFromJsonSchema, make, provide, register, toAikitTool, toProviderJsonSchema };
|
package/tool.mjs
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
2
|
import { ToolExecutionError } from "./tool/error.mjs";
|
|
3
|
-
import { Effect, Schema, SchemaAST } from "effect";
|
|
3
|
+
import { Effect, JsonSchema, Schema, SchemaAST, SchemaRepresentation } from "effect";
|
|
4
4
|
//#region src/tool.ts
|
|
5
5
|
var tool_exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
ToolCallContext: () => ToolCallContext,
|
|
7
7
|
ToolExposure: () => ToolExposure,
|
|
8
8
|
declared: () => declared,
|
|
9
9
|
define: () => define,
|
|
10
|
+
fromJsonSchema: () => fromJsonSchema,
|
|
10
11
|
implement: () => implement,
|
|
12
|
+
isFromJsonSchema: () => isFromJsonSchema,
|
|
11
13
|
make: () => make,
|
|
12
14
|
provide: () => provide,
|
|
13
15
|
register: () => register,
|
|
@@ -67,12 +69,38 @@ const register = (impl) => toRegistered(impl.definition, impl.handler);
|
|
|
67
69
|
* registry never has to unify anyone's `R`.
|
|
68
70
|
*/
|
|
69
71
|
const provide = (impl, layer) => toRegistered(impl.definition, ((params, ctx) => impl.handler(params, ctx).pipe(Effect.provide(layer))));
|
|
72
|
+
const providerJsonSchema = "codework/providerJsonSchema";
|
|
73
|
+
/**
|
|
74
|
+
* Parameters from a JSON Schema someone else wrote, such as an MCP server's `inputSchema`. The
|
|
75
|
+
* provider receives it exactly as written; arguments are validated against its Effect translation,
|
|
76
|
+
* `pattern`s included: the user chose the server. A schema the translation cannot express (an
|
|
77
|
+
* external `$ref`, a pattern invalid in Unicode mode) validates nothing, since rejecting arguments
|
|
78
|
+
* the schema allows would be worse than letting the server check them.
|
|
79
|
+
*/
|
|
80
|
+
const fromJsonSchema = (schema) => {
|
|
81
|
+
return (() => {
|
|
82
|
+
try {
|
|
83
|
+
const draft07 = typeof schema.$schema === "string" && schema.$schema.includes("draft-07") || "definitions" in schema;
|
|
84
|
+
return SchemaRepresentation.fromJsonSchemaDocument(draft07 ? JsonSchema.fromSchemaDraft07(schema) : JsonSchema.fromSchemaDraft2020_12(schema), { patterns: "apply" });
|
|
85
|
+
} catch {
|
|
86
|
+
return Schema.Unknown;
|
|
87
|
+
}
|
|
88
|
+
})().annotate({ [providerJsonSchema]: schema });
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Whether `schema` came from {@link fromJsonSchema}. Its arguments are checked as JSON Schema checks
|
|
92
|
+
* them: a key a closed object does not declare is an error, not dropped, since the tool receives the
|
|
93
|
+
* arguments as written.
|
|
94
|
+
*/
|
|
95
|
+
const isFromJsonSchema = (schema) => SchemaAST.resolveAt(providerJsonSchema)(schema.ast) !== void 0;
|
|
70
96
|
/**
|
|
71
97
|
* Derive a provider-safe JSON Schema object from an Effect Schema. This is the
|
|
72
98
|
* single boundary that crosses into the provider wire; if a provider rejects a
|
|
73
99
|
* construct, fix it here. Draft-07 inlines the root (no top-level `$ref`).
|
|
74
100
|
*/
|
|
75
101
|
const toProviderJsonSchema = (schema) => {
|
|
102
|
+
const written = SchemaAST.resolveAt(providerJsonSchema)(schema.ast);
|
|
103
|
+
if (written !== void 0) return written;
|
|
76
104
|
const encoded = SchemaAST.toEncoded(schema.ast);
|
|
77
105
|
if (SchemaAST.isObjects(encoded) && encoded.propertySignatures.length === 0 && encoded.indexSignatures.length === 0) return {
|
|
78
106
|
type: "object",
|
|
@@ -93,6 +121,6 @@ const toAikitTool = (def) => ({
|
|
|
93
121
|
...def.constrainedSampling === void 0 ? {} : { constrainedSampling: def.constrainedSampling }
|
|
94
122
|
});
|
|
95
123
|
//#endregion
|
|
96
|
-
export { ToolCallContext, ToolExposure, declared, define, implement, make, provide, register, tool_exports as t, toAikitTool, toProviderJsonSchema };
|
|
124
|
+
export { ToolCallContext, ToolExposure, declared, define, fromJsonSchema, implement, isFromJsonSchema, make, provide, register, tool_exports as t, toAikitTool, toProviderJsonSchema };
|
|
97
125
|
|
|
98
126
|
//# sourceMappingURL=tool.mjs.map
|
package/tool.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.mjs","names":[],"sources":["../../src/tool.ts"],"sourcesContent":["import type { Message } from \"@codeworksh/aikit\";\nimport { Effect, type Layer, Schema, SchemaAST } from \"effect\";\nimport type { TSchema } from \"typebox\";\nimport { ToolExecutionError } from \"./tool/error.ts\";\nimport type { ToolProgress } from \"./tool/progress.ts\";\n\n/**\n * The tool definition + handler model.\n *\n * A tool definition is pure, serializable data: name, description, and Effect\n * Schema for parameters / success / failure. Execution is a separate `Handler`\n * — an `Effect` whose capability dependencies (e.g. `ToolShell`) live in its\n * requirements `R`, provided by a Layer at runtime. Separating the two is the\n * main testing win: assert on the definition as plain data, and run the handler\n * against a stub capability Layer.\n *\n * Effect Schema is the single source of truth. {@link toAikitTool} derives a\n * provider-safe JSON Schema object for the aikit wire view; the harness\n * decode/encodes arguments and results with Effect Schema natively (it does not\n * use aikit's Typebox validators).\n */\n\n/** What the model reads next turn (the `content` side of content/details). */\nexport type ModelContent = ReadonlyArray<Message.TextContent | Message.ImageContent>;\n\n/** Per-call metadata handed to a handler instead of positional args. */\nexport const ToolCallContext = Schema.Struct({\n\tcallID: Schema.String,\n\ttoolName: Schema.String,\n\trawArgs: Schema.Record(Schema.String, Schema.Unknown),\n\t/** Input modalities of the model the call answers, e.g. `[\"text\", \"image\"]`. */\n\tmodelInput: Schema.optional(Schema.Array(Schema.Literals([\"text\", \"image\"]))),\n});\nexport type ToolCallContext = typeof ToolCallContext.Type;\n\n/**\n * Where a tool is reachable. `direct` and `model` tools are declared to the model each turn;\n * `model` ones are never callable from other tools. `codemode` and `deferred` tools stay off the\n * wire until loaded, and `hidden` ones never reach the model.\n */\nexport const ToolExposure = Schema.Literals([\"direct\", \"model\", \"codemode\", \"deferred\", \"hidden\"]);\nexport type ToolExposure = typeof ToolExposure.Type;\n\n/** Whether a tool is declared to the model every turn. Omitted exposure means `direct`. */\nexport const declared = (def: { readonly exposure?: ToolExposure }): boolean =>\n\tdef.exposure === undefined || def.exposure === \"direct\" || def.exposure === \"model\";\n\n/**\n * A pure tool definition. Parametrised over the *schema* instances so the\n * decoded parameter/success/failure types can be recovered via `[\"Type\"]`.\n */\nexport interface ToolDef<\n\tName extends string = string,\n\tParams extends Schema.Top = Schema.Top,\n\tSuccess extends Schema.Top = Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n> {\n\treadonly name: Name;\n\treadonly description: string;\n\t/** Human-readable display label (kept from the previous `AgentTool`). */\n\treadonly label?: string;\n\t/**\n\t * A short one-line summary for compact tool listings (e.g. a system-prompt tool index),\n\t * distinct from the fuller `description`.\n\t */\n\treadonly promptSnippet?: string;\n\t/** Optional guideline bullets appended to the default system prompt Guidelines section when this tool is active. */\n\treadonly promptGuidelines?: ReadonlyArray<string>;\n\t/** Where the tool is reachable. Omit → `direct`. */\n\treadonly exposure?: ToolExposure;\n\t/**\n\t * Repair argument shapes models commonly send before they are validated against\n\t * `parameters`. Return a copy; a throw makes the arguments invalid.\n\t */\n\treadonly prepareArguments?: (args: unknown) => unknown;\n\treadonly parameters: Params;\n\t/**\n\t * How the provider constrains the generated arguments. `{ type: \"json_schema\", strict: \"prefer\" }` sends\n\t * `parameters` in strict mode where the provider can express it and falls back to non-strict otherwise.\n\t */\n\treadonly constrainedSampling?: Message.Tool[\"constrainedSampling\"];\n\treadonly success: Success;\n\t/** Declared, model-visible failures (typed). Omit for tools that cannot fail expectedly. */\n\treadonly failure?: Failure;\n\t/** Render success for the model. Omit → executor falls back to JSON text. */\n\treadonly encodeContent?: (success: Success[\"Type\"]) => ModelContent;\n\t/** Render an expected failure for the model. Omit → executor falls back to JSON text. */\n\treadonly encodeFailureContent?: (failure: Failure[\"Type\"]) => ModelContent;\n\t/**\n\t * The `details` kept with a success, for UIs and programmatic consumers. Omit → the encoded\n\t * success. Set it when `encodeContent` already carries the payload, so it is not stored twice.\n\t */\n\treadonly encodeDetails?: (success: Success[\"Type\"]) => unknown;\n}\n\n/** A handler: validated params + context → typed success or typed failure. */\nexport type Handler<Params extends Schema.Top, Success extends Schema.Top, Failure extends Schema.Top, R = never> = (\n\tparams: Params[\"Type\"],\n\tctx: ToolCallContext,\n) => Effect.Effect<Success[\"Type\"], Failure[\"Type\"], R>;\n\n/** A definition paired with its handler (the unit the executor runs). */\nexport interface ToolImpl<\n\tName extends string = string,\n\tParams extends Schema.Top = Schema.Top,\n\tSuccess extends Schema.Top = Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n\tR = never,\n> {\n\treadonly definition: ToolDef<Name, Params, Success, Failure>;\n\treadonly handler: Handler<Params, Success, Failure, R>;\n}\n\n// Heterogeneous-collection aliases. `any` for the schema generics keeps handlers\n// of differing parameter types assignable into one array (the precise generics\n// live on the authoring helpers below).\n// biome-ignore lint/suspicious/noExplicitAny: erased schema generics for storage\nexport type AnyToolDef = ToolDef<string, any, any, any>;\n// biome-ignore lint/suspicious/noExplicitAny: erased schema generics for storage\nexport type AnyToolImpl<R = never> = ToolImpl<string, any, any, any, R>;\n\ninterface DefineInput<\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n> {\n\treadonly name: Name;\n\treadonly description: string;\n\treadonly label?: string;\n\treadonly promptSnippet?: string;\n\treadonly promptGuidelines?: ReadonlyArray<string>;\n\treadonly exposure?: ToolExposure;\n\treadonly prepareArguments?: (args: unknown) => unknown;\n\treadonly parameters: Params;\n\treadonly constrainedSampling?: Message.Tool[\"constrainedSampling\"];\n\treadonly success: Success;\n\treadonly failure?: Failure;\n\treadonly encodeContent?: (success: Success[\"Type\"]) => ModelContent;\n\treadonly encodeFailureContent?: (failure: Failure[\"Type\"]) => ModelContent;\n\treadonly encodeDetails?: (success: Success[\"Type\"]) => unknown;\n}\n\n/** Define a pure tool (handler attached later via {@link implement} or a toolkit). */\nexport const define = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n>(\n\tinput: DefineInput<Name, Params, Success, Failure>,\n): ToolDef<Name, Params, Success, Failure> => ({\n\t...input,\n});\n\n/** Attach a handler to an existing definition (the testable def/exec split). */\nexport const implement = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n\tR = never,\n>(\n\tdefinition: ToolDef<Name, Params, Success, Failure>,\n\thandler: Handler<Params, Success, Failure, R>,\n): ToolImpl<Name, Params, Success, Failure, R> => ({ definition, handler });\n\n/** Sugar for the co-located case: a definition with its handler in one object. */\nexport const make = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n\tR = never,\n>(\n\tinput: DefineInput<Name, Params, Success, Failure> & {\n\t\treadonly handler: Handler<Params, Success, Failure, R>;\n\t},\n): ToolImpl<Name, Params, Success, Failure, R> => {\n\tconst { handler, ...rest } = input;\n\treturn { definition: define(rest), handler };\n};\n\n/**\n * A tool ready to register: its capability requirements have been discharged, leaving only\n * the executor-provided {@link ToolProgress}. The registry and executor hold `RegisteredTool`s\n * and are non-generic (only `handle` is generic, over a progress sink's `RProgress`), so any\n * number of tools — built-in or\n * third-party/plugin — compose without a shared capability union\n */\nexport interface RegisteredTool {\n\treadonly definition: AnyToolDef;\n\treadonly handler: (\n\t\tparams: unknown,\n\t\tctx: ToolCallContext,\n\t) => Effect.Effect<unknown, ToolExecutionError, ToolProgress>;\n}\n\nconst toRegistered = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n>(\n\tdefinition: ToolDef<Name, Params, Success, Failure>,\n\thandler: Handler<Params, Success, Failure, ToolProgress>,\n): RegisteredTool => ({\n\tdefinition,\n\t// The executor decodes with `definition.parameters` before invoking this\n\t// erased handler, so restoring the authored parameter type is safe here.\n\thandler: (params, ctx) =>\n\t\thandler(params as Params[\"Type\"], ctx).pipe(\n\t\t\tEffect.mapError((cause) => new ToolExecutionError({ toolName: definition.name, cause })),\n\t\t),\n});\n\n/** Register a tool whose only requirement is the executor-provided progress service. */\nexport const register = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n>(\n\timpl: ToolImpl<Name, Params, Success, Failure, ToolProgress>,\n): RegisteredTool => toRegistered(impl.definition, impl.handler);\n\n/**\n * Discharge a tool's capability requirements into a {@link RegisteredTool}, erasing its `R`\n * (the executor still provides `ToolProgress`). This is the registration boundary: a\n * plugin/third-party tool provides its own fully-resolved capability Layer here, so the\n * registry never has to unify anyone's `R`.\n */\nexport const provide = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n\tR,\n>(\n\timpl: ToolImpl<Name, Params, Success, Failure, R | ToolProgress>,\n\tlayer: Layer.Layer<R>,\n): RegisteredTool =>\n\t// `Effect.provide` discharges `R`, leaving `ToolProgress`. TS can't simplify\n\t// `Exclude<ToolProgress, R>` for a generic `R`, so localize the cast before\n\t// crossing the registered-tool boundary.\n\ttoRegistered(impl.definition, ((params, ctx) => impl.handler(params, ctx).pipe(Effect.provide(layer))) as Handler<\n\t\tParams,\n\t\tSuccess,\n\t\tFailure,\n\t\tToolProgress\n\t>);\n\n/**\n * Derive a provider-safe JSON Schema object from an Effect Schema. This is the\n * single boundary that crosses into the provider wire; if a provider rejects a\n * construct, fix it here. Draft-07 inlines the root (no top-level `$ref`).\n */\nexport const toProviderJsonSchema = (schema: Schema.Top): Record<string, unknown> => {\n\t// Effect reads `Struct({})` as TS `{}` (any non-null) and emits `{ not: { type: \"null\" } }`;\n\t// providers require an object, so emit one shaped like a non-empty struct's.\n\tconst encoded = SchemaAST.toEncoded(schema.ast);\n\tif (\n\t\tSchemaAST.isObjects(encoded) &&\n\t\tencoded.propertySignatures.length === 0 &&\n\t\tencoded.indexSignatures.length === 0\n\t) {\n\t\treturn { type: \"object\", properties: {}, additionalProperties: true };\n\t}\n\treturn Schema.toStandardJSONSchemaV1(schema)[\"~standard\"].jsonSchema.input({ target: \"draft-07\" });\n};\n\n/**\n * Build the aikit `Message.Tool` wire view from a definition. The derived JSON\n * Schema object satisfies aikit's `parameters` slot structurally at runtime; the\n * single localized cast keeps aikit untouched (decision 3-A).\n */\nexport const toAikitTool = (def: AnyToolDef): Message.Tool => ({\n\tname: def.name,\n\tdescription: def.description,\n\tparameters: toProviderJsonSchema(def.parameters) as unknown as TSchema,\n\t...(def.constrainedSampling === undefined ? {} : { constrainedSampling: def.constrainedSampling }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,MAAa,kBAAkB,OAAO,OAAO;CAC5C,QAAQ,OAAO;CACf,UAAU,OAAO;CACjB,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;;CAEpD,YAAY,OAAO,SAAS,OAAO,MAAM,OAAO,SAAS,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC;AAC7E,CAAC;;;;;;AAQD,MAAa,eAAe,OAAO,SAAS;CAAC;CAAU;CAAS;CAAY;CAAY;AAAQ,CAAC;;AAIjG,MAAa,YAAY,QACxB,IAAI,aAAa,KAAA,KAAa,IAAI,aAAa,YAAY,IAAI,aAAa;;AAmG7E,MAAa,UAMZ,WAC8C,EAC9C,GAAG,MACJ;;AAGA,MAAa,aAOZ,YACA,aACkD;CAAE;CAAY;AAAQ;;AAGzE,MAAa,QAOZ,UAGiD;CACjD,MAAM,EAAE,SAAS,GAAG,SAAS;CAC7B,OAAO;EAAE,YAAY,OAAO,IAAI;EAAG;CAAQ;AAC5C;AAiBA,MAAM,gBAML,YACA,aACqB;CACrB;CAGA,UAAU,QAAQ,QACjB,QAAQ,QAA0B,GAAG,CAAC,CAAC,KACtC,OAAO,UAAU,UAAU,IAAI,mBAAmB;EAAE,UAAU,WAAW;EAAM;CAAM,CAAC,CAAC,CACxF;AACF;;AAGA,MAAa,YAMZ,SACoB,aAAa,KAAK,YAAY,KAAK,OAAO;;;;;;;AAQ/D,MAAa,WAOZ,MACA,UAKA,aAAa,KAAK,cAAc,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,EAKnG;;;;;;AAOF,MAAa,wBAAwB,WAAgD;CAGpF,MAAM,UAAU,UAAU,UAAU,OAAO,GAAG;CAC9C,IACC,UAAU,UAAU,OAAO,KAC3B,QAAQ,mBAAmB,WAAW,KACtC,QAAQ,gBAAgB,WAAW,GAEnC,OAAO;EAAE,MAAM;EAAU,YAAY,CAAC;EAAG,sBAAsB;CAAK;CAErE,OAAO,OAAO,uBAAuB,MAAM,CAAC,CAAC,YAAY,CAAC,WAAW,MAAM,EAAE,QAAQ,WAAW,CAAC;AAClG;;;;;;AAOA,MAAa,eAAe,SAAmC;CAC9D,MAAM,IAAI;CACV,aAAa,IAAI;CACjB,YAAY,qBAAqB,IAAI,UAAU;CAC/C,GAAI,IAAI,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB,IAAI,oBAAoB;AACjG"}
|
|
1
|
+
{"version":3,"file":"tool.mjs","names":[],"sources":["../../src/tool.ts"],"sourcesContent":["import type { Message } from \"@codeworksh/aikit\";\nimport { Effect, JsonSchema, type Layer, Schema, SchemaAST, SchemaRepresentation } from \"effect\";\nimport type { TSchema } from \"typebox\";\nimport { ToolExecutionError } from \"./tool/error.ts\";\nimport type { ToolProgress } from \"./tool/progress.ts\";\n\n/**\n * The tool definition + handler model.\n *\n * A tool definition is pure, serializable data: name, description, and Effect\n * Schema for parameters / success / failure. Execution is a separate `Handler`\n * — an `Effect` whose capability dependencies (e.g. `ToolShell`) live in its\n * requirements `R`, provided by a Layer at runtime. Separating the two is the\n * main testing win: assert on the definition as plain data, and run the handler\n * against a stub capability Layer.\n *\n * Effect Schema is the single source of truth. {@link toAikitTool} derives a\n * provider-safe JSON Schema object for the aikit wire view; the harness\n * decode/encodes arguments and results with Effect Schema natively (it does not\n * use aikit's Typebox validators).\n */\n\n/** What the model reads next turn (the `content` side of content/details). */\nexport type ModelContent = ReadonlyArray<Message.TextContent | Message.ImageContent>;\n\n/** Per-call metadata handed to a handler instead of positional args. */\nexport const ToolCallContext = Schema.Struct({\n\tcallID: Schema.String,\n\ttoolName: Schema.String,\n\trawArgs: Schema.Record(Schema.String, Schema.Unknown),\n\t/** Input modalities of the model the call answers, e.g. `[\"text\", \"image\"]`. */\n\tmodelInput: Schema.optional(Schema.Array(Schema.Literals([\"text\", \"image\"]))),\n});\nexport type ToolCallContext = typeof ToolCallContext.Type;\n\n/**\n * Where a tool is reachable. `direct` and `model` tools are declared to the model each turn;\n * `model` ones are never callable from other tools. `codemode` and `deferred` tools stay off the\n * wire until loaded, and `hidden` ones never reach the model.\n */\nexport const ToolExposure = Schema.Literals([\"direct\", \"model\", \"codemode\", \"deferred\", \"hidden\"]);\nexport type ToolExposure = typeof ToolExposure.Type;\n\n/** Whether a tool is declared to the model every turn. Omitted exposure means `direct`. */\nexport const declared = (def: { readonly exposure?: ToolExposure }): boolean =>\n\tdef.exposure === undefined || def.exposure === \"direct\" || def.exposure === \"model\";\n\n/**\n * A pure tool definition. Parametrised over the *schema* instances so the\n * decoded parameter/success/failure types can be recovered via `[\"Type\"]`.\n */\nexport interface ToolDef<\n\tName extends string = string,\n\tParams extends Schema.Top = Schema.Top,\n\tSuccess extends Schema.Top = Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n> {\n\treadonly name: Name;\n\treadonly description: string;\n\t/** Human-readable display label (kept from the previous `AgentTool`). */\n\treadonly label?: string;\n\t/**\n\t * A short one-line summary for compact tool listings (e.g. a system-prompt tool index),\n\t * distinct from the fuller `description`.\n\t */\n\treadonly promptSnippet?: string;\n\t/** Optional guideline bullets appended to the default system prompt Guidelines section when this tool is active. */\n\treadonly promptGuidelines?: ReadonlyArray<string>;\n\t/** Where the tool is reachable. Omit → `direct`. */\n\treadonly exposure?: ToolExposure;\n\t/**\n\t * Repair argument shapes models commonly send before they are validated against\n\t * `parameters`. Return a copy; a throw makes the arguments invalid.\n\t */\n\treadonly prepareArguments?: (args: unknown) => unknown;\n\treadonly parameters: Params;\n\t/**\n\t * How the provider constrains the generated arguments. `{ type: \"json_schema\", strict: \"prefer\" }` sends\n\t * `parameters` in strict mode where the provider can express it and falls back to non-strict otherwise.\n\t */\n\treadonly constrainedSampling?: Message.Tool[\"constrainedSampling\"];\n\treadonly success: Success;\n\t/** Declared, model-visible failures (typed). Omit for tools that cannot fail expectedly. */\n\treadonly failure?: Failure;\n\t/** Render success for the model. Omit → executor falls back to JSON text. */\n\treadonly encodeContent?: (success: Success[\"Type\"]) => ModelContent;\n\t/** Render an expected failure for the model. Omit → executor falls back to JSON text. */\n\treadonly encodeFailureContent?: (failure: Failure[\"Type\"]) => ModelContent;\n\t/**\n\t * The `details` kept with a success, for UIs and programmatic consumers. Omit → the encoded\n\t * success. Set it when `encodeContent` already carries the payload, so it is not stored twice.\n\t */\n\treadonly encodeDetails?: (success: Success[\"Type\"]) => unknown;\n}\n\n/** A handler: validated params + context → typed success or typed failure. */\nexport type Handler<Params extends Schema.Top, Success extends Schema.Top, Failure extends Schema.Top, R = never> = (\n\tparams: Params[\"Type\"],\n\tctx: ToolCallContext,\n) => Effect.Effect<Success[\"Type\"], Failure[\"Type\"], R>;\n\n/** A definition paired with its handler (the unit the executor runs). */\nexport interface ToolImpl<\n\tName extends string = string,\n\tParams extends Schema.Top = Schema.Top,\n\tSuccess extends Schema.Top = Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n\tR = never,\n> {\n\treadonly definition: ToolDef<Name, Params, Success, Failure>;\n\treadonly handler: Handler<Params, Success, Failure, R>;\n}\n\n// Heterogeneous-collection aliases. `any` for the schema generics keeps handlers\n// of differing parameter types assignable into one array (the precise generics\n// live on the authoring helpers below).\n// biome-ignore lint/suspicious/noExplicitAny: erased schema generics for storage\nexport type AnyToolDef = ToolDef<string, any, any, any>;\n// biome-ignore lint/suspicious/noExplicitAny: erased schema generics for storage\nexport type AnyToolImpl<R = never> = ToolImpl<string, any, any, any, R>;\n\ninterface DefineInput<\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n> {\n\treadonly name: Name;\n\treadonly description: string;\n\treadonly label?: string;\n\treadonly promptSnippet?: string;\n\treadonly promptGuidelines?: ReadonlyArray<string>;\n\treadonly exposure?: ToolExposure;\n\treadonly prepareArguments?: (args: unknown) => unknown;\n\treadonly parameters: Params;\n\treadonly constrainedSampling?: Message.Tool[\"constrainedSampling\"];\n\treadonly success: Success;\n\treadonly failure?: Failure;\n\treadonly encodeContent?: (success: Success[\"Type\"]) => ModelContent;\n\treadonly encodeFailureContent?: (failure: Failure[\"Type\"]) => ModelContent;\n\treadonly encodeDetails?: (success: Success[\"Type\"]) => unknown;\n}\n\n/** Define a pure tool (handler attached later via {@link implement} or a toolkit). */\nexport const define = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n>(\n\tinput: DefineInput<Name, Params, Success, Failure>,\n): ToolDef<Name, Params, Success, Failure> => ({\n\t...input,\n});\n\n/** Attach a handler to an existing definition (the testable def/exec split). */\nexport const implement = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n\tR = never,\n>(\n\tdefinition: ToolDef<Name, Params, Success, Failure>,\n\thandler: Handler<Params, Success, Failure, R>,\n): ToolImpl<Name, Params, Success, Failure, R> => ({ definition, handler });\n\n/** Sugar for the co-located case: a definition with its handler in one object. */\nexport const make = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top = Schema.Top,\n\tR = never,\n>(\n\tinput: DefineInput<Name, Params, Success, Failure> & {\n\t\treadonly handler: Handler<Params, Success, Failure, R>;\n\t},\n): ToolImpl<Name, Params, Success, Failure, R> => {\n\tconst { handler, ...rest } = input;\n\treturn { definition: define(rest), handler };\n};\n\n/**\n * A tool ready to register: its capability requirements have been discharged, leaving only\n * the executor-provided {@link ToolProgress}. The registry and executor hold `RegisteredTool`s\n * and are non-generic (only `handle` is generic, over a progress sink's `RProgress`), so any\n * number of tools — built-in or\n * third-party/plugin — compose without a shared capability union\n */\nexport interface RegisteredTool {\n\treadonly definition: AnyToolDef;\n\treadonly handler: (\n\t\tparams: unknown,\n\t\tctx: ToolCallContext,\n\t) => Effect.Effect<unknown, ToolExecutionError, ToolProgress>;\n}\n\nconst toRegistered = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n>(\n\tdefinition: ToolDef<Name, Params, Success, Failure>,\n\thandler: Handler<Params, Success, Failure, ToolProgress>,\n): RegisteredTool => ({\n\tdefinition,\n\t// The executor decodes with `definition.parameters` before invoking this\n\t// erased handler, so restoring the authored parameter type is safe here.\n\thandler: (params, ctx) =>\n\t\thandler(params as Params[\"Type\"], ctx).pipe(\n\t\t\tEffect.mapError((cause) => new ToolExecutionError({ toolName: definition.name, cause })),\n\t\t),\n});\n\n/** Register a tool whose only requirement is the executor-provided progress service. */\nexport const register = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n>(\n\timpl: ToolImpl<Name, Params, Success, Failure, ToolProgress>,\n): RegisteredTool => toRegistered(impl.definition, impl.handler);\n\n/**\n * Discharge a tool's capability requirements into a {@link RegisteredTool}, erasing its `R`\n * (the executor still provides `ToolProgress`). This is the registration boundary: a\n * plugin/third-party tool provides its own fully-resolved capability Layer here, so the\n * registry never has to unify anyone's `R`.\n */\nexport const provide = <\n\tName extends string,\n\tParams extends Schema.Top,\n\tSuccess extends Schema.Top,\n\tFailure extends Schema.Top,\n\tR,\n>(\n\timpl: ToolImpl<Name, Params, Success, Failure, R | ToolProgress>,\n\tlayer: Layer.Layer<R>,\n): RegisteredTool =>\n\t// `Effect.provide` discharges `R`, leaving `ToolProgress`. TS can't simplify\n\t// `Exclude<ToolProgress, R>` for a generic `R`, so localize the cast before\n\t// crossing the registered-tool boundary.\n\ttoRegistered(impl.definition, ((params, ctx) => impl.handler(params, ctx).pipe(Effect.provide(layer))) as Handler<\n\t\tParams,\n\t\tSuccess,\n\t\tFailure,\n\t\tToolProgress\n\t>);\n\nconst providerJsonSchema = \"codework/providerJsonSchema\";\n\n/**\n * Parameters from a JSON Schema someone else wrote, such as an MCP server's `inputSchema`. The\n * provider receives it exactly as written; arguments are validated against its Effect translation,\n * `pattern`s included: the user chose the server. A schema the translation cannot express (an\n * external `$ref`, a pattern invalid in Unicode mode) validates nothing, since rejecting arguments\n * the schema allows would be worse than letting the server check them.\n */\nexport const fromJsonSchema = (schema: Record<string, unknown>): Schema.Top => {\n\tconst validator = (() => {\n\t\ttry {\n\t\t\tconst draft07 =\n\t\t\t\t(typeof schema.$schema === \"string\" && schema.$schema.includes(\"draft-07\")) || \"definitions\" in schema;\n\t\t\treturn SchemaRepresentation.fromJsonSchemaDocument(\n\t\t\t\tdraft07 ? JsonSchema.fromSchemaDraft07(schema) : JsonSchema.fromSchemaDraft2020_12(schema),\n\t\t\t\t{ patterns: \"apply\" },\n\t\t\t);\n\t\t} catch {\n\t\t\treturn Schema.Unknown;\n\t\t}\n\t})();\n\treturn validator.annotate({ [providerJsonSchema]: schema });\n};\n\n/**\n * Whether `schema` came from {@link fromJsonSchema}. Its arguments are checked as JSON Schema checks\n * them: a key a closed object does not declare is an error, not dropped, since the tool receives the\n * arguments as written.\n */\nexport const isFromJsonSchema = (schema: Schema.Top) =>\n\tSchemaAST.resolveAt<Record<string, unknown>>(providerJsonSchema)(schema.ast) !== undefined;\n\n/**\n * Derive a provider-safe JSON Schema object from an Effect Schema. This is the\n * single boundary that crosses into the provider wire; if a provider rejects a\n * construct, fix it here. Draft-07 inlines the root (no top-level `$ref`).\n */\nexport const toProviderJsonSchema = (schema: Schema.Top): Record<string, unknown> => {\n\tconst written = SchemaAST.resolveAt<Record<string, unknown>>(providerJsonSchema)(schema.ast);\n\tif (written !== undefined) return written;\n\t// Effect reads `Struct({})` as TS `{}` (any non-null) and emits `{ not: { type: \"null\" } }`;\n\t// providers require an object, so emit one shaped like a non-empty struct's.\n\tconst encoded = SchemaAST.toEncoded(schema.ast);\n\tif (\n\t\tSchemaAST.isObjects(encoded) &&\n\t\tencoded.propertySignatures.length === 0 &&\n\t\tencoded.indexSignatures.length === 0\n\t) {\n\t\treturn { type: \"object\", properties: {}, additionalProperties: true };\n\t}\n\treturn Schema.toStandardJSONSchemaV1(schema)[\"~standard\"].jsonSchema.input({ target: \"draft-07\" });\n};\n\n/**\n * Build the aikit `Message.Tool` wire view from a definition. The derived JSON\n * Schema object satisfies aikit's `parameters` slot structurally at runtime; the\n * single localized cast keeps aikit untouched (decision 3-A).\n */\nexport const toAikitTool = (def: AnyToolDef): Message.Tool => ({\n\tname: def.name,\n\tdescription: def.description,\n\tparameters: toProviderJsonSchema(def.parameters) as unknown as TSchema,\n\t...(def.constrainedSampling === undefined ? {} : { constrainedSampling: def.constrainedSampling }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA0BA,MAAa,kBAAkB,OAAO,OAAO;CAC5C,QAAQ,OAAO;CACf,UAAU,OAAO;CACjB,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;;CAEpD,YAAY,OAAO,SAAS,OAAO,MAAM,OAAO,SAAS,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC;AAC7E,CAAC;;;;;;AAQD,MAAa,eAAe,OAAO,SAAS;CAAC;CAAU;CAAS;CAAY;CAAY;AAAQ,CAAC;;AAIjG,MAAa,YAAY,QACxB,IAAI,aAAa,KAAA,KAAa,IAAI,aAAa,YAAY,IAAI,aAAa;;AAmG7E,MAAa,UAMZ,WAC8C,EAC9C,GAAG,MACJ;;AAGA,MAAa,aAOZ,YACA,aACkD;CAAE;CAAY;AAAQ;;AAGzE,MAAa,QAOZ,UAGiD;CACjD,MAAM,EAAE,SAAS,GAAG,SAAS;CAC7B,OAAO;EAAE,YAAY,OAAO,IAAI;EAAG;CAAQ;AAC5C;AAiBA,MAAM,gBAML,YACA,aACqB;CACrB;CAGA,UAAU,QAAQ,QACjB,QAAQ,QAA0B,GAAG,CAAC,CAAC,KACtC,OAAO,UAAU,UAAU,IAAI,mBAAmB;EAAE,UAAU,WAAW;EAAM;CAAM,CAAC,CAAC,CACxF;AACF;;AAGA,MAAa,YAMZ,SACoB,aAAa,KAAK,YAAY,KAAK,OAAO;;;;;;;AAQ/D,MAAa,WAOZ,MACA,UAKA,aAAa,KAAK,cAAc,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,EAKnG;AAEF,MAAM,qBAAqB;;;;;;;;AAS3B,MAAa,kBAAkB,WAAgD;CAa9E,cAZyB;EACxB,IAAI;GACH,MAAM,UACJ,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,SAAS,UAAU,KAAM,iBAAiB;GACjG,OAAO,qBAAqB,uBAC3B,UAAU,WAAW,kBAAkB,MAAM,IAAI,WAAW,uBAAuB,MAAM,GACzF,EAAE,UAAU,QAAQ,CACrB;EACD,QAAQ;GACP,OAAO,OAAO;EACf;CACD,EAAA,CACe,CAAC,CAAC,SAAS,GAAG,qBAAqB,OAAO,CAAC;AAC3D;;;;;;AAOA,MAAa,oBAAoB,WAChC,UAAU,UAAmC,kBAAkB,CAAC,CAAC,OAAO,GAAG,MAAM,KAAA;;;;;;AAOlF,MAAa,wBAAwB,WAAgD;CACpF,MAAM,UAAU,UAAU,UAAmC,kBAAkB,CAAC,CAAC,OAAO,GAAG;CAC3F,IAAI,YAAY,KAAA,GAAW,OAAO;CAGlC,MAAM,UAAU,UAAU,UAAU,OAAO,GAAG;CAC9C,IACC,UAAU,UAAU,OAAO,KAC3B,QAAQ,mBAAmB,WAAW,KACtC,QAAQ,gBAAgB,WAAW,GAEnC,OAAO;EAAE,MAAM;EAAU,YAAY,CAAC;EAAG,sBAAsB;CAAK;CAErE,OAAO,OAAO,uBAAuB,MAAM,CAAC,CAAC,YAAY,CAAC,WAAW,MAAM,EAAE,QAAQ,WAAW,CAAC;AAClG;;;;;;AAOA,MAAa,eAAe,SAAmC;CAC9D,MAAM,IAAI;CACV,aAAa,IAAI;CACjB,YAAY,qBAAqB,IAAI,UAAU;CAC/C,GAAI,IAAI,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB,IAAI,oBAAoB;AACjG"}
|
package/plugin-XaYYRsX-.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-XaYYRsX-.mjs","names":[],"sources":["../../src/plugin/plugin.ts","../../src/plugin.ts"],"sourcesContent":["import type { Effect } from \"effect\";\nimport type { Definition } from \"../event.ts\";\nimport type { Service as LocationService } from \"../location.ts\";\nimport type { SandboxIO } from \"../sandbox/io.ts\";\nimport type { SharedPluginContext } from \"./context.ts\";\nimport type { PluginOptions } from \"./ref.ts\";\n\n/**\n * The domains a plugin can extend, and the order the harness runs them in.\n *\n * Order is declared, not positional. A plugin's place used to come from where its entry sat in\n * the `plugins` array, which is unknowable when the entry is written: a user's settings file and\n * a project's are edited by different people at different times, and neither can see the other's\n * order. Since a prompt plugin indexes the tools registered before it, that made a tool added\n * from settings invisible in the system prompt, with no way to fix it from a settings file.\n *\n * A plugin instead says which domain it extends, and the harness runs the domains in this order.\n * Entries within one domain keep the order they were written in, because that is where\n * composition actually happens -- a plugin patching another's tool, or appending to the prompt a\n * previous one rendered, is written next to it and deliberately after it.\n *\n * Kept as data so a later release can add a domain, or make the order configurable, without\n * touching the loader: `{ tool: 1, skill: 2, prompt: 3 }` needs no code change here.\n */\nexport const domains = { tool: 1, prompt: 2 } as const;\n\nexport type PluginKind = keyof typeof domains;\n\n/** Sort key for a plugin: its domain first, then where it was written. */\nexport const rank = (kind: PluginKind) => domains[kind];\n\nexport type Mount = SandboxIO.Provides | LocationService;\nexport interface Plugin {\n\treadonly id: string;\n\t/**\n\t * The domain this plugin extends, which decides when it runs: every `tool` plugin is set up\n\t * before any `prompt` plugin, whichever settings layer each came from, so a prompt plugin\n\t * always sees the complete tool set. Plugins within one domain run in the order they were\n\t * written.\n\t */\n\treadonly kind: PluginKind;\n\t/**\n\t * Event definitions this plugin publishes. Declared rather than registered at\n\t * runtime so they are known before the event system builds, and so a bad type\n\t * fails the boot instead of the first publish. Types must be namespaced\n\t * `plugin.<id>.*`.\n\t */\n\treadonly events?: ReadonlyArray<Definition>;\n\t/**\n\t * Off until a user asks for it. An `optIn` plugin is selected like any other but runs only\n\t * when a settings entry turns it on: `{ \"plugin\": \"<id>\", \"enabled\": true }`.\n\t */\n\treadonly optIn?: boolean;\n\t/**\n\t * `options` is this plugin's own configuration block, `{}` when its entry carried none.\n\t * Unvalidated: the harness never looks inside it, so a plugin checks whatever shape it\n\t * documents. It is a second argument rather than a context field so `ctx` stays one object\n\t * shared by every plugin in the turn.\n\t */\n\treadonly setup: (\n\t\tctx: SharedPluginContext,\n\t\toptions: PluginOptions,\n\t) => void | Promise<void> | Effect.Effect<void, unknown, Mount>;\n}\n\nexport const define = (plugin: Plugin): Plugin => plugin;\n","/**\n * The plugin authoring surface.\n *\n * Everything a third-party plugin needs to describe itself and to write into the harness during\n * `setup`, and nothing about how the harness finds, installs or runs it. Loading, the store and\n * the `.npmrc` anchoring stay in `@codeworksh/harness`, which imports this same module — so a\n * plugin and its host agree on one set of types rather than two that happen to match.\n */\nexport type { Config, Events, Paths, PromptResolver, SharedPluginContext } from \"./plugin/context.ts\";\nexport { define, domains, type Mount, type Plugin, type PluginKind, rank } from \"./plugin/plugin.ts\";\nexport * as Prompt from \"./plugin/prompt.ts\";\nexport * as Section from \"./plugin/section.ts\";\nexport type { PluginOptions, PluginPatch, PluginRef, PluginSpec } from \"./plugin/ref.ts\";\nexport type { PluginRegistry } from \"./plugin/registry.ts\";\nexport * as Tool from \"./plugin/tool.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,UAAU;CAAE,MAAM;CAAG,QAAQ;AAAE;;AAK5C,MAAa,QAAQ,SAAqB,QAAQ;AAoClD,MAAa,UAAU,WAA2B"}
|