@hanhnd/agent-kit 1.0.34 → 1.0.35
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/dist/cli/commands/cli-digest-pending.test.js +19 -10
- package/dist/cli/commands/memory.js +44 -4
- package/dist/cli.js +307 -129
- package/dist/core/config/index.d.ts +3 -0
- package/dist/core/config/index.js +20 -0
- package/dist/entrypoints/server.js +1 -3
- package/dist/mcp/memory.d.ts +2 -1
- package/dist/mcp/memory.js +45 -18
- package/dist/server.js +253 -150
- package/dist/services/digest/constants.d.ts +3 -3
- package/dist/services/digest/constants.js +3 -3
- package/dist/services/digest/digest-background.test.js +19 -8
- package/dist/services/digest/digest-init.test.js +13 -2
- package/dist/services/digest/digest-pending.test.js +13 -2
- package/dist/services/digest/digest-processor.test.js +66 -0
- package/dist/services/digest/files.js +3 -3
- package/dist/services/digest/model-registry.js +2 -2
- package/dist/services/digest/processor.js +43 -13
- package/dist/services/digest/providers/llama-local.js +17 -28
- package/dist/services/digest/types.d.ts +3 -1
- package/dist/services/digest/types.js +1 -1
- package/dist/services/memory/chunker.d.ts +5 -2
- package/dist/services/memory/chunker.js +3 -1
- package/dist/services/memory/chunker.test.js +21 -11
- package/dist/services/memory/constants.js +1 -1
- package/dist/services/memory/embedder.js +1 -1
- package/dist/services/memory/index.d.ts +1 -1
- package/dist/services/memory/indexer.d.ts +2 -1
- package/dist/services/memory/indexer.js +24 -8
- package/dist/services/memory/indexer.test.js +38 -2
- package/dist/services/memory/memory.test.js +172 -15
- package/dist/services/memory/store.d.ts +6 -1
- package/dist/services/memory/store.js +87 -47
- package/dist/services/memory/store.test.js +123 -3
- package/dist/services/memory/types.d.ts +9 -1
- package/dist/services/memory/types.js +2 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.js +2 -1
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +3 -3
- package/package.json +2 -2
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
import * as assert from 'node:assert/strict';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
-
import { afterEach, describe, test } from 'node:test';
|
|
4
|
+
import { afterEach, describe, test, beforeEach } from 'node:test';
|
|
5
5
|
import { createTempDirTracker } from '../../utils/temp-dir.test.js';
|
|
6
6
|
import { runMemoryCli } from './memory.js';
|
|
7
7
|
import { writeConversationDigestSettings } from '../../services/digest/files.js';
|
|
8
8
|
import { DigestModelId } from '../../services/digest/types.js';
|
|
9
9
|
const tempDirs = createTempDirTracker();
|
|
10
|
+
let originalHome;
|
|
11
|
+
let originalUserProfile;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
originalHome = process.env.HOME;
|
|
14
|
+
originalUserProfile = process.env.USERPROFILE;
|
|
15
|
+
const mockHome = tempDirs.makeTempDir('mock-home-');
|
|
16
|
+
process.env.HOME = mockHome;
|
|
17
|
+
process.env.USERPROFILE = mockHome;
|
|
18
|
+
});
|
|
10
19
|
afterEach(() => {
|
|
11
20
|
tempDirs.cleanup();
|
|
21
|
+
process.env.HOME = originalHome;
|
|
22
|
+
process.env.USERPROFILE = originalUserProfile;
|
|
12
23
|
});
|
|
13
24
|
function writeInitState(workspace) {
|
|
14
25
|
writeConversationDigestSettings(workspace, {
|
|
15
26
|
enabled: true,
|
|
16
27
|
initialized: true,
|
|
17
|
-
modelId: DigestModelId.
|
|
28
|
+
modelId: DigestModelId.BASE,
|
|
18
29
|
initializedAt: new Date().toISOString(),
|
|
19
30
|
});
|
|
20
31
|
}
|
|
@@ -57,8 +68,8 @@ describe('cmdDigestPending CLI', () => {
|
|
|
57
68
|
})));
|
|
58
69
|
assert.equal(code, 0);
|
|
59
70
|
const parsed = JSON.parse(output.trim());
|
|
60
|
-
assert.ok('
|
|
61
|
-
assert.
|
|
71
|
+
assert.ok('systemMessage' in parsed, 'result must have systemMessage field');
|
|
72
|
+
assert.match(parsed.systemMessage, /No conversations to digest|digested|initialized/);
|
|
62
73
|
});
|
|
63
74
|
test('--background returns launcher JSON without waiting for worker when no pending', async () => {
|
|
64
75
|
const workspace = tempDirs.makeTempDir('cli-pending-bg-');
|
|
@@ -69,9 +80,8 @@ describe('cmdDigestPending CLI', () => {
|
|
|
69
80
|
})));
|
|
70
81
|
assert.equal(code, 0);
|
|
71
82
|
const parsed = JSON.parse(output.trim());
|
|
72
|
-
assert.
|
|
73
|
-
assert.equal(parsed.
|
|
74
|
-
assert.equal(parsed.status.state, 'no-pending');
|
|
83
|
+
assert.ok('systemMessage' in parsed, 'result must have systemMessage field');
|
|
84
|
+
assert.equal(parsed.systemMessage, '[memory-kit] No conversations to digest');
|
|
75
85
|
});
|
|
76
86
|
test('--background worker flag returns final worker status JSON', async () => {
|
|
77
87
|
const workspace = tempDirs.makeTempDir('cli-pending-worker-');
|
|
@@ -100,9 +110,8 @@ describe('cmdDigestPending CLI', () => {
|
|
|
100
110
|
})));
|
|
101
111
|
assert.equal(code, 0);
|
|
102
112
|
const parsed = JSON.parse(output.trim());
|
|
103
|
-
assert.
|
|
104
|
-
assert.equal(parsed.
|
|
105
|
-
assert.equal(parsed.status.state, 'failed');
|
|
113
|
+
assert.ok('systemMessage' in parsed, 'result must have systemMessage field');
|
|
114
|
+
assert.equal(parsed.systemMessage, '[memory-kit] Digest failed: CLI entrypoint is unavailable');
|
|
106
115
|
}
|
|
107
116
|
finally {
|
|
108
117
|
process.argv[1] = previousArgv;
|
|
@@ -2,7 +2,7 @@ import { initializeConversationDigestModel, digestConversationFile, digestPendin
|
|
|
2
2
|
import { launchDigestPendingWorker, runDigestPendingWorker } from '../../services/digest/background.js';
|
|
3
3
|
import { isDigestWorkerInvocation, runDigestFileInWorker } from '../../services/digest/worker.js';
|
|
4
4
|
import { DEFAULT_DIGEST_MAX_INPUT_CHARS, DEFAULT_DIGEST_MODEL_ID, DEFAULT_DIGEST_TIMEOUT_MS, DIGEST_WORKER_FLAG, DIGEST_WORKER_RESULT_PREFIX, } from '../../services/digest/constants.js';
|
|
5
|
-
import {
|
|
5
|
+
import { loadGlobalSettings, resolveConversationDigestConfig } from '../../core/config/index.js';
|
|
6
6
|
import { parseArgs, stringFlag, numberFlag } from '../utils/args.js';
|
|
7
7
|
import { getWorkspaceRoot } from '../../utils/utils.js';
|
|
8
8
|
function writeDigestFileResult(result, workerMode) {
|
|
@@ -12,6 +12,42 @@ function writeDigestFileResult(result, workerMode) {
|
|
|
12
12
|
}
|
|
13
13
|
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
14
14
|
}
|
|
15
|
+
function formatLauncherResult(result) {
|
|
16
|
+
if (!result.ok)
|
|
17
|
+
return `Digest failed: ${result.error ?? 'unknown error'}`;
|
|
18
|
+
if (result.spawned)
|
|
19
|
+
return 'Background digest started';
|
|
20
|
+
switch (result.status.state) {
|
|
21
|
+
case 'locked':
|
|
22
|
+
return 'Digest already running';
|
|
23
|
+
case 'no-pending':
|
|
24
|
+
return 'No conversations to digest';
|
|
25
|
+
case 'not-initialized':
|
|
26
|
+
return 'Digest not initialized';
|
|
27
|
+
default:
|
|
28
|
+
return `Digest skipped (${result.status.state})`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function formatPendingResult(result) {
|
|
32
|
+
if (!result.ok)
|
|
33
|
+
return `Digest failed: ${result.error ?? 'unknown error'}`;
|
|
34
|
+
if (result.action === 'noop') {
|
|
35
|
+
switch (result.reason) {
|
|
36
|
+
case 'locked':
|
|
37
|
+
return 'Digest already running';
|
|
38
|
+
case 'no-pending':
|
|
39
|
+
return 'No conversations to digest';
|
|
40
|
+
case 'not-initialized':
|
|
41
|
+
return 'Digest not initialized';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const parts = [`${result.count} conversation${result.count !== 1 ? 's' : ''} digested`];
|
|
45
|
+
if (result.skipped > 0)
|
|
46
|
+
parts.push(`${result.skipped} skipped`);
|
|
47
|
+
if (result.errors > 0)
|
|
48
|
+
parts.push(`${result.errors} errors`);
|
|
49
|
+
return parts.join(', ');
|
|
50
|
+
}
|
|
15
51
|
async function cmdDigestInit(args) {
|
|
16
52
|
const parsed = parseArgs(args);
|
|
17
53
|
const modelId = stringFlag(parsed.flags, 'model') ?? DEFAULT_DIGEST_MODEL_ID;
|
|
@@ -30,7 +66,7 @@ async function cmdDigestFile(args) {
|
|
|
30
66
|
return workerResult;
|
|
31
67
|
const parsed = parseArgs(args);
|
|
32
68
|
const workspaceRoot = getWorkspaceRoot();
|
|
33
|
-
const digestConfig = resolveConversationDigestConfig(
|
|
69
|
+
const digestConfig = resolveConversationDigestConfig(loadGlobalSettings());
|
|
34
70
|
const modelId = stringFlag(parsed.flags, 'model') ?? digestConfig?.modelId ?? DEFAULT_DIGEST_MODEL_ID;
|
|
35
71
|
const inputPath = stringFlag(parsed.flags, 'input');
|
|
36
72
|
if (!inputPath) {
|
|
@@ -63,11 +99,15 @@ async function cmdDigestPending(args) {
|
|
|
63
99
|
args,
|
|
64
100
|
entrypoint: process.argv[1],
|
|
65
101
|
});
|
|
66
|
-
process.stdout.write(JSON.stringify(
|
|
102
|
+
process.stdout.write(JSON.stringify({
|
|
103
|
+
systemMessage: `[memory-kit] ${formatLauncherResult(result)}`,
|
|
104
|
+
}) + '\n');
|
|
67
105
|
return 0;
|
|
68
106
|
}
|
|
69
107
|
const result = await digestPendingConversations({ workspaceRoot });
|
|
70
|
-
process.stdout.write(JSON.stringify(
|
|
108
|
+
process.stdout.write(JSON.stringify({
|
|
109
|
+
systemMessage: `[memory-kit] ${formatPendingResult(result)}`,
|
|
110
|
+
}) + '\n');
|
|
71
111
|
return 0;
|
|
72
112
|
}
|
|
73
113
|
export async function runMemoryCli(args, _env) {
|