pi-shadow-mind 0.1.5

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 (51) hide show
  1. package/DESIGN.md +493 -0
  2. package/README.md +58 -0
  3. package/dist/config.d.ts +18 -0
  4. package/dist/config.js +132 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/entity-store.d.ts +22 -0
  7. package/dist/entity-store.js +71 -0
  8. package/dist/entity-store.js.map +1 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +8537 -0
  11. package/dist/index.js.map +7 -0
  12. package/dist/management-tools.d.ts +4 -0
  13. package/dist/management-tools.js +130 -0
  14. package/dist/management-tools.js.map +1 -0
  15. package/dist/protocol.d.ts +5 -0
  16. package/dist/protocol.js +34 -0
  17. package/dist/protocol.js.map +1 -0
  18. package/dist/random.d.ts +2 -0
  19. package/dist/random.js +14 -0
  20. package/dist/random.js.map +1 -0
  21. package/dist/registry.d.ts +9 -0
  22. package/dist/registry.js +139 -0
  23. package/dist/registry.js.map +1 -0
  24. package/dist/report-batcher.d.ts +15 -0
  25. package/dist/report-batcher.js +49 -0
  26. package/dist/report-batcher.js.map +1 -0
  27. package/dist/runtime.d.ts +36 -0
  28. package/dist/runtime.js +274 -0
  29. package/dist/runtime.js.map +1 -0
  30. package/dist/scheduler.d.ts +10 -0
  31. package/dist/scheduler.js +46 -0
  32. package/dist/scheduler.js.map +1 -0
  33. package/dist/shadow-runner.d.ts +93 -0
  34. package/dist/shadow-runner.js +251 -0
  35. package/dist/shadow-runner.js.map +1 -0
  36. package/dist/shutdown-drain.d.ts +12 -0
  37. package/dist/shutdown-drain.js +22 -0
  38. package/dist/shutdown-drain.js.map +1 -0
  39. package/dist/summaries.d.ts +9 -0
  40. package/dist/summaries.js +56 -0
  41. package/dist/summaries.js.map +1 -0
  42. package/dist/trajectory.d.ts +7 -0
  43. package/dist/trajectory.js +33 -0
  44. package/dist/trajectory.js.map +1 -0
  45. package/dist/types.d.ts +64 -0
  46. package/dist/types.js +2 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/validation.d.ts +8 -0
  49. package/dist/validation.js +18 -0
  50. package/dist/validation.js.map +1 -0
  51. package/package.json +52 -0
