@noopolis/daimon 0.1.1 → 0.1.2

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 (102) hide show
  1. package/README.md +54 -10
  2. package/dist/core/siblingBuildFreshness.d.ts +21 -0
  3. package/dist/core/siblingBuildFreshness.d.ts.map +1 -0
  4. package/dist/core/siblingBuildFreshness.js +25 -0
  5. package/dist/core/types.d.ts +10 -1
  6. package/dist/core/types.d.ts.map +1 -1
  7. package/dist/examples/exampleCausalId.d.ts +3 -0
  8. package/dist/examples/exampleCausalId.d.ts.map +1 -0
  9. package/dist/examples/exampleCausalId.js +8 -0
  10. package/dist/examples/jungian-play-org.js +3 -2
  11. package/dist/examples/jungian-triad-org.js +3 -2
  12. package/dist/examples/jungianPlayAgent.d.ts +1 -1
  13. package/dist/examples/jungianPlayAgent.d.ts.map +1 -1
  14. package/dist/examples/jungianPlayAgent.js +1 -1
  15. package/dist/examples/jungianProfiles.d.ts +1 -1
  16. package/dist/examples/jungianProfiles.d.ts.map +1 -1
  17. package/dist/examples/jungianTriadProfiles.d.ts +1 -1
  18. package/dist/examples/jungianTriadProfiles.d.ts.map +1 -1
  19. package/dist/examples/pi-agent.js +3 -2
  20. package/dist/examples/pi-memory-org.js +6 -5
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/mcp/toolServer.d.ts +14 -0
  25. package/dist/mcp/toolServer.d.ts.map +1 -0
  26. package/dist/mcp/toolServer.js +105 -0
  27. package/dist/observability/causalEvents.d.ts +118 -0
  28. package/dist/observability/causalEvents.d.ts.map +1 -0
  29. package/dist/observability/causalEvents.js +135 -0
  30. package/dist/observability/controlCausal.d.ts +117 -0
  31. package/dist/observability/controlCausal.d.ts.map +1 -0
  32. package/dist/observability/controlCausal.js +107 -0
  33. package/dist/observability/emitCausalFixture.d.ts +25 -0
  34. package/dist/observability/emitCausalFixture.d.ts.map +1 -0
  35. package/dist/observability/emitCausalFixture.js +98 -0
  36. package/dist/observability/index.d.ts +2 -0
  37. package/dist/observability/index.d.ts.map +1 -1
  38. package/dist/observability/index.js +2 -0
  39. package/dist/pi/cliSession.d.ts +46 -0
  40. package/dist/pi/cliSession.d.ts.map +1 -0
  41. package/dist/pi/cliSession.js +224 -0
  42. package/dist/pi/index.d.ts +5 -0
  43. package/dist/pi/index.d.ts.map +1 -1
  44. package/dist/pi/index.js +5 -0
  45. package/dist/pi/memoryTools.d.ts +55 -1
  46. package/dist/pi/memoryTools.d.ts.map +1 -1
  47. package/dist/pi/memoryTools.js +144 -24
  48. package/dist/pi/modelRegistry.d.ts +13 -0
  49. package/dist/pi/modelRegistry.d.ts.map +1 -0
  50. package/dist/pi/modelRegistry.js +19 -0
  51. package/dist/pi/piAgentHandle.d.ts +45 -0
  52. package/dist/pi/piAgentHandle.d.ts.map +1 -0
  53. package/dist/pi/piAgentHandle.js +324 -0
  54. package/dist/pi/piAgentWakeSupport.d.ts +68 -0
  55. package/dist/pi/piAgentWakeSupport.d.ts.map +1 -0
  56. package/dist/pi/piAgentWakeSupport.js +147 -0
  57. package/dist/pi/piHarness.d.ts +30 -4
  58. package/dist/pi/piHarness.d.ts.map +1 -1
  59. package/dist/pi/piHarness.js +97 -255
  60. package/dist/pi/prompts.d.ts +9 -0
  61. package/dist/pi/prompts.d.ts.map +1 -0
  62. package/dist/pi/prompts.js +39 -0
  63. package/dist/pi/rawTrainingCapture.d.ts +59 -0
  64. package/dist/pi/rawTrainingCapture.d.ts.map +1 -0
  65. package/dist/pi/rawTrainingCapture.js +175 -0
  66. package/dist/pi/turnCausal.d.ts +73 -0
  67. package/dist/pi/turnCausal.d.ts.map +1 -0
  68. package/dist/pi/turnCausal.js +75 -0
  69. package/dist/pi/turnTrace.d.ts +128 -0
  70. package/dist/pi/turnTrace.d.ts.map +1 -0
  71. package/dist/pi/turnTrace.js +141 -0
  72. package/dist/pi/wakeAcceptance.d.ts +49 -0
  73. package/dist/pi/wakeAcceptance.d.ts.map +1 -0
  74. package/dist/pi/wakeAcceptance.js +281 -0
  75. package/dist/pi/wakeAcceptanceFs.d.ts +44 -0
  76. package/dist/pi/wakeAcceptanceFs.d.ts.map +1 -0
  77. package/dist/pi/wakeAcceptanceFs.js +318 -0
  78. package/dist/pi/wakeAcceptanceSchema.d.ts +75 -0
  79. package/dist/pi/wakeAcceptanceSchema.d.ts.map +1 -0
  80. package/dist/pi/wakeAcceptanceSchema.js +265 -0
  81. package/dist/pi/wakeModes.d.ts +9 -0
  82. package/dist/pi/wakeModes.d.ts.map +1 -0
  83. package/dist/pi/wakeModes.js +19 -0
  84. package/dist/pi/worldNudge.d.ts +22 -0
  85. package/dist/pi/worldNudge.d.ts.map +1 -0
  86. package/dist/pi/worldNudge.js +62 -0
  87. package/dist/pi/worldToolProtocol.d.ts +13 -0
  88. package/dist/pi/worldToolProtocol.d.ts.map +1 -0
  89. package/dist/pi/worldToolProtocol.js +49 -0
  90. package/dist/pi/worldTools.d.ts +32 -0
  91. package/dist/pi/worldTools.d.ts.map +1 -0
  92. package/dist/pi/worldTools.js +373 -0
  93. package/dist/pi/worldTrajectory.d.ts +52 -0
  94. package/dist/pi/worldTrajectory.d.ts.map +1 -0
  95. package/dist/pi/worldTrajectory.js +131 -0
  96. package/package.json +10 -13
  97. package/dist/examples/mixed-engine-org.d.ts +0 -2
  98. package/dist/examples/mixed-engine-org.d.ts.map +0 -1
  99. package/dist/examples/mixed-engine-org.js +0 -351
  100. package/dist/examples/mixedEngineCli.d.ts +0 -15
  101. package/dist/examples/mixedEngineCli.d.ts.map +0 -1
  102. package/dist/examples/mixedEngineCli.js +0 -174
