@deepstrike/wasm 0.1.6

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.
@@ -0,0 +1,74 @@
1
+ import type { Agent } from "../agent.js";
2
+ export interface Criterion {
3
+ text: string;
4
+ required: boolean;
5
+ weight?: number;
6
+ }
7
+ export interface CriterionResult {
8
+ criterion: string;
9
+ passed: boolean;
10
+ score: number;
11
+ feedback: string;
12
+ }
13
+ export interface HarnessRequest {
14
+ goal: string;
15
+ criteria?: Criterion[];
16
+ extensions?: Record<string, unknown>;
17
+ }
18
+ export interface HarnessOutcome {
19
+ result: string;
20
+ passed: boolean;
21
+ iterations: number;
22
+ totalTokens: number;
23
+ status: string;
24
+ overallScore?: number;
25
+ feedback?: string;
26
+ details?: CriterionResult[];
27
+ }
28
+ export interface Verdict {
29
+ passed: boolean;
30
+ overallScore: number;
31
+ feedback: string;
32
+ details: CriterionResult[];
33
+ }
34
+ export type HarnessEvent = {
35
+ type: "token";
36
+ text: string;
37
+ } | {
38
+ type: "tool_call";
39
+ id: string;
40
+ name: string;
41
+ } | {
42
+ type: "tool_result";
43
+ callId: string;
44
+ content: string;
45
+ isError: boolean;
46
+ } | {
47
+ type: "supervising";
48
+ } | {
49
+ type: "revising";
50
+ verdict: Verdict;
51
+ } | {
52
+ type: "done";
53
+ verdict: Verdict;
54
+ iterations: number;
55
+ totalTokens: number;
56
+ status: string;
57
+ } | {
58
+ type: "max_attempts_reached";
59
+ };
60
+ export declare class SinglePassHarness {
61
+ private agent;
62
+ constructor(agent: Agent);
63
+ run(request: HarnessRequest): Promise<HarnessOutcome>;
64
+ }
65
+ export interface HarnessLoopOptions {
66
+ maxAttempts?: number;
67
+ }
68
+ export declare class HarnessLoop {
69
+ private agent;
70
+ private evalProvider;
71
+ private maxAttempts;
72
+ constructor(agent: Agent, evalProvider: import("../types.js").LLMProvider, options?: HarnessLoopOptions);
73
+ runStreaming(request: HarnessRequest): AsyncIterable<HarnessEvent>;
74
+ }
@@ -0,0 +1,91 @@
1
+ async function runOnce(agent, goal, req) {
2
+ let text = "";
3
+ let done;
4
+ for await (const evt of agent.runStreaming(goal, (req.criteria ?? []).map(c => c.text), req.extensions)) {
5
+ if (evt.type === "text_delta")
6
+ text += evt.delta;
7
+ else if (evt.type === "done")
8
+ done = evt;
9
+ }
10
+ return { result: text, passed: false, iterations: done?.iterations ?? 0, totalTokens: done?.totalTokens ?? 0, status: done?.status ?? "error" };
11
+ }
12
+ export class SinglePassHarness {
13
+ agent;
14
+ constructor(agent) {
15
+ this.agent = agent;
16
+ }
17
+ async run(request) {
18
+ return { ...await runOnce(this.agent, request.goal, request), passed: true };
19
+ }
20
+ }
21
+ export class HarnessLoop {
22
+ agent;
23
+ evalProvider;
24
+ maxAttempts;
25
+ constructor(agent, evalProvider, options = {}) {
26
+ this.agent = agent;
27
+ this.evalProvider = evalProvider;
28
+ this.maxAttempts = options.maxAttempts ?? 3;
29
+ }
30
+ async *runStreaming(request) {
31
+ const kernel = await import("@deepstrike/wasm-kernel");
32
+ const pipeline = new kernel.EvalPipeline({ extractSkillOnPass: true });
33
+ const criteria = request.criteria ?? [];
34
+ let currentGoal = request.goal;
35
+ let lastIterations = 0;
36
+ let lastTotalTokens = 0;
37
+ let lastStatus = "error";
38
+ let lastResult = "";
39
+ for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
40
+ for await (const evt of this.agent.runStreaming(currentGoal, criteria.map(c => c.text), request.extensions)) {
41
+ if (evt.type === "text_delta") {
42
+ lastResult += evt.delta;
43
+ yield { type: "token", text: evt.delta };
44
+ }
45
+ else if (evt.type === "tool_call") {
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ const tc = evt;
48
+ yield { type: "tool_call", id: tc.id, name: tc.name };
49
+ }
50
+ else if (evt.type === "tool_result") {
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ const tr = evt;
53
+ yield { type: "tool_result", callId: tr.callId, content: tr.content, isError: tr.isError };
54
+ }
55
+ else if (evt.type === "done") {
56
+ const d = evt;
57
+ lastIterations = d.iterations;
58
+ lastTotalTokens = d.totalTokens;
59
+ lastStatus = d.status;
60
+ }
61
+ }
62
+ yield { type: "supervising" };
63
+ const evalAction = pipeline.feedOutcome(request.goal, criteria, lastResult, attempt);
64
+ if (evalAction.kind !== "evaluate")
65
+ break;
66
+ let evalText = "";
67
+ for await (const evt of this.evalProvider.stream((evalAction.messages ?? []), [], undefined)) {
68
+ if (evt.type === "text_delta")
69
+ evalText += evt.delta;
70
+ }
71
+ const doneAction = pipeline.feedEvalResult(evalText);
72
+ if (doneAction.kind !== "done")
73
+ break;
74
+ const verdict = {
75
+ passed: doneAction.passed ?? false,
76
+ overallScore: doneAction.overallScore ?? 0,
77
+ feedback: doneAction.feedback ?? "",
78
+ details: doneAction.details ?? [],
79
+ };
80
+ if (verdict.passed) {
81
+ yield { type: "done", verdict, iterations: lastIterations, totalTokens: lastTotalTokens, status: lastStatus };
82
+ return;
83
+ }
84
+ yield { type: "revising", verdict };
85
+ currentGoal = `${request.goal}\n\n[Attempt ${attempt} feedback: ${verdict.feedback}]`;
86
+ lastResult = "";
87
+ pipeline.reset();
88
+ }
89
+ yield { type: "max_attempts_reached" };
90
+ }
91
+ }
@@ -0,0 +1,18 @@
1
+ export { Agent } from "./agent.js";
2
+ export type { AgentOptions, SkillMetadata } from "./agent.js";
3
+ export { Governance } from "./governance.js";
4
+ export type { GovernanceVerdict } from "./governance.js";
5
+ export { AnthropicProvider } from "./providers/anthropic.js";
6
+ export { OpenAIProvider, QwenProvider, DeepSeekProvider, MiniMaxProvider, KimiProvider } from "./providers/openai.js";
7
+ export { tool, executeTools } from "./tools/index.js";
8
+ export type { RegisteredTool } from "./tools/index.js";
9
+ export { WorkingMemory } from "./memory/index.js";
10
+ export type { DreamStore, DreamResult, SessionData, SessionMessage, MemoryEntry, CurationResult, CurationStats, } from "./memory/index.js";
11
+ export type { KnowledgeSource } from "./knowledge/index.js";
12
+ export { SinglePassHarness, HarnessLoop } from "./harness/index.js";
13
+ export type { HarnessRequest, HarnessOutcome, HarnessLoopOptions } from "./harness/index.js";
14
+ export { ScheduledPrompt } from "./signals/index.js";
15
+ export type { RuntimeSignal, SignalSource } from "./signals/index.js";
16
+ export { PermissionManager, PermissionMode } from "./safety/index.js";
17
+ export type { PermissionDecision } from "./safety/index.js";
18
+ export type { Message, ToolCall, ToolResult, ToolSchema, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolResultEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, LLMProvider, } from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { Agent } from "./agent.js";
2
+ export { Governance } from "./governance.js";
3
+ export { AnthropicProvider } from "./providers/anthropic.js";
4
+ export { OpenAIProvider, QwenProvider, DeepSeekProvider, MiniMaxProvider, KimiProvider } from "./providers/openai.js";
5
+ export { tool, executeTools } from "./tools/index.js";
6
+ export { WorkingMemory } from "./memory/index.js";
7
+ export { SinglePassHarness, HarnessLoop } from "./harness/index.js";
8
+ export { ScheduledPrompt } from "./signals/index.js";
9
+ export { PermissionManager, PermissionMode } from "./safety/index.js";
@@ -0,0 +1,5 @@
1
+ export interface KnowledgeSource {
2
+ retrieve(goal: string, topK?: number): Promise<string[]>;
3
+ /** One-time warmup called before the first run (load index, open connection, etc.). */
4
+ init(): Promise<void>;
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,56 @@
1
+ export declare class WorkingMemory {
2
+ private store;
3
+ set(key: string, value: unknown): void;
4
+ get<T = unknown>(key: string, defaultValue?: T): T | undefined;
5
+ delete(key: string): void;
6
+ clear(): void;
7
+ has(key: string): boolean;
8
+ }
9
+ export interface SessionMessage {
10
+ role: "user" | "assistant" | "tool";
11
+ content: string;
12
+ tokenCount?: number;
13
+ toolCalls?: Array<{
14
+ id: string;
15
+ name: string;
16
+ arguments: string;
17
+ }>;
18
+ }
19
+ export interface SessionData {
20
+ sessionId: string;
21
+ agentId: string;
22
+ messages: SessionMessage[];
23
+ metadata: unknown;
24
+ createdAtMs: number;
25
+ updatedAtMs: number;
26
+ }
27
+ export interface MemoryEntry {
28
+ text: string;
29
+ score: number;
30
+ metadata: unknown;
31
+ }
32
+ export interface CurationStats {
33
+ insightsProcessed: number;
34
+ duplicatesRemoved: number;
35
+ conflictsResolved: number;
36
+ entriesAdded: number;
37
+ }
38
+ export interface CurationResult {
39
+ toAdd: MemoryEntry[];
40
+ toRemoveIndices: number[];
41
+ stats: CurationStats;
42
+ }
43
+ export interface DreamResult {
44
+ sessionsProcessed: number;
45
+ insightsExtracted: number;
46
+ entriesAdded: number;
47
+ entriesRemoved: number;
48
+ }
49
+ export interface DreamStore {
50
+ loadSessions(agentId: string): Promise<SessionData[]>;
51
+ loadMemories(agentId: string): Promise<MemoryEntry[]>;
52
+ commit(agentId: string, result: CurationResult, existing: MemoryEntry[]): Promise<void>;
53
+ search(agentId: string, query: string, topK?: number): Promise<MemoryEntry[]>;
54
+ /** Persist a completed session for future consolidation via `Agent.dream()`. */
55
+ saveSession(data: SessionData): Promise<void>;
56
+ }
@@ -0,0 +1,8 @@
1
+ export class WorkingMemory {
2
+ store = new Map();
3
+ set(key, value) { this.store.set(key, value); }
4
+ get(key, defaultValue) { return this.store.get(key) ?? defaultValue; }
5
+ delete(key) { this.store.delete(key); }
6
+ clear() { this.store.clear(); }
7
+ has(key) { return this.store.has(key); }
8
+ }
@@ -0,0 +1,8 @@
1
+ import type { Message, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
2
+ export declare class AnthropicProvider implements LLMProvider {
3
+ private readonly apiKey;
4
+ private readonly model;
5
+ private readonly maxTokens;
6
+ constructor(apiKey: string, model?: string, maxTokens?: number);
7
+ stream(messages: Message[], tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
8
+ }
@@ -0,0 +1,89 @@
1
+ function buildAnthropicTools(tools) {
2
+ return tools.map(t => ({ name: t.name, description: t.description, input_schema: JSON.parse(t.parameters) }));
3
+ }
4
+ export class AnthropicProvider {
5
+ apiKey;
6
+ model;
7
+ maxTokens;
8
+ constructor(apiKey, model = "claude-sonnet-4-6", maxTokens = 8096) {
9
+ this.apiKey = apiKey;
10
+ this.model = model;
11
+ this.maxTokens = maxTokens;
12
+ }
13
+ async *stream(messages, tools, extensions) {
14
+ const system = messages.filter(m => m.role === "system").map(m => m.content).join("\n\n");
15
+ const msgs = messages.filter(m => m.role !== "system").map(m => ({ role: m.role, content: m.content }));
16
+ const body = {
17
+ model: this.model,
18
+ max_tokens: this.maxTokens,
19
+ messages: msgs,
20
+ stream: true,
21
+ ...(system ? { system } : {}),
22
+ ...(tools.length ? { tools: buildAnthropicTools(tools) } : {}),
23
+ };
24
+ if (extensions?.enable_thinking) {
25
+ body.thinking = { type: "enabled", budget_tokens: 8000 };
26
+ }
27
+ const resp = await fetch("https://api.anthropic.com/v1/messages", {
28
+ method: "POST",
29
+ headers: {
30
+ "x-api-key": this.apiKey,
31
+ "anthropic-version": "2023-06-01",
32
+ "content-type": "application/json",
33
+ },
34
+ body: JSON.stringify(body),
35
+ });
36
+ if (!resp.ok)
37
+ throw new Error(`Anthropic ${resp.status}: ${await resp.text()}`);
38
+ const toolBlocks = {};
39
+ const reader = resp.body.getReader();
40
+ const decoder = new TextDecoder();
41
+ let buf = "";
42
+ while (true) {
43
+ const { done, value } = await reader.read();
44
+ if (done)
45
+ break;
46
+ buf += decoder.decode(value, { stream: true });
47
+ const lines = buf.split("\n");
48
+ buf = lines.pop() ?? "";
49
+ for (const line of lines) {
50
+ if (!line.startsWith("data: "))
51
+ continue;
52
+ const data = line.slice(6).trim();
53
+ if (data === "[DONE]")
54
+ return;
55
+ try {
56
+ const evt = JSON.parse(data);
57
+ if (evt.type === "content_block_start") {
58
+ const cb = evt.content_block;
59
+ if (cb.type === "tool_use")
60
+ toolBlocks[evt.index] = { id: cb.id, name: cb.name, argsBuf: "" };
61
+ }
62
+ else if (evt.type === "content_block_delta") {
63
+ const d = evt.delta;
64
+ const idx = evt.index;
65
+ if (d.type === "text_delta")
66
+ yield { type: "text_delta", delta: d.text };
67
+ else if (d.type === "thinking_delta")
68
+ yield { type: "thinking_delta", delta: d.thinking };
69
+ else if (d.type === "input_json_delta" && toolBlocks[idx])
70
+ toolBlocks[idx].argsBuf += d.partial_json;
71
+ }
72
+ else if (evt.type === "content_block_stop" && toolBlocks[evt.index]) {
73
+ const tb = toolBlocks[evt.index];
74
+ delete toolBlocks[evt.index];
75
+ let args = {};
76
+ try {
77
+ args = JSON.parse(tb.argsBuf || "{}");
78
+ }
79
+ catch {
80
+ args = {};
81
+ }
82
+ yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
83
+ }
84
+ }
85
+ catch { /* skip malformed */ }
86
+ }
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,32 @@
1
+ import type { Message, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
2
+ export declare class OpenAIProvider implements LLMProvider {
3
+ protected readonly apiKey: string;
4
+ protected readonly model: string;
5
+ protected readonly baseUrl: string;
6
+ constructor(apiKey: string, model?: string, baseUrl?: string);
7
+ protected buildTools(tools: ToolSchema[]): {
8
+ type: string;
9
+ function: {
10
+ name: string;
11
+ description: string;
12
+ parameters: any;
13
+ };
14
+ }[];
15
+ protected streamInner(messages: Message[], tools: ToolSchema[], extraBody: Record<string, unknown>, exposeReasoning?: boolean): AsyncIterable<StreamEvent>;
16
+ stream(messages: Message[], tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
17
+ }
18
+ export declare class QwenProvider extends OpenAIProvider {
19
+ constructor(apiKey: string, model?: string);
20
+ stream(messages: Message[], tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
21
+ }
22
+ export declare class DeepSeekProvider extends OpenAIProvider {
23
+ constructor(apiKey: string, model?: string);
24
+ stream(messages: Message[], tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
25
+ }
26
+ export declare class MiniMaxProvider extends OpenAIProvider {
27
+ constructor(apiKey: string, model?: string);
28
+ stream(messages: Message[], tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
29
+ }
30
+ export declare class KimiProvider extends OpenAIProvider {
31
+ constructor(apiKey: string, model?: string);
32
+ }
@@ -0,0 +1,127 @@
1
+ const DEEPSEEK_REASONERS = new Set(["deepseek-reasoner", "deepseek-r1"]);
2
+ const MINIMAX_REASONERS = new Set(["MiniMax-M1", "minimax-m1"]);
3
+ // OpenAI-compatible provider — works for OpenAI, Qwen (DashScope), DeepSeek, MiniMax, Kimi
4
+ export class OpenAIProvider {
5
+ apiKey;
6
+ model;
7
+ baseUrl;
8
+ constructor(apiKey, model = "gpt-4o", baseUrl = "https://api.openai.com/v1") {
9
+ this.apiKey = apiKey;
10
+ this.model = model;
11
+ this.baseUrl = baseUrl;
12
+ }
13
+ buildTools(tools) {
14
+ return tools.map(t => ({ type: "function", function: { name: t.name, description: t.description, parameters: JSON.parse(t.parameters) } }));
15
+ }
16
+ async *streamInner(messages, tools, extraBody, exposeReasoning = false) {
17
+ const msgs = messages.map(m => ({ role: m.role, content: m.content }));
18
+ const body = {
19
+ model: this.model,
20
+ messages: msgs,
21
+ stream: true,
22
+ ...(tools.length ? { tools: this.buildTools(tools) } : {}),
23
+ ...extraBody,
24
+ };
25
+ const resp = await fetch(`${this.baseUrl}/chat/completions`, {
26
+ method: "POST",
27
+ headers: { "Authorization": `Bearer ${this.apiKey}`, "Content-Type": "application/json" },
28
+ body: JSON.stringify(body),
29
+ });
30
+ if (!resp.ok)
31
+ throw new Error(`OpenAI ${resp.status}: ${await resp.text()}`);
32
+ const toolAccum = {};
33
+ const reader = resp.body.getReader();
34
+ const decoder = new TextDecoder();
35
+ let buf = "";
36
+ while (true) {
37
+ const { done, value } = await reader.read();
38
+ if (done)
39
+ break;
40
+ buf += decoder.decode(value, { stream: true });
41
+ const lines = buf.split("\n");
42
+ buf = lines.pop() ?? "";
43
+ for (const line of lines) {
44
+ if (!line.startsWith("data: "))
45
+ continue;
46
+ const data = line.slice(6).trim();
47
+ if (data === "[DONE]")
48
+ return;
49
+ try {
50
+ const chunk = JSON.parse(data);
51
+ const delta = chunk.choices?.[0]?.delta;
52
+ if (!delta)
53
+ continue;
54
+ if (exposeReasoning && typeof delta.reasoning_content === "string" && delta.reasoning_content)
55
+ yield { type: "thinking_delta", delta: delta.reasoning_content };
56
+ if (typeof delta.content === "string" && delta.content)
57
+ yield { type: "text_delta", delta: delta.content };
58
+ for (const tc of delta.tool_calls ?? []) {
59
+ const idx = tc.index;
60
+ if (!toolAccum[idx])
61
+ toolAccum[idx] = { id: tc.id ?? "", name: tc.function?.name ?? "", argsBuf: "" };
62
+ toolAccum[idx].argsBuf += tc.function?.arguments ?? "";
63
+ }
64
+ }
65
+ catch { /* skip */ }
66
+ }
67
+ }
68
+ for (const tb of Object.values(toolAccum)) {
69
+ let args = {};
70
+ try {
71
+ args = JSON.parse(tb.argsBuf || "{}");
72
+ }
73
+ catch {
74
+ args = {};
75
+ }
76
+ yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
77
+ }
78
+ }
79
+ async *stream(messages, tools, extensions) {
80
+ const { expose_reasoning: _, exposeReasoning: __, ...passthrough } = extensions ?? {};
81
+ yield* this.streamInner(messages, tools, passthrough);
82
+ }
83
+ }
84
+ export class QwenProvider extends OpenAIProvider {
85
+ constructor(apiKey, model = "qwen-max") {
86
+ super(apiKey, model, "https://dashscope.aliyuncs.com/compatible-mode/v1");
87
+ }
88
+ async *stream(messages, tools, extensions) {
89
+ const enableThinking = Boolean(extensions?.enableThinking);
90
+ const thinkingBudget = extensions?.thinkingBudget;
91
+ const { enableThinking: _, thinkingBudget: __, expose_reasoning: ___, exposeReasoning: ____, ...passthrough } = extensions ?? {};
92
+ const extra = {
93
+ ...passthrough,
94
+ ...(enableThinking ? { enable_thinking: true, ...(thinkingBudget ? { thinking_budget: thinkingBudget } : {}) } : {}),
95
+ };
96
+ yield* this.streamInner(messages, tools, extra, enableThinking);
97
+ }
98
+ }
99
+ export class DeepSeekProvider extends OpenAIProvider {
100
+ constructor(apiKey, model = "deepseek-chat") {
101
+ super(apiKey, model, "https://api.deepseek.com/v1");
102
+ }
103
+ async *stream(messages, tools, extensions) {
104
+ const exposeReasoning = Boolean(extensions?.exposeReasoning);
105
+ const isReasoner = DEEPSEEK_REASONERS.has(this.model);
106
+ const filteredTools = isReasoner ? [] : tools;
107
+ const { exposeReasoning: _, expose_reasoning: __, ...passthrough } = extensions ?? {};
108
+ yield* this.streamInner(messages, filteredTools, passthrough, exposeReasoning);
109
+ }
110
+ }
111
+ export class MiniMaxProvider extends OpenAIProvider {
112
+ constructor(apiKey, model = "MiniMax-Text-01") {
113
+ super(apiKey, model, "https://api.minimax.chat/v1");
114
+ }
115
+ async *stream(messages, tools, extensions) {
116
+ const exposeReasoning = Boolean(extensions?.exposeReasoning);
117
+ const isReasoner = MINIMAX_REASONERS.has(this.model);
118
+ const filteredTools = isReasoner ? [] : tools;
119
+ const { exposeReasoning: _, expose_reasoning: __, ...passthrough } = extensions ?? {};
120
+ yield* this.streamInner(messages, filteredTools, passthrough, exposeReasoning);
121
+ }
122
+ }
123
+ export class KimiProvider extends OpenAIProvider {
124
+ constructor(apiKey, model = "moonshot-v1-8k") {
125
+ super(apiKey, model, "https://api.moonshot.cn/v1");
126
+ }
127
+ }
@@ -0,0 +1,17 @@
1
+ export declare enum PermissionMode {
2
+ DEFAULT = "DEFAULT",
3
+ PLAN = "PLAN",
4
+ AUTO = "AUTO"
5
+ }
6
+ export interface PermissionDecision {
7
+ allowed: boolean;
8
+ reason: string;
9
+ }
10
+ export declare class PermissionManager {
11
+ private mode;
12
+ private grants;
13
+ constructor(mode?: PermissionMode);
14
+ grant(resource: string, action: string): this;
15
+ revoke(resource: string, action: string): this;
16
+ evaluate(resource: string, action: string): PermissionDecision;
17
+ }
@@ -0,0 +1,32 @@
1
+ export var PermissionMode;
2
+ (function (PermissionMode) {
3
+ PermissionMode["DEFAULT"] = "DEFAULT";
4
+ PermissionMode["PLAN"] = "PLAN";
5
+ PermissionMode["AUTO"] = "AUTO";
6
+ })(PermissionMode || (PermissionMode = {}));
7
+ export class PermissionManager {
8
+ mode;
9
+ grants = new Map();
10
+ constructor(mode = PermissionMode.DEFAULT) {
11
+ this.mode = mode;
12
+ }
13
+ grant(resource, action) {
14
+ if (!this.grants.has(resource))
15
+ this.grants.set(resource, new Set());
16
+ this.grants.get(resource).add(action);
17
+ return this;
18
+ }
19
+ revoke(resource, action) {
20
+ this.grants.get(resource)?.delete(action);
21
+ return this;
22
+ }
23
+ evaluate(resource, action) {
24
+ if (this.mode === PermissionMode.AUTO)
25
+ return { allowed: true, reason: "AUTO mode" };
26
+ if (this.mode === PermissionMode.PLAN)
27
+ return { allowed: false, reason: "PLAN mode blocks all" };
28
+ const actions = this.grants.get(resource);
29
+ const allowed = !!(actions && (actions.has(action) || actions.has("*")));
30
+ return { allowed, reason: allowed ? "granted" : "not granted" };
31
+ }
32
+ }
@@ -0,0 +1,18 @@
1
+ export interface RuntimeSignal {
2
+ source: "cron" | "gateway" | "heartbeat" | "custom";
3
+ signalType: "event" | "job" | "alert";
4
+ urgency: "low" | "normal" | "high" | "critical";
5
+ payload: Record<string, unknown>;
6
+ dedupeKey?: string;
7
+ }
8
+ export interface SignalSource {
9
+ nextSignal(): Promise<RuntimeSignal | null>;
10
+ }
11
+ export declare class ScheduledPrompt {
12
+ readonly goal: string;
13
+ readonly runAtMs: number;
14
+ readonly criteria: string[];
15
+ readonly metadata: Record<string, unknown>;
16
+ constructor(goal: string, runAtMs: number, criteria?: string[], metadata?: Record<string, unknown>);
17
+ toSignal(): RuntimeSignal;
18
+ }
@@ -0,0 +1,21 @@
1
+ export class ScheduledPrompt {
2
+ goal;
3
+ runAtMs;
4
+ criteria;
5
+ metadata;
6
+ constructor(goal, runAtMs, criteria = [], metadata = {}) {
7
+ this.goal = goal;
8
+ this.runAtMs = runAtMs;
9
+ this.criteria = criteria;
10
+ this.metadata = metadata;
11
+ }
12
+ toSignal() {
13
+ return {
14
+ source: "cron",
15
+ signalType: "job",
16
+ urgency: "normal",
17
+ payload: { goal: this.goal, criteria: this.criteria, runAtMs: this.runAtMs, ...this.metadata },
18
+ dedupeKey: `scheduled-${this.runAtMs}`,
19
+ };
20
+ }
21
+ }
@@ -0,0 +1,11 @@
1
+ import type { ToolSchema, ToolResult } from "../types.js";
2
+ export interface RegisteredTool {
3
+ schema: ToolSchema;
4
+ execute(args: Record<string, unknown>): Promise<string>;
5
+ }
6
+ export declare function tool(name: string, description: string, parameters: Record<string, unknown>, fn: (args: Record<string, unknown>) => Promise<string> | string): RegisteredTool;
7
+ export declare function executeTools(calls: {
8
+ id: string;
9
+ name: string;
10
+ arguments: string;
11
+ }[], registry: Map<string, RegisteredTool>): Promise<ToolResult[]>;
@@ -0,0 +1,20 @@
1
+ export function tool(name, description, parameters, fn) {
2
+ return {
3
+ schema: { name, description, parameters: JSON.stringify(parameters) },
4
+ async execute(args) { return fn(args); },
5
+ };
6
+ }
7
+ export async function executeTools(calls, registry) {
8
+ return Promise.all(calls.map(async (c) => {
9
+ const t = registry.get(c.name);
10
+ if (!t)
11
+ return { callId: c.id, output: `unknown tool: ${c.name}`, isError: true };
12
+ try {
13
+ const args = JSON.parse(c.arguments || "{}");
14
+ return { callId: c.id, output: await t.execute(args), isError: false };
15
+ }
16
+ catch (err) {
17
+ return { callId: c.id, output: String(err), isError: true };
18
+ }
19
+ }));
20
+ }