@hanhnd/agent-kit 1.0.32 → 1.0.34

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 (111) hide show
  1. package/dist/cli/commands/cli-digest-pending.test.js +111 -0
  2. package/dist/cli/commands/cli-memory.test.js +34 -0
  3. package/dist/cli/{memory.js → commands/memory.js} +24 -11
  4. package/dist/cli/index.js +2 -2
  5. package/dist/{utils → cli/utils}/args.d.ts +2 -1
  6. package/dist/{kit-cli.js → cli.js} +342 -58
  7. package/dist/{tools/config.d.ts → core/config/index.d.ts} +2 -7
  8. package/dist/{tools/config.js → core/config/index.js} +2 -13
  9. package/dist/core/handoffs/index.d.ts +17 -0
  10. package/dist/{tools/handoffs.js → core/handoffs/index.js} +15 -7
  11. package/dist/core/handoffs/index.test.js +88 -0
  12. package/dist/{tools/security.d.ts → core/security/index.d.ts} +0 -19
  13. package/dist/{tools/security.js → core/security/index.js} +3 -76
  14. package/dist/entrypoints/cli.js +11 -0
  15. package/dist/entrypoints/server.js +37 -0
  16. package/dist/{tools → mcp}/agent.d.ts +1 -1
  17. package/dist/{tools → mcp}/agent.js +4 -4
  18. package/dist/mcp/core.d.ts +17 -0
  19. package/dist/mcp/core.js +60 -0
  20. package/dist/mcp/core.test.js +98 -0
  21. package/dist/{tools → mcp}/integration.js +3 -3
  22. package/dist/mcp/memory.d.ts +15 -0
  23. package/dist/{tools → mcp}/memory.js +15 -13
  24. package/dist/{kit-server.js → server.js} +129 -98
  25. package/dist/services/digest/background.d.ts +11 -0
  26. package/dist/services/digest/background.js +258 -0
  27. package/dist/{memory → services}/digest/constants.d.ts +4 -1
  28. package/dist/{memory → services}/digest/constants.js +6 -2
  29. package/dist/services/digest/digest-background.test.js +206 -0
  30. package/dist/{tools/__tests__ → services/digest}/digest-init.test.js +4 -3
  31. package/dist/{memory/__tests__ → services/digest}/digest-llama-local.test.js +1 -13
  32. package/dist/{memory/__tests__ → services/digest}/digest-pending.test.js +39 -11
  33. package/dist/{memory/__tests__ → services/digest}/digest-processor.test.js +5 -7
  34. package/dist/{memory → services}/digest/files.d.ts +0 -1
  35. package/dist/{memory → services}/digest/files.js +2 -2
  36. package/dist/services/digest/model-registry.d.ts +2 -0
  37. package/dist/{memory → services}/digest/model-registry.js +9 -8
  38. package/dist/services/digest/processor.d.ts +13 -0
  39. package/dist/{memory → services}/digest/processor.js +48 -31
  40. package/dist/services/digest/providers/llama-local.d.ts +2 -0
  41. package/dist/{memory → services}/digest/providers/llama-local.js +3 -4
  42. package/dist/{memory → services}/digest/types.d.ts +34 -2
  43. package/dist/services/digest/types.js +6 -0
  44. package/dist/{memory → services}/digest/worker.d.ts +0 -1
  45. package/dist/{memory → services}/digest/worker.js +2 -2
  46. package/dist/{utils → services/integration}/credentials.js +1 -1
  47. package/dist/{utils/parser.js → services/integration/parser/adf.js} +1 -0
  48. package/dist/{memory → services/memory}/chunker.d.ts +0 -2
  49. package/dist/{memory → services/memory}/chunker.js +3 -3
  50. package/dist/{memory/__tests__ → services/memory}/chunker.test.js +1 -34
  51. package/dist/{memory → services/memory}/constants.d.ts +1 -1
  52. package/dist/{memory → services/memory}/constants.js +2 -1
  53. package/dist/{memory → services/memory}/embedder.d.ts +2 -2
  54. package/dist/{memory → services/memory}/embedder.js +5 -5
  55. package/dist/services/memory/embedder.test.js +13 -0
  56. package/dist/{memory → services/memory}/indexer.d.ts +2 -1
  57. package/dist/{memory → services/memory}/indexer.js +1 -1
  58. package/dist/{memory/__tests__ → services/memory}/indexer.test.js +4 -3
  59. package/dist/{tools/__tests__ → services/memory}/memory.test.js +54 -13
  60. package/dist/{memory/__tests__ → services/memory}/store.test.js +3 -2
  61. package/dist/{memory → services/memory}/types.d.ts +7 -2
  62. package/dist/services/memory/types.js +6 -0
  63. package/dist/utils/files.d.ts +0 -1
  64. package/dist/utils/files.js +1 -1
  65. package/dist/{memory/__tests__/lockfile.test.js → utils/files.test.js} +14 -14
  66. package/dist/utils/index.d.ts +6 -0
  67. package/dist/utils/index.js +6 -0
  68. package/dist/utils/json.d.ts +0 -1
  69. package/dist/utils/json.js +0 -10
  70. package/dist/utils/paths.d.ts +0 -1
  71. package/dist/utils/paths.js +1 -1
  72. package/package.json +6 -6
  73. package/dist/memory/__tests__/digest-worker.test.js +0 -46
  74. package/dist/memory/__tests__/embedder.test.js +0 -14
  75. package/dist/memory/digest/model-registry.d.ts +0 -6
  76. package/dist/memory/digest/processor.d.ts +0 -7
  77. package/dist/memory/digest/providers/llama-local.d.ts +0 -7
  78. package/dist/tools/__tests__/cli-digest-pending.test.js +0 -51
  79. package/dist/tools/__tests__/cli-memory.test.js +0 -22
  80. package/dist/tools/core.d.ts +0 -10
  81. package/dist/tools/core.js +0 -46
  82. package/dist/tools/handoffs.d.ts +0 -22
  83. package/dist/tools/memory.d.ts +0 -16
  84. /package/dist/{tools/__tests__ → cli/commands}/cli-digest-pending.test.d.ts +0 -0
  85. /package/dist/{tools/__tests__ → cli/commands}/cli-memory.test.d.ts +0 -0
  86. /package/dist/cli/{memory.d.ts → commands/memory.d.ts} +0 -0
  87. /package/dist/{utils → cli/utils}/args.js +0 -0
  88. /package/dist/{memory/__tests__/chunker.test.d.ts → core/handoffs/index.test.d.ts} +0 -0
  89. /package/dist/{kit-cli.d.ts → entrypoints/cli.d.ts} +0 -0
  90. /package/dist/{kit-server.d.ts → entrypoints/server.d.ts} +0 -0
  91. /package/dist/{memory/__tests__/digest-llama-local.test.d.ts → mcp/core.test.d.ts} +0 -0
  92. /package/dist/{tools → mcp}/integration.d.ts +0 -0
  93. /package/dist/{memory/__tests__/digest-pending.test.d.ts → services/digest/digest-background.test.d.ts} +0 -0
  94. /package/dist/{tools/__tests__ → services/digest}/digest-init.test.d.ts +0 -0
  95. /package/dist/{memory/__tests__/digest-processor.test.d.ts → services/digest/digest-llama-local.test.d.ts} +0 -0
  96. /package/dist/{memory/__tests__/digest-worker.test.d.ts → services/digest/digest-pending.test.d.ts} +0 -0
  97. /package/dist/{memory/__tests__/embedder.test.d.ts → services/digest/digest-processor.test.d.ts} +0 -0
  98. /package/dist/{utils → services/integration}/credentials.d.ts +0 -0
  99. /package/dist/{utils/parser.d.ts → services/integration/parser/adf.d.ts} +0 -0
  100. /package/dist/{memory/__tests__/indexer.test.d.ts → services/memory/chunker.test.d.ts} +0 -0
  101. /package/dist/{memory/__tests__/lockfile.test.d.ts → services/memory/embedder.test.d.ts} +0 -0
  102. /package/dist/{memory → services/memory}/index.d.ts +0 -0
  103. /package/dist/{memory → services/memory}/index.js +0 -0
  104. /package/dist/{memory/__tests__/store.test.d.ts → services/memory/indexer.test.d.ts} +0 -0
  105. /package/dist/{tools/__tests__ → services/memory}/memory.test.d.ts +0 -0
  106. /package/dist/{memory → services/memory}/store.d.ts +0 -0
  107. /package/dist/{memory → services/memory}/store.js +0 -0
  108. /package/dist/{memory/digest/types.js → services/memory/store.test.d.ts} +0 -0
  109. /package/dist/{memory/types.js → utils/files.test.d.ts} +0 -0
  110. /package/dist/{__tests__/temp-dir.d.ts → utils/temp-dir.test.d.ts} +0 -0
  111. /package/dist/{__tests__/temp-dir.js → utils/temp-dir.test.js} +0 -0
