@deepstrike/sdk 0.2.28 → 0.2.31
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/README.md +45 -21
- package/dist/harness/harness.d.ts +3 -2
- package/dist/harness/harness.js +15 -35
- package/dist/harness/judge.d.ts +42 -0
- package/dist/harness/judge.js +58 -0
- package/dist/harness/public.d.ts +4 -0
- package/dist/harness/public.js +3 -0
- package/dist/index.d.ts +21 -80
- package/dist/index.js +28 -60
- package/dist/kernel.d.ts +7 -1
- package/dist/memory/public.d.ts +4 -0
- package/dist/memory/public.js +3 -0
- package/dist/os/public.d.ts +18 -0
- package/dist/os/public.js +14 -0
- package/dist/planes/public.d.ts +13 -0
- package/dist/planes/public.js +9 -0
- package/dist/providers/anthropic-compatible.d.ts +23 -0
- package/dist/providers/anthropic-compatible.js +29 -0
- package/dist/providers/anthropic.d.ts +11 -2
- package/dist/providers/anthropic.js +14 -9
- package/dist/providers/catalog.js +5 -53
- package/dist/providers/deepseek.d.ts +28 -8
- package/dist/providers/deepseek.js +38 -157
- package/dist/providers/factories.d.ts +31 -0
- package/dist/providers/factories.js +33 -0
- package/dist/providers/glm.d.ts +5 -4
- package/dist/providers/glm.js +8 -23
- package/dist/providers/kimi.d.ts +5 -4
- package/dist/providers/kimi.js +8 -22
- package/dist/providers/minimax.d.ts +26 -12
- package/dist/providers/minimax.js +32 -158
- package/dist/providers/openai.d.ts +57 -2
- package/dist/providers/openai.js +139 -70
- package/dist/providers/public.d.ts +10 -0
- package/dist/providers/public.js +11 -0
- package/dist/providers/qwen.d.ts +19 -19
- package/dist/providers/qwen.js +37 -176
- package/dist/providers/registry.d.ts +18 -0
- package/dist/providers/registry.js +35 -0
- package/dist/providers/vendor-profiles.d.ts +54 -0
- package/dist/providers/vendor-profiles.js +62 -0
- package/dist/runtime/event-stream.d.ts +44 -0
- package/dist/runtime/event-stream.js +39 -0
- package/dist/runtime/facade.js +6 -1
- package/dist/runtime/reactive-session.d.ts +125 -0
- package/dist/runtime/reactive-session.js +127 -0
- package/dist/runtime/run-group.d.ts +74 -0
- package/dist/runtime/run-group.js +72 -0
- package/dist/runtime/runner.d.ts +9 -0
- package/dist/runtime/runner.js +79 -46
- package/dist/runtime/session-log.d.ts +8 -0
- package/dist/runtime/turn-policy.d.ts +33 -0
- package/dist/runtime/turn-policy.js +58 -0
- package/dist/signals/gateway.d.ts +7 -2
- package/dist/signals/gateway.js +13 -3
- package/dist/signals/types.d.ts +10 -1
- package/dist/workflow/public.d.ts +20 -0
- package/dist/workflow/public.js +15 -0
- package/package.json +54 -2
package/dist/runtime/runner.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { SignalSource } from "../signals/types.js";
|
|
|
5
5
|
import type { SessionLog, SessionEvent } from "./session-log.js";
|
|
6
6
|
import type { ArchiveStore } from "./archive.js";
|
|
7
7
|
import type { ExecutionPlane } from "./execution-plane.js";
|
|
8
|
+
import type { RunGroup } from "./run-group.js";
|
|
8
9
|
import { type MemoryPolicy, type ResourceQuota } from "../kernel.js";
|
|
9
10
|
import type { AgentRunSpec, MilestoneCheckResult, MilestoneContract, MilestonePolicy, WorkflowSpec } from "../types/agent.js";
|
|
10
11
|
import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
@@ -117,6 +118,14 @@ export interface RuntimeOptions {
|
|
|
117
118
|
* and memory-write syscalls are admitted unconditionally (pre-M2 behavior).
|
|
118
119
|
*/
|
|
119
120
|
resourceQuota?: ResourceQuota;
|
|
121
|
+
/**
|
|
122
|
+
* L1 (RunGroup): bind this runner to a governance domain shared by N peer sessions of one logical
|
|
123
|
+
* run. Members pass the same `id` + `budgetStore`; the kernel's run-level token cap is then enforced
|
|
124
|
+
* against the group's cumulative spend (seeded at boot, charged at run end) rather than per-vehicle.
|
|
125
|
+
* Unset ⇒ N=1, pre-L1 per-run budget (byte-identical). Only cumulative budget is shared; instantaneous
|
|
126
|
+
* concurrency stays vehicle-scoped (spec §2.5).
|
|
127
|
+
*/
|
|
128
|
+
runGroup?: RunGroup;
|
|
120
129
|
/**
|
|
121
130
|
* Optional long-term memory policy (`set_memory_policy`). Tunes the kernel's memory subsystem
|
|
122
131
|
* (retrieval top-k, stale-warning age, write validation, memory path). Unset leaves the kernel
|
package/dist/runtime/runner.js
CHANGED
|
@@ -146,52 +146,42 @@ export class RuntimeRunner {
|
|
|
146
146
|
* exactly as a mid-run spawn would be. Must run BEFORE `start_run` so the in-kernel gate enforces
|
|
147
147
|
* every policy from the first spawn. No config ⇒ the native-profile defaults (铁律: defaults only).
|
|
148
148
|
*/
|
|
149
|
-
applyKernelPolicies(runtime) {
|
|
149
|
+
applyKernelPolicies(runtime, groupTokensBase, groupSpawnsBase) {
|
|
150
|
+
// K2: lower governance / attention / scheduler / quota in ONE `configure_run` event instead of
|
|
151
|
+
// the previous 2–4 separate `set_*` / `load_governance_policy` events. The kernel applies each
|
|
152
|
+
// present field via the same path its granular event uses; absent fields are left untouched.
|
|
153
|
+
// (Requires the 0.2.30 core that ships `configure_run`.)
|
|
150
154
|
const osProfile = assertNativeProfile(this.opts.osProfile ?? "native");
|
|
151
155
|
const attentionPolicy = this.opts.attentionPolicy ?? osProfile.attentionPolicy;
|
|
152
156
|
const governancePolicy = this.opts.governancePolicy ?? osProfile.governancePolicy;
|
|
153
|
-
//
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
});
|
|
163
|
-
// Set optional wall-clock budget override.
|
|
164
|
-
if (this.opts.schedulerBudget) {
|
|
165
|
-
kernelApply(runtime, this.pendingObservations, {
|
|
166
|
-
kind: "set_scheduler_budget",
|
|
167
|
-
...(this.opts.schedulerBudget.maxWallMs !== undefined
|
|
168
|
-
? { max_wall_ms: this.opts.schedulerBudget.maxWallMs }
|
|
169
|
-
: {}),
|
|
170
|
-
});
|
|
157
|
+
// Strip the event `kind` off the governance event — `configure_run.config.governance` carries the
|
|
158
|
+
// bare policy fields (default_action / rules / vetoed_tools / rate_limits / constraints).
|
|
159
|
+
const { kind: _govKind, ...governance } = governancePolicyToKernelEvent(governancePolicy);
|
|
160
|
+
const config = { governance };
|
|
161
|
+
if (attentionPolicy.maxQueueSize !== undefined) {
|
|
162
|
+
config.attention_max_queue_size = attentionPolicy.maxQueueSize;
|
|
163
|
+
}
|
|
164
|
+
if (this.opts.schedulerBudget?.maxWallMs !== undefined) {
|
|
165
|
+
config.scheduler_max_wall_ms = this.opts.schedulerBudget.maxWallMs;
|
|
171
166
|
}
|
|
172
|
-
// Install optional resource quotas at the syscall trap (M2). Maps the ergonomic camelCase
|
|
173
|
-
// option onto the kernel's snake_case quota shape; the write-rate window is the serde tuple
|
|
174
|
-
// `[maxWrites, windowMs]`. Omitting the option leaves spawn / memory writes unbounded.
|
|
175
167
|
if (this.opts.resourceQuota) {
|
|
176
168
|
const q = this.opts.resourceQuota;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
: {}),
|
|
192
|
-
},
|
|
193
|
-
});
|
|
169
|
+
config.resource_quota = {
|
|
170
|
+
...(q.maxConcurrentSubagents !== undefined ? { max_concurrent_subagents: q.maxConcurrentSubagents } : {}),
|
|
171
|
+
...(q.maxTotalSubagents !== undefined ? { max_total_subagents: q.maxTotalSubagents } : {}),
|
|
172
|
+
...(q.maxSpawnDepth !== undefined ? { max_spawn_depth: q.maxSpawnDepth } : {}),
|
|
173
|
+
...(q.memoryWritesPerWindow !== undefined
|
|
174
|
+
? { memory_writes_per_window: [q.memoryWritesPerWindow.maxWrites, q.memoryWritesPerWindow.windowMs] }
|
|
175
|
+
: {}),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (groupTokensBase !== undefined && groupTokensBase > 0) {
|
|
179
|
+
config.group_tokens_base = groupTokensBase;
|
|
180
|
+
}
|
|
181
|
+
if (groupSpawnsBase !== undefined && groupSpawnsBase > 0) {
|
|
182
|
+
config.group_spawns_base = groupSpawnsBase;
|
|
194
183
|
}
|
|
184
|
+
kernelApply(runtime, this.pendingObservations, { kind: "configure_run", config });
|
|
195
185
|
}
|
|
196
186
|
async appendMemorySyscallObservations(sessionId, observations) {
|
|
197
187
|
if (!sessionId)
|
|
@@ -452,7 +442,18 @@ export class RuntimeRunner {
|
|
|
452
442
|
// already set by an in-flight `run()`) keep the original in-place behavior with no teardown.
|
|
453
443
|
const bootstrapped = !this.activeKernel || !this.currentSessionId;
|
|
454
444
|
if (bootstrapped) {
|
|
455
|
-
|
|
445
|
+
const sessionId = opts?.sessionId ?? `wf-${crypto.randomUUID()}`;
|
|
446
|
+
// L1: a standalone workflow is a member of its runner's governance domain too. Seed the
|
|
447
|
+
// bootstrap kernel with the group's cumulative spend (so the cumulative spawn/token cap bites
|
|
448
|
+
// while scheduling DAG nodes) and register membership — mirroring `execute()`. Mid-run callers
|
|
449
|
+
// skip this: their parent `run()` already seeds + counts the nodes via `localSubagentsSpawned()`.
|
|
450
|
+
let groupLedger;
|
|
451
|
+
if (this.opts.runGroup) {
|
|
452
|
+
const g = this.opts.runGroup;
|
|
453
|
+
groupLedger = await g.budgetStore.read(g.id);
|
|
454
|
+
await g.budgetStore.join(g.id, { sessionId, role: this.opts.agentId });
|
|
455
|
+
}
|
|
456
|
+
this.bootstrapWorkflowKernel(sessionId, spec, groupLedger?.tokensSpent, groupLedger?.subagentsSpawned);
|
|
456
457
|
}
|
|
457
458
|
const parentSessionId = this.currentSessionId;
|
|
458
459
|
const runtime = this.activeKernel;
|
|
@@ -470,6 +471,17 @@ export class RuntimeRunner {
|
|
|
470
471
|
}
|
|
471
472
|
finally {
|
|
472
473
|
if (bootstrapped) {
|
|
474
|
+
// L1: charge the standalone workflow's node spawns back to the group so the cumulative spawn
|
|
475
|
+
// cap (`maxTotalSubagents`) counts workflow nodes — they are member runs whose own
|
|
476
|
+
// `execute()` charge contributes 0 spawns, so without this the node count is invisible to the
|
|
477
|
+
// group. The envelope kernel's TaskTable holds one proc per scheduled node, so
|
|
478
|
+
// `localSubagentsSpawned()` is exactly that node count (the envelope itself burns no tokens).
|
|
479
|
+
if (this.opts.runGroup) {
|
|
480
|
+
const subagents = runtime.localSubagentsSpawned?.() ?? 0;
|
|
481
|
+
if (subagents > 0) {
|
|
482
|
+
await this.opts.runGroup.budgetStore.charge(this.opts.runGroup.id, { subagents });
|
|
483
|
+
}
|
|
484
|
+
}
|
|
473
485
|
this.activeKernel = null;
|
|
474
486
|
this.currentSessionId = null;
|
|
475
487
|
this.pendingObservations = [];
|
|
@@ -483,7 +495,7 @@ export class RuntimeRunner {
|
|
|
483
495
|
* and records a `run_started` event so the standalone run is resumable from the session log. Sets
|
|
484
496
|
* `activeKernel` / `currentSessionId`; `runWorkflow` is responsible for tearing them down.
|
|
485
497
|
*/
|
|
486
|
-
bootstrapWorkflowKernel(sessionId, spec) {
|
|
498
|
+
bootstrapWorkflowKernel(sessionId, spec, groupTokensBase, groupSpawnsBase) {
|
|
487
499
|
this.interrupted = false;
|
|
488
500
|
this.abortController = new AbortController();
|
|
489
501
|
this.pendingObservations = [];
|
|
@@ -502,8 +514,9 @@ export class RuntimeRunner {
|
|
|
502
514
|
criteria: [],
|
|
503
515
|
agent_id: this.opts.agentId,
|
|
504
516
|
}).catch(() => { });
|
|
505
|
-
this.applyKernelPolicies(runtime);
|
|
506
|
-
|
|
517
|
+
this.applyKernelPolicies(runtime, groupTokensBase, groupSpawnsBase);
|
|
518
|
+
// K1: no explicit `start_run` — the host `load_workflow` (fired next by `runWorkflow`) self-bootstraps
|
|
519
|
+
// the run on the 0.2.30 core, matching the agent-reachable `submit_workflow` path.
|
|
507
520
|
return runtime;
|
|
508
521
|
}
|
|
509
522
|
/**
|
|
@@ -558,7 +571,7 @@ export class RuntimeRunner {
|
|
|
558
571
|
if (!source)
|
|
559
572
|
return null;
|
|
560
573
|
while (!batchState.settled) {
|
|
561
|
-
const sig = await source.nextSignal();
|
|
574
|
+
const sig = await source.nextSignal(this.currentSessionId ?? undefined);
|
|
562
575
|
if (batchState.settled)
|
|
563
576
|
break;
|
|
564
577
|
if (!sig) {
|
|
@@ -883,6 +896,7 @@ export class RuntimeRunner {
|
|
|
883
896
|
maxTokens: this.opts.maxTokens,
|
|
884
897
|
maxTurns: effectiveMaxTurns,
|
|
885
898
|
timeoutMs: effectiveTimeoutMs !== undefined ? BigInt(effectiveTimeoutMs) : undefined,
|
|
899
|
+
maxTotalTokens: this.opts.maxTotalTokens !== undefined ? BigInt(this.opts.maxTotalTokens) : undefined,
|
|
886
900
|
});
|
|
887
901
|
this.activeKernel = runtime;
|
|
888
902
|
this.nextArchiveStart = nextCompressedArchiveStart;
|
|
@@ -1020,7 +1034,16 @@ export class RuntimeRunner {
|
|
|
1020
1034
|
: baseSpec;
|
|
1021
1035
|
startPayload.run_spec = agentRunSpecToKernel(spec);
|
|
1022
1036
|
}
|
|
1023
|
-
|
|
1037
|
+
// L1: seed the kernel with the group's cumulative spend so the run-level token cap + cumulative
|
|
1038
|
+
// spawn cap span the whole governance domain (other members' prior spend). No group ⇒ per-run.
|
|
1039
|
+
// Also register this session as a member so the run's lineage (R2) spans personas/invocations.
|
|
1040
|
+
let groupLedger;
|
|
1041
|
+
if (this.opts.runGroup) {
|
|
1042
|
+
const g = this.opts.runGroup;
|
|
1043
|
+
groupLedger = await g.budgetStore.read(g.id);
|
|
1044
|
+
await g.budgetStore.join(g.id, { sessionId, role: this.opts.agentId });
|
|
1045
|
+
}
|
|
1046
|
+
this.applyKernelPolicies(runtime, groupLedger?.tokensSpent, groupLedger?.subagentsSpawned);
|
|
1024
1047
|
// Multimodal upload: seed the user's attachments (images/audio) as a history
|
|
1025
1048
|
// message before start_run pushes the "[TASK STATE]" anchor. init_task does not
|
|
1026
1049
|
// clear history, so order becomes [attachment user msg, "Proceed…"] — both land
|
|
@@ -1077,7 +1100,7 @@ export class RuntimeRunner {
|
|
|
1077
1100
|
break;
|
|
1078
1101
|
}
|
|
1079
1102
|
if (this.opts.signalSource) {
|
|
1080
|
-
const sig = await this.opts.signalSource.nextSignal();
|
|
1103
|
+
const sig = await this.opts.signalSource.nextSignal(this.currentSessionId ?? undefined);
|
|
1081
1104
|
if (sig) {
|
|
1082
1105
|
// Kernel-routed: the kernel decides disposition (dedup/queue/interrupt) and emits
|
|
1083
1106
|
// `signal_disposed`. An actionable disposition yields a new action to adopt; queued/observed/
|
|
@@ -1500,6 +1523,14 @@ export class RuntimeRunner {
|
|
|
1500
1523
|
turnsUsed,
|
|
1501
1524
|
totalTokens,
|
|
1502
1525
|
}));
|
|
1526
|
+
// L1: charge this vehicle's local spend (tokens + sub-agent spawns) back to the governance domain
|
|
1527
|
+
// so the next member is seeded with the updated cumulative totals.
|
|
1528
|
+
if (this.opts.runGroup) {
|
|
1529
|
+
const subagents = runtime.localSubagentsSpawned?.() ?? 0;
|
|
1530
|
+
if (totalTokens > 0 || subagents > 0) {
|
|
1531
|
+
await this.opts.runGroup.budgetStore.charge(this.opts.runGroup.id, { tokens: totalTokens, subagents });
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1503
1534
|
if (this.opts.dreamStore && this.opts.agentId) {
|
|
1504
1535
|
const newMsgs = runtime.drainNewMessages().map(m => ({
|
|
1505
1536
|
role: m.role,
|
|
@@ -1941,6 +1972,8 @@ function signalToKernelEvent(sig) {
|
|
|
1941
1972
|
summary: String(sig.payload?.goal ?? sig.kind ?? "signal"),
|
|
1942
1973
|
payload: sig.payload ?? {},
|
|
1943
1974
|
...(sig.dedupeKey ? { dedupe_key: sig.dedupeKey } : {}),
|
|
1975
|
+
...(sig.recipient ? { recipient: sig.recipient } : {}),
|
|
1976
|
+
...(sig.topic ? { topic: sig.topic } : {}),
|
|
1944
1977
|
timestamp_ms: Date.now(),
|
|
1945
1978
|
},
|
|
1946
1979
|
};
|
|
@@ -275,6 +275,14 @@ export type SessionEvent = {
|
|
|
275
275
|
kind: "summary_upgraded";
|
|
276
276
|
compressed_seq: number;
|
|
277
277
|
summary: string;
|
|
278
|
+
} | {
|
|
279
|
+
kind: "group_member_joined";
|
|
280
|
+
session_id: string;
|
|
281
|
+
role?: string;
|
|
282
|
+
} | {
|
|
283
|
+
kind: "group_budget_charged";
|
|
284
|
+
tokens: number;
|
|
285
|
+
subagents: number;
|
|
278
286
|
};
|
|
279
287
|
export interface SessionLog {
|
|
280
288
|
append(sessionId: string, event: SessionEvent): Promise<number>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L2 (TurnPolicy) — who reacts to a blackboard event. This is the one caller-customizable seam of a
|
|
3
|
+
* `ReactiveSession`; the framework supplies a spanning default set (addressing / delegated /
|
|
4
|
+
* deterministic-cyclic) plus combinators, so teams compose rather than hand-roll turn-taking.
|
|
5
|
+
*
|
|
6
|
+
* Stateful policies (e.g. `roundRobin`) must keep their cursor in `state`, which a `ReactiveSession`
|
|
7
|
+
* persists to the group store so it survives stateless turns.
|
|
8
|
+
*/
|
|
9
|
+
import type { BlackboardEvent } from "./event-stream.js";
|
|
10
|
+
/** A peer the policy can choose to activate. */
|
|
11
|
+
export interface PeerView {
|
|
12
|
+
personaId: string;
|
|
13
|
+
role?: string;
|
|
14
|
+
channels?: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Decide which peers react to `event`. Async to allow LLM-delegated selection. `state` is opaque,
|
|
18
|
+
* persisted across turns by the session (for cursors etc.); mutate-and-return it.
|
|
19
|
+
*/
|
|
20
|
+
export type TurnPolicy = (event: BlackboardEvent, peers: PeerView[], state: Record<string, unknown>) => string[] | Promise<string[]>;
|
|
21
|
+
/** Addressing: react iff the event names the peer (its `audience`, or its id/role in the payload). */
|
|
22
|
+
export declare function reactByMention(): TurnPolicy;
|
|
23
|
+
/**
|
|
24
|
+
* Delegated: a designated persona (or fn) decides who reacts. The most flexible escape hatch — the
|
|
25
|
+
* selector can be an LLM call. `select` receives the event + candidate peers and returns chosen ids.
|
|
26
|
+
*/
|
|
27
|
+
export declare function directorDriven(directorId: string, select: (event: BlackboardEvent, peers: PeerView[]) => string[] | Promise<string[]>): TurnPolicy;
|
|
28
|
+
/** Deterministic: cycle through peers in order, one per event. Cursor persisted in `state`. */
|
|
29
|
+
export declare function roundRobin(): TurnPolicy;
|
|
30
|
+
/** Combinator: first policy that selects a non-empty set wins (e.g. mention, else director). */
|
|
31
|
+
export declare function firstNonEmpty(...policies: TurnPolicy[]): TurnPolicy;
|
|
32
|
+
/** Combinator: union of all policies' selections (deduped, order-stable). */
|
|
33
|
+
export declare function union(...policies: TurnPolicy[]): TurnPolicy;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const idsOf = (peers) => peers.map(p => p.personaId);
|
|
2
|
+
/** Addressing: react iff the event names the peer (its `audience`, or its id/role in the payload). */
|
|
3
|
+
export function reactByMention() {
|
|
4
|
+
return (event, peers) => {
|
|
5
|
+
const hay = typeof event.payload === "string" ? event.payload : JSON.stringify(event.payload ?? "");
|
|
6
|
+
return idsOf(peers).filter(id => {
|
|
7
|
+
const peer = peers.find(p => p.personaId === id);
|
|
8
|
+
if (event.audience?.includes(id))
|
|
9
|
+
return true;
|
|
10
|
+
if (hay.includes(id))
|
|
11
|
+
return true;
|
|
12
|
+
return peer.role !== undefined && hay.includes(peer.role);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Delegated: a designated persona (or fn) decides who reacts. The most flexible escape hatch — the
|
|
18
|
+
* selector can be an LLM call. `select` receives the event + candidate peers and returns chosen ids.
|
|
19
|
+
*/
|
|
20
|
+
export function directorDriven(directorId, select) {
|
|
21
|
+
return async (event, peers) => {
|
|
22
|
+
const chosen = await select(event, peers);
|
|
23
|
+
const valid = new Set(idsOf(peers));
|
|
24
|
+
return chosen.filter(id => valid.has(id) && id !== directorId);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Deterministic: cycle through peers in order, one per event. Cursor persisted in `state`. */
|
|
28
|
+
export function roundRobin() {
|
|
29
|
+
return (event, peers, state) => {
|
|
30
|
+
if (peers.length === 0)
|
|
31
|
+
return [];
|
|
32
|
+
const cursor = typeof state.rrCursor === "number" ? state.rrCursor : 0;
|
|
33
|
+
const idx = cursor % peers.length;
|
|
34
|
+
state.rrCursor = cursor + 1;
|
|
35
|
+
return [peers[idx].personaId];
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Combinator: first policy that selects a non-empty set wins (e.g. mention, else director). */
|
|
39
|
+
export function firstNonEmpty(...policies) {
|
|
40
|
+
return async (event, peers, state) => {
|
|
41
|
+
for (const p of policies) {
|
|
42
|
+
const chosen = await p(event, peers, state);
|
|
43
|
+
if (chosen.length > 0)
|
|
44
|
+
return chosen;
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Combinator: union of all policies' selections (deduped, order-stable). */
|
|
50
|
+
export function union(...policies) {
|
|
51
|
+
return async (event, peers, state) => {
|
|
52
|
+
const out = new Set();
|
|
53
|
+
for (const p of policies)
|
|
54
|
+
for (const id of await p(event, peers, state))
|
|
55
|
+
out.add(id);
|
|
56
|
+
return [...out];
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -16,8 +16,13 @@ export declare class SignalGateway implements SignalSource {
|
|
|
16
16
|
private timers;
|
|
17
17
|
private queue;
|
|
18
18
|
private listeners;
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Called by the agent loop each turn. Returns the oldest queued signal or null.
|
|
21
|
+
* When `recipient` is given, returns only the oldest signal addressed to it (plus
|
|
22
|
+
* unaddressed broadcasts); signals addressed to other recipients stay queued, so one
|
|
23
|
+
* shared gateway can serve N peer loops. Omit ⇒ legacy FIFO drain (any signal).
|
|
24
|
+
*/
|
|
25
|
+
nextSignal(recipient?: string): Promise<RuntimeSignal | null>;
|
|
21
26
|
/** Register a listener that is called synchronously whenever a signal is emitted. */
|
|
22
27
|
onSignal(listener: (sig: RuntimeSignal) => void): void;
|
|
23
28
|
/** Schedule a ScheduledPrompt to fire at its `runAtMs`. Idempotent by goal+time. */
|
package/dist/signals/gateway.js
CHANGED
|
@@ -15,9 +15,19 @@ export class SignalGateway {
|
|
|
15
15
|
queue = [];
|
|
16
16
|
listeners = [];
|
|
17
17
|
// ── SignalSource interface (pull model) ─────────────────────────────────────
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Called by the agent loop each turn. Returns the oldest queued signal or null.
|
|
20
|
+
* When `recipient` is given, returns only the oldest signal addressed to it (plus
|
|
21
|
+
* unaddressed broadcasts); signals addressed to other recipients stay queued, so one
|
|
22
|
+
* shared gateway can serve N peer loops. Omit ⇒ legacy FIFO drain (any signal).
|
|
23
|
+
*/
|
|
24
|
+
async nextSignal(recipient) {
|
|
25
|
+
if (recipient === undefined)
|
|
26
|
+
return this.queue.shift() ?? null;
|
|
27
|
+
const idx = this.queue.findIndex(s => s.recipient === undefined || s.recipient === recipient);
|
|
28
|
+
if (idx === -1)
|
|
29
|
+
return null;
|
|
30
|
+
return this.queue.splice(idx, 1)[0];
|
|
21
31
|
}
|
|
22
32
|
// ── Push API ────────────────────────────────────────────────────────────────
|
|
23
33
|
/** Register a listener that is called synchronously whenever a signal is emitted. */
|
package/dist/signals/types.d.ts
CHANGED
|
@@ -7,11 +7,20 @@ export interface RuntimeSignal {
|
|
|
7
7
|
urgency: RuntimeSignalUrgency;
|
|
8
8
|
payload: Record<string, unknown>;
|
|
9
9
|
dedupeKey?: string;
|
|
10
|
+
/** Target a specific session loop (its `sessionId`). Omitted ⇒ broadcast (any puller). */
|
|
11
|
+
recipient?: string;
|
|
12
|
+
/** Optional pub/sub topic (carried through; multi-subscriber routing deferred). */
|
|
13
|
+
topic?: string;
|
|
10
14
|
/** @deprecated Use source/signalType/urgency directly. */
|
|
11
15
|
kind?: "interrupt" | "scheduled" | "external";
|
|
12
16
|
/** @deprecated Prefer explicit `urgency`. */
|
|
13
17
|
priority?: number;
|
|
14
18
|
}
|
|
15
19
|
export interface SignalSource {
|
|
16
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Pull the next pending signal. When `recipient` is given, return only signals
|
|
22
|
+
* addressed to it (plus unaddressed broadcasts); other recipients' signals stay
|
|
23
|
+
* queued. Omit ⇒ legacy FIFO drain (any signal).
|
|
24
|
+
*/
|
|
25
|
+
nextSignal(recipient?: string): Promise<RuntimeSignal | null>;
|
|
17
26
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { SubAgentOrchestrator, defaultSubAgentOrchestrator, spawnStandalone } from "../runtime/sub-agent-orchestrator.js";
|
|
2
|
+
export type { SubAgentRunContext } from "../runtime/sub-agent-orchestrator.js";
|
|
3
|
+
export { builtinReducers, resolveReducer } from "../runtime/reducers.js";
|
|
4
|
+
export type { Reducer, ReducerRegistry, ReducerInput } from "../runtime/reducers.js";
|
|
5
|
+
export { FileWorkflowStore } from "../runtime/workflow-store.js";
|
|
6
|
+
export { submitWorkflowNodesTool, startWorkflowTool, generateAndFilter, verifyRules, genEval, milestoneCheckPass, milestoneCheckFail, } from "../types/agent.js";
|
|
7
|
+
export type { AgentCapabilityFilter, AgentIdentity, AgentIsolation, AgentRunSpec, AgentProcessChangedObservation, ContextInheritance, KernelAgentRole, LoopResult, MilestoneCheckResult, MilestoneContract, MilestonePhase, MilestonePolicy, SubAgentResult, TerminationReason, WorkflowSpawnInfo, WorkflowTaskSpec, } from "../types/agent.js";
|
|
8
|
+
export type { AcceptanceCriterion, VerificationContract, ContractCheckResult } from "../collaboration/contract.js";
|
|
9
|
+
export { ContractBuilder, formatContractForSystemPrompt, contractToCriteriaStrings } from "../collaboration/contract.js";
|
|
10
|
+
export type { AgentRole, IsolatedVerifierContext, CoordinatorConfig } from "../collaboration/pool.js";
|
|
11
|
+
export { ContractDrivenHarness } from "../collaboration/harness.js";
|
|
12
|
+
export type { ContractOutcome, ContractHarnessOptions, Violation } from "../collaboration/harness.js";
|
|
13
|
+
export { HandoffBus } from "../collaboration/handoff.js";
|
|
14
|
+
export type { HandoffArtifact, ContractOutcomeInput } from "../collaboration/handoff.js";
|
|
15
|
+
export { CreatorVerifierMode, OrchestrationMode } from "../collaboration/modes/creator-verifier.js";
|
|
16
|
+
export type { CreatorVerifierMetrics } from "../collaboration/modes/creator-verifier.js";
|
|
17
|
+
export { scanSkillDir, readSkillFile } from "../skills/loader.js";
|
|
18
|
+
export type { SkillMetadata } from "../skills/loader.js";
|
|
19
|
+
export { executeTools, readFile, validateToolArguments } from "../tools/index.js";
|
|
20
|
+
export type { ToolExecContext } from "../tools/index.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// `@deepstrike/sdk/workflow` — multi-agent orchestration: the sub-agent host, reducers, spec builders,
|
|
2
|
+
// workflow node tools, agent/milestone types, and the collaboration (contract/handoff/mode) layer.
|
|
3
|
+
// The root package exports `runFanout`, `AgentPool`, `WorkflowSpec`/`WorkflowNodeSpec`; the advanced
|
|
4
|
+
// machinery lives here.
|
|
5
|
+
export { SubAgentOrchestrator, defaultSubAgentOrchestrator, spawnStandalone } from "../runtime/sub-agent-orchestrator.js";
|
|
6
|
+
export { builtinReducers, resolveReducer } from "../runtime/reducers.js";
|
|
7
|
+
export { FileWorkflowStore } from "../runtime/workflow-store.js";
|
|
8
|
+
export { submitWorkflowNodesTool, startWorkflowTool, generateAndFilter, verifyRules, genEval, milestoneCheckPass, milestoneCheckFail, } from "../types/agent.js";
|
|
9
|
+
export { ContractBuilder, formatContractForSystemPrompt, contractToCriteriaStrings } from "../collaboration/contract.js";
|
|
10
|
+
export { ContractDrivenHarness } from "../collaboration/harness.js";
|
|
11
|
+
export { HandoffBus } from "../collaboration/handoff.js";
|
|
12
|
+
export { CreatorVerifierMode, OrchestrationMode } from "../collaboration/modes/creator-verifier.js";
|
|
13
|
+
// Skills loader + lower-level tool execution helpers.
|
|
14
|
+
export { scanSkillDir, readSkillFile } from "../skills/loader.js";
|
|
15
|
+
export { executeTools, readFile, validateToolArguments } from "../tools/index.js";
|
package/package.json
CHANGED
|
@@ -1,10 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"description": "DeepStrike Node.js SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./providers": {
|
|
14
|
+
"types": "./dist/providers/public.d.ts",
|
|
15
|
+
"import": "./dist/providers/public.js"
|
|
16
|
+
},
|
|
17
|
+
"./workflow": {
|
|
18
|
+
"types": "./dist/workflow/public.d.ts",
|
|
19
|
+
"import": "./dist/workflow/public.js"
|
|
20
|
+
},
|
|
21
|
+
"./planes": {
|
|
22
|
+
"types": "./dist/planes/public.d.ts",
|
|
23
|
+
"import": "./dist/planes/public.js"
|
|
24
|
+
},
|
|
25
|
+
"./memory": {
|
|
26
|
+
"types": "./dist/memory/public.d.ts",
|
|
27
|
+
"import": "./dist/memory/public.js"
|
|
28
|
+
},
|
|
29
|
+
"./harness": {
|
|
30
|
+
"types": "./dist/harness/public.d.ts",
|
|
31
|
+
"import": "./dist/harness/public.js"
|
|
32
|
+
},
|
|
33
|
+
"./os": {
|
|
34
|
+
"types": "./dist/os/public.d.ts",
|
|
35
|
+
"import": "./dist/os/public.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"typesVersions": {
|
|
39
|
+
"*": {
|
|
40
|
+
"providers": [
|
|
41
|
+
"./dist/providers/public.d.ts"
|
|
42
|
+
],
|
|
43
|
+
"workflow": [
|
|
44
|
+
"./dist/workflow/public.d.ts"
|
|
45
|
+
],
|
|
46
|
+
"planes": [
|
|
47
|
+
"./dist/planes/public.d.ts"
|
|
48
|
+
],
|
|
49
|
+
"memory": [
|
|
50
|
+
"./dist/memory/public.d.ts"
|
|
51
|
+
],
|
|
52
|
+
"harness": [
|
|
53
|
+
"./dist/harness/public.d.ts"
|
|
54
|
+
],
|
|
55
|
+
"os": [
|
|
56
|
+
"./dist/os/public.d.ts"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
8
60
|
"files": [
|
|
9
61
|
"dist",
|
|
10
62
|
"README.md"
|
|
@@ -20,7 +72,7 @@
|
|
|
20
72
|
},
|
|
21
73
|
"dependencies": {
|
|
22
74
|
"@anthropic-ai/sdk": "^0.99.0",
|
|
23
|
-
"@deepstrike/core": "0.2.
|
|
75
|
+
"@deepstrike/core": "0.2.31",
|
|
24
76
|
"@google/generative-ai": "^0.24.1",
|
|
25
77
|
"openai": "^5.23.2"
|
|
26
78
|
},
|