@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
package/README.md CHANGED
@@ -5,9 +5,19 @@ Daimon is the Noopolis-native per-agent runtime harness.
5
5
  It defines a small per-agent contract and currently implements that contract on
6
6
  top of Pi. A Daimon runs one harnessed agent inside a caller-prepared workspace.
7
7
 
8
- Spawnfile should own orgs, nested teams, schedules, Moltnet wiring, workspace
9
- resource compilation, and the app that starts many harnessed agents. This package
10
- should not know what an org is.
8
+ Spawnfile compiles and deploys orgs, nested teams, member-owned schedules,
9
+ Moltnet wiring, and workspace resources. Daimon executes one agent runtime: it
10
+ accepts a wake selected by that runtime's organization policy and runs one
11
+ turn. It does not know the org graph, schedule other agents, or let Simfile or
12
+ a world service trigger cognition.
13
+
14
+ For a world-capable `kind: every` wake, the harness starts without a decision
15
+ token and privately calls `world_claim` before exposing any other world tool.
16
+ The claim binds authority to the schedule wake's run/request/wake identity; the
17
+ opaque token stays inside the harness. Subsequent observe/affordance/action
18
+ calls carry it without placing it in the model prompt or tool schema. Optional
19
+ world recommendations are ordinary observation fields discovered after the
20
+ independent wake and claim—they are never Daimon wake inputs.
11
21
 
12
22
  ## Install
13
23
 
@@ -15,6 +25,8 @@ should not know what an org is.
15
25
  npm install @noopolis/daimon
16
26
  ```
17
27
 
28
+ The latest published version is 0.1.1; this README describes the source tree (0.1.2).
29
+
18
30
  For Pi agents with memory enabled, install Mneme too:
19
31
 
20
32
  ```bash
@@ -37,10 +49,31 @@ Pi-specific exports live under the Pi subpath:
37
49
  import { PiHarnessAdapter } from "@noopolis/daimon/pi";
38
50
  ```
39
51
 
52
+ By default, the in-process Mneme runtime uses the same path as each agent's
53
+ `runtimeHomePath`. If you need agents to keep separate Pi/runtime directories but
54
+ share one memory bank, pass an explicit `memory.runtimeHomePath` in
55
+ `PiHarnessOptions`.
56
+
57
+ ```ts
58
+ const adapter = new PiHarnessAdapter({
59
+ authPath: "/tmp/daimon-auth.json",
60
+ memory: {
61
+ runtimeHomePath: "/shared/memory/bank"
62
+ }
63
+ });
64
+ ```
65
+
66
+ Pi agents receive Mneme tools in awake mode for normal work. Dream wakes use a
67
+ fresh one-off Pi session under `sessions/dream/<wake-id>-<random>` and inject
68
+ the Mneme dream guidance instead. Daimon does not automatically record every
69
+ turn as memory; agents write memories only by calling Mneme tools such as
70
+ `memory_register`, `memory_summarize`, and `memory_forget`.
71
+
40
72
  ## Tests
41
73
 
42
- The package has a non-live test suite for auth seeding and Pi model config
43
- generation:
74
+ The package has a non-live test suite covering auth seeding, Pi model config
75
+ generation, the harness contract, memory tool wiring, wake and turn traces, and
76
+ the org observer:
44
77
 
45
78
  ```bash
46
79
  npm test
@@ -68,6 +101,10 @@ upstream-documented dummy `ollama` value.
68
101
  The Pi E2E uses the local Codex CLI subscription auth file to seed an ignored Pi
69
102
  `auth.json` under `.runtime/`.
70
103
 