@@ -14920,13 +14920,13 @@ var require_stopword_cjs = __commonJS({
14920
14920
  }
14921
14921
  });
14922
14922
 
14923
- // src/memory/digest/processor.ts
14923
+ // src/services/digest/processor.ts
14924
14924
  import * as fs7 from "node:fs";
14925
14925
  import * as path9 from "node:path";
14926
14926
 
14927
- // src/memory/digest/constants.ts
14927
+ // src/services/digest/constants.ts
14928
14928
  import * as path from "node:path";
14929
- var DEFAULT_DIGEST_MODEL_ID = "qwen2.5-1.5b-instruct-q4";
14929
+ var DEFAULT_DIGEST_MODEL_ID = "default" /* DEFAULT */;
14930
14930
  var DEFAULT_DIGEST_MAX_INPUT_CHARS = 3e3;
14931
14931
  var DEFAULT_DIGEST_TIMEOUT_MS = 12e4;
14932
14932
  var DIGEST_TIMEOUT_GRACE_MS = 5e3;
@@ -14936,12 +14936,15 @@ var KIT_DIR = ".agent-kit";
14936
14936
  var WIKI_DIR = path.join(KIT_DIR, "wiki");
14937
14937
  var WIKI_RAW_DIR = path.join(WIKI_DIR, "raw");
14938
14938
  var PROVISIONAL_DIGEST_DIR = path.join(WIKI_DIR, "compiled", "provisional", "conversation-digests");
14939
- var DIGEST_LOCKFILE_REL_PATH = path.join(KIT_DIR, "digest-worker.lock");
14939
+ var DIGEST_WORKER_DIR = path.join(WIKI_DIR, "digest");
14940
+ var DIGEST_LOCKFILE_REL_PATH = path.join(DIGEST_WORKER_DIR, "digest-worker.lock");
14941
+ var DIGEST_WORKER_STATUS_REL_PATH = path.join(DIGEST_WORKER_DIR, "digest-worker.status.json");
14942
+ var DIGEST_WORKER_LOG_REL_PATH = path.join(DIGEST_WORKER_DIR, "digest-worker.log");
14940
14943
  var LLAMA_CONTEXT_SIZE = 4096;
