@hanhnd/agent-kit 1.0.33 → 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.
Files changed (51) hide show
  1. package/dist/cli/commands/cli-digest-pending.test.js +19 -10
  2. package/dist/cli/commands/memory.js +44 -4
  3. package/dist/cli.js +307 -129
  4. package/dist/core/config/index.d.ts +3 -0
  5. package/dist/core/config/index.js +20 -0
  6. package/dist/core/handoffs/index.d.ts +8 -7
  7. package/dist/core/handoffs/index.js +12 -4
  8. package/dist/core/handoffs/index.test.d.ts +1 -0
  9. package/dist/core/handoffs/index.test.js +88 -0
  10. package/dist/entrypoints/server.js +1 -3
  11. package/dist/mcp/agent.d.ts +1 -1
  12. package/dist/mcp/agent.js +3 -3
  13. package/dist/mcp/core.d.ts +7 -0
  14. package/dist/mcp/core.js +39 -25
  15. package/dist/mcp/core.test.d.ts +1 -0
  16. package/dist/mcp/core.test.js +98 -0
  17. package/dist/mcp/memory.d.ts +2 -1
  18. package/dist/mcp/memory.js +45 -18
  19. package/dist/server.js +302 -178
  20. package/dist/services/digest/constants.d.ts +3 -3
  21. package/dist/services/digest/constants.js +3 -3
  22. package/dist/services/digest/digest-background.test.js +19 -8
  23. package/dist/services/digest/digest-init.test.js +13 -2
  24. package/dist/services/digest/digest-pending.test.js +13 -2
  25. package/dist/services/digest/digest-processor.test.js +66 -0
  26. package/dist/services/digest/files.js +3 -3
  27. package/dist/services/digest/model-registry.js +2 -2
  28. package/dist/services/digest/processor.js +43 -13
  29. package/dist/services/digest/providers/llama-local.js +17 -28
  30. package/dist/services/digest/types.d.ts +3 -1
  31. package/dist/services/digest/types.js +1 -1
  32. package/dist/services/memory/chunker.d.ts +5 -2
  33. package/dist/services/memory/chunker.js +3 -1
  34. package/dist/services/memory/chunker.test.js +21 -11
  35. package/dist/services/memory/constants.js +1 -1
  36. package/dist/services/memory/embedder.js +1 -1
  37. package/dist/services/memory/index.d.ts +1 -1
  38. package/dist/services/memory/indexer.d.ts +2 -1
  39. package/dist/services/memory/indexer.js +24 -8
  40. package/dist/services/memory/indexer.test.js +38 -2
  41. package/dist/services/memory/memory.test.js +172 -15
  42. package/dist/services/memory/store.d.ts +6 -1
  43. package/dist/services/memory/store.js +87 -47
  44. package/dist/services/memory/store.test.js +123 -3
  45. package/dist/services/memory/types.d.ts +9 -1
  46. package/dist/services/memory/types.js +2 -1
  47. package/dist/utils/paths.d.ts +2 -0
  48. package/dist/utils/paths.js +2 -1
  49. package/dist/utils/utils.d.ts +1 -0
  50. package/dist/utils/utils.js +3 -3
  51. 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.DEFAULT,
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('ok' in parsed, 'result must have ok field');
61
- assert.ok('action' in parsed, 'result must have action field');
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.equal(parsed.mode, 'background-launcher');
73
- assert.equal(parsed.spawned, false);
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.equal(parsed.mode, 'background-launcher');
104
- assert.equal(parsed.spawned, false);
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 { loadProjectSettings, resolveConversationDigestConfig } from '../../core/config/index.js';
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(loadProjectSettings(workspaceRoot));
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(result) + '\n');
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(result) + '\n');
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) {