@nebutra/agent-runtime 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +115 -0
- package/.turbo/turbo-test.log +44 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +253 -0
- package/LICENSE +676 -0
- package/README.md +50 -0
- package/dist/adapters/dispatcher-sse.d.ts +68 -0
- package/dist/adapters/dispatcher-sse.js +11 -0
- package/dist/adapters/dispatcher-sse.js.map +1 -0
- package/dist/adapters/index.d.ts +12 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/mcp-catalog.d.ts +58 -0
- package/dist/adapters/mcp-catalog.js +9 -0
- package/dist/adapters/mcp-catalog.js.map +1 -0
- package/dist/adapters/prisma-rollout.d.ts +60 -0
- package/dist/adapters/prisma-rollout.js +7 -0
- package/dist/adapters/prisma-rollout.js.map +1 -0
- package/dist/chunk-24ZXP7FI.js +93 -0
- package/dist/chunk-24ZXP7FI.js.map +1 -0
- package/dist/chunk-2DA6Q6TN.js +126 -0
- package/dist/chunk-2DA6Q6TN.js.map +1 -0
- package/dist/chunk-37BBB2P2.js +73 -0
- package/dist/chunk-37BBB2P2.js.map +1 -0
- package/dist/chunk-57W3AR43.js +52 -0
- package/dist/chunk-57W3AR43.js.map +1 -0
- package/dist/chunk-5N4644PB.js +67 -0
- package/dist/chunk-5N4644PB.js.map +1 -0
- package/dist/chunk-5YS7WAPS.js +177 -0
- package/dist/chunk-5YS7WAPS.js.map +1 -0
- package/dist/chunk-6EGG2OZC.js +13 -0
- package/dist/chunk-6EGG2OZC.js.map +1 -0
- package/dist/chunk-7BUOF367.js +126 -0
- package/dist/chunk-7BUOF367.js.map +1 -0
- package/dist/chunk-BJBBR3QA.js +121 -0
- package/dist/chunk-BJBBR3QA.js.map +1 -0
- package/dist/chunk-CGRCUKGT.js +73 -0
- package/dist/chunk-CGRCUKGT.js.map +1 -0
- package/dist/chunk-FUG5DT2C.js +75 -0
- package/dist/chunk-FUG5DT2C.js.map +1 -0
- package/dist/chunk-LO24VOA3.js +199 -0
- package/dist/chunk-LO24VOA3.js.map +1 -0
- package/dist/chunk-MUF7ZZTO.js +57 -0
- package/dist/chunk-MUF7ZZTO.js.map +1 -0
- package/dist/chunk-NN7DATXA.js +46 -0
- package/dist/chunk-NN7DATXA.js.map +1 -0
- package/dist/chunk-PGGWSUTM.js +33 -0
- package/dist/chunk-PGGWSUTM.js.map +1 -0
- package/dist/chunk-RDKYDMXT.js +135 -0
- package/dist/chunk-RDKYDMXT.js.map +1 -0
- package/dist/chunk-YYFPDBJG.js +63 -0
- package/dist/chunk-YYFPDBJG.js.map +1 -0
- package/dist/chunk-ZMYX5VBU.js +135 -0
- package/dist/chunk-ZMYX5VBU.js.map +1 -0
- package/dist/chunk-ZTSKS42I.js +131 -0
- package/dist/chunk-ZTSKS42I.js.map +1 -0
- package/dist/commands.d.ts +74 -0
- package/dist/commands.js +10 -0
- package/dist/commands.js.map +1 -0
- package/dist/definitions.d.ts +94 -0
- package/dist/definitions.js +15 -0
- package/dist/definitions.js.map +1 -0
- package/dist/dispatcher.d.ts +50 -0
- package/dist/dispatcher.js +8 -0
- package/dist/dispatcher.js.map +1 -0
- package/dist/durable-turn.d.ts +58 -0
- package/dist/durable-turn.js +9 -0
- package/dist/durable-turn.js.map +1 -0
- package/dist/hook-pipeline.d.ts +114 -0
- package/dist/hook-pipeline.js +13 -0
- package/dist/hook-pipeline.js.map +1 -0
- package/dist/index.d.ts +1874 -0
- package/dist/index.js +3117 -0
- package/dist/index.js.map +1 -0
- package/dist/loop.d.ts +78 -0
- package/dist/loop.js +9 -0
- package/dist/loop.js.map +1 -0
- package/dist/mcp-bridge.d.ts +48 -0
- package/dist/mcp-bridge.js +8 -0
- package/dist/mcp-bridge.js.map +1 -0
- package/dist/model.d.ts +154 -0
- package/dist/model.js +9 -0
- package/dist/model.js.map +1 -0
- package/dist/policy.d.ts +130 -0
- package/dist/policy.js +23 -0
- package/dist/policy.js.map +1 -0
- package/dist/protocol.d.ts +170 -0
- package/dist/protocol.js +15 -0
- package/dist/protocol.js.map +1 -0
- package/dist/rollout-store-persistent.d.ts +48 -0
- package/dist/rollout-store-persistent.js +9 -0
- package/dist/rollout-store-persistent.js.map +1 -0
- package/dist/rollout.d.ts +82 -0
- package/dist/rollout.js +15 -0
- package/dist/rollout.js.map +1 -0
- package/dist/sandbox.d.ts +65 -0
- package/dist/sandbox.js +15 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/skills.d.ts +93 -0
- package/dist/skills.js +10 -0
- package/dist/skills.js.map +1 -0
- package/dist/subagents.d.ts +129 -0
- package/dist/subagents.js +21 -0
- package/dist/subagents.js.map +1 -0
- package/dist/tools.d.ts +77 -0
- package/dist/tools.js +9 -0
- package/dist/tools.js.map +1 -0
- package/package.json +74 -0
- package/src/adapters/dispatcher-sse.test.ts +218 -0
- package/src/adapters/dispatcher-sse.ts +222 -0
- package/src/adapters/index.ts +18 -0
- package/src/adapters/mcp-catalog.test.ts +213 -0
- package/src/adapters/mcp-catalog.ts +188 -0
- package/src/adapters/prisma-rollout.test.ts +153 -0
- package/src/adapters/prisma-rollout.ts +104 -0
- package/src/agent-runtime.test.ts +176 -0
- package/src/artifact-stream.test.ts +330 -0
- package/src/artifact-stream.ts +453 -0
- package/src/channel-gateway.test.ts +432 -0
- package/src/channel-gateway.ts +357 -0
- package/src/code-review.test.ts +501 -0
- package/src/code-review.ts +495 -0
- package/src/command-suggestions.test.ts +251 -0
- package/src/command-suggestions.ts +338 -0
- package/src/commands.test.ts +184 -0
- package/src/commands.ts +140 -0
- package/src/commit-message.test.ts +249 -0
- package/src/commit-message.ts +180 -0
- package/src/context-compaction.test.ts +522 -0
- package/src/context-compaction.ts +434 -0
- package/src/definitions.test.ts +78 -0
- package/src/definitions.ts +190 -0
- package/src/deployment-status.test.ts +215 -0
- package/src/deployment-status.ts +227 -0
- package/src/design-context.test.ts +195 -0
- package/src/design-context.ts +198 -0
- package/src/dispatcher.test.ts +234 -0
- package/src/dispatcher.ts +189 -0
- package/src/durable-turn.test.ts +209 -0
- package/src/durable-turn.ts +135 -0
- package/src/edit-planner.test.ts +204 -0
- package/src/edit-planner.ts +325 -0
- package/src/fuzzy-match.test.ts +311 -0
- package/src/fuzzy-match.ts +444 -0
- package/src/hook-pipeline.test.ts +279 -0
- package/src/hook-pipeline.ts +373 -0
- package/src/inbound-admission.test.ts +394 -0
- package/src/inbound-admission.ts +246 -0
- package/src/index.ts +47 -0
- package/src/loop.test.ts +161 -0
- package/src/loop.ts +211 -0
- package/src/mcp-bridge.test.ts +165 -0
- package/src/mcp-bridge.ts +76 -0
- package/src/memory-provider.test.ts +232 -0
- package/src/memory-provider.ts +257 -0
- package/src/model.ts +168 -0
- package/src/permission-ruleset.test.ts +301 -0
- package/src/permission-ruleset.ts +200 -0
- package/src/policy.ts +151 -0
- package/src/project-repo.test.ts +232 -0
- package/src/project-repo.ts +311 -0
- package/src/protocol.ts +159 -0
- package/src/rollout-store-persistent.test.ts +217 -0
- package/src/rollout-store-persistent.ts +166 -0
- package/src/rollout.ts +150 -0
- package/src/sandbox.ts +113 -0
- package/src/session-share.test.ts +360 -0
- package/src/session-share.ts +310 -0
- package/src/skill-distillation.test.ts +177 -0
- package/src/skill-distillation.ts +369 -0
- package/src/skills.test.ts +277 -0
- package/src/skills.ts +255 -0
- package/src/subagents.test.ts +290 -0
- package/src/subagents.ts +332 -0
- package/src/tools.ts +126 -0
- package/src/workbench.test.ts +0 -0
- package/src/workbench.ts +0 -0
- package/tsconfig.json +12 -0
- package/tsup.config.ts +33 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/dispatcher-sse.ts"],"sourcesContent":["/**\n * Runtime-agnostic SSE / HTTP transport binding for `ProtocolDispatcher`.\n *\n * Built on Web-standard primitives ONLY — `Request`, `Response`,\n * `ReadableStream`, `TextEncoder`, `AbortSignal`. There is no Hono / Express /\n * `node:http` dependency, so the same code runs unchanged on edge runtimes,\n * Cloudflare Workers, Deno, Bun, and Node (>=18, where these globals exist).\n *\n * Design goals:\n * - Pure functions returning Web objects; nothing is mutated in place.\n * - The dispatcher already fails closed on a missing `tenantId` (its\n * `requestEnvelopeSchema` makes `tenantId` mandatory). This binding does\n * not re-implement that policy — it faithfully relays the JSON-RPC error.\n * - Never throw across the transport boundary and never leak a stack trace:\n * a malformed body becomes a well-formed JSON-RPC parse error.\n *\n * Wire framing (SSE): each event is emitted as\n * `event: <ThreadEvent.type>\\n` + `data: <JSON(event)>\\n\\n`\n */\n\nimport type { ProtocolDispatcher } from \"../dispatcher\";\nimport type { ThreadEvent } from \"../model\";\nimport type { NotificationName } from \"../protocol\";\n\n// ── JSON-RPC constants ───────────────────────────────────────────────────────\n\n/** Spec code for \"Parse error\" — the request body was not valid JSON. */\nconst ERR_PARSE = -32700;\n\nconst JSON_HEADERS: Readonly<Record<string, string>> = {\n \"content-type\": \"application/json; charset=utf-8\",\n};\n\n/** A self-contained JSON-RPC failure envelope (used only for parse errors;\n * every other failure path is produced by the dispatcher itself). */\nfunction parseErrorEnvelope(message: string): {\n readonly jsonrpc: \"2.0\";\n readonly id: null;\n readonly error: { readonly code: number; readonly message: string };\n} {\n return { jsonrpc: \"2.0\", id: null, error: { code: ERR_PARSE, message } };\n}\n\nfunction jsonResponse(payload: unknown, status: number): Response {\n return new Response(JSON.stringify(payload), { status, headers: { ...JSON_HEADERS } });\n}\n\n// ── HTTP / JSON-RPC handler ──────────────────────────────────────────────────\n\n/**\n * Build a Web-standard request handler bound to a dispatcher.\n *\n * Contract:\n * - Unparseable body → `400` with a JSON-RPC parse-error envelope.\n * - Any parseable body (incl. missing tenant / unknown method / handler\n * failure) → `200` with the dispatcher's own JSON-RPC envelope. The HTTP\n * layer stays `200` for business-level JSON-RPC errors per JSON-RPC-over-\n * HTTP convention; the error lives in the envelope, not the status line.\n * - The returned function never throws and never emits a 500-with-stack.\n */\nexport function createRpcHandler(\n dispatcher: ProtocolDispatcher,\n): (request: Request) => Promise<Response> {\n return async (request: Request): Promise<Response> => {\n let raw: unknown;\n try {\n raw = await request.json();\n } catch {\n return jsonResponse(parseErrorEnvelope(\"Request body is not valid JSON\"), 400);\n }\n\n // `dispatch` is documented to never throw; the try/catch is defence in\n // depth so the transport boundary is total under any future change.\n try {\n const envelope = await dispatcher.dispatch(raw);\n return jsonResponse(envelope, 200);\n } catch {\n return jsonResponse(parseErrorEnvelope(\"Dispatcher failure\"), 400);\n }\n };\n}\n\n// ── SSE streaming ────────────────────────────────────────────────────────────\n\nexport interface SseOptions {\n /** Cancels the stream cleanly; closing the consumer also cancels it. */\n readonly signal?: AbortSignal;\n}\n\n/** Encode one `ThreadEvent` as a single SSE frame. */\nfunction frame(event: ThreadEvent): string {\n return `event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`;\n}\n\n/** Encode a terminal transport-level error as an `event: error` SSE frame. */\nfunction errorFrame(message: string): string {\n return `event: error\\ndata: ${JSON.stringify({ type: \"error\", message })}\\n\\n`;\n}\n\n/**\n * Adapt an async `ThreadEvent` stream into a Web-standard\n * `text/event-stream` `Response`.\n *\n * Guarantees:\n * - Incremental flush: each event is enqueued as soon as it is produced.\n * - Clean termination: the stream closes when the iterable is exhausted.\n * - Error surfacing: an iterable error is emitted as a final\n * `event: error` frame, then the stream closes (it never hangs).\n * - Cancellation: an aborted `signal` (or a cancelled reader) stops\n * pulling from the source and releases its iterator.\n */\nexport function sseResponse(stream: AsyncIterable<ThreadEvent>, opts?: SseOptions): Response {\n const encoder = new TextEncoder();\n const signal = opts?.signal;\n\n const body = new ReadableStream<Uint8Array>({\n async start(controller) {\n const iterator = stream[Symbol.asyncIterator]();\n\n const onAbort = () => {\n void iterator.return?.(undefined);\n };\n if (signal) {\n if (signal.aborted) {\n await iterator.return?.(undefined);\n controller.close();\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n try {\n for (;;) {\n if (signal?.aborted) break;\n const next = await iterator.next();\n if (next.done) break;\n controller.enqueue(encoder.encode(frame(next.value)));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Stream error\";\n controller.enqueue(encoder.encode(errorFrame(message)));\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n controller.close();\n }\n },\n cancel() {\n // Consumer hung up: best-effort release of the upstream iterator.\n void stream[Symbol.asyncIterator]().return?.(undefined);\n },\n });\n\n return new Response(body, {\n status: 200,\n headers: {\n \"content-type\": \"text/event-stream; charset=utf-8\",\n \"cache-control\": \"no-cache, no-transform\",\n connection: \"keep-alive\",\n },\n });\n}\n\n// ── Notification → async-iterable bridge ─────────────────────────────────────\n\nexport interface NotificationFrame {\n readonly name: NotificationName;\n readonly payload: unknown;\n}\n\n/**\n * Bridge `dispatcher.onNotification` (a push listener API) into a pull-based\n * `AsyncIterable`. A bounded backlog buffers events that arrive between\n * `next()` calls; pending readers are resolved immediately when an event\n * arrives. Calling `return()` (or breaking a `for await`) unsubscribes every\n * underlying listener — no leaks, fail-closed teardown.\n */\nexport function subscribeNotifications(\n dispatcher: ProtocolDispatcher,\n names: readonly NotificationName[],\n): AsyncIterable<NotificationFrame> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<NotificationFrame> {\n const backlog: NotificationFrame[] = [];\n const waiters: Array<(r: IteratorResult<NotificationFrame>) => void> = [];\n let closed = false;\n\n const unsubscribers = names.map((name) =>\n dispatcher.onNotification(name, (payload) => {\n if (closed) return;\n const value: NotificationFrame = { name, payload };\n const waiter = waiters.shift();\n if (waiter) waiter({ value, done: false });\n else backlog.push(value);\n }),\n );\n\n const teardown = (): void => {\n if (closed) return;\n closed = true;\n for (const off of unsubscribers) off();\n let waiter = waiters.shift();\n while (waiter) {\n waiter({ value: undefined, done: true });\n waiter = waiters.shift();\n }\n };\n\n return {\n next(): Promise<IteratorResult<NotificationFrame>> {\n const buffered = backlog.shift();\n if (buffered) return Promise.resolve({ value: buffered, done: false });\n if (closed) return Promise.resolve({ value: undefined, done: true });\n return new Promise((resolve) => waiters.push(resolve));\n },\n return(): Promise<IteratorResult<NotificationFrame>> {\n teardown();\n return Promise.resolve({ value: undefined, done: true });\n },\n };\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Definition, ResolveContext } from './definitions.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Slash-command registry — faithful re-expression of the unified command model.
|
|
6
|
+
*
|
|
7
|
+
* Semantic model:
|
|
8
|
+
* - A command and a skill are the SAME underlying type. `CommandRecord` is just
|
|
9
|
+
* a `Definition`. The only differences are carried in the record itself:
|
|
10
|
+
* `sourceTier`, and the `userInvocable` / `modelInvocable` frontmatter flags.
|
|
11
|
+
* - Slash invocation (a human types `/deploy`) and model invocation (the model
|
|
12
|
+
* auto-triggers) are two FRONT-DOORS to ONE expansion path.
|
|
13
|
+
* - The registry IS a `DefinitionResolver<CommandRecord>` (layered tier merge +
|
|
14
|
+
* precedence + dual gate are provided by definitions.ts — reused, not rebuilt).
|
|
15
|
+
* `CommandRegistry` is a thin wrapper exposing the two front-doors; both
|
|
16
|
+
* recompute per call so entitlement/flag changes apply live.
|
|
17
|
+
*
|
|
18
|
+
* Scope note: the source harness also has `local` / `local-jsx` command kinds
|
|
19
|
+
* that run TUI-side JSX. Those are intentionally DROPPED here — a server runtime
|
|
20
|
+
* only needs the prompt-expansion path. This module models that path only.
|
|
21
|
+
*
|
|
22
|
+
* Multi-tenant: `tenantId` is mandatory at every entry point; an empty tenant
|
|
23
|
+
* throws (fail-closed); cross-tenant resolution is impossible (the underlying
|
|
24
|
+
* resolver rejects foreign-tenant records).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A command IS a Definition. No new fields — the distinction between "command"
|
|
29
|
+
* and "skill" is purely the `sourceTier` + invocability flags already present.
|
|
30
|
+
*/
|
|
31
|
+
type CommandRecord = Definition;
|
|
32
|
+
/** Lazily loads a command's body text (FS / blob / remote — caller's choice). */
|
|
33
|
+
type BodyLoader = (cmd: CommandRecord) => Promise<string>;
|
|
34
|
+
/** One content block destined for the model turn. */
|
|
35
|
+
interface ContentBlock {
|
|
36
|
+
readonly role: "user";
|
|
37
|
+
readonly content: string;
|
|
38
|
+
}
|
|
39
|
+
/** Result of expanding a command — declarative only; no enforcement here. */
|
|
40
|
+
interface ExpandedCommand {
|
|
41
|
+
/** Prompt blocks to splice into the turn. */
|
|
42
|
+
readonly contentBlocks: readonly ContentBlock[];
|
|
43
|
+
/** Tools the command self-declares for the permission context. */
|
|
44
|
+
readonly allowedTools: readonly string[];
|
|
45
|
+
/** Model alias to switch to, if the command pins one (not "inherit"). */
|
|
46
|
+
readonly modelOverride?: string | undefined;
|
|
47
|
+
/** Reasoning effort hint, if declared. */
|
|
48
|
+
readonly effort?: "low" | "medium" | "high" | undefined;
|
|
49
|
+
/** inline = expand into current turn; fork = isolated child. */
|
|
50
|
+
readonly executionMode: "inline" | "fork";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Pure expansion. Loads the body lazily (exactly once), substitutes named args
|
|
54
|
+
* and a tenant-safe variable map (only the explicitly injected `variables` —
|
|
55
|
+
* never `process.env`), and returns the declarative execution context.
|
|
56
|
+
*/
|
|
57
|
+
declare function expandCommand(cmd: CommandRecord, argInput: string, variables: Readonly<Record<string, string>>, bodyLoader: BodyLoader): Promise<ExpandedCommand>;
|
|
58
|
+
/**
|
|
59
|
+
* Thin tenant-scoped wrapper over `DefinitionResolver<CommandRecord>`. Exposes
|
|
60
|
+
* the two front-doors. Tier merge / precedence / dual gate / tenant isolation
|
|
61
|
+
* are delegated to the resolver — this class only filters by invocability.
|
|
62
|
+
*/
|
|
63
|
+
declare class CommandRegistry {
|
|
64
|
+
#private;
|
|
65
|
+
constructor(commands: readonly CommandRecord[]);
|
|
66
|
+
/** Commands a human may type as a slash command. */
|
|
67
|
+
listForUser(ctx: ResolveContext): CommandRecord[];
|
|
68
|
+
/** Commands the model may auto-trigger. */
|
|
69
|
+
listForModel(ctx: ResolveContext): CommandRecord[];
|
|
70
|
+
/** Highest-precedence gated record for a slug (no invocability filter). */
|
|
71
|
+
resolveOne(slug: string, ctx: ResolveContext): CommandRecord | undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type BodyLoader, type CommandRecord, CommandRegistry, type ContentBlock, type ExpandedCommand, expandCommand };
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared definition kernel (WRAP — Claude-Code-class harness, the delta).
|
|
5
|
+
*
|
|
6
|
+
* Faithful re-expression of the source harness's layered-merge + precedence +
|
|
7
|
+
* dual-gate resolver and its frontmatter→record parser. One implementation
|
|
8
|
+
* backs the command registry, the skill catalog, and the subagent-definition
|
|
9
|
+
* registry (the source uses the same loader for all three).
|
|
10
|
+
*
|
|
11
|
+
* Multi-tenant: every resolution is keyed by `tenantId`; tiers from one tenant
|
|
12
|
+
* never merge into another. Pure data/logic — no FS scan, no shell, no TUI.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Source-tier precedence, low → high authority. A later tier overrides an
|
|
17
|
+
* earlier one on slug collision (mirrors the upstream merge order:
|
|
18
|
+
* bundled → builtin → workspace → workflow → plugin → dynamic, with
|
|
19
|
+
* org policy as the final, non-overridable authority).
|
|
20
|
+
*/
|
|
21
|
+
declare const SOURCE_TIERS: readonly ["bundled", "builtin", "workspace", "workflow", "plugin", "dynamic", "policy"];
|
|
22
|
+
type SourceTier = (typeof SOURCE_TIERS)[number];
|
|
23
|
+
/** Frontmatter shared by skills / commands / subagents (faithful subset). */
|
|
24
|
+
declare const frontmatterSchema: z.ZodObject<{
|
|
25
|
+
name: z.ZodString;
|
|
26
|
+
description: z.ZodDefault<z.ZodString>;
|
|
27
|
+
allowedTools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
28
|
+
disallowedTools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
29
|
+
argumentHint: z.ZodOptional<z.ZodString>;
|
|
30
|
+
argNames: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
31
|
+
whenToUse: z.ZodOptional<z.ZodString>;
|
|
32
|
+
version: z.ZodOptional<z.ZodString>;
|
|
33
|
+
model: z.ZodOptional<z.ZodString>;
|
|
34
|
+
effort: z.ZodOptional<z.ZodEnum<{
|
|
35
|
+
low: "low";
|
|
36
|
+
medium: "medium";
|
|
37
|
+
high: "high";
|
|
38
|
+
}>>;
|
|
39
|
+
modelInvocable: z.ZodDefault<z.ZodBoolean>;
|
|
40
|
+
userInvocable: z.ZodDefault<z.ZodBoolean>;
|
|
41
|
+
executionMode: z.ZodDefault<z.ZodEnum<{
|
|
42
|
+
inline: "inline";
|
|
43
|
+
fork: "fork";
|
|
44
|
+
}>>;
|
|
45
|
+
agent: z.ZodOptional<z.ZodString>;
|
|
46
|
+
paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
47
|
+
}, z.core.$strip>;
|
|
48
|
+
type Frontmatter = z.infer<typeof frontmatterSchema>;
|
|
49
|
+
/**
|
|
50
|
+
* Parse a `--- … ---` frontmatter block + remaining body. Dependency-light
|
|
51
|
+
* line parser (the package only depends on zod) — sufficient for the simple
|
|
52
|
+
* key: value / list frontmatter the source uses. Throws on missing block.
|
|
53
|
+
*/
|
|
54
|
+
declare function parseFrontmatter(raw: string): {
|
|
55
|
+
frontmatter: Frontmatter;
|
|
56
|
+
body: string;
|
|
57
|
+
};
|
|
58
|
+
/** A resolvable definition of any kind (skill / command / subagent). */
|
|
59
|
+
interface Definition {
|
|
60
|
+
readonly slug: string;
|
|
61
|
+
readonly tenantId: string;
|
|
62
|
+
readonly sourceTier: SourceTier;
|
|
63
|
+
readonly frontmatter: Frontmatter;
|
|
64
|
+
readonly bodyRef: string;
|
|
65
|
+
/** Entitlement gate — who may have this at all. */
|
|
66
|
+
readonly availabilityPlans?: readonly string[];
|
|
67
|
+
/** Runtime/feature toggle, recomputed per request. */
|
|
68
|
+
readonly enabled?: boolean;
|
|
69
|
+
}
|
|
70
|
+
interface ResolveContext {
|
|
71
|
+
readonly tenantId: string;
|
|
72
|
+
readonly plan?: string;
|
|
73
|
+
/** Names already loaded this session (suppressed from re-listing). */
|
|
74
|
+
readonly loadedSlugs?: ReadonlySet<string>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Tenant-scoped layered resolver. Merges definitions by slug with tier
|
|
78
|
+
* precedence and applies the dual gate (availability ∧ enabled), recomputed
|
|
79
|
+
* per call so entitlement/flag changes apply live. Cross-tenant inputs are
|
|
80
|
+
* rejected — fail closed.
|
|
81
|
+
*/
|
|
82
|
+
declare class DefinitionResolver<T extends Definition = Definition> {
|
|
83
|
+
#private;
|
|
84
|
+
constructor(definitions: readonly T[]);
|
|
85
|
+
/** Entitlement gate. */
|
|
86
|
+
static available(def: Definition, plan?: string): boolean;
|
|
87
|
+
resolve(ctx: ResolveContext): T[];
|
|
88
|
+
/** Resolve a single slug (highest-precedence, gated). */
|
|
89
|
+
resolveOne(slug: string, ctx: ResolveContext): T | undefined;
|
|
90
|
+
}
|
|
91
|
+
/** Substitute `${name}` / positional `$1` args + session/dir variables. */
|
|
92
|
+
declare function substituteArguments(template: string, args: Record<string, string>, variables?: Record<string, string>): string;
|
|
93
|
+
|
|
94
|
+
export { type Definition, DefinitionResolver, type Frontmatter, type ResolveContext, SOURCE_TIERS, type SourceTier, frontmatterSchema, parseFrontmatter, substituteArguments };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DefinitionResolver,
|
|
3
|
+
SOURCE_TIERS,
|
|
4
|
+
frontmatterSchema,
|
|
5
|
+
parseFrontmatter,
|
|
6
|
+
substituteArguments
|
|
7
|
+
} from "./chunk-7BUOF367.js";
|
|
8
|
+
export {
|
|
9
|
+
DefinitionResolver,
|
|
10
|
+
SOURCE_TIERS,
|
|
11
|
+
frontmatterSchema,
|
|
12
|
+
parseFrontmatter,
|
|
13
|
+
substituteArguments
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=definitions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SerializationScope, NotificationName } from './protocol.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Transport-agnostic JSON-RPC dispatcher for the app-server protocol.
|
|
6
|
+
*
|
|
7
|
+
* Pure and testable: no sockets. WS/SSE/stdio adapters wrap this dispatcher
|
|
8
|
+
* and are intentionally out of scope here.
|
|
9
|
+
*
|
|
10
|
+
* Faithful concurrency model (see `protocol.ts`): requests sharing a
|
|
11
|
+
* `scopeKey` are serialized FIFO; distinct scope keys run concurrently.
|
|
12
|
+
* Because every scope is tenant-prefixed, cross-tenant requests can never
|
|
13
|
+
* share a serial lane (fail-closed multi-tenancy by construction).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
type MethodHandler = (params: unknown, scope: SerializationScope) => Promise<unknown>;
|
|
17
|
+
type NotificationListener = (payload: unknown) => void;
|
|
18
|
+
interface JsonRpcSuccess {
|
|
19
|
+
readonly jsonrpc: "2.0";
|
|
20
|
+
readonly id: string | number | null;
|
|
21
|
+
readonly result: unknown;
|
|
22
|
+
}
|
|
23
|
+
interface JsonRpcFailure {
|
|
24
|
+
readonly jsonrpc: "2.0";
|
|
25
|
+
readonly id: string | number | null;
|
|
26
|
+
readonly error: {
|
|
27
|
+
readonly code: number;
|
|
28
|
+
readonly message: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
type JsonRpcResponse = JsonRpcSuccess | JsonRpcFailure;
|
|
32
|
+
declare class ProtocolDispatcher {
|
|
33
|
+
#private;
|
|
34
|
+
/** Register a handler for a wire method name (e.g. `"turn/start"`). */
|
|
35
|
+
register(methodName: string, handler: MethodHandler): this;
|
|
36
|
+
/** Subscribe to a server→client notification. */
|
|
37
|
+
onNotification(name: NotificationName, listener: NotificationListener): () => void;
|
|
38
|
+
/**
|
|
39
|
+
* Emit a server→client notification. Validates the name against the
|
|
40
|
+
* `NOTIFICATIONS` allow-list (fail-closed: unknown name throws).
|
|
41
|
+
*/
|
|
42
|
+
emitNotification(name: NotificationName, payload: unknown): void;
|
|
43
|
+
/**
|
|
44
|
+
* Dispatch a single raw envelope. Never throws — every failure path maps
|
|
45
|
+
* to a JSON-RPC error response.
|
|
46
|
+
*/
|
|
47
|
+
dispatch(rawEnvelope: unknown): Promise<JsonRpcResponse>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { type JsonRpcResponse, type MethodHandler, type NotificationListener, ProtocolDispatcher };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ThreadEvent } from './model.js';
|
|
2
|
+
import { RolloutStore } from './rollout.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Durable / resumable turn (WRAP — capability #10).
|
|
6
|
+
*
|
|
7
|
+
* Wraps the existing {@link runTurn} async generator so a turn survives a
|
|
8
|
+
* process crash. `start` enqueues a tenant+thread-scoped durable job whose
|
|
9
|
+
* handler drains `runTurn` (the loop runner already appends every event to the
|
|
10
|
+
* tenant-scoped {@link RolloutStore}); the durable layer guarantees the job is
|
|
11
|
+
* replayable if the worker dies mid-turn. `resume` inspects the persisted
|
|
12
|
+
* rollout: if the last recorded event is non-terminal the turn is re-driven to
|
|
13
|
+
* completion, otherwise the recorded terminal stream is replayed.
|
|
14
|
+
*
|
|
15
|
+
* Queue binding is interface-only — callers wire `@nebutra/queue` by
|
|
16
|
+
* implementing {@link DurableTurnQueuePort}; this package never depends on it.
|
|
17
|
+
* Tenant scoping is mandatory and fail-closed: a missing tenant or thread
|
|
18
|
+
* throws, and resume can never read another tenant's rollout.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** A durable job handed to the queue. Mirrors `@nebutra/queue` job shape. */
|
|
22
|
+
interface DurableTurnJob {
|
|
23
|
+
/** Logical job name — used for handler routing. */
|
|
24
|
+
readonly name: string;
|
|
25
|
+
/** Tenant+thread-scoped id; the queue must de-dupe / make idempotent on it. */
|
|
26
|
+
readonly jobId: string;
|
|
27
|
+
/** Opaque Zod-validated payload (kept narrow on purpose). */
|
|
28
|
+
readonly payload: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Minimal injectable queue seam (enqueue + handler registration). Mirrors
|
|
32
|
+
* `@nebutra/queue`'s `defineQueueJob` / `createJobRouter` contract without a
|
|
33
|
+
* hard dependency, so this package stays provider-agnostic.
|
|
34
|
+
*/
|
|
35
|
+
interface DurableTurnQueuePort {
|
|
36
|
+
enqueue(job: DurableTurnJob): Promise<void>;
|
|
37
|
+
registerHandler(name: string, handler: (payload: unknown) => Promise<void>): void;
|
|
38
|
+
}
|
|
39
|
+
/** Drives one turn, yielding the event stream (persists internally). */
|
|
40
|
+
type DurableTurnRunner = (input: string, ctx: TurnContext) => AsyncGenerator<ThreadEvent>;
|
|
41
|
+
interface TurnContext {
|
|
42
|
+
readonly tenantId: string;
|
|
43
|
+
readonly threadId: string;
|
|
44
|
+
}
|
|
45
|
+
interface CreateDurableTurnDeps {
|
|
46
|
+
readonly store: RolloutStore;
|
|
47
|
+
readonly queue: DurableTurnQueuePort;
|
|
48
|
+
readonly runner: DurableTurnRunner;
|
|
49
|
+
}
|
|
50
|
+
interface DurableTurn {
|
|
51
|
+
start(input: string, ctx: TurnContext): Promise<{
|
|
52
|
+
readonly turnId: string;
|
|
53
|
+
}>;
|
|
54
|
+
resume(tenantId: string, threadId: string): AsyncGenerator<ThreadEvent>;
|
|
55
|
+
}
|
|
56
|
+
declare function createDurableTurn(deps: CreateDurableTurnDeps): DurableTurn;
|
|
57
|
+
|
|
58
|
+
export { type CreateDurableTurnDeps, type DurableTurn, type DurableTurnJob, type DurableTurnQueuePort, type DurableTurnRunner, type TurnContext, createDurableTurn };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ToolDispatchContext, ToolHooks } from './tools.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook pipeline (WRAP — config-driven orchestrator hooks).
|
|
6
|
+
*
|
|
7
|
+
* Faithful re-expression of the upstream config-driven, decision-returning
|
|
8
|
+
* hook system. This is the configuration layer ABOVE the bare {@link ToolHooks}
|
|
9
|
+
* interface in `./tools.js`: events are matched by an event + matcher
|
|
10
|
+
* (+ optional ifCondition), fanned out to transports in parallel, and merged
|
|
11
|
+
* into a single deterministic {@link HookOutcome}.
|
|
12
|
+
*
|
|
13
|
+
* MULTI-TENANT SAFETY — the upstream `command`/shell/async (host-process)
|
|
14
|
+
* transports are deliberately DROPPED. In a multi-tenant runtime, executing a
|
|
15
|
+
* tenant-supplied host command is unbounded RCE against the shared process and
|
|
16
|
+
* cannot be sandboxed at this layer. Only in-process `function`, caller-fetched
|
|
17
|
+
* `http`, and caller-injected `prompt` transports are supported — each fails
|
|
18
|
+
* closed and cannot reach the host shell.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Event taxonomy — ported verbatim from the upstream hook system.
|
|
23
|
+
* The matcher is matched against the tool name (tool events) or the event
|
|
24
|
+
* name itself (lifecycle events).
|
|
25
|
+
*/
|
|
26
|
+
type HookEvent = "PreToolUse" | "PostToolUse" | "PostToolUseFailure" | "UserPromptSubmit" | "SessionStart" | "SessionEnd" | "Stop" | "StopFailure" | "SubagentStart" | "SubagentStop" | "PreCompact" | "PostCompact" | "PermissionRequest" | "PermissionDenied" | "TaskCreated" | "TaskCompleted" | "ConfigChange" | "FileChanged";
|
|
27
|
+
/** Tenant-scoped context — reuses the dispatch context shape from `./tools.js`. */
|
|
28
|
+
type HookContext = ToolDispatchContext;
|
|
29
|
+
/** The event payload presented to a transport. */
|
|
30
|
+
interface HookPayload {
|
|
31
|
+
/** The tool name (tool events) or event name (lifecycle events). */
|
|
32
|
+
readonly name: string;
|
|
33
|
+
/** Parsed tool/event input. */
|
|
34
|
+
readonly input: unknown;
|
|
35
|
+
/** Tool output (only present for Post* events). */
|
|
36
|
+
readonly toolOutput?: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decision protocol — ported verbatim. A transport returns a PARTIAL outcome;
|
|
40
|
+
* the pipeline merges all partials with deterministic precedence.
|
|
41
|
+
*/
|
|
42
|
+
interface HookOutcome {
|
|
43
|
+
readonly preventContinuation?: boolean | undefined;
|
|
44
|
+
readonly stopReason?: string | undefined;
|
|
45
|
+
readonly permissionBehavior?: "allow" | "deny" | "ask" | undefined;
|
|
46
|
+
readonly blockingError?: string | undefined;
|
|
47
|
+
readonly additionalContext?: string | undefined;
|
|
48
|
+
readonly updatedInput?: unknown;
|
|
49
|
+
readonly updatedToolOutput?: unknown;
|
|
50
|
+
readonly systemMessage?: string | undefined;
|
|
51
|
+
}
|
|
52
|
+
/** Exit-code-style lane for the function transport. */
|
|
53
|
+
interface HookExitResult {
|
|
54
|
+
readonly code: number;
|
|
55
|
+
readonly stdout?: string;
|
|
56
|
+
readonly stderr?: string;
|
|
57
|
+
}
|
|
58
|
+
type FunctionRunResult = Partial<HookOutcome> | HookExitResult;
|
|
59
|
+
/** In-process transport — the tenant-safe default. */
|
|
60
|
+
interface FunctionTransport {
|
|
61
|
+
readonly kind: "function";
|
|
62
|
+
readonly run: (payload: HookPayload, ctx: HookContext) => Promise<FunctionRunResult>;
|
|
63
|
+
}
|
|
64
|
+
/** HTTP transport — caller injects `fetchImpl`; absolute https + fail-closed. */
|
|
65
|
+
interface HttpTransport {
|
|
66
|
+
readonly kind: "http";
|
|
67
|
+
readonly url: string;
|
|
68
|
+
readonly allowEnvVars?: readonly string[];
|
|
69
|
+
readonly fetchImpl: (url: string, init: RequestInit) => Promise<Response>;
|
|
70
|
+
}
|
|
71
|
+
/** Prompt transport — caller injects the LLM evaluator. */
|
|
72
|
+
interface PromptTransport {
|
|
73
|
+
readonly kind: "prompt";
|
|
74
|
+
readonly model: string;
|
|
75
|
+
readonly llmEval: (payload: HookPayload, ctx: HookContext) => Promise<Partial<HookOutcome>>;
|
|
76
|
+
}
|
|
77
|
+
type HookTransport = FunctionTransport | HttpTransport | PromptTransport;
|
|
78
|
+
/** A single hook configuration entry. */
|
|
79
|
+
interface HookConfig {
|
|
80
|
+
readonly event: HookEvent;
|
|
81
|
+
/** `"*"` | exact | pipe-list (`"Write|Edit"`) | `/regex/`. */
|
|
82
|
+
readonly matcher: string;
|
|
83
|
+
/** Predicate over parsed input, evaluated BEFORE the transport runs. */
|
|
84
|
+
readonly ifCondition?: (input: unknown, ctx: HookContext) => boolean;
|
|
85
|
+
readonly transport: HookTransport;
|
|
86
|
+
}
|
|
87
|
+
/** Out-of-band progress event — decoupled from outcomes. */
|
|
88
|
+
interface HookProgressEvent {
|
|
89
|
+
readonly phase: "started" | "completed";
|
|
90
|
+
readonly event: HookEvent;
|
|
91
|
+
readonly matcher: string;
|
|
92
|
+
readonly tenantId: string;
|
|
93
|
+
}
|
|
94
|
+
type HookProgressListener = (e: HookProgressEvent) => void;
|
|
95
|
+
/** Subscribe to out-of-band hook progress. Returns an unsubscribe function. */
|
|
96
|
+
declare function onHookEvent(listener: HookProgressListener): () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Pure matcher: `"*"` | exact | pipe-list | `/regex/`.
|
|
99
|
+
*/
|
|
100
|
+
declare function matchesMatcher(matcher: string, name: string): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Select matching hooks, fan out in parallel, merge with deterministic
|
|
103
|
+
* precedence. tenantId is mandatory — empty fails closed (throws).
|
|
104
|
+
*/
|
|
105
|
+
declare function runHooks(event: HookEvent, payload: HookPayload, hooks: ReadonlyArray<HookConfig>, ctx: HookContext): Promise<HookOutcome>;
|
|
106
|
+
/**
|
|
107
|
+
* Adapt the bare {@link ToolHooks} interface (from `./tools.js`) into
|
|
108
|
+
* config-driven function-transport entries — the in-process transport feeding
|
|
109
|
+
* the lower layer. preToolUse/postToolUse are void-returning, so the produced
|
|
110
|
+
* outcome is always empty (they observe; they do not decide here).
|
|
111
|
+
*/
|
|
112
|
+
declare function fromToolHooks(toolHooks: ToolHooks): HookConfig[];
|
|
113
|
+
|
|
114
|
+
export { type FunctionTransport, type HookConfig, type HookContext, type HookEvent, type HookExitResult, type HookOutcome, type HookPayload, type HookProgressEvent, type HookTransport, type HttpTransport, type PromptTransport, fromToolHooks, matchesMatcher, onHookEvent, runHooks };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|