@@ -0,0 +1,4 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import type { ShadowConfig } from "./types.js";
3
+ import { type EntityStore } from "./entity-store.js";
4
+ export declare function registerManagementTools(pi: ExtensionAPI, store: EntityStore, getConfig: () => ShadowConfig): void;
@@ -0,0 +1,130 @@
1
+ import { Type } from "typebox";
2
+ import { parseConfig } from "./config.js";
3
+ import { describeShadow } from "./entity-store.js";
4
+ const ID = Type.String({ pattern: "^[a-z0-9][a-z0-9_-]*$" });
5
+ const THINKING = Type.Union([Type.Literal("minimal"), Type.Literal("low"), Type.Literal("medium"), Type.Literal("high"), Type.Literal("xhigh"), Type.Literal("max")]);
6
+ const SHADOW_FIELDS = {
7
+ name: Type.Optional(Type.String()),
8
+ enabled: Type.Optional(Type.Boolean()),
9
+ debug: Type.Optional(Type.Boolean()),
10
+ activation_probability: Type.Optional(Type.Number({ minimum: 0, maximum: 1 })),
11
+ active_for_models: Type.Optional(Type.Array(Type.String())),
12
+ run_with_model: Type.Optional(Type.String()),
13
+ thinking_level: Type.Optional(THINKING),
14
+ timeout_seconds: Type.Optional(Type.Number({ exclusiveMinimum: 0 })),
15
+ tools: Type.Optional(Type.Array(Type.String())),
16
+ prompt: Type.Optional(Type.String()),
17
+ };
18
+ export function registerManagementTools(pi, store, getConfig) {
19
+ pi.registerTool(listTool(store));
20
+ pi.registerTool(createTool(store));
21
+ pi.registerTool(updateTool(store));
22
+ pi.registerTool(toggleTool(store, true));
23
+ pi.registerTool(toggleTool(store, false));
24
+ pi.registerTool(deleteTool(store));
25
+ pi.registerTool(configReadTool(store));
26
+ pi.registerTool(configWriteTool(store, getConfig));
27
+ }
28
+ function listTool(store) {
29
+ return tool("list_shadows", "List Shadows", "List all valid globally configured Shadow Minds.", Type.Object({}), async () => {
30
+ const shadows = await store.list();
31
+ return textResult(shadows.length ? shadows.map(describeShadow).join("\n") : "No Shadow Minds configured.");
32
+ });
33
+ }
34
+ function createTool(store) {
35
+ return tool("create_shadow", "Create Shadow", "Create a global Shadow Mind definition after user confirmation.", Type.Object({ id: ID, ...SHADOW_FIELDS, prompt: Type.String() }), async (_id, params, _signal, _update, ctx) => {
36
+ const raw = params;
37
+ if (!(await confirm(ctx, "Create Shadow Mind", `Create ${String(raw.id)} in the global registry?`)))
38
+ return textResult("Cancelled.");
39
+ const shadow = await store.create(toDraft(raw));
40
+ return textResult(`Created ${describeShadow(shadow)}`);
41
+ });
42
+ }
43
+ function updateTool(store) {
44
+ return tool("update_shadow", "Update Shadow", "Update a global Shadow Mind definition after user confirmation. The id is immutable.", Type.Object({ id: ID, ...SHADOW_FIELDS }), async (_id, params, _signal, _update, ctx) => {
45
+ const raw = params;
46
+ if (!(await confirm(ctx, "Update Shadow Mind", `Apply changes to ${String(raw.id)}?`)))
47
+ return textResult("Cancelled.");
48
+ const shadow = await store.update(String(raw.id), toPatch(raw));
49
+ return textResult(`Updated ${describeShadow(shadow)}`);
50
+ });
51
+ }
52
+ function toggleTool(store, enabled) {
53
+ const action = enabled ? "enable" : "disable";
54
+ return tool(`${action}_shadow`, `${enabled ? "Enable" : "Disable"} Shadow`, `${enabled ? "Enable" : "Disable"} a global Shadow Mind after user confirmation.`, Type.Object({ id: ID }), async (_id, params, _signal, _update, ctx) => {
55
+ const id = String(params.id);
56
+ if (!(await confirm(ctx, `${enabled ? "Enable" : "Disable"} Shadow Mind`, `${action} ${id}?`)))
57
+ return textResult("Cancelled.");
58
+ return textResult(describeShadow(await store.setEnabled(id, enabled)));
59
+ });
60
+ }
61
+ function deleteTool(store) {
62
+ return tool("delete_shadow", "Delete Shadow", "Delete a Shadow Mind definition after user confirmation. Debug logs are retained.", Type.Object({ id: ID }), async (_id, params, _signal, _update, ctx) => {
63
+ const id = String(params.id);
64
+ if (!(await confirm(ctx, "Delete Shadow Mind", `Delete ${id}? Its debug logs will be kept.`)))
65
+ return textResult("Cancelled.");
66
+ await store.delete(id);
67
+ return textResult(`Deleted ${id}; logs were retained.`);
68
+ });
69
+ }
70
+ function configReadTool(store) {
71
+ return tool("get_shadow_config", "Get Shadow Config", "Read the global Shadow Mind runtime configuration.", Type.Object({}), async () => textResult(await store.readConfig()));
72
+ }
73
+ function configWriteTool(store, getConfig) {
74
+ return tool("update_shadow_config", "Update Shadow Config", "Update global Shadow Mind runtime configuration after user confirmation.", Type.Object({
75
+ heartbeat_probability: Type.Optional(Type.Number({ minimum: 0, maximum: 1 })),
76
+ max_parallel_shadows: Type.Optional(Type.Integer({ minimum: 1 })),
77
+ default_shadow_timeout_seconds: Type.Optional(Type.Number({ exclusiveMinimum: 0 })),
78
+ headless_drain_timeout_seconds: Type.Optional(Type.Number({ exclusiveMinimum: 0 })),
79
+ result_batch_window_ms: Type.Optional(Type.Integer({ minimum: 0 })),
80
+ default_shadow_model: Type.Optional(Type.String()),
81
+ default_thinking_level: Type.Optional(THINKING),
82
+ random_seed: Type.Optional(Type.Integer({ minimum: 0, maximum: 0xffff_ffff })),
83
+ }), async (_id, params, _signal, _update, ctx) => {
84
+ const current = getConfig();
85
+ const raw = params;
86
+ const next = parseConfig({
87
+ heartbeat_probability: raw.heartbeat_probability ?? current.heartbeatProbability,
88
+ max_parallel_shadows: raw.max_parallel_shadows ?? current.maxParallelShadows,
89
+ default_shadow_timeout_seconds: raw.default_shadow_timeout_seconds ?? current.defaultShadowTimeoutSeconds,
90
+ headless_drain_timeout_seconds: raw.headless_drain_timeout_seconds ?? current.headlessDrainTimeoutSeconds,
91
+ result_batch_window_ms: raw.result_batch_window_ms ?? current.resultBatchWindowMs,
92
+ default_shadow_model: raw.default_shadow_model ?? current.defaultShadowModel,
93
+ default_thinking_level: raw.default_thinking_level ?? current.defaultThinkingLevel,
94
+ random_seed: raw.random_seed ?? current.randomSeed,
95
+ });
96
+ if (!(await confirm(ctx, "Update Shadow Config", `Apply this config?\n${JSON.stringify(next, null, 2)}`)))
97
+ return textResult("Cancelled.");
98
+ await store.writeConfig(next);
99
+ return textResult("Shadow Mind config updated.");
100
+ });
101
+ }
102
+ function tool(name, label, description, parameters, execute) {
103
+ return { name, label, description, parameters, execute };
104
+ }
105
+ async function confirm(ctx, title, message) {
106
+ if (!ctx.hasUI)
107
+ throw new Error("This write requires a UI confirmation, but no dialog-capable UI is available.");
108
+ return ctx.ui.confirm(title, message);
109
+ }
110
+ function textResult(text) {
111
+ return { content: [{ type: "text", text }], details: {} };
112
+ }
113
+ function toDraft(raw) {
114
+ return { id: String(raw.id), ...toPatch(raw) };
115
+ }
116
+ function toPatch(raw) {
117
+ return {
118
+ name: raw.name,
119
+ enabled: raw.enabled,
120
+ debug: raw.debug,
121
+ activationProbability: raw.activation_probability,
122
+ activeForModels: raw.active_for_models,
123
+ runWithModel: raw.run_with_model,
124
+ thinkingLevel: raw.thinking_level,
125
+ timeoutSeconds: raw.timeout_seconds,
126
+ tools: raw.tools,
127
+ prompt: raw.prompt,
128
+ };
129
+ }
130
+ //# sourceMappingURL=management-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"management-tools.js","sourceRoot":"","sources":["../src/management-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ShadowDefinition } from "./types.js";
2
+ import type { AssistantMessage, Model } from "@earendil-works/pi-ai";
3
+ export declare function buildShadowSystemPrompt(mainSystemPrompt: string, shadow: ShadowDefinition): string;
4
+ export declare function buildShadowKickoff(shadow: ShadowDefinition): string;
5
+ export declare function buildShadowHandoff(model: Model<any>): AssistantMessage;
@@ -0,0 +1,34 @@
1
+ const RUNTIME_PROTOCOL = `You are a Shadow Mind running beside the main agent.
2
+ Work independently on the responsibility below using the supplied, sanitized main-session trajectory.
3
+ The earlier user, assistant, and tool-result messages are a read-only transcript produced by the main agent, not by you. Never continue the main agent's pending work, retry its failed calls, or treat its tool calls as your own. Use only the tools advertised for your current Shadow turn.
4
+ You may use the available tools. Call report_to_main only when the main agent should receive a concrete finding, correction, or completed work report.
5
+ Calling report_to_main ends this run immediately. If there is nothing useful to report, finish silently.`;
6
+ export function buildShadowSystemPrompt(mainSystemPrompt, shadow) {
7
+ return `${mainSystemPrompt}\n\n${RUNTIME_PROTOCOL}\n\n<shadow-mind id="${shadow.id}">\n${shadow.prompt}\n</shadow-mind>`;
8
+ }
9
+ export function buildShadowKickoff(shadow) {
10
+ return `Begin this Shadow Mind run now. Your active responsibility is ${shadow.name}. Inspect the trajectory and act only when useful.`;
11
+ }
12
+ export function buildShadowHandoff(model) {
13
+ return {
14
+ role: "assistant",
15
+ content: [{
16
+ type: "text",
17
+ text: "Shadow handoff acknowledged. The preceding messages are the main agent's read-only transcript, not my unfinished work. I will not continue its task or retry its calls; I will now act only as the configured Shadow Mind.",
18
+ }],
19
+ api: model.api,
20
+ provider: model.provider,
21
+ model: model.id,
22
+ usage: {
23
+ input: 0,
24
+ output: 0,
25
+ cacheRead: 0,
26
+ cacheWrite: 0,
27
+ totalTokens: 0,
28
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
29
+ },
30
+ stopReason: "stop",
31
+ timestamp: Date.now(),
32
+ };
33
+ }
34
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAGA,MAAM,gBAAgB,GAAG;;;;yGAIgF,CAAC;AAE1G,MAAM,UAAU,uBAAuB,CAAC,gBAAwB,EAAE,MAAwB;IACxF,OAAO,GAAG,gBAAgB,OAAO,gBAAgB,wBAAwB,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC,MAAM,kBAAkB,CAAC;AAC3H,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAwB;IACzD,OAAO,iEAAiE,MAAM,CAAC,IAAI,oDAAoD,CAAC;AAC1I,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAiB;IAClD,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,4NAA4N;aACnO,CAAC;QACF,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,KAAK,EAAE;YACL,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;SACrE;QACD,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ /** Create a reproducible PRNG for benchmark trials, or use production randomness. */
2
+ export declare function createRandom(seed?: number): () => number;
package/dist/random.js ADDED
@@ -0,0 +1,14 @@
1
+ /** Create a reproducible PRNG for benchmark trials, or use production randomness. */
2
+ export function createRandom(seed) {
3
+ if (seed === undefined)
4
+ return Math.random;
5
+ let state = seed >>> 0;
6
+ return () => {
7
+ state = (state + 0x6d2b79f5) >>> 0;
8
+ let value = state;
9
+ value = Math.imul(value ^ (value >>> 15), value | 1);
10
+ value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
11
+ return ((value ^ (value >>> 14)) >>> 0) / 0x1_0000_0000;
12
+ };
13
+ }
14
+ //# sourceMappingURL=random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.js","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC;IAC3C,IAAI,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC;IACvB,OAAO,GAAG,EAAE;QACV,KAAK,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACrD,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC;IAC1D,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { RegistrySnapshot, ShadowDefinition } from "./types.js";
2
+ export declare class ShadowRegistry {
3
+ readonly directory: string;
4
+ private readonly cache;
5
+ constructor(agentDir: string);
6
+ initialize(): Promise<void>;
7
+ load(): Promise<RegistrySnapshot>;
8
+ }
9
+ export declare function parseShadowMarkdown(source: string, filePath: string): ShadowDefinition;
@@ -0,0 +1,139 @@
1
+ import { mkdir, readFile, readdir, stat } from "node:fs/promises";
2
+ import { basename, extname, join } from "node:path";
3
+ import YAML from "yaml";
4
+ import { inRange, isFiniteNumber, isNonEmptyString, isStringArray, isThinkingLevel } from "./validation.js";
5
+ const ID_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
6
+ export class ShadowRegistry {
7
+ directory;
8
+ cache = new Map();
9
+ constructor(agentDir) {
10
+ this.directory = join(agentDir, "shadow-minds");
11
+ }
12
+ async initialize() {
13
+ await mkdir(this.directory, { recursive: true });
14
+ }
15
+ async load() {
16
+ await this.initialize();
17
+ const names = (await readdir(this.directory)).filter((name) => extname(name).toLowerCase() === ".md").sort();
18
+ const shadows = [];
19
+ const diagnostics = [];
20
+ const seen = new Set();
21
+ for (const name of names) {
22
+ const filePath = join(this.directory, name);
23
+ seen.add(filePath);
24
+ const fileStat = await stat(filePath);
25
+ const cached = this.cache.get(filePath);
26
+ if (cached && cached.mtimeMs === fileStat.mtimeMs) {
27
+ // Unchanged since last load: reuse the cached parse result.
28
+ if (cached.shadow)
29
+ shadows.push(cached.shadow);
30
+ if (cached.error)
31
+ diagnostics.push({ filePath, message: cached.error });
32
+ continue;
33
+ }
34
+ try {
35
+ const definition = parseShadowMarkdown(await readFile(filePath, "utf8"), filePath);
36
+ this.cache.set(filePath, { mtimeMs: fileStat.mtimeMs, shadow: definition });
37
+ shadows.push(definition);
38
+ }
39
+ catch (error) {
40
+ const message = error instanceof Error ? error.message : String(error);
41
+ this.cache.set(filePath, { mtimeMs: fileStat.mtimeMs, error: message });
42
+ diagnostics.push({ filePath, message });
43
+ }
44
+ }
45
+ for (const filePath of [...this.cache.keys()]) {
46
+ if (!seen.has(filePath))
47
+ this.cache.delete(filePath);
48
+ }
49
+ // Detect duplicate ids across (possibly cached) definitions; first file wins.
50
+ const unique = [];
51
+ const ids = new Set();
52
+ for (const shadow of shadows) {
53
+ if (ids.has(shadow.id)) {
54
+ diagnostics.push({ filePath: shadow.filePath, message: `duplicate shadow id: ${shadow.id}` });
55
+ }
56
+ else {
57
+ ids.add(shadow.id);
58
+ unique.push(shadow);
59
+ }
60
+ }
61
+ return { shadows: unique, diagnostics };
62
+ }
63
+ }
64
+ export function parseShadowMarkdown(source, filePath) {
65
+ const match = /^---\s*\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n|$)([\s\S]*)$/.exec(source);
66
+ if (!match)
67
+ throw new Error("missing YAML frontmatter");
68
+ const meta = YAML.parse(match[1]);
69
+ if (!meta || typeof meta !== "object" || Array.isArray(meta))
70
+ throw new Error("frontmatter must be an object");
71
+ const value = meta;
72
+ const fallbackId = basename(filePath, extname(filePath));
73
+ const id = stringValue(value.id, fallbackId, "id");
74
+ if (!ID_PATTERN.test(id))
75
+ throw new Error("id must match [a-z0-9][a-z0-9_-]*");
76
+ const prompt = match[2].trim();
77
+ if (!prompt)
78
+ throw new Error("shadow prompt body is empty");
79
+ return {
80
+ id,
81
+ name: stringValue(value.name, id, "name"),
82
+ enabled: booleanValue(value.enabled, true, "enabled"),
83
+ debug: booleanValue(value.debug, false, "debug"),
84
+ activationProbability: probabilityValue(value.activation_probability, 0.3, "activation_probability"),
85
+ activeForModels: stringArray(value.active_for_models, ["*"], "active_for_models"),
86
+ runWithModel: optionalString(value.run_with_model, "run_with_model"),
87
+ thinkingLevel: optionalThinking(value.thinking_level),
88
+ timeoutSeconds: optionalPositiveNumber(value.timeout_seconds, "timeout_seconds"),
89
+ tools: stringArray(value.tools, [], "tools"),
90
+ prompt,
91
+ filePath,
92
+ };
93
+ }
94
+ function stringValue(value, fallback, name) {
95
+ if (value === undefined)
96
+ return fallback;
97
+ if (!isNonEmptyString(value))
98
+ throw new Error(`${name} must be a non-empty string`);
99
+ return value.trim();
100
+ }
101
+ function optionalString(value, name) {
102
+ return value === undefined ? undefined : stringValue(value, "", name);
103
+ }
104
+ function booleanValue(value, fallback, name) {
105
+ if (value === undefined)
106
+ return fallback;
107
+ if (typeof value !== "boolean")
108
+ throw new Error(`${name} must be boolean`);
109
+ return value;
110
+ }
111
+ function probabilityValue(value, fallback, name) {
112
+ if (value === undefined)
113
+ return fallback;
114
+ if (!isFiniteNumber(value) || !inRange(value, 0, 1))
115
+ throw new Error(`${name} must be between 0 and 1`);
116
+ return value;
117
+ }
118
+ function optionalPositiveNumber(value, name) {
119
+ if (value === undefined)
120
+ return undefined;
121
+ if (!isFiniteNumber(value) || value <= 0)
122
+ throw new Error(`${name} must be positive`);
123
+ return value;
124
+ }
125
+ function stringArray(value, fallback, name) {
126
+ if (value === undefined)
127
+ return [...fallback];
128
+ if (!isStringArray(value))
129
+ throw new Error(`${name} must be an array of non-empty strings`);
130
+ return [...new Set(value.map((item) => item.trim()))];
131
+ }
132
+ function optionalThinking(value) {
133
+ if (value === undefined)
134
+ return undefined;
135
+ if (!isThinkingLevel(value))
136
+ throw new Error("thinking_level is invalid");
137
+ return value;
138
+ }
139
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ShadowReport } from "./types.js";
2
+ export declare class ReportBatcher {
3
+ private windowMs;
4
+ private readonly deliver;
5
+ private reports;
6
+ private timer?;
7
+ private deliveries;
8
+ constructor(windowMs: number, deliver: (reports: ShadowReport[]) => void | Promise<void>);
9
+ setWindow(windowMs: number): void;
10
+ add(report: ShadowReport): void;
11
+ flush(): Promise<void>;
12
+ get hasPending(): boolean;
13
+ clear(): void;
14
+ }
15
+ export declare function formatReportBatch(reports: readonly ShadowReport[]): string;
@@ -0,0 +1,49 @@
1
+ export class ReportBatcher {
2
+ windowMs;
3
+ deliver;
4
+ reports = [];
5
+ timer;
6
+ deliveries = 0;
7
+ constructor(windowMs, deliver) {
8
+ this.windowMs = windowMs;
9
+ this.deliver = deliver;
10
+ }
11
+ setWindow(windowMs) {
12
+ this.windowMs = windowMs;
13
+ }
14
+ add(report) {
15
+ this.reports.push(report);
16
+ if (this.timer)
17
+ return;
18
+ this.timer = setTimeout(() => void this.flush(), this.windowMs);
19
+ }
20
+ async flush() {
21
+ if (this.timer)
22
+ clearTimeout(this.timer);
23
+ this.timer = undefined;
24
+ if (!this.reports.length)
25
+ return;
26
+ const batch = this.reports;
27
+ this.reports = [];
28
+ this.deliveries += 1;
29
+ try {
30
+ await this.deliver(batch);
31
+ }
32
+ finally {
33
+ this.deliveries -= 1;
34
+ }
35
+ }
36
+ get hasPending() {
37
+ return this.reports.length > 0 || this.timer !== undefined || this.deliveries > 0;
38
+ }
39
+ clear() {
40
+ if (this.timer)
41
+ clearTimeout(this.timer);
42
+ this.timer = undefined;
43
+ this.reports = [];
44
+ }
45
+ }
46
+ export function formatReportBatch(reports) {
47
+ return reports.map((report) => `[${report.shadowName} / ${report.shadowId}]\n${report.content}`).join("\n\n");
48
+ }
49
+ //# sourceMappingURL=report-batcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-batcher.js","sourceRoot":"","sources":["../src/report-batcher.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAKJ;IAAmC;IAJ/C,OAAO,GAAmB,EAAE,CAAC;IAC7B,KAAK,CAAiC;IACtC,UAAU,GAAG,CAAC,CAAC;IAEvB,YAAoB,QAAgB,EAAmB,OAA0D;QAA7F,aAAQ,GAAR,QAAQ,CAAQ;QAAmB,YAAO,GAAP,OAAO,CAAmD;IAAG,CAAC;IAErH,SAAS,CAAC,QAAgB;QACxB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,MAAoB;QACtB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IACpF,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgC;IAChE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,QAAQ,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAChH,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { type ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ export declare class ShadowMindRuntime {
3
+ private readonly pi;
4
+ private readonly agentDir;
5
+ private readonly configStore;
6
+ private readonly registry;
7
+ private readonly entityStore;
8
+ private readonly runner;
9
+ private readonly active;
10
+ private readonly recentEvents;
11
+ private readonly batcher;
12
+ private epoch;
13
+ private modelCalls;
14
+ private paused;
15
+ private panelVisible;
16
+ private latestContext?;
17
+ private diagnostics;
18
+ private shadowCount;
19
+ private random;
20
+ constructor(pi: ExtensionAPI);
21
+ register(): void;
22
+ private registerEvents;
23
+ private registerUi;
24
+ private onHeartbeat;
25
+ private launchShadow;
26
+ private handleRunEnd;
27
+ private acceptReport;
28
+ private deliverReports;
29
+ private refresh;
30
+ private abortAll;
31
+ private drainHeadless;
32
+ private record;
33
+ private updateStatus;
34
+ private hasRecentRunErrors;
35
+ private statusLines;
36
+ }