@tt-a1i/hive 2.1.4 → 2.1.5
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 +16 -0
- package/dist/src/cli/team.d.ts +4 -1
- package/dist/src/cli/team.js +95 -6
- package/dist/src/server/agent-startup-instructions.js +1 -1
- package/dist/src/server/hive-team-guidance.js +2 -2
- package/dist/src/server/routes-team-memory.js +53 -2
- package/dist/src/server/routes-workspace-memory.js +31 -2
- package/dist/src/server/runtime-store-contract.d.ts +2 -0
- package/dist/src/server/runtime-store-dream.d.ts +2 -5
- package/dist/src/server/runtime-store-dream.js +2 -12
- package/dist/src/server/runtime-store-helpers.d.ts +4 -0
- package/dist/src/server/runtime-store-helpers.js +21 -1
- package/dist/src/server/runtime-store-memory.d.ts +6 -0
- package/dist/src/server/runtime-store-memory.js +1 -0
- package/dist/src/server/sqlite-schema-v36.d.ts +3 -0
- package/dist/src/server/sqlite-schema-v36.js +21 -0
- package/dist/src/server/sqlite-schema.d.ts +1 -1
- package/dist/src/server/sqlite-schema.js +6 -1
- package/dist/src/server/team-memory-diagnostics.d.ts +86 -0
- package/dist/src/server/team-memory-diagnostics.js +87 -0
- package/dist/src/server/team-memory-digest.d.ts +7 -0
- package/dist/src/server/team-memory-digest.js +22 -5
- package/dist/src/server/team-memory-dream-applier.js +20 -3
- package/dist/src/server/team-memory-dream-cli.d.ts +13 -0
- package/dist/src/server/team-memory-dream-cli.js +115 -0
- package/dist/src/server/team-memory-dream-input.d.ts +15 -0
- package/dist/src/server/team-memory-dream-input.js +14 -0
- package/dist/src/server/team-memory-dream-ops.d.ts +4 -1
- package/dist/src/server/team-memory-dream-ops.js +32 -3
- package/dist/src/server/team-memory-dream-prompt.js +5 -3
- package/dist/src/server/team-memory-dream-reverter.js +13 -3
- package/dist/src/server/team-memory-dream-run-store.d.ts +1 -0
- package/dist/src/server/team-memory-dream-run-store.js +20 -0
- package/dist/src/server/team-memory-dream-runner.d.ts +10 -1
- package/dist/src/server/team-memory-dream-runner.js +34 -5
- package/dist/src/server/team-memory-dream-scheduler.js +2 -2
- package/dist/src/server/team-memory-dream-store.d.ts +2 -1
- package/dist/src/server/team-memory-dream-store.js +1 -1
- package/dist/src/server/team-memory-dream-types.d.ts +5 -1
- package/dist/src/server/team-memory-export.js +7 -0
- package/dist/src/server/team-memory-http-serializers.d.ts +15 -0
- package/dist/src/server/team-memory-http-serializers.js +7 -0
- package/dist/src/server/team-memory-provider.d.ts +33 -0
- package/dist/src/server/team-memory-provider.js +54 -0
- package/dist/src/server/team-memory-store.d.ts +10 -3
- package/dist/src/server/team-memory-store.js +134 -58
- package/dist/src/shared/team-memory.d.ts +13 -0
- package/dist/src/shared/team-memory.js +12 -0
- package/package.json +1 -1
- package/web/dist/assets/{AddWorkerDialog-CkCGKa0N.js → AddWorkerDialog-AxzWv2T8.js} +2 -2
- package/web/dist/assets/AddWorkspaceFlow-D-Yh_kk_.js +1 -0
- package/web/dist/assets/{FirstRunWizard-Db4HWbBQ.js → FirstRunWizard-nAK4Eprj.js} +1 -1
- package/web/dist/assets/{MarketplaceDrawer-DHwl1if1.js → MarketplaceDrawer-B8JW-znT.js} +1 -1
- package/web/dist/assets/{TaskGraphDrawer-B_OibVQO.js → TaskGraphDrawer-BQ9Wr41D.js} +1 -1
- package/web/dist/assets/{WhatsNewDialog-9QXlLVfy.js → WhatsNewDialog-D7DwCnTR.js} +1 -1
- package/web/dist/assets/{WorkerModal-BGdtte3-.js → WorkerModal-tU-XkiFG.js} +1 -1
- package/web/dist/assets/{WorkflowsDrawer-DRuS0Ao5.js → WorkflowsDrawer-DCa-HN3D.js} +1 -1
- package/web/dist/assets/WorkspaceMemoryDrawer-4hLlu8BO.js +1 -0
- package/web/dist/assets/WorkspaceTaskDrawer-D3LcLkw_.js +1 -0
- package/web/dist/assets/{index-BiGD5NhO.js → index-B8tv0NRK.js} +13 -13
- package/web/dist/assets/{search-BHvXxsdK.js → search-CcRvD2Q5.js} +1 -1
- package/web/dist/assets/{square-terminal-CzkQzjCU.js → square-terminal-zBgH6nhI.js} +1 -1
- package/web/dist/index.html +1 -1
- package/web/dist/sw.js +1 -1
- package/web/dist/assets/AddWorkspaceFlow-Cd73iChz.js +0 -1
- package/web/dist/assets/WorkspaceMemoryDrawer-C8PuHo0x.js +0 -1
- package/web/dist/assets/WorkspaceTaskDrawer-6mbgRoOq.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 2.1.5 - 2026-06-21
|
|
6
|
+
|
|
7
|
+
Ambient memory reliability and background consolidation.
|
|
8
|
+
|
|
9
|
+
- Makes team memory quieter and more automatic by removing the visible
|
|
10
|
+
candidate-review surface from the Memory drawer while keeping active,
|
|
11
|
+
archived, and Dream audit history available when you look for it.
|
|
12
|
+
- Adds user-scoped memory for lightweight personal preferences and working
|
|
13
|
+
style, without mixing those preferences into workspace project facts.
|
|
14
|
+
- Adds structured procedure references so workflows, skills, and checklists can
|
|
15
|
+
be recalled as short references instead of long copied instructions.
|
|
16
|
+
- Improves dispatch memory retrieval so unrelated worker-role matches do not
|
|
17
|
+
inject stale or cross-task memory into a new assignment.
|
|
18
|
+
- Moves scheduled Dream consolidation into a background apply path with
|
|
19
|
+
transaction checks, source-window validation, failure isolation, and revert.
|
|
20
|
+
|
|
5
21
|
## 2.1.4 - 2026-06-21
|
|
6
22
|
|
|
7
23
|
Quieter onboarding and team activity signals.
|
package/dist/src/cli/team.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type MemoryKind } from '../shared/team-memory.js';
|
|
1
|
+
import { type MemoryKind, type MemoryProcedureRef, type MemoryScope } from '../shared/team-memory.js';
|
|
2
2
|
interface ParsedCancelArgs {
|
|
3
3
|
dispatchId: string;
|
|
4
4
|
reason: string;
|
|
@@ -19,6 +19,8 @@ export declare const parseRecallArgs: (args: string[]) => {
|
|
|
19
19
|
export interface ParsedMemoryAddArgs {
|
|
20
20
|
body: string;
|
|
21
21
|
kind: MemoryKind;
|
|
22
|
+
procedureRef: MemoryProcedureRef | null;
|
|
23
|
+
scope: MemoryScope;
|
|
22
24
|
tags: string[];
|
|
23
25
|
}
|
|
24
26
|
export declare const parseMemoryAddArgs: (args: string[]) => ParsedMemoryAddArgs;
|
|
@@ -26,6 +28,7 @@ export declare const parseMemoryShowArgs: (args: string[]) => {
|
|
|
26
28
|
memoryId: string;
|
|
27
29
|
};
|
|
28
30
|
export declare const parseMemorySearchArgs: (args: string[]) => {
|
|
31
|
+
scope: "workspace" | "user" | "all";
|
|
29
32
|
limit?: number;
|
|
30
33
|
query: string;
|
|
31
34
|
};
|
package/dist/src/cli/team.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import { BUILTIN_COMMAND_PRESET_CLI_LIST } from '../server/command-preset-defaults.js';
|
|
3
3
|
import { sameFilesystemPath } from '../server/path-canonicalization.js';
|
|
4
|
-
import { isMemoryKind, MEMORY_BODY_MAX_CHARS, MEMORY_KINDS, MEMORY_QUERY_MAX_CHARS, MEMORY_SEARCH_MAX_LIMIT, MEMORY_TAG_MAX_CHARS, MEMORY_TAG_MAX_COUNT, } from '../shared/team-memory.js';
|
|
4
|
+
import { isMemoryKind, isMemoryProcedureRefType, isMemoryScope, MEMORY_BODY_MAX_CHARS, MEMORY_KINDS, MEMORY_PROCEDURE_REF_ID_MAX_CHARS, MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS, MEMORY_PROCEDURE_REF_TYPES, MEMORY_QUERY_MAX_CHARS, MEMORY_SCOPES, MEMORY_SEARCH_MAX_LIMIT, MEMORY_TAG_MAX_CHARS, MEMORY_TAG_MAX_COUNT, } from '../shared/team-memory.js';
|
|
5
5
|
import { RECALL_QUERY_MAX_CHARS } from '../shared/team-recall.js';
|
|
6
6
|
const REQUIRED_ENV_KEYS = [
|
|
7
7
|
'HIVE_PORT',
|
|
@@ -14,9 +14,9 @@ const TEAM_USAGE = [
|
|
|
14
14
|
' team list',
|
|
15
15
|
' team next (tasks in .hive/tasks.md that are unblocked now — those whose [needs: #n] deps are all done)',
|
|
16
16
|
' team recall "<query>" [--limit <n>] [--window <n>]',
|
|
17
|
-
' team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--tag <tag>]',
|
|
17
|
+
' team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--scope workspace|user] [--tag <tag>] [--ref-type workflow|skill|procedure|template|doc --ref-id <id> [--ref-title <title>]]',
|
|
18
18
|
' team memory show <memory-id>',
|
|
19
|
-
' team memory search "<query>" [--limit <n>]',
|
|
19
|
+
' team memory search "<query>" [--limit <n>] [--scope workspace|user|all]',
|
|
20
20
|
' team memory dream show <dream-run-id>',
|
|
21
21
|
' team memory apply --run <dream-run-id> --stdin',
|
|
22
22
|
' team memory forget <memory-id>',
|
|
@@ -107,9 +107,9 @@ const REPORT_USAGE = 'Usage: team report (<result> | --stdin) [--dispatch <dispa
|
|
|
107
107
|
const STATUS_USAGE = 'Usage: team status (<current status> | --stdin) [--artifact <path>]';
|
|
108
108
|
const CANCEL_USAGE = 'Usage: team cancel --dispatch <dispatch-id> <reason>';
|
|
109
109
|
const RECALL_USAGE = 'Usage: team recall "<query>" [--limit <n>] [--window <n>]';
|
|
110
|
-
const MEMORY_ADD_USAGE = 'Usage: team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--tag <tag>]';
|
|
110
|
+
const MEMORY_ADD_USAGE = 'Usage: team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--scope workspace|user] [--tag <tag>] [--ref-type workflow|skill|procedure|template|doc --ref-id <id> [--ref-title <title>]]';
|
|
111
111
|
const MEMORY_SHOW_USAGE = 'Usage: team memory show <memory-id>';
|
|
112
|
-
const MEMORY_SEARCH_USAGE = 'Usage: team memory search "<query>" [--limit <n>]';
|
|
112
|
+
const MEMORY_SEARCH_USAGE = 'Usage: team memory search "<query>" [--limit <n>] [--scope workspace|user|all]';
|
|
113
113
|
const MEMORY_DREAM_SHOW_USAGE = 'Usage: team memory dream show <dream-run-id>';
|
|
114
114
|
const MEMORY_APPLY_USAGE = 'Usage: team memory apply --run <dream-run-id> --stdin';
|
|
115
115
|
const MEMORY_FORGET_USAGE = 'Usage: team memory forget <memory-id>';
|
|
@@ -256,6 +256,10 @@ export const parseMemoryAddArgs = (args) => {
|
|
|
256
256
|
const positionals = [];
|
|
257
257
|
const tags = [];
|
|
258
258
|
let kind = 'fact';
|
|
259
|
+
let procedureRefId;
|
|
260
|
+
let procedureRefTitle = null;
|
|
261
|
+
let procedureRefType;
|
|
262
|
+
let scope = 'workspace';
|
|
259
263
|
for (let index = 0; index < args.length; index += 1) {
|
|
260
264
|
const arg = args[index];
|
|
261
265
|
if (arg === undefined)
|
|
@@ -272,6 +276,58 @@ export const parseMemoryAddArgs = (args) => {
|
|
|
272
276
|
index += 1;
|
|
273
277
|
continue;
|
|
274
278
|
}
|
|
279
|
+
if (arg === '--scope') {
|
|
280
|
+
const next = args[index + 1];
|
|
281
|
+
if (next === undefined || next.startsWith('--')) {
|
|
282
|
+
throw new Error(`--scope requires a value\n\n${MEMORY_ADD_USAGE}`);
|
|
283
|
+
}
|
|
284
|
+
if (!isMemoryScope(next)) {
|
|
285
|
+
throw new Error(`--scope must be one of: ${MEMORY_SCOPES.join(', ')}\n\n${MEMORY_ADD_USAGE}`);
|
|
286
|
+
}
|
|
287
|
+
scope = next;
|
|
288
|
+
index += 1;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (arg === '--ref-type') {
|
|
292
|
+
const next = args[index + 1];
|
|
293
|
+
if (next === undefined || next.startsWith('--')) {
|
|
294
|
+
throw new Error(`--ref-type requires a value\n\n${MEMORY_ADD_USAGE}`);
|
|
295
|
+
}
|
|
296
|
+
if (!isMemoryProcedureRefType(next)) {
|
|
297
|
+
throw new Error(`--ref-type must be one of: ${MEMORY_PROCEDURE_REF_TYPES.join(', ')}\n\n${MEMORY_ADD_USAGE}`);
|
|
298
|
+
}
|
|
299
|
+
procedureRefType = next;
|
|
300
|
+
index += 1;
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (arg === '--ref-id') {
|
|
304
|
+
const next = args[index + 1];
|
|
305
|
+
if (next === undefined || next.startsWith('--')) {
|
|
306
|
+
throw new Error(`--ref-id requires a value\n\n${MEMORY_ADD_USAGE}`);
|
|
307
|
+
}
|
|
308
|
+
const refId = next.trim();
|
|
309
|
+
if (!refId)
|
|
310
|
+
throw new Error(`--ref-id requires a non-empty value\n\n${MEMORY_ADD_USAGE}`);
|
|
311
|
+
if ([...refId].length > MEMORY_PROCEDURE_REF_ID_MAX_CHARS) {
|
|
312
|
+
throw new Error(`--ref-id must be ${MEMORY_PROCEDURE_REF_ID_MAX_CHARS} characters or fewer\n\n${MEMORY_ADD_USAGE}`);
|
|
313
|
+
}
|
|
314
|
+
procedureRefId = refId;
|
|
315
|
+
index += 1;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (arg === '--ref-title') {
|
|
319
|
+
const next = args[index + 1];
|
|
320
|
+
if (next === undefined || next.startsWith('--')) {
|
|
321
|
+
throw new Error(`--ref-title requires a value\n\n${MEMORY_ADD_USAGE}`);
|
|
322
|
+
}
|
|
323
|
+
const refTitle = next.trim();
|
|
324
|
+
if ([...refTitle].length > MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS) {
|
|
325
|
+
throw new Error(`--ref-title must be ${MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS} characters or fewer\n\n${MEMORY_ADD_USAGE}`);
|
|
326
|
+
}
|
|
327
|
+
procedureRefTitle = refTitle || null;
|
|
328
|
+
index += 1;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
275
331
|
if (arg === '--tag') {
|
|
276
332
|
const next = args[index + 1];
|
|
277
333
|
if (next === undefined || next.startsWith('--')) {
|
|
@@ -307,7 +363,23 @@ export const parseMemoryAddArgs = (args) => {
|
|
|
307
363
|
if ([...body].length > MEMORY_BODY_MAX_CHARS) {
|
|
308
364
|
throw new Error(`body must be ${MEMORY_BODY_MAX_CHARS} characters or fewer\n\n${MEMORY_ADD_USAGE}`);
|
|
309
365
|
}
|
|
310
|
-
|
|
366
|
+
if ((procedureRefType || procedureRefId || procedureRefTitle) &&
|
|
367
|
+
(!procedureRefType || !procedureRefId)) {
|
|
368
|
+
throw new Error(`--ref-type and --ref-id must be provided together\n\n${MEMORY_ADD_USAGE}`);
|
|
369
|
+
}
|
|
370
|
+
const procedureRef = procedureRefType && procedureRefId
|
|
371
|
+
? { id: procedureRefId, title: procedureRefTitle, type: procedureRefType }
|
|
372
|
+
: null;
|
|
373
|
+
if (kind === 'procedure_ref' && !procedureRef) {
|
|
374
|
+
throw new Error(`--kind procedure_ref requires --ref-type and --ref-id\n\n${MEMORY_ADD_USAGE}`);
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
body,
|
|
378
|
+
kind,
|
|
379
|
+
procedureRef,
|
|
380
|
+
scope,
|
|
381
|
+
tags,
|
|
382
|
+
};
|
|
311
383
|
};
|
|
312
384
|
export const parseMemoryShowArgs = (args) => {
|
|
313
385
|
if (args.length !== 1 || !args[0] || args[0].startsWith('--')) {
|
|
@@ -318,6 +390,7 @@ export const parseMemoryShowArgs = (args) => {
|
|
|
318
390
|
export const parseMemorySearchArgs = (args) => {
|
|
319
391
|
const positionals = [];
|
|
320
392
|
let limit;
|
|
393
|
+
let scope = 'workspace';
|
|
321
394
|
for (let index = 0; index < args.length; index += 1) {
|
|
322
395
|
const arg = args[index];
|
|
323
396
|
if (arg === undefined)
|
|
@@ -335,6 +408,18 @@ export const parseMemorySearchArgs = (args) => {
|
|
|
335
408
|
index += 1;
|
|
336
409
|
continue;
|
|
337
410
|
}
|
|
411
|
+
if (arg === '--scope') {
|
|
412
|
+
const next = args[index + 1];
|
|
413
|
+
if (next === undefined || next.startsWith('--')) {
|
|
414
|
+
throw new Error(`--scope requires a value\n\n${MEMORY_SEARCH_USAGE}`);
|
|
415
|
+
}
|
|
416
|
+
if (next !== 'all' && !isMemoryScope(next)) {
|
|
417
|
+
throw new Error(`--scope must be workspace, user, or all\n\n${MEMORY_SEARCH_USAGE}`);
|
|
418
|
+
}
|
|
419
|
+
scope = next;
|
|
420
|
+
index += 1;
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
338
423
|
if (arg.startsWith('--')) {
|
|
339
424
|
throw new Error(`Unknown argument: ${arg}\n\n${MEMORY_SEARCH_USAGE}`);
|
|
340
425
|
}
|
|
@@ -353,6 +438,7 @@ export const parseMemorySearchArgs = (args) => {
|
|
|
353
438
|
return {
|
|
354
439
|
query,
|
|
355
440
|
...(limit !== undefined ? { limit } : {}),
|
|
441
|
+
scope,
|
|
356
442
|
};
|
|
357
443
|
};
|
|
358
444
|
export const parseMemoryDreamShowArgs = (args) => {
|
|
@@ -515,6 +601,8 @@ export const runTeamCommand = async (argv) => {
|
|
|
515
601
|
token: env.HIVE_AGENT_TOKEN,
|
|
516
602
|
body: memory.body,
|
|
517
603
|
kind: memory.kind,
|
|
604
|
+
procedure_ref: memory.procedureRef,
|
|
605
|
+
scope: memory.scope,
|
|
518
606
|
tags: memory.tags,
|
|
519
607
|
});
|
|
520
608
|
console.log(JSON.stringify(await response.json()));
|
|
@@ -541,6 +629,7 @@ export const runTeamCommand = async (argv) => {
|
|
|
541
629
|
token: env.HIVE_AGENT_TOKEN,
|
|
542
630
|
query: memory.query,
|
|
543
631
|
...(memory.limit !== undefined ? { limit: memory.limit } : {}),
|
|
632
|
+
scope: memory.scope,
|
|
544
633
|
});
|
|
545
634
|
console.log(JSON.stringify(await response.json()));
|
|
546
635
|
return;
|
|
@@ -24,7 +24,7 @@ export const buildAgentStartupInstructions = ({ agent, memoryDigest, workspace,
|
|
|
24
24
|
lines.push(memoryDigest, '');
|
|
25
25
|
}
|
|
26
26
|
if (agent.role === 'orchestrator') {
|
|
27
|
-
lines.push('Your responsibilities:', '- Respond to the user directly; clarify the goal and break it into dispatchable tasks', `- Maintain ${TASKS_RELATIVE_PATH} (GFM task list; mark dependencies with a trailing \`[needs: #2, #5]\` — 1-based positions; \`team next\` lists the tasks unblocked right now)`, '- Dispatch by worker name and drive the next step from each report', '', 'Available team commands:', '- team list', '- team next', '- team recall "<query>" [--limit <n>] [--window <n>]', '- team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--tag <tag>]', '- team memory show <memory-id>', '- team memory search "<query>" [--limit <n>]', '- team memory dream show <dream-run-id>', '- team memory apply --run <dream-run-id> --stdin', '- team memory forget <memory-id>', '- team send "<worker-name>" "<task>"', `- team spawn <role> [--name <n>] [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>] [--ephemeral]`, '- team dismiss <worker-name>', '- team cancel --dispatch <id> "<reason>"', ...(workflowsEnabled
|
|
27
|
+
lines.push('Your responsibilities:', '- Respond to the user directly; clarify the goal and break it into dispatchable tasks', `- Maintain ${TASKS_RELATIVE_PATH} (GFM task list; mark dependencies with a trailing \`[needs: #2, #5]\` — 1-based positions; \`team next\` lists the tasks unblocked right now)`, '- Dispatch by worker name and drive the next step from each report', '', 'Available team commands:', '- team list', '- team next', '- team recall "<query>" [--limit <n>] [--window <n>]', '- team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--scope workspace|user] [--tag <tag>] [--ref-type workflow|skill|procedure|template|doc --ref-id <id> [--ref-title <title>]]', '- team memory show <memory-id>', '- team memory search "<query>" [--limit <n>] [--scope workspace|user|all]', '- team memory dream show <dream-run-id>', '- team memory apply --run <dream-run-id> --stdin', '- team memory forget <memory-id>', '- team send "<worker-name>" "<task>"', `- team spawn <role> [--name <n>] [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>] [--ephemeral]`, '- team dismiss <worker-name>', '- team cancel --dispatch <id> "<reason>"', ...(workflowsEnabled
|
|
28
28
|
? [
|
|
29
29
|
'- team workflow run --stdin (fan-out / staged work — see .hive/PROTOCOL.md for the DSL)',
|
|
30
30
|
]
|
|
@@ -320,9 +320,9 @@ export const buildProtocolDoc = (cliPolicy = DEFAULT_WORKFLOW_CLI_POLICY, flags
|
|
|
320
320
|
'- `team list` — show workspace members and their status; each worker lists its open dispatches (id, age, queued/submitted) — use those ids for `team cancel`',
|
|
321
321
|
'- `team next` — tasks in `.hive/tasks.md` that are unblocked right now (mark dependencies with a trailing `[needs: #2, #5]` — 1-based task positions; `team next` returns only tasks whose deps are all done)',
|
|
322
322
|
'- `team recall "<query>" [--limit <n>] [--window <n>]` — search prior team messages/reports in this workspace',
|
|
323
|
-
'- `team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--tag <tag>]` — save durable workspace memory (orchestrator entries become active)',
|
|
323
|
+
'- `team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--scope workspace|user] [--tag <tag>] [--ref-type workflow|skill|procedure|template|doc --ref-id <id> [--ref-title <title>]]` — save durable workspace/user memory (orchestrator entries become active)',
|
|
324
324
|
'- `team memory show <memory-id>` — inspect a memory entry and evidence snapshots',
|
|
325
|
-
'- `team memory search "<query>" [--limit <n>]` — search active
|
|
325
|
+
'- `team memory search "<query>" [--limit <n>] [--scope workspace|user|all]` — search active memory',
|
|
326
326
|
'- `team memory dream show <dream-run-id>` — inspect the bounded input for a pending memory maintenance run',
|
|
327
327
|
'- `team memory apply --run <dream-run-id> --stdin` — apply strict JSON Dream ops for a pending maintenance run',
|
|
328
328
|
'- `team memory forget <memory-id>` — archive obsolete memory (orchestrator only; does not physically delete evidence)',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isMemoryKind, MEMORY_BODY_MAX_CHARS, MEMORY_KINDS, MEMORY_QUERY_MAX_CHARS, MEMORY_SEARCH_MAX_LIMIT, MEMORY_TAG_MAX_CHARS, MEMORY_TAG_MAX_COUNT, } from '../shared/team-memory.js';
|
|
1
|
+
import { isMemoryKind, isMemoryProcedureRefType, isMemoryScope, MEMORY_BODY_MAX_CHARS, MEMORY_KINDS, MEMORY_PROCEDURE_REF_ID_MAX_CHARS, MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS, MEMORY_PROCEDURE_REF_TYPES, MEMORY_QUERY_MAX_CHARS, MEMORY_SCOPES, MEMORY_SEARCH_MAX_LIMIT, MEMORY_TAG_MAX_CHARS, MEMORY_TAG_MAX_COUNT, } from '../shared/team-memory.js';
|
|
2
2
|
import { BadRequestError } from './http-errors.js';
|
|
3
3
|
import { readJsonBody, route, sendJson } from './route-helpers.js';
|
|
4
4
|
import { authenticateCliAgent, requireCommandForRole } from './team-authz.js';
|
|
@@ -42,6 +42,49 @@ const parseKind = (value) => {
|
|
|
42
42
|
}
|
|
43
43
|
return value;
|
|
44
44
|
};
|
|
45
|
+
const parseScope = (value) => {
|
|
46
|
+
if (value === undefined)
|
|
47
|
+
return 'workspace';
|
|
48
|
+
if (!isMemoryScope(value)) {
|
|
49
|
+
throw new BadRequestError(`scope must be one of: ${MEMORY_SCOPES.join(', ')}`);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
};
|
|
53
|
+
const parseSearchScopes = (value) => {
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
return ['workspace'];
|
|
56
|
+
if (value === 'all')
|
|
57
|
+
return ['workspace', 'user'];
|
|
58
|
+
if (isMemoryScope(value))
|
|
59
|
+
return [value];
|
|
60
|
+
throw new BadRequestError(`scope must be workspace, user, or all`);
|
|
61
|
+
};
|
|
62
|
+
const parseProcedureRef = (value) => {
|
|
63
|
+
if (value === undefined || value === null)
|
|
64
|
+
return null;
|
|
65
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
66
|
+
throw new BadRequestError('procedure_ref must be an object');
|
|
67
|
+
}
|
|
68
|
+
const record = value;
|
|
69
|
+
if (!isMemoryProcedureRefType(record.type)) {
|
|
70
|
+
throw new BadRequestError(`procedure_ref.type must be one of: ${MEMORY_PROCEDURE_REF_TYPES.join(', ')}`);
|
|
71
|
+
}
|
|
72
|
+
if (typeof record.id !== 'string' || !record.id.trim()) {
|
|
73
|
+
throw new BadRequestError('procedure_ref.id must be a non-empty string');
|
|
74
|
+
}
|
|
75
|
+
const id = record.id.trim();
|
|
76
|
+
if ([...id].length > MEMORY_PROCEDURE_REF_ID_MAX_CHARS) {
|
|
77
|
+
throw new BadRequestError(`procedure_ref.id must be ${MEMORY_PROCEDURE_REF_ID_MAX_CHARS} characters or fewer`);
|
|
78
|
+
}
|
|
79
|
+
if (record.title !== undefined && record.title !== null && typeof record.title !== 'string') {
|
|
80
|
+
throw new BadRequestError('procedure_ref.title must be a string');
|
|
81
|
+
}
|
|
82
|
+
const title = typeof record.title === 'string' ? record.title.trim() || null : null;
|
|
83
|
+
if (title !== null && [...title].length > MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS) {
|
|
84
|
+
throw new BadRequestError(`procedure_ref.title must be ${MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS} characters or fewer`);
|
|
85
|
+
}
|
|
86
|
+
return { id, title, type: record.type };
|
|
87
|
+
};
|
|
45
88
|
const parseTags = (value) => {
|
|
46
89
|
if (value === undefined)
|
|
47
90
|
return [];
|
|
@@ -83,6 +126,11 @@ export const teamMemoryRoutes = [
|
|
|
83
126
|
const body = await readJsonBody(request);
|
|
84
127
|
const { agent, workspaceId } = authenticateMemoryRequest(body, store);
|
|
85
128
|
requireCommandForRole(agent, 'memory_add');
|
|
129
|
+
const kind = parseKind(body.kind);
|
|
130
|
+
const procedureRef = parseProcedureRef(body.procedure_ref);
|
|
131
|
+
if (kind === 'procedure_ref' && procedureRef === null) {
|
|
132
|
+
throw new BadRequestError('procedure_ref is required when kind is procedure_ref');
|
|
133
|
+
}
|
|
86
134
|
const memory = store.addMemoryEntry({
|
|
87
135
|
actor: {
|
|
88
136
|
id: agent.id,
|
|
@@ -90,7 +138,9 @@ export const teamMemoryRoutes = [
|
|
|
90
138
|
role: agent.role,
|
|
91
139
|
},
|
|
92
140
|
body: requireMemoryBody(body.body),
|
|
93
|
-
kind
|
|
141
|
+
kind,
|
|
142
|
+
procedureRef,
|
|
143
|
+
scope: parseScope(body.scope),
|
|
94
144
|
tags: parseTags(body.tags),
|
|
95
145
|
workspaceId,
|
|
96
146
|
});
|
|
@@ -121,6 +171,7 @@ export const teamMemoryRoutes = [
|
|
|
121
171
|
const limit = parseLimit(body.limit);
|
|
122
172
|
const results = store.searchMemoryEntries(workspaceId, requireMemoryQuery(body.query), {
|
|
123
173
|
...(limit !== undefined ? { limit } : {}),
|
|
174
|
+
scopes: parseSearchScopes(body.scope),
|
|
124
175
|
});
|
|
125
176
|
sendJson(response, 200, {
|
|
126
177
|
ok: true,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MEMORY_QUERY_MAX_CHARS, MEMORY_SEARCH_MAX_LIMIT } from '../shared/team-memory.js';
|
|
1
|
+
import { isMemoryScope, MEMORY_QUERY_MAX_CHARS, MEMORY_SEARCH_MAX_LIMIT, } from '../shared/team-memory.js';
|
|
2
2
|
import { BadRequestError } from './http-errors.js';
|
|
3
3
|
import { getRequiredParam, readJsonBody, route, sendJson } from './route-helpers.js';
|
|
4
4
|
import { readWorkspaceMemoryDreamEnabled, readWorkspaceMemoryEnabled, serializeWorkspaceMemoryDreamEnabled, serializeWorkspaceMemoryEnabled, workspaceMemoryDreamEnabledKey, workspaceMemoryEnabledKey, } from './team-memory-feature.js';
|
|
@@ -30,6 +30,15 @@ const parseQuery = (value) => {
|
|
|
30
30
|
}
|
|
31
31
|
return query;
|
|
32
32
|
};
|
|
33
|
+
const parseScopes = (value) => {
|
|
34
|
+
if (value === null)
|
|
35
|
+
return ['workspace'];
|
|
36
|
+
if (value === 'all')
|
|
37
|
+
return ['workspace', 'user'];
|
|
38
|
+
if (isMemoryScope(value))
|
|
39
|
+
return [value];
|
|
40
|
+
throw new BadRequestError('scope must be workspace, user, or all');
|
|
41
|
+
};
|
|
33
42
|
const requireBoolean = (value, field) => {
|
|
34
43
|
if (typeof value !== 'boolean')
|
|
35
44
|
throw new BadRequestError(`${field} must be a boolean`);
|
|
@@ -69,13 +78,15 @@ export const workspaceMemoryRoutes = [
|
|
|
69
78
|
const statuses = parseStatuses(url.searchParams.get('status'));
|
|
70
79
|
const limit = parseLimit(url.searchParams.get('limit'));
|
|
71
80
|
const query = parseQuery(url.searchParams.get('query'));
|
|
81
|
+
const scopes = parseScopes(url.searchParams.get('scope'));
|
|
72
82
|
const memories = query
|
|
73
83
|
? store.searchMemoryEntries(workspaceId, query, {
|
|
74
84
|
includeDisabled: true,
|
|
75
85
|
limit,
|
|
86
|
+
scopes,
|
|
76
87
|
statuses,
|
|
77
88
|
})
|
|
78
|
-
: store.listMemoryEntries(workspaceId, { limit, statuses });
|
|
89
|
+
: store.listMemoryEntries(workspaceId, { limit, scopes, statuses });
|
|
79
90
|
sendJson(response, 200, { memories: memories.map(serializeMemoryEntry), ok: true });
|
|
80
91
|
}),
|
|
81
92
|
route('GET', '/api/ui/workspaces/:workspaceId/memory/injections', ({ params, request, response, store }) => {
|
|
@@ -109,6 +120,24 @@ export const workspaceMemoryRoutes = [
|
|
|
109
120
|
ok: true,
|
|
110
121
|
});
|
|
111
122
|
}),
|
|
123
|
+
route('GET', '/api/ui/workspaces/:workspaceId/memory/diagnostics', ({ params, request, response, store }) => {
|
|
124
|
+
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
125
|
+
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Missing workspaceId');
|
|
126
|
+
if (!workspaceId)
|
|
127
|
+
return;
|
|
128
|
+
if (!requireWorkspace(response, store, workspaceId))
|
|
129
|
+
return;
|
|
130
|
+
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
131
|
+
sendJson(response, 200, {
|
|
132
|
+
diagnostics: store.getMemoryDiagnostics({
|
|
133
|
+
query: parseQuery(url.searchParams.get('query')) || null,
|
|
134
|
+
taskText: parseQuery(url.searchParams.get('task_text')) || null,
|
|
135
|
+
workerDescription: parseQuery(url.searchParams.get('worker_description')) || null,
|
|
136
|
+
workspaceId,
|
|
137
|
+
}),
|
|
138
|
+
ok: true,
|
|
139
|
+
});
|
|
140
|
+
}),
|
|
112
141
|
route('PUT', '/api/ui/workspaces/:workspaceId/memory/settings', async ({ params, request, response, store }) => {
|
|
113
142
|
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
114
143
|
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Missing workspaceId');
|
|
@@ -13,6 +13,7 @@ import type { RemotePairing } from './remote-pairing.js';
|
|
|
13
13
|
import type { RemoteTunnel, TunnelStatus } from './remote-tunnel.js';
|
|
14
14
|
import type { MemoryDreamInput } from './runtime-store-dream.js';
|
|
15
15
|
import type { SettingsStore } from './settings-store.js';
|
|
16
|
+
import type { BuildMemoryDiagnosticsInput, MemoryDiagnostics } from './team-memory-diagnostics.js';
|
|
16
17
|
import type { DreamRunRecord } from './team-memory-dream-store.js';
|
|
17
18
|
import type { AddMemoryEntryInput, LogMemoryInjectionsInput, MemoryEntryWithSources, MemoryInjectionWithMemory, MemoryListOptions, MemorySearchOptions, MemorySearchResult } from './team-memory-store.js';
|
|
18
19
|
import type { CancelTaskInput, DispatchTaskInput, ReportTaskInput, ReportTaskResult, StatusTaskInput } from './team-operations.js';
|
|
@@ -80,6 +81,7 @@ export interface RuntimeStore {
|
|
|
80
81
|
approveMemoryCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
|
|
81
82
|
archiveMemoryEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
|
|
82
83
|
getMemoryEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources | undefined;
|
|
84
|
+
getMemoryDiagnostics: (input: BuildMemoryDiagnosticsInput) => MemoryDiagnostics;
|
|
83
85
|
listMemoryEntries: (workspaceId: string, options?: MemoryListOptions) => MemoryEntryWithSources[];
|
|
84
86
|
listMemoryInjectionsForDispatch: (workspaceId: string, dispatchId: string) => MemoryInjectionWithMemory[];
|
|
85
87
|
logMemoryInjections: (input: LogMemoryInjectionsInput) => string[];
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
import { type MemoryDreamInput } from './team-memory-dream-input.js';
|
|
1
2
|
import { type DreamMessageInput, type DreamRunRecord } from './team-memory-dream-store.js';
|
|
2
3
|
import type { MemoryEntryWithSources } from './team-memory-store.js';
|
|
3
|
-
export
|
|
4
|
-
prompt: string;
|
|
5
|
-
run: DreamRunRecord;
|
|
6
|
-
}
|
|
4
|
+
export type { MemoryDreamInput } from './team-memory-dream-input.js';
|
|
7
5
|
interface RuntimeStoreDreamServices {
|
|
8
6
|
teamMemoryDreamRunner: {
|
|
9
7
|
runManual: (workspaceId: string) => Promise<DreamRunRecord>;
|
|
@@ -33,4 +31,3 @@ export declare const createRuntimeStoreDreamMethods: (services: RuntimeStoreDrea
|
|
|
33
31
|
runMemoryDream(workspaceId: string): Promise<DreamRunRecord>;
|
|
34
32
|
tickMemoryDreamScheduler(now?: number): Promise<void>;
|
|
35
33
|
};
|
|
36
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildMemoryDreamInput } from './team-memory-dream-input.js';
|
|
2
2
|
import { DREAM_STALE_ERROR, DreamRunNotFoundError, DreamRunValidationError, } from './team-memory-dream-store.js';
|
|
3
3
|
const shouldExportStaleRun = (run) => run.status === 'failed' && run.error === DREAM_STALE_ERROR;
|
|
4
4
|
export const createRuntimeStoreDreamMethods = (services) => ({
|
|
@@ -31,17 +31,7 @@ export const createRuntimeStoreDreamMethods = (services) => ({
|
|
|
31
31
|
services.teamMemoryExport.schedule(workspaceId);
|
|
32
32
|
throw new DreamRunValidationError('Dream run is no longer running');
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
.listInputMessages(workspaceId, run.inputSeqFrom, run.inputSeqTo)
|
|
36
|
-
.slice(-DREAM_PROMPT_MESSAGE_LIMIT);
|
|
37
|
-
const memories = services.teamMemoryStore
|
|
38
|
-
.listAllEntries(workspaceId)
|
|
39
|
-
.filter((memory) => memory.status === 'active' && memory.updatedAt <= run.startedAt)
|
|
40
|
-
.slice(0, DREAM_PROMPT_MEMORY_LIMIT);
|
|
41
|
-
return {
|
|
42
|
-
prompt: buildDreamPrompt({ memories, messages, workspaceId }),
|
|
43
|
-
run,
|
|
44
|
-
};
|
|
34
|
+
return buildMemoryDreamInput(services, workspaceId, run);
|
|
45
35
|
},
|
|
46
36
|
listMemoryDreamRuns(workspaceId, limit) {
|
|
47
37
|
const runs = services.teamMemoryDreamStore.listRuns(workspaceId, limit);
|
|
@@ -15,10 +15,12 @@ import { createSentinelHeartbeatService } from './sentinel-heartbeat.js';
|
|
|
15
15
|
import { createSettingsStore } from './settings-store.js';
|
|
16
16
|
import { createTasksFileService } from './tasks-file.js';
|
|
17
17
|
import { createTasksFileWatcher } from './tasks-file-watcher.js';
|
|
18
|
+
import { createTeamMemoryDiagnostics } from './team-memory-diagnostics.js';
|
|
18
19
|
import { createTeamMemoryDreamRunner } from './team-memory-dream-runner.js';
|
|
19
20
|
import { createTeamMemoryDreamScheduler } from './team-memory-dream-scheduler.js';
|
|
20
21
|
import { createTeamMemoryDreamStore } from './team-memory-dream-store.js';
|
|
21
22
|
import { createTeamMemoryExportService } from './team-memory-export.js';
|
|
23
|
+
import { createLocalTeamMemoryProvider } from './team-memory-provider.js';
|
|
22
24
|
import { createTeamMemoryStore } from './team-memory-store.js';
|
|
23
25
|
import { createTeamOperations } from './team-operations.js';
|
|
24
26
|
import { createTeamRecallStore } from './team-recall-store.js';
|
|
@@ -52,8 +54,10 @@ export interface RuntimeStoreServices {
|
|
|
52
54
|
sentinelHeartbeat: ReturnType<typeof createSentinelHeartbeatService>;
|
|
53
55
|
protocolEventStats: ReturnType<typeof createProtocolEventStats>;
|
|
54
56
|
teamMemoryDreamStore: ReturnType<typeof createTeamMemoryDreamStore>;
|
|
57
|
+
teamMemoryDiagnostics: ReturnType<typeof createTeamMemoryDiagnostics>;
|
|
55
58
|
teamMemoryStore: ReturnType<typeof createTeamMemoryStore>;
|
|
56
59
|
teamMemoryExport: ReturnType<typeof createTeamMemoryExportService>;
|
|
60
|
+
teamMemoryProvider: ReturnType<typeof createLocalTeamMemoryProvider>;
|
|
57
61
|
teamRecallStore: ReturnType<typeof createTeamRecallStore>;
|
|
58
62
|
teamOps: ReturnType<typeof createTeamOperations>;
|
|
59
63
|
uiAuth: ReturnType<typeof createUiAuth>;
|
|
@@ -21,11 +21,15 @@ import { createSentinelHeartbeatService } from './sentinel-heartbeat.js';
|
|
|
21
21
|
import { createSettingsStore } from './settings-store.js';
|
|
22
22
|
import { createTasksFileService } from './tasks-file.js';
|
|
23
23
|
import { createTasksFileWatcher } from './tasks-file-watcher.js';
|
|
24
|
+
import { createTeamMemoryDiagnostics } from './team-memory-diagnostics.js';
|
|
24
25
|
import { createWorkspaceMemoryDigestProvider } from './team-memory-digest.js';
|
|
26
|
+
import { createDreamCliExecutor } from './team-memory-dream-cli.js';
|
|
27
|
+
import { buildMemoryDreamInput } from './team-memory-dream-input.js';
|
|
25
28
|
import { createTeamMemoryDreamRunner } from './team-memory-dream-runner.js';
|
|
26
29
|
import { createTeamMemoryDreamScheduler } from './team-memory-dream-scheduler.js';
|
|
27
30
|
import { createTeamMemoryDreamStore } from './team-memory-dream-store.js';
|
|
28
31
|
import { createTeamMemoryExportService, MEMORY_EXPORT_DREAM_CHANGELOG_LIMIT, } from './team-memory-export.js';
|
|
32
|
+
import { createLocalTeamMemoryProvider } from './team-memory-provider.js';
|
|
29
33
|
import { createTeamMemoryStore } from './team-memory-store.js';
|
|
30
34
|
import { createTeamOperations } from './team-operations.js';
|
|
31
35
|
import { createTeamRecallStore } from './team-recall-store.js';
|
|
@@ -87,8 +91,15 @@ export const createRuntimeStoreServices = (options = {}) => {
|
|
|
87
91
|
const agentSessionStore = createAgentSessionStore(db);
|
|
88
92
|
const settings = createSettingsStore(db);
|
|
89
93
|
const getFlags = () => readFeatureFlags(settings);
|
|
90
|
-
const
|
|
94
|
+
const teamMemoryProvider = createLocalTeamMemoryProvider({ memoryStore: teamMemoryStore });
|
|
95
|
+
const teamMemoryDreamCli = createDreamCliExecutor();
|
|
96
|
+
const teamMemoryDiagnostics = createTeamMemoryDiagnostics({
|
|
97
|
+
dreamStore: teamMemoryDreamStore,
|
|
98
|
+
memoryProvider: teamMemoryProvider,
|
|
91
99
|
memoryStore: teamMemoryStore,
|
|
100
|
+
});
|
|
101
|
+
const memoryDigestProvider = createWorkspaceMemoryDigestProvider({
|
|
102
|
+
memoryStore: teamMemoryProvider,
|
|
92
103
|
settings,
|
|
93
104
|
});
|
|
94
105
|
const memoryInjection = {
|
|
@@ -194,10 +205,16 @@ export const createRuntimeStoreServices = (options = {}) => {
|
|
|
194
205
|
}
|
|
195
206
|
}, restartPolicy, (workspaceId, agentId) => workspaceStore.getAgent(workspaceId, agentId), getFlags, memoryInjection);
|
|
196
207
|
const teamMemoryDreamRunner = createTeamMemoryDreamRunner({
|
|
208
|
+
applyScheduledRun: teamMemoryDreamStore.applyAndCompleteRun,
|
|
209
|
+
buildScheduledInput: (workspaceId, run) => buildMemoryDreamInput({ teamMemoryDreamStore, teamMemoryStore }, workspaceId, run),
|
|
197
210
|
dreamStore: teamMemoryDreamStore,
|
|
198
211
|
deliverToOrchestrator: (workspaceId, text) => agentRuntime.deliverSystemMessageToAgent(workspaceId, getOrchestratorId(workspaceId), text, {
|
|
199
212
|
requireActiveRun: true,
|
|
200
213
|
}),
|
|
214
|
+
executeScheduledDream: ({ prompt, workspaceId }) => teamMemoryDreamCli.execute({
|
|
215
|
+
cwd: workspaceStore.getWorkspaceSnapshot(workspaceId).summary.path,
|
|
216
|
+
prompt,
|
|
217
|
+
}),
|
|
201
218
|
scheduleExport: teamMemoryExport.schedule,
|
|
202
219
|
});
|
|
203
220
|
const teamMemoryDreamScheduler = createTeamMemoryDreamScheduler({
|
|
@@ -294,7 +311,9 @@ export const createRuntimeStoreServices = (options = {}) => {
|
|
|
294
311
|
sentinelHeartbeat,
|
|
295
312
|
protocolEventStats,
|
|
296
313
|
teamMemoryDreamStore,
|
|
314
|
+
teamMemoryDiagnostics,
|
|
297
315
|
teamMemoryExport,
|
|
316
|
+
teamMemoryProvider,
|
|
298
317
|
teamMemoryStore,
|
|
299
318
|
teamRecallStore,
|
|
300
319
|
teamOps,
|
|
@@ -392,6 +411,7 @@ export const createRuntimeStoreLifecycle = ({ agentManager, services, }) => {
|
|
|
392
411
|
// runner's `await agent(...)` rejects with a clear shutdown error
|
|
393
412
|
// instead of hanging on a Promise that can never resolve.
|
|
394
413
|
services.sentinelHeartbeat.close();
|
|
414
|
+
await services.teamMemoryDreamScheduler.close();
|
|
395
415
|
services.workflowDispatchAwaiter.cancelAll('runtime closing');
|
|
396
416
|
services.shellRuntime.close();
|
|
397
417
|
await services.teamMemoryExport.close();
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import type { BuildMemoryDiagnosticsInput, MemoryDiagnostics } from './team-memory-diagnostics.js';
|
|
1
2
|
import type { AddMemoryEntryInput, LogMemoryInjectionsInput, MemoryEntryWithSources, MemoryInjectionWithMemory, MemoryListOptions, MemorySearchOptions, MemorySearchResult } from './team-memory-store.js';
|
|
2
3
|
interface RuntimeStoreMemoryServices {
|
|
3
4
|
teamMemoryExport: {
|
|
4
5
|
schedule: (workspaceId: string) => void;
|
|
5
6
|
};
|
|
7
|
+
teamMemoryDiagnostics: {
|
|
8
|
+
build: (input: BuildMemoryDiagnosticsInput) => MemoryDiagnostics;
|
|
9
|
+
};
|
|
6
10
|
teamMemoryStore: {
|
|
7
11
|
addEntry: (input: AddMemoryEntryInput) => MemoryEntryWithSources;
|
|
8
12
|
approveCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
|
|
9
13
|
archiveEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
|
|
10
14
|
getEntryWithSources: (workspaceId: string, memoryId: string) => MemoryEntryWithSources | undefined;
|
|
11
15
|
listEntries: (workspaceId: string, options?: MemoryListOptions) => MemoryEntryWithSources[];
|
|
16
|
+
listInjections: (workspaceId: string, limit?: number) => MemoryInjectionWithMemory[];
|
|
12
17
|
listInjectionsForDispatch: (workspaceId: string, dispatchId: string) => MemoryInjectionWithMemory[];
|
|
13
18
|
logInjections: (input: LogMemoryInjectionsInput) => string[];
|
|
14
19
|
rejectCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
|
|
@@ -23,6 +28,7 @@ export declare const createRuntimeStoreMemoryMethods: (services: RuntimeStoreMem
|
|
|
23
28
|
archiveMemoryEntry(workspaceId: string, memoryId: string): MemoryEntryWithSources;
|
|
24
29
|
getMemoryEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources | undefined;
|
|
25
30
|
listMemoryEntries: (workspaceId: string, options?: MemoryListOptions) => MemoryEntryWithSources[];
|
|
31
|
+
getMemoryDiagnostics: (input: BuildMemoryDiagnosticsInput) => MemoryDiagnostics;
|
|
26
32
|
listMemoryInjectionsForDispatch: (workspaceId: string, dispatchId: string) => MemoryInjectionWithMemory[];
|
|
27
33
|
logMemoryInjections: (input: LogMemoryInjectionsInput) => string[];
|
|
28
34
|
rejectMemoryCandidate(workspaceId: string, memoryId: string): MemoryEntryWithSources;
|
|
@@ -16,6 +16,7 @@ export const createRuntimeStoreMemoryMethods = (services) => ({
|
|
|
16
16
|
},
|
|
17
17
|
getMemoryEntry: (workspaceId, memoryId) => services.teamMemoryStore.getEntryWithSources(workspaceId, memoryId),
|
|
18
18
|
listMemoryEntries: (workspaceId, options) => services.teamMemoryStore.listEntries(workspaceId, options),
|
|
19
|
+
getMemoryDiagnostics: (input) => services.teamMemoryDiagnostics.build(input),
|
|
19
20
|
listMemoryInjectionsForDispatch: (workspaceId, dispatchId) => services.teamMemoryStore.listInjectionsForDispatch(workspaceId, dispatchId),
|
|
20
21
|
logMemoryInjections: (input) => services.teamMemoryStore.logInjections(input),
|
|
21
22
|
rejectMemoryCandidate(workspaceId, memoryId) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const ensureColumn = (db, table, column, definition) => {
|
|
2
|
+
const columns = new Set(db.prepare(`PRAGMA table_info(${table})`).all().map((row) => row.name));
|
|
3
|
+
if (!columns.has(column))
|
|
4
|
+
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
5
|
+
};
|
|
6
|
+
/** v36: structured memory procedure/workflow references. */
|
|
7
|
+
export const applySchemaVersion36 = (db) => {
|
|
8
|
+
const table = db
|
|
9
|
+
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_entries'")
|
|
10
|
+
.get();
|
|
11
|
+
if (!table)
|
|
12
|
+
return;
|
|
13
|
+
ensureColumn(db, 'memory_entries', 'ref_type', 'TEXT');
|
|
14
|
+
ensureColumn(db, 'memory_entries', 'ref_id', 'TEXT');
|
|
15
|
+
ensureColumn(db, 'memory_entries', 'ref_title', 'TEXT');
|
|
16
|
+
db.exec(`
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_memory_entries_ref
|
|
18
|
+
ON memory_entries(ref_type, ref_id)
|
|
19
|
+
WHERE ref_type IS NOT NULL AND ref_id IS NOT NULL;
|
|
20
|
+
`);
|
|
21
|
+
};
|
|
@@ -28,7 +28,8 @@ import { applySchemaVersion32 } from './sqlite-schema-v32.js';
|
|
|
28
28
|
import { applySchemaVersion33 } from './sqlite-schema-v33.js';
|
|
29
29
|
import { applySchemaVersion34 } from './sqlite-schema-v34.js';
|
|
30
30
|
import { applySchemaVersion35 } from './sqlite-schema-v35.js';
|
|
31
|
-
|
|
31
|
+
import { applySchemaVersion36 } from './sqlite-schema-v36.js';
|
|
32
|
+
export const CURRENT_SCHEMA_VERSION = 36;
|
|
32
33
|
// Idempotent column-add helper. SQLite doesn't have `ALTER TABLE … ADD COLUMN
|
|
33
34
|
// IF NOT EXISTS`, so PRAGMA-check first. Safe to call on every init; required
|
|
34
35
|
// for foreign-built DBs where the version-gated migration is skipped.
|
|
@@ -399,4 +400,8 @@ export const initializeRuntimeDatabase = (db) => {
|
|
|
399
400
|
applySchemaVersion35(db);
|
|
400
401
|
db.prepare('INSERT INTO schema_version (version, applied_at) VALUES (?, ?)').run(35, Date.now());
|
|
401
402
|
}
|
|
403
|
+
applySchemaVersion36(db);
|
|
404
|
+
if (!appliedVersions.has(36)) {
|
|
405
|
+
db.prepare('INSERT INTO schema_version (version, applied_at) VALUES (?, ?)').run(36, Date.now());
|
|
406
|
+
}
|
|
402
407
|
};
|