@oka-core/reason 0.2.15 → 0.2.16
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/dist/abort-controller.d.ts +19 -0
- package/dist/abort-controller.d.ts.map +1 -0
- package/dist/abort-controller.js +53 -0
- package/dist/activity-tracker.d.ts +48 -0
- package/dist/activity-tracker.d.ts.map +1 -0
- package/dist/activity-tracker.js +80 -0
- package/dist/analytics.d.ts +49 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +88 -0
- package/dist/array.d.ts +12 -0
- package/dist/array.d.ts.map +1 -0
- package/dist/array.js +20 -0
- package/dist/async-context.d.ts +20 -0
- package/dist/async-context.d.ts.map +1 -0
- package/dist/async-context.js +25 -0
- package/dist/binary-check.d.ts +16 -0
- package/dist/binary-check.d.ts.map +1 -0
- package/dist/binary-check.js +43 -0
- package/dist/buffered-writer.d.ts +30 -0
- package/dist/buffered-writer.d.ts.map +1 -0
- package/dist/buffered-writer.js +87 -0
- package/dist/circular-buffer.d.ts +28 -0
- package/dist/circular-buffer.d.ts.map +1 -0
- package/dist/circular-buffer.js +61 -0
- package/dist/cleanup-registry.d.ts +23 -0
- package/dist/cleanup-registry.d.ts.map +1 -0
- package/dist/cleanup-registry.js +34 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +32 -10
- package/dist/combined-abort-signal.d.ts +25 -0
- package/dist/combined-abort-signal.d.ts.map +1 -0
- package/dist/combined-abort-signal.js +47 -0
- package/dist/cron-lock.d.ts +29 -0
- package/dist/cron-lock.d.ts.map +1 -0
- package/dist/cron-lock.js +127 -0
- package/dist/cron-scheduler.d.ts +41 -0
- package/dist/cron-scheduler.d.ts.map +1 -0
- package/dist/cron-scheduler.js +189 -0
- package/dist/cron-tasks.d.ts +86 -0
- package/dist/cron-tasks.d.ts.map +1 -0
- package/dist/cron-tasks.js +205 -0
- package/dist/cron.d.ts +35 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +215 -0
- package/dist/env.d.ts +26 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +50 -0
- package/dist/errors.d.ts +99 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +214 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +48 -0
- package/dist/fps-tracker.d.ts +22 -0
- package/dist/fps-tracker.d.ts.map +1 -0
- package/dist/fps-tracker.js +44 -0
- package/dist/graceful-shutdown.d.ts +35 -0
- package/dist/graceful-shutdown.d.ts.map +1 -0
- package/dist/graceful-shutdown.js +89 -0
- package/dist/hash.d.ts +21 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +31 -0
- package/dist/heap-diagnostics.d.ts +68 -0
- package/dist/heap-diagnostics.d.ts.map +1 -0
- package/dist/heap-diagnostics.js +110 -0
- package/dist/idle-timeout.d.ts +21 -0
- package/dist/idle-timeout.d.ts.map +1 -0
- package/dist/idle-timeout.js +42 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/intl.d.ts +18 -0
- package/dist/intl.d.ts.map +1 -0
- package/dist/intl.js +75 -0
- package/dist/jsonl.d.ts +16 -0
- package/dist/jsonl.d.ts.map +1 -0
- package/dist/jsonl.js +60 -0
- package/dist/lazy-schema.d.ts +6 -0
- package/dist/lazy-schema.d.ts.map +1 -0
- package/dist/lazy-schema.js +8 -0
- package/dist/memo.d.ts +64 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/memo.js +162 -0
- package/dist/pkce.d.ts +13 -0
- package/dist/pkce.d.ts.map +1 -0
- package/dist/pkce.js +28 -0
- package/dist/priority-queue.d.ts +36 -0
- package/dist/priority-queue.d.ts.map +1 -0
- package/dist/priority-queue.js +97 -0
- package/dist/process-utils.d.ts +20 -0
- package/dist/process-utils.d.ts.map +1 -0
- package/dist/process-utils.js +54 -0
- package/dist/query-guard.d.ts +34 -0
- package/dist/query-guard.d.ts.map +1 -0
- package/dist/query-guard.js +74 -0
- package/dist/retry.d.ts +60 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +89 -0
- package/dist/schemas.d.ts +6 -6
- package/dist/secrets.d.ts +44 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +115 -0
- package/dist/semantic-types.d.ts +39 -0
- package/dist/semantic-types.d.ts.map +1 -0
- package/dist/semantic-types.js +49 -0
- package/dist/sequential.d.ts +21 -0
- package/dist/sequential.d.ts.map +1 -0
- package/dist/sequential.js +49 -0
- package/dist/signal.d.ts +29 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +39 -0
- package/dist/sleep.d.ts +21 -0
- package/dist/sleep.d.ts.map +1 -0
- package/dist/sleep.js +58 -0
- package/dist/slow-ops.d.ts +41 -0
- package/dist/slow-ops.d.ts.map +1 -0
- package/dist/slow-ops.js +133 -0
- package/dist/store.d.ts +20 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +34 -0
- package/dist/stream.d.ts +29 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +92 -0
- package/dist/string-utils.d.ts +46 -0
- package/dist/string-utils.d.ts.map +1 -0
- package/dist/string-utils.js +69 -0
- package/dist/strip-bom.d.ts +8 -0
- package/dist/strip-bom.d.ts.map +1 -0
- package/dist/strip-bom.js +10 -0
- package/dist/subprocess-env.d.ts +25 -0
- package/dist/subprocess-env.d.ts.map +1 -0
- package/dist/subprocess-env.js +55 -0
- package/dist/temp-file.d.ts +18 -0
- package/dist/temp-file.d.ts.map +1 -0
- package/dist/temp-file.js +26 -0
- package/dist/tool-contract.d.ts +85 -0
- package/dist/tool-contract.d.ts.map +1 -0
- package/dist/tool-contract.js +101 -0
- package/dist/tools/read.d.ts +2 -10
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +662 -537
- package/dist/tools/write.d.ts +3 -2
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +329 -177
- package/dist/uuid.d.ts +20 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +28 -0
- package/dist/validation.d.ts +64 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +236 -0
- package/dist/with-resolvers.d.ts +12 -0
- package/dist/with-resolvers.d.ts.map +1 -0
- package/dist/with-resolvers.js +14 -0
- package/dist/xml-escape.d.ts +12 -0
- package/dist/xml-escape.d.ts.map +1 -0
- package/dist/xml-escape.js +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret-aware environment scrubbing for subprocess spawning.
|
|
3
|
+
*
|
|
4
|
+
* Strips sensitive variables (API keys, cloud credentials, OIDC tokens)
|
|
5
|
+
* from child process environments to prevent exfiltration via shell
|
|
6
|
+
* expansion in CI/CD and agent contexts.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by Claude Code's `src/utils/subprocessEnv.ts`.
|
|
9
|
+
*/
|
|
10
|
+
import { isEnvTruthy } from "./env.js";
|
|
11
|
+
/** Default variables to scrub from subprocess environments. */
|
|
12
|
+
const DEFAULT_SCRUB_LIST = [
|
|
13
|
+
// API keys
|
|
14
|
+
"ANTHROPIC_API_KEY",
|
|
15
|
+
"OPENAI_API_KEY",
|
|
16
|
+
"OPENROUTER_API_KEY",
|
|
17
|
+
// Cloud provider credentials
|
|
18
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
19
|
+
"AWS_SESSION_TOKEN",
|
|
20
|
+
"GOOGLE_APPLICATION_CREDENTIALS",
|
|
21
|
+
"AZURE_CLIENT_SECRET",
|
|
22
|
+
"AZURE_CLIENT_CERTIFICATE_PATH",
|
|
23
|
+
// OTEL exporter headers (may carry Bearer tokens)
|
|
24
|
+
"OTEL_EXPORTER_OTLP_HEADERS",
|
|
25
|
+
"OTEL_EXPORTER_OTLP_LOGS_HEADERS",
|
|
26
|
+
"OTEL_EXPORTER_OTLP_METRICS_HEADERS",
|
|
27
|
+
"OTEL_EXPORTER_OTLP_TRACES_HEADERS",
|
|
28
|
+
// GitHub Actions OIDC + runtime tokens
|
|
29
|
+
"ACTIONS_ID_TOKEN_REQUEST_TOKEN",
|
|
30
|
+
"ACTIONS_ID_TOKEN_REQUEST_URL",
|
|
31
|
+
"ACTIONS_RUNTIME_TOKEN",
|
|
32
|
+
"ACTIONS_RUNTIME_URL",
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Create a scrubbed copy of `process.env` for subprocess spawning.
|
|
36
|
+
*
|
|
37
|
+
* Scrubbing is only active when the gate env var is truthy.
|
|
38
|
+
* Also scrubs `INPUT_<NAME>` variants (GitHub Actions auto-creates these).
|
|
39
|
+
*/
|
|
40
|
+
export function createSubprocessEnv(opts) {
|
|
41
|
+
const gateVar = opts?.enableEnvVar ?? "OKA_SUBPROCESS_ENV_SCRUB";
|
|
42
|
+
if (!isEnvTruthy(process.env[gateVar])) {
|
|
43
|
+
return process.env;
|
|
44
|
+
}
|
|
45
|
+
const env = { ...process.env };
|
|
46
|
+
const scrubList = opts?.scrubList ?? [
|
|
47
|
+
...DEFAULT_SCRUB_LIST,
|
|
48
|
+
...(opts?.extraScrubList ?? []),
|
|
49
|
+
];
|
|
50
|
+
for (const k of scrubList) {
|
|
51
|
+
delete env[k];
|
|
52
|
+
delete env[`INPUT_${k}`];
|
|
53
|
+
}
|
|
54
|
+
return env;
|
|
55
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporary file path generation — deterministic (content-hashed) or random.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by Claude Code's `src/utils/tempfile.ts`.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generate a temporary file path.
|
|
8
|
+
*
|
|
9
|
+
* @param prefix File name prefix (default: "oka-tmp")
|
|
10
|
+
* @param extension File extension including dot (default: ".md")
|
|
11
|
+
* @param options.contentHash When provided, the ID is a stable SHA-256
|
|
12
|
+
* prefix of this string. Same content → same path across processes.
|
|
13
|
+
* Use when the path is included in API payloads (avoids cache busting).
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateTempFilePath(prefix?: string, extension?: string, options?: {
|
|
16
|
+
contentHash?: string;
|
|
17
|
+
}): string;
|
|
18
|
+
//# sourceMappingURL=temp-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temp-file.d.ts","sourceRoot":"","sources":["../src/temp-file.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,SAAY,EAClB,SAAS,SAAQ,EACjB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,MAAM,CAQR"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporary file path generation — deterministic (content-hashed) or random.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by Claude Code's `src/utils/tempfile.ts`.
|
|
5
|
+
*/
|
|
6
|
+
import { createHash, randomUUID } from "crypto";
|
|
7
|
+
import { tmpdir } from "os";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
/**
|
|
10
|
+
* Generate a temporary file path.
|
|
11
|
+
*
|
|
12
|
+
* @param prefix File name prefix (default: "oka-tmp")
|
|
13
|
+
* @param extension File extension including dot (default: ".md")
|
|
14
|
+
* @param options.contentHash When provided, the ID is a stable SHA-256
|
|
15
|
+
* prefix of this string. Same content → same path across processes.
|
|
16
|
+
* Use when the path is included in API payloads (avoids cache busting).
|
|
17
|
+
*/
|
|
18
|
+
export function generateTempFilePath(prefix = "oka-tmp", extension = ".md", options) {
|
|
19
|
+
const id = options?.contentHash
|
|
20
|
+
? createHash("sha256")
|
|
21
|
+
.update(options.contentHash)
|
|
22
|
+
.digest("hex")
|
|
23
|
+
.slice(0, 16)
|
|
24
|
+
: randomUUID();
|
|
25
|
+
return join(tmpdir(), `${prefix}-${id}${extension}`);
|
|
26
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool contract pattern — typed, composable MCP tool definitions.
|
|
3
|
+
*
|
|
4
|
+
* ZERO external dependencies beyond Zod (already required by MCP SDK).
|
|
5
|
+
*
|
|
6
|
+
* Inspired by Claude Code's Tool<Input,Output> pattern:
|
|
7
|
+
* - Separates tool definition from MCP registration
|
|
8
|
+
* - Permission pipeline (allow/deny/ask)
|
|
9
|
+
* - Input validation lifecycle
|
|
10
|
+
* - Lazy schema construction
|
|
11
|
+
* - Concurrency and read-only markers for pool assembly
|
|
12
|
+
*/
|
|
13
|
+
import type { z, ZodRawShape } from "zod";
|
|
14
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
export type PermissionResult = {
|
|
16
|
+
decision: "allow";
|
|
17
|
+
} | {
|
|
18
|
+
decision: "deny";
|
|
19
|
+
reason: string;
|
|
20
|
+
} | {
|
|
21
|
+
decision: "ask";
|
|
22
|
+
prompt: string;
|
|
23
|
+
};
|
|
24
|
+
/** A typed, framework-agnostic tool definition. */
|
|
25
|
+
export interface ToolDef<TShape extends ZodRawShape = ZodRawShape> {
|
|
26
|
+
/** Unique tool name (used as MCP tool ID). */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Human-readable description for the agent. */
|
|
29
|
+
description: string;
|
|
30
|
+
/** Zod shape for input validation. */
|
|
31
|
+
inputSchema: TShape;
|
|
32
|
+
/** Whether this tool only reads data (no side effects). */
|
|
33
|
+
isReadOnly: boolean;
|
|
34
|
+
/** Whether concurrent invocations are safe. */
|
|
35
|
+
isConcurrencySafe: boolean;
|
|
36
|
+
/** Optional permission check before execution. */
|
|
37
|
+
checkPermissions?: (input: z.objectOutputType<TShape, z.ZodTypeAny>) => PermissionResult;
|
|
38
|
+
/** The tool handler. */
|
|
39
|
+
call: (input: z.objectOutputType<TShape, z.ZodTypeAny>) => Promise<{
|
|
40
|
+
content: Array<{
|
|
41
|
+
type: "text";
|
|
42
|
+
text: string;
|
|
43
|
+
}>;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
interface BuildToolOpts<TShape extends ZodRawShape> {
|
|
47
|
+
name: string;
|
|
48
|
+
description: string;
|
|
49
|
+
inputSchema: TShape;
|
|
50
|
+
isReadOnly?: boolean;
|
|
51
|
+
isConcurrencySafe?: boolean;
|
|
52
|
+
checkPermissions?: ToolDef<TShape>["checkPermissions"];
|
|
53
|
+
call: ToolDef<TShape>["call"];
|
|
54
|
+
}
|
|
55
|
+
/** Build a typed tool definition with sensible defaults. */
|
|
56
|
+
export declare function buildTool<TShape extends ZodRawShape>(opts: BuildToolOpts<TShape>): ToolDef<TShape>;
|
|
57
|
+
/**
|
|
58
|
+
* Defer schema construction until first access.
|
|
59
|
+
* Useful when Zod shapes depend on runtime config.
|
|
60
|
+
*/
|
|
61
|
+
export declare function lazySchema<TShape extends ZodRawShape>(factory: () => TShape): TShape;
|
|
62
|
+
/** A named deny rule that prevents certain tools from registering. */
|
|
63
|
+
export interface DenyRule {
|
|
64
|
+
/** Tool names to deny. */
|
|
65
|
+
names: string[];
|
|
66
|
+
reason: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Assemble a tool pool from definitions, applying deny rules and deduplication.
|
|
70
|
+
* Returns only tools that pass all rules.
|
|
71
|
+
*/
|
|
72
|
+
export declare function assembleToolPool(tools: ToolDef[], denyRules?: DenyRule[]): ToolDef[];
|
|
73
|
+
/**
|
|
74
|
+
* Register a ToolDef on an MCP server instance.
|
|
75
|
+
*
|
|
76
|
+
* This is the thin adapter that bridges our typed tool definitions
|
|
77
|
+
* to the MCP SDK's `server.tool()` registration.
|
|
78
|
+
*/
|
|
79
|
+
export declare function wrapForMcp(tool: ToolDef, server: McpServer): void;
|
|
80
|
+
/**
|
|
81
|
+
* Register all tools from a pool onto an MCP server.
|
|
82
|
+
*/
|
|
83
|
+
export declare function registerToolPool(tools: ToolDef[], server: McpServer): void;
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=tool-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-contract.d.ts","sourceRoot":"","sources":["../src/tool-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GACrB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAIxC,mDAAmD;AACnD,MAAM,WAAW,OAAO,CAAC,MAAM,SAAS,WAAW,GAAG,WAAW;IAC/D,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,UAAU,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,CACjB,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,KAC5C,gBAAgB,CAAC;IACtB,wBAAwB;IACxB,IAAI,EAAE,CACJ,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,KAC5C,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAClE;AAID,UAAU,aAAa,CAAC,MAAM,SAAS,WAAW;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IACvD,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,MAAM,SAAS,WAAW,EAClD,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAC1B,OAAO,CAAC,MAAM,CAAC,CAUjB;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,SAAS,WAAW,EACnD,OAAO,EAAE,MAAM,MAAM,GACpB,MAAM,CAgBR;AAID,sEAAsE;AACtE,MAAM,WAAW,QAAQ;IACvB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EAAE,EAChB,SAAS,CAAC,EAAE,QAAQ,EAAE,GACrB,OAAO,EAAE,CAeX;AAID;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAcjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAI1E"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool contract pattern — typed, composable MCP tool definitions.
|
|
3
|
+
*
|
|
4
|
+
* ZERO external dependencies beyond Zod (already required by MCP SDK).
|
|
5
|
+
*
|
|
6
|
+
* Inspired by Claude Code's Tool<Input,Output> pattern:
|
|
7
|
+
* - Separates tool definition from MCP registration
|
|
8
|
+
* - Permission pipeline (allow/deny/ask)
|
|
9
|
+
* - Input validation lifecycle
|
|
10
|
+
* - Lazy schema construction
|
|
11
|
+
* - Concurrency and read-only markers for pool assembly
|
|
12
|
+
*/
|
|
13
|
+
/** Build a typed tool definition with sensible defaults. */
|
|
14
|
+
export function buildTool(opts) {
|
|
15
|
+
return {
|
|
16
|
+
name: opts.name,
|
|
17
|
+
description: opts.description,
|
|
18
|
+
inputSchema: opts.inputSchema,
|
|
19
|
+
isReadOnly: opts.isReadOnly ?? false,
|
|
20
|
+
isConcurrencySafe: opts.isConcurrencySafe ?? true,
|
|
21
|
+
checkPermissions: opts.checkPermissions,
|
|
22
|
+
call: opts.call,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// ─── Lazy Schema ────────────────────────────────────────────────────
|
|
26
|
+
/**
|
|
27
|
+
* Defer schema construction until first access.
|
|
28
|
+
* Useful when Zod shapes depend on runtime config.
|
|
29
|
+
*/
|
|
30
|
+
export function lazySchema(factory) {
|
|
31
|
+
let cached = null;
|
|
32
|
+
return new Proxy({}, {
|
|
33
|
+
get(_target, prop, receiver) {
|
|
34
|
+
if (!cached)
|
|
35
|
+
cached = factory();
|
|
36
|
+
return Reflect.get(cached, prop, receiver);
|
|
37
|
+
},
|
|
38
|
+
ownKeys() {
|
|
39
|
+
if (!cached)
|
|
40
|
+
cached = factory();
|
|
41
|
+
return Reflect.ownKeys(cached);
|
|
42
|
+
},
|
|
43
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
44
|
+
if (!cached)
|
|
45
|
+
cached = factory();
|
|
46
|
+
return Object.getOwnPropertyDescriptor(cached, prop);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Assemble a tool pool from definitions, applying deny rules and deduplication.
|
|
52
|
+
* Returns only tools that pass all rules.
|
|
53
|
+
*/
|
|
54
|
+
export function assembleToolPool(tools, denyRules) {
|
|
55
|
+
const denied = new Set();
|
|
56
|
+
for (const rule of denyRules ?? []) {
|
|
57
|
+
for (const name of rule.names)
|
|
58
|
+
denied.add(name);
|
|
59
|
+
}
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
const result = [];
|
|
62
|
+
for (const tool of tools) {
|
|
63
|
+
if (denied.has(tool.name))
|
|
64
|
+
continue;
|
|
65
|
+
if (seen.has(tool.name))
|
|
66
|
+
continue;
|
|
67
|
+
seen.add(tool.name);
|
|
68
|
+
result.push(tool);
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
// ─── MCP Adapter ────────────────────────────────────────────────────
|
|
73
|
+
/**
|
|
74
|
+
* Register a ToolDef on an MCP server instance.
|
|
75
|
+
*
|
|
76
|
+
* This is the thin adapter that bridges our typed tool definitions
|
|
77
|
+
* to the MCP SDK's `server.tool()` registration.
|
|
78
|
+
*/
|
|
79
|
+
export function wrapForMcp(tool, server) {
|
|
80
|
+
server.tool(tool.name, tool.description, tool.inputSchema, async (input) => {
|
|
81
|
+
// Permission check
|
|
82
|
+
if (tool.checkPermissions) {
|
|
83
|
+
const perm = tool.checkPermissions(input);
|
|
84
|
+
if (perm.decision === "deny") {
|
|
85
|
+
return {
|
|
86
|
+
content: [{ type: "text", text: `Denied: ${perm.reason}` }],
|
|
87
|
+
isError: true,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return tool.call(input);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Register all tools from a pool onto an MCP server.
|
|
96
|
+
*/
|
|
97
|
+
export function registerToolPool(tools, server) {
|
|
98
|
+
for (const tool of tools) {
|
|
99
|
+
wrapForMcp(tool, server);
|
|
100
|
+
}
|
|
101
|
+
}
|
package/dist/tools/read.d.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { OkaClient } from "../client.js";
|
|
3
|
+
import { type ToolDef } from "../tool-contract.js";
|
|
4
|
+
export declare function buildReadTools(client: OkaClient): ToolDef[];
|
|
3
5
|
/**
|
|
4
6
|
* Register read tools on the MCP server.
|
|
5
|
-
*
|
|
6
|
-
* Tools:
|
|
7
|
-
* - context — ranked learnings for a topic (flagship query)
|
|
8
|
-
* - learnings — browse institutional knowledge
|
|
9
|
-
* - decisions — decision log
|
|
10
|
-
* - patterns — recurring patterns
|
|
11
|
-
* - suggest — evidence-ranked priorities
|
|
12
|
-
* - backlog — agentic product backlog
|
|
13
|
-
* - priorities — evidence-ranked priorities from approved backlog
|
|
14
|
-
* - consolidate — manually trigger a consolidation run
|
|
15
7
|
*/
|
|
16
8
|
export declare function registerReadTools(server: McpServer, client: OkaClient): void;
|
|
17
9
|
//# sourceMappingURL=read.d.ts.map
|
package/dist/tools/read.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EACV,SAAS,EAKV,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EACV,SAAS,EAKV,MAAM,cAAc,CAAC;AAKtB,OAAO,EAA+B,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAgIhF,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,EAAE,CAivB3D;AAID;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAE5E"}
|