@kindgi/tools 0.0.0-bootstrap.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +86 -1
  3. package/dist/define.d.ts +138 -0
  4. package/dist/define.d.ts.map +1 -0
  5. package/dist/define.js +318 -0
  6. package/dist/define.js.map +1 -0
  7. package/dist/errors.d.ts +113 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +4 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/http.d.ts +2 -0
  12. package/dist/http.d.ts.map +1 -0
  13. package/dist/http.js +213 -0
  14. package/dist/http.js.map +1 -0
  15. package/dist/index.d.ts +15 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +14 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/invoke.d.ts +27 -0
  20. package/dist/invoke.d.ts.map +1 -0
  21. package/dist/invoke.js +127 -0
  22. package/dist/invoke.js.map +1 -0
  23. package/dist/manifest.d.ts +23 -0
  24. package/dist/manifest.d.ts.map +1 -0
  25. package/dist/manifest.js +37 -0
  26. package/dist/manifest.js.map +1 -0
  27. package/dist/precondition.d.ts +25 -0
  28. package/dist/precondition.d.ts.map +1 -0
  29. package/dist/precondition.js +34 -0
  30. package/dist/precondition.js.map +1 -0
  31. package/dist/registry.d.ts +87 -0
  32. package/dist/registry.d.ts.map +1 -0
  33. package/dist/registry.js +171 -0
  34. package/dist/registry.js.map +1 -0
  35. package/dist/spec-registry.d.ts +48 -0
  36. package/dist/spec-registry.d.ts.map +1 -0
  37. package/dist/spec-registry.js +37 -0
  38. package/dist/spec-registry.js.map +1 -0
  39. package/dist/tool.schema.json +297 -0
  40. package/dist/types.d.ts +508 -0
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/types.js +14 -0
  43. package/dist/types.js.map +1 -0
  44. package/package.json +64 -4
  45. package/src/define.ts +537 -0
  46. package/src/errors.ts +139 -0
  47. package/src/http.ts +268 -0
  48. package/src/index.ts +68 -0
  49. package/src/invoke.ts +165 -0
  50. package/src/manifest.ts +40 -0
  51. package/src/precondition.ts +40 -0
  52. package/src/registry.ts +262 -0
  53. package/src/spec-registry.ts +78 -0
  54. package/src/tool.schema.json +297 -0
  55. package/src/types.ts +538 -0
