@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.
Files changed (179) hide show
  1. package/.turbo/turbo-build.log +115 -0
  2. package/.turbo/turbo-test.log +44 -0
  3. package/.turbo/turbo-typecheck.log +4 -0
  4. package/CHANGELOG.md +253 -0
  5. package/LICENSE +676 -0
  6. package/README.md +50 -0
  7. package/dist/adapters/dispatcher-sse.d.ts +68 -0
  8. package/dist/adapters/dispatcher-sse.js +11 -0
  9. package/dist/adapters/dispatcher-sse.js.map +1 -0
  10. package/dist/adapters/index.d.ts +12 -0
  11. package/dist/adapters/index.js +21 -0
  12. package/dist/adapters/index.js.map +1 -0
  13. package/dist/adapters/mcp-catalog.d.ts +58 -0
  14. package/dist/adapters/mcp-catalog.js +9 -0
  15. package/dist/adapters/mcp-catalog.js.map +1 -0
  16. package/dist/adapters/prisma-rollout.d.ts +60 -0
  17. package/dist/adapters/prisma-rollout.js +7 -0
  18. package/dist/adapters/prisma-rollout.js.map +1 -0
  19. package/dist/chunk-24ZXP7FI.js +93 -0
  20. package/dist/chunk-24ZXP7FI.js.map +1 -0
  21. package/dist/chunk-2DA6Q6TN.js +126 -0
  22. package/dist/chunk-2DA6Q6TN.js.map +1 -0
  23. package/dist/chunk-37BBB2P2.js +73 -0
  24. package/dist/chunk-37BBB2P2.js.map +1 -0
  25. package/dist/chunk-57W3AR43.js +52 -0
  26. package/dist/chunk-57W3AR43.js.map +1 -0
  27. package/dist/chunk-5N4644PB.js +67 -0
  28. package/dist/chunk-5N4644PB.js.map +1 -0
  29. package/dist/chunk-5YS7WAPS.js +177 -0
  30. package/dist/chunk-5YS7WAPS.js.map +1 -0
  31. package/dist/chunk-6EGG2OZC.js +13 -0
  32. package/dist/chunk-6EGG2OZC.js.map +1 -0
  33. package/dist/chunk-7BUOF367.js +126 -0
  34. package/dist/chunk-7BUOF367.js.map +1 -0
  35. package/dist/chunk-BJBBR3QA.js +121 -0
  36. package/dist/chunk-BJBBR3QA.js.map +1 -0
  37. package/dist/chunk-CGRCUKGT.js +73 -0
  38. package/dist/chunk-CGRCUKGT.js.map +1 -0
  39. package/dist/chunk-FUG5DT2C.js +75 -0
  40. package/dist/chunk-FUG5DT2C.js.map +1 -0
  41. package/dist/chunk-LO24VOA3.js +199 -0
  42. package/dist/chunk-LO24VOA3.js.map +1 -0
  43. package/dist/chunk-MUF7ZZTO.js +57 -0
  44. package/dist/chunk-MUF7ZZTO.js.map +1 -0
  45. package/dist/chunk-NN7DATXA.js +46 -0
  46. package/dist/chunk-NN7DATXA.js.map +1 -0
  47. package/dist/chunk-PGGWSUTM.js +33 -0
  48. package/dist/chunk-PGGWSUTM.js.map +1 -0
  49. package/dist/chunk-RDKYDMXT.js +135 -0
  50. package/dist/chunk-RDKYDMXT.js.map +1 -0
  51. package/dist/chunk-YYFPDBJG.js +63 -0
  52. package/dist/chunk-YYFPDBJG.js.map +1 -0
  53. package/dist/chunk-ZMYX5VBU.js +135 -0
  54. package/dist/chunk-ZMYX5VBU.js.map +1 -0
  55. package/dist/chunk-ZTSKS42I.js +131 -0
  56. package/dist/chunk-ZTSKS42I.js.map +1 -0
  57. package/dist/commands.d.ts +74 -0
  58. package/dist/commands.js +10 -0
  59. package/dist/commands.js.map +1 -0
  60. package/dist/definitions.d.ts +94 -0
  61. package/dist/definitions.js +15 -0
  62. package/dist/definitions.js.map +1 -0
  63. package/dist/dispatcher.d.ts +50 -0
  64. package/dist/dispatcher.js +8 -0
  65. package/dist/dispatcher.js.map +1 -0
  66. package/dist/durable-turn.d.ts +58 -0
  67. package/dist/durable-turn.js +9 -0
  68. package/dist/durable-turn.js.map +1 -0
  69. package/dist/hook-pipeline.d.ts +114 -0
  70. package/dist/hook-pipeline.js +13 -0
  71. package/dist/hook-pipeline.js.map +1 -0
  72. package/dist/index.d.ts +1874 -0
  73. package/dist/index.js +3117 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/loop.d.ts +78 -0
  76. package/dist/loop.js +9 -0
  77. package/dist/loop.js.map +1 -0
  78. package/dist/mcp-bridge.d.ts +48 -0
  79. package/dist/mcp-bridge.js +8 -0
  80. package/dist/mcp-bridge.js.map +1 -0
  81. package/dist/model.d.ts +154 -0
  82. package/dist/model.js +9 -0
  83. package/dist/model.js.map +1 -0
  84. package/dist/policy.d.ts +130 -0
  85. package/dist/policy.js +23 -0
  86. package/dist/policy.js.map +1 -0
  87. package/dist/protocol.d.ts +170 -0
  88. package/dist/protocol.js +15 -0
  89. package/dist/protocol.js.map +1 -0
  90. package/dist/rollout-store-persistent.d.ts +48 -0
  91. package/dist/rollout-store-persistent.js +9 -0
  92. package/dist/rollout-store-persistent.js.map +1 -0
  93. package/dist/rollout.d.ts +82 -0
  94. package/dist/rollout.js +15 -0
  95. package/dist/rollout.js.map +1 -0
  96. package/dist/sandbox.d.ts +65 -0
  97. package/dist/sandbox.js +15 -0
  98. package/dist/sandbox.js.map +1 -0
  99. package/dist/skills.d.ts +93 -0
  100. package/dist/skills.js +10 -0
  101. package/dist/skills.js.map +1 -0
  102. package/dist/subagents.d.ts +129 -0
  103. package/dist/subagents.js +21 -0
  104. package/dist/subagents.js.map +1 -0
  105. package/dist/tools.d.ts +77 -0
  106. package/dist/tools.js +9 -0
  107. package/dist/tools.js.map +1 -0
  108. package/package.json +74 -0
  109. package/src/adapters/dispatcher-sse.test.ts +218 -0
  110. package/src/adapters/dispatcher-sse.ts +222 -0
  111. package/src/adapters/index.ts +18 -0
  112. package/src/adapters/mcp-catalog.test.ts +213 -0
  113. package/src/adapters/mcp-catalog.ts +188 -0
  114. package/src/adapters/prisma-rollout.test.ts +153 -0
  115. package/src/adapters/prisma-rollout.ts +104 -0
  116. package/src/agent-runtime.test.ts +176 -0
  117. package/src/artifact-stream.test.ts +330 -0
  118. package/src/artifact-stream.ts +453 -0
  119. package/src/channel-gateway.test.ts +432 -0
  120. package/src/channel-gateway.ts +357 -0
  121. package/src/code-review.test.ts +501 -0
  122. package/src/code-review.ts +495 -0
  123. package/src/command-suggestions.test.ts +251 -0
  124. package/src/command-suggestions.ts +338 -0
  125. package/src/commands.test.ts +184 -0
  126. package/src/commands.ts +140 -0
  127. package/src/commit-message.test.ts +249 -0
  128. package/src/commit-message.ts +180 -0
  129. package/src/context-compaction.test.ts +522 -0
  130. package/src/context-compaction.ts +434 -0
  131. package/src/definitions.test.ts +78 -0
  132. package/src/definitions.ts +190 -0
  133. package/src/deployment-status.test.ts +215 -0
  134. package/src/deployment-status.ts +227 -0
  135. package/src/design-context.test.ts +195 -0
  136. package/src/design-context.ts +198 -0
  137. package/src/dispatcher.test.ts +234 -0
  138. package/src/dispatcher.ts +189 -0
  139. package/src/durable-turn.test.ts +209 -0
  140. package/src/durable-turn.ts +135 -0
  141. package/src/edit-planner.test.ts +204 -0
  142. package/src/edit-planner.ts +325 -0
  143. package/src/fuzzy-match.test.ts +311 -0
  144. package/src/fuzzy-match.ts +444 -0
  145. package/src/hook-pipeline.test.ts +279 -0
  146. package/src/hook-pipeline.ts +373 -0
  147. package/src/inbound-admission.test.ts +394 -0
  148. package/src/inbound-admission.ts +246 -0
  149. package/src/index.ts +47 -0
  150. package/src/loop.test.ts +161 -0
  151. package/src/loop.ts +211 -0
  152. package/src/mcp-bridge.test.ts +165 -0
  153. package/src/mcp-bridge.ts +76 -0
  154. package/src/memory-provider.test.ts +232 -0
  155. package/src/memory-provider.ts +257 -0
  156. package/src/model.ts +168 -0
  157. package/src/permission-ruleset.test.ts +301 -0
  158. package/src/permission-ruleset.ts +200 -0
  159. package/src/policy.ts +151 -0
  160. package/src/project-repo.test.ts +232 -0
  161. package/src/project-repo.ts +311 -0
  162. package/src/protocol.ts +159 -0
  163. package/src/rollout-store-persistent.test.ts +217 -0
  164. package/src/rollout-store-persistent.ts +166 -0
  165. package/src/rollout.ts +150 -0
  166. package/src/sandbox.ts +113 -0
  167. package/src/session-share.test.ts +360 -0
  168. package/src/session-share.ts +310 -0
  169. package/src/skill-distillation.test.ts +177 -0
  170. package/src/skill-distillation.ts +369 -0
  171. package/src/skills.test.ts +277 -0
  172. package/src/skills.ts +255 -0
  173. package/src/subagents.test.ts +290 -0
  174. package/src/subagents.ts +332 -0
  175. package/src/tools.ts +126 -0
  176. package/src/workbench.test.ts +0 -0
  177. package/src/workbench.ts +0 -0
  178. package/tsconfig.json +12 -0
  179. package/tsup.config.ts +33 -0
