@hanhnd/agent-kit 1.0.32 → 1.0.33
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 +111 -0
- package/dist/cli/commands/cli-memory.test.js +34 -0
- package/dist/cli/{memory.js → commands/memory.js} +24 -11
- package/dist/cli/index.js +2 -2
- package/dist/{utils → cli/utils}/args.d.ts +2 -1
- package/dist/{kit-cli.js → cli.js} +342 -58
- package/dist/{tools/config.d.ts → core/config/index.d.ts} +2 -7
- package/dist/{tools/config.js → core/config/index.js} +2 -13
- package/dist/core/handoffs/index.d.ts +16 -0
- package/dist/{tools/handoffs.js → core/handoffs/index.js} +3 -3
- package/dist/{tools/security.d.ts → core/security/index.d.ts} +0 -19
- package/dist/{tools/security.js → core/security/index.js} +3 -76
- package/dist/entrypoints/cli.js +11 -0
- package/dist/entrypoints/server.js +37 -0
- package/dist/{tools → mcp}/agent.js +1 -1
- package/dist/{tools → mcp}/core.d.ts +1 -1
- package/dist/{tools → mcp}/core.js +2 -2
- package/dist/{tools → mcp}/integration.js +3 -3
- package/dist/mcp/memory.d.ts +15 -0
- package/dist/{tools → mcp}/memory.js +15 -13
- package/dist/{kit-server.js → server.js} +80 -70
- package/dist/services/digest/background.d.ts +11 -0
- package/dist/services/digest/background.js +258 -0
- package/dist/{memory → services}/digest/constants.d.ts +4 -1
- package/dist/{memory → services}/digest/constants.js +6 -2
- package/dist/services/digest/digest-background.test.js +206 -0
- package/dist/{tools/__tests__ → services/digest}/digest-init.test.js +4 -3
- package/dist/{memory/__tests__ → services/digest}/digest-llama-local.test.js +1 -13
- package/dist/{memory/__tests__ → services/digest}/digest-pending.test.js +39 -11
- package/dist/{memory/__tests__ → services/digest}/digest-processor.test.js +5 -7
- package/dist/{memory → services}/digest/files.d.ts +0 -1
- package/dist/{memory → services}/digest/files.js +2 -2
- package/dist/services/digest/model-registry.d.ts +2 -0
- package/dist/{memory → services}/digest/model-registry.js +9 -8
- package/dist/services/digest/processor.d.ts +13 -0
- package/dist/{memory → services}/digest/processor.js +48 -31
- package/dist/services/digest/providers/llama-local.d.ts +2 -0
- package/dist/{memory → services}/digest/providers/llama-local.js +3 -4
- package/dist/{memory → services}/digest/types.d.ts +34 -2
- package/dist/services/digest/types.js +6 -0
- package/dist/{memory → services}/digest/worker.d.ts +0 -1
- package/dist/{memory → services}/digest/worker.js +2 -2
- package/dist/{utils → services/integration}/credentials.js +1 -1
- package/dist/{utils/parser.js → services/integration/parser/adf.js} +1 -0
- package/dist/{memory → services/memory}/chunker.d.ts +0 -2
- package/dist/{memory → services/memory}/chunker.js +3 -3
- package/dist/{memory/__tests__ → services/memory}/chunker.test.js +1 -34
- package/dist/{memory → services/memory}/constants.d.ts +1 -1
- package/dist/{memory → services/memory}/constants.js +2 -1
- package/dist/{memory → services/memory}/embedder.d.ts +2 -2
- package/dist/{memory → services/memory}/embedder.js +5 -5
- package/dist/services/memory/embedder.test.js +13 -0
- package/dist/{memory → services/memory}/indexer.d.ts +2 -1
- package/dist/{memory → services/memory}/indexer.js +1 -1
- package/dist/{memory/__tests__ → services/memory}/indexer.test.js +4 -3
- package/dist/{tools/__tests__ → services/memory}/memory.test.js +54 -13
- package/dist/{memory/__tests__ → services/memory}/store.test.js +3 -2
- package/dist/{memory → services/memory}/types.d.ts +7 -2
- package/dist/services/memory/types.js +6 -0
- package/dist/utils/files.d.ts +0 -1
- package/dist/utils/files.js +1 -1
- package/dist/{memory/__tests__/lockfile.test.js → utils/files.test.js} +14 -14
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/json.d.ts +0 -1
- package/dist/utils/json.js +0 -10
- package/dist/utils/paths.d.ts +0 -1
- package/dist/utils/paths.js +1 -1
- package/package.json +6 -6
- package/dist/memory/__tests__/digest-worker.test.js +0 -46
- package/dist/memory/__tests__/embedder.test.js +0 -14
- package/dist/memory/digest/model-registry.d.ts +0 -6
- package/dist/memory/digest/processor.d.ts +0 -7
- package/dist/memory/digest/providers/llama-local.d.ts +0 -7
- package/dist/memory/digest/types.js +0 -1
- package/dist/memory/types.js +0 -1
- package/dist/tools/__tests__/cli-digest-pending.test.js +0 -51
- package/dist/tools/__tests__/cli-memory.test.js +0 -22
- package/dist/tools/handoffs.d.ts +0 -22
- package/dist/tools/memory.d.ts +0 -16
- /package/dist/{tools/__tests__ → cli/commands}/cli-digest-pending.test.d.ts +0 -0
- /package/dist/{tools/__tests__ → cli/commands}/cli-memory.test.d.ts +0 -0
- /package/dist/cli/{memory.d.ts → commands/memory.d.ts} +0 -0
- /package/dist/{utils → cli/utils}/args.js +0 -0
- /package/dist/{kit-cli.d.ts → entrypoints/cli.d.ts} +0 -0
- /package/dist/{kit-server.d.ts → entrypoints/server.d.ts} +0 -0
- /package/dist/{tools → mcp}/agent.d.ts +0 -0
- /package/dist/{tools → mcp}/integration.d.ts +0 -0
- /package/dist/{memory/__tests__/chunker.test.d.ts → services/digest/digest-background.test.d.ts} +0 -0
- /package/dist/{tools/__tests__ → services/digest}/digest-init.test.d.ts +0 -0
- /package/dist/{memory/__tests__ → services/digest}/digest-llama-local.test.d.ts +0 -0
- /package/dist/{memory/__tests__ → services/digest}/digest-pending.test.d.ts +0 -0
- /package/dist/{memory/__tests__ → services/digest}/digest-processor.test.d.ts +0 -0
- /package/dist/{utils → services/integration}/credentials.d.ts +0 -0
- /package/dist/{utils/parser.d.ts → services/integration/parser/adf.d.ts} +0 -0
- /package/dist/{memory/__tests__/digest-worker.test.d.ts → services/memory/chunker.test.d.ts} +0 -0
- /package/dist/{memory/__tests__ → services/memory}/embedder.test.d.ts +0 -0
- /package/dist/{memory → services/memory}/index.d.ts +0 -0
- /package/dist/{memory → services/memory}/index.js +0 -0
- /package/dist/{memory/__tests__ → services/memory}/indexer.test.d.ts +0 -0
- /package/dist/{tools/__tests__ → services/memory}/memory.test.d.ts +0 -0
- /package/dist/{memory → services/memory}/store.d.ts +0 -0
- /package/dist/{memory → services/memory}/store.js +0 -0
- /package/dist/{memory/__tests__ → services/memory}/store.test.d.ts +0 -0
- /package/dist/{memory/__tests__/lockfile.test.d.ts → utils/files.test.d.ts} +0 -0
- /package/dist/{__tests__/temp-dir.d.ts → utils/temp-dir.test.d.ts} +0 -0
- /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/
|
|
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/
|
|
14927
|
+
// src/services/digest/constants.ts
|
|
14928
14928
|
import * as path from "node:path";
|
|
14929
|
-
var DEFAULT_DIGEST_MODEL_ID = "
|
|
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
|
|
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/
|
|
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/
|
|
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: "
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
-
"
|
|
15124
|
-
id: "
|
|
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
|
-
"
|
|
15132
|
-
id: "
|
|
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
|
-
"
|
|
15140
|
-
id: "
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
|
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/
|
|
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/
|
|
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:
|
|
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
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
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
|
|
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:
|
|
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:
|
|
16477
|
+
process.stderr.write("Usage: cli memory <digest-file|digest-init|digest-pending>\n");
|
|
16194
16478
|
return 1;
|
|
16195
16479
|
}
|
|
16196
16480
|
|
|
16197
|
-
// src/
|
|
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 '
|
|
6
|
-
import type { ConversationDigestSettings } from '
|
|
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 '
|
|
8
|
-
import { atomicWriteJsonFile } from '
|
|
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,16 @@
|
|
|
1
|
+
export declare const HANDOFF_TYPES: readonly ["brainstorm", "clarification", "plan", "ticket", "research", "scenario", "investigation"];
|
|
2
|
+
type HandoffType = (typeof HANDOFF_TYPES)[number];
|
|
3
|
+
type CanonicalHandoffType = 'brainstorm' | 'clarification' | 'plan' | 'ticket' | 'research' | 'scenario' | 'investigation';
|
|
4
|
+
interface SavedHandoffLocation {
|
|
5
|
+
featureSlug: string;
|
|
6
|
+
canonicalType: CanonicalHandoffType;
|
|
7
|
+
filePath: string;
|
|
8
|
+
relativePath: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveHandoffPath(input: {
|
|
11
|
+
workspaceRoot: string;
|
|
12
|
+
type: HandoffType;
|
|
13
|
+
slug: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}): SavedHandoffLocation;
|
|
16
|
+
export {};
|