@noopolis/daimon 0.1.0 → 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.
- package/README.md +141 -5
- package/dist/core/siblingBuildFreshness.d.ts +21 -0
- package/dist/core/siblingBuildFreshness.d.ts.map +1 -0
- package/dist/core/siblingBuildFreshness.js +25 -0
- package/dist/core/types.d.ts +20 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/examples/exampleCausalId.d.ts +3 -0
- package/dist/examples/exampleCausalId.d.ts.map +1 -0
- package/dist/examples/exampleCausalId.js +8 -0
- 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 +281 -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 +281 -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/pi-agent.js +3 -2
- 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 +231 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/mcp/toolServer.d.ts +14 -0
- package/dist/mcp/toolServer.d.ts.map +1 -0
- package/dist/mcp/toolServer.js +105 -0
- package/dist/observability/causalEvents.d.ts +118 -0
- package/dist/observability/causalEvents.d.ts.map +1 -0
- package/dist/observability/causalEvents.js +135 -0
- package/dist/observability/controlCausal.d.ts +117 -0
- package/dist/observability/controlCausal.d.ts.map +1 -0
- package/dist/observability/controlCausal.js +107 -0
- package/dist/observability/emitCausalFixture.d.ts +25 -0
- package/dist/observability/emitCausalFixture.d.ts.map +1 -0
- package/dist/observability/emitCausalFixture.js +98 -0
- package/dist/observability/index.d.ts +4 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +3 -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/cliSession.d.ts +46 -0
- package/dist/pi/cliSession.d.ts.map +1 -0
- package/dist/pi/cliSession.js +224 -0
- package/dist/pi/index.d.ts +9 -0
- package/dist/pi/index.d.ts.map +1 -0
- package/dist/pi/index.js +8 -0
- package/dist/pi/memoryTools.d.ts +69 -0
- package/dist/pi/memoryTools.d.ts.map +1 -0
- package/dist/pi/memoryTools.js +190 -0
- package/dist/pi/modelRegistry.d.ts +13 -0
- package/dist/pi/modelRegistry.d.ts.map +1 -0
- package/dist/pi/modelRegistry.js +19 -0
- package/dist/pi/piAgentHandle.d.ts +45 -0
- package/dist/pi/piAgentHandle.d.ts.map +1 -0
- package/dist/pi/piAgentHandle.js +324 -0
- package/dist/pi/piAgentWakeSupport.d.ts +68 -0
- package/dist/pi/piAgentWakeSupport.d.ts.map +1 -0
- package/dist/pi/piAgentWakeSupport.js +147 -0
- package/dist/pi/piHarness.d.ts +36 -2
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +100 -127
- package/dist/pi/prompts.d.ts +9 -0
- package/dist/pi/prompts.d.ts.map +1 -0
- package/dist/pi/prompts.js +39 -0
- package/dist/pi/rawTrainingCapture.d.ts +59 -0
- package/dist/pi/rawTrainingCapture.d.ts.map +1 -0
- package/dist/pi/rawTrainingCapture.js +175 -0
- package/dist/pi/turnCausal.d.ts +73 -0
- package/dist/pi/turnCausal.d.ts.map +1 -0
- package/dist/pi/turnCausal.js +75 -0
- package/dist/pi/turnTrace.d.ts +128 -0
- package/dist/pi/turnTrace.d.ts.map +1 -0
- package/dist/pi/turnTrace.js +141 -0
- package/dist/pi/wakeAcceptance.d.ts +49 -0
- package/dist/pi/wakeAcceptance.d.ts.map +1 -0
- package/dist/pi/wakeAcceptance.js +281 -0
- package/dist/pi/wakeAcceptanceFs.d.ts +44 -0
- package/dist/pi/wakeAcceptanceFs.d.ts.map +1 -0
- package/dist/pi/wakeAcceptanceFs.js +318 -0
- package/dist/pi/wakeAcceptanceSchema.d.ts +75 -0
- package/dist/pi/wakeAcceptanceSchema.d.ts.map +1 -0
- package/dist/pi/wakeAcceptanceSchema.js +265 -0
- package/dist/pi/wakeModes.d.ts +9 -0
- package/dist/pi/wakeModes.d.ts.map +1 -0
- package/dist/pi/wakeModes.js +19 -0
- package/dist/pi/worldNudge.d.ts +22 -0
- package/dist/pi/worldNudge.d.ts.map +1 -0
- package/dist/pi/worldNudge.js +62 -0
- package/dist/pi/worldToolProtocol.d.ts +13 -0
- package/dist/pi/worldToolProtocol.d.ts.map +1 -0
- package/dist/pi/worldToolProtocol.js +49 -0
- package/dist/pi/worldTools.d.ts +32 -0
- package/dist/pi/worldTools.d.ts.map +1 -0
- package/dist/pi/worldTools.js +373 -0
- package/dist/pi/worldTrajectory.d.ts +52 -0
- package/dist/pi/worldTrajectory.d.ts.map +1 -0
- package/dist/pi/worldTrajectory.js +131 -0
- package/package.json +23 -4
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
|
|
9
|
-
|
|
10
|
-
|
|
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,10 +25,55 @@ 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
|
+
|
|
30
|
+
For Pi agents with memory enabled, install Mneme too:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @noopolis/daimon @noopolis/mneme
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
During local incubation, use the sibling Mneme checkout:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@noopolis/mneme": "file:../mneme"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Pi-specific exports live under the Pi subpath:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { PiHarnessAdapter } from "@noopolis/daimon/pi";
|
|
50
|
+
```
|
|
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
|
+
|
|
18
72
|
## Tests
|
|
19
73
|
|
|
20
|
-
The package has a non-live test suite
|
|
21
|
-
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:
|
|
22
77
|
|
|
23
78
|
```bash
|
|
24
79
|
npm test
|
|
@@ -46,11 +101,92 @@ upstream-documented dummy `ollama` value.
|
|
|
46
101
|
The Pi E2E uses the local Codex CLI subscription auth file to seed an ignored Pi
|
|
47
102
|
`auth.json` under `.runtime/`.
|
|
48
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
|
+
|
|
49
108
|
```bash
|
|
50
109
|
npm install
|
|
51
110
|
npm run e2e:pi-agent
|
|
111
|
+
npm run e2e:pi-memory-org
|
|
112
|
+
npm run e2e:mixed-engine-org
|
|
113
|
+
npm run e2e:jungian-play-org
|
|
114
|
+
npm run e2e:jungian-triad-org
|
|
52
115
|
```
|
|
53
116
|
|
|
54
117
|
The example starts two harnessed Pi agents from plain caller code. The example
|
|
55
118
|
creates the workspaces and shared resource itself to demonstrate the intended
|
|
56
119
|
boundary: the caller prepares files, the harness runs agent turns.
|
|
120
|
+
|
|
121
|
+
The memory-org example starts three harnessed Pi agents, gives each agent a
|
|
122
|
+
private marker memory, clears Pi session history, then runs a room-style recall
|
|
123
|
+
conversation. It restarts one agent again before the final check, so the final
|
|
124
|
+
answer must come from Daimon's persisted memory rather than Pi's live chat
|
|
125
|
+
session.
|
|
126
|
+
|
|
127
|
+
The mixed-engine example starts a small org backed by real local CLIs:
|
|
128
|
+
Navigator uses Codex, Cartographer uses Grok, and Sentinel uses Agy. Each engine
|
|
129
|
+
invents its own private signal, then the room conversation verifies that later
|
|
130
|
+
turns recall those LLM-generated signals through Daimon memory.
|
|
131
|
+
|
|
132
|
+
The Jungian play example starts two selves as characters in a play. Each self
|
|
133
|
+
has archetype voices such as Persona, Shadow, Anima/Animus, Wise One, Great
|
|
134
|
+
Mother, Hero, and Trickster. The inner voices run first, the representative self
|
|
135
|
+
then speaks externally, and the run writes play traces plus memory/latency
|
|
136
|
+
telemetry under `.runtime/jungian-play-org/`.
|
|
137
|
+
|
|
138
|
+
The Jungian triad example uses three complete Jungian selves in one
|
|
139
|
+
conversation: Maya speaks through Codex CLI, Leo speaks through Grok, and Priya
|
|
140
|
+
speaks through a Pi agent seeded from local Codex subscription auth. All three
|
|
141
|
+
selves carry the same full archetype set, rotated through the run so every
|
|
142
|
+
archetype gets consulted.
|
|
143
|
+
|
|
144
|
+
## Design Notes
|
|
145
|
+
|
|
146
|
+
- `MEMORY-SYSTEM.md` describes the implemented scoped memory runtime.
|
|
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`.
|
|
150
|
+
- Mneme is a sibling package, `@noopolis/mneme`, published separately and used
|
|
151
|
+
by Daimon in-process for Pi agents. Other runtimes can use Mneme through its
|
|
152
|
+
MCP server. The agent-facing tools stay named `memory_search`,
|
|
153
|
+
`memory_register`, and `memory.*` at the protocol boundary because those names
|
|
154
|
+
are clearer to agents.
|
|
155
|
+
|
|
156
|
+
## Runtime Artifact Image
|
|
157
|
+
|
|
158
|
+
Daimon defines a local copy-only runtime artifact image build for Spawnfile:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm run image:runtime:local
|
|
162
|
+
```
|
|
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
|
+
|
|
170
|
+
This creates:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
noopolis/spawnfile-runtime-daimon:0.1.2-local
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The image is not a full organization image and is not intended to be run
|
|
177
|
+
directly. It contains only:
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
/opt/spawnfile/runtime-installs/daimon
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Spawnfile can copy that path into generated organization images:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
SPAWNFILE_DAIMON_RUNTIME_IMAGE=noopolis/spawnfile-runtime-daimon:0.1.2-local \
|
|
187
|
+
spawnfile build ./agentic-org
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This keeps mixed-runtime organizations composable: a generated image can copy
|
|
191
|
+
Daimon, OpenClaw, PicoClaw, or any future runtime artifact independently instead
|
|
192
|
+
of depending on one prebuilt image for every runtime combination.
|
|
@@ -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
|
+
}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -20,11 +20,30 @@ 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;
|
|
34
|
+
context?: {
|
|
35
|
+
networkId?: string;
|
|
36
|
+
roomId?: string;
|
|
37
|
+
teamId?: string;
|
|
38
|
+
taskId?: string;
|
|
39
|
+
roleId?: string;
|
|
40
|
+
from?: string;
|
|
41
|
+
pairPeers?: string[];
|
|
42
|
+
artifactPaths?: string[];
|
|
43
|
+
};
|
|
44
|
+
delivery?: WakeDeliveryMetadata;
|
|
45
|
+
/** Exact transport body retained outside the runtime-enriched model prompt. */
|
|
46
|
+
transportText?: string;
|
|
28
47
|
}
|
|
29
48
|
export interface WakeResult {
|
|
30
49
|
agentId: AgentId;
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -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;
|
|
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 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jungian-play-org.d.ts","sourceRoot":"","sources":["../../src/examples/jungian-play-org.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { JsonlMemoryStore } from "@noopolis/mneme";
|
|
5
|
+
import { OrgObserver } from "../observability/index.js";
|
|
6
|
+
import { beatsFor, defaultDialogueTurns, selectVoicesForBeat } from "./jungianConversationPlan.js";
|
|
7
|
+
import { exampleCausalId } from "./exampleCausalId.js";
|
|
8
|
+
import { JungianVoice, runLimited } from "./jungianPlayAgent.js";
|
|
9
|
+
import { jungianSelves, playScenario } from "./jungianProfiles.js";
|
|
10
|
+
import { JungianTrace, parseInnerUsed, parseSpeakLine } from "./jungianTrace.js";
|
|
11
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const daimonRoot = path.resolve(__dirname, "../..");
|
|
13
|
+
const runtimeRoot = path.join(daimonRoot, ".runtime", "jungian-play-org");
|
|
14
|
+
const runId = `run-${Date.now().toString(36)}`;
|
|
15
|
+
const councilConcurrency = Number.parseInt(process.env.DAIMON_JUNGIAN_COUNCIL_CONCURRENCY ?? "3", 10);
|
|
16
|
+
const dialogueTurnCount = Math.max(10, Number.parseInt(process.env.DAIMON_JUNGIAN_TURNS ?? String(defaultDialogueTurns), 10));
|
|
17
|
+
const voicesPerTurn = Math.max(1, Number.parseInt(process.env.DAIMON_JUNGIAN_VOICES_PER_TURN ?? "2", 10));
|
|
18
|
+
const observer = new OrgObserver({ orgId: "jungian-play-org", runId });
|
|
19
|
+
const trace = new JungianTrace({ runId, title: playScenario.title });
|
|
20
|
+
const roomContext = {
|
|
21
|
+
networkId: "jungian-sitcom",
|
|
22
|
+
roomId: "community-kitchen",
|
|
23
|
+
teamId: "jungian-play-org",
|
|
24
|
+
participants: jungianSelves.map((self) => self.representative.id)
|
|
25
|
+
};
|
|
26
|
+
const observeTurn = (turn) => {
|
|
27
|
+
observer.recordTurn({
|
|
28
|
+
agent: turn.voice.id,
|
|
29
|
+
engine: turn.voice.engine,
|
|
30
|
+
event: turn.event.id,
|
|
31
|
+
eventText: turn.event.text,
|
|
32
|
+
totalMs: turn.totalMs,
|
|
33
|
+
memoryPrepareMs: turn.memoryPrepareMs,
|
|
34
|
+
engineMs: turn.engineResult.durationMs,
|
|
35
|
+
memoryRecordMs: turn.memoryRecordMs,
|
|
36
|
+
promptChars: turn.engineResult.promptChars,
|
|
37
|
+
outputChars: turn.engineResult.outputChars,
|
|
38
|
+
outputText: turn.outputText,
|
|
39
|
+
recall: turn.recall
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const archetypeInstructions = (self, voice) => [
|
|
43
|
+
`You are ${voice.name}, the ${voice.archetype} voice inside ${self.name}.`,
|
|
44
|
+
`Agenda: ${voice.agenda}`,
|
|
45
|
+
`Fear: ${voice.fear}`,
|
|
46
|
+
`Gift: ${voice.gift}`,
|
|
47
|
+
`Wound: ${voice.wound}`,
|
|
48
|
+
"You are an inner counselor, not the public speaker.",
|
|
49
|
+
"Keep counsel psychologically specific but grounded in ordinary human behavior.",
|
|
50
|
+
"No mythic language, no grand symbols, no fantasy imagery.",
|
|
51
|
+
"Use recalled memory if the same conversation pattern returns."
|
|
52
|
+
];
|
|
53
|
+
const representativeInstructions = (self) => [
|
|
54
|
+
`You are ${self.representative.name}, the outward speaking Self for ${self.name}.`,
|
|
55
|
+
`Play role: ${self.playRole}`,
|
|
56
|
+
`Public mask: ${self.publicMask}`,
|
|
57
|
+
`Backstory: ${self.backstory}`,
|
|
58
|
+
`Core conflict: ${self.conflict}`,
|
|
59
|
+
`Secret want: ${self.secretWant}`,
|
|
60
|
+
`Style: ${self.representative.style}`,
|
|
61
|
+
"You speak externally after listening to inner archetypal counsel.",
|
|
62
|
+
"Sound like a real person in a grounded TV drama or workplace sitcom.",
|
|
63
|
+
"Use short, conversational lines. No speeches. No poetic metaphors.",
|
|
64
|
+
"Do not mention the machinery of prompts, engines, memory, or tests.",
|
|
65
|
+
"Return the requested SPEAK/STAGE/INNER_USED shape exactly."
|
|
66
|
+
];
|
|
67
|
+
const buildSelf = (profile) => ({
|
|
68
|
+
profile,
|
|
69
|
+
representative: new JungianVoice({
|
|
70
|
+
id: profile.representative.id,
|
|
71
|
+
name: profile.representative.name,
|
|
72
|
+
selfId: profile.id,
|
|
73
|
+
selfName: profile.name,
|
|
74
|
+
engine: profile.engine,
|
|
75
|
+
runtimeRoot,
|
|
76
|
+
instructions: representativeInstructions(profile)
|
|
77
|
+
}),
|
|
78
|
+
archetypes: profile.voices.map((voice) => new JungianVoice({
|
|
79
|
+
id: `${profile.id}-${voice.id}`,
|
|
80
|
+
name: voice.name,
|
|
81
|
+
selfId: profile.id,
|
|
82
|
+
selfName: profile.name,
|
|
83
|
+
archetype: voice.archetype,
|
|
84
|
+
engine: voice.engine,
|
|
85
|
+
runtimeRoot,
|
|
86
|
+
instructions: archetypeInstructions(profile, voice)
|
|
87
|
+
}))
|
|
88
|
+
});
|
|
89
|
+
const selves = jungianSelves.map(buildSelf);
|
|
90
|
+
const transcriptText = (transcript) => transcript.length === 0 ? "(no external dialogue yet)" : transcript.join("\n");
|
|
91
|
+
const councilPrompt = (self, focus, transcript) => [
|
|
92
|
+
`Scene: ${playScenario.title}`,
|
|
93
|
+
`Premise: ${playScenario.premise}`,
|
|
94
|
+
`Set: ${playScenario.openingImage}`,
|
|
95
|
+
"",
|
|
96
|
+
`Self under counsel: ${self.name}`,
|
|
97
|
+
`Current focus: ${focus}`,
|
|
98
|
+
"",
|
|
99
|
+
"External dialogue so far:",
|
|
100
|
+
transcriptText(transcript),
|
|
101
|
+
"",
|
|
102
|
+
"Respond as this archetype only.",
|
|
103
|
+
"Keep it plain and practical. No poetic stage images.",
|
|
104
|
+
"Use exactly this shape:",
|
|
105
|
+
"ARCHETYPE: <archetype name>",
|
|
106
|
+
"COUNSEL: <one short practical note>",
|
|
107
|
+
"RISK: <what could go wrong emotionally>",
|
|
108
|
+
"LINE_NOTE: <what the representative should sound like>"
|
|
109
|
+
].join("\n");
|
|
110
|
+
const representativePrompt = (self, focus, transcript, counsel) => [
|
|
111
|
+
`Scene: ${playScenario.title}`,
|
|
112
|
+
`Premise: ${playScenario.premise}`,
|
|
113
|
+
`Set: ${playScenario.openingImage}`,
|
|
114
|
+
"",
|
|
115
|
+
"External dialogue so far:",
|
|
116
|
+
transcriptText(transcript),
|
|
117
|
+
"",
|
|
118
|
+
`Current focus: ${focus}`,
|
|
119
|
+
"",
|
|
120
|
+
"Inner council counsel:",
|
|
121
|
+
...counsel.map((turn) => `- ${turn.voice.id}: ${turn.outputText.replace(/\n/g, " ")}`),
|
|
122
|
+
"",
|
|
123
|
+
"Choose one natural next line of dialogue.",
|
|
124
|
+
"The line must sound like a normal person, not a symbol or narrator.",
|
|
125
|
+
"Keep SPEAK under 22 words. Avoid words like ledger, mercy, truth, blood, crown, soul, destiny, wound unless the transcript already used them.",
|
|
126
|
+
"Do not use Markdown, bullets, bold markers, or quotation marks inside SPEAK.",
|
|
127
|
+
"Use exactly this shape:",
|
|
128
|
+
"SPEAK: <one natural spoken line, without wrapping quotation marks>",
|
|
129
|
+
"STAGE: <one tiny normal action>",
|
|
130
|
+
`INNER_USED: <comma-separated ids from ${self.voices.map((voice) => voice.id).join(", ")}>`
|
|
131
|
+
].join("\n");
|
|
132
|
+
const runCouncil = async (self, eventId, focus, transcript, voices) => {
|
|
133
|
+
console.log(`\n== ${self.profile.name} inner council: ${focus} ==`);
|
|
134
|
+
const turns = await runLimited(voices, councilConcurrency, async (voice) => {
|
|
135
|
+
const event = {
|
|
136
|
+
id: exampleCausalId(`${eventId}-${voice.config.id}`),
|
|
137
|
+
kind: "manual",
|
|
138
|
+
context: roomContext,
|
|
139
|
+
text: councilPrompt(self.profile, focus, transcript)
|
|
140
|
+
};
|
|
141
|
+
const turn = await voice.wake(event);
|
|
142
|
+
observeTurn(turn);
|
|
143
|
+
trace.addCounsel({
|
|
144
|
+
archetype: voice.config.archetype ?? "unknown",
|
|
145
|
+
engine: voice.config.engine,
|
|
146
|
+
event: event.id,
|
|
147
|
+
output: turn.outputText,
|
|
148
|
+
recallSelected: turn.recall.selectedEventIds.length,
|
|
149
|
+
self: self.profile.name,
|
|
150
|
+
voice: voice.config.id
|
|
151
|
+
});
|
|
152
|
+
console.log(`${voice.config.id}: ${turn.outputText.split("\n")[0]}`);
|
|
153
|
+
return turn;
|
|
154
|
+
});
|
|
155
|
+
return turns;
|
|
156
|
+
};
|
|
157
|
+
const runRepresentative = async (self, eventId, focus, transcript, counsel) => {
|
|
158
|
+
const event = {
|
|
159
|
+
id: exampleCausalId(eventId),
|
|
160
|
+
kind: "manual",
|
|
161
|
+
context: roomContext,
|
|
162
|
+
text: representativePrompt(self.profile, focus, transcript, counsel)
|
|
163
|
+
};
|
|
164
|
+
const turn = await self.representative.wake(event);
|
|
165
|
+
observeTurn(turn);
|
|
166
|
+
const used = parseInnerUsed(turn.outputText);
|
|
167
|
+
const selectedVoiceIds = new Set(counsel.flatMap((entry) => [
|
|
168
|
+
entry.voice.id,
|
|
169
|
+
entry.voice.id.replace(`${self.profile.id}-`, "")
|
|
170
|
+
]));
|
|
171
|
+
const passed = used.some((voiceId) => selectedVoiceIds.has(voiceId));
|
|
172
|
+
observer.recordAssertion({
|
|
173
|
+
detail: `${self.profile.representative.id} should declare at least one selected inner voice used`,
|
|
174
|
+
event: event.id,
|
|
175
|
+
kind: "consultation",
|
|
176
|
+
passed
|
|
177
|
+
});
|
|
178
|
+
if (!passed) {
|
|
179
|
+
throw new Error(`${self.profile.representative.id} did not declare a selected INNER_USED voice:\n${turn.outputText}`);
|
|
180
|
+
}
|
|
181
|
+
trace.addDialogue({
|
|
182
|
+
engine: self.profile.engine,
|
|
183
|
+
event: event.id,
|
|
184
|
+
innerUsed: used,
|
|
185
|
+
output: turn.outputText,
|
|
186
|
+
recallSelected: turn.recall.selectedEventIds.length,
|
|
187
|
+
self: self.profile.name,
|
|
188
|
+
speaker: self.profile.representative.name
|
|
189
|
+
});
|
|
190
|
+
const line = `${self.profile.name}: ${parseSpeakLine(turn.outputText)}`;
|
|
191
|
+
transcript.push(line);
|
|
192
|
+
console.log(`\n${line}`);
|
|
193
|
+
return line;
|
|
194
|
+
};
|
|
195
|
+
const prepareAll = async () => {
|
|
196
|
+
await rm(runtimeRoot, { recursive: true, force: true });
|
|
197
|
+
await Promise.all(selves.flatMap((self) => [
|
|
198
|
+
self.representative.prepare(),
|
|
199
|
+
...self.archetypes.map((voice) => voice.prepare())
|
|
200
|
+
]));
|
|
201
|
+
await writeFile(path.join(runtimeRoot, "org.json"), JSON.stringify({
|
|
202
|
+
scenario: playScenario,
|
|
203
|
+
selves: jungianSelves.map((self) => ({
|
|
204
|
+
id: self.id,
|
|
205
|
+
name: self.name,
|
|
206
|
+
engine: self.engine,
|
|
207
|
+
representative: self.representative,
|
|
208
|
+
voices: self.voices.map((voice) => ({
|
|
209
|
+
id: voice.id,
|
|
210
|
+
archetype: voice.archetype,
|
|
211
|
+
engine: voice.engine,
|
|
212
|
+
name: voice.name
|
|
213
|
+
}))
|
|
214
|
+
}))
|
|
215
|
+
}, null, 2));
|
|
216
|
+
};
|
|
217
|
+
const writeMemoryCounts = async () => {
|
|
218
|
+
const rows = await Promise.all(selves.flatMap((self) => [
|
|
219
|
+
self.representative,
|
|
220
|
+
...self.archetypes
|
|
221
|
+
]).map(async (voice) => {
|
|
222
|
+
const events = await new JsonlMemoryStore(voice.runtimeHomePath).read();
|
|
223
|
+
const counts = events.reduce((memo, event) => {
|
|
224
|
+
memo[event.type] = (memo[event.type] ?? 0) + 1;
|
|
225
|
+
return memo;
|
|
226
|
+
}, {});
|
|
227
|
+
return {
|
|
228
|
+
voice: voice.config.id,
|
|
229
|
+
self: voice.config.selfId,
|
|
230
|
+
engine: voice.config.engine,
|
|
231
|
+
counts
|
|
232
|
+
};
|
|
233
|
+
}));
|
|
234
|
+
await writeFile(path.join(runtimeRoot, "play-memory-counts.jsonl"), `${rows.map((row) => JSON.stringify(row)).join("\n")}\n`);
|
|
235
|
+
};
|
|
236
|
+
const writePlaySummary = async () => {
|
|
237
|
+
const behavior = observer.behaviorSummary();
|
|
238
|
+
const byRole = observer.turns.reduce((memo, turn) => {
|
|
239
|
+
const role = turn.agent.endsWith("-self") ? "representative" : "archetype";
|
|
240
|
+
const current = memo[role] ?? { count: 0, engineMs: 0, recallSelected: 0 };
|
|
241
|
+
current.count += 1;
|
|
242
|
+
current.engineMs += turn.engineMs;
|
|
243
|
+
current.recallSelected += turn.recallSelected;
|
|
244
|
+
memo[role] = current;
|
|
245
|
+
return memo;
|
|
246
|
+
}, {});
|
|
247
|
+
await writeFile(path.join(runtimeRoot, "play-summary.json"), `${JSON.stringify({ behavior, by_role: byRole, run_id: runId, schema: "daimon.jungian-play.summary/v1" }, null, 2)}\n`);
|
|
248
|
+
};
|
|
249
|
+
const run = async () => {
|
|
250
|
+
await prepareAll();
|
|
251
|
+
const selfById = new Map(selves.map((self) => [self.profile.id, self]));
|
|
252
|
+
const transcript = [];
|
|
253
|
+
const beats = beatsFor(dialogueTurnCount);
|
|
254
|
+
for (const [index, beat] of beats.entries()) {
|
|
255
|
+
const self = selfById.get(beat.speakerId);
|
|
256
|
+
if (!self) {
|
|
257
|
+
throw new Error(`Unknown Jungian self ${beat.speakerId}`);
|
|
258
|
+
}
|
|
259
|
+
const selectedProfiles = selectVoicesForBeat(self.profile, index, voicesPerTurn);
|
|
260
|
+
const selectedIds = new Set(selectedProfiles.map((voice) => `${self.profile.id}-${voice.id}`));
|
|
261
|
+
const selectedVoices = self.archetypes.filter((voice) => selectedIds.has(voice.config.id));
|
|
262
|
+
const eventBase = `${self.profile.id}-turn-${String(index + 1).padStart(2, "0")}`;
|
|
263
|
+
const counsel = await runCouncil(self, `${eventBase}-council`, beat.focus, transcript, selectedVoices);
|
|
264
|
+
await runRepresentative(self, `${eventBase}-speaks`, beat.focus, transcript, counsel);
|
|
265
|
+
}
|
|
266
|
+
await observer.write(runtimeRoot);
|
|
267
|
+
await trace.write(runtimeRoot);
|
|
268
|
+
await writeMemoryCounts();
|
|
269
|
+
await writePlaySummary();
|
|
270
|
+
console.log("\nExternal dialogue:");
|
|
271
|
+
for (const line of transcript) {
|
|
272
|
+
console.log(line);
|
|
273
|
+
}
|
|
274
|
+
console.log(`\nTrace: ${path.join(runtimeRoot, "jungian-trace.md")}`);
|
|
275
|
+
console.log(`Telemetry: ${path.join(runtimeRoot, "trace.md")}`);
|
|
276
|
+
console.log("\ne2e:jungian-play-org ok");
|
|
277
|
+
};
|
|
278
|
+
run().catch((error) => {
|
|
279
|
+
console.error(error instanceof Error ? error.stack ?? error.message : String(error));
|
|
280
|
+
process.exitCode = 1;
|
|
281
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jungian-triad-org.d.ts","sourceRoot":"","sources":["../../src/examples/jungian-triad-org.ts"],"names":[],"mappings":""}
|