@@ -0,0 +1,48 @@
1
+ import { RolloutStore, RolloutLine } from './rollout.js';
2
+ import './model.js';
3
+
4
+ /**
5
+ * Production-grade, tenant-scoped {@link RolloutStore} backed by an injectable
6
+ * persistence port. This package depends on NO datastore: a Postgres /
7
+ * ClickHouse / `@nebutra/db` / `@nebutra/audit` adapter satisfies
8
+ * {@link RolloutPersistencePort} from the outside, so the "no infra change"
9
+ * promise stays honest — swap the adapter, keep the interface.
10
+ *
11
+ * Tenancy is structural: `tenantId` is part of the storage key AND Zod-validated
12
+ * on every read and write. Cross-tenant access is impossible by construction.
13
+ * The store fails closed — empty identifiers and malformed stored payloads
14
+ * raise typed errors; records are never silently dropped.
15
+ */
16
+
17
+ /**
18
+ * Minimal append-only persistence seam. Implementations MUST persist records
19
+ * durably and return them ascending by `seq` for a given (tenant, thread).
20
+ */
21
+ interface RolloutPersistencePort {
22
+ put(record: {
23
+ tenantId: string;
24
+ threadId: string;
25
+ seq: number;
26
+ at: string;
27
+ payload: string;
28
+ }): Promise<void>;
29
+ /** Records for one (tenant, thread), ascending by seq. */
30
+ list(tenantId: string, threadId: string): Promise<{
31
+ seq: number;
32
+ payload: string;
33
+ }[]>;
34
+ }
35
+ /** Raised when a stored payload cannot be faithfully reconstructed. */
36
+ declare class RoundTripError extends Error {
37
+ constructor(message: string, options?: {
38
+ cause?: unknown;
39
+ });
40
+ }
41
+ declare class PersistentRolloutStore implements RolloutStore {
42
+ #private;
43
+ constructor(port: RolloutPersistencePort);
44
+ append(line: RolloutLine): Promise<void>;
45
+ read(tenantIdArg: string, threadIdArg: string): Promise<readonly RolloutLine[]>;
46
+ }
47
+
48
+ export { PersistentRolloutStore, type RolloutPersistencePort, RoundTripError };
@@ -0,0 +1,9 @@
1
+ import {
2
+ PersistentRolloutStore,
3
+ RoundTripError
4
+ } from "./chunk-2DA6Q6TN.js";
5
+ export {
6
+ PersistentRolloutStore,
7
+ RoundTripError
8
+ };
9
+ //# sourceMappingURL=rollout-store-persistent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,82 @@
1
+ import { TurnConfig, ThreadEvent, ThreadItem } from './model.js';
2
+
3
+ /**
4
+ * Event-sourced rollout / session trace (WRAP — capability #7).
5
+ *
6
+ * Faithful re-expression of the upstream rollout model: an append-only typed
7
+ * event log, state derived by replay, a first-class context-compaction marker
8
+ * (so replay stays bounded), and a per-item persistence policy that sanitizes
9
+ * and size-caps outputs before they are durable.
10
+ *
11
+ * Multi-tenant adaptation: every rollout line carries `tenantId`; the store
12
+ * interface is tenant-scoped so a Postgres/ClickHouse-backed implementation
13
+ * (via `@nebutra/audit` providers / `@nebutra/db`) replaces the upstream
14
+ * single-host jsonl + embedded-SQLite assumptions. Only an in-memory
15
+ * reference store ships here.
16
+ */
17
+
18
+ /** Cap mirrors the upstream persisted-output ceiling. */
19
+ declare const PERSISTED_OUTPUT_MAX_BYTES = 10000;
20
+ type EventPersistenceMode = "limited" | "extended";
21
+ /** One durable line in a thread's append-only log. */
22
+ type RolloutLine = {
23
+ readonly tenantId: string;
24
+ readonly threadId: string;
25
+ readonly type: "session_meta";
26
+ readonly config: TurnConfig;
27
+ readonly at: string;
28
+ } | {
29
+ readonly tenantId: string;
30
+ readonly threadId: string;
31
+ readonly type: "event";
32
+ readonly event: ThreadEvent;
33
+ readonly at: string;
34
+ } | {
35
+ readonly tenantId: string;
36
+ readonly threadId: string;
37
+ readonly type: "turn_context";
38
+ readonly config: TurnConfig;
39
+ readonly at: string;
40
+ } | {
41
+ readonly tenantId: string;
42
+ readonly threadId: string;
43
+ readonly type: "compacted";
44
+ readonly summary: string;
45
+ readonly droppedThrough: string;
46
+ readonly at: string;
47
+ };
48
+ /**
49
+ * Persistence policy: decide per item whether it is durable, and sanitize +
50
+ * size-cap its output first. Executive markers are always persisted.
51
+ */
52
+ declare function isPersisted(item: ThreadItem, mode: EventPersistenceMode): boolean;
53
+ /** Truncate aggregated command output to the persisted ceiling. */
54
+ declare function sanitizeForPersist(item: ThreadItem): ThreadItem;
55
+ /** Tenant-scoped append-only store. Replace the impl, keep the interface. */
56
+ interface RolloutStore {
57
+ append(line: RolloutLine): Promise<void>;
58
+ /** Lines for a thread, in append order. */
59
+ read(tenantId: string, threadId: string): Promise<readonly RolloutLine[]>;
60
+ }
61
+ /** In-memory reference store (dev/test only — never multi-instance safe). */
62
+ declare class InMemoryRolloutStore implements RolloutStore {
63
+ #private;
64
+ append(line: RolloutLine): Promise<void>;
65
+ read(tenantId: string, threadId: string): Promise<readonly RolloutLine[]>;
66
+ }
67
+ /** Derived thread state — the projection rebuilt by replaying the log. */
68
+ interface ThreadProjection {
69
+ readonly tenantId: string;
70
+ readonly threadId: string;
71
+ config?: TurnConfig;
72
+ readonly items: ThreadItem[];
73
+ /** Marks where a compaction summary replaced earlier history. */
74
+ compactionSummary?: string;
75
+ }
76
+ /**
77
+ * Replay an append-only log into derived state. A `compacted` line bounds
78
+ * replay: items prior to it are represented by the summary, not re-applied.
79
+ */
80
+ declare function replay(lines: readonly RolloutLine[]): ThreadProjection | null;
81
+
82
+ export { type EventPersistenceMode, InMemoryRolloutStore, PERSISTED_OUTPUT_MAX_BYTES, type RolloutLine, type RolloutStore, type ThreadProjection, isPersisted, replay, sanitizeForPersist };
@@ -0,0 +1,15 @@
1
+ import {
2
+ InMemoryRolloutStore,
3
+ PERSISTED_OUTPUT_MAX_BYTES,
4
+ isPersisted,
5
+ replay,
6
+ sanitizeForPersist
7
+ } from "./chunk-37BBB2P2.js";
8
+ export {
9
+ InMemoryRolloutStore,
10
+ PERSISTED_OUTPUT_MAX_BYTES,
11
+ isPersisted,
12
+ replay,
13
+ sanitizeForPersist
14
+ };
15
+ //# sourceMappingURL=rollout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,65 @@
1
+ import { CapabilityPolicy } from './policy.js';
2
+ import 'zod';
3
+
4
+ /**
5
+ * External-sandbox delegation seam (PORT — capability #11).
6
+ *
7
+ * Governance decision (dual-track, ExternalSandbox posture): this multi-tenant
8
+ * web runtime NEVER executes untrusted code itself and introduces no isolation
9
+ * infrastructure. It only:
10
+ * 1. carries the capability policy (see ./policy),
11
+ * 2. delegates execution to an external isolator behind this interface
12
+ * (a self-hosted kernel sidecar — Track B — or any other executor),
13
+ * 3. records the outcome as a `command_execution` item (see ./model).
14
+ *
15
+ * The upstream OS enforcers (Seatbelt / Landlock / bubblewrap / Windows
16
+ * restricted token) are deliberately NOT ported — they are single-host and
17
+ * out of scope for a multi-tenant web product.
18
+ */
19
+
20
+ interface SandboxExecRequest {
21
+ /** Mandatory tenant scope — every delegated exec is tenant-bound. */
22
+ readonly tenantId: string;
23
+ readonly threadId: string;
24
+ readonly command: string;
25
+ /** The capabilities the external isolator must honor. */
26
+ readonly capabilityPolicy: CapabilityPolicy;
27
+ /** Optional inputs the executor should materialize before running. */
28
+ readonly inputs?: Readonly<Record<string, string>>;
29
+ }
30
+ interface SandboxExecResult {
31
+ readonly exitCode: number;
32
+ readonly aggregatedOutput: string;
33
+ /** Identifier of the isolator that actually ran the command. */
34
+ readonly executedOn: string;
35
+ }
36
+ /**
37
+ * The only thing Track A depends on for execution. Implemented by a decoupled
38
+ * isolator over the ./protocol contract; never implemented in-process here.
39
+ */
40
+ interface ExternalSandbox {
41
+ exec(request: SandboxExecRequest): Promise<SandboxExecResult>;
42
+ }
43
+ /**
44
+ * Fail-closed default. Wiring this in production requires a real
45
+ * {@link ExternalSandbox}; absent one, untrusted code never runs — by design.
46
+ */
47
+ declare class NoExecutorConfiguredError extends Error {
48
+ constructor();
49
+ }
50
+ declare const REFUSING_SANDBOX: ExternalSandbox;
51
+ declare class SandboxDelegationError extends Error {
52
+ readonly status: number;
53
+ constructor(message: string, status: number);
54
+ }
55
+ /**
56
+ * The concrete Track-B coupling: delegate execution over HTTP to the decoupled
57
+ * Rust isolator (`backends/rust/sandbox`, `POST /api/v1/sandbox/exec`). The
58
+ * isolator is fail-closed; a non-2xx (e.g. 403 refusal) is surfaced as an
59
+ * error and never coerced into a fabricated result.
60
+ */
61
+ declare function createHttpSandbox(baseUrl: string, fetchImpl?: typeof fetch): ExternalSandbox;
62
+ /** Guard: reject the most dangerous posture unless explicitly opted in. */
63
+ declare function assertSafePosture(policy: CapabilityPolicy, allowDanger?: boolean): void;
64
+
65
+ export { type ExternalSandbox, NoExecutorConfiguredError, REFUSING_SANDBOX, SandboxDelegationError, type SandboxExecRequest, type SandboxExecResult, assertSafePosture, createHttpSandbox };
@@ -0,0 +1,15 @@
1
+ import {
2
+ NoExecutorConfiguredError,
3
+ REFUSING_SANDBOX,
4
+ SandboxDelegationError,
5
+ assertSafePosture,
6
+ createHttpSandbox
7
+ } from "./chunk-MUF7ZZTO.js";
8
+ export {
9
+ NoExecutorConfiguredError,
10
+ REFUSING_SANDBOX,
11
+ SandboxDelegationError,
12
+ assertSafePosture,
13
+ createHttpSandbox
14
+ };
15
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,93 @@
1
+ import { z } from 'zod';
2
+ import { Definition, DefinitionResolver, ResolveContext } from './definitions.js';
3
+
4
+ /**
5
+ * Skills system (WRAP — progressive-disclosure capability).
6
+ *
7
+ * Faithful re-expression of the source harness's two-phase skill model:
8
+ *
9
+ * Phase 1 — Listing (cheap, always in context): a budget-bounded catalog
10
+ * exposing only {name, description, whenToUse} per skill. First-party
11
+ * skills (bundled/builtin tier) are never truncated and never dropped;
12
+ * lower-tier skills degrade to names-only, then drop, as the context
13
+ * budget is exhausted. Path-activated skills stay hidden until a touched
14
+ * file matches one of their globs.
15
+ *
16
+ * Phase 2 — Invocation (lazy, on demand): expand the chosen skill's body
17
+ * into turn messages, with arg/var substitution and a merged tool
18
+ * allowlist contributed to the permission context.
19
+ *
20
+ * A skill IS a `Definition` — the same tenant-scoped layered resolver backs
21
+ * the command registry and the subagent registry (see ./definitions).
22
+ *
23
+ * SECURITY: this re-expression intentionally drops the source's body-side
24
+ * command-substitution (the upstream "!`…`" inline-shell facility). Skill
25
+ * bodies are inert text; they NEVER trigger host shell execution here. All
26
+ * entry points require a non-empty `tenantId` and fail closed; cross-tenant
27
+ * inputs are rejected by the underlying `DefinitionResolver`. Pure data/logic
28
+ * — no host filesystem access (resource base is an injected indirection).
29
+ */
30
+
31
+ /** A skill is just a resolvable `Definition`. */
32
+ type SkillRecord = Definition;
33
+ /** One catalog entry — only the cheap, always-in-context surface. */
34
+ interface SkillListingEntry {
35
+ readonly name: string;
36
+ readonly description: string;
37
+ readonly whenToUse?: string | undefined;
38
+ /** True when this entry was degraded to names-only by the budget. */
39
+ readonly degraded: boolean;
40
+ readonly firstParty: boolean;
41
+ }
42
+ interface SkillListing {
43
+ readonly entries: readonly SkillListingEntry[];
44
+ readonly text: string;
45
+ }
46
+ declare const listingOptionsSchema: z.ZodObject<{
47
+ maxListingDescChars: z.ZodDefault<z.ZodNumber>;
48
+ contextWindowTokens: z.ZodDefault<z.ZodNumber>;
49
+ budgetPercent: z.ZodDefault<z.ZodNumber>;
50
+ touchedPaths: z.ZodDefault<z.ZodArray<z.ZodString>>;
51
+ }, z.core.$strip>;
52
+ type SkillListingOptions = z.input<typeof listingOptionsSchema>;
53
+ /**
54
+ * Phase 1 — build the always-in-context skill catalog. Pure & deterministic.
55
+ *
56
+ * Budget = `contextWindowTokens * budgetPercent`. First-party skills are
57
+ * emitted in full and do NOT consume budget against being dropped. Each
58
+ * remaining skill is tried at full description; if it would overflow it is
59
+ * degraded to names-only; if even that overflows it is dropped. Skills in
60
+ * `ctx.loadedSlugs` and unactivated path-gated skills are suppressed.
61
+ */
62
+ declare function buildSkillListing(resolver: DefinitionResolver<SkillRecord>, ctx: ResolveContext, options?: SkillListingOptions): SkillListing;
63
+ interface SkillMessage {
64
+ readonly role: "system" | "user";
65
+ readonly content: string;
66
+ }
67
+ interface ExpandedSkill {
68
+ readonly messages: readonly SkillMessage[];
69
+ readonly allowedTools: readonly string[];
70
+ readonly modelOverride?: string | undefined;
71
+ readonly effort?: "low" | "medium" | "high" | undefined;
72
+ readonly executionMode: "inline" | "fork";
73
+ }
74
+ interface ExpandContext {
75
+ readonly tenantId: string;
76
+ readonly args: Record<string, string>;
77
+ readonly vars: Record<string, string>;
78
+ /** Lazy body fetch — host supplies; called only here, only once. */
79
+ readonly bodyLoader: (bodyRef: string) => Promise<string>;
80
+ /** Host-injected resource-base indirection (NO host FS access here). */
81
+ readonly skillResourceBase: (slug: string) => string;
82
+ }
83
+ /**
84
+ * Phase 2 — expand a skill into turn messages. Body is loaded lazily via the
85
+ * injected `bodyLoader` (never during listing). A `Base directory…` line is
86
+ * prepended via the injected `skillResourceBase` indirection. Args + vars are
87
+ * substituted with `substituteArguments`. The skill's `allowedTools` are
88
+ * returned for the caller to merge into the permission context — this never
89
+ * mutates global state and never executes anything from the body.
90
+ */
91
+ declare function expandSkill(skill: SkillRecord, ctx: ExpandContext): Promise<ExpandedSkill>;
92
+
93
+ export { type ExpandContext, type ExpandedSkill, type SkillListing, type SkillListingEntry, type SkillListingOptions, type SkillMessage, type SkillRecord, buildSkillListing, expandSkill };
package/dist/skills.js ADDED
@@ -0,0 +1,10 @@
1
+ import {
2
+ buildSkillListing,
3
+ expandSkill
4
+ } from "./chunk-ZMYX5VBU.js";
5
+ import "./chunk-7BUOF367.js";
6
+ export {
7
+ buildSkillListing,
8
+ expandSkill
9
+ };
10
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,129 @@
1
+ import { Definition, Frontmatter } from './definitions.js';
2
+ import { ThreadItem, TurnUsage } from './model.js';
3
+ import 'zod';
4
+
5
+ /**
6
+ * Subagent / task dispatch (WRAP — isolated-child-agent model, the delta).
7
+ *
8
+ * Faithful re-expression of the source harness's child-agent dispatch grammar:
9
+ * a registry decides WHICH definition runs, a context-boundary contract decides
10
+ * WITH WHAT inherited context it starts, and a typed terminal envelope decides
11
+ * HOW its result re-enters the parent. The child loop, child policy, and
12
+ * rollout store live elsewhere in agent-runtime and are intentionally NOT
13
+ * reimplemented here — this layer is pure decision + data + state machine.
14
+ *
15
+ * Multi-tenant: every task operation is keyed by `tenantId` and fails closed.
16
+ * Pure data/logic — no FS scan, no shell, no network.
17
+ *
18
+ * NOTE on dropped task kinds: the source harness models several local execution
19
+ * task kinds (local_bash / monitor_mcp / worktree). Those are deliberately NOT
20
+ * represented here: this package never executes locally — execution is delegated
21
+ * via the external-sandbox seam — so only the agent-facing `subagent` kind (and
22
+ * its `deferred` sibling) is modelled.
23
+ */
24
+
25
+ /** A subagent definition is just a `Definition` (same loader as skills/commands). */
26
+ type SubagentRecord = Definition;
27
+ /**
28
+ * Effective tool set for a subagent: `allowedTools` minus `disallowedTools`,
29
+ * intersected with the runtime tool universe so a definition can never widen
30
+ * its scope past what the host exposes. When `allowedTools` is empty the
31
+ * contract is "all tools except the denied ones" (all-except-deny).
32
+ *
33
+ * Pure — order follows `allTools` for determinism.
34
+ */
35
+ declare function resolveSubagentTools(fm: Frontmatter, allTools: readonly string[]): string[];
36
+ type DispatchMode = "spawn" | "fork";
37
+ interface DispatchCtx {
38
+ readonly tenantId: string;
39
+ }
40
+ interface PrepareDispatchInput {
41
+ readonly definition: SubagentRecord;
42
+ readonly mode: DispatchMode;
43
+ readonly parentItems?: readonly ThreadItem[];
44
+ /** Caller's directive. Mandatory & non-empty in `spawn` mode. */
45
+ readonly brief: string;
46
+ readonly ctx: DispatchCtx;
47
+ /** Runtime tool universe; defaults to the definition's own allow list. */
48
+ readonly allTools?: readonly string[];
49
+ }
50
+ interface PreparedDispatch {
51
+ readonly initialContext: readonly ThreadItem[];
52
+ readonly toolScope: readonly string[];
53
+ /** Opaque reference to the system prompt body (resolved by the child loop). */
54
+ readonly systemPromptRef: string;
55
+ readonly modelOverride?: string;
56
+ }
57
+ /**
58
+ * Decide the child's starting context boundary.
59
+ *
60
+ * - `spawn`: zero inherited context. The caller MUST fully brief the child;
61
+ * an empty brief is a programming error and throws.
62
+ * - `fork`: inherit a defensive copy of `parentItems` with incomplete tool
63
+ * calls filtered out, then append the brief as a directive.
64
+ *
65
+ * `parentItems` is never mutated. Cross-tenant dispatch fails closed.
66
+ */
67
+ declare function prepareDispatch(input: PrepareDispatchInput): PreparedDispatch;
68
+ declare const TASK_KINDS: readonly ["subagent", "deferred"];
69
+ type TaskKind = (typeof TASK_KINDS)[number];
70
+ declare const TASK_STATUSES: readonly ["pending", "running", "completed", "failed", "killed"];
71
+ type TaskStatus = (typeof TASK_STATUSES)[number];
72
+ interface TaskRecord {
73
+ readonly taskId: string;
74
+ readonly tenantId: string;
75
+ readonly status: TaskStatus;
76
+ readonly notified: boolean;
77
+ readonly kind: TaskKind;
78
+ readonly createdAtMs: number;
79
+ }
80
+ /**
81
+ * Tenant-scoped task registry. Every mutating op verifies the caller's
82
+ * tenant against the stored record; a mismatch is treated as "not found"
83
+ * for reads and throws for mutations — cross-tenant access is impossible.
84
+ */
85
+ declare class TaskRegistry {
86
+ #private;
87
+ create(tenantId: string, kind: TaskKind): string;
88
+ /** Tenant-checked read. Returns undefined for unknown or cross-tenant ids. */
89
+ get(taskId: string, tenantId: string): TaskRecord | undefined;
90
+ transition(taskId: string, to: TaskStatus, tenantId: string): TaskRecord;
91
+ /** Unified kill — drives any non-terminal task to `killed`. */
92
+ stop(taskId: string, tenantId: string): TaskRecord;
93
+ markNotified(taskId: string, tenantId: string): TaskRecord;
94
+ }
95
+ /**
96
+ * No-peek / no-race guard. Throws if a parent tries to read an in-flight
97
+ * deferred task's transcript before it has settled.
98
+ */
99
+ declare function assertNotPeeking(task: TaskRecord): void;
100
+ interface SyncEnvelope {
101
+ readonly kind: "sync";
102
+ readonly content: readonly ThreadItem[];
103
+ readonly usage: TurnUsage;
104
+ readonly agentId: string;
105
+ readonly toolUses: number;
106
+ readonly durationMs: number;
107
+ }
108
+ interface DeferredEnvelope {
109
+ readonly kind: "deferred";
110
+ readonly taskId: string;
111
+ readonly channel: string;
112
+ }
113
+ type DispatchEnvelope = SyncEnvelope | DeferredEnvelope;
114
+ /** Build a fire-and-forget deferred envelope for a registered task. */
115
+ declare function makeDeferred(taskId: string, channel: string): DeferredEnvelope;
116
+ interface SettleDeferredTarget {
117
+ readonly taskId: string;
118
+ readonly channel: string;
119
+ readonly tenantId: string;
120
+ readonly registry: TaskRegistry;
121
+ }
122
+ /**
123
+ * Settle a previously-deferred task: drive it to `completed` (tenant-checked)
124
+ * and produce the eventual sync-shaped result. Empty content is normalized to
125
+ * the explicit no-output marker.
126
+ */
127
+ declare function settleDeferred(target: SettleDeferredTarget, content: readonly ThreadItem[], usage: TurnUsage): SyncEnvelope;
128
+
129
+ export { type DeferredEnvelope, type DispatchCtx, type DispatchEnvelope, type DispatchMode, type PrepareDispatchInput, type PreparedDispatch, type SettleDeferredTarget, type SubagentRecord, type SyncEnvelope, TASK_KINDS, TASK_STATUSES, type TaskKind, type TaskRecord, TaskRegistry, type TaskStatus, assertNotPeeking, makeDeferred, prepareDispatch, resolveSubagentTools, settleDeferred };
@@ -0,0 +1,21 @@
1
+ import {
2
+ TASK_KINDS,
3
+ TASK_STATUSES,
4
+ TaskRegistry,
5
+ assertNotPeeking,
6
+ makeDeferred,
7
+ prepareDispatch,
8
+ resolveSubagentTools,
9
+ settleDeferred
10
+ } from "./chunk-5YS7WAPS.js";
11
+ export {
12
+ TASK_KINDS,
13
+ TASK_STATUSES,
14
+ TaskRegistry,
15
+ assertNotPeeking,
16
+ makeDeferred,
17
+ prepareDispatch,
18
+ resolveSubagentTools,
19
+ settleDeferred
20
+ };
21
+ //# sourceMappingURL=subagents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Tool / MCP abstraction (WRAP — capability #9).
5
+ *
6
+ * Faithful re-expression of the upstream uniform tool model: one
7
+ * `ToolDefinition` interface, JSON-schema in/out, a deferred-load flag, and
8
+ * MCP-as-adapter behind the same interface (MCP tools and native tools are
9
+ * indistinguishable at dispatch). Activates `@nebutra/mcp` primitives rather
10
+ * than re-porting them.
11
+ */
12
+
13
+ /** A tool definition — pure data; transport-agnostic. */
14
+ interface ToolDefinition<I = unknown, O = unknown> {
15
+ readonly name: string;
16
+ readonly description: string;
17
+ readonly inputSchema: z.ZodType<I>;
18
+ readonly outputSchema?: z.ZodType<O>;
19
+ /**
20
+ * When true, the full schema is withheld until a `tool_search` discovery
21
+ * step lazily loads it (parity with the upstream deferred-tool pattern).
22
+ */
23
+ readonly deferLoading?: boolean;
24
+ }
25
+ /** Source provenance — native vs. adapted from an MCP server. */
26
+ type ToolOrigin = {
27
+ readonly kind: "native";
28
+ } | {
29
+ readonly kind: "mcp";
30
+ readonly server: string;
31
+ };
32
+ interface RegisteredTool {
33
+ readonly definition: ToolDefinition;
34
+ readonly origin: ToolOrigin;
35
+ }
36
+ /** A tool invocation routed through the registry. */
37
+ interface ToolDispatchContext {
38
+ /** Mandatory tenant scope — every dispatch is tenant-bound. */
39
+ readonly tenantId: string;
40
+ readonly threadId: string;
41
+ }
42
+ type ToolHandler<I = unknown, O = unknown> = (input: I, ctx: ToolDispatchContext) => Promise<O>;
43
+ /** Pre/post dispatch hooks (parity with upstream orchestrator hooks). */
44
+ interface ToolHooks {
45
+ readonly preToolUse?: (name: string, input: unknown, ctx: ToolDispatchContext) => Promise<void>;
46
+ readonly postToolUse?: (name: string, output: unknown, ctx: ToolDispatchContext) => Promise<void>;
47
+ }
48
+ /**
49
+ * registry -> router -> orchestrator pipeline. MCP tools register via
50
+ * {@link adaptMcpTool} and are dispatched identically to native tools.
51
+ */
52
+ declare class ToolRegistry {
53
+ #private;
54
+ constructor(hooks?: ToolHooks);
55
+ register<I, O>(definition: ToolDefinition<I, O>, handler: ToolHandler<I, O>, origin?: ToolOrigin): void;
56
+ list(): readonly RegisteredTool[];
57
+ dispatch(name: string, rawInput: unknown, ctx: ToolDispatchContext): Promise<unknown>;
58
+ }
59
+ /** Minimal shape of an MCP client (satisfied by `@nebutra/mcp`'s `mcpClient`). */
60
+ interface McpClientLike {
61
+ executeTool(name: string, args: unknown, ctx: {
62
+ requestId: string;
63
+ tenantId: string;
64
+ }): Promise<unknown>;
65
+ }
66
+ /**
67
+ * Adapt an external MCP tool into the uniform tool model. The resulting
68
+ * handler delegates to the MCP client; callers cannot tell it apart from a
69
+ * native tool.
70
+ */
71
+ declare function adaptMcpTool(server: string, definition: ToolDefinition, client: McpClientLike): {
72
+ definition: ToolDefinition;
73
+ handler: ToolHandler;
74
+ origin: ToolOrigin;
75
+ };
76
+
77
+ export { type McpClientLike, type RegisteredTool, type ToolDefinition, type ToolDispatchContext, type ToolHandler, type ToolHooks, type ToolOrigin, ToolRegistry, adaptMcpTool };
package/dist/tools.js ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ ToolRegistry,
3
+ adaptMcpTool
4
+ } from "./chunk-NN7DATXA.js";
5
+ export {
6
+ ToolRegistry,
7
+ adaptMcpTool
8
+ };
9
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}