104
+ These are live runs: they spend real tokens and require local engine auth
105
+ (`~/.codex/auth.json` for Pi/Codex; mixed-engine and triad additionally need
106
+ authenticated `grok` and `agy` CLIs on PATH). They are not part of `npm test`.
107
+
71
108
  ```bash
72
109
  npm install
73
110
  npm run e2e:pi-agent
@@ -107,8 +144,9 @@ archetype gets consulted.
107
144
  ## Design Notes
108
145
 
109
146
  - `MEMORY-SYSTEM.md` describes the implemented scoped memory runtime.
110
- - `ENGINE-SYSTEM.md` describes the next engine abstraction plan: Pi, Ollama,
111
- API providers, and CLI-backed engines such as `agy`, `grok`, and `gemini`.
147
+ - `ENGINE-SYSTEM.md` describes the engine abstraction plan: Pi, local/API
148
+ model providers, and CLI-backed engines such as `codex`, `claude`, `grok`,
149
+ and `agy`.
112
150
  - Mneme is a sibling package, `@noopolis/mneme`, published separately and used
113
151
  by Daimon in-process for Pi agents. Other runtimes can use Mneme through its
114
152
  MCP server. The agent-facing tools stay named `memory_search`,
@@ -117,16 +155,22 @@ archetype gets consulted.
117
155
 
118
156
  ## Runtime Artifact Image
119
157
 
120
- Daimon can build a local copy-only runtime artifact image for Spawnfile:
158
+ Daimon defines a local copy-only runtime artifact image build for Spawnfile:
121
159
 
122
160
  ```bash
123
161
  npm run image:runtime:local
124
162
  ```
125
163
 
164
+ Status: this build currently fails against the public npm registry. The
165
+ Dockerfile pins `@noopolis/daimon@0.1.2` and `@noopolis/mneme@0.1.1`, and
166
+ neither is published yet (registry has daimon 0.1.1 and mneme 0.1.0). Works
167
+ only after those versions publish or against a registry that has them. Treat
168
+ as pending publish.
169
+
126
170
  This creates:
127
171
 
128
172
  ```text
129
- noopolis/spawnfile-runtime-daimon:0.1.1-local
173
+ noopolis/spawnfile-runtime-daimon:0.1.2-local
130
174
  ```
131
175
 
132
176
  The image is not a full organization image and is not intended to be run
@@ -139,7 +183,7 @@ directly. It contains only:
139
183
  Spawnfile can copy that path into generated organization images:
140
184
 
141
185
  ```bash
142
- SPAWNFILE_DAIMON_RUNTIME_IMAGE=noopolis/spawnfile-runtime-daimon:0.1.1-local \
186
+ SPAWNFILE_DAIMON_RUNTIME_IMAGE=noopolis/spawnfile-runtime-daimon:0.1.2-local \
143
187
  spawnfile build ./agentic-org
