0xkobold 0.7.2 → 0.8.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.
- package/HEARTBEAT.md +239 -0
- package/IDENTITY.md +12 -0
- package/README.md +138 -4
- package/SOUL.md +21 -0
- package/dist/package.json +10 -5
- package/dist/src/agent/bootstrap-loader.js +295 -66
- package/dist/src/agent/bootstrap-loader.js.map +1 -1
- package/dist/src/agent/context-pruning.js +10 -5
- package/dist/src/agent/context-pruning.js.map +1 -1
- package/dist/src/agent/embedded-runner.js +29 -15
- package/dist/src/agent/embedded-runner.js.map +1 -1
- package/dist/src/agent/index.js +5 -2
- package/dist/src/agent/index.js.map +1 -1
- package/dist/src/agent/system-prompt.js +167 -20
- package/dist/src/agent/system-prompt.js.map +1 -1
- package/dist/src/agent/tools/spawn-agent.js +72 -5
- package/dist/src/agent/tools/spawn-agent.js.map +1 -1
- package/dist/src/channels/slack/webhook.js +2 -2
- package/dist/src/channels/slack/webhook.js.map +1 -1
- package/dist/src/channels/telegram/bot.js +4 -4
- package/dist/src/channels/telegram/bot.js.map +1 -1
- package/dist/src/channels/whatsapp/integration.js +4 -4
- package/dist/src/channels/whatsapp/integration.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +9 -10
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/init.js +90 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/setup.js +53 -0
- package/dist/src/cli/commands/setup.js.map +1 -1
- package/dist/src/cli/index.js +0 -0
- package/dist/src/config/unified-config.js +5 -0
- package/dist/src/config/unified-config.js.map +1 -1
- package/dist/src/cron/index.js +2 -0
- package/dist/src/cron/index.js.map +1 -1
- package/dist/src/cron/nl-parser.js +522 -0
- package/dist/src/cron/nl-parser.js.map +1 -0
- package/dist/src/cron/runner.js +6 -31
- package/dist/src/cron/runner.js.map +1 -1
- package/dist/src/event-bus/index.js.map +1 -1
- package/dist/src/extensions/core/agent-orchestrator-extension.js +200 -148
- package/dist/src/extensions/core/agent-orchestrator-extension.js.map +1 -1
- package/dist/src/extensions/core/diagnostics-extension.js +93 -56
- package/dist/src/extensions/core/diagnostics-extension.js.map +1 -1
- package/dist/src/extensions/core/draconic-safety-extension.js +256 -3
- package/dist/src/extensions/core/draconic-safety-extension.js.map +1 -1
- package/dist/src/extensions/core/heartbeat-extension.js +416 -150
- package/dist/src/extensions/core/heartbeat-extension.js.map +1 -1
- package/dist/src/extensions/core/{generative-agents-extension.js → learning-extension.js} +90 -128
- package/dist/src/extensions/core/learning-extension.js.map +1 -0
- package/dist/src/extensions/core/perennial-memory-extension.js +884 -87
- package/dist/src/extensions/core/perennial-memory-extension.js.map +1 -1
- package/dist/src/extensions/core/routed-ollama-extension.js +345 -0
- package/dist/src/extensions/core/routed-ollama-extension.js.map +1 -0
- package/dist/src/extensions/core/task-manager-extension.js +25 -2
- package/dist/src/extensions/core/task-manager-extension.js.map +1 -1
- package/dist/src/extensions/core/websearch-enhanced-extension.js +81 -23
- package/dist/src/extensions/core/websearch-enhanced-extension.js.map +1 -1
- package/dist/src/extensions/core/workspace-footer-extension.js +40 -63
- package/dist/src/extensions/core/workspace-footer-extension.js.map +1 -1
- package/dist/src/extensions/loader.js +5 -1
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/gateway/gateway-server.js +74 -3
- package/dist/src/gateway/gateway-server.js.map +1 -1
- package/dist/src/gateway/index.js +2 -2
- package/dist/src/gateway/index.js.map +1 -1
- package/dist/src/gateway/methods/agent.js +1 -1
- package/dist/src/gateway/methods/agent.js.map +1 -1
- package/dist/src/gateway/methods/index.js +4 -0
- package/dist/src/gateway/methods/index.js.map +1 -1
- package/dist/src/gateway/methods/node.js +261 -0
- package/dist/src/gateway/methods/node.js.map +1 -0
- package/dist/src/gateway/queue-modes.js +356 -0
- package/dist/src/gateway/queue-modes.js.map +1 -0
- package/dist/src/index.js +47 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/llm/community-analytics.js +569 -0
- package/dist/src/llm/community-analytics.js.map +1 -0
- package/dist/src/llm/index.js +28 -4
- package/dist/src/llm/index.js.map +1 -1
- package/dist/src/llm/model-discovery.js +335 -0
- package/dist/src/llm/model-discovery.js.map +1 -0
- package/dist/src/llm/model-popularity.js +566 -0
- package/dist/src/llm/model-popularity.js.map +1 -0
- package/dist/src/llm/model-scoring-db.js +553 -0
- package/dist/src/llm/model-scoring-db.js.map +1 -0
- package/dist/src/llm/multi-provider.js +258 -0
- package/dist/src/llm/multi-provider.js.map +1 -0
- package/dist/src/llm/ollama.js +133 -187
- package/dist/src/llm/ollama.js.map +1 -1
- package/dist/src/llm/router-commands.js +773 -0
- package/dist/src/llm/router-commands.js.map +1 -0
- package/dist/src/llm/router-core.js +600 -0
- package/dist/src/llm/router-core.js.map +1 -0
- package/dist/src/memory/checkpoint-manager.js +278 -0
- package/dist/src/memory/checkpoint-manager.js.map +1 -0
- package/dist/src/memory/conflict-detector.js +279 -0
- package/dist/src/memory/conflict-detector.js.map +1 -0
- package/dist/src/memory/context-graph.js +360 -0
- package/dist/src/memory/context-graph.js.map +1 -0
- package/dist/src/memory/dialectic/benchmark-cli.js +200 -0
- package/dist/src/memory/dialectic/benchmark-cli.js.map +1 -0
- package/dist/src/memory/dialectic/debug-reasoning.js +37 -0
- package/dist/src/memory/dialectic/debug-reasoning.js.map +1 -0
- package/dist/src/memory/dialectic/index.js +135 -0
- package/dist/src/memory/dialectic/index.js.map +1 -0
- package/dist/src/memory/dialectic/nudges.js +380 -0
- package/dist/src/memory/dialectic/nudges.js.map +1 -0
- package/dist/src/memory/dialectic/reasoning-engine.js +607 -0
- package/dist/src/memory/dialectic/reasoning-engine.js.map +1 -0
- package/dist/src/memory/dialectic/reasoning.js +390 -0
- package/dist/src/memory/dialectic/reasoning.js.map +1 -0
- package/dist/src/memory/dialectic/skill-creation.js +481 -0
- package/dist/src/memory/dialectic/skill-creation.js.map +1 -0
- package/dist/src/memory/dialectic/store.js +663 -0
- package/dist/src/memory/dialectic/store.js.map +1 -0
- package/dist/src/memory/dialectic/types.js +11 -0
- package/dist/src/memory/dialectic/types.js.map +1 -0
- package/dist/src/memory/index.js +24 -2
- package/dist/src/memory/index.js.map +1 -1
- package/dist/src/memory/memory-decay.js +350 -0
- package/dist/src/memory/memory-decay.js.map +1 -0
- package/dist/src/memory/memory-integration.js +5 -5
- package/dist/src/memory/memory-integration.js.map +1 -1
- package/dist/src/memory/migrate-memory-stream.js +97 -0
- package/dist/src/memory/migrate-memory-stream.js.map +1 -0
- package/dist/src/memory/session-memory-bridge.js +49 -5
- package/dist/src/memory/session-memory-bridge.js.map +1 -1
- package/dist/src/memory/session-store.js +123 -0
- package/dist/src/memory/session-store.js.map +1 -1
- package/dist/src/memory/smart-write-rules.js +164 -0
- package/dist/src/memory/smart-write-rules.js.map +1 -0
- package/dist/src/memory/tiered-memory.js +436 -0
- package/dist/src/memory/tiered-memory.js.map +1 -0
- package/dist/src/memory/types.js +6 -0
- package/dist/src/memory/types.js.map +1 -0
- package/dist/src/memory/verify-migration.js +99 -0
- package/dist/src/memory/verify-migration.js.map +1 -0
- package/dist/src/pi-config.js +11 -9
- package/dist/src/pi-config.js.map +1 -1
- package/dist/src/skills/conditional-skills.js +464 -0
- package/dist/src/skills/conditional-skills.js.map +1 -0
- package/dist/src/skills/index.js +5 -0
- package/dist/src/skills/index.js.map +1 -1
- package/dist/src/skills/loader.js +56 -0
- package/dist/src/skills/loader.js.map +1 -1
- package/dist/src/skills/skill-manage.js +417 -0
- package/dist/src/skills/skill-manage.js.map +1 -0
- package/dist/src/tui/commands/orchestration-commands.js +62 -0
- package/dist/src/tui/commands/orchestration-commands.js.map +1 -1
- package/package.json +10 -5
- package/skills/model-router-test.ts +65 -0
- package/dist/src/extensions/core/auto-security-scan-extension.js +0 -41
- package/dist/src/extensions/core/auto-security-scan-extension.js.map +0 -1
- package/dist/src/extensions/core/cloudflare-browser-extension.js +0 -389
- package/dist/src/extensions/core/cloudflare-browser-extension.js.map +0 -1
- package/dist/src/extensions/core/compaction-safeguard.js +0 -223
- package/dist/src/extensions/core/compaction-safeguard.js.map +0 -1
- package/dist/src/extensions/core/generative-agents-extension.js.map +0 -1
- package/dist/src/extensions/core/obsidian-bridge-extension.js +0 -488
- package/dist/src/extensions/core/obsidian-bridge-extension.js.map +0 -1
- package/dist/src/llm/router.js +0 -145
- package/dist/src/llm/router.js.map +0 -1
- package/skills/kobold-scan-skill/node_modules/.package-lock.json +0 -172
- package/skills/kobold-scan-skill/node_modules/ansi-styles/index.d.ts +0 -345
- package/skills/kobold-scan-skill/node_modules/ansi-styles/index.js +0 -163
- package/skills/kobold-scan-skill/node_modules/ansi-styles/license +0 -9
- package/skills/kobold-scan-skill/node_modules/ansi-styles/package.json +0 -56
- package/skills/kobold-scan-skill/node_modules/ansi-styles/readme.md +0 -152
- package/skills/kobold-scan-skill/node_modules/balanced-match/.github/FUNDING.yml +0 -2
- package/skills/kobold-scan-skill/node_modules/balanced-match/LICENSE.md +0 -21
- package/skills/kobold-scan-skill/node_modules/balanced-match/README.md +0 -97
- package/skills/kobold-scan-skill/node_modules/balanced-match/index.js +0 -62
- package/skills/kobold-scan-skill/node_modules/balanced-match/package.json +0 -48
- package/skills/kobold-scan-skill/node_modules/brace-expansion/.github/FUNDING.yml +0 -2
- package/skills/kobold-scan-skill/node_modules/brace-expansion/LICENSE +0 -21
- package/skills/kobold-scan-skill/node_modules/brace-expansion/README.md +0 -135
- package/skills/kobold-scan-skill/node_modules/brace-expansion/index.js +0 -203
- package/skills/kobold-scan-skill/node_modules/brace-expansion/package.json +0 -49
- package/skills/kobold-scan-skill/node_modules/chalk/index.d.ts +0 -415
- package/skills/kobold-scan-skill/node_modules/chalk/license +0 -9
- package/skills/kobold-scan-skill/node_modules/chalk/package.json +0 -68
- package/skills/kobold-scan-skill/node_modules/chalk/readme.md +0 -341
- package/skills/kobold-scan-skill/node_modules/chalk/source/index.js +0 -229
- package/skills/kobold-scan-skill/node_modules/chalk/source/templates.js +0 -134
- package/skills/kobold-scan-skill/node_modules/chalk/source/util.js +0 -39
- package/skills/kobold-scan-skill/node_modules/color-convert/CHANGELOG.md +0 -54
- package/skills/kobold-scan-skill/node_modules/color-convert/LICENSE +0 -21
- package/skills/kobold-scan-skill/node_modules/color-convert/README.md +0 -68
- package/skills/kobold-scan-skill/node_modules/color-convert/conversions.js +0 -839
- package/skills/kobold-scan-skill/node_modules/color-convert/index.js +0 -81
- package/skills/kobold-scan-skill/node_modules/color-convert/package.json +0 -48
- package/skills/kobold-scan-skill/node_modules/color-convert/route.js +0 -97
- package/skills/kobold-scan-skill/node_modules/color-name/LICENSE +0 -8
- package/skills/kobold-scan-skill/node_modules/color-name/README.md +0 -11
- package/skills/kobold-scan-skill/node_modules/color-name/index.js +0 -152
- package/skills/kobold-scan-skill/node_modules/color-name/package.json +0 -28
- package/skills/kobold-scan-skill/node_modules/commander/LICENSE +0 -22
- package/skills/kobold-scan-skill/node_modules/commander/Readme.md +0 -1129
- package/skills/kobold-scan-skill/node_modules/commander/esm.mjs +0 -16
- package/skills/kobold-scan-skill/node_modules/commander/index.js +0 -27
- package/skills/kobold-scan-skill/node_modules/commander/lib/argument.js +0 -147
- package/skills/kobold-scan-skill/node_modules/commander/lib/command.js +0 -2179
- package/skills/kobold-scan-skill/node_modules/commander/lib/error.js +0 -45
- package/skills/kobold-scan-skill/node_modules/commander/lib/help.js +0 -461
- package/skills/kobold-scan-skill/node_modules/commander/lib/option.js +0 -326
- package/skills/kobold-scan-skill/node_modules/commander/lib/suggestSimilar.js +0 -100
- package/skills/kobold-scan-skill/node_modules/commander/package-support.json +0 -16
- package/skills/kobold-scan-skill/node_modules/commander/package.json +0 -80
- package/skills/kobold-scan-skill/node_modules/commander/typings/index.d.ts +0 -891
- package/skills/kobold-scan-skill/node_modules/fs.realpath/LICENSE +0 -43
- package/skills/kobold-scan-skill/node_modules/fs.realpath/README.md +0 -33
- package/skills/kobold-scan-skill/node_modules/fs.realpath/index.js +0 -66
- package/skills/kobold-scan-skill/node_modules/fs.realpath/old.js +0 -303
- package/skills/kobold-scan-skill/node_modules/fs.realpath/package.json +0 -26
- package/skills/kobold-scan-skill/node_modules/glob/LICENSE +0 -15
- package/skills/kobold-scan-skill/node_modules/glob/README.md +0 -399
- package/skills/kobold-scan-skill/node_modules/glob/common.js +0 -244
- package/skills/kobold-scan-skill/node_modules/glob/glob.js +0 -790
- package/skills/kobold-scan-skill/node_modules/glob/package.json +0 -55
- package/skills/kobold-scan-skill/node_modules/glob/sync.js +0 -486
- package/skills/kobold-scan-skill/node_modules/has-flag/index.d.ts +0 -39
- package/skills/kobold-scan-skill/node_modules/has-flag/index.js +0 -8
- package/skills/kobold-scan-skill/node_modules/has-flag/license +0 -9
- package/skills/kobold-scan-skill/node_modules/has-flag/package.json +0 -46
- package/skills/kobold-scan-skill/node_modules/has-flag/readme.md +0 -89
- package/skills/kobold-scan-skill/node_modules/inflight/LICENSE +0 -15
- package/skills/kobold-scan-skill/node_modules/inflight/README.md +0 -37
- package/skills/kobold-scan-skill/node_modules/inflight/inflight.js +0 -54
- package/skills/kobold-scan-skill/node_modules/inflight/package.json +0 -29
- package/skills/kobold-scan-skill/node_modules/inherits/LICENSE +0 -16
- package/skills/kobold-scan-skill/node_modules/inherits/README.md +0 -42
- package/skills/kobold-scan-skill/node_modules/inherits/inherits.js +0 -9
- package/skills/kobold-scan-skill/node_modules/inherits/inherits_browser.js +0 -27
- package/skills/kobold-scan-skill/node_modules/inherits/package.json +0 -29
- package/skills/kobold-scan-skill/node_modules/minimatch/LICENSE +0 -15
- package/skills/kobold-scan-skill/node_modules/minimatch/README.md +0 -259
- package/skills/kobold-scan-skill/node_modules/minimatch/lib/path.js +0 -4
- package/skills/kobold-scan-skill/node_modules/minimatch/minimatch.js +0 -944
- package/skills/kobold-scan-skill/node_modules/minimatch/package.json +0 -35
- package/skills/kobold-scan-skill/node_modules/once/LICENSE +0 -15
- package/skills/kobold-scan-skill/node_modules/once/README.md +0 -79
- package/skills/kobold-scan-skill/node_modules/once/once.js +0 -42
- package/skills/kobold-scan-skill/node_modules/once/package.json +0 -33
- package/skills/kobold-scan-skill/node_modules/supports-color/browser.js +0 -5
- package/skills/kobold-scan-skill/node_modules/supports-color/index.js +0 -135
- package/skills/kobold-scan-skill/node_modules/supports-color/license +0 -9
- package/skills/kobold-scan-skill/node_modules/supports-color/package.json +0 -53
- package/skills/kobold-scan-skill/node_modules/supports-color/readme.md +0 -76
- package/skills/kobold-scan-skill/node_modules/wrappy/LICENSE +0 -15
- package/skills/kobold-scan-skill/node_modules/wrappy/README.md +0 -36
- package/skills/kobold-scan-skill/node_modules/wrappy/package.json +0 -29
- package/skills/kobold-scan-skill/node_modules/wrappy/wrappy.js +0 -33
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dialectic Store
|
|
3
|
+
*
|
|
4
|
+
* SQLite storage for dialectic memory components:
|
|
5
|
+
* - Peers (users, agents, projects, ideas)
|
|
6
|
+
* - Observations (what happened)
|
|
7
|
+
* - Contradictions (conflicts between observations)
|
|
8
|
+
* - Syntheses (resolved understanding)
|
|
9
|
+
* - Representations (inferred preferences, goals, constraints, values)
|
|
10
|
+
* - Nudges (scheduled reflections)
|
|
11
|
+
*/
|
|
12
|
+
import { Database } from "bun:sqlite";
|
|
13
|
+
import * as fs from "node:fs/promises";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
import { randomUUID } from "node:crypto";
|
|
17
|
+
const DB_DIR = path.join(homedir(), ".0xkobold", "dialectic");
|
|
18
|
+
const DB_PATH = path.join(DB_DIR, "dialectic.db");
|
|
19
|
+
const CURRENT_SCHEMA_VERSION = 1;
|
|
20
|
+
// ═════════════════════════════════════════════════════════════════
|
|
21
|
+
// SCHEMA
|
|
22
|
+
// ═════════════════════════════════════════════════════════════════
|
|
23
|
+
const SCHEMA_V1 = `
|
|
24
|
+
-- Metadata
|
|
25
|
+
CREATE TABLE IF NOT EXISTS _metadata (
|
|
26
|
+
key TEXT PRIMARY KEY,
|
|
27
|
+
value TEXT
|
|
28
|
+
);
|
|
29
|
+
INSERT OR REPLACE INTO _metadata VALUES ('schema_version', '1');
|
|
30
|
+
INSERT OR REPLACE INTO _metadata VALUES ('created_at', datetime('now'));
|
|
31
|
+
|
|
32
|
+
-- Peers: Entities that persist and change over time
|
|
33
|
+
CREATE TABLE IF NOT EXISTS peers (
|
|
34
|
+
id TEXT PRIMARY KEY,
|
|
35
|
+
type TEXT NOT NULL CHECK(type IN ('user', 'agent', 'project', 'idea')),
|
|
36
|
+
name TEXT NOT NULL,
|
|
37
|
+
metadata TEXT, -- JSON
|
|
38
|
+
created_at TEXT NOT NULL,
|
|
39
|
+
last_updated TEXT NOT NULL
|
|
40
|
+
);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_peers_type ON peers(type);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_peers_name ON peers(name);
|
|
43
|
+
|
|
44
|
+
-- Observations: Raw input to dialectic reasoning
|
|
45
|
+
CREATE TABLE IF NOT EXISTS observations (
|
|
46
|
+
id TEXT PRIMARY KEY,
|
|
47
|
+
peer_id TEXT NOT NULL,
|
|
48
|
+
content TEXT NOT NULL,
|
|
49
|
+
category TEXT NOT NULL CHECK(category IN ('behavior', 'statement', 'preference', 'goal', 'constraint', 'value', 'error', 'success')),
|
|
50
|
+
timestamp TEXT NOT NULL,
|
|
51
|
+
source_type TEXT NOT NULL CHECK(source_type IN ('message', 'tool_call', 'event', 'reflection')),
|
|
52
|
+
source_id TEXT NOT NULL,
|
|
53
|
+
session_id TEXT,
|
|
54
|
+
project_id TEXT,
|
|
55
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
56
|
+
);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_observations_peer ON observations(peer_id);
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_observations_category ON observations(category);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_observations_timestamp ON observations(timestamp);
|
|
60
|
+
|
|
61
|
+
-- Contradictions: Conflicts between observations
|
|
62
|
+
CREATE TABLE IF NOT EXISTS contradictions (
|
|
63
|
+
id TEXT PRIMARY KEY,
|
|
64
|
+
peer_id TEXT NOT NULL,
|
|
65
|
+
observation_a TEXT NOT NULL,
|
|
66
|
+
observation_b TEXT NOT NULL,
|
|
67
|
+
resolution TEXT NOT NULL CHECK(resolution IN ('newer_wins', 'context', 'refinement', 'correction', 'both_true', 'unknown')),
|
|
68
|
+
resolution_note TEXT,
|
|
69
|
+
confidence REAL DEFAULT 0.5,
|
|
70
|
+
detected_at TEXT NOT NULL,
|
|
71
|
+
resolved_at TEXT,
|
|
72
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
73
|
+
);
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_contradictions_peer ON contradictions(peer_id);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_contradictions_resolved ON contradictions(resolved_at);
|
|
76
|
+
|
|
77
|
+
-- Syntheses: Resolved understanding from dialectic reasoning
|
|
78
|
+
CREATE TABLE IF NOT EXISTS syntheses (
|
|
79
|
+
id TEXT PRIMARY KEY,
|
|
80
|
+
peer_id TEXT NOT NULL,
|
|
81
|
+
content TEXT NOT NULL,
|
|
82
|
+
derived_from TEXT NOT NULL, -- JSON array of observation IDs
|
|
83
|
+
resolved_contradictions TEXT, -- JSON array of contradiction IDs
|
|
84
|
+
confidence REAL DEFAULT 0.5,
|
|
85
|
+
timestamp TEXT NOT NULL,
|
|
86
|
+
superseded_by TEXT,
|
|
87
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
88
|
+
);
|
|
89
|
+
CREATE INDEX IF NOT EXISTS idx_syntheses_peer ON syntheses(peer_id);
|
|
90
|
+
|
|
91
|
+
-- Inferred Preferences: What the peer prefers
|
|
92
|
+
CREATE TABLE IF NOT EXISTS inferred_preferences (
|
|
93
|
+
id TEXT PRIMARY KEY,
|
|
94
|
+
peer_id TEXT NOT NULL,
|
|
95
|
+
topic TEXT NOT NULL,
|
|
96
|
+
preference TEXT NOT NULL,
|
|
97
|
+
evidence TEXT NOT NULL, -- JSON array of observation IDs
|
|
98
|
+
confidence REAL DEFAULT 0.5,
|
|
99
|
+
last_updated TEXT NOT NULL,
|
|
100
|
+
contradicted BOOLEAN DEFAULT FALSE,
|
|
101
|
+
contradicted_by TEXT,
|
|
102
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
103
|
+
);
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_preferences_peer ON inferred_preferences(peer_id);
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_preferences_topic ON inferred_preferences(topic);
|
|
106
|
+
|
|
107
|
+
-- Inferred Goals: What the peer is trying to achieve
|
|
108
|
+
CREATE TABLE IF NOT EXISTS inferred_goals (
|
|
109
|
+
id TEXT PRIMARY KEY,
|
|
110
|
+
peer_id TEXT NOT NULL,
|
|
111
|
+
description TEXT NOT NULL,
|
|
112
|
+
status TEXT NOT NULL CHECK(status IN ('active', 'completed', 'abandoned', 'unknown')),
|
|
113
|
+
priority TEXT NOT NULL CHECK(priority IN ('high', 'medium', 'low')),
|
|
114
|
+
evidence TEXT NOT NULL,
|
|
115
|
+
confidence REAL DEFAULT 0.5,
|
|
116
|
+
first_observed TEXT NOT NULL,
|
|
117
|
+
last_updated TEXT NOT NULL,
|
|
118
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
119
|
+
);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_goals_peer ON inferred_goals(peer_id);
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_goals_status ON inferred_goals(status);
|
|
122
|
+
|
|
123
|
+
-- Inferred Constraints: What the peer cannot/will not do
|
|
124
|
+
CREATE TABLE IF NOT EXISTS inferred_constraints (
|
|
125
|
+
id TEXT PRIMARY KEY,
|
|
126
|
+
peer_id TEXT NOT NULL,
|
|
127
|
+
description TEXT NOT NULL,
|
|
128
|
+
type TEXT NOT NULL CHECK(type IN ('hard', 'soft', 'preference')),
|
|
129
|
+
evidence TEXT NOT NULL,
|
|
130
|
+
confidence REAL DEFAULT 0.5,
|
|
131
|
+
last_updated TEXT NOT NULL,
|
|
132
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
133
|
+
);
|
|
134
|
+
CREATE INDEX IF NOT EXISTS idx_constraints_peer ON inferred_constraints(peer_id);
|
|
135
|
+
|
|
136
|
+
-- Inferred Values: What the peer cares about intrinsically
|
|
137
|
+
CREATE TABLE IF NOT EXISTS inferred_values (
|
|
138
|
+
id TEXT PRIMARY KEY,
|
|
139
|
+
peer_id TEXT NOT NULL,
|
|
140
|
+
value TEXT NOT NULL,
|
|
141
|
+
context TEXT,
|
|
142
|
+
evidence TEXT NOT NULL,
|
|
143
|
+
confidence REAL DEFAULT 0.5,
|
|
144
|
+
last_updated TEXT NOT NULL,
|
|
145
|
+
FOREIGN KEY (peer_id) REFERENCES peers(id)
|
|
146
|
+
);
|
|
147
|
+
CREATE INDEX IF NOT EXISTS idx_values_peer ON inferred_values(peer_id);
|
|
148
|
+
|
|
149
|
+
-- Nudges: Scheduled reflections and actions
|
|
150
|
+
CREATE TABLE IF NOT EXISTS nudges (
|
|
151
|
+
id TEXT PRIMARY KEY,
|
|
152
|
+
trigger_type TEXT NOT NULL CHECK(trigger_type IN ('time', 'event', 'threshold')),
|
|
153
|
+
trigger_data TEXT NOT NULL, -- JSON
|
|
154
|
+
question TEXT NOT NULL,
|
|
155
|
+
action_type TEXT NOT NULL,
|
|
156
|
+
action_data TEXT NOT NULL, -- JSON
|
|
157
|
+
priority TEXT NOT NULL CHECK(priority IN ('low', 'medium', 'high')),
|
|
158
|
+
created_at TEXT NOT NULL,
|
|
159
|
+
run_at TEXT,
|
|
160
|
+
completed_at TEXT,
|
|
161
|
+
result TEXT
|
|
162
|
+
);
|
|
163
|
+
CREATE INDEX IF NOT EXISTS idx_nudges_pending ON nudges(completed_at) WHERE completed_at IS NULL;
|
|
164
|
+
`;
|
|
165
|
+
// ═════════════════════════════════════════════════════════════════
|
|
166
|
+
// STORE CLASS
|
|
167
|
+
// ═════════════════════════════════════════════════════════════════
|
|
168
|
+
export class DialecticStore {
|
|
169
|
+
db;
|
|
170
|
+
constructor(db) {
|
|
171
|
+
if (db) {
|
|
172
|
+
this.db = db;
|
|
173
|
+
// Initialize schema for provided databases (including :memory:)
|
|
174
|
+
this.initSchema();
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.db = this.initDatabase();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Initialize schema on an existing database
|
|
182
|
+
*/
|
|
183
|
+
initSchema() {
|
|
184
|
+
// Check if schema exists
|
|
185
|
+
try {
|
|
186
|
+
const result = this.db.query("SELECT value FROM _metadata WHERE key = 'schema_version'").get();
|
|
187
|
+
if (result?.value === "1") {
|
|
188
|
+
return; // Schema already initialized
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Schema doesn't exist, create it
|
|
193
|
+
}
|
|
194
|
+
console.log("[DialecticStore] Initializing schema v1");
|
|
195
|
+
this.db.exec(SCHEMA_V1);
|
|
196
|
+
}
|
|
197
|
+
initDatabase() {
|
|
198
|
+
// Ensure directory exists
|
|
199
|
+
fs.mkdir(DB_DIR, { recursive: true }).catch(() => { });
|
|
200
|
+
const db = new Database(DB_PATH);
|
|
201
|
+
db.exec("PRAGMA journal_mode = WAL;");
|
|
202
|
+
db.exec("PRAGMA synchronous = NORMAL;");
|
|
203
|
+
// Check schema version
|
|
204
|
+
let version = "0";
|
|
205
|
+
try {
|
|
206
|
+
const result = db.query("SELECT value FROM _metadata WHERE key = 'schema_version'").get();
|
|
207
|
+
version = result?.value || "0";
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
version = "0";
|
|
211
|
+
}
|
|
212
|
+
// Run migrations
|
|
213
|
+
if (version === "0") {
|
|
214
|
+
console.log("[DialecticStore] Initializing schema v1");
|
|
215
|
+
db.exec(SCHEMA_V1);
|
|
216
|
+
}
|
|
217
|
+
return db;
|
|
218
|
+
}
|
|
219
|
+
// ─────────────────────────────────────────────────────────────────
|
|
220
|
+
// PEERS
|
|
221
|
+
// ─────────────────────────────────────────────────────────────────
|
|
222
|
+
createPeer(type, name, metadata) {
|
|
223
|
+
const id = `peer_${type}_${name.toLowerCase().replace(/[^a-z0-9]/g, "_")}`;
|
|
224
|
+
const now = new Date().toISOString();
|
|
225
|
+
this.db.query(`
|
|
226
|
+
INSERT OR REPLACE INTO peers (id, type, name, metadata, created_at, last_updated)
|
|
227
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
228
|
+
`).run(id, type, name, metadata ? JSON.stringify(metadata) : null, now, now);
|
|
229
|
+
return { id, type, name, createdAt: now, lastUpdated: now, metadata };
|
|
230
|
+
}
|
|
231
|
+
getPeer(id) {
|
|
232
|
+
const row = this.db.query(`SELECT * FROM peers WHERE id = ?`).get(id);
|
|
233
|
+
if (!row)
|
|
234
|
+
return undefined;
|
|
235
|
+
return {
|
|
236
|
+
id: row.id,
|
|
237
|
+
type: row.type,
|
|
238
|
+
name: row.name,
|
|
239
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
240
|
+
createdAt: row.created_at,
|
|
241
|
+
lastUpdated: row.last_updated,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
getPeerByName(name, type) {
|
|
245
|
+
const query = type
|
|
246
|
+
? `SELECT * FROM peers WHERE name = ? AND type = ?`
|
|
247
|
+
: `SELECT * FROM peers WHERE name = ?`;
|
|
248
|
+
const params = type ? [name, type] : [name];
|
|
249
|
+
const row = this.db.query(query).get(...params);
|
|
250
|
+
if (!row)
|
|
251
|
+
return undefined;
|
|
252
|
+
return {
|
|
253
|
+
id: row.id,
|
|
254
|
+
type: row.type,
|
|
255
|
+
name: row.name,
|
|
256
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
257
|
+
createdAt: row.created_at,
|
|
258
|
+
lastUpdated: row.last_updated,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
listPeers(type) {
|
|
262
|
+
const query = type
|
|
263
|
+
? `SELECT * FROM peers WHERE type = ? ORDER BY last_updated DESC`
|
|
264
|
+
: `SELECT * FROM peers ORDER BY last_updated DESC`;
|
|
265
|
+
const params = type ? [type] : [];
|
|
266
|
+
const rows = this.db.query(query).all(...params);
|
|
267
|
+
return rows.map(row => ({
|
|
268
|
+
id: row.id,
|
|
269
|
+
type: row.type,
|
|
270
|
+
name: row.name,
|
|
271
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
272
|
+
createdAt: row.created_at,
|
|
273
|
+
lastUpdated: row.last_updated,
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
// ─────────────────────────────────────────────────────────────────
|
|
277
|
+
// OBSERVATIONS
|
|
278
|
+
// ─────────────────────────────────────────────────────────────────
|
|
279
|
+
addObservation(peerId, content, category, sourceType, sourceId, sessionId, projectId) {
|
|
280
|
+
const id = `obs_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
281
|
+
const timestamp = new Date().toISOString();
|
|
282
|
+
this.db.query(`
|
|
283
|
+
INSERT INTO observations (id, peer_id, content, category, timestamp, source_type, source_id, session_id, project_id)
|
|
284
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
285
|
+
`).run(id, peerId, content, category, timestamp, sourceType, sourceId, sessionId || null, projectId || null);
|
|
286
|
+
// Update peer's last_updated
|
|
287
|
+
this.db.query(`UPDATE peers SET last_updated = ? WHERE id = ?`).run(timestamp, peerId);
|
|
288
|
+
return {
|
|
289
|
+
id,
|
|
290
|
+
peerId,
|
|
291
|
+
content,
|
|
292
|
+
category,
|
|
293
|
+
timestamp,
|
|
294
|
+
sourceType,
|
|
295
|
+
sourceId,
|
|
296
|
+
sessionId,
|
|
297
|
+
projectId,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
getObservations(peerId, limit = 100) {
|
|
301
|
+
const rows = this.db.query(`
|
|
302
|
+
SELECT * FROM observations WHERE peer_id = ? ORDER BY timestamp DESC LIMIT ?
|
|
303
|
+
`).all(peerId, limit);
|
|
304
|
+
return rows.map(row => ({
|
|
305
|
+
id: row.id,
|
|
306
|
+
peerId: row.peer_id,
|
|
307
|
+
content: row.content,
|
|
308
|
+
category: row.category,
|
|
309
|
+
timestamp: row.timestamp,
|
|
310
|
+
sourceType: row.source_type,
|
|
311
|
+
sourceId: row.source_id,
|
|
312
|
+
sessionId: row.session_id,
|
|
313
|
+
projectId: row.project_id,
|
|
314
|
+
}));
|
|
315
|
+
}
|
|
316
|
+
getRecentObservations(peerId, since) {
|
|
317
|
+
const rows = this.db.query(`
|
|
318
|
+
SELECT * FROM observations WHERE peer_id = ? AND timestamp > ? ORDER BY timestamp DESC
|
|
319
|
+
`).all(peerId, since.toISOString());
|
|
320
|
+
return rows.map(row => ({
|
|
321
|
+
id: row.id,
|
|
322
|
+
peerId: row.peer_id,
|
|
323
|
+
content: row.content,
|
|
324
|
+
category: row.category,
|
|
325
|
+
timestamp: row.timestamp,
|
|
326
|
+
sourceType: row.source_type,
|
|
327
|
+
sourceId: row.source_id,
|
|
328
|
+
sessionId: row.session_id,
|
|
329
|
+
projectId: row.project_id,
|
|
330
|
+
}));
|
|
331
|
+
}
|
|
332
|
+
// ─────────────────────────────────────────────────────────────────
|
|
333
|
+
// CONTRADICTIONS
|
|
334
|
+
// ─────────────────────────────────────────────────────────────────
|
|
335
|
+
addContradiction(peerId, observationA, observationB, resolution = "unknown", resolutionNote = "", confidence = 0.5) {
|
|
336
|
+
const id = `contra_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
337
|
+
const detectedAt = new Date().toISOString();
|
|
338
|
+
this.db.query(`
|
|
339
|
+
INSERT INTO contradictions (id, peer_id, observation_a, observation_b, resolution, resolution_note, confidence, detected_at)
|
|
340
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
341
|
+
`).run(id, peerId, observationA, observationB, resolution, resolutionNote, confidence, detectedAt);
|
|
342
|
+
return {
|
|
343
|
+
id,
|
|
344
|
+
peerId,
|
|
345
|
+
observationA,
|
|
346
|
+
observationB,
|
|
347
|
+
resolution,
|
|
348
|
+
resolutionNote,
|
|
349
|
+
confidence,
|
|
350
|
+
detectedAt,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
resolveContradiction(id, resolution, note) {
|
|
354
|
+
const resolvedAt = new Date().toISOString();
|
|
355
|
+
this.db.query(`
|
|
356
|
+
UPDATE contradictions SET resolution = ?, resolution_note = ?, resolved_at = ? WHERE id = ?
|
|
357
|
+
`).run(resolution, note, resolvedAt, id);
|
|
358
|
+
}
|
|
359
|
+
getUnresolvedContradictions(peerId) {
|
|
360
|
+
const rows = this.db.query(`
|
|
361
|
+
SELECT * FROM contradictions WHERE peer_id = ? AND resolved_at IS NULL ORDER BY detected_at DESC
|
|
362
|
+
`).all(peerId);
|
|
363
|
+
return rows.map(row => ({
|
|
364
|
+
id: row.id,
|
|
365
|
+
peerId: row.peer_id,
|
|
366
|
+
observationA: row.observation_a,
|
|
367
|
+
observationB: row.observation_b,
|
|
368
|
+
resolution: row.resolution,
|
|
369
|
+
resolutionNote: row.resolution_note,
|
|
370
|
+
confidence: row.confidence,
|
|
371
|
+
detectedAt: row.detected_at,
|
|
372
|
+
resolvedAt: row.resolved_at,
|
|
373
|
+
}));
|
|
374
|
+
}
|
|
375
|
+
// ─────────────────────────────────────────────────────────────────
|
|
376
|
+
// SYNTHESES
|
|
377
|
+
// ─────────────────────────────────────────────────────────────────
|
|
378
|
+
addSynthesis(peerId, content, derivedFrom, resolvedContradictions, confidence = 0.5) {
|
|
379
|
+
const id = `synth_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
380
|
+
const timestamp = new Date().toISOString();
|
|
381
|
+
this.db.query(`
|
|
382
|
+
INSERT INTO syntheses (id, peer_id, content, derived_from, resolved_contradictions, confidence, timestamp)
|
|
383
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
384
|
+
`).run(id, peerId, content, JSON.stringify(derivedFrom), JSON.stringify(resolvedContradictions), confidence, timestamp);
|
|
385
|
+
return {
|
|
386
|
+
id,
|
|
387
|
+
peerId,
|
|
388
|
+
content,
|
|
389
|
+
derivedFrom,
|
|
390
|
+
resolvedContradictions,
|
|
391
|
+
confidence,
|
|
392
|
+
timestamp,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
getSyntheses(peerId, limit = 10) {
|
|
396
|
+
const rows = this.db.query(`
|
|
397
|
+
SELECT * FROM syntheses WHERE peer_id = ? AND superseded_by IS NULL ORDER BY timestamp DESC LIMIT ?
|
|
398
|
+
`).all(peerId, limit);
|
|
399
|
+
return rows.map(row => ({
|
|
400
|
+
id: row.id,
|
|
401
|
+
peerId: row.peer_id,
|
|
402
|
+
content: row.content,
|
|
403
|
+
derivedFrom: JSON.parse(row.derived_from),
|
|
404
|
+
resolvedContradictions: JSON.parse(row.resolved_contradictions),
|
|
405
|
+
confidence: row.confidence,
|
|
406
|
+
timestamp: row.timestamp,
|
|
407
|
+
supersededBy: row.superseded_by,
|
|
408
|
+
}));
|
|
409
|
+
}
|
|
410
|
+
// ─────────────────────────────────────────────────────────────────
|
|
411
|
+
// INFERRED PREFERENCES
|
|
412
|
+
// ─────────────────────────────────────────────────────────────────
|
|
413
|
+
addPreference(peerId, topic, preference, evidence, confidence = 0.5) {
|
|
414
|
+
const id = `pref_${topic}_${randomUUID().slice(0, 8)}`;
|
|
415
|
+
const now = new Date().toISOString();
|
|
416
|
+
this.db.query(`
|
|
417
|
+
INSERT OR REPLACE INTO inferred_preferences (id, peer_id, topic, preference, evidence, confidence, last_updated)
|
|
418
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
419
|
+
`).run(id, peerId, topic, preference, JSON.stringify(evidence), confidence, now);
|
|
420
|
+
return {
|
|
421
|
+
id,
|
|
422
|
+
peerId,
|
|
423
|
+
topic,
|
|
424
|
+
preference,
|
|
425
|
+
evidence,
|
|
426
|
+
confidence,
|
|
427
|
+
lastUpdated: now,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
getPreferences(peerId) {
|
|
431
|
+
const rows = this.db.query(`
|
|
432
|
+
SELECT * FROM inferred_preferences WHERE peer_id = ? AND contradicted = FALSE ORDER BY confidence DESC
|
|
433
|
+
`).all(peerId);
|
|
434
|
+
return rows.map(row => ({
|
|
435
|
+
id: row.id,
|
|
436
|
+
peerId: row.peer_id,
|
|
437
|
+
topic: row.topic,
|
|
438
|
+
preference: row.preference,
|
|
439
|
+
evidence: JSON.parse(row.evidence),
|
|
440
|
+
confidence: row.confidence,
|
|
441
|
+
lastUpdated: row.last_updated,
|
|
442
|
+
contradicted: row.contradicted === 1,
|
|
443
|
+
contradictedBy: row.contradicted_by,
|
|
444
|
+
}));
|
|
445
|
+
}
|
|
446
|
+
// ─────────────────────────────────────────────────────────────────
|
|
447
|
+
// INFERRED GOALS
|
|
448
|
+
// ─────────────────────────────────────────────────────────────────
|
|
449
|
+
addGoal(peerId, description, status = "active", priority = "medium", evidence = [], confidence = 0.5) {
|
|
450
|
+
const id = `goal_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
451
|
+
const now = new Date().toISOString();
|
|
452
|
+
this.db.query(`
|
|
453
|
+
INSERT INTO inferred_goals (id, peer_id, description, status, priority, evidence, confidence, first_observed, last_updated)
|
|
454
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
455
|
+
`).run(id, peerId, description, status, priority, JSON.stringify(evidence), confidence, now, now);
|
|
456
|
+
return {
|
|
457
|
+
id,
|
|
458
|
+
peerId,
|
|
459
|
+
description,
|
|
460
|
+
status,
|
|
461
|
+
priority,
|
|
462
|
+
evidence,
|
|
463
|
+
confidence,
|
|
464
|
+
firstObserved: now,
|
|
465
|
+
lastUpdated: now,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
getGoals(peerId, status) {
|
|
469
|
+
const query = status
|
|
470
|
+
? `SELECT * FROM inferred_goals WHERE peer_id = ? AND status = ? ORDER BY priority, confidence DESC`
|
|
471
|
+
: `SELECT * FROM inferred_goals WHERE peer_id = ? ORDER BY priority, confidence DESC`;
|
|
472
|
+
const params = status ? [peerId, status] : [peerId];
|
|
473
|
+
const rows = this.db.query(query).all(...params);
|
|
474
|
+
return rows.map(row => ({
|
|
475
|
+
id: row.id,
|
|
476
|
+
peerId: row.peer_id,
|
|
477
|
+
description: row.description,
|
|
478
|
+
status: row.status,
|
|
479
|
+
priority: row.priority,
|
|
480
|
+
evidence: JSON.parse(row.evidence),
|
|
481
|
+
confidence: row.confidence,
|
|
482
|
+
firstObserved: row.first_observed,
|
|
483
|
+
lastUpdated: row.last_updated,
|
|
484
|
+
}));
|
|
485
|
+
}
|
|
486
|
+
// ─────────────────────────────────────────────────────────────────
|
|
487
|
+
// INFERRED CONSTRAINTS
|
|
488
|
+
// ─────────────────────────────────────────────────────────────────
|
|
489
|
+
addConstraint(peerId, description, type = "soft", evidence = [], confidence = 0.5) {
|
|
490
|
+
const id = `const_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
491
|
+
const now = new Date().toISOString();
|
|
492
|
+
this.db.query(`
|
|
493
|
+
INSERT INTO inferred_constraints (id, peer_id, description, type, evidence, confidence, last_updated)
|
|
494
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
495
|
+
`).run(id, peerId, description, type, JSON.stringify(evidence), confidence, now);
|
|
496
|
+
return {
|
|
497
|
+
id,
|
|
498
|
+
peerId,
|
|
499
|
+
description,
|
|
500
|
+
type,
|
|
501
|
+
evidence,
|
|
502
|
+
confidence,
|
|
503
|
+
lastUpdated: now,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
getConstraints(peerId) {
|
|
507
|
+
const rows = this.db.query(`
|
|
508
|
+
SELECT * FROM inferred_constraints WHERE peer_id = ? ORDER BY type, confidence DESC
|
|
509
|
+
`).all(peerId);
|
|
510
|
+
return rows.map(row => ({
|
|
511
|
+
id: row.id,
|
|
512
|
+
peerId: row.peer_id,
|
|
513
|
+
description: row.description,
|
|
514
|
+
type: row.type,
|
|
515
|
+
evidence: JSON.parse(row.evidence),
|
|
516
|
+
confidence: row.confidence,
|
|
517
|
+
lastUpdated: row.last_updated,
|
|
518
|
+
}));
|
|
519
|
+
}
|
|
520
|
+
// ─────────────────────────────────────────────────────────────────
|
|
521
|
+
// INFERRED VALUES
|
|
522
|
+
// ─────────────────────────────────────────────────────────────────
|
|
523
|
+
addValue(peerId, value, context, evidence, confidence = 0.5) {
|
|
524
|
+
const id = `val_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
525
|
+
const now = new Date().toISOString();
|
|
526
|
+
this.db.query(`
|
|
527
|
+
INSERT INTO inferred_values (id, peer_id, value, context, evidence, confidence, last_updated)
|
|
528
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
529
|
+
`).run(id, peerId, value, context, JSON.stringify(evidence), confidence, now);
|
|
530
|
+
return {
|
|
531
|
+
id,
|
|
532
|
+
peerId,
|
|
533
|
+
value,
|
|
534
|
+
context,
|
|
535
|
+
evidence,
|
|
536
|
+
confidence,
|
|
537
|
+
lastUpdated: now,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
getValues(peerId) {
|
|
541
|
+
const rows = this.db.query(`
|
|
542
|
+
SELECT * FROM inferred_values WHERE peer_id = ? ORDER BY confidence DESC
|
|
543
|
+
`).all(peerId);
|
|
544
|
+
return rows.map(row => ({
|
|
545
|
+
id: row.id,
|
|
546
|
+
peerId: row.peer_id,
|
|
547
|
+
value: row.value,
|
|
548
|
+
context: row.context,
|
|
549
|
+
evidence: JSON.parse(row.evidence),
|
|
550
|
+
confidence: row.confidence,
|
|
551
|
+
lastUpdated: row.last_updated,
|
|
552
|
+
}));
|
|
553
|
+
}
|
|
554
|
+
// ─────────────────────────────────────────────────────────────────
|
|
555
|
+
// REPRESENTATIONS (Aggregate)
|
|
556
|
+
// ─────────────────────────────────────────────────────────────────
|
|
557
|
+
getRepresentation(peerId) {
|
|
558
|
+
const peer = this.getPeer(peerId);
|
|
559
|
+
if (!peer)
|
|
560
|
+
return undefined;
|
|
561
|
+
const preferences = this.getPreferences(peerId);
|
|
562
|
+
const goals = this.getGoals(peerId);
|
|
563
|
+
const constraints = this.getConstraints(peerId);
|
|
564
|
+
const values = this.getValues(peerId);
|
|
565
|
+
const observations = this.getObservations(peerId, 50);
|
|
566
|
+
const contradictions = this.getUnresolvedContradictions(peerId);
|
|
567
|
+
const synthesis = this.getSyntheses(peerId);
|
|
568
|
+
// Calculate overall confidence
|
|
569
|
+
const allConfidences = [
|
|
570
|
+
...preferences.map(p => p.confidence),
|
|
571
|
+
...goals.map(g => g.confidence),
|
|
572
|
+
...constraints.map(c => c.confidence),
|
|
573
|
+
...values.map(v => v.confidence),
|
|
574
|
+
...synthesis.map(s => s.confidence),
|
|
575
|
+
];
|
|
576
|
+
const avgConfidence = allConfidences.length > 0
|
|
577
|
+
? allConfidences.reduce((a, b) => a + b, 0) / allConfidences.length
|
|
578
|
+
: 0.5;
|
|
579
|
+
return {
|
|
580
|
+
id: `repr_${peerId}`,
|
|
581
|
+
peerId,
|
|
582
|
+
peerType: peer.type,
|
|
583
|
+
preferences,
|
|
584
|
+
goals,
|
|
585
|
+
constraints,
|
|
586
|
+
values,
|
|
587
|
+
observations,
|
|
588
|
+
contradictions,
|
|
589
|
+
synthesis,
|
|
590
|
+
confidence: avgConfidence,
|
|
591
|
+
lastUpdated: peer.lastUpdated,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
// ─────────────────────────────────────────────────────────────────
|
|
595
|
+
// NUDGES
|
|
596
|
+
// ─────────────────────────────────────────────────────────────────
|
|
597
|
+
addNudge(trigger, question, action, priority = "medium") {
|
|
598
|
+
const id = `nudge_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
599
|
+
const createdAt = new Date().toISOString();
|
|
600
|
+
this.db.query(`
|
|
601
|
+
INSERT INTO nudges (id, trigger_type, trigger_data, question, action_type, action_data, priority, created_at)
|
|
602
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
603
|
+
`).run(id, trigger.type, JSON.stringify(trigger), question, action.type, JSON.stringify(action), priority, createdAt);
|
|
604
|
+
return {
|
|
605
|
+
id,
|
|
606
|
+
trigger,
|
|
607
|
+
question,
|
|
608
|
+
action,
|
|
609
|
+
priority,
|
|
610
|
+
createdAt,
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
getPendingNudges(limit = 10) {
|
|
614
|
+
const rows = this.db.query(`
|
|
615
|
+
SELECT * FROM nudges WHERE completed_at IS NULL ORDER BY priority, created_at LIMIT ?
|
|
616
|
+
`).all(limit);
|
|
617
|
+
return rows.map(row => ({
|
|
618
|
+
id: row.id,
|
|
619
|
+
trigger: JSON.parse(row.trigger_data),
|
|
620
|
+
question: row.question,
|
|
621
|
+
action: JSON.parse(row.action_data),
|
|
622
|
+
priority: row.priority,
|
|
623
|
+
createdAt: row.created_at,
|
|
624
|
+
runAt: row.run_at,
|
|
625
|
+
completedAt: row.completed_at,
|
|
626
|
+
result: row.result,
|
|
627
|
+
}));
|
|
628
|
+
}
|
|
629
|
+
completeNudge(id, result) {
|
|
630
|
+
const completedAt = new Date().toISOString();
|
|
631
|
+
this.db.query(`
|
|
632
|
+
UPDATE nudges SET completed_at = ?, result = ? WHERE id = ?
|
|
633
|
+
`).run(completedAt, result, id);
|
|
634
|
+
}
|
|
635
|
+
// ─────────────────────────────────────────────────────────────────
|
|
636
|
+
// UTILITY
|
|
637
|
+
// ─────────────────────────────────────────────────────────────────
|
|
638
|
+
close() {
|
|
639
|
+
this.db.close();
|
|
640
|
+
}
|
|
641
|
+
getStats() {
|
|
642
|
+
return {
|
|
643
|
+
peers: this.db.query(`SELECT COUNT(*) as n FROM peers`).get().n,
|
|
644
|
+
observations: this.db.query(`SELECT COUNT(*) as n FROM observations`).get().n,
|
|
645
|
+
contradictions: this.db.query(`SELECT COUNT(*) as n FROM contradictions`).get().n,
|
|
646
|
+
syntheses: this.db.query(`SELECT COUNT(*) as n FROM syntheses`).get().n,
|
|
647
|
+
preferences: this.db.query(`SELECT COUNT(*) as n FROM inferred_preferences`).get().n,
|
|
648
|
+
goals: this.db.query(`SELECT COUNT(*) as n FROM inferred_goals`).get().n,
|
|
649
|
+
constraints: this.db.query(`SELECT COUNT(*) as n FROM inferred_constraints`).get().n,
|
|
650
|
+
values: this.db.query(`SELECT COUNT(*) as n FROM inferred_values`).get().n,
|
|
651
|
+
nudges: this.db.query(`SELECT COUNT(*) as n FROM nudges`).get().n,
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
// Singleton
|
|
656
|
+
let store = null;
|
|
657
|
+
export function getDialecticStore() {
|
|
658
|
+
if (!store) {
|
|
659
|
+
store = new DialecticStore();
|
|
660
|
+
}
|
|
661
|
+
return store;
|
|
662
|
+
}
|
|
663
|
+
//# sourceMappingURL=store.js.map
|