@@ -0,0 +1,508 @@
1
+ import type { ZodLikeSchema } from '@kindgi/schema';
2
+ import type { TenantId, ToolId, UserId } from '@kindgi/types';
3
+ /**
4
+ * JSON Schema for a tool's input/output. Author-supplied, Draft 2020-12.
5
+ * Kept as `unknown` here — the loader validates that the provided value is
6
+ * a legal Ajv schema at `defineTool` time.
7
+ */
8
+ export type JsonSchema = Readonly<Record<string, unknown>>;
9
+ /** Closed set of effect kinds Kindgi recognises. Matches @kindgi/specs/tool.schema.json. */
10
+ export declare const EFFECT_KINDS: readonly ["reads", "writes", "deletes", "network", "spawns-run", "emits-event", "external-side-effect", "sensitive-data-egress"];
11
+ export type EffectKind = (typeof EFFECT_KINDS)[number];
12
+ /**
13
+ * A declared side-effect. Enables policy enforcement (can this tool run in
14
+ * this tenant?), safe parallelization (are two invocations conflicting?),
15
+ * and causal provenance annotation.
16
+ */
17
+ export interface Effect {
18
+ readonly kind: EffectKind;
19
+ /**
20
+ * Resource identifier the effect targets — for example `memory:facts`,
21
+ * `blob:*`, `external:api.example.com`. Opaque to this package; the
22
+ * policy engine interprets it when enforcing tenant policy.
23
+ */
24
+ readonly resource?: string;
25
+ readonly notes?: string;
26
+ }
27
+ /**
28
+ * A typed context requirement — a named slot the tool expects the runtime
29
+ * to supply. The name matches an entry in the tenant's provider registry
30
+ * (`tenant`, `db`, `memory:facts`, `blob`, etc.). Not enforced by this
31
+ * package; declarative metadata for capability + policy layers.
32
+ */
33
+ export interface Need {
34
+ readonly name: string;
35
+ readonly optional?: boolean;
36
+ }
37
+ /**
38
+ * The transport-neutral context a tool receives at invocation. Whether the
39
+ * tool is called from a kernel run (in-process) or over MCP (remote), the
40
+ * caller synthesises a `ToolContext` and passes it in.
41
+ *
42
+ * Deliberately narrow — kernel-specific things like the journal or
43
+ * NodeContext helpers stay on the kernel side of the bridge.
44
+ */
45
+ export interface ToolContext {
46
+ /**
47
+ * Tenant scope for the invocation. Every tool call is tenant-scoped;
48
+ * cross-tenant access is denied by policy at the kernel layer.
49
+ * Handlers use this to key persistence (per-tenant DBs, per-tenant
50
+ * blob buckets) and to route capability calls (secrets scoped to
51
+ * this tenant only).
52
+ */
53
+ readonly tenantId: TenantId;
54
+ /**
55
+ * The acting principal, if the runtime can identify one. Optional
56
+ * because some invocations (scheduled background jobs) are system-run.
57
+ */
58
+ readonly principal?: UserId;
59
+ /**
60
+ * The kernel run the call belongs to, when a run invokes the tool — an
61
+ * agent turn or a flow step. Stable across every call the run makes.
62
+ */
63
+ readonly runId?: string;
64
+ /**
65
+ * Correlation id for this individual call (the model's tool-call id,
66
+ * an MCP request id, a webhook id). Opaque to tools; useful for logs,
67
+ * provenance and idempotency.
68
+ */
69
+ readonly requestId?: string;
70
+ /**
71
+ * Signal that fires when the caller wants the tool to abort — kernel
72
+ * cancel/failure teardown, MCP client disconnect, HTTP request cancel.
73
+ * Cooperative handlers should observe this and exit early.
74
+ */
75
+ readonly abortSignal: AbortSignal;
76
+ /**
77
+ * Optional secret resolver. HTTP tools built via
78
+ * `defineTool({spec: {kind: 'http', ...}})` uses this at invoke time to resolve its
79
+ * declared `secret_ref`s to plaintext credentials. Absent → HTTP
80
+ * tools that declare a `secret_ref` throw with a clear
81
+ * "resolveSecret not wired" error; tools that don't need secrets
82
+ * (dev-echo, in-process handlers) ignore it.
83
+ *
84
+ * Caller responsibility: the dispatch site (the agent turn's
85
+ * `dispatch-tools` step in `@kindgi/agents`, a flow node that runs
86
+ * the tool, an MCP server) populates this from the deployment's
87
+ * `SecretBinding` scoped to the invoking tenant.
88
+ */
89
+ readonly resolveSecret?: (ref: ToolSecretRef) => Promise<string>;
90
+ /**
91
+ * The secrets this tool declares in `needsSpec.secrets`, by name,
92
+ * resolved by the runtime for this call: for the call's tenant, in the
93
+ * env the runtime serves (`KINDGI_ENV`; in `kindgi dev`, `local` — the
94
+ * pack's `.env` and `.env.local`). Every declared name is present: one
95
+ * the runtime can't resolve, or whose value doesn't match its schema,
96
+ * fails the call before the handler runs. Absent when the tool
97
+ * declares none, and wherever nothing resolves them — a unit test
98
+ * passes its own.
99
+ */
100
+ readonly secrets?: Readonly<Record<string, string>>;
101
+ }
102
+ /**
103
+ * Pointer to a tenant-scoped secret used by a declarative tool
104
+ * (e.g. `{kind: 'http'}` with a bearer secretRef). Same shape as
105
+ * `ProviderSecretRef` in `@kindgi/api` — both are `{envName, name}`
106
+ * references resolved via the deployment's `SecretBinding`. Kept
107
+ * local to `@kindgi/tools` so the tools package doesn't take an
108
+ * api-layer dep.
109
+ */
110
+ export interface ToolSecretRef {
111
+ readonly envName: string;
112
+ readonly name: string;
113
+ }
114
+ /**
115
+ * Isolation posture the runtime enforces around the handler. Three tiers:
116
+ * - `'none'` — no isolation. First-party framework handlers
117
+ * only; registration rejects tenant-authored
118
+ * tools declaring `'none'`.
119
+ * - `'context-isolated'` — same-process `node:vm` context. NOT a
120
+ * security boundary; prevents accidental state
121
+ * bleed.
122
+ * - `'strict'` — real container / MicroVM isolation. Required
123
+ * for anything running untrusted code.
124
+ *
125
+ * Sandbox declaration + capability manifest = the handler's declared
126
+ * capability contract.
127
+ */
128
+ export type SandboxMode = 'none' | 'context-isolated' | 'strict';
129
+ /**
130
+ * Runtime resource caps enforced by the sandbox layer at dispatch. Wall-
131
+ * clock (`wallMs`) intentionally NOT here — it belongs on the incoming
132
+ * edge as `EdgePolicy.timeoutMs`.
133
+ */
134
+ export interface RuntimeLimits {
135
+ readonly memMB: number;
136
+ readonly cpuMs: number;
137
+ }
138
+ /**
139
+ * Network egress policy for the sandboxed handler. Discriminated on
140
+ * `kind`; `allowlist` carries the explicit host list, the other two are
141
+ * unary.
142
+ */
143
+ export type NetworkPolicy = {
144
+ readonly kind: 'none';
145
+ } | {
146
+ readonly kind: 'allowlist';
147
+ readonly hosts: readonly string[];
148
+ } | {
149
+ readonly kind: 'unrestricted';
150
+ };
151
+ /**
152
+ * Typed dependency declarations for handler code, carried on the
153
+ * manifest as `needsSpec`. Each slot is optional; a handler that
154
+ * consumes none of a slot omits it entirely.
155
+ *
156
+ * In this shape (the serialisable projection carried in `index.json`
157
+ * and over the wire) values in `env` / `secrets` / `config` are JSON
158
+ * Schemas. An authoring tool that accepts Zod converts with
159
+ * `z.toJSONSchema()` before the manifest is built.
160
+ *
161
+ * `capabilities` names capability-router features (e.g. `'embedding'`);
162
+ * `bindings` names deployment-plugged binding keys (e.g. `'blob'`).
163
+ *
164
+ * The manifest field is `needsSpec` because `needs` holds the flat
165
+ * `Need[]` list of named context slots; both fields exist side by side.
166
+ */
167
+ export interface TypedNeeds {
168
+ readonly env?: Readonly<Record<string, JsonSchema>>;
169
+ readonly secrets?: Readonly<Record<string, JsonSchema>>;
170
+ readonly config?: Readonly<Record<string, JsonSchema>>;
171
+ readonly capabilities?: readonly string[];
172
+ readonly bindings?: readonly string[];
173
+ }
174
+ /**
175
+ * Handler-artifact pointer. Discriminated on `kind`:
176
+ *
177
+ * - `'oci'` — production. Populated by the deploy pipeline
178
+ * once the image is built
179
+ * + signed. `modulePath` resolves inside the pinned
180
+ * `imageRef`. `artifactVersion` is the auto-assigned
181
+ * `YYYYMMDD.N` version pinning one deploy (distinct
182
+ * from `ToolManifest.version` — semver, pack-authored).
183
+ * - `'filesystem'` — dev-mode. Populated by local development tooling
184
+ * at registration time. `modulePath` is an
185
+ * absolute host filesystem path pointing at the
186
+ * pack's on-disk handler file. Production
187
+ * deployments SHOULD reject this variant — the
188
+ * substrate is dev-only.
189
+ *
190
+ * Absent on framework-owned in-process manifests.
191
+ */
192
+ export type CodeArtifactRef = {
193
+ readonly kind: 'oci';
194
+ readonly imageRef: string;
195
+ readonly modulePath: string;
196
+ readonly artifactVersion: string;
197
+ } | {
198
+ readonly kind: 'filesystem';
199
+ readonly modulePath: string;
200
+ };
201
+ /**
202
+ * The serialisable projection of a tool — everything except the runtime
203
+ * handler binding. Matches `@kindgi/specs/tool.schema.json` and round-trips over
204
+ * the wire. This is what MCP and cross-runtime discovery consume.
205
+ *
206
+ * ## Additive extensions
207
+ *
208
+ * `sandbox`, `limits`, `network`, `needsSpec`, `codeArtifactRef` are
209
+ * optional extensions that the dispatch, SDK and deploy layers
210
+ * populate + honor. Registrations that don't set them leave them
211
+ * undefined; consumers that don't know about them ignore the fields.
212
+ */
213
+ export interface ToolManifest {
214
+ /**
215
+ * Globally-unique tool identifier. Convention: `<pack-id>.<tool-name>`
216
+ * (kebab-case, dot-namespaced) — e.g. `acme.verify-citation`,
217
+ * `demo.echo`. The `<pack-id>` prefix scopes the tool to its pack;
218
+ * `<tool-name>` names the operation. Enforced as a `ToolId` brand;
219
+ * `defineTool` refuses ids that don't match the convention.
220
+ */
221
+ readonly id: ToolId;
222
+ /**
223
+ * Human-readable one-liner describing what the tool does. Surfaced
224
+ * to the model as part of the tool definition (`ModelToolDefinition.description`)
225
+ * — the model uses it to decide when to call. Write it for the
226
+ * model: what the tool DOES, what it RETURNS, and when to prefer
227
+ * it over other tools. Skip implementation details.
228
+ */
229
+ readonly description: string;
230
+ /**
231
+ * Semver — REQUIRED. Every tool registered in a Kindgi deployment
232
+ * ships versioned; an agent's `tools[].version` is a semver range
233
+ * matched against these versions at dispatch time via
234
+ * `semver.maxSatisfying`. Enforced by
235
+ * `defineTool(...)` at the API boundary.
236
+ */
237
+ readonly version: string;
238
+ /**
239
+ * JSON Schema Draft 2020-12 for the tool's input. Handed to the
240
+ * model as the tool's parameter schema so it can generate valid
241
+ * calls. `invokeTool` validates every incoming input against this
242
+ * before invoking the handler — invalid input surfaces as a
243
+ * `bad-input` error, never reaches the handler.
244
+ *
245
+ * Zod authors: pass a Zod v4 schema to `defineTool({input: zSchema})`;
246
+ * the framework converts to JSON Schema at author time and preserves
247
+ * the Zod schema on `tool.inputZod` for TS-side inference.
248
+ */
249
+ readonly input: JsonSchema;
250
+ /**
251
+ * JSON Schema Draft 2020-12 for the tool's output. `invokeTool`
252
+ * validates the handler's return value against this before surfacing
253
+ * it — a handler that returns off-schema fails with
254
+ * `bad-output`. Same Zod-conversion story as `input`.
255
+ *
256
+ * Prefer explicit schemas over `type: 'object', additionalProperties: true`
257
+ * — the model uses the output schema to interpret tool results
258
+ * downstream.
259
+ */
260
+ readonly output: JsonSchema;
261
+ /**
262
+ * Named context slots the tool depends on (e.g. `tenant`, `run`,
263
+ * `blob`, `memory:facts`). Framework-level dependencies the tool
264
+ * expects the runtime to inject via `ToolContext`. Declarative: not
265
+ * checked when a flow is loaded. `needsSpec` is the typed,
266
+ * discriminated form (env / secrets / config / capabilities /
267
+ * bindings).
268
+ */
269
+ readonly needs?: readonly Need[];
270
+ /**
271
+ * Declared side-effects the tool causes — an `EFFECT_KINDS` kind
272
+ * (`writes`, `network`, `external-side-effect`, …), optionally with
273
+ * the `resource` it targets. Consumed by policy + audit machinery for
274
+ * effect-based gating (e.g. "block any tool with an
275
+ * `external-side-effect` in a dry-run"). Distinct from `mutating` —
276
+ * `effects` names WHICH effects; `mutating` is a coarser boolean.
277
+ */
278
+ readonly effects?: readonly Effect[];
279
+ /**
280
+ * How the tool is dispatched at invoke time. `'native'` (default)
281
+ * uses the framework's in-process dispatch; `'mcp'` routes through
282
+ * the Model Context Protocol endpoint declared at `mcpEndpoint`;
283
+ * `'auto'` picks native if a handler exists, else mcp. Most
284
+ * pack-authored tools omit this and default to native.
285
+ */
286
+ readonly transport?: 'auto' | 'native' | 'mcp';
287
+ /**
288
+ * MCP server URL for `transport: 'mcp'` tools. Ignored when
289
+ * transport is native. See the Model Context Protocol spec for the
290
+ * expected endpoint shape.
291
+ */
292
+ readonly mcpEndpoint?: string;
293
+ /**
294
+ * Free-form key/value metadata that rides along with the manifest.
295
+ * Not interpreted by the framework — passthrough for pack-authored
296
+ * annotations (e.g. `{owner: 'team-legal', ticket: 'PROJ-123'}`).
297
+ * Surfaced in `GET /v1/tools/:id` responses for tooling.
298
+ */
299
+ readonly metadata?: Readonly<Record<string, unknown>>;
300
+ /**
301
+ * Semantic marker: `true` when this tool causes observable side
302
+ * effects (writes state, calls external APIs with mutations, sends
303
+ * messages, etc.). Read-only tools (queries, computations, retrievals)
304
+ * set `false`. Absent = defaults to `true` (safer — the framework's
305
+ * `never_ask / ask_on_first_use / always_ask` policy defaults hinge
306
+ * on this flag; mistakenly marking a mutating tool as read-only would
307
+ * bypass HITL, while the reverse only adds friction).
308
+ *
309
+ * Consumed by `@kindgi/agents` as the per-tool HITL default when an
310
+ * agent's `conversationPolicy.hitl.tools` sets neither an override
311
+ * nor a `default` for the tool — a read-only tool passes straight
312
+ * through, a mutating tool asks on first use.
313
+ */
314
+ readonly mutating?: boolean;
315
+ /** Isolation posture — see `SandboxMode`. */
316
+ readonly sandbox?: SandboxMode;
317
+ /** Memory + CPU caps enforced by the sandbox at dispatch. */
318
+ readonly limits?: RuntimeLimits;
319
+ /** Network egress policy the sandbox honors. */
320
+ readonly network?: NetworkPolicy;
321
+ /**
322
+ * Discriminated typed-dependency declarations (env / secrets / config /
323
+ * capabilities / bindings). See `TypedNeeds` for the shape.
324
+ */
325
+ readonly needsSpec?: TypedNeeds;
326
+ /**
327
+ * Signed pointer at the deploy-time OCI image + module path carrying
328
+ * the handler bytes. Absent for in-process manifests.
329
+ */
330
+ readonly codeArtifactRef?: CodeArtifactRef;
331
+ /**
332
+ * Declarative handler specification. When present, the runtime
333
+ * `Tool.handler` is synthesized from this spec — the manifest
334
+ * carries everything needed for a first-party framework
335
+ * synthesizer to build the fetch/query/dispatch call at register
336
+ * time. Author writes the spec; framework owns the correctness
337
+ * bits (timeouts, aborts, secret resolution, retries).
338
+ *
339
+ * Discriminated on `spec.kind`. The framework ships `'http'` (see
340
+ * `HttpToolSpec`) as the first-party kind; other kinds plug in via
341
+ * `registerToolSpecSynthesizer`.
342
+ *
343
+ * `spec` and `handler` are MUTUALLY EXCLUSIVE at `defineTool` time
344
+ * — a tool is either declarative or imperative. Mixed usage
345
+ * fails to compile.
346
+ *
347
+ * The full JSON-serializable manifest (spec included) is what
348
+ * `POST /v1/tools` accepts — declarative tools can be registered
349
+ * from configuration without shipping code.
350
+ */
351
+ readonly spec?: ToolSpec;
352
+ }
353
+ /**
354
+ * Union of all declarative handler specifications the framework
355
+ * synthesizes into runtime handlers. Discriminated on `kind`; `'http'`
356
+ * is the only kind in this union. Adding a kind does not change the
357
+ * `defineTool({ spec })` author surface.
358
+ */
359
+ export type ToolSpec = HttpToolSpec;
360
+ /**
361
+ * Declarative HTTP-invocation spec. All fields serialize cleanly to
362
+ * JSON — no runtime closures. Credentials appear ONLY as
363
+ * `secret_ref` pointers; the actual plaintext is resolved at invoke
364
+ * time via `ToolContext.resolveSecret`.
365
+ */
366
+ export interface HttpToolSpec {
367
+ /**
368
+ * Discriminant. Every declarative tool spec self-identifies via
369
+ * `kind` so the framework's synthesizer registry can route to the
370
+ * right handler builder.
371
+ */
372
+ readonly kind: 'http';
373
+ /**
374
+ * HTTP method. `GET` and `DELETE` typically carry no body;
375
+ * `POST`, `PUT`, `PATCH` typically do. The default body shape is
376
+ * `json-input` (see `requestBody`).
377
+ */
378
+ readonly method: HttpMethod;
379
+ /**
380
+ * URL template with `{param}` placeholders substituted from the
381
+ * tool's input at invoke time. Example:
382
+ * `https://api.github.com/repos/{owner}/{repo}/issues/{number}`.
383
+ * Every placeholder must correspond to an input property; missing
384
+ * substitutions surface as a `handler-error` at invoke time.
385
+ */
386
+ readonly urlTemplate: string;
387
+ /**
388
+ * Static or templated headers. Values may include `{param}`
389
+ * placeholders substituted from the tool's input (e.g.
390
+ * `X-Trace-Id: {requestId}`). For credentialed headers use
391
+ * `authorization` — it keeps secret references out of `headers`.
392
+ */
393
+ readonly headers?: readonly HttpHeaderSpec[];
394
+ /**
395
+ * Optional authentication injected as a header on the outbound
396
+ * request. Union kinds:
397
+ * - `bearer` — writes `Authorization: Bearer <secret>` where
398
+ * `<secret>` is the plaintext of `secret_ref`.
399
+ * - `header` — writes `<headerName>: <secret>` verbatim (for
400
+ * vendors that use a non-`Authorization` header,
401
+ * e.g. `X-API-Key`).
402
+ */
403
+ readonly authorization?: HttpAuthSpec;
404
+ /**
405
+ * Request-body specification for methods that carry a body
406
+ * (`POST`, `PUT`, `PATCH`, `DELETE`). Absent → no body sent.
407
+ *
408
+ * The default body strategy is `{kind: 'json-input'}` — the tool's
409
+ * INPUT (after URL-template substitution consumes its keys) is
410
+ * JSON-serialized as the body. `input-passthrough` sends the raw
411
+ * input object (JSON body) without URL-consuming any keys, so
412
+ * keys used in the URL template appear redundantly in the body
413
+ * too. Choose based on the target API's expected shape.
414
+ */
415
+ readonly requestBody?: HttpRequestBodySpec;
416
+ /**
417
+ * Wall-clock timeout in milliseconds. Enforced via AbortController.
418
+ * Defaults to 30_000 (30s) when absent — matches typical vendor
419
+ * SLOs.
420
+ */
421
+ readonly timeoutMs?: number;
422
+ /**
423
+ * When the response body should be parsed as JSON before returning
424
+ * to the invoker. Default: `true`. Set `false` for adapters that
425
+ * hand-parse (rare) or for text-only endpoints.
426
+ */
427
+ readonly parseJson?: boolean;
428
+ /**
429
+ * Acceptable status-code range. Responses outside this range are
430
+ * treated as `handler-error` with the response text as the message.
431
+ * Default: `[200, 299]` (any 2xx).
432
+ */
433
+ readonly successStatus?: {
434
+ readonly min: number;
435
+ readonly max: number;
436
+ };
437
+ }
438
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
439
+ export interface HttpHeaderSpec {
440
+ readonly name: string;
441
+ readonly value: string;
442
+ }
443
+ export type HttpAuthSpec = {
444
+ readonly kind: 'bearer';
445
+ readonly secretRef: ToolSecretRef;
446
+ } | {
447
+ readonly kind: 'header';
448
+ readonly headerName: string;
449
+ readonly secretRef: ToolSecretRef;
450
+ };
451
+ export type HttpRequestBodySpec = {
452
+ readonly kind: 'json-input';
453
+ } | {
454
+ readonly kind: 'input-passthrough';
455
+ } | {
456
+ readonly kind: 'text';
457
+ readonly template: string;
458
+ };
459
+ /**
460
+ * The runtime object: manifest + local handler. Only exists in-process;
461
+ * `handler` is stripped when the tool is projected to a manifest for
462
+ * serialisation, MCP exposure, or discovery.
463
+ *
464
+ * Type parameters are caller-asserted — the runtime validates against
465
+ * `input` / `output` JSON Schema, not the TS type — but let authors write
466
+ * typed handlers when they know the shape.
467
+ */
468
+ export interface Tool<TInput = unknown, TOutput = unknown> extends ToolManifest {
469
+ /**
470
+ * The runtime handler — the function `invokeTool` actually calls.
471
+ * Types are caller-asserted (matches the `defineTool` generics);
472
+ * the runtime validates against `input` / `output` JSON Schema at
473
+ * every invocation, not the TS type.
474
+ */
475
+ readonly handler: (input: TInput, ctx: ToolContext) => Promise<TOutput>;
476
+ /**
477
+ * The original Zod schema, preserved when the tool was authored with a
478
+ * Zod v4 schema at the `input` slot. Present iff the author passed a
479
+ * Zod schema to `defineTool`; otherwise `undefined`. Wire form is
480
+ * always the converted JSON Schema on `input` — this field exists so
481
+ * TS callers can `z.infer<typeof tool.inputZod>` for static types.
482
+ *
483
+ * Explicitly `ZodLikeSchema | undefined` (not a bare optional marker):
484
+ * the more specific `DefinedTool<TInSchema, TOutSchema>` returned by
485
+ * `defineTool` narrows this to the exact Zod schema type when Zod is
486
+ * used, and to `undefined` when JSON Schema is used. Consumers reading
487
+ * a heterogeneous `AnyTool` see the union and narrow with `!== undefined`.
488
+ */
489
+ readonly inputZod?: ZodLikeSchema | undefined;
490
+ /** Symmetric to `inputZod` for the `output` slot. */
491
+ readonly outputZod?: ZodLikeSchema | undefined;
492
+ }
493
+ /**
494
+ * Type-erased alias for cross-boundary storage (registries, arrays of mixed
495
+ * tools). Handlers are contravariant in their input type, so a
496
+ * `Tool<{ text: string }, ...>` is not assignable to `Tool<unknown, unknown>`
497
+ * — this alias uses `unknown` on both sides so heterogeneous collections
498
+ * type-check without lying about the runtime shape.
499
+ */
500
+ export type AnyTool = Tool<any, any>;
501
+ /** MCP-compatible tool manifest. Narrower shape than `ToolManifest`. */
502
+ export interface McpToolManifest {
503
+ readonly name: string;
504
+ readonly description: string;
505
+ readonly inputSchema: JsonSchema;
506
+ readonly outputSchema?: JsonSchema;
507
+ }
508
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE9D;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3D,4FAA4F;AAC5F,eAAO,MAAM,YAAY,kIASf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,kBAAkB,GAAG,QAAQ,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AAEtC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEN;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,gDAAgD;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IACtC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,YAAY,GACpB;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;CACnC,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;CACnC,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAC/B;IAAE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;CAAE,GACtC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,WAAW,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,CAAE,SAAQ,YAAY;IAC7E;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC9C,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAChD;AAED;;;;;;GAMG;AAEH,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAErC,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC;CACpC"}
package/dist/types.js ADDED
@@ -0,0 +1,14 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ /** Closed set of effect kinds Kindgi recognises. Matches @kindgi/specs/tool.schema.json. */
4
+ export const EFFECT_KINDS = [
5
+ 'reads',
6
+ 'writes',
7
+ 'deletes',
8
+ 'network',
9
+ 'spawns-run',
10
+ 'emits-event',
11
+ 'external-side-effect',
12
+ 'sensitive-data-egress',
13
+ ];
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAYjC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO;IACP,QAAQ;IACR,SAAS;IACT,SAAS;IACT,YAAY;IACZ,aAAa;IACb,sBAAsB;IACtB,uBAAuB;CACf,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,67 @@
1
1
  {
2
2
  "name": "@kindgi/tools",
3
- "version": "0.0.0-bootstrap.0",
4
- "description": "Placeholder so a trusted publisher can be attached. Releases are published from https://github.com/kindgi/kindgi-sdk with provenance; use 0.1.0 or later.",
3
+ "version": "0.1.0",
4
+ "description": "Tool authoring shape + registry + invocation for Kindgi. A tool is a typed, effect-declared unit of work — the same definition runs in-process for one flow, over MCP for another. Pure — no kernel dependency; the kernel bridges tools to node handlers separately.",
5
5
  "license": "Apache-2.0",
6
- "repository": { "type": "git", "url": "git+https://github.com/kindgi/kindgi-sdk.git" }
7
- }
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/kindgi/kindgi-sdk.git",
9
+ "directory": "packages/tools"
10
+ },
11
+ "homepage": "https://github.com/kindgi/kindgi-sdk/tree/main/packages/tools#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/kindgi/kindgi-sdk/issues"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "src",
27
+ "README.md",
28
+ "SPEC.md",
29
+ "type-manifest.json"
30
+ ],
31
+ "dependencies": {
32
+ "@kindgi/schema": "0.1.0",
33
+ "@kindgi/types": "0.1.0",
34
+ "ajv": "^8.17.1",
35
+ "ajv-formats": "^3.0.1",
36
+ "semver": "^7.6.3"
37
+ },
38
+ "peerDependencies": {
39
+ "zod": "^4.0.0"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "zod": {
43
+ "optional": true
44
+ }
45
+ },
46
+ "devDependencies": {
47
+ "@kindgi/specs": "0.1.0",
48
+ "@types/node": "^22.10.5",
49
+ "@types/semver": "^7.5.8",
50
+ "typescript": "^5.7.3",
51
+ "vitest": "^2.1.8",
52
+ "zod": "^4.6.5"
53
+ },
54
+ "engines": {
55
+ "node": ">=22.0.0"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public",
59
+ "provenance": true
60
+ },
61
+ "scripts": {
62
+ "build": "tsc -p tsconfig.build.json",
63
+ "typecheck": "tsc --noEmit",
64
+ "test": "vitest run",
65
+ "clean": "rm -rf dist *.tsbuildinfo"
66
+ }
67
+ }