@josharsh/demon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/actions/portable.d.ts +4 -0
  4. package/dist/actions/portable.d.ts.map +1 -0
  5. package/dist/actions/portable.js +40 -0
  6. package/dist/actions/portable.js.map +1 -0
  7. package/dist/index.d.ts +17 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +26 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/llm/providers.d.ts +4 -0
  12. package/dist/llm/providers.d.ts.map +1 -0
  13. package/dist/llm/providers.js +163 -0
  14. package/dist/llm/providers.js.map +1 -0
  15. package/dist/loop.d.ts +16 -0
  16. package/dist/loop.d.ts.map +1 -0
  17. package/dist/loop.js +142 -0
  18. package/dist/loop.js.map +1 -0
  19. package/dist/memory/episodes.d.ts +12 -0
  20. package/dist/memory/episodes.d.ts.map +1 -0
  21. package/dist/memory/episodes.js +50 -0
  22. package/dist/memory/episodes.js.map +1 -0
  23. package/dist/memory/facts.d.ts +3 -0
  24. package/dist/memory/facts.d.ts.map +1 -0
  25. package/dist/memory/facts.js +98 -0
  26. package/dist/memory/facts.js.map +1 -0
  27. package/dist/memory/manager.d.ts +14 -0
  28. package/dist/memory/manager.d.ts.map +1 -0
  29. package/dist/memory/manager.js +113 -0
  30. package/dist/memory/manager.js.map +1 -0
  31. package/dist/memory/narrative.d.ts +8 -0
  32. package/dist/memory/narrative.d.ts.map +1 -0
  33. package/dist/memory/narrative.js +37 -0
  34. package/dist/memory/narrative.js.map +1 -0
  35. package/dist/platform/memory-kv.d.ts +3 -0
  36. package/dist/platform/memory-kv.d.ts.map +1 -0
  37. package/dist/platform/memory-kv.js +24 -0
  38. package/dist/platform/memory-kv.js.map +1 -0
  39. package/dist/reasoning.d.ts +22 -0
  40. package/dist/reasoning.d.ts.map +1 -0
  41. package/dist/reasoning.js +104 -0
  42. package/dist/reasoning.js.map +1 -0
  43. package/dist/types.d.ts +144 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +9 -0
  46. package/dist/types.js.map +1 -0
  47. package/dist/util/time.d.ts +9 -0
  48. package/dist/util/time.d.ts.map +1 -0
  49. package/dist/util/time.js +38 -0
  50. package/dist/util/time.js.map +1 -0
  51. package/package.json +39 -0