144
188
  ```
145
189
 
@@ -0,0 +1,21 @@
1
+ export type SiblingFileFact = {
2
+ path: string;
3
+ mtimeMs: number;
4
+ };
5
+ export type SiblingBuildFacts = {
6
+ packageName: string;
7
+ packageDirectory: string;
8
+ hasSourceDirectory: boolean;
9
+ sourceFiles: SiblingFileFact[];
10
+ outputFiles: SiblingFileFact[];
11
+ };
12
+ export type SiblingBuildFreshness = {
13
+ packageName: string;
14
+ linked: boolean;
15
+ sourcesScanned: number;
16
+ outputsScanned: number;
17
+ ok: boolean;
18
+ message?: string;
19
+ };
20
+ export declare function checkSiblingBuildFreshness(facts: SiblingBuildFacts): SiblingBuildFreshness;
21
+ //# sourceMappingURL=siblingBuildFreshness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siblingBuildFreshness.d.ts","sourceRoot":"","sources":["../../src/core/siblingBuildFreshness.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,EAAE,eAAe,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,CA2B1F"}
@@ -0,0 +1,25 @@
1
+ const excludedSource = /(?:\.test\.ts|\.test-helper\.ts|\.d\.ts)$/u;
2
+ export function checkSiblingBuildFreshness(facts) {
3
+ if (!facts.hasSourceDirectory) {
4
+ return { packageName: facts.packageName, linked: false, sourcesScanned: 0, outputsScanned: 0, ok: true };
5
+ }
6
+ const sourceFiles = facts.sourceFiles.filter(({ path }) => !excludedSource.test(path));
7
+ const outputFiles = facts.outputFiles.filter(({ path }) => path.endsWith(".js"));
8
+ const command = `run "npm run build" in ${facts.packageDirectory}`;
9
+ if (sourceFiles.length === 0) {
10
+ return failure(facts.packageName, sourceFiles.length, outputFiles.length, `linked package ${facts.packageName} scanned zero source files; ${command}`);
11
+ }
12
+ if (outputFiles.length === 0) {
13
+ return failure(facts.packageName, sourceFiles.length, outputFiles.length, `linked package ${facts.packageName} has no emitted JavaScript; ${command}`);
14
+ }
15
+ const newestSource = sourceFiles.reduce((newest, file) => file.mtimeMs > newest.mtimeMs ? file : newest);
16
+ const oldestOutput = outputFiles.reduce((oldest, file) => file.mtimeMs < oldest.mtimeMs ? file : oldest);
17
+ if (newestSource.mtimeMs > oldestOutput.mtimeMs) {
18
+ return failure(facts.packageName, sourceFiles.length, outputFiles.length, `linked package ${facts.packageName} is stale: newest source ${newestSource.path} (${newestSource.mtimeMs}) `
19
+ + `is newer than oldest output ${oldestOutput.path} (${oldestOutput.mtimeMs}); ${command}`);
20
+ }
21
+ return { packageName: facts.packageName, linked: true, sourcesScanned: sourceFiles.length, outputsScanned: outputFiles.length, ok: true };
22
+ }
23
+ function failure(packageName, sourcesScanned, outputsScanned, message) {
24
+ return { packageName, linked: true, sourcesScanned, outputsScanned, ok: false, message };
25
+ }
@@ -20,9 +20,15 @@ export interface HarnessModelSpec {
20
20
  name: string;
21
21
  provider: string;
22
22
  }
23
+ export interface WakeDeliveryMetadata {
24
+ eventId: string;
25
+ sender: string;
26
+ target: string;
27
+ contextId: string;
28
+ }
23
29
  export interface WakeEvent {
24
30
  id: string;
25
- kind: "manual" | "message" | "schedule";
31
+ kind: "manual" | "message" | "schedule" | "dream";
26
32
  from?: string;
27
33
  text: string;
28
34
  context?: {
@@ -35,6 +41,9 @@ export interface WakeEvent {
35
41
  pairPeers?: string[];
36
42
  artifactPaths?: string[];
37
43
  };
44
+ delivery?: WakeDeliveryMetadata;
45
+ /** Exact transport body retained outside the runtime-enriched model prompt. */
46
+ transportText?: string;
38
47
  }
39
48
  export interface WakeResult {
40
49
  agentId: AgentId;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,WAAW,GAAG,QAAQ,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;KACtD,CAAC;IACF,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,IAAI,WAAW,CAAC;IACtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,WAAW,GAAG,QAAQ,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;KACtD,CAAC;IACF,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,IAAI,WAAW,CAAC;IACtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1D"}
@@ -0,0 +1,3 @@
1
+ /** Namespaces caller-authored example wakes for the shared causal contract. */
2
+ export declare const exampleCausalId: (localId: string) => string;
3
+ //# sourceMappingURL=exampleCausalId.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exampleCausalId.d.ts","sourceRoot":"","sources":["../../src/examples/exampleCausalId.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAKjD,CAAC"}
@@ -0,0 +1,8 @@
1
+ const LOCAL_CAUSAL_ID = /^[a-z0-9][a-z0-9._-]{0,255}$/u;
2
+ /** Namespaces caller-authored example wakes for the shared causal contract. */
3
+ export const exampleCausalId = (localId) => {
4
+ if (!LOCAL_CAUSAL_ID.test(localId)) {
5
+ throw new Error("Daimon example causal id must be a bounded local id");
6
+ }
7
+ return `daimon:${localId}`;
8
+ };
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  import { JsonlMemoryStore } from "@noopolis/mneme";
5
5
  import { OrgObserver } from "../observability/index.js";
6
6
  import { beatsFor, defaultDialogueTurns, selectVoicesForBeat } from "./jungianConversationPlan.js";
7
+ import { exampleCausalId } from "./exampleCausalId.js";
7
8
  import { JungianVoice, runLimited } from "./jungianPlayAgent.js";
8
9
  import { jungianSelves, playScenario } from "./jungianProfiles.js";
9
10
  import { JungianTrace, parseInnerUsed, parseSpeakLine } from "./jungianTrace.js";
@@ -132,7 +133,7 @@ const runCouncil = async (self, eventId, focus, transcript, voices) => {
132
133
  console.log(`\n== ${self.profile.name} inner council: ${focus} ==`);
133
134
  const turns = await runLimited(voices, councilConcurrency, async (voice) => {
134
135
  const event = {
135
- id: `${eventId}-${voice.config.id}`,
136
+ id: exampleCausalId(`${eventId}-${voice.config.id}`),
136
137
  kind: "manual",
137
138
  context: roomContext,
138
139
  text: councilPrompt(self.profile, focus, transcript)
@@ -155,7 +156,7 @@ const runCouncil = async (self, eventId, focus, transcript, voices) => {
155
156
  };
156
157
  const runRepresentative = async (self, eventId, focus, transcript, counsel) => {
157
158
  const event = {
158
- id: eventId,
159
+ id: exampleCausalId(eventId),
159
160
  kind: "manual",
160
161
  context: roomContext,
161
162
  text: representativePrompt(self.profile, focus, transcript, counsel)
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  import { JsonlMemoryStore } from "@noopolis/mneme";
5
5
  import { OrgObserver } from "../observability/index.js";
6
6
  import { PiHarnessAdapter } from "../pi/piHarness.js";
7
+ import { exampleCausalId } from "./exampleCausalId.js";
7
8
  import { JungianPiRepresentative, seedPiCodexAuth } from "./jungianPiRepresentative.js";
8
9
  import { JungianVoice, runLimited } from "./jungianPlayAgent.js";
9
10
  import { JungianTrace, parseInnerUsed, parseSpeakLine } from "./jungianTrace.js";
@@ -134,7 +135,7 @@ const runCouncil = async (self, eventBase, focus, transcript, voices) => {
134
135
  console.log(`\n== ${self.profile.name} inner counsel ==`);
135
136
  return runLimited(voices, 2, async (voice) => {
136
137
  const event = {
137
- id: `${eventBase}-council-${voice.config.id}`,
138
+ id: exampleCausalId(`${eventBase}-council-${voice.config.id}`),
138
139
  kind: "manual",
139
140
  context: roomContext,
140
141
  text: councilPrompt(self.profile, focus, transcript)
@@ -171,7 +172,7 @@ const assertUsedCounsel = (self, eventId, output, counsel) => {
171
172
  };
172
173
  const runRepresentative = async (self, eventBase, focus, transcript, counsel) => {
173
174
  const event = {
174
- id: `${eventBase}-speaks`,
175
+ id: exampleCausalId(`${eventBase}-speaks`),
175
176
  kind: "manual",
176
177
  context: roomContext,
177
178
  text: representativePrompt(self.profile, focus, transcript, counsel)
@@ -1,6 +1,6 @@
1
1
  import type { WakeEvent } from "../core/types.js";
2
2
  import type { MemoryRecallAudit } from "@noopolis/mneme";
3
- import { type EngineKind, type EngineRunResult } from "./mixedEngineCli.js";
3
+ import { type CliEngineKind as EngineKind, type EngineRunResult } from "../pi/cliSession.js";
4
4
  export interface JungianVoiceConfig {
5
5
  archetype?: string;
6
6
  engine: EngineKind;
@@ -1 +1 @@
1
- {"version":3,"file":"jungianPlayAgent.d.ts","sourceRoot":"","sources":["../../src/examples/jungianPlayAgent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAqB,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE/F,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,eAAe,CAAC;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAUD,qBAAa,YAAY;IAKX,QAAQ,CAAC,MAAM,EAAE,kBAAkB;IAJ/C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,kBAAkB;IAWzC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA4DxD;AAED,eAAO,MAAM,UAAU,GAAU,CAAC,EAAE,CAAC,EACnC,QAAQ,SAAS,CAAC,EAAE,EACpB,OAAO,MAAM,EACb,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,KAC5B,OAAO,CAAC,CAAC,EAAE,CAYb,CAAC"}
1
+ {"version":3,"file":"jungianPlayAgent.d.ts","sourceRoot":"","sources":["../../src/examples/jungianPlayAgent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAqB,KAAK,aAAa,IAAI,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEhH,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,eAAe,CAAC;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAUD,qBAAa,YAAY;IAKX,QAAQ,CAAC,MAAM,EAAE,kBAAkB;IAJ/C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,kBAAkB;IAWzC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA4DxD;AAED,eAAO,MAAM,UAAU,GAAU,CAAC,EAAE,CAAC,EACnC,QAAQ,SAAS,CAAC,EAAE,EACpB,OAAO,MAAM,EACb,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,KAC5B,OAAO,CAAC,CAAC,EAAE,CAYb,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { createMemoryRuntime } from "@noopolis/mneme";
4
- import { runEngineDetailed } from "./mixedEngineCli.js";
4
+ import { runEngineDetailed } from "../pi/cliSession.js";
5
5
  const maxMemoryChars = 2200;
6
6
  const truncate = (text, maxChars) => text.length <= maxChars ? text : `${text.slice(0, maxChars).trim()}\n[truncated]`;
7
7
  const memorySections = (turnPrompt) => truncate(turnPrompt, maxMemoryChars);
@@ -1,4 +1,4 @@
1
- import type { EngineKind } from "./mixedEngineCli.js";
1
+ import type { CliEngineKind as EngineKind } from "../pi/cliSession.js";
2
2
  export interface JungianArchetypeProfile {
3
3
  agenda: string;
4
4
  archetype: string;
@@ -1 +1 @@
1
- {"version":3,"file":"jungianProfiles.d.ts","sourceRoot":"","sources":["../../src/examples/jungianProfiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AA+JD,eAAO,MAAM,aAAa,EAAE,kBAAkB,EAiC7C,CAAC;AAEF,eAAO,MAAM,YAAY;;;;CAMxB,CAAC"}
1
+ {"version":3,"file":"jungianProfiles.d.ts","sourceRoot":"","sources":["../../src/examples/jungianProfiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AA+JD,eAAO,MAAM,aAAa,EAAE,kBAAkB,EAiC7C,CAAC;AAEF,eAAO,MAAM,YAAY;;;;CAMxB,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { EngineKind } from "./mixedEngineCli.js";
1
+ import type { CliEngineKind as EngineKind } from "../pi/cliSession.js";
2
2
  export type RepresentativeEngine = EngineKind | "pi";
3
3
  export interface TriadArchetypeProfile {
4
4
  agenda: string;
@@ -1 +1 @@
1
- {"version":3,"file":"jungianTriadProfiles.d.ts","sourceRoot":"","sources":["../../src/examples/jungianTriadProfiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,IAAI,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAsDD,eAAO,MAAM,WAAW,EAAE,gBAAgB,EAqCzC,CAAC;AAEF,eAAO,MAAM,aAAa;;;;CAMzB,CAAC"}
1
+ {"version":3,"file":"jungianTriadProfiles.d.ts","sourceRoot":"","sources":["../../src/examples/jungianTriadProfiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,IAAI,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAsDD,eAAO,MAAM,WAAW,EAAE,gBAAgB,EAqCzC,CAAC;AAEF,eAAO,MAAM,aAAa;;;;CAMzB,CAAC"}
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { seedPiOpenAICodexAuthFromCodex } from "../pi/auth.js";
5
5
  import { PiHarnessAdapter } from "../pi/piHarness.js";
6
+ import { exampleCausalId } from "./exampleCausalId.js";
6
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
8
  const daimonRoot = path.resolve(__dirname, "../..");
8
9
  const runtimeRoot = path.join(daimonRoot, ".runtime", "pi-agent");
@@ -66,7 +67,7 @@ const run = async () => {
66
67
  try {
67
68
  console.log("started", JSON.stringify([mapper.status(), reviewer.status()], null, 2));
68
69
  const mapped = await mapper.wake({
69
- id: "wake-mapper-1",
70
+ id: exampleCausalId("wake-mapper-1"),
70
71
  kind: "manual",
71
72
  from: "caller",
72
73
  text: [
@@ -78,7 +79,7 @@ const run = async () => {
78
79
  });
79
80
  console.log("mapper", JSON.stringify(mapped, null, 2));
80
81
  const reviewed = await reviewer.wake({
81
- id: "wake-reviewer-1",
82
+ id: exampleCausalId("wake-reviewer-1"),
82
83
  kind: "message",
83
84
  from: "mapper",
84
85
  text: [
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  import { JsonlMemoryStore } from "@noopolis/mneme";
5
5
  import { seedPiOpenAICodexAuthFromCodex } from "../pi/auth.js";
6
6
  import { PiHarnessAdapter } from "../pi/piHarness.js";
7
+ import { exampleCausalId } from "./exampleCausalId.js";
7
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
9
  const daimonRoot = path.resolve(__dirname, "../..");
9
10
  const runtimeRoot = path.join(daimonRoot, ".runtime", "pi-memory-org");
@@ -92,7 +93,7 @@ const seedPrivateMemories = async (handles) => {
92
93
  console.log("\n== Private seed phase ==");
93
94
  for (const agent of demoAgents) {
94
95
  const result = await handles.get(agent.id)?.wake({
95
- id: `seed-${agent.id}`,
96
+ id: exampleCausalId(`seed-${agent.id}`),
96
97
  kind: "manual",
97
98
  text: [
98
99
  "Private memory seed.",
@@ -107,7 +108,7 @@ const runRoomConversation = async (handles) => {
107
108
  console.log("\n== Room recall phase ==");
108
109
  const transcript = [];
109
110
  const atlas = await wake(handles.get("atlas"), {
110
- id: "room-atlas-1",
111
+ id: exampleCausalId("room-atlas-1"),
111
112
  kind: "manual",
112
113
  context: roomContext,
113
114
  text: [
@@ -121,7 +122,7 @@ const runRoomConversation = async (handles) => {
121
122
  assertIncludes("atlas room reply", atlas.text, "ATLAS_BLUE_17");
122
123
  transcript.push(`atlas: ${atlas.text}`);
123
124
  const oracle = await wake(handles.get("oracle"), {
124
- id: "room-oracle-1",
125
+ id: exampleCausalId("room-oracle-1"),
125
126
  kind: "manual",
126
127
  context: roomContext,
127
128
  text: [
@@ -135,7 +136,7 @@ const runRoomConversation = async (handles) => {
135
136
  assertIncludes("oracle room reply", oracle.text, "ATLAS_BLUE_17");
136
137
  transcript.push(`oracle: ${oracle.text}`);
137
138
  const keeper = await wake(handles.get("keeper"), {
138
- id: "room-keeper-1",
139
+ id: exampleCausalId("room-keeper-1"),
139
140
  kind: "manual",
140
141
  context: roomContext,
141
142
  text: [
@@ -162,7 +163,7 @@ const verifyFreshSessionRecall = async (adapter, previousKeeper) => {
162
163
  const keeper = await startAgent(adapter, demoAgents.find((agent) => agent.id === "keeper"));
163
164
  try {
164
165
  const event = {
165
- id: "room-keeper-2",
166
+ id: exampleCausalId("room-keeper-2"),
166
167
  kind: "manual",
167
168
  context: roomContext,
168
169
  text: [
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./core/types.js";
2
2
  export * from "./observability/index.js";
3
+ export * from "./mcp/toolServer.js";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./core/types.js";
2
2
  export * from "./observability/index.js";
3
+ export * from "./mcp/toolServer.js";
@@ -0,0 +1,14 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
3
+ export declare class McpToolTurnLimitError extends Error {
4
+ constructor(maxToolTurns: number);
5
+ }
6
+ export declare class McpWakeDeadlineError extends Error {
7
+ constructor();
8
+ }
9
+ export interface PiToolMcpServerOptions {
10
+ readonly maxToolTurns: number;
11
+ readonly wakeDeadline: number;
12
+ }
13
+ export declare const createPiToolMcpServer: (tools: ToolDefinition[], options: PiToolMcpServerOptions) => Server;
14
+ //# sourceMappingURL=toolServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolServer.d.ts","sourceRoot":"","sources":["../../src/mcp/toolServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAYnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,qBAAa,qBAAsB,SAAQ,KAAK;gBAC3B,YAAY,EAAE,MAAM;CAIxC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;;CAK9C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAqCD,eAAO,MAAM,qBAAqB,GAChC,OAAO,cAAc,EAAE,EACvB,SAAS,sBAAsB,KAC9B,MAmEF,CAAC"}
@@ -0,0 +1,105 @@
1
+ import { Ajv2020 } from "ajv/dist/2020.js";
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from "@modelcontextprotocol/sdk/types.js";
4
+ export class McpToolTurnLimitError extends Error {
5
+ constructor(maxToolTurns) {
6
+ super(`McpToolTurnLimitError: maximum ${maxToolTurns} calls per wake`);
7
+ this.name = "McpToolTurnLimitError";
8
+ }
9
+ }
10
+ export class McpWakeDeadlineError extends Error {
11
+ constructor() {
12
+ super("McpWakeDeadlineError: wake deadline exceeded");
13
+ this.name = "McpWakeDeadlineError";
14
+ }
15
+ }
16
+ const jsonSchema = (parameters) => {
17
+ if (parameters === null || typeof parameters !== "object" || Array.isArray(parameters)) {
18
+ throw new TypeError("Pi tool parameters must be a JSON schema object");
19
+ }
20
+ return Object.fromEntries(Object.entries(parameters));
21
+ };
22
+ const toolResult = (result) => ({
23
+ content: result.content,
24
+ ...(result.details !== undefined && typeof result.details === "object" && result.details !== null
25
+ ? { structuredContent: Object.fromEntries(Object.entries(result.details)) }
26
+ : {})
27
+ });
28
+ const toolError = (error) => ({
29
+ content: [{ type: "text", text: error instanceof Error ? `${error.name}: ${error.message}` : String(error) }],
30
+ isError: true
31
+ });
32
+ // Pi's ExtensionContext has no meaning outside a Pi session. Mounted tools
33
+ // must not read it; this named value documents the explicit absence.
34
+ // The MCP mount deliberately has no Pi session context; `never` preserves typed positional checks.
35
+ const NO_PI_EXTENSION_CONTEXT = undefined;
36
+ const validateOptions = (options) => {
37
+ if (!Number.isSafeInteger(options.maxToolTurns) || options.maxToolTurns < 1) {
38
+ throw new TypeError("maxToolTurns must be a positive safe integer");
39
+ }
40
+ if (!Number.isFinite(options.wakeDeadline)) {
41
+ throw new TypeError("wakeDeadline must be a finite epoch-millisecond deadline");
42
+ }
43
+ };
44
+ export const createPiToolMcpServer = (tools, options) => {
45
+ validateOptions(options);
46
+ const server = new Server({ name: "daimon-pi-tools", version: "0.1.2" });
47
+ const validators = new Map(tools.map((tool) => {
48
+ const schema = jsonSchema(tool.parameters);
49
+ return [tool.name, new Ajv2020({ strict: false }).compile(schema)];
50
+ }));
51
+ let toolTurns = 0;
52
+ server.registerCapabilities({ tools: { listChanged: true } });
53
+ server.setRequestHandler(ListToolsRequestSchema, () => ({
54
+ tools: tools.map((tool) => ({
55
+ name: tool.name,
56
+ title: tool.label,
57
+ description: tool.description,
58
+ inputSchema: jsonSchema(tool.parameters)
59
+ }))
60
+ }));
61
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
62
+ try {
63
+ if (Date.now() >= options.wakeDeadline)
64
+ throw new McpWakeDeadlineError();
65
+ if (toolTurns >= options.maxToolTurns)
66
+ throw new McpToolTurnLimitError(options.maxToolTurns);
67
+ const tool = tools.find((candidate) => candidate.name === request.params.name);
68
+ const validator = validators.get(request.params.name);
69
+ if (tool === undefined || validator === undefined) {
70
+ throw new McpError(ErrorCode.InvalidParams, `Unknown tool: ${request.params.name}`);
71
+ }
72
+ const args = request.params.arguments ?? {};
73
+ if (!validator(args)) {
74
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${tool.name}`);
75
+ }
76
+ toolTurns += 1;
77
+ // Ajv validated this value against this tool's own schema immediately above.
78
+ const validatedArgs = args;
79
+ const deadlineController = new AbortController();
80
+ const remainingMs = Math.max(0, options.wakeDeadline - Date.now());
81
+ const deadlineTimer = setTimeout(() => deadlineController.abort(), remainingMs);
82
+ const signal = extra.signal === undefined
83
+ ? deadlineController.signal
84
+ : AbortSignal.any([extra.signal, deadlineController.signal]);
85
+ const deadline = new Promise((_resolve, reject) => {
86
+ deadlineController.signal.addEventListener("abort", () => reject(new McpWakeDeadlineError()), { once: true });
87
+ });
88
+ let result;
89
+ try {
90
+ result = await Promise.race([
91
+ tool.execute(`mcp-tool-turn-${toolTurns}`, validatedArgs, signal, undefined, NO_PI_EXTENSION_CONTEXT),
92
+ deadline
93
+ ]);
94
+ }
95
+ finally {
96
+ clearTimeout(deadlineTimer);
97
+ }
98
+ return toolResult(result);
99
+ }
100
+ catch (error) {
101
+ return toolError(error);
102
+ }
103
+ });
104
+ return server;
105
+ };