nemoris 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 (223) hide show
  1. package/.env.example +49 -0
  2. package/LICENSE +21 -0
  3. package/README.md +209 -0
  4. package/SECURITY.md +119 -0
  5. package/bin/nemoris +46 -0
  6. package/config/agents/agent.toml.example +28 -0
  7. package/config/agents/default.toml +22 -0
  8. package/config/agents/orchestrator.toml +18 -0
  9. package/config/delivery.toml +73 -0
  10. package/config/embeddings.toml +5 -0
  11. package/config/identity/default-purpose.md +1 -0
  12. package/config/identity/default-soul.md +3 -0
  13. package/config/identity/orchestrator-purpose.md +1 -0
  14. package/config/identity/orchestrator-soul.md +1 -0
  15. package/config/improvement-targets.toml +15 -0
  16. package/config/jobs/heartbeat-check.toml +30 -0
  17. package/config/jobs/memory-rollup.toml +46 -0
  18. package/config/jobs/workspace-health.toml +63 -0
  19. package/config/mcp.toml +16 -0
  20. package/config/output-contracts.toml +17 -0
  21. package/config/peers.toml +32 -0
  22. package/config/peers.toml.example +32 -0
  23. package/config/policies/memory-default.toml +10 -0
  24. package/config/policies/memory-heartbeat.toml +5 -0
  25. package/config/policies/memory-ops.toml +10 -0
  26. package/config/policies/tools-heartbeat-minimal.toml +8 -0
  27. package/config/policies/tools-interactive-safe.toml +8 -0
  28. package/config/policies/tools-ops-bounded.toml +8 -0
  29. package/config/policies/tools-orchestrator.toml +7 -0
  30. package/config/providers/anthropic.toml +15 -0
  31. package/config/providers/ollama.toml +5 -0
  32. package/config/providers/openai-codex.toml +9 -0
  33. package/config/providers/openrouter.toml +5 -0
  34. package/config/router.toml +22 -0
  35. package/config/runtime.toml +114 -0
  36. package/config/skills/self-improvement.toml +15 -0
  37. package/config/skills/telegram-onboarding-spec.md +240 -0
  38. package/config/skills/workspace-monitor.toml +15 -0
  39. package/config/task-router.toml +42 -0
  40. package/install.sh +50 -0
  41. package/package.json +90 -0
  42. package/src/auth/auth-profiles.js +169 -0
  43. package/src/auth/openai-codex-oauth.js +285 -0
  44. package/src/battle.js +449 -0
  45. package/src/cli/help.js +265 -0
  46. package/src/cli/output-filter.js +49 -0
  47. package/src/cli/runtime-control.js +704 -0
  48. package/src/cli-main.js +2763 -0
  49. package/src/cli.js +78 -0
  50. package/src/config/loader.js +332 -0
  51. package/src/config/schema-validator.js +214 -0
  52. package/src/config/toml-lite.js +8 -0
  53. package/src/daemon/action-handlers.js +71 -0
  54. package/src/daemon/healing-tick.js +87 -0
  55. package/src/daemon/health-probes.js +90 -0
  56. package/src/daemon/notifier.js +57 -0
  57. package/src/daemon/nurse.js +218 -0
  58. package/src/daemon/repair-log.js +106 -0
  59. package/src/daemon/rule-staging.js +90 -0
  60. package/src/daemon/rules.js +29 -0
  61. package/src/daemon/telegram-commands.js +54 -0
  62. package/src/daemon/updater.js +85 -0
  63. package/src/jobs/job-runner.js +78 -0
  64. package/src/mcp/consumer.js +129 -0
  65. package/src/memory/active-recall.js +171 -0
  66. package/src/memory/backend-manager.js +97 -0
  67. package/src/memory/backends/file-backend.js +38 -0
  68. package/src/memory/backends/qmd-backend.js +219 -0
  69. package/src/memory/embedding-guards.js +24 -0
  70. package/src/memory/embedding-index.js +118 -0
  71. package/src/memory/embedding-service.js +179 -0
  72. package/src/memory/file-index.js +177 -0
  73. package/src/memory/memory-signature.js +5 -0
  74. package/src/memory/memory-store.js +648 -0
  75. package/src/memory/retrieval-planner.js +66 -0
  76. package/src/memory/scoring.js +145 -0
  77. package/src/memory/simhash.js +78 -0
  78. package/src/memory/sqlite-active-store.js +824 -0
  79. package/src/memory/write-policy.js +36 -0
  80. package/src/onboarding/aliases.js +33 -0
  81. package/src/onboarding/auth/api-key.js +224 -0
  82. package/src/onboarding/auth/ollama-detect.js +42 -0
  83. package/src/onboarding/clack-prompter.js +77 -0
  84. package/src/onboarding/doctor.js +530 -0
  85. package/src/onboarding/lock.js +42 -0
  86. package/src/onboarding/model-catalog.js +344 -0
  87. package/src/onboarding/phases/auth.js +589 -0
  88. package/src/onboarding/phases/build.js +130 -0
  89. package/src/onboarding/phases/choose.js +82 -0
  90. package/src/onboarding/phases/detect.js +98 -0
  91. package/src/onboarding/phases/hatch.js +216 -0
  92. package/src/onboarding/phases/identity.js +79 -0
  93. package/src/onboarding/phases/ollama.js +345 -0
  94. package/src/onboarding/phases/scaffold.js +99 -0
  95. package/src/onboarding/phases/telegram.js +377 -0
  96. package/src/onboarding/phases/validate.js +204 -0
  97. package/src/onboarding/phases/verify.js +206 -0
  98. package/src/onboarding/platform.js +482 -0
  99. package/src/onboarding/status-bar.js +95 -0
  100. package/src/onboarding/templates.js +794 -0
  101. package/src/onboarding/toml-writer.js +38 -0
  102. package/src/onboarding/tui.js +250 -0
  103. package/src/onboarding/uninstall.js +153 -0
  104. package/src/onboarding/wizard.js +499 -0
  105. package/src/providers/anthropic.js +168 -0
  106. package/src/providers/base.js +247 -0
  107. package/src/providers/circuit-breaker.js +136 -0
  108. package/src/providers/ollama.js +163 -0
  109. package/src/providers/openai-codex.js +149 -0
  110. package/src/providers/openrouter.js +136 -0
  111. package/src/providers/registry.js +36 -0
  112. package/src/providers/router.js +16 -0
  113. package/src/runtime/bootstrap-cache.js +47 -0
  114. package/src/runtime/capabilities-prompt.js +25 -0
  115. package/src/runtime/completion-ping.js +99 -0
  116. package/src/runtime/config-validator.js +121 -0
  117. package/src/runtime/context-ledger.js +360 -0
  118. package/src/runtime/cutover-readiness.js +42 -0
  119. package/src/runtime/daemon.js +729 -0
  120. package/src/runtime/delivery-ack.js +195 -0
  121. package/src/runtime/delivery-adapters/local-file.js +41 -0
  122. package/src/runtime/delivery-adapters/openclaw-cli.js +94 -0
  123. package/src/runtime/delivery-adapters/openclaw-peer.js +98 -0
  124. package/src/runtime/delivery-adapters/shadow.js +13 -0
  125. package/src/runtime/delivery-adapters/standalone-http.js +98 -0
  126. package/src/runtime/delivery-adapters/telegram.js +104 -0
  127. package/src/runtime/delivery-adapters/tui.js +128 -0
  128. package/src/runtime/delivery-manager.js +807 -0
  129. package/src/runtime/delivery-store.js +168 -0
  130. package/src/runtime/dependency-health.js +118 -0
  131. package/src/runtime/envelope.js +114 -0
  132. package/src/runtime/evaluation.js +1089 -0
  133. package/src/runtime/exec-approvals.js +216 -0
  134. package/src/runtime/executor.js +500 -0
  135. package/src/runtime/failure-ping.js +67 -0
  136. package/src/runtime/flows.js +83 -0
  137. package/src/runtime/guards.js +45 -0
  138. package/src/runtime/handoff.js +51 -0
  139. package/src/runtime/identity-cache.js +28 -0
  140. package/src/runtime/improvement-engine.js +109 -0
  141. package/src/runtime/improvement-harness.js +581 -0
  142. package/src/runtime/input-sanitiser.js +72 -0
  143. package/src/runtime/interaction-contract.js +347 -0
  144. package/src/runtime/lane-readiness.js +226 -0
  145. package/src/runtime/migration.js +323 -0
  146. package/src/runtime/model-resolution.js +78 -0
  147. package/src/runtime/network.js +64 -0
  148. package/src/runtime/notification-store.js +97 -0
  149. package/src/runtime/notifier.js +256 -0
  150. package/src/runtime/orchestrator.js +53 -0
  151. package/src/runtime/orphan-reaper.js +41 -0
  152. package/src/runtime/output-contract-schema.js +139 -0
  153. package/src/runtime/output-contract-validator.js +439 -0
  154. package/src/runtime/peer-readiness.js +69 -0
  155. package/src/runtime/peer-registry.js +133 -0
  156. package/src/runtime/pilot-status.js +108 -0
  157. package/src/runtime/prompt-builder.js +261 -0
  158. package/src/runtime/provider-attempt.js +582 -0
  159. package/src/runtime/report-fallback.js +71 -0
  160. package/src/runtime/result-normalizer.js +183 -0
  161. package/src/runtime/retention.js +74 -0
  162. package/src/runtime/review.js +244 -0
  163. package/src/runtime/route-job.js +15 -0
  164. package/src/runtime/run-store.js +38 -0
  165. package/src/runtime/schedule.js +88 -0
  166. package/src/runtime/scheduler-state.js +434 -0
  167. package/src/runtime/scheduler.js +656 -0
  168. package/src/runtime/session-compactor.js +182 -0
  169. package/src/runtime/session-search.js +155 -0
  170. package/src/runtime/slack-inbound.js +249 -0
  171. package/src/runtime/ssrf.js +102 -0
  172. package/src/runtime/status-aggregator.js +330 -0
  173. package/src/runtime/task-contract.js +140 -0
  174. package/src/runtime/task-packet.js +107 -0
  175. package/src/runtime/task-router.js +140 -0
  176. package/src/runtime/telegram-inbound.js +1565 -0
  177. package/src/runtime/token-counter.js +134 -0
  178. package/src/runtime/token-estimator.js +59 -0
  179. package/src/runtime/tool-loop.js +200 -0
  180. package/src/runtime/transport-server.js +311 -0
  181. package/src/runtime/tui-server.js +411 -0
  182. package/src/runtime/ulid.js +44 -0
  183. package/src/security/ssrf-check.js +197 -0
  184. package/src/setup.js +369 -0
  185. package/src/shadow/bridge.js +303 -0
  186. package/src/skills/loader.js +84 -0
  187. package/src/tools/catalog.json +49 -0
  188. package/src/tools/cli-delegate.js +44 -0
  189. package/src/tools/mcp-client.js +106 -0
  190. package/src/tools/micro/cancel-task.js +6 -0
  191. package/src/tools/micro/complete-task.js +6 -0
  192. package/src/tools/micro/fail-task.js +6 -0
  193. package/src/tools/micro/http-fetch.js +74 -0
  194. package/src/tools/micro/index.js +36 -0
  195. package/src/tools/micro/lcm-recall.js +60 -0
  196. package/src/tools/micro/list-dir.js +17 -0
  197. package/src/tools/micro/list-skills.js +46 -0
  198. package/src/tools/micro/load-skill.js +38 -0
  199. package/src/tools/micro/memory-search.js +45 -0
  200. package/src/tools/micro/read-file.js +11 -0
  201. package/src/tools/micro/session-search.js +54 -0
  202. package/src/tools/micro/shell-exec.js +43 -0
  203. package/src/tools/micro/trigger-job.js +79 -0
  204. package/src/tools/micro/web-search.js +58 -0
  205. package/src/tools/micro/workspace-paths.js +39 -0
  206. package/src/tools/micro/write-file.js +14 -0
  207. package/src/tools/micro/write-memory.js +41 -0
  208. package/src/tools/registry.js +348 -0
  209. package/src/tools/tool-result-contract.js +36 -0
  210. package/src/tui/chat.js +835 -0
  211. package/src/tui/renderer.js +175 -0
  212. package/src/tui/socket-client.js +217 -0
  213. package/src/utils/canonical-json.js +29 -0
  214. package/src/utils/compaction.js +30 -0
  215. package/src/utils/env-loader.js +5 -0
  216. package/src/utils/errors.js +80 -0
  217. package/src/utils/fs.js +101 -0
  218. package/src/utils/ids.js +5 -0
  219. package/src/utils/model-context-limits.js +30 -0
  220. package/src/utils/token-budget.js +74 -0
  221. package/src/utils/usage-cost.js +25 -0
  222. package/src/utils/usage-metrics.js +14 -0
  223. package/vendor/smol-toml-1.5.2.tgz +0 -0