@@ -0,0 +1,46 @@
1
+ import type { ChildProcess } from "node:child_process";
2
+ import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
3
+ import type { PiSessionLike } from "./piAgentHandle.js";
4
+ import type { PiSessionFactoryInput } from "./piHarness.js";
5
+ export type CliEngineKind = "agy" | "codex" | "grok";
6
+ export type CliEngineOptions = {
7
+ readonly commandArgs?: readonly string[];
8
+ readonly command?: string;
9
+ readonly maxToolTurns: number;
10
+ readonly onToolsMounted?: (tools: readonly ToolDefinition[]) => void;
11
+ readonly timeoutMs: number;
12
+ readonly redactedEnvironmentNames?: readonly string[];
13
+ } & ({
14
+ readonly engine: "codex" | "grok";
15
+ } | {
16
+ /** AGY has no MCP client. Selecting this state explicitly permits tool-free participation. */
17
+ readonly engine: "agy";
18
+ readonly toolAccess: "none";
19
+ });
20
+ type SessionInput = {
21
+ readonly cwd: string;
22
+ readonly customTools?: ToolDefinition[];
23
+ readonly daimonSecretEnvironmentNames?: readonly string[];
24
+ };
25
+ export declare const readChild: (child: ChildProcess, timeoutMs: number, secretValues: readonly string[]) => Promise<string>;
26
+ export declare const renderCodexArgs: (options: Pick<CliEngineOptions, "commandArgs">, cwd: string, endpoint: string | undefined, sandbox?: string) => string[];
27
+ export declare const spawnEngine: (options: CliEngineOptions, prompt: string, input: SessionInput, endpoint: string | undefined) => ChildProcess;
28
+ export declare const createCliSessionFactory: (options: CliEngineOptions) => (input: PiSessionFactoryInput) => Promise<{
29
+ session: PiSessionLike;
30
+ }>;
31
+ export interface EngineRunResult {
32
+ readonly durationMs: number;
33
+ readonly outputChars: number;
34
+ readonly promptChars: number;
35
+ readonly text: string;
36
+ }
37
+ export declare const runEngineDetailed: (engine: CliEngineKind, prompt: string, paths: {
38
+ readonly workspacePath: string;
39
+ readonly runtimeHomePath?: string;
40
+ }) => Promise<EngineRunResult>;
41
+ export declare const runEngine: (engine: CliEngineKind, prompt: string, paths: {
42
+ readonly workspacePath: string;
43
+ readonly runtimeHomePath?: string;
44
+ }) => Promise<string>;
45
+ export {};
46
+ //# sourceMappingURL=cliSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliSession.d.ts","sourceRoot":"","sources":["../../src/pi/cliSession.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG5D,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAErD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,KAAK,IAAI,CAAC;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,wBAAwB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvD,GAAG,CAAC;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CACnC,GAAG;IACF,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC,CAAC;AAEH,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IACxC,QAAQ,CAAC,4BAA4B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3D,CAAC;AAgCF,eAAO,MAAM,SAAS,GAAI,OAAO,YAAY,EAAE,WAAW,MAAM,EAAE,cAAc,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAyBhH,CAAC;AAiDH,eAAO,MAAM,eAAe,GAC1B,SAAS,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,EAC9C,KAAK,MAAM,EACX,UAAU,MAAM,GAAG,SAAS,EAC5B,UAAS,MAAiE,KACzE,MAAM,EACyC,CAAC;AAEnD,eAAO,MAAM,WAAW,GACtB,SAAS,gBAAgB,EACzB,QAAQ,MAAM,EACd,OAAO,YAAY,EACnB,UAAU,MAAM,GAAG,SAAS,KAC3B,YA2BF,CAAC;AAsEF,eAAO,MAAM,uBAAuB,GAAI,SAAS,gBAAgB,MAC/D,OAAO,qBAAqB,KAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,CASpC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,aAAa,EACrB,QAAQ,MAAM,EACd,OAAO;IAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,KAC3E,OAAO,CAAC,eAAe,CAkBzB,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,QAAQ,aAAa,EACrB,QAAQ,MAAM,EACd,OAAO;IAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,KAC3E,OAAO,CAAC,MAAM,CAA0D,CAAC"}
@@ -0,0 +1,224 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { createServer } from "node:http";
3
+ import { spawn } from "node:child_process";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import { createPiToolMcpServer } from "../mcp/toolServer.js";
6
+ import { redactTraceText } from "./turnTrace.js";
7
+ const childEnvironment = (redactedNames) => {
8
+ const redacted = new Set(redactedNames);
9
+ return Object.fromEntries(Object.entries(process.env).filter(([name]) => !redacted.has(name)));
10
+ };
11
+ const childSecretValues = (redactedNames) => redactedNames
12
+ .map((name) => process.env[name])
13
+ .filter((value) => typeof value === "string" && value.length > 0);
14
+ const redactChildOutput = (value, secretValues) => {
15
+ let redacted = redactTraceText(value);
16
+ for (const secret of secretValues)
17
+ redacted = redacted.split(secret).join("[REDACTED]");
18
+ return redacted;
19
+ };
20
+ const childDiagnostic = (stdout, stderr, secretValues) => {
21
+ const output = stderr.trim().length > 0 ? stderr : stdout;
22
+ const redacted = redactChildOutput(output, secretValues).trim();
23
+ return redacted.length > 0 ? `: ${redacted}` : "";
24
+ };
25
+ const terminate = (child) => {
26
+ if (!child.killed)
27
+ child.kill("SIGTERM");
28
+ };
29
+ export const readChild = (child, timeoutMs, secretValues) => new Promise((resolve, reject) => {
30
+ const stdout = [];
31
+ const stderr = [];
32
+ child.stdout?.on("data", (chunk) => stdout.push(chunk));
33
+ child.stderr?.on("data", (chunk) => stderr.push(chunk));
34
+ const timer = setTimeout(() => {
35
+ terminate(child);
36
+ reject(new Error("CLI engine timed out"));
37
+ }, timeoutMs);
38
+ child.once("error", (error) => {
39
+ clearTimeout(timer);
40
+ reject(error);
41
+ });
42
+ child.once("close", (code, signal) => {
43
+ clearTimeout(timer);
44
+ if (code === 0) {
45
+ resolve(Buffer.concat(stdout).toString("utf8").trim());
46
+ }
47
+ else {
48
+ reject(new Error(`CLI engine exited ${code ?? signal}${childDiagnostic(Buffer.concat(stdout).toString("utf8"), Buffer.concat(stderr).toString("utf8"), secretValues)}`));
49
+ }
50
+ });
51
+ });
52
+ const startMcp = async (tools, maxToolTurns, wakeDeadline, onToolsMounted) => {
53
+ onToolsMounted?.(tools);
54
+ const mcpServer = createPiToolMcpServer(tools, { maxToolTurns, wakeDeadline });
55
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID() });
56
+ await mcpServer.connect(transport);
57
+ const httpServer = createServer((request, response) => {
58
+ void transport.handleRequest(request, response);
59
+ });
60
+ try {
61
+ await new Promise((resolve, reject) => {
62
+ httpServer.once("error", reject);
63
+ httpServer.listen(0, "127.0.0.1", () => resolve());
64
+ });
65
+ }
66
+ catch (error) {
67
+ await transport.close().catch(() => undefined);
68
+ await mcpServer.close().catch(() => undefined);
69
+ throw error;
70
+ }
71
+ const address = httpServer.address();
72
+ if (address === null || typeof address === "string") {
73
+ await new Promise((resolve) => httpServer.close(() => resolve()));
74
+ await transport.close();
75
+ await mcpServer.close();
76
+ throw new Error("MCP server did not receive an ephemeral port");
77
+ }
78
+ const close = async () => {
79
+ await transport.close().catch(() => undefined);
80
+ await mcpServer.close().catch(() => undefined);
81
+ await new Promise((resolve) => httpServer.close(() => resolve()));
82
+ };
83
+ return { endpoint: `http://127.0.0.1:${address.port}/mcp`, close };
84
+ };
85
+ const addGrokServer = async (endpoint, cwd, env, command, commandArgs, secretValues) => {
86
+ const child = spawn(command, [...commandArgs, "mcp", "add", "--transport", "http", "--scope", "project", "daimon", endpoint], {
87
+ cwd,
88
+ env,
89
+ stdio: ["ignore", "pipe", "pipe"]
90
+ });
91
+ await readChild(child, 30_000, secretValues);
92
+ };
93
+ export const renderCodexArgs = (options, cwd, endpoint, sandbox = process.env.DAIMON_CODEX_SANDBOX ?? "danger-full-access") => [...(options.commandArgs ?? []), "exec", "--sandbox", sandbox, "--skip-git-repo-check", "--color", "never", "-C", cwd,
94
+ "-c", `mcp_servers.daimon.url=${endpoint}`, "-"];
95
+ export const spawnEngine = (options, prompt, input, endpoint) => {
96
+ const command = options.command ?? options.engine;
97
+ const env = childEnvironment([
98
+ ...(options.redactedEnvironmentNames ?? []),
99
+ ...(input.daimonSecretEnvironmentNames ?? [])
100
+ ]);
101
+ if (options.engine === "codex") {
102
+ const args = renderCodexArgs(options, input.cwd, endpoint);
103
+ const child = spawn(command, args, { cwd: input.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
104
+ child.stdin.on("error", () => undefined);
105
+ child.stdin.write(prompt);
106
+ child.stdin.end();
107
+ return child;
108
+ }
109
+ if (options.engine === "grok") {
110
+ return spawn(command, [...(options.commandArgs ?? []), "--single", prompt, "--max-turns", String(options.maxToolTurns), "--no-memory",
111
+ "--disable-web-search", "--cwd", input.cwd, "--output-format", "plain"], {
112
+ cwd: input.cwd,
113
+ env,
114
+ stdio: ["ignore", "pipe", "pipe"]
115
+ });
116
+ }
117
+ return spawn(command, [...(options.commandArgs ?? []), "--print", prompt, "--print-timeout", `${options.timeoutMs}ms`], {
118
+ cwd: input.cwd,
119
+ env,
120
+ stdio: ["ignore", "pipe", "pipe"]
121
+ });
122
+ };
123
+ class CliSession {
124
+ options;
125
+ input;
126
+ listeners = new Set();
127
+ disposed = false;
128
+ constructor(options, input) {
129
+ this.options = options;
130
+ this.input = input;
131
+ }
132
+ subscribe(listener) {
133
+ this.listeners.add(listener);
134
+ return () => this.listeners.delete(listener);
135
+ }
136
+ async prompt(text) {
137
+ if (this.disposed)
138
+ throw new Error("CLI session is disposed");
139
+ const deadline = Date.now() + this.options.timeoutMs;
140
+ const secretValues = childSecretValues([
141
+ ...(this.options.redactedEnvironmentNames ?? []),
142
+ ...(this.input.daimonSecretEnvironmentNames ?? [])
143
+ ]);
144
+ const needsMcp = this.options.engine !== "agy";
145
+ const mount = needsMcp
146
+ ? await startMcp(this.input.customTools ?? [], this.options.maxToolTurns, deadline, this.options.onToolsMounted)
147
+ : undefined;
148
+ let child;
149
+ try {
150
+ if (this.options.engine === "grok" && mount !== undefined) {
151
+ await addGrokServer(mount.endpoint, this.input.cwd, childEnvironment([
152
+ ...(this.options.redactedEnvironmentNames ?? []),
153
+ ...(this.input.daimonSecretEnvironmentNames ?? [])
154
+ ]), this.options.command ?? "grok", this.options.commandArgs ?? [], secretValues);
155
+ }
156
+ child = spawnEngine(this.options, text, this.input, mount?.endpoint);
157
+ const output = await readChild(child, Math.max(1, deadline - Date.now()), secretValues);
158
+ for (const listener of this.listeners)
159
+ listener({
160
+ type: "turn_end",
161
+ message: {
162
+ role: "assistant",
163
+ content: [{ type: "text", text: output }],
164
+ api: "openai-completions",
165
+ provider: "openai",
166
+ model: "cli",
167
+ usage: {
168
+ input: 0,
169
+ output: 0,
170
+ cacheRead: 0,
171
+ cacheWrite: 0,
172
+ totalTokens: 0,
173
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
174
+ },
175
+ stopReason: "stop",
176
+ timestamp: Date.now()
177
+ },
178
+ toolResults: []
179
+ });
180
+ }
181
+ finally {
182
+ if (child !== undefined)
183
+ terminate(child);
184
+ await mount?.close();
185
+ }
186
+ }
187
+ dispose() {
188
+ this.disposed = true;
189
+ this.listeners.clear();
190
+ }
191
+ }
192
+ export const createCliSessionFactory = (options) => async (input) => {
193
+ if (input.cwd === undefined)
194
+ throw new Error("CLI session cwd is required");
195
+ return {
196
+ session: new CliSession(options, {
197
+ cwd: input.cwd,
198
+ customTools: input.customTools,
199
+ daimonSecretEnvironmentNames: input.daimonSecretEnvironmentNames
200
+ })
201
+ };
202
+ };
203
+ export const runEngineDetailed = async (engine, prompt, paths) => {
204
+ const startedAt = Date.now();
205
+ const options = engine === "agy"
206
+ ? { engine, maxToolTurns: 1, timeoutMs: 180_000, toolAccess: "none" }
207
+ : { engine, maxToolTurns: 2, timeoutMs: 180_000 };
208
+ const session = new CliSession(options, { cwd: paths.workspacePath });
209
+ let text = "";
210
+ const unsubscribe = session.subscribe((event) => {
211
+ if (event.type !== "turn_end")
212
+ return;
213
+ if (!("content" in event.message))
214
+ return;
215
+ text = Array.isArray(event.message.content)
216
+ ? event.message.content.filter((entry) => entry.type === "text").map((entry) => entry.text).join("")
217
+ : event.message.content;
218
+ });
219
+ await session.prompt(prompt);
220
+ unsubscribe();
221
+ session.dispose();
222
+ return { durationMs: Date.now() - startedAt, outputChars: text.length, promptChars: prompt.length, text };
223
+ };
224
+ export const runEngine = async (engine, prompt, paths) => (await runEngineDetailed(engine, prompt, paths)).text;
@@ -1,4 +1,9 @@
1
1
  export * from "./auth.js";
2
+ export * from "./cliSession.js";
2
3
  export * from "./modelConfig.js";
4
+ export * from "./piAgentHandle.js";
3
5
  export * from "./piHarness.js";
6
+ export * from "./rawTrainingCapture.js";
7
+ export * from "./turnCausal.js";
8
+ export * from "./worldTools.js";
4
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pi/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pi/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
package/dist/pi/index.js CHANGED
@@ -1,3 +1,8 @@
1
1
  export * from "./auth.js";
2
+ export * from "./cliSession.js";
2
3
  export * from "./modelConfig.js";
4
+ export * from "./piAgentHandle.js";
3
5
  export * from "./piHarness.js";
6
+ export * from "./rawTrainingCapture.js";
7
+ export * from "./turnCausal.js";
8
+ export * from "./worldTools.js";
@@ -1,14 +1,68 @@
1
+ import { Type } from "@earendil-works/pi-ai";
1
2
  import { type ToolDefinition } from "@earendil-works/pi-coding-agent";
2
- import type { MemoryRuntime, MemoryToolExecutionContext } from "@noopolis/mneme";
3
+ import type { MemoryPrepareTurnResult, MemoryRuntime, MemoryToolExecutionContext, MemoryWakeMode } from "@noopolis/mneme";
3
4
  export interface PiMemoryToolContextRef {
4
5
  current?: MemoryToolExecutionContext;
6
+ observeTool?: (event: PiMemoryToolTraceEvent) => void;
7
+ }
8
+ export interface PiMemoryToolTraceEvent {
9
+ contentCount?: number;
10
+ decision?: string;
11
+ durationMs: number;
12
+ error?: string;
13
+ kind: "memory";
14
+ name: string;
15
+ redactionCount?: number;
16
+ status: "completed" | "failed";
5
17
  }
6
18
  interface PiMemoryToolInput {
7
19
  agentId: string;
8
20
  memory: MemoryRuntime;
9
21
  contextRef: PiMemoryToolContextRef;
22
+ mode?: MemoryWakeMode;
10
23
  }
11
24
  type PiMemoryTool = ToolDefinition<any, unknown>;
25
+ export declare const createTrustedPiMemoryToolContext: (input: {
26
+ agentId: string;
27
+ memory: MemoryRuntime;
28
+ mode: MemoryWakeMode;
29
+ prepared: MemoryPrepareTurnResult;
30
+ threadId: string;
31
+ wakeId: string;
32
+ }) => MemoryToolExecutionContext;
33
+ export declare function canonicalToolFieldNames(name: string, representation?: unknown): string[];
34
+ export declare const MEMORY_TOOL_ARGUMENT_FIELDS: Readonly<Record<string, ReadonlySet<string>>>;
35
+ export declare const schemaFor: (name: string) => Type.TObject<{
36
+ scope: Type.TString;
37
+ query: Type.TString;
38
+ limit: Type.TOptional<Type.TNumber>;
39
+ }> | Type.TObject<{
40
+ query: Type.TString;
41
+ limit: Type.TOptional<Type.TNumber>;
42
+ active_scope: Type.TOptional<Type.TString>;
43
+ }> | Type.TObject<{
44
+ scope: Type.TString;
45
+ kind: Type.TString;
46
+ content: Type.TObject<{
47
+ kind: Type.TString;
48
+ }>;
49
+ visibility: Type.TString;
50
+ sensitivity: Type.TString;
51
+ source_type: Type.TString;
52
+ confidence: Type.TOptional<Type.TNumber>;
53
+ memory_id: Type.TOptional<Type.TString>;
54
+ }> | Type.TObject<{
55
+ scope: Type.TString;
56
+ horizon: Type.TOptional<Type.TNumber>;
57
+ }> | Type.TObject<{
58
+ scope: Type.TString;
59
+ memory_id: Type.TString;
60
+ reason: Type.TOptional<Type.TString>;
61
+ }> | Type.TObject<{
62
+ scope: Type.TString;
63
+ event_ids: Type.TArray<Type.TString>;
64
+ reason: Type.TOptional<Type.TString>;
65
+ }>;
12
66
  export declare const createPiMemoryTools: (input: PiMemoryToolInput) => PiMemoryTool[];
13
67
  export declare const piMemoryToolNames: (tools: PiMemoryTool[]) => string[];
14
68
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"memoryTools.d.ts","sourceRoot":"","sources":["../../src/pi/memoryTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGlF,OAAO,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAoB,MAAM,iBAAiB,CAAC;AAEnG,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,0BAA0B,CAAC;CACtC;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,sBAAsB,CAAC;CACpC;AAED,KAAK,YAAY,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AA4DjD,eAAO,MAAM,mBAAmB,GAAI,OAAO,iBAAiB,KAAG,YAAY,EAiBxE,CAAC;AAEJ,eAAO,MAAM,iBAAiB,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAChC,CAAC"}
1
+ {"version":3,"file":"memoryTools.d.ts","sourceRoot":"","sources":["../../src/pi/memoryTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAQlF,OAAO,KAAK,EAEV,uBAAuB,EACvB,aAAa,EACb,0BAA0B,EAE1B,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;CAChC;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,sBAAsB,CAAC;IACnC,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,KAAK,YAAY,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAyCjD,eAAO,MAAM,gCAAgC,GAAI,OAAO;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,KAAG,0BAqBH,CAAC;AAqBF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAaxF;AAED,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAInF,CAAC;AAqBJ,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDrC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,OAAO,iBAAiB,KAAG,YAAY,EAuCxE,CAAC;AAEJ,eAAO,MAAM,iBAAiB,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAChC,CAAC"}
@@ -1,35 +1,122 @@
1
1
  import { Type } from "@earendil-works/pi-ai";
2
2
  import { defineTool } from "@earendil-works/pi-coding-agent";
3
- import { createMemoryToolDescriptors } from "@noopolis/mneme";
4
- const fallbackContext = (agentId) => ({
5
- wakeId: "manual",
6
- threadId: "manual",
7
- principal: { agentId, scope: "global" },
8
- conversationScope: "global",
9
- audienceKey: agentId,
10
- transport: "in_process"
11
- });
3
+ import { canonicalScopeKey, createMemoryToolDescriptors, memoryScopeId, schemaForModelToolName } from "@noopolis/mneme";
4
+ const MAX_ALLOWED_SCOPES = 32;
5
+ const MEMORY_PRINCIPAL_SCOPES = new Set([
6
+ "artifact",
7
+ "global",
8
+ "pair",
9
+ "role",
10
+ "room",
11
+ "task",
12
+ "team"
13
+ ]);
14
+ const trustedAllowedScopes = (agentId, prepared) => {
15
+ if (!Array.isArray(prepared.allowedScopes)
16
+ || prepared.allowedScopes.length === 0
17
+ || prepared.allowedScopes.length > MAX_ALLOWED_SCOPES) {
18
+ throw new Error("prepared memory turn requires a bounded finite scope set");
19
+ }
20
+ const scopes = prepared.allowedScopes.map((scope) => {
21
+ if (typeof scope !== "string" || scope !== canonicalScopeKey(scope)
22
+ || scope.length > 512 || /[\u0000-\u001f\u007f]/u.test(scope)) {
23
+ throw new Error("prepared memory turn contains an invalid scope");
24
+ }
25
+ return scope;
26
+ });
27
+ const agentPrefix = canonicalScopeKey(`agent:${agentId}/scope:`);
28
+ if (new Set(scopes).size !== scopes.length || scopes.some((scope) => !scope.startsWith(agentPrefix))) {
29
+ throw new Error("prepared memory turn contains a foreign or duplicate scope");
30
+ }
31
+ const activeScope = canonicalScopeKey(memoryScopeId(prepared.principal));
32
+ if (!scopes.includes(activeScope)) {
33
+ throw new Error("prepared memory turn omits its active principal scope");
34
+ }
35
+ return Object.freeze([...scopes]);
36
+ };
37
+ export const createTrustedPiMemoryToolContext = (input) => {
38
+ if (input.prepared.principal.agentId !== input.agentId
39
+ || input.memory.authority.bankId !== input.agentId) {
40
+ throw new Error("prepared memory authority does not match the Pi agent");
41
+ }
42
+ if (!MEMORY_PRINCIPAL_SCOPES.has(input.prepared.principal.scope)) {
43
+ throw new Error("prepared memory turn contains an invalid principal scope");
44
+ }
45
+ const principal = Object.freeze({ ...input.prepared.principal });
46
+ const activeScope = canonicalScopeKey(memoryScopeId(principal));
47
+ return Object.freeze({
48
+ allowedScopes: trustedAllowedScopes(input.agentId, input.prepared),
49
+ audienceKey: activeScope,
50
+ authority: input.memory.authority,
51
+ conversationScope: activeScope,
52
+ mode: input.mode,
53
+ principal,
54
+ threadId: input.threadId,
55
+ transport: "in_process",
56
+ wakeId: input.wakeId
57
+ });
58
+ };
59
+ const requireTrustedContext = (agentId, contextRef) => {
60
+ const context = contextRef.current;
61
+ if (context === undefined
62
+ || context.principal.agentId !== agentId
63
+ || context.authority?.bankId !== agentId
64
+ || !Array.isArray(context.allowedScopes)) {
65
+ throw new Error("Pi memory tool requires the active trusted turn context");
66
+ }
67
+ return context;
68
+ };
12
69
  const textContent = (result) => ({
13
70
  content: [{ type: "text", text: JSON.stringify(result) }],
14
71
  details: result
15
72
  });
73
+ export function canonicalToolFieldNames(name, representation) {
74
+ const source = arguments.length >= 2 ? representation : schemaForModelToolName(name);
75
+ if (source !== null && typeof source === "object") {
76
+ const candidate = source;
77
+ const fields = candidate.shape !== undefined ? candidate.shape : source;
78
+ if (fields !== null && typeof fields === "object" && !Array.isArray(fields)) {
79
+ const names = Object.keys(fields);
80
+ if (names.length > 0) {
81
+ return names;
82
+ }
83
+ }
84
+ }
85
+ throw new Error(`@noopolis/mneme returned no usable field contract for memory tool ${name}`);
86
+ }
87
+ export const MEMORY_TOOL_ARGUMENT_FIELDS = Object.fromEntries(createMemoryToolDescriptors({}, { mode: "dream" })
88
+ .map(({ modelName }) => [modelName, new Set(canonicalToolFieldNames(modelName))]));
89
+ const requireExactModelArguments = (toolName, params) => {
90
+ if (typeof params !== "object" || params === null || Array.isArray(params)) {
91
+ throw new Error("Pi memory tool arguments must be an object");
92
+ }
93
+ const allowed = MEMORY_TOOL_ARGUMENT_FIELDS[toolName];
94
+ if (allowed === undefined) {
95
+ throw new Error(`Pi memory tool ${toolName} has no argument contract`);
96
+ }
97
+ for (const field of Reflect.ownKeys(params)) {
98
+ if (typeof field !== "string" || !allowed.has(field)) {
99
+ throw new Error(`Pi memory tool ${toolName} received unexpected top-level argument ${String(field)}`);
100
+ }
101
+ }
102
+ };
16
103
  const contentSchema = Type.Object({
17
104
  kind: Type.String({ description: "Memory content kind: text, claim, decision, artifact, or relationship." })
18
105
  }, { additionalProperties: true });
19
- const schemaFor = (name) => {
106
+ export const schemaFor = (name) => {
20
107
  if (name === "memory_search") {
21
108
  return Type.Object({
22
109
  scope: Type.String({ description: "Scope alias or canonical scope id. Use current, global, or all when appropriate." }),
23
110
  query: Type.String({ description: "Search query." }),
24
111
  limit: Type.Optional(Type.Number({ description: "Maximum result count." }))
25
- });
112
+ }, { additionalProperties: false });
26
113
  }
27
114
  if (name === "memory_locate") {
28
115
  return Type.Object({
29
116
  query: Type.String({ description: "What to locate in memory." }),
30
117
  limit: Type.Optional(Type.Number({ description: "Maximum candidate count." })),
31
118
  active_scope: Type.Optional(Type.String({ description: "Optional active scope hint." }))
32
- });
119
+ }, { additionalProperties: false });
33
120
  }
34
121
  if (name === "memory_register") {
35
122
  return Type.Object({
@@ -38,24 +125,34 @@ const schemaFor = (name) => {
38
125
  content: contentSchema,
39
126
  visibility: Type.String({ description: "private, pair, team, room, global, public, or sealed." }),
40
127
  sensitivity: Type.String({ description: "normal, sensitive, or secret." }),
41
- evidence_event_ids: Type.Array(Type.String(), { description: "Event ids that justify the memory." }),
42
128
  source_type: Type.String({ description: "Source label for the registered memory." }),
43
- confidence: Type.Optional(Type.Number({ description: "Confidence from 0 to 1." }))
44
- });
129
+ confidence: Type.Optional(Type.Number({ description: "Confidence from 0 to 1." })),
130
+ memory_id: Type.Optional(Type.String({ description: "Existing memory chain id for a new revision." }))
131
+ }, { additionalProperties: false });
45
132
  }