@@ -0,0 +1,98 @@
1
+ // ============================================================================
2
+ // Bi-temporal facts store — pure JS, portable, persisted via KVStore.
3
+ //
4
+ // Research-backed (Zep/Graphiti, ATOM): contradictions are resolved as TEMPORAL
5
+ // operations, not deletions. When a fact's value changes, the old fact's
6
+ // validity interval is closed (valid_until set) and a new fact opened. History
7
+ // is preserved; nothing drifts.
8
+ //
9
+ // No native dependency. For a demon tracking dozens of entities, an in-memory
10
+ // array persisted as JSON is more than sufficient — and runs in any runtime.
11
+ // ============================================================================
12
+ let idCounter = 0;
13
+ function generateId(now) {
14
+ // Deterministic-enough unique id without Date.now()/random (keeps core pure).
15
+ idCounter += 1;
16
+ return `${now}-${idCounter.toString(36)}`;
17
+ }
18
+ export async function createFactsStore(kv, key = 'facts.json') {
19
+ let facts = [];
20
+ const raw = await kv.read(key);
21
+ if (raw) {
22
+ try {
23
+ facts = JSON.parse(raw);
24
+ }
25
+ catch {
26
+ facts = [];
27
+ }
28
+ }
29
+ function persist() {
30
+ // Fire-and-forget; the demon re-persists every cycle so a dropped write
31
+ // self-heals on the next observation.
32
+ void kv.write(key, JSON.stringify(facts));
33
+ }
34
+ function upsert(fact) {
35
+ const now = Date.parse(fact.observed_at) || 0;
36
+ if (fact.confidence >= 0.5) {
37
+ const existing = facts.find(f => f.entity === fact.entity && f.relation === fact.relation && f.valid_until === null);
38
+ if (existing) {
39
+ if (existing.value === fact.value) {
40
+ // Same fact observed again — reinforce confidence (cap 1.0).
41
+ existing.confidence = Math.min(1.0, existing.confidence + 0.1);
42
+ existing.observed_at = fact.observed_at;
43
+ persist();
44
+ return;
45
+ }
46
+ // Different value — close the existing fact (temporal invalidation).
47
+ existing.valid_until = fact.observed_at;
48
+ existing.invalidated_at = fact.observed_at;
49
+ }
50
+ }
51
+ facts.push({ id: generateId(now), ...fact });
52
+ persist();
53
+ }
54
+ function getCurrent(entity, relation) {
55
+ return facts
56
+ .filter(f => f.entity === entity &&
57
+ f.valid_until === null &&
58
+ (relation === undefined || f.relation === relation))
59
+ .sort((a, b) => b.confidence - a.confidence);
60
+ }
61
+ function getHistory(entity) {
62
+ return facts
63
+ .filter(f => f.entity === entity)
64
+ .sort((a, b) => (a.valid_from < b.valid_from ? 1 : -1));
65
+ }
66
+ function getAllCurrent() {
67
+ return facts
68
+ .filter(f => f.valid_until === null)
69
+ .sort((a, b) => {
70
+ if (a.entity !== b.entity)
71
+ return a.entity < b.entity ? -1 : 1;
72
+ if (a.relation !== b.relation)
73
+ return a.relation < b.relation ? -1 : 1;
74
+ return b.confidence - a.confidence;
75
+ });
76
+ }
77
+ function invalidate(entity, relation, value) {
78
+ const stamp = new Date(0).toISOString(); // placeholder; callers pass via upsert normally
79
+ let changed = false;
80
+ for (const f of facts) {
81
+ if (f.entity === entity &&
82
+ f.relation === relation &&
83
+ f.value === value &&
84
+ f.valid_until === null) {
85
+ f.valid_until = f.observed_at || stamp;
86
+ f.invalidated_at = f.observed_at || stamp;
87
+ changed = true;
88
+ }
89
+ }
90
+ if (changed)
91
+ persist();
92
+ }
93
+ function close() {
94
+ persist();
95
+ }
96
+ return { upsert, getCurrent, getHistory, getAllCurrent, invalidate, close };
97
+ }
98
+ //# sourceMappingURL=facts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facts.js","sourceRoot":"","sources":["../../src/memory/facts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { LLMProvider, DemonManifest, MemoryEntry, Observation, Fact, KVStore } from '../types.js';
2
+ export interface MemoryContext {
3
+ narrative: string;
4
+ recentEpisodes: string;
5
+ relevantFacts: string;
6
+ }
7
+ export interface MemoryManager {
8
+ recordCycle(entry: MemoryEntry): Promise<void>;
9
+ buildContext(currentObservations: Observation[]): Promise<MemoryContext>;
10
+ close(): void;
11
+ }
12
+ export declare function createMemoryManager(kv: KVStore, manifest: DemonManifest, llm: LLMProvider): Promise<MemoryManager>;
13
+ export declare function extractFacts(observations: Observation[], cycleNumber: number): Array<Omit<Fact, 'id'>>;
14
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/memory/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAejG,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,YAAY,CAAC,mBAAmB,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACxE,KAAK,IAAI,IAAI,CAAA;CACd;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,OAAO,EACX,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,aAAa,CAAC,CAgExB;AAsBD,wBAAgB,YAAY,CAC1B,YAAY,EAAE,WAAW,EAAE,EAC3B,WAAW,EAAE,MAAM,GAClB,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CA2BzB"}
@@ -0,0 +1,113 @@
1
+ import { createFactsStore } from './facts.js';
2
+ import { createNarrativeManager } from './narrative.js';
3
+ import { createEpisodeStore } from './episodes.js';
4
+ export async function createMemoryManager(kv, manifest, llm) {
5
+ const facts = await createFactsStore(kv);
6
+ const narrative = createNarrativeManager(kv);
7
+ const episodes = createEpisodeStore(kv);
8
+ const episodeBuffer = [];
9
+ async function recordCycle(entry) {
10
+ // 1. Episode layer — persist the raw cycle record.
11
+ await episodes.append(entry);
12
+ // 2. Facts layer — extract entity/relation/value facts generically.
13
+ for (const fact of extractFacts(entry.observations, entry.cycleNumber)) {
14
+ facts.upsert(fact);
15
+ }
16
+ // 3. Narrative layer — buffer for periodic compression.
17
+ episodeBuffer.push(entry);
18
+ if (narrative.shouldUpdate(entry.cycleNumber)) {
19
+ const batch = episodeBuffer.splice(0, episodeBuffer.length);
20
+ await narrative.update(llm, manifest, batch);
21
+ }
22
+ }
23
+ async function buildContext(currentObservations) {
24
+ const narrativeText = await narrative.read();
25
+ const recent = await episodes.getRecent(3);
26
+ let recentEpisodes = 'No prior history.';
27
+ if (recent.length > 0) {
28
+ recentEpisodes = recent
29
+ .map(e => {
30
+ const obs = e.observations.map(o => ` [${o.watcherType}] ${o.summary}`).join('\n');
31
+ const action = e.actionFired
32
+ ? ` Action: ${e.actionFired.provider}.${e.actionFired.action}${e.actionFired.dryRun ? ' (dry-run)' : ''}${e.actionFired.error ? ' [FAILED]' : ' [OK]'}`
33
+ : ' No action.';
34
+ return `Cycle #${e.cycleNumber} → ${e.decision.decision.toUpperCase()}: ${e.decision.reasoning.slice(0, 200)}\n${obs}\n${action}`;
35
+ })
36
+ .join('\n\n');
37
+ }
38
+ const entities = extractEntities(currentObservations);
39
+ let relevantFacts = 'No tracked entity states.';
40
+ const collected = entities.length > 0
41
+ ? entities.flatMap(e => facts.getCurrent(e))
42
+ : facts.getAllCurrent();
43
+ if (collected.length > 0) {
44
+ relevantFacts = collected
45
+ .map(f => `${f.entity}.${f.relation} = ${f.value} (confidence: ${f.confidence.toFixed(2)}, since: ${f.valid_from})`)
46
+ .join('\n');
47
+ }
48
+ return { narrative: narrativeText, recentEpisodes, relevantFacts };
49
+ }
50
+ function close() {
51
+ facts.close();
52
+ }
53
+ return { recordCycle, buildContext, close };
54
+ }
55
+ // ─── Generic fact extraction — no domain knowledge ───────────────────────────
56
+ // Derives entity + scalar state from the SHAPE of an observation, never its
57
+ // meaning. Works for any watcher: PRs, endpoints, paths, anything future.
58
+ const ID_FIELDS = ['id', 'number', 'name', 'key', 'path', 'url', 'repo', 'sha', 'title'];
59
+ function deriveEntityId(obs) {
60
+ const data = obs.data;
61
+ if (typeof data.owner === 'string' && typeof data.repo === 'string') {
62
+ const sub = data.number ?? data.id ?? data.sha;
63
+ return sub !== undefined ? `${data.owner}/${data.repo}#${sub}` : `${data.owner}/${data.repo}`;
64
+ }
65
+ for (const field of ID_FIELDS) {
66
+ const v = data[field];
67
+ if (typeof v === 'string' && v.trim() !== '')
68
+ return v;
69
+ if (typeof v === 'number')
70
+ return `${field}:${v}`;
71
+ }
72
+ return String(obs.watcherType);
73
+ }
74
+ export function extractFacts(observations, cycleNumber) {
75
+ const out = [];
76
+ for (const obs of observations) {
77
+ const entity = deriveEntityId(obs);
78
+ const now = obs.timestamp || new Date(0).toISOString();
79
+ for (const [relation, raw] of Object.entries(obs.data)) {
80
+ if (ID_FIELDS.includes(relation) || relation === 'owner')
81
+ continue;
82
+ let value;
83
+ if (typeof raw === 'string')
84
+ value = raw;
85
+ else if (typeof raw === 'number' || typeof raw === 'boolean')
86
+ value = String(raw);
87
+ else
88
+ continue;
89
+ if (value.trim() === '' || value.length > 500)
90
+ continue;
91
+ out.push({
92
+ entity,
93
+ relation,
94
+ value,
95
+ confidence: 1.0,
96
+ observed_at: now,
97
+ valid_from: now,
98
+ valid_until: null,
99
+ invalidated_at: null,
100
+ source_cycle: cycleNumber,
101
+ source_watcher: String(obs.watcherType),
102
+ });
103
+ }
104
+ }
105
+ return out;
106
+ }
107
+ function extractEntities(observations) {
108
+ const set = new Set();
109
+ for (const obs of observations)
110
+ set.add(deriveEntityId(obs));
111
+ return Array.from(set);
112
+ }
113
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/memory/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { LLMProvider, DemonManifest, MemoryEntry, KVStore } from '../types.js';
2
+ export interface NarrativeManager {
3
+ read(): Promise<string>;
4
+ update(llm: LLMProvider, manifest: DemonManifest, newEpisodes: MemoryEntry[]): Promise<void>;
5
+ shouldUpdate(cycleNumber: number): boolean;
6
+ }
7
+ export declare function createNarrativeManager(kv: KVStore, key?: string): NarrativeManager;
8
+ //# sourceMappingURL=narrative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrative.d.ts","sourceRoot":"","sources":["../../src/memory/narrative.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAc,OAAO,EAAE,MAAM,aAAa,CAAA;AAQ1F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IACvB,MAAM,CACJ,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,WAAW,EAAE,GACzB,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3C;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,SAAkB,GAAG,gBAAgB,CAiD3F"}
@@ -0,0 +1,37 @@
1
+ export function createNarrativeManager(kv, key = 'narrative.txt') {
2
+ async function read() {
3
+ return (await kv.read(key)) ?? '';
4
+ }
5
+ async function update(llm, manifest, newEpisodes) {
6
+ const current = await read();
7
+ const episodesSummary = newEpisodes
8
+ .map(e => {
9
+ const obsSummaries = e.observations.map(o => ` [${o.watcherType}] ${o.summary}`).join('\n');
10
+ const actionNote = e.actionFired
11
+ ? ` Action fired: ${e.actionFired.provider}.${e.actionFired.action}${e.actionFired.dryRun ? ' (dry-run)' : ''}${e.actionFired.error ? ` [FAILED: ${e.actionFired.error}]` : ''}`
12
+ : ' No action taken.';
13
+ return `Cycle #${e.cycleNumber} [${e.timestamp}]\n${obsSummaries}\n Decision: ${e.decision.decision.toUpperCase()} — ${e.decision.reasoning}\n${actionNote}`;
14
+ })
15
+ .join('\n\n');
16
+ const prompt = `You are maintaining a running summary of your domain as a persistent daemon named ${manifest.name}.
17
+ Your purpose: ${manifest.purpose}
18
+
19
+ Current summary (update this, don't replace wholesale):
20
+ ${current || '(no summary yet — this is the first update)'}
21
+
22
+ New observations from the last cycles:
23
+ ${episodesSummary || '(no new episodes)'}
24
+
25
+ Update the summary to reflect new information. Keep it under 500 words.
26
+ Structure: ENTITIES (current state of things you watch), PATTERNS (behavioral patterns you've noticed), LAST ACTED (when and why you last fired an action).
27
+ Return ONLY the updated summary text, no preamble.`;
28
+ const messages = [{ role: 'user', content: prompt }];
29
+ const updated = await llm.call(messages, 'You are a concise summarizer maintaining a persistent daemon memory.');
30
+ await kv.write(key, updated.trim());
31
+ }
32
+ function shouldUpdate(cycleNumber) {
33
+ return cycleNumber > 0 && cycleNumber % 10 === 0;
34
+ }
35
+ return { read, update, shouldUpdate };
36
+ }
37
+ //# sourceMappingURL=narrative.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrative.js","sourceRoot":"","sources":["../../src/memory/narrative.ts"],"names":[],"mappings":"AAkBA,MAAM,UAAU,sBAAsB,CAAC,EAAW,EAAE,GAAG,GAAG,eAAe;IACvE,KAAK,UAAU,IAAI;QACjB,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IACnC,CAAC;IAED,KAAK,UAAU,MAAM,CACnB,GAAgB,EAChB,QAAuB,EACvB,WAA0B;QAE1B,MAAM,OAAO,GAAG,MAAM,IAAI,EAAE,CAAA;QAE5B,MAAM,eAAe,GAAG,WAAW;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE;YACP,MAAM,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC5F,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW;gBAC9B,CAAC,CAAC,mBAAmB,CAAC,CAAC,WAAW,CAAC,QAAQ,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACjL,CAAC,CAAC,oBAAoB,CAAA;YACxB,OAAO,UAAU,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,SAAS,MAAM,YAAY,iBAAiB,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,KAAK,UAAU,EAAE,CAAA;QAC/J,CAAC,CAAC;aACD,IAAI,CAAC,MAAM,CAAC,CAAA;QAEf,MAAM,MAAM,GAAG,qFAAqF,QAAQ,CAAC,IAAI;gBACrG,QAAQ,CAAC,OAAO;;;EAG9B,OAAO,IAAI,6CAA6C;;;EAGxD,eAAe,IAAI,mBAAmB;;;;mDAIW,CAAA;QAE/C,MAAM,QAAQ,GAAiB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;QAClE,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,CAC5B,QAAQ,EACR,sEAAsE,CACvE,CAAA;QAED,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACrC,CAAC;IAED,SAAS,YAAY,CAAC,WAAmB;QACvC,OAAO,WAAW,GAAG,CAAC,IAAI,WAAW,GAAG,EAAE,KAAK,CAAC,CAAA;IAClD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;AACvC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { KVStore } from '../types.js';
2
+ export declare function createMemoryKV(): KVStore;
3
+ //# sourceMappingURL=memory-kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-kv.d.ts","sourceRoot":"","sources":["../../src/platform/memory-kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAKrC,wBAAgB,cAAc,IAAI,OAAO,CAmBxC"}
@@ -0,0 +1,24 @@
1
+ // An in-memory KVStore. Zero dependencies, works everywhere. Used as the
2
+ // default/ephemeral store and in tests. Hosts provide durable implementations
3
+ // (CLI → filesystem, browser → IndexedDB) implementing the same interface.
4
+ export function createMemoryKV() {
5
+ const store = new Map();
6
+ return {
7
+ async read(key) {
8
+ return store.has(key) ? store.get(key) : null;
9
+ },
10
+ async write(key, value) {
11
+ store.set(key, value);
12
+ },
13
+ async append(key, line) {
14
+ const prev = store.get(key) ?? '';
15
+ store.set(key, prev + line + '\n');
16
+ },
17
+ async readLines(key, lastN) {
18
+ const content = store.get(key) ?? '';
19
+ const lines = content.split('\n').filter(Boolean);
20
+ return typeof lastN === 'number' ? lines.slice(-lastN) : lines;
21
+ },
22
+ };
23
+ }
24
+ //# sourceMappingURL=memory-kv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-kv.js","sourceRoot":"","sources":["../../src/platform/memory-kv.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,8EAA8E;AAC9E,2EAA2E;AAC3E,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,GAAW;YACpB,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAChD,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,KAAa;YACpC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACvB,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,IAAY;YACpC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;YACjC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAA;QACpC,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,KAAc;YACzC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;YACpC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YACjD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAChE,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { LLMDecision } from './types.js';
2
+ /**
3
+ * Build the full demon reasoning prompt. Returns systemPrompt + separator +
4
+ * userPrompt joined; callers split on SEPARATOR to feed each part correctly.
5
+ */
6
+ export declare function buildDemonPrompt(purpose: string, contextSummary: string, observations: Array<{
7
+ watcherType: string;
8
+ summary: string;
9
+ data: Record<string, unknown>;
10
+ }>): string;
11
+ /** Split a built prompt back into its system and user halves. */
12
+ export declare function splitPrompt(combined: string): {
13
+ systemPrompt: string;
14
+ userContent: string;
15
+ };
16
+ /**
17
+ * Robustly parse an LLM response into an LLMDecision.
18
+ * Handles markdown code fences, leading/trailing prose, and malformed output
19
+ * (falls back to a safe "wait").
20
+ */
21
+ export declare function parseLLMDecision(raw: string): LLMDecision;
22
+ //# sourceMappingURL=reasoning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning.d.ts","sourceRoot":"","sources":["../src/reasoning.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAmBxC;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GAC3F,MAAM,CAkCR;AAED,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAY3F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAwCzD"}
@@ -0,0 +1,104 @@
1
+ // ============================================================================
2
+ // Reasoning — pure prompt construction + decision parsing.
3
+ // No platform deps. This is the demon's "how do I think about a cycle" layer.
4
+ // ============================================================================
5
+ const LLM_DECISION_SCHEMA = `{
6
+ "decision": "act" | "wait",
7
+ "reasoning": string, // 1-3 sentences, must reference specific observations
8
+ "action": { // ONLY include when decision is "act"
9
+ "provider": string, // one of the available action providers
10
+ "action": string, // provider-specific action name
11
+ "params": object // complete, actionable params — no placeholders
12
+ }
13
+ }`;
14
+ const SEPARATOR = '\n\n===USER===\n';
15
+ /**
16
+ * Build the full demon reasoning prompt. Returns systemPrompt + separator +
17
+ * userPrompt joined; callers split on SEPARATOR to feed each part correctly.
18
+ */
19
+ export function buildDemonPrompt(purpose, contextSummary, observations) {
20
+ const systemPrompt = `You are a Demon — a persistent AI reasoning process with a defined purpose.
21
+ You are NOT a task executor. You are a continuous observer and reasoner.
22
+ You observe the world, reason about it in the context of your purpose, and decide whether to act.
23
+
24
+ Your response MUST be valid JSON matching this exact schema:
25
+ ${LLM_DECISION_SCHEMA}
26
+
27
+ Rules:
28
+ - Prefer "wait" when nothing meaningful has changed relative to your purpose
29
+ - Prefer "act" only when something genuinely warrants a response given your purpose
30
+ - Your reasoning must reference specific observations, not be generic
31
+ - Params must be complete and actionable — do not use placeholders
32
+ - Respond ONLY with a single JSON object — no explanation, no code fences, no prose`;
33
+ const observationText = observations.length > 0
34
+ ? observations
35
+ .map(obs => `[${obs.watcherType}] ${obs.summary}\nData: ${JSON.stringify(obs.data, null, 2)}`)
36
+ .join('\n\n---\n\n')
37
+ : 'No observations available this cycle.';
38
+ const userPrompt = `Purpose: ${purpose}
39
+
40
+ ${contextSummary}
41
+
42
+ Current observations:
43
+ ${observationText}
44
+
45
+ Reason about whether to act based on your purpose and the observations above.`;
46
+ return [systemPrompt, userPrompt].join(SEPARATOR);
47
+ }
48
+ /** Split a built prompt back into its system and user halves. */
49
+ export function splitPrompt(combined) {
50
+ const idx = combined.indexOf(SEPARATOR);
51
+ if (idx === -1) {
52
+ return {
53
+ systemPrompt: combined,
54
+ userContent: 'Reason about whether to act based on your purpose and the observations above.',
55
+ };
56
+ }
57
+ return {
58
+ systemPrompt: combined.slice(0, idx),
59
+ userContent: combined.slice(idx + SEPARATOR.length),
60
+ };
61
+ }
62
+ /**
63
+ * Robustly parse an LLM response into an LLMDecision.
64
+ * Handles markdown code fences, leading/trailing prose, and malformed output
65
+ * (falls back to a safe "wait").
66
+ */
67
+ export function parseLLMDecision(raw) {
68
+ let cleaned = raw.trim();
69
+ const fenceMatch = cleaned.match(/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/m);
70
+ if (fenceMatch)
71
+ cleaned = fenceMatch[1].trim();
72
+ const jsonStart = cleaned.indexOf('{');
73
+ const jsonEnd = cleaned.lastIndexOf('}');
74
+ if (jsonStart !== -1 && jsonEnd !== -1 && jsonStart < jsonEnd) {
75
+ cleaned = cleaned.slice(jsonStart, jsonEnd + 1);
76
+ }
77
+ let parsed;
78
+ try {
79
+ parsed = JSON.parse(cleaned);
80
+ }
81
+ catch {
82
+ return {
83
+ decision: 'wait',
84
+ reasoning: `LLM returned unparseable response: ${raw.slice(0, 200)}`,
85
+ };
86
+ }
87
+ const p = parsed;
88
+ const decision = p.decision === 'act' ? 'act' : 'wait';
89
+ const reasoning = typeof p.reasoning === 'string' ? p.reasoning : 'No reasoning provided.';
90
+ if (decision === 'act' && p.action && typeof p.action === 'object') {
91
+ const a = p.action;
92
+ return {
93
+ decision: 'act',
94
+ reasoning,
95
+ action: {
96
+ provider: String(a.provider ?? ''),
97
+ action: String(a.action ?? ''),
98
+ params: a.params ?? {},
99
+ },
100
+ };
101
+ }
102
+ return { decision: 'wait', reasoning };
103
+ }
104
+ //# sourceMappingURL=reasoning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning.js","sourceRoot":"","sources":["../src/reasoning.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ export interface DemonManifest {
2
+ name: string;
3
+ purpose: string;
4
+ watch: WatcherConfig[];
5
+ interval: string;
6
+ actions: ActionConfig[];
7
+ model: string;
8
+ action_mode: ActionMode;
9
+ memory_path?: string;
10
+ }
11
+ export type ActionMode = 'dry_run' | 'cautious' | 'auto';
12
+ export interface WatcherConfig {
13
+ type: WatcherType;
14
+ repo?: string;
15
+ url?: string;
16
+ path?: string;
17
+ headers?: Record<string, string>;
18
+ branch?: string;
19
+ }
20
+ export type WatcherType = 'github_prs' | 'github_ci' | 'github_commits' | 'http' | 'filesystem';
21
+ export interface ActionConfig {
22
+ provider: string;
23
+ action: string;
24
+ on?: string;
25
+ channel?: string;
26
+ url?: string;
27
+ method?: string;
28
+ script?: string;
29
+ path?: string;
30
+ label?: string;
31
+ }
32
+ export type DemonStatus = 'running' | 'paused' | 'stopped' | 'error' | 'starting';
33
+ export interface DemonState {
34
+ pid: number;
35
+ name: string;
36
+ manifestPath: string;
37
+ startedAt: string;
38
+ cycles: number;
39
+ actionsCount: number;
40
+ lastCheck: string | null;
41
+ status: DemonStatus;
42
+ model: string;
43
+ actionMode: ActionMode;
44
+ }
45
+ export interface Observation {
46
+ watcherType: WatcherType | string;
47
+ data: Record<string, unknown>;
48
+ summary: string;
49
+ timestamp: string;
50
+ }
51
+ export interface LLMDecision {
52
+ decision: 'act' | 'wait';
53
+ reasoning: string;
54
+ action?: ActionInstruction;
55
+ }
56
+ export interface ActionInstruction {
57
+ provider: string;
58
+ action: string;
59
+ params: Record<string, unknown>;
60
+ }
61
+ export interface ActionFired {
62
+ provider: string;
63
+ action: string;
64
+ params: Record<string, unknown>;
65
+ result?: unknown;
66
+ error?: string;
67
+ dryRun: boolean;
68
+ timestamp: string;
69
+ }
70
+ export interface MemoryEntry {
71
+ id: string;
72
+ timestamp: string;
73
+ cycleNumber: number;
74
+ observations: Observation[];
75
+ decision: LLMDecision;
76
+ actionFired?: ActionFired;
77
+ }
78
+ export interface LLMMessage {
79
+ role: 'user' | 'assistant';
80
+ content: string;
81
+ }
82
+ export interface LLMProvider {
83
+ name: string;
84
+ model: string;
85
+ call(messages: LLMMessage[], systemPrompt: string): Promise<string>;
86
+ callStructured?(schema: Record<string, unknown>, toolName: string, prompt: string): Promise<unknown>;
87
+ }
88
+ export interface Watcher {
89
+ type: WatcherType | string;
90
+ config: WatcherConfig;
91
+ collect(): Promise<Observation[]>;
92
+ }
93
+ export interface ActionProvider {
94
+ provider: string;
95
+ execute(instruction: ActionInstruction, credentials: Record<string, string>): Promise<unknown>;
96
+ getAvailableActions(): string[];
97
+ }
98
+ export interface Clock {
99
+ now(): number;
100
+ sleep(ms: number): Promise<void>;
101
+ }
102
+ export interface Logger {
103
+ debug(msg: string, meta?: Record<string, unknown>): void;
104
+ info(msg: string, meta?: Record<string, unknown>): void;
105
+ warn(msg: string, meta?: Record<string, unknown>): void;
106
+ error(msg: string, meta?: Record<string, unknown>): void;
107
+ }
108
+ export interface KVStore {
109
+ read(key: string): Promise<string | null>;
110
+ write(key: string, value: string): Promise<void>;
111
+ append(key: string, line: string): Promise<void>;
112
+ readLines(key: string, lastN?: number): Promise<string[]>;
113
+ }
114
+ export interface Fact {
115
+ id: string;
116
+ entity: string;
117
+ relation: string;
118
+ value: string;
119
+ confidence: number;
120
+ observed_at: string;
121
+ valid_from: string;
122
+ valid_until: string | null;
123
+ invalidated_at: string | null;
124
+ source_cycle: number;
125
+ source_watcher: string;
126
+ }
127
+ export interface FactsStore {
128
+ upsert(fact: Omit<Fact, 'id'>): void;
129
+ getCurrent(entity: string, relation?: string): Fact[];
130
+ getHistory(entity: string): Fact[];
131
+ getAllCurrent(): Fact[];
132
+ invalidate(entity: string, relation: string, value: string): void;
133
+ close(): void;
134
+ }
135
+ export interface Storage {
136
+ kv: KVStore;
137
+ facts: FactsStore;
138
+ }
139
+ export interface Platform {
140
+ clock: Clock;
141
+ logger: Logger;
142
+ storage: Storage;
143
+ }
144
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ // ============================================================================
2
+ // @josharsh/demon — core domain types
3
+ //
4
+ // This file has NO platform dependencies. The core engine depends only on the
5
+ // interfaces declared here; concrete Node / browser implementations are
6
+ // injected by the host (CLI, website, edge function).
7
+ // ============================================================================
8
+ export {};
9
+ //# sourceMappingURL=types.js.map