14941
14944
  var LLAMA_MAX_GENERATED_TOKENS = 512;
14942
14945
  var LLAMA_TEMPERATURE = 0.1;
14943
14946
 
14944
- // src/memory/digest/files.ts
14947
+ // src/services/digest/files.ts
14945
14948
  import * as fs3 from "node:fs";
14946
14949
  import * as path4 from "node:path";
14947
14950
 
@@ -15017,25 +15020,25 @@ function sha256Hex(content) {
15017
15020
  return createHash("sha256").update(content).digest("hex");
15018
15021
  }
15019
15022
 
15020
- // src/tools/config.ts
15023
+ // src/core/config/index.ts
15021
15024
  import * as fs2 from "fs";
15022
15025
  import * as path3 from "path";
15023
15026
 
15024
- // src/memory/constants.ts
15027
+ // src/services/memory/constants.ts
15025
15028
  var DEFAULT_MEMORY_CONFIG = {
15026
15029
  enabled: false,
15027
15030
  wikiDir: "",
15028
15031
  topK: 5,
15029
15032
  chunkSize: 1500,
15030
15033
  overlapLines: 2,
15031
- embeddingModel: "Xenova/bge-small-en-v1.5",
15034
+ embeddingModel: "small" /* SMALL */,
15032
15035
  vectorDimension: 384
15033
15036
  };
15034
15037
  var LOCK_RETRY_MS = 50;
15035
15038
  var LOCK_TIMEOUT_MS = 500;
15036
15039
  var RRF_K = 60;
15037
15040
 
15038
- // src/tools/config.ts
15041
+ // src/core/config/index.ts
15039
15042
  function resolveMemoryConfig(settings, workspaceRoot) {
15040
15043
  const override = settings.memory ?? {};
15041
15044
  return {
@@ -15074,7 +15077,7 @@ function resolveConversationDigestConfig(settings) {
15074
15077
  };
15075
15078
  }
15076
15079
 
15077
- // src/memory/digest/files.ts
15080
+ // src/services/digest/files.ts
15078
15081
  function defaultProvisionalDigestDir(workspaceRoot) {
15079
15082
  return path4.join(workspaceRoot, PROVISIONAL_DIGEST_DIR);
15080
15083
  }
@@ -15112,7 +15115,7 @@ function writeConversationDigestSettings(workspaceRoot, digest) {
15112
15115
  });
15113
15116
  }
15114
15117
 