@@ -0,0 +1,66 @@
1
+ const STOPWORDS = new Set([
2
+ "the",
3
+ "and",
4
+ "with",
5
+ "that",
6
+ "this",
7
+ "from",
8
+ "into",
9
+ "your",
10
+ "have",
11
+ "will",
12
+ "would",
13
+ "should",
14
+ "could",
15
+ "through",
16
+ "using",
17
+ "use",
18
+ "for",
19
+ "job",
20
+ "type",
21
+ "bounded",
22
+ "runtime",
23
+ "overhead",
24
+ "execute",
25
+ "keep",
26
+ "only",
27
+ "what",
28
+ "deserves"
29
+ ]);
30
+
31
+ const TASK_HINTS = {
32
+ heartbeat: ["heartbeat", "memory", "status", "check", "triage"],
33
+ workspace_health: ["workspace", "health", "status", "calendar", "issues", "weather", "blockers", "deltas"],
34
+ memory_rollup: ["memory", "summary", "notes", "rollup", "handoff", "inbox", "projects", "backlog", "update"]
35
+ };
36
+
37
+ function tokenize(text) {
38
+ return String(text || "")
39
+ .toLowerCase()
40
+ .split(/[^a-z0-9]+/i)
41
+ .filter(Boolean)
42
+ .filter((token) => token.length > 2 && !STOPWORDS.has(token));
43
+ }
44
+
45
+ function unique(tokens) {
46
+ return [...new Set(tokens)];
47
+ }
48
+
49
+ export function planRetrievalQueries({ objective, taskType, purpose, identity, reportGuidance = null }) {
50
+ const objectiveTokens = tokenize(objective);
51
+ const purposeTokens = tokenize(purpose || identity?.purpose || "").slice(0, 12);
52
+ const taskTokens = TASK_HINTS[taskType] || tokenize(String(taskType || "").replaceAll("_", " "));
53
+ const guidanceTokens = tokenize(
54
+ [reportGuidance?.focus || [], reportGuidance?.qualityChecks || []]
55
+ .flat()
56
+ .join(" ")
57
+ ).slice(0, 12);
58
+
59
+ const fileQuery = unique([...objectiveTokens, ...taskTokens, ...purposeTokens, ...guidanceTokens]).slice(0, 22).join(" ");
60
+ const qmdQuery = unique([...taskTokens, ...guidanceTokens, ...purposeTokens, ...objectiveTokens]).slice(0, 10).join(" ");
61
+
62
+ return {
63
+ fileQuery: fileQuery || objective,
64
+ qmdQuery: qmdQuery || fileQuery || objective
65
+ };
66
+ }
@@ -0,0 +1,145 @@
1
+ const DAY_MS = 24 * 60 * 60 * 1000;
2
+
3
+ const TYPE_WEIGHT = {
4
+ fact: 1,
5
+ summary: 0.9,
6
+ event: 0.55,
7
+ scratchpad: 0.75
8
+ };
9
+
10
+ const SYNONYMS = {
11
+ heartbeat: ["check", "status", "pulse", "monitor"],
12
+ memory: ["notes", "context", "recall", "summary"],
13
+ workspace: ["vault", "project", "repo", "files"],
14
+ health: ["status", "stability", "signal", "check"],
15
+ purpose: ["mission", "role", "goal"],
16
+ soul: ["identity", "voice", "values"],
17
+ cron: ["schedule", "job", "automation"]
18
+ };
19
+
20
+ export const DEFAULT_RETRIEVAL_BLEND = {
21
+ lexicalWeight: 0.36,
22
+ embeddingWeight: 0.3,
23
+ recencyWeight: 0.14,
24
+ salienceWeight: 0.14,
25
+ typeWeight: 0.06,
26
+ semanticRescueBonus: 0.06,
27
+ shadowSnapshotPenalty: 0.12
28
+ };
29
+
30
+ function tokenize(text) {
31
+ return String(text || "")
32
+ .toLowerCase()
33
+ .split(/[^a-z0-9]+/i)
34
+ .filter(Boolean);
35
+ }
36
+
37
+ function expandTokens(tokens) {
38
+ const expanded = new Set(tokens);
39
+ for (const token of tokens) {
40
+ const synonyms = SYNONYMS[token];
41
+ if (!synonyms) continue;
42
+ for (const synonym of synonyms) expanded.add(synonym);
43
+ }
44
+ return [...expanded];
45
+ }
46
+
47
+ export function computeLexicalScore(query, text) {
48
+ const queryTokens = new Set(expandTokens(tokenize(query)));
49
+ if (queryTokens.size === 0) return 0;
50
+ const textTokens = tokenize(text);
51
+ if (textTokens.length === 0) return 0;
52
+ let hits = 0;
53
+ for (const token of textTokens) {
54
+ if (queryTokens.has(token)) hits += 1;
55
+ }
56
+ return Math.min(1, hits / Math.max(queryTokens.size, 1));
57
+ }
58
+
59
+ export function computeRecencyScore(timestamp, now = Date.now(), halfLifeDays = 14) {
60
+ if (!timestamp) return 0.2;
61
+ const ageDays = Math.max(0, now - new Date(timestamp).getTime()) / DAY_MS;
62
+ return Math.pow(0.5, ageDays / halfLifeDays);
63
+ }
64
+
65
+ export function scoreMemory(item, query, now = Date.now(), blend = {}) {
66
+ const weights = {
67
+ ...DEFAULT_RETRIEVAL_BLEND,
68
+ ...blend
69
+ };
70
+ const text = [item.title, item.content, item.summary, item.reason, item.category]
71
+ .filter(Boolean)
72
+ .join(" ");
73
+ const lexicalScore = Number(item.lexicalScore ?? computeLexicalScore(query, text));
74
+ const embeddingSimilarity = Number(item.embeddingSimilarity ?? 0);
75
+ const recencyScore = computeRecencyScore(item.timestamp, now);
76
+ const salienceScore = Math.max(0, Math.min(1, Number(item.salience ?? 0.5)));
77
+ const typeScore = TYPE_WEIGHT[item.type] ?? 0.5;
78
+ const shadowSnapshotPenalty =
79
+ item.sourceKind === "shadow_snapshot" || String(item.title || "").startsWith("shadow snapshot")
80
+ ? weights.shadowSnapshotPenalty
81
+ : 0;
82
+ const semanticRescueBonus =
83
+ lexicalScore < 0.12 && embeddingSimilarity >= 0.35 && item.embeddingFreshness === "fresh"
84
+ ? weights.semanticRescueBonus
85
+ : 0;
86
+
87
+ const blendedScore =
88
+ lexicalScore * weights.lexicalWeight +
89
+ embeddingSimilarity * weights.embeddingWeight +
90
+ recencyScore * weights.recencyWeight +
91
+ salienceScore * weights.salienceWeight +
92
+ typeScore * weights.typeWeight +
93
+ semanticRescueBonus -
94
+ shadowSnapshotPenalty;
95
+
96
+ return {
97
+ score: blendedScore,
98
+ lexicalScore,
99
+ embeddingSimilarity,
100
+ recencyScore,
101
+ salienceScore,
102
+ typeScore,
103
+ semanticRescueBonus,
104
+ shadowSnapshotPenalty
105
+ };
106
+ }
107
+
108
+ // Compatibility helper retained for tests and older call sites.
109
+ export function computeDenseSimilarity(query, text, dimensions = 64) {
110
+ const queryVector = vectorize(expandTokens(tokenize(query)), dimensions);
111
+ const textVector = vectorize(expandTokens(tokenize(text)), dimensions);
112
+ return cosineSimilarity(queryVector, textVector);
113
+ }
114
+
115
+ function vectorize(tokens, dimensions) {
116
+ const vector = new Array(dimensions).fill(0);
117
+ for (const token of tokens) {
118
+ const hash = stableHash(token);
119
+ const index = Math.abs(hash) % dimensions;
120
+ const sign = hash % 2 === 0 ? 1 : -1;
121
+ vector[index] += sign * (1 + token.length / 10);
122
+ }
123
+ return vector;
124
+ }
125
+
126
+ function stableHash(text) {
127
+ let hash = 0;
128
+ for (let i = 0; i < text.length; i += 1) {
129
+ hash = (hash * 31 + text.charCodeAt(i)) | 0;
130
+ }
131
+ return hash;
132
+ }
133
+
134
+ function cosineSimilarity(a, b) {
135
+ let dot = 0;
136
+ let normA = 0;
137
+ let normB = 0;
138
+ for (let i = 0; i < a.length; i += 1) {
139
+ dot += a[i] * b[i];
140
+ normA += a[i] * a[i];
141
+ normB += b[i] * b[i];
142
+ }
143
+ if (normA === 0 || normB === 0) return 0;
144
+ return dot / (Math.sqrt(normA) * Math.sqrt(normB));
145
+ }
@@ -0,0 +1,78 @@
1
+ const STOP_WORDS = new Set([
2
+ "a", "an", "the", "is", "was", "are", "were", "be", "been", "being",
3
+ "have", "has", "had", "do", "does", "did", "will", "would", "shall",
4
+ "should", "may", "might", "can", "could", "must", "ought",
5
+ "i", "me", "my", "we", "our", "you", "your", "he", "him", "his",
6
+ "she", "her", "it", "its", "they", "them", "their",
7
+ "this", "that", "these", "those",
8
+ "in", "on", "at", "to", "for", "of", "with", "by", "from",
9
+ "and", "but", "or", "not", "no", "nor", "so", "yet",
10
+ "if", "then", "else", "when", "where", "how", "what", "which", "who",
11
+ "all", "each", "every", "both", "few", "more", "most", "some", "any",
12
+ "just", "very", "also", "too", "only"
13
+ ]);
14
+
15
+ // FNV-1a 64-bit hash
16
+ const FNV_OFFSET = 0xcbf29ce484222325n;
17
+ const FNV_PRIME = 0x100000001b3n;
18
+ const MASK_64 = (1n << 64n) - 1n;
19
+
20
+ function fnv1a64(str) {
21
+ let hash = FNV_OFFSET;
22
+ for (let i = 0; i < str.length; i++) {
23
+ hash ^= BigInt(str.charCodeAt(i));
24
+ hash = (hash * FNV_PRIME) & MASK_64;
25
+ }
26
+ return hash;
27
+ }
28
+
29
+ function tokenize(text) {
30
+ return String(text || "")
31
+ .toLowerCase()
32
+ .split(/[^a-z0-9]+/)
33
+ .filter((token) => token.length > 0 && !STOP_WORDS.has(token));
34
+ }
35
+
36
+ export function computeSimhash(text) {
37
+ const tokens = tokenize(text);
38
+ if (tokens.length === 0) return 0n;
39
+
40
+ const weights = new Int32Array(64);
41
+
42
+ for (const token of tokens) {
43
+ const hash = fnv1a64(token);
44
+ for (let i = 0; i < 64; i++) {
45
+ if ((hash >> BigInt(i)) & 1n) {
46
+ weights[i] += 1;
47
+ } else {
48
+ weights[i] -= 1;
49
+ }
50
+ }
51
+ }
52
+
53
+ let result = 0n;
54
+ for (let i = 0; i < 64; i++) {
55
+ if (weights[i] > 0) {
56
+ result |= (1n << BigInt(i));
57
+ }
58
+ }
59
+ return result;
60
+ }
61
+
62
+ export function hammingDistance(a, b) {
63
+ let xor = a ^ b;
64
+ let count = 0;
65
+ while (xor > 0n) {
66
+ count += Number(xor & 1n);
67
+ xor >>= 1n;
68
+ }
69
+ return count;
70
+ }
71
+
72
+ export function simhashToHex(hash) {
73
+ return hash.toString(16).padStart(16, "0");
74
+ }
75
+
76
+ export function hexToSimhash(hex) {
77
+ return BigInt(`0x${hex}`);
78
+ }