46
133
  if (name === "memory_summarize") {
47
134
  return Type.Object({
48
135
  scope: Type.String({ description: "Scope alias or canonical scope id to summarize." }),
49
136
  horizon: Type.Optional(Type.Number({ description: "Approximate number of recent memories to include." }))
50
- });
137
+ }, { additionalProperties: false });
51
138
  }
52
- return Type.Object({
53
- scope: Type.String({ description: "Scope alias or canonical scope id for the tombstone." }),
54
- event_ids: Type.Array(Type.String(), { description: "Memory event ids to tombstone." }),
55
- reason: Type.Optional(Type.String({ description: "Why these memories should be forgotten." }))
56
- });
139
+ if (name === "memory_promote") {
140
+ return Type.Object({
141
+ scope: Type.String({ description: "Scope alias or canonical scope id the memory belongs to." }),
142
+ memory_id: Type.String({ description: "Current memory chain head to promote." }),
143
+ reason: Type.Optional(Type.String({ description: "Why this memory is being promoted." }))
144
+ }, { additionalProperties: false });
145
+ }
146
+ if (name === "memory_forget") {
147
+ return Type.Object({
148
+ scope: Type.String({ description: "Scope alias or canonical scope id for the tombstone." }),
149
+ event_ids: Type.Array(Type.String(), { description: "Memory event ids to tombstone." }),
150
+ reason: Type.Optional(Type.String({ description: "Why these memories should be forgotten." }))
151
+ }, { additionalProperties: false });
152
+ }
153
+ throw new Error(`Unknown Pi memory tool: ${name}`);
57
154
  };