15115
- // src/memory/digest/model-registry.ts
15118
+ // src/services/digest/model-registry.ts
15116
15119
  var DigestModelRegistryError = class extends Error {
15117
15120
  constructor(message) {
15118
15121
  super(message);
@@ -15120,24 +15123,24 @@ var DigestModelRegistryError = class extends Error {
15120
15123
  }
15121
15124
  };
15122
15125
  var DIGEST_MODEL_REGISTRY = {
15123
- "qwen2.5-0.5b-instruct-q4": {
15124
- id: "qwen2.5-0.5b-instruct-q4",
15126
+ ["tiny" /* TINY */]: {
15127
+ id: "tiny" /* TINY */,
15125
15128
  ggufUri: "hf:bartowski/Qwen2.5-0.5B-Instruct-GGUF/Qwen2.5-0.5B-Instruct-Q4_K_M.gguf",
15126
15129
  approxSizeBytes: 4e8,
15127
15130
  license: "Apache-2.0",
15128
15131
  sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-0.5B-Instruct-GGUF",
15129
15132
  enabled: true
15130
15133
  },
15131
- "qwen2.5-1.5b-instruct-q4": {
15132
- id: "qwen2.5-1.5b-instruct-q4",
15134
+ ["default" /* DEFAULT */]: {
15135
+ id: "default" /* DEFAULT */,
15133
15136
  ggufUri: "hf:bartowski/Qwen2.5-1.5B-Instruct-GGUF/Qwen2.5-1.5B-Instruct-Q4_K_M.gguf",
15134
15137
  approxSizeBytes: 1e9,
15135
15138
  license: "Apache-2.0",
15136
15139
  sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-1.5B-Instruct-GGUF",
15137
15140
  enabled: true
15138
15141
  },
15139
- "qwen2.5-3b-instruct-q4": {
15140
- id: "qwen2.5-3b-instruct-q4",
15142
+ ["large" /* LARGE */]: {
15143
+ id: "large" /* LARGE */,
15141
15144
  ggufUri: "hf:bartowski/Qwen2.5-3B-Instruct-GGUF/Qwen2.5-3B-Instruct-Q4_K_M.gguf",
15142
15145
  approxSizeBytes: 19e8,
15143
15146
  license: "Apache-2.0",
@@ -15162,7 +15165,7 @@ function getDigestModelSpec(modelId) {
15162
15165
  return spec;
15163
15166
  }
15164
15167
 
15165
- // src/memory/digest/providers/llama-local.ts
15168
+ // src/services/digest/providers/llama-local.ts
15166
15169
  import * as fs4 from "node:fs";
15167
15170
  import * as path6 from "node:path";
15168
15171
  import { getLlama, LlamaChatSession, createModelDownloader } from "node-llama-cpp";
@@ -15190,7 +15193,7 @@ var CREDENTIALS_FILE = path5.join(AGENT_KIT_HOME, "credentials");
15190
15193
  var MODEL_CACHE_DIR = path5.join(AGENT_KIT_HOME, "cache", "models");
15191
15194
  var FASTEMBED_CACHE_DIR = path5.join(MODEL_CACHE_DIR, "fastembed");
15192
15195
 
15193
- // src/memory/digest/providers/llama-local.ts
15196
+ // src/services/digest/providers/llama-local.ts
15194
15197
  var LlamaLocalDigestProviderError = class extends Error {
15195
15198
  constructor(message) {
15196
15199
  super(message);
@@ -15210,7 +15213,6 @@ function trimConversationExport(content, maxInputChars) {
15210
15213
  }
15211
15214
  function buildPrompt(input, maxInputChars) {
15212
15215
  const conversationExport = trimConversationExport(input.content, maxInputChars);
15213
- const sourceName = path6.basename(input.sourcePath);
15214
15216
  return [
15215
15217
  {
15216
15218
  role: "system",
@@ -15318,7 +15320,7 @@ async function createLlamaLocalDigestProvider(modelId) {
15318
15320
  };
15319
15321
  }
15320
15322
 
15321
- // src/memory/store.ts
15323
+ // src/services/memory/store.ts
15322
15324
  var import_stopword = __toESM(require_stopword_cjs(), 1);
15323
15325
  import Database from "better-sqlite3";
15324
15326
  import * as fs5 from "fs";
@@ -15564,11 +15566,11 @@ var MemoryStore = class {
15564
15566
  }
15565
15567
  };
15566
15568
 
15567
- // src/memory/indexer.ts
15569
+ // src/services/memory/indexer.ts
15568
15570
  import * as fs6 from "fs";
15569
15571
  import * as path8 from "path";
15570
15572
 
15571
- // src/memory/chunker.ts
15573
+ // src/services/memory/chunker.ts
15572
15574
  function computeChunkId(content) {
15573
15575
  return sha256Hex(content).slice(0, 16);
15574
15576
  }
@@ -15699,7 +15701,7 @@ ${sectionText}` : sectionText;
15699
15701
  return chunks;
15700
15702
  }
15701
15703
 
15702
- // src/memory/indexer.ts
15704
+ // src/services/memory/indexer.ts
15703
15705
  var MemoryIndexer = class {
15704
15706
  constructor(store, embedder, config) {
15705
15707
  this.store = store;
@@ -15882,10 +15884,32 @@ ${content}
15882
15884
  }
15883
15885
  };
15884
15886
 
15885
- // src/memory/digest/processor.ts
15887
+ // src/services/digest/processor.ts
15886
15888
  function digestLockPath(workspaceRoot) {
15887
15889
  return path9.join(workspaceRoot, DIGEST_LOCKFILE_REL_PATH);
15888
15890
  }
15891
+ function discoverPendingConversationFiles(workspaceRoot) {
15892
+ const rawDir = path9.join(workspaceRoot, WIKI_RAW_DIR);
15893
+ let files;
15894
+ try {
15895
+ files = fs7.readdirSync(rawDir).filter((f) => f.startsWith("conv_") && f.endsWith(".md")).map((f) => path9.join(rawDir, f)).sort((a, b) => fs7.statSync(a).mtimeMs - fs7.statSync(b).mtimeMs);
15896
+ } catch (err) {
15897
+ if (err.code === "ENOENT") {
15898
+ files = [];
15899
+ } else {
15900
+ throw err;
15901
+ }
15902
+ }
15903
+ const outDir = defaultProvisionalDigestDir(workspaceRoot);
15904
+ return files.filter((f) => {
15905
+ try {
15906
+ const input = readConversationDigestInput(workspaceRoot, f);
15907
+ return !findExistingProvisionalDigest(outDir, input);
15908
+ } catch {
15909
+ return false;
15910
+ }
15911
+ });
15912
+ }
15889
15913
  async function indexProvisionalDigestFile(workspaceRoot, markdownPath) {
15890
15914
  try {
15891
15915
  const settings = loadProjectSettings(workspaceRoot);
@@ -15935,9 +15959,21 @@ async function digestConversationFile(options) {
15935
15959
  await provider.dispose?.();
15936
15960
  }
15937
15961
  }
15962
+ function summarizePendingConversations(workspaceRoot) {
15963
+ const digestConfig = resolveConversationDigestConfig(loadProjectSettings(workspaceRoot));
15964
+ if (!digestConfig || digestConfig.enabled === false) {
15965
+ return { initialized: false, pending: 0, reason: "not-initialized" };
15966
+ }
15967
+ const candidates = discoverPendingConversationFiles(workspaceRoot);
15968
+ if (candidates.length === 0) {
15969
+ return { initialized: true, pending: 0, reason: "no-pending" };
15970
+ }
15971
+ return { initialized: true, pending: candidates.length };
15972
+ }
15938
15973
  async function digestPendingConversations({
15939
15974
  workspaceRoot,
15940
- digestFn = digestConversationFile
15975
+ digestFn = digestConversationFile,
15976
+ onProgress
15941
15977
  }) {
15942
15978
  const digestConfig = resolveConversationDigestConfig(loadProjectSettings(workspaceRoot));
15943
15979
  if (!digestConfig || digestConfig.enabled === false) {
@@ -15948,26 +15984,7 @@ async function digestPendingConversations({
15948
15984
  return { ok: true, initialized: true, action: "noop", reason: "locked" };
15949
15985
  }
15950
15986
  try {
15951
- const rawDir = path9.join(workspaceRoot, WIKI_RAW_DIR);
15952
- let files;
15953
- try {
15954
- files = fs7.readdirSync(rawDir).filter((f) => f.startsWith("conv_") && f.endsWith(".md")).map((f) => path9.join(rawDir, f)).sort((a, b) => fs7.statSync(a).mtimeMs - fs7.statSync(b).mtimeMs);
15955
- } catch (err) {
15956
- if (err.code === "ENOENT") {
15957
- files = [];
15958
- } else {
15959
- throw err;
15960
- }
15961
- }
15962
- const outDir = defaultProvisionalDigestDir(workspaceRoot);
15963
- const candidates = files.filter((f) => {
15964
- try {
15965
- const input = readConversationDigestInput(workspaceRoot, f);
15966
- return !findExistingProvisionalDigest(outDir, input);
15967
- } catch {
15968
- return false;
15969
- }
15970
- });
15987
+ const candidates = discoverPendingConversationFiles(workspaceRoot);
15971
15988
  if (candidates.length === 0) {
15972
15989
  return { ok: true, initialized: true, action: "noop", reason: "no-pending" };
15973
15990
  }
@@ -15989,6 +16006,9 @@ async function digestPendingConversations({
15989
16006
  } catch {
15990
16007
  errors++;
15991
16008
  }
16009
+ if (onProgress) {
16010
+ await onProgress({ processed: count, skipped, errors });
16011
+ }
15992
16012
  }
15993
16013
  return { ok: true, initialized: true, action: "digested", count, skipped, errors };
15994
16014
  } catch (err) {
@@ -16033,10 +16053,262 @@ async function initializeConversationDigestModel(input) {
16033
16053
  }
16034
16054
  }
16035
16055
 
16036
- // src/memory/digest/worker.ts
16056
+ // src/services/digest/background.ts
16057
+ import * as fs8 from "node:fs";
16058
+ import * as path10 from "node:path";
16059
+ import { spawn } from "node:child_process";
16060
+
16061
+ // src/utils/json.ts
16062
+ function isRecord(value) {
16063
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16064
+ }
16065
+
16066
+ // src/services/digest/background.ts
16067
+ function digestWorkerStatusPath(workspaceRoot) {
16068
+ return path10.join(workspaceRoot, DIGEST_WORKER_STATUS_REL_PATH);
16069
+ }
16070
+ function digestWorkerLogPath(workspaceRoot) {
16071
+ return path10.join(workspaceRoot, DIGEST_WORKER_LOG_REL_PATH);
16072
+ }
16073
+ function digestWorkerLockPath(workspaceRoot) {
16074
+ return path10.join(workspaceRoot, DIGEST_LOCKFILE_REL_PATH);
16075
+ }
16076
+ function isoNow() {
16077
+ return (/* @__PURE__ */ new Date()).toISOString();
16078
+ }
16079
+ function errorMessage(err) {
16080
+ return err instanceof Error ? err.message : String(err);
16081
+ }
16082
+ function emptyStatus(state, pendingAtStart, startedAt = isoNow()) {
16083
+ return {
16084
+ state,
16085
+ pid: null,
16086
+ startedAt,
16087
+ updatedAt: startedAt,
16088
+ pendingAtStart,
16089
+ processed: 0,
16090
+ skipped: 0,
16091
+ errors: 0
16092
+ };
16093
+ }
16094
+ var WORKER_STATES = /* @__PURE__ */ new Set([
16095
+ "running",
16096
+ "complete",
16097
+ "failed",
16098
+ "not-initialized",
16099
+ "no-pending",
16100
+ "locked",
16101
+ "stale"
16102
+ ]);
16103
+ function isDigestWorkerStatus(value) {
16104
+ if (!isRecord(value)) return false;
16105
+ return typeof value.state === "string" && WORKER_STATES.has(value.state) && (typeof value.pid === "number" || value.pid === null) && typeof value.startedAt === "string" && typeof value.updatedAt === "string" && typeof value.pendingAtStart === "number" && typeof value.processed === "number" && typeof value.skipped === "number" && typeof value.errors === "number" && (value.lastError === void 0 || typeof value.lastError === "string");
16106
+ }
16107
+ function readDigestWorkerStatus(workspaceRoot) {
16108
+ try {
16109
+ const parsed = JSON.parse(fs8.readFileSync(digestWorkerStatusPath(workspaceRoot), "utf8"));
16110
+ return isDigestWorkerStatus(parsed) ? parsed : void 0;
16111
+ } catch {
16112
+ return void 0;
16113
+ }
16114
+ }
16115
+ function writeDigestWorkerStatus(workspaceRoot, status) {
16116
+ atomicWriteJsonFile(digestWorkerStatusPath(workspaceRoot), status);
16117
+ }
16118
+ function appendDigestWorkerLog(workspaceRoot, message) {
16119
+ try {
16120
+ const logPath = digestWorkerLogPath(workspaceRoot);
16121
+ fs8.mkdirSync(path10.dirname(logPath), { recursive: true });
16122
+ fs8.appendFileSync(logPath, `[${isoNow()}] ${message}
16123
+ `, "utf8");
16124
+ } catch {
16125
+ }
16126
+ }
16127
+ function isLivePid(pid) {
16128
+ if (pid === null || !Number.isInteger(pid) || pid <= 0) return false;
16129
+ try {
16130
+ process.kill(pid, 0);
16131
+ return true;
16132
+ } catch (err) {
16133
+ return err.code !== "ESRCH";
16134
+ }
16135
+ }
16136
+ function readLockPid(workspaceRoot) {
16137
+ const lockPath = digestWorkerLockPath(workspaceRoot);
16138
+ if (!fs8.existsSync(lockPath)) return void 0;
16139
+ try {
16140
+ const parsed = JSON.parse(fs8.readFileSync(lockPath, "utf8"));
16141
+ return isRecord(parsed) && typeof parsed.pid === "number" ? parsed.pid : null;
16142
+ } catch {
16143
+ return null;
16144
+ }
16145
+ }
16146
+ function statusFromPendingResult(result, startedAt, pendingAtStart) {
16147
+ const updatedAt = isoNow();
16148
+ if (!result.ok) {
16149
+ return {
16150
+ ...emptyStatus("failed", pendingAtStart, startedAt),
16151
+ updatedAt,
16152
+ errors: 1,
16153
+ lastError: result.error
16154
+ };
16155
+ }
16156
+ if (result.action === "digested") {
16157
+ return {
16158
+ state: "complete",
16159
+ pid: null,
16160
+ startedAt,
16161
+ updatedAt,
16162
+ pendingAtStart,
16163
+ processed: result.count,
16164
+ skipped: result.skipped,
16165
+ errors: result.errors
16166
+ };
16167
+ }
16168
+ return {
16169
+ ...emptyStatus(result.reason, pendingAtStart, startedAt),
16170
+ updatedAt
16171
+ };
16172
+ }
16173
+ async function runDigestPendingWorker(input) {
16174
+ const startedAt = isoNow();
16175
+ let pendingAtStart = input.pendingAtStart ?? 0;
16176
+ try {
16177
+ const summary = summarizePendingConversations(input.workspaceRoot);
16178
+ if (input.pendingAtStart === void 0) {
16179
+ pendingAtStart = summary.initialized ? summary.pending : 0;
16180
+ }
16181
+ const runningStatus = {
16182
+ ...emptyStatus("running", pendingAtStart, startedAt),
16183
+ pid: process.pid
16184
+ };
16185
+ writeDigestWorkerStatus(input.workspaceRoot, runningStatus);
16186
+ appendDigestWorkerLog(input.workspaceRoot, `worker started pid=${process.pid} pending=${pendingAtStart}`);
16187
+ const result = await digestPendingConversations({
16188
+ workspaceRoot: input.workspaceRoot,
16189
+ digestFn: input.digestFn,
16190
+ onProgress: (progress) => {
16191
+ const currentStatus = {
16192
+ ...runningStatus,
16193
+ updatedAt: isoNow(),
16194
+ processed: progress.processed,
16195
+ skipped: progress.skipped,
16196
+ errors: progress.errors
16197
+ };
16198
+ writeDigestWorkerStatus(input.workspaceRoot, currentStatus);
16199
+ }
16200
+ });
16201
+ const status = statusFromPendingResult(result, startedAt, pendingAtStart);
16202
+ writeDigestWorkerStatus(input.workspaceRoot, status);
16203
+ appendDigestWorkerLog(
16204
+ input.workspaceRoot,
16205
+ `worker finished state=${status.state} processed=${status.processed} skipped=${status.skipped} errors=${status.errors}`
16206
+ );
16207
+ return status;
16208
+ } catch (err) {
16209
+ const status = {
16210
+ ...emptyStatus("failed", pendingAtStart, startedAt),
16211
+ updatedAt: isoNow(),
16212
+ errors: 1,
16213
+ lastError: errorMessage(err)
16214
+ };
16215
+ writeDigestWorkerStatus(input.workspaceRoot, status);
16216
+ appendDigestWorkerLog(input.workspaceRoot, `worker failed error=${status.lastError}`);
16217
+ return status;
16218
+ }
16219
+ }
16220
+ function launchDigestPendingWorker(input) {
16221
+ const startedAt = isoNow();
16222
+ let pendingAtStart = 0;
16223
+ try {
16224
+ const previousStatus = readDigestWorkerStatus(input.workspaceRoot);
16225
+ if (previousStatus?.state === "running" && isLivePid(previousStatus.pid)) {
16226
+ const status2 = {
16227
+ ...previousStatus,
16228
+ state: "locked",
16229
+ updatedAt: isoNow(),
16230
+ lastError: void 0
16231
+ };
16232
+ writeDigestWorkerStatus(input.workspaceRoot, status2);
16233
+ return { ok: true, mode: "background-launcher", status: status2, spawned: false, reason: "locked" };
16234
+ }
16235
+ const lockPid = readLockPid(input.workspaceRoot);
16236
+ if (lockPid !== void 0 && isLivePid(lockPid)) {
16237
+ const status2 = emptyStatus("locked", 0, startedAt);
16238
+ writeDigestWorkerStatus(input.workspaceRoot, status2);
16239
+ return { ok: true, mode: "background-launcher", status: status2, spawned: false, reason: "locked" };
16240
+ }
16241
+ const summary = summarizePendingConversations(input.workspaceRoot);
16242
+ if (!summary.initialized) {
16243
+ const status2 = emptyStatus("not-initialized", 0, startedAt);
16244
+ writeDigestWorkerStatus(input.workspaceRoot, status2);
16245
+ return { ok: true, mode: "background-launcher", status: status2, spawned: false, reason: "not-initialized" };
16246
+ }
16247
+ if (summary.pending === 0) {
16248
+ const status2 = emptyStatus("no-pending", 0, startedAt);
16249
+ writeDigestWorkerStatus(input.workspaceRoot, status2);
16250
+ return { ok: true, mode: "background-launcher", status: status2, spawned: false, reason: "no-pending" };
16251
+ }
16252
+ pendingAtStart = summary.pending;
16253
+ if (!input.entrypoint) {
16254
+ const status2 = {
16255
+ ...emptyStatus("failed", pendingAtStart, startedAt),
16256
+ errors: 1,
16257
+ lastError: "CLI entrypoint is unavailable"
16258
+ };
16259
+ writeDigestWorkerStatus(input.workspaceRoot, status2);
16260
+ return {
16261
+ ok: false,
16262
+ mode: "background-launcher",
16263
+ status: status2,
16264
+ spawned: false,
16265
+ reason: "spawn-failed",
16266
+ error: status2.lastError
16267
+ };
16268
+ }
16269
+ const child = spawn(
16270
+ process.execPath,
16271
+ [input.entrypoint, "memory", "digest-pending", ...input.args, `--${DIGEST_WORKER_FLAG}`],
16272
+ {
16273
+ cwd: input.workspaceRoot,
16274
+ detached: true,
16275
+ stdio: "ignore"
16276
+ }
16277
+ );
16278
+ child.unref();
16279
+ if (!child.pid) {
16280
+ throw new Error("worker process did not expose a pid");
16281
+ }
16282
+ const status = {
16283
+ ...emptyStatus("running", pendingAtStart, startedAt),
16284
+ pid: child.pid
16285
+ };
16286
+ writeDigestWorkerStatus(input.workspaceRoot, status);
16287
+ appendDigestWorkerLog(input.workspaceRoot, `launcher spawned pid=${child.pid} pending=${pendingAtStart}`);
16288
+ return { ok: true, mode: "background-launcher", status, spawned: true, pid: child.pid };
16289
+ } catch (err) {
16290
+ const status = {
16291
+ ...emptyStatus("failed", pendingAtStart, startedAt),
16292
+ errors: 1,
16293
+ lastError: errorMessage(err)
16294
+ };
16295
+ writeDigestWorkerStatus(input.workspaceRoot, status);
16296
+ appendDigestWorkerLog(input.workspaceRoot, `launcher failed error=${status.lastError}`);
16297
+ return {
16298
+ ok: false,
16299
+ mode: "background-launcher",
16300
+ status,
16301
+ spawned: false,
16302
+ reason: "spawn-failed",
16303
+ error: status.lastError
16304
+ };
16305
+ }
16306
+ }
16307
+
16308
+ // src/services/digest/worker.ts
16037
16309
  import { spawnSync } from "node:child_process";
16038
16310
 
16039
- // src/utils/args.ts
16311
+ // src/cli/utils/args.ts
16040
16312
  function parseArgs(args) {
16041
16313
  const flags = /* @__PURE__ */ new Map();
16042
16314
  const positionals = [];
@@ -16069,7 +16341,7 @@ function numberFlag(flags, key, defaultValue) {
16069
16341
  return value;
16070
16342
  }
16071
16343
 
16072
- // src/memory/digest/worker.ts
16344
+ // src/services/digest/worker.ts
16073
16345
  function isDigestWorkerResult(value) {
16074
16346
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
16075
16347
  const record = value;
@@ -16116,7 +16388,7 @@ function getWorkspaceRoot() {
16116
16388
  return process.env.WORKSPACE_DIR || process.env.CLAUDE_PROJECT_DIR || process.env.CODEX_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.CLAUDE_WORKSPACE || process.env.CODEX_WORKSPACE || process.env.GEMINI_WORKSPACE || process.env.INIT_CWD || process.env.PWD || process.cwd();
16117
16389
  }
16118
16390
 
16119
- // src/cli/memory.ts
16391
+ // src/cli/commands/memory.ts
16120
16392
  function writeDigestFileResult(result, workerMode) {
16121
16393
  if (workerMode) {
16122
16394
  process.stdout.write(DIGEST_WORKER_RESULT_PREFIX + JSON.stringify(result) + "\n");
@@ -16145,7 +16417,7 @@ async function cmdDigestFile(args) {
16145
16417
  const modelId = stringFlag(parsed.flags, "model") ?? digestConfig?.modelId ?? DEFAULT_DIGEST_MODEL_ID;
16146
16418
  const inputPath = stringFlag(parsed.flags, "input");
16147
16419
  if (!inputPath) {
16148
- process.stderr.write("Usage: agent-kit-cli memory digest-file --input <path> --model <id>\n");
16420
+ process.stderr.write("Usage: cli memory digest-file --input <path> --model <id>\n");
16149
16421
  return 1;
16150
16422
  }
16151
16423
  const result = await digestConversationFile({
@@ -16161,11 +16433,23 @@ async function cmdDigestFile(args) {
16161
16433
  }
16162
16434
  async function cmdDigestPending(args) {
16163
16435
  const parsed = parseArgs(args);
16164
- if (parsed.flags.get("hook") !== true) {
16165
- process.stderr.write("Usage: agent-kit-cli memory digest-pending --hook\n");
16166
- return 1;
16436
+ const workspaceRoot = getWorkspaceRoot();
16437
+ const isBackground = parsed.flags.get("background") === true;
16438
+ if (isBackground && parsed.flags.get(DIGEST_WORKER_FLAG) === true) {
16439
+ const result2 = await runDigestPendingWorker({ workspaceRoot });
16440
+ process.stdout.write(JSON.stringify(result2) + "\n");
16441
+ return 0;
16442
+ }
16443
+ if (isBackground) {
16444
+ const result2 = launchDigestPendingWorker({
16445
+ workspaceRoot,
16446
+ args,
16447
+ entrypoint: process.argv[1]
16448
+ });
16449
+ process.stdout.write(JSON.stringify(result2) + "\n");
16450
+ return 0;
16167
16451
  }
16168
- const result = await digestPendingConversations({ workspaceRoot: getWorkspaceRoot() });
16452
+ const result = await digestPendingConversations({ workspaceRoot });
16169
16453
  process.stdout.write(JSON.stringify(result) + "\n");
16170
16454
  return 0;
16171
16455
  }
@@ -16180,7 +16464,7 @@ async function runMemoryCli(args, _env) {
16180
16464
  process.stderr.write("[agent-kit] memory " + (command ?? "") + " failed: " + message + "\n");
16181
16465
  return 1;
16182
16466
  }
16183
- process.stderr.write("Usage: agent-kit-cli memory <digest-file|digest-init|digest-pending>\n");
16467
+ process.stderr.write("Usage: cli memory <digest-file|digest-init|digest-pending>\n");
16184
16468
  return 1;
16185
16469
  }
16186
16470
 
@@ -16190,11 +16474,11 @@ async function runAgentKitCli(argv, env) {
16190
16474
  if (command === "memory") {
16191
16475
  return runMemoryCli(rest, env);
16192
16476
  }
16193
- process.stderr.write("Usage: agent-kit-cli memory <digest-file|digest-init|digest-pending>\n");
16477
+ process.stderr.write("Usage: cli memory <digest-file|digest-init|digest-pending>\n");
16194
16478
  return 1;
16195
16479
  }
16196
16480
 
16197
- // src/kit-cli.ts
16481
+ // src/entrypoints/cli.ts
16198
16482
  try {
16199
16483
  const exitCode = await runAgentKitCli(process.argv.slice(2), process.env);
16200
16484
  process.exit(exitCode);
@@ -2,8 +2,8 @@
2
2
  * Configuration utilities
3
3
  * Shared configuration constants and loaders
4
4
  */
5
- import type { MemoryConfig } from '../memory/types.js';
6
- import type { ConversationDigestSettings } from '../memory/digest/types.js';
5
+ import type { MemoryConfig } from '../../services/memory/types.js';
6
+ import type { ConversationDigestSettings } from '../../services/digest/types.js';
7
7
  /**
8
8
  * Default file extensions - expanded to support more languages
9
9
  * Used by kit_get_project_context and other tools
@@ -22,11 +22,6 @@ export { MemoryConfig };
22
22
  * Merge DEFAULT_MEMORY_CONFIG with settings.memory; resolve wikiDir when not explicitly set.
23
23
  */
24
24
  export declare function resolveMemoryConfig(settings: ProjectSettings, workspaceRoot: string): MemoryConfig;
25
- /**
26
- * Get file extensions - from settings.json or defaults
27
- * Allows project-specific customization
28
- */
29
- export declare function getFileExtensions(projectDir: string): string[];
30
25
  export declare function loadProjectSettings(projectDir: string): ProjectSettings;
31
26
  export declare function writeProjectSettings(workspaceRoot: string, patch: Partial<ProjectSettings>): void;
32
27
  export declare function resolveConversationDigestConfig(settings: ProjectSettings): ConversationDigestSettings | undefined;
@@ -4,8 +4,8 @@
4
4
  */
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
- import { DEFAULT_MEMORY_CONFIG } from '../memory/constants.js';
8
- import { atomicWriteJsonFile } from '../utils/files.js';
7
+ import { DEFAULT_MEMORY_CONFIG } from '../../services/memory/constants.js';
8
+ import { atomicWriteJsonFile } from '../../utils/files.js';
9
9
  /**
10
10
  * Default file extensions - expanded to support more languages
11
11
  * Used by kit_get_project_context and other tools
@@ -48,17 +48,6 @@ export function resolveMemoryConfig(settings, workspaceRoot) {
48
48
  : path.join(workspaceRoot, '.agent-kit', 'wiki'),
49
49
  };
50
50
  }
51
- /**
52
- * Get file extensions - from settings.json or defaults
53
- * Allows project-specific customization
54
- */
55
- export function getFileExtensions(projectDir) {
56
- const settings = loadProjectSettings(projectDir);
57
- if (settings.fileExtensions && Array.isArray(settings.fileExtensions)) {
58
- return settings.fileExtensions;
59
- }
60
- return DEFAULT_EXTENSIONS;
61
- }
62
51
  export function loadProjectSettings(projectDir) {
63
52
  const settingsPath = path.join(projectDir, '.agent-kit', 'settings.json');
64
53
  if (fs.existsSync(settingsPath)) {
@@ -0,0 +1,17 @@
1
+ export declare const HANDOFF_TYPES: readonly ["brainstorm", "clarification", "plan", "ticket", "research", "scenario", "investigation", "code"];
2
+ type HandoffType = (typeof HANDOFF_TYPES)[number];
3
+ type CanonicalHandoffType = 'brainstorm' | 'clarification' | 'plan' | 'ticket' | 'research' | 'scenario' | 'investigation' | 'code';
4
+ export interface SavedHandoffFolderLocation {
5
+ featureSlug: string;
6
+ canonicalType: CanonicalHandoffType;
7
+ folderPath: string;
8
+ relativePath: string;
9
+ }
10
+ export declare function resolveHandoffFolder(input: {
11
+ workspaceRoot: string;
12
+ type: HandoffType;
13
+ slug: string;
14
+ primaryContent: string;
15
+ }): SavedHandoffFolderLocation;
16
+ export declare function validateHandoffFilename(name: string): string;
17
+ export {};