@noopolis/daimon 0.1.0 → 0.1.1
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 +92 -0
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/examples/jungian-play-org.d.ts +2 -0
- package/dist/examples/jungian-play-org.d.ts.map +1 -0
- package/dist/examples/jungian-play-org.js +280 -0
- package/dist/examples/jungian-triad-org.d.ts +2 -0
- package/dist/examples/jungian-triad-org.d.ts.map +1 -0
- package/dist/examples/jungian-triad-org.js +280 -0
- package/dist/examples/jungianConversationPlan.d.ts +10 -0
- package/dist/examples/jungianConversationPlan.d.ts.map +1 -0
- package/dist/examples/jungianConversationPlan.js +64 -0
- package/dist/examples/jungianPiRepresentative.d.ts +36 -0
- package/dist/examples/jungianPiRepresentative.d.ts.map +1 -0
- package/dist/examples/jungianPiRepresentative.js +81 -0
- package/dist/examples/jungianPlayAgent.d.ts +36 -0
- package/dist/examples/jungianPlayAgent.d.ts.map +1 -0
- package/dist/examples/jungianPlayAgent.js +111 -0
- package/dist/examples/jungianProfiles.d.ts +34 -0
- package/dist/examples/jungianProfiles.d.ts.map +1 -0
- package/dist/examples/jungianProfiles.js +190 -0
- package/dist/examples/jungianTrace.d.ts +47 -0
- package/dist/examples/jungianTrace.d.ts.map +1 -0
- package/dist/examples/jungianTrace.js +101 -0
- package/dist/examples/jungianTriadProfiles.d.ts +35 -0
- package/dist/examples/jungianTriadProfiles.d.ts.map +1 -0
- package/dist/examples/jungianTriadProfiles.js +81 -0
- package/dist/examples/mixed-engine-org.d.ts +2 -0
- package/dist/examples/mixed-engine-org.d.ts.map +1 -0
- package/dist/examples/mixed-engine-org.js +351 -0
- package/dist/examples/mixedEngineCli.d.ts +15 -0
- package/dist/examples/mixedEngineCli.d.ts.map +1 -0
- package/dist/examples/mixedEngineCli.js +174 -0
- package/dist/examples/pi-memory-org.d.ts +2 -0
- package/dist/examples/pi-memory-org.d.ts.map +1 -0
- package/dist/examples/pi-memory-org.js +230 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/observability/index.d.ts +2 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +1 -0
- package/dist/observability/orgObserver.d.ts +98 -0
- package/dist/observability/orgObserver.d.ts.map +1 -0
- package/dist/observability/orgObserver.js +181 -0
- package/dist/pi/index.d.ts +4 -0
- package/dist/pi/index.d.ts.map +1 -0
- package/dist/pi/index.js +3 -0
- package/dist/pi/memoryTools.d.ts +15 -0
- package/dist/pi/memoryTools.d.ts.map +1 -0
- package/dist/pi/memoryTools.js +70 -0
- package/dist/pi/piHarness.d.ts +8 -0
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +137 -6
- package/package.json +26 -4
package/dist/pi/piHarness.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
1
2
|
import type { AgentHandle, AgentHarnessAdapter, AgentStartInput, HarnessModelSpec } from "../core/types.js";
|
|
2
3
|
export interface PiHarnessOptions {
|
|
3
4
|
authPath: string;
|
|
5
|
+
sessionFactory?: PiSessionFactory;
|
|
4
6
|
model?: {
|
|
5
7
|
auth?: HarnessModelSpec["auth"];
|
|
6
8
|
endpoint?: HarnessModelSpec["endpoint"];
|
|
@@ -8,11 +10,17 @@ export interface PiHarnessOptions {
|
|
|
8
10
|
name: string;
|
|
9
11
|
};
|
|
10
12
|
modelsPath?: string;
|
|
13
|
+
memory?: {
|
|
14
|
+
source?: string;
|
|
15
|
+
tokenBudget?: number;
|
|
16
|
+
};
|
|
11
17
|
}
|
|
18
|
+
export type PiSessionFactory = (input: Parameters<typeof createAgentSession>[0]) => ReturnType<typeof createAgentSession>;
|
|
12
19
|
export declare class PiHarnessAdapter implements AgentHarnessAdapter {
|
|
13
20
|
private readonly options;
|
|
14
21
|
private readonly authStorage;
|
|
15
22
|
private readonly modelRegistry;
|
|
23
|
+
private readonly sessionFactory;
|
|
16
24
|
constructor(options: PiHarnessOptions);
|
|
17
25
|
startAgent(input: AgentStartInput): Promise<AgentHandle>;
|
|
18
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"piHarness.d.ts","sourceRoot":"","sources":["../../src/pi/piHarness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"piHarness.d.ts","sourceRoot":"","sources":["../../src/pi/piHarness.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,kBAAkB,EAMnB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,eAAe,EAEf,gBAAgB,EAGjB,MAAM,kBAAkB,CAAC;AAe1B,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,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;IACpB,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC,KAC5C,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAwP3C,qBAAa,gBAAiB,YAAW,mBAAmB;IAK9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmB;gBAErB,OAAO,EAAE,gBAAgB;IAMhD,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;CAiD/D"}
|
package/dist/pi/piHarness.js
CHANGED
|
@@ -2,6 +2,8 @@ import { mkdir } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { AuthStorage, createAgentSession, createExtensionRuntime, ModelRegistry, SessionManager, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { resolvePiHarnessModel } from "./modelConfig.js";
|
|
5
|
+
import { createPiMemoryTools, piMemoryToolNames } from "./memoryTools.js";
|
|
6
|
+
import { createMemoryRuntime, memoryScopeId, readMemoryContext } from "@noopolis/mneme";
|
|
5
7
|
const createModelRegistry = (authStorage, options) => {
|
|
6
8
|
const registry = options.modelsPath
|
|
7
9
|
? ModelRegistry.create(authStorage, options.modelsPath)
|
|
@@ -19,23 +21,46 @@ const createModelRegistry = (authStorage, options) => {
|
|
|
19
21
|
}
|
|
20
22
|
return registry;
|
|
21
23
|
};
|
|
24
|
+
const fallbackPacket = (input) => ({
|
|
25
|
+
principal: {
|
|
26
|
+
agentId: "unknown",
|
|
27
|
+
scope: "global"
|
|
28
|
+
},
|
|
29
|
+
sections: [{ heading: "Wake event", text: formatWakePrompt(input) }],
|
|
30
|
+
rawHint: "memory bypass active"
|
|
31
|
+
});
|
|
32
|
+
const extractOutputText = (chunks) => chunks.join("\n").trim();
|
|
22
33
|
class PiAgentHandle {
|
|
23
34
|
id;
|
|
24
35
|
session;
|
|
36
|
+
memory;
|
|
37
|
+
memoryToolContext;
|
|
25
38
|
state = "idle";
|
|
26
39
|
lastWakeAt;
|
|
27
40
|
lastError;
|
|
28
|
-
|
|
41
|
+
wakeQueue = Promise.resolve();
|
|
42
|
+
constructor(id, session, memory, memoryToolContext) {
|
|
29
43
|
this.id = id;
|
|
30
44
|
this.session = session;
|
|
45
|
+
this.memory = memory;
|
|
46
|
+
this.memoryToolContext = memoryToolContext;
|
|
31
47
|
}
|
|
32
48
|
async wake(event) {
|
|
49
|
+
const queued = this.wakeQueue.then(() => this.runWake(event), () => this.runWake(event));
|
|
50
|
+
this.wakeQueue = queued.then(() => undefined, () => undefined);
|
|
51
|
+
return queued;
|
|
52
|
+
}
|
|
53
|
+
async runWake(event) {
|
|
33
54
|
const startedAt = Date.now();
|
|
34
55
|
const chunks = [];
|
|
56
|
+
const toolEvents = [];
|
|
35
57
|
this.state = "running";
|
|
36
58
|
this.lastWakeAt = new Date().toISOString();
|
|
37
59
|
this.lastError = undefined;
|
|
38
60
|
const unsubscribe = this.session.subscribe((piEvent) => {
|
|
61
|
+
if (piEvent && typeof piEvent === "object" && "type" in piEvent && piEvent.type !== "turn_end") {
|
|
62
|
+
toolEvents.push(piEvent);
|
|
63
|
+
}
|
|
39
64
|
if (piEvent.type !== "turn_end") {
|
|
40
65
|
return;
|
|
41
66
|
}
|
|
@@ -54,21 +79,107 @@ class PiAgentHandle {
|
|
|
54
79
|
.join(""));
|
|
55
80
|
}
|
|
56
81
|
});
|
|
82
|
+
const memoryContext = readMemoryContext({
|
|
83
|
+
kind: event.kind,
|
|
84
|
+
id: event.id,
|
|
85
|
+
from: event.from,
|
|
86
|
+
text: event.text,
|
|
87
|
+
context: event.context
|
|
88
|
+
});
|
|
89
|
+
const request = {
|
|
90
|
+
eventId: event.id,
|
|
91
|
+
kind: event.kind,
|
|
92
|
+
text: event.text,
|
|
93
|
+
from: event.from,
|
|
94
|
+
context: memoryContext
|
|
95
|
+
};
|
|
96
|
+
let prepared;
|
|
97
|
+
let promptText = formatWakePrompt(event);
|
|
57
98
|
try {
|
|
58
|
-
|
|
99
|
+
if (this.memory) {
|
|
100
|
+
prepared = await this.memory.prepareTurn(request);
|
|
101
|
+
promptText = prepared.promptText;
|
|
102
|
+
if (this.memoryToolContext) {
|
|
103
|
+
this.memoryToolContext.current = {
|
|
104
|
+
wakeId: event.id,
|
|
105
|
+
threadId: `${memoryContext.networkId ?? "local"}:${memoryContext.roomId ?? event.from ?? "manual"}`,
|
|
106
|
+
principal: prepared.principal,
|
|
107
|
+
conversationScope: memoryScopeId(prepared.principal),
|
|
108
|
+
audienceKey: memoryContext.roomId ?? event.from ?? this.id,
|
|
109
|
+
transport: "in_process"
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
await this.session.prompt(promptText, { expandPromptTemplates: false });
|
|
59
114
|
this.state = "idle";
|
|
115
|
+
const outputText = extractOutputText(chunks);
|
|
116
|
+
if (this.memory) {
|
|
117
|
+
const promptPacket = prepared?.packet ?? fallbackPacket(event);
|
|
118
|
+
await this.memory.recordTurn({
|
|
119
|
+
principal: {
|
|
120
|
+
agentId: this.id,
|
|
121
|
+
scope: prepared?.principal.scope ?? "global",
|
|
122
|
+
qualifier: prepared?.principal.qualifier
|
|
123
|
+
},
|
|
124
|
+
prompt: {
|
|
125
|
+
...promptPacket,
|
|
126
|
+
principal: {
|
|
127
|
+
agentId: this.id,
|
|
128
|
+
scope: prepared?.principal.scope ?? "global",
|
|
129
|
+
qualifier: prepared?.principal.qualifier
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
request,
|
|
133
|
+
recall: prepared?.recall,
|
|
134
|
+
result: "completed",
|
|
135
|
+
outputText,
|
|
136
|
+
toolEvents
|
|
137
|
+
});
|
|
138
|
+
}
|
|
60
139
|
return {
|
|
61
140
|
agentId: this.id,
|
|
62
|
-
text:
|
|
141
|
+
text: outputText,
|
|
63
142
|
durationMs: Date.now() - startedAt
|
|
64
143
|
};
|
|
65
144
|
}
|
|
66
145
|
catch (error) {
|
|
67
146
|
this.state = "failed";
|
|
68
147
|
this.lastError = error instanceof Error ? error.message : String(error);
|
|
148
|
+
if (this.memory) {
|
|
149
|
+
try {
|
|
150
|
+
const promptPacket = prepared?.packet ?? fallbackPacket(event);
|
|
151
|
+
await this.memory.recordTurn({
|
|
152
|
+
principal: {
|
|
153
|
+
agentId: this.id,
|
|
154
|
+
scope: prepared?.principal.scope ?? "global",
|
|
155
|
+
qualifier: prepared?.principal.qualifier
|
|
156
|
+
},
|
|
157
|
+
prompt: {
|
|
158
|
+
...promptPacket,
|
|
159
|
+
principal: {
|
|
160
|
+
agentId: this.id,
|
|
161
|
+
scope: prepared?.principal.scope ?? "global",
|
|
162
|
+
qualifier: prepared?.principal.qualifier
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
request,
|
|
166
|
+
recall: prepared?.recall,
|
|
167
|
+
result: "failed",
|
|
168
|
+
outputText: extractOutputText(chunks),
|
|
169
|
+
toolEvents,
|
|
170
|
+
error: this.lastError
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Memory write-back is best-effort when waking fails.
|
|
175
|
+
}
|
|
176
|
+
}
|
|
69
177
|
throw error;
|
|
70
178
|
}
|
|
71
179
|
finally {
|
|
180
|
+
if (this.memoryToolContext) {
|
|
181
|
+
this.memoryToolContext.current = undefined;
|
|
182
|
+
}
|
|
72
183
|
unsubscribe();
|
|
73
184
|
}
|
|
74
185
|
}
|
|
@@ -97,6 +208,7 @@ const createResourceLoader = (input) => {
|
|
|
97
208
|
input.instructions,
|
|
98
209
|
"You are running inside a harnessed workspace prepared by the caller.",
|
|
99
210
|
"Use the available coding tools when asked to read, write, edit, or inspect files.",
|
|
211
|
+
"Use memory_search, memory_locate, memory_register, memory_summarize, and memory_forget when scoped memory matters.",
|
|
100
212
|
"Keep responses brief and report the exact files you created or modified."
|
|
101
213
|
].join("\n\n");
|
|
102
214
|
return {
|
|
@@ -115,10 +227,12 @@ export class PiHarnessAdapter {
|
|
|
115
227
|
options;
|
|
116
228
|
authStorage;
|
|
117
229
|
modelRegistry;
|
|
230
|
+
sessionFactory;
|
|
118
231
|
constructor(options) {
|
|
119
232
|
this.options = options;
|
|
120
233
|
this.authStorage = AuthStorage.create(options.authPath);
|
|
121
234
|
this.modelRegistry = createModelRegistry(this.authStorage, options);
|
|
235
|
+
this.sessionFactory = options.sessionFactory ?? createAgentSession;
|
|
122
236
|
}
|
|
123
237
|
async startAgent(input) {
|
|
124
238
|
await mkdir(input.runtimeHomePath, { recursive: true });
|
|
@@ -133,7 +247,23 @@ export class PiHarnessAdapter {
|
|
|
133
247
|
if (!model) {
|
|
134
248
|
throw new Error(`Pi model not found: ${resolvedModel.provider}/${resolvedModel.name}`);
|
|
135
249
|
}
|
|
136
|
-
const
|
|
250
|
+
const memory = createMemoryRuntime({
|
|
251
|
+
agentId: input.id,
|
|
252
|
+
runtimeHomePath: input.runtimeHomePath,
|
|
253
|
+
source: this.options.memory?.source,
|
|
254
|
+
tokenBudget: this.options.memory?.tokenBudget
|
|
255
|
+
});
|
|
256
|
+
const memoryToolContext = {};
|
|
257
|
+
const memoryTools = createPiMemoryTools({
|
|
258
|
+
agentId: input.id,
|
|
259
|
+
memory,
|
|
260
|
+
contextRef: memoryToolContext
|
|
261
|
+
});
|
|
262
|
+
const toolNames = [
|
|
263
|
+
...(input.tools ?? ["read", "write", "edit", "bash", "grep", "find", "ls"]),
|
|
264
|
+
...piMemoryToolNames(memoryTools)
|
|
265
|
+
];
|
|
266
|
+
const { session } = await this.sessionFactory({
|
|
137
267
|
cwd: input.workspacePath,
|
|
138
268
|
agentDir: input.runtimeHomePath,
|
|
139
269
|
authStorage: this.authStorage,
|
|
@@ -141,13 +271,14 @@ export class PiHarnessAdapter {
|
|
|
141
271
|
model,
|
|
142
272
|
thinkingLevel: "off",
|
|
143
273
|
resourceLoader: createResourceLoader(input),
|
|
144
|
-
tools:
|
|
274
|
+
tools: [...new Set(toolNames)],
|
|
275
|
+
customTools: memoryTools,
|
|
145
276
|
sessionManager: SessionManager.create(input.workspacePath, path.join(input.runtimeHomePath, "sessions")),
|
|
146
277
|
settingsManager: SettingsManager.inMemory({
|
|
147
278
|
compaction: { enabled: false },
|
|
148
279
|
retry: { enabled: true, maxRetries: 1 }
|
|
149
280
|
})
|
|
150
281
|
});
|
|
151
|
-
return new PiAgentHandle(input.id, session);
|
|
282
|
+
return new PiAgentHandle(input.id, session, memory, memoryToolContext);
|
|
152
283
|
}
|
|
153
284
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noopolis/daimon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Noopolis native per-agent runtime harness built on Pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./pi": {
|
|
15
|
+
"types": "./dist/pi/index.d.ts",
|
|
16
|
+
"import": "./dist/pi/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./observability": {
|
|
19
|
+
"types": "./dist/observability/index.d.ts",
|
|
20
|
+
"import": "./dist/observability/index.js"
|
|
13
21
|
}
|
|
14
22
|
},
|
|
15
23
|
"files": [
|
|
@@ -30,16 +38,30 @@
|
|
|
30
38
|
"prepublishOnly": "npm run typecheck && npm test",
|
|
31
39
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
32
40
|
"test": "node --import tsx --test \"src/**/*.test.ts\"",
|
|
33
|
-
"e2e:pi-agent": "tsx src/examples/pi-agent.ts"
|
|
41
|
+
"e2e:pi-agent": "tsx src/examples/pi-agent.ts",
|
|
42
|
+
"e2e:pi-memory-org": "tsx src/examples/pi-memory-org.ts",
|
|
43
|
+
"e2e:mixed-engine-org": "tsx src/examples/mixed-engine-org.ts",
|
|
44
|
+
"e2e:jungian-play-org": "tsx src/examples/jungian-play-org.ts",
|
|
45
|
+
"e2e:jungian-triad-org": "tsx src/examples/jungian-triad-org.ts",
|
|
46
|
+
"image:runtime:local": "docker build -f Dockerfile.runtime -t noopolis/spawnfile-runtime-daimon:0.1.1-local --build-arg DAIMON_VERSION=0.1.1 --build-arg MNEME_VERSION=0.1.0 --build-arg PI_VERSION=0.79.10 ."
|
|
34
47
|
},
|
|
35
48
|
"engines": {
|
|
36
49
|
"node": ">=22.19.0"
|
|
37
50
|
},
|
|
38
51
|
"dependencies": {
|
|
39
|
-
"@earendil-works/pi-ai": "^0.79.
|
|
40
|
-
"@earendil-works/pi-coding-agent": "^0.79.
|
|
52
|
+
"@earendil-works/pi-ai": "^0.79.10",
|
|
53
|
+
"@earendil-works/pi-coding-agent": "^0.79.10"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@noopolis/mneme": "^0.1.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependenciesMeta": {
|
|
59
|
+
"@noopolis/mneme": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
41
62
|
},
|
|
42
63
|
"devDependencies": {
|
|
64
|
+
"@noopolis/mneme": "^0.1.0",
|
|
43
65
|
"@types/node": "^24.12.4",
|
|
44
66
|
"tsx": "^4.21.0",
|
|
45
67
|
"typescript": "^5.9.3"
|