58
- export const createPiMemoryTools = (input) => createMemoryToolDescriptors(input.memory.kernel).map((descriptor) => defineTool({
155
+ export const createPiMemoryTools = (input) => createMemoryToolDescriptors(input.memory.kernel, { mode: input.mode ?? "awake" }).map((descriptor) => defineTool({
59
156
  name: descriptor.modelName,
60
157
  label: descriptor.label,
61
158
  description: descriptor.description,
@@ -63,8 +160,31 @@ export const createPiMemoryTools = (input) => createMemoryToolDescriptors(input.
63
160
  promptGuidelines: descriptor.promptGuidelines,
64
161
  parameters: schemaFor(descriptor.modelName),
65
162
  async execute(_toolCallId, params) {
66
- const result = await descriptor.invoke(params, input.contextRef.current ?? fallbackContext(input.agentId));
67
- return textContent(result);
163
+ const startedAt = Date.now();
164
+ try {
165
+ requireExactModelArguments(descriptor.modelName, params);
166
+ const result = await descriptor.invoke(params, requireTrustedContext(input.agentId, input.contextRef));
167
+ input.contextRef.observeTool?.({
168
+ contentCount: result.content.length,
169
+ decision: result.decision,
170
+ durationMs: Date.now() - startedAt,
171
+ kind: "memory",
172
+ name: descriptor.modelName,
173
+ redactionCount: result.content.reduce((total, content) => total + content.redactions.length, 0),
174
+ status: "completed"
175
+ });
176
+ return textContent(result);
177
+ }
178
+ catch (error) {
179
+ input.contextRef.observeTool?.({
180
+ durationMs: Date.now() - startedAt,
181
+ error: error instanceof Error ? error.message : String(error),
182
+ kind: "memory",
183
+ name: descriptor.modelName,
184
+ status: "failed"
185
+ });
186
+ throw error;
187
+ }
68
188
  }
69
189
  }));
70
190
  export const piMemoryToolNames = (tools) => tools.map((tool) => tool.name);
@@ -0,0 +1,13 @@
1
+ import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
2
+ import type { HarnessModelSpec } from "../core/types.js";
3
+ export interface PiModelRegistryOptions {
4
+ model?: {
5
+ auth?: HarnessModelSpec["auth"];
6
+ endpoint?: HarnessModelSpec["endpoint"];
7
+ provider: string;
8
+ name: string;
9
+ };
10
+ modelsPath?: string;
11
+ }
12
+ export declare const createPiModelRegistry: (authStorage: AuthStorage, options: PiModelRegistryOptions) => ModelRegistry;
13
+ //# sourceMappingURL=modelRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelRegistry.d.ts","sourceRoot":"","sources":["../../src/pi/modelRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,aAAa,EACd,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAIzD,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACxC,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,qBAAqB,GAChC,aAAa,WAAW,EACxB,SAAS,sBAAsB,KAC9B,aAkBF,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { ModelRegistry } from "@earendil-works/pi-coding-agent";
2
+ import { resolvePiHarnessModel } from "./modelConfig.js";
3
+ export const createPiModelRegistry = (authStorage, options) => {
4
+ const registry = options.modelsPath
5
+ ? ModelRegistry.create(authStorage, options.modelsPath)
6
+ : ModelRegistry.inMemory(authStorage);
7
+ if (!options.modelsPath && options.model?.endpoint) {
8
+ const { modelsConfig } = resolvePiHarnessModel(options.model);
9
+ for (const [provider, config] of Object.entries(modelsConfig.providers)) {
10
+ registry.registerProvider(provider, {
11
+ api: config.api,
12
+ apiKey: config.apiKey,
13
+ baseUrl: config.baseUrl,
14
+ models: config.models
15
+ });
16
+ }
17
+ }
18
+ return registry;
19
+ };