@jbarket/loomai 0.5.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/CHANGELOG.md +475 -0
- package/LICENSE +661 -0
- package/README.md +702 -0
- package/assets/demo.cast +396 -0
- package/assets/skill/SKILL.md +192 -0
- package/dist/backends/embedding-runtime.d.ts +39 -0
- package/dist/backends/embedding-runtime.js +265 -0
- package/dist/backends/episodes.d.ts +36 -0
- package/dist/backends/episodes.js +126 -0
- package/dist/backends/fastembed.d.ts +18 -0
- package/dist/backends/fastembed.js +95 -0
- package/dist/backends/glob.d.ts +10 -0
- package/dist/backends/glob.js +16 -0
- package/dist/backends/index.d.ts +6 -0
- package/dist/backends/index.js +78 -0
- package/dist/backends/migrations.d.ts +38 -0
- package/dist/backends/migrations.js +157 -0
- package/dist/backends/mmr.d.ts +45 -0
- package/dist/backends/mmr.js +82 -0
- package/dist/backends/proposals.d.ts +65 -0
- package/dist/backends/proposals.js +182 -0
- package/dist/backends/recall-log.d.ts +42 -0
- package/dist/backends/recall-log.js +143 -0
- package/dist/backends/retry.d.ts +29 -0
- package/dist/backends/retry.js +60 -0
- package/dist/backends/salience.d.ts +57 -0
- package/dist/backends/salience.js +186 -0
- package/dist/backends/sqlite-knowledge.d.ts +37 -0
- package/dist/backends/sqlite-knowledge.js +788 -0
- package/dist/backends/sqlite-vec.d.ts +64 -0
- package/dist/backends/sqlite-vec.js +737 -0
- package/dist/backends/ttl.d.ts +24 -0
- package/dist/backends/ttl.js +50 -0
- package/dist/backends/types.d.ts +562 -0
- package/dist/backends/types.js +8 -0
- package/dist/blocks/harness.d.ts +45 -0
- package/dist/blocks/harness.js +142 -0
- package/dist/blocks/model.d.ts +4 -0
- package/dist/blocks/model.js +56 -0
- package/dist/blocks/types.d.ts +40 -0
- package/dist/blocks/types.js +34 -0
- package/dist/categories.d.ts +16 -0
- package/dist/categories.js +29 -0
- package/dist/cli/args.d.ts +21 -0
- package/dist/cli/args.js +47 -0
- package/dist/cli/bootstrap.d.ts +2 -0
- package/dist/cli/bootstrap.js +214 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.js +206 -0
- package/dist/cli/forget.d.ts +2 -0
- package/dist/cli/forget.js +97 -0
- package/dist/cli/harness.d.ts +2 -0
- package/dist/cli/harness.js +91 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/inject.d.ts +2 -0
- package/dist/cli/inject.js +298 -0
- package/dist/cli/install.d.ts +2 -0
- package/dist/cli/install.js +137 -0
- package/dist/cli/io.d.ts +14 -0
- package/dist/cli/io.js +63 -0
- package/dist/cli/knowledge.d.ts +2 -0
- package/dist/cli/knowledge.js +216 -0
- package/dist/cli/memory.d.ts +2 -0
- package/dist/cli/memory.js +608 -0
- package/dist/cli/migrate.d.ts +2 -0
- package/dist/cli/migrate.js +116 -0
- package/dist/cli/recall.d.ts +2 -0
- package/dist/cli/recall.js +91 -0
- package/dist/cli/remember.d.ts +2 -0
- package/dist/cli/remember.js +111 -0
- package/dist/cli/serve.d.ts +2 -0
- package/dist/cli/serve.js +71 -0
- package/dist/cli/subcommands.d.ts +7 -0
- package/dist/cli/subcommands.js +11 -0
- package/dist/cli/tui/multi-select.d.ts +53 -0
- package/dist/cli/tui/multi-select.js +116 -0
- package/dist/cli/update-identity.d.ts +2 -0
- package/dist/cli/update-identity.js +90 -0
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.js +87 -0
- package/dist/cli/wake.d.ts +2 -0
- package/dist/cli/wake.js +53 -0
- package/dist/clients.d.ts +8 -0
- package/dist/clients.js +63 -0
- package/dist/config.d.ts +59 -0
- package/dist/config.js +160 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +75 -0
- package/dist/injection/harnesses.d.ts +17 -0
- package/dist/injection/harnesses.js +51 -0
- package/dist/injection/render.d.ts +17 -0
- package/dist/injection/render.js +50 -0
- package/dist/injection/writer.d.ts +25 -0
- package/dist/injection/writer.js +118 -0
- package/dist/install/harnesses.d.ts +26 -0
- package/dist/install/harnesses.js +90 -0
- package/dist/install/names.d.ts +16 -0
- package/dist/install/names.js +36 -0
- package/dist/install/render.d.ts +18 -0
- package/dist/install/render.js +42 -0
- package/dist/install/skill-source.d.ts +1 -0
- package/dist/install/skill-source.js +11 -0
- package/dist/path-safety.d.ts +19 -0
- package/dist/path-safety.js +62 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.js +571 -0
- package/dist/tools/append-maintenance-log.d.ts +52 -0
- package/dist/tools/append-maintenance-log.js +103 -0
- package/dist/tools/archive.d.ts +2 -0
- package/dist/tools/archive.js +21 -0
- package/dist/tools/bootstrap.d.ts +11 -0
- package/dist/tools/bootstrap.js +161 -0
- package/dist/tools/dossier.d.ts +1 -0
- package/dist/tools/dossier.js +102 -0
- package/dist/tools/eurorack-import.d.ts +47 -0
- package/dist/tools/eurorack-import.js +199 -0
- package/dist/tools/find-similar.d.ts +3 -0
- package/dist/tools/find-similar.js +26 -0
- package/dist/tools/forget.d.ts +6 -0
- package/dist/tools/forget.js +70 -0
- package/dist/tools/harness.d.ts +18 -0
- package/dist/tools/harness.js +54 -0
- package/dist/tools/identity-scaffold.d.ts +22 -0
- package/dist/tools/identity-scaffold.js +142 -0
- package/dist/tools/identity.d.ts +4 -0
- package/dist/tools/identity.js +226 -0
- package/dist/tools/knowledge-archive.d.ts +5 -0
- package/dist/tools/knowledge-archive.js +24 -0
- package/dist/tools/knowledge-history.d.ts +6 -0
- package/dist/tools/knowledge-history.js +55 -0
- package/dist/tools/knowledge-maintain.d.ts +9 -0
- package/dist/tools/knowledge-maintain.js +113 -0
- package/dist/tools/knowledge-merge.d.ts +8 -0
- package/dist/tools/knowledge-merge.js +40 -0
- package/dist/tools/knowledge-move.d.ts +10 -0
- package/dist/tools/knowledge-move.js +48 -0
- package/dist/tools/knowledge-purge.d.ts +5 -0
- package/dist/tools/knowledge-purge.js +20 -0
- package/dist/tools/knowledge-recall.d.ts +20 -0
- package/dist/tools/knowledge-recall.js +142 -0
- package/dist/tools/knowledge-restore.d.ts +4 -0
- package/dist/tools/knowledge-restore.js +24 -0
- package/dist/tools/knowledge-supersede.d.ts +6 -0
- package/dist/tools/knowledge-supersede.js +36 -0
- package/dist/tools/knowledge-verify.d.ts +8 -0
- package/dist/tools/knowledge-verify.js +39 -0
- package/dist/tools/knowledge-write.d.ts +25 -0
- package/dist/tools/knowledge-write.js +87 -0
- package/dist/tools/memory-audit.d.ts +3 -0
- package/dist/tools/memory-audit.js +47 -0
- package/dist/tools/memory-list.d.ts +4 -0
- package/dist/tools/memory-list.js +23 -0
- package/dist/tools/prune.d.ts +4 -0
- package/dist/tools/prune.js +28 -0
- package/dist/tools/recall.d.ts +4 -0
- package/dist/tools/recall.js +24 -0
- package/dist/tools/remember.d.ts +10 -0
- package/dist/tools/remember.js +43 -0
- package/dist/tools/restore.d.ts +2 -0
- package/dist/tools/restore.js +20 -0
- package/dist/tools/update-identity.d.ts +34 -0
- package/dist/tools/update-identity.js +194 -0
- package/dist/tools/update.d.ts +2 -0
- package/dist/tools/update.js +16 -0
- package/dist/transport/guards.d.ts +35 -0
- package/dist/transport/guards.js +107 -0
- package/dist/transport/http-server.d.ts +17 -0
- package/dist/transport/http-server.js +198 -0
- package/dist/transport/mcp-app-hello.d.ts +3 -0
- package/dist/transport/mcp-app-hello.js +66 -0
- package/dist/widgets/display-modes.html +131 -0
- package/dist/widgets/hello.html +138 -0
- package/dist/widgets/proposals.html +131 -0
- package/dist/widgets/top-of-mind.html +131 -0
- package/package.json +73 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loom knowledge — write / recall / maintain the knowledge store.
|
|
3
|
+
*/
|
|
4
|
+
import { parseArgs } from 'node:util';
|
|
5
|
+
import { knowledgeWrite } from '../tools/knowledge-write.js';
|
|
6
|
+
import { knowledgeRecall } from '../tools/knowledge-recall.js';
|
|
7
|
+
import { knowledgeMaintain } from '../tools/knowledge-maintain.js';
|
|
8
|
+
import { createKnowledgeBackend } from '../backends/index.js';
|
|
9
|
+
import { extractGlobalFlags, resolveEnv } from './args.js';
|
|
10
|
+
import { renderJson } from './io.js';
|
|
11
|
+
const USAGE = `Usage: loom knowledge <subcommand> [options]
|
|
12
|
+
|
|
13
|
+
Subcommands:
|
|
14
|
+
write Upsert an entity page (create or append/revise body in place)
|
|
15
|
+
recall Search knowledge pages (LIKE over title+body+domain)
|
|
16
|
+
maintain Read-only health report (expansion candidates, cold pages, misfile audit)
|
|
17
|
+
|
|
18
|
+
Options (write):
|
|
19
|
+
--slug <slug> Entity key for upsert (default: derived from title)
|
|
20
|
+
--title <title> Page title (required)
|
|
21
|
+
--domain <domain> Domain tag, e.g. music/eurorack (required)
|
|
22
|
+
--body <text> Page body markdown (required)
|
|
23
|
+
--citation <json> Citation JSON: '{"claim":"...","source_kind":"web","source_locator":"...","excerpt":"..."}' (repeatable)
|
|
24
|
+
--json Emit KnowledgeWriteResult
|
|
25
|
+
|
|
26
|
+
Options (recall):
|
|
27
|
+
<query> Search terms (positional, optional)
|
|
28
|
+
--domain <domain> Filter by domain prefix
|
|
29
|
+
--limit <n> Max results (default 10)
|
|
30
|
+
--json Emit KnowledgePageWithCitations[]
|
|
31
|
+
|
|
32
|
+
Options (maintain):
|
|
33
|
+
--expansion-hit-threshold <n> hit_count floor for expansion candidates (default 3)
|
|
34
|
+
--thin-body-threshold <n> body char ceiling for thin pages (default 500)
|
|
35
|
+
--cold-days <n> days without access = cold (default 30)
|
|
36
|
+
--json Emit raw report object
|
|
37
|
+
|
|
38
|
+
Global: --context-dir, --help/-h
|
|
39
|
+
`;
|
|
40
|
+
const SUBCOMMANDS = new Set(['write', 'recall', 'maintain']);
|
|
41
|
+
export async function run(argv, io) {
|
|
42
|
+
const { flags: global, rest } = extractGlobalFlags(argv);
|
|
43
|
+
const sub = rest[0];
|
|
44
|
+
const subRest = rest.slice(1);
|
|
45
|
+
if (!sub || sub === '--help' || sub === '-h') {
|
|
46
|
+
io.stdout(USAGE);
|
|
47
|
+
return sub ? 0 : 2;
|
|
48
|
+
}
|
|
49
|
+
if (!SUBCOMMANDS.has(sub)) {
|
|
50
|
+
io.stderr(`Unknown knowledge subcommand: ${sub}\n${USAGE}`);
|
|
51
|
+
return 2;
|
|
52
|
+
}
|
|
53
|
+
// Subcommand-level --help, honoured before any side effect (see memory.ts).
|
|
54
|
+
if (subRest[0] === '--help' || subRest[0] === '-h') {
|
|
55
|
+
io.stdout(USAGE);
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
const env = resolveEnv(global, io.env);
|
|
59
|
+
if (sub === 'write') {
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = parseArgs({
|
|
63
|
+
args: subRest,
|
|
64
|
+
options: {
|
|
65
|
+
slug: { type: 'string' },
|
|
66
|
+
title: { type: 'string' },
|
|
67
|
+
domain: { type: 'string' },
|
|
68
|
+
body: { type: 'string' },
|
|
69
|
+
citation: { type: 'string', multiple: true },
|
|
70
|
+
},
|
|
71
|
+
strict: true,
|
|
72
|
+
allowPositionals: false,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
io.stderr(`${err.message}\n${USAGE}`);
|
|
77
|
+
return 2;
|
|
78
|
+
}
|
|
79
|
+
const { title, domain, body } = parsed.values;
|
|
80
|
+
if (!title || !domain || !body) {
|
|
81
|
+
io.stderr(`--title, --domain, and --body are required for knowledge write.\n`);
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
const rawCitations = parsed.values.citation ?? [];
|
|
85
|
+
const citations = [];
|
|
86
|
+
for (const raw of rawCitations) {
|
|
87
|
+
try {
|
|
88
|
+
const cit = JSON.parse(raw);
|
|
89
|
+
if (!cit.claim || !cit.source_kind || !cit.excerpt) {
|
|
90
|
+
io.stderr(`Invalid citation JSON (missing claim, source_kind, or excerpt): ${raw}\n`);
|
|
91
|
+
return 2;
|
|
92
|
+
}
|
|
93
|
+
citations.push(cit);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
io.stderr(`Could not parse --citation as JSON: ${raw}\n`);
|
|
97
|
+
return 2;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (env.json) {
|
|
101
|
+
if (citations.length === 0) {
|
|
102
|
+
io.stderr('Error: at least one citation is required for knowledge write.\n');
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
const sourcing = citations.every((c) => c.source_kind === 'conversation') ? 'provisional' : 'sourced';
|
|
106
|
+
const backend = createKnowledgeBackend(env.contextDir);
|
|
107
|
+
try {
|
|
108
|
+
const result = await backend.writePage({
|
|
109
|
+
slug: parsed.values.slug ?? title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''),
|
|
110
|
+
title,
|
|
111
|
+
domain,
|
|
112
|
+
body,
|
|
113
|
+
sourcing,
|
|
114
|
+
citations,
|
|
115
|
+
});
|
|
116
|
+
renderJson(io, result);
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
backend.close();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const text = await knowledgeWrite(env.contextDir, {
|
|
124
|
+
slug: parsed.values.slug,
|
|
125
|
+
title,
|
|
126
|
+
domain,
|
|
127
|
+
body,
|
|
128
|
+
citations,
|
|
129
|
+
});
|
|
130
|
+
io.stdout(text.endsWith('\n') ? text : text + '\n');
|
|
131
|
+
return text.startsWith('Error') ? 1 : 0;
|
|
132
|
+
}
|
|
133
|
+
if (sub === 'recall') {
|
|
134
|
+
let parsed;
|
|
135
|
+
try {
|
|
136
|
+
parsed = parseArgs({
|
|
137
|
+
args: subRest,
|
|
138
|
+
options: {
|
|
139
|
+
domain: { type: 'string' },
|
|
140
|
+
limit: { type: 'string' },
|
|
141
|
+
},
|
|
142
|
+
strict: true,
|
|
143
|
+
allowPositionals: true,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
io.stderr(`${err.message}\n${USAGE}`);
|
|
148
|
+
return 2;
|
|
149
|
+
}
|
|
150
|
+
const query = parsed.positionals[0];
|
|
151
|
+
const limit = parsed.values.limit !== undefined
|
|
152
|
+
? Number.parseInt(parsed.values.limit, 10)
|
|
153
|
+
: undefined;
|
|
154
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {
|
|
155
|
+
io.stderr(`--limit must be a positive integer.\n`);
|
|
156
|
+
return 2;
|
|
157
|
+
}
|
|
158
|
+
if (env.json) {
|
|
159
|
+
const backend = createKnowledgeBackend(env.contextDir);
|
|
160
|
+
try {
|
|
161
|
+
const pages = await backend.queryPages({
|
|
162
|
+
query,
|
|
163
|
+
domain: parsed.values.domain,
|
|
164
|
+
excludeStatus: 'archived',
|
|
165
|
+
limit: limit ?? 10,
|
|
166
|
+
});
|
|
167
|
+
renderJson(io, pages);
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
backend.close();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const text = await knowledgeRecall(env.contextDir, {
|
|
175
|
+
query,
|
|
176
|
+
domain: parsed.values.domain,
|
|
177
|
+
limit,
|
|
178
|
+
});
|
|
179
|
+
io.stdout(text.endsWith('\n') ? text : text + '\n');
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
// maintain
|
|
183
|
+
let parsed;
|
|
184
|
+
try {
|
|
185
|
+
parsed = parseArgs({
|
|
186
|
+
args: subRest,
|
|
187
|
+
options: {
|
|
188
|
+
'expansion-hit-threshold': { type: 'string' },
|
|
189
|
+
'thin-body-threshold': { type: 'string' },
|
|
190
|
+
'cold-days': { type: 'string' },
|
|
191
|
+
},
|
|
192
|
+
strict: true,
|
|
193
|
+
allowPositionals: false,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
io.stderr(`${err.message}\n${USAGE}`);
|
|
198
|
+
return 2;
|
|
199
|
+
}
|
|
200
|
+
const expansionHitThreshold = parsed.values['expansion-hit-threshold'] !== undefined
|
|
201
|
+
? Number.parseInt(parsed.values['expansion-hit-threshold'], 10)
|
|
202
|
+
: undefined;
|
|
203
|
+
const thinBodyThreshold = parsed.values['thin-body-threshold'] !== undefined
|
|
204
|
+
? Number.parseInt(parsed.values['thin-body-threshold'], 10)
|
|
205
|
+
: undefined;
|
|
206
|
+
const coldDays = parsed.values['cold-days'] !== undefined
|
|
207
|
+
? Number.parseInt(parsed.values['cold-days'], 10)
|
|
208
|
+
: undefined;
|
|
209
|
+
const text = await knowledgeMaintain(env.contextDir, {
|
|
210
|
+
expansionHitThreshold,
|
|
211
|
+
thinBodyThreshold,
|
|
212
|
+
coldDays,
|
|
213
|
+
});
|
|
214
|
+
io.stdout(text.endsWith('\n') ? text : text + '\n');
|
|
215
|
+
return 0;
|
|
216
|
+
}
|