@rlabs-inc/memory 0.4.6 → 0.4.8
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/index.js +39 -7
- package/dist/index.mjs +39 -7
- package/dist/server/index.js +39 -7
- package/dist/server/index.mjs +39 -7
- package/hooks/claude/curation.ts +6 -2
- package/package.json +1 -1
- package/src/core/curator.ts +154 -8
package/dist/index.js
CHANGED
|
@@ -35223,10 +35223,11 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
35223
35223
|
try {
|
|
35224
35224
|
const jsonMatch = responseJson.match(/\{[\s\S]*\}/)?.[0];
|
|
35225
35225
|
if (!jsonMatch) {
|
|
35226
|
+
logger.debug("parseCurationResponse: No JSON object found in response", "curator");
|
|
35226
35227
|
throw new Error("No JSON object found in response");
|
|
35227
35228
|
}
|
|
35228
35229
|
const data = JSON.parse(jsonMatch);
|
|
35229
|
-
|
|
35230
|
+
const result = {
|
|
35230
35231
|
session_summary: data.session_summary ?? "",
|
|
35231
35232
|
interaction_tone: data.interaction_tone,
|
|
35232
35233
|
project_snapshot: data.project_snapshot ? {
|
|
@@ -35241,7 +35242,10 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
35241
35242
|
} : undefined,
|
|
35242
35243
|
memories: this._parseMemories(data.memories ?? [])
|
|
35243
35244
|
};
|
|
35244
|
-
|
|
35245
|
+
logger.debug(`Curator parsed: ${result.memories.length} memories, summary: ${result.session_summary ? "yes" : "no"}, snapshot: ${result.project_snapshot ? "yes" : "no"}`, "curator");
|
|
35246
|
+
return result;
|
|
35247
|
+
} catch (error2) {
|
|
35248
|
+
logger.debug(`parseCurationResponse error: ${error2.message}`, "curator");
|
|
35245
35249
|
return {
|
|
35246
35250
|
session_summary: "",
|
|
35247
35251
|
memories: []
|
|
@@ -35345,7 +35349,6 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
35345
35349
|
options: {
|
|
35346
35350
|
systemPrompt,
|
|
35347
35351
|
permissionMode: "bypassPermissions",
|
|
35348
|
-
maxTurns: 1,
|
|
35349
35352
|
model: "claude-opus-4-5-20251101"
|
|
35350
35353
|
}
|
|
35351
35354
|
});
|
|
@@ -35357,8 +35360,14 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
35357
35360
|
}
|
|
35358
35361
|
}
|
|
35359
35362
|
if (!resultText) {
|
|
35363
|
+
logger.debug("Curator SDK: No result text returned from Agent SDK", "curator");
|
|
35360
35364
|
return { session_summary: "", memories: [] };
|
|
35361
35365
|
}
|
|
35366
|
+
logger.debug(`Curator SDK raw response (${resultText.length} chars):`, "curator");
|
|
35367
|
+
if (logger.isVerbose()) {
|
|
35368
|
+
const preview = resultText.length > 3000 ? resultText.slice(0, 3000) + "...[truncated]" : resultText;
|
|
35369
|
+
console.log(preview);
|
|
35370
|
+
}
|
|
35362
35371
|
return this.parseCurationResponse(resultText);
|
|
35363
35372
|
}
|
|
35364
35373
|
_formatConversationTranscript(messages) {
|
|
@@ -35405,7 +35414,7 @@ ${content}
|
|
|
35405
35414
|
];
|
|
35406
35415
|
const response = await client.messages.create({
|
|
35407
35416
|
model: "claude-sonnet-4-20250514",
|
|
35408
|
-
max_tokens:
|
|
35417
|
+
max_tokens: 64000,
|
|
35409
35418
|
system: systemPrompt,
|
|
35410
35419
|
messages: conversationMessages
|
|
35411
35420
|
});
|
|
@@ -35425,7 +35434,7 @@ ${content}
|
|
|
35425
35434
|
const args = [];
|
|
35426
35435
|
let command = this._config.cliCommand;
|
|
35427
35436
|
if (type === "claude-code") {
|
|
35428
|
-
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json"
|
|
35437
|
+
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json");
|
|
35429
35438
|
} else {
|
|
35430
35439
|
command = "gemini";
|
|
35431
35440
|
args.push("--resume", sessionId, "-p", `${systemPrompt}
|
|
@@ -35436,7 +35445,8 @@ ${userMessage}`, "--output-format", "json");
|
|
|
35436
35445
|
cwd: cwd2,
|
|
35437
35446
|
env: {
|
|
35438
35447
|
...process.env,
|
|
35439
|
-
MEMORY_CURATOR_ACTIVE: "1"
|
|
35448
|
+
MEMORY_CURATOR_ACTIVE: "1",
|
|
35449
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000"
|
|
35440
35450
|
},
|
|
35441
35451
|
stdout: "pipe",
|
|
35442
35452
|
stderr: "pipe"
|
|
@@ -35447,37 +35457,59 @@ ${userMessage}`, "--output-format", "json");
|
|
|
35447
35457
|
]);
|
|
35448
35458
|
const exitCode = await proc.exited;
|
|
35449
35459
|
if (exitCode !== 0) {
|
|
35460
|
+
logger.debug(`Curator CLI exited with code ${exitCode}`, "curator");
|
|
35461
|
+
if (stderr) {
|
|
35462
|
+
logger.debug(`Curator stderr: ${stderr}`, "curator");
|
|
35463
|
+
}
|
|
35450
35464
|
return { session_summary: "", memories: [] };
|
|
35451
35465
|
}
|
|
35466
|
+
logger.debug(`Curator CLI raw stdout (${stdout.length} chars):`, "curator");
|
|
35467
|
+
if (logger.isVerbose()) {
|
|
35468
|
+
const preview = stdout.length > 2000 ? stdout.slice(0, 2000) + "...[truncated]" : stdout;
|
|
35469
|
+
console.log(preview);
|
|
35470
|
+
}
|
|
35452
35471
|
try {
|
|
35453
35472
|
const cliOutput = JSON.parse(stdout);
|
|
35454
35473
|
let resultObj;
|
|
35455
35474
|
if (Array.isArray(cliOutput)) {
|
|
35456
35475
|
resultObj = cliOutput.find((item) => item.type === "result");
|
|
35457
35476
|
if (!resultObj) {
|
|
35477
|
+
logger.debug("Curator: No result object found in CLI output array", "curator");
|
|
35458
35478
|
return { session_summary: "", memories: [] };
|
|
35459
35479
|
}
|
|
35460
35480
|
} else {
|
|
35461
35481
|
resultObj = cliOutput;
|
|
35462
35482
|
}
|
|
35463
35483
|
if (resultObj.type === "error" || resultObj.is_error === true) {
|
|
35484
|
+
logger.debug(`Curator: Error response from CLI: ${JSON.stringify(resultObj).slice(0, 500)}`, "curator");
|
|
35464
35485
|
return { session_summary: "", memories: [] };
|
|
35465
35486
|
}
|
|
35466
35487
|
let aiResponse = "";
|
|
35467
35488
|
if (typeof resultObj.result === "string") {
|
|
35468
35489
|
aiResponse = resultObj.result;
|
|
35469
35490
|
} else {
|
|
35491
|
+
logger.debug(`Curator: result field is not a string: ${typeof resultObj.result}`, "curator");
|
|
35470
35492
|
return { session_summary: "", memories: [] };
|
|
35471
35493
|
}
|
|
35494
|
+
logger.debug(`Curator AI response (${aiResponse.length} chars):`, "curator");
|
|
35495
|
+
if (logger.isVerbose()) {
|
|
35496
|
+
const preview = aiResponse.length > 3000 ? aiResponse.slice(0, 3000) + "...[truncated]" : aiResponse;
|
|
35497
|
+
console.log(preview);
|
|
35498
|
+
}
|
|
35472
35499
|
const codeBlockMatch = aiResponse.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
35473
35500
|
if (codeBlockMatch) {
|
|
35474
35501
|
aiResponse = codeBlockMatch[1].trim();
|
|
35475
35502
|
}
|
|
35476
35503
|
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/)?.[0];
|
|
35477
35504
|
if (jsonMatch) {
|
|
35505
|
+
logger.debug(`Curator: Found JSON object (${jsonMatch.length} chars), parsing...`, "curator");
|
|
35478
35506
|
return this.parseCurationResponse(jsonMatch);
|
|
35507
|
+
} else {
|
|
35508
|
+
logger.debug("Curator: No JSON object found in AI response", "curator");
|
|
35479
35509
|
}
|
|
35480
|
-
} catch {
|
|
35510
|
+
} catch (error2) {
|
|
35511
|
+
logger.debug(`Curator: Parse error: ${error2.message}`, "curator");
|
|
35512
|
+
}
|
|
35481
35513
|
return { session_summary: "", memories: [] };
|
|
35482
35514
|
}
|
|
35483
35515
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -35192,10 +35192,11 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
35192
35192
|
try {
|
|
35193
35193
|
const jsonMatch = responseJson.match(/\{[\s\S]*\}/)?.[0];
|
|
35194
35194
|
if (!jsonMatch) {
|
|
35195
|
+
logger.debug("parseCurationResponse: No JSON object found in response", "curator");
|
|
35195
35196
|
throw new Error("No JSON object found in response");
|
|
35196
35197
|
}
|
|
35197
35198
|
const data = JSON.parse(jsonMatch);
|
|
35198
|
-
|
|
35199
|
+
const result = {
|
|
35199
35200
|
session_summary: data.session_summary ?? "",
|
|
35200
35201
|
interaction_tone: data.interaction_tone,
|
|
35201
35202
|
project_snapshot: data.project_snapshot ? {
|
|
@@ -35210,7 +35211,10 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
35210
35211
|
} : undefined,
|
|
35211
35212
|
memories: this._parseMemories(data.memories ?? [])
|
|
35212
35213
|
};
|
|
35213
|
-
|
|
35214
|
+
logger.debug(`Curator parsed: ${result.memories.length} memories, summary: ${result.session_summary ? "yes" : "no"}, snapshot: ${result.project_snapshot ? "yes" : "no"}`, "curator");
|
|
35215
|
+
return result;
|
|
35216
|
+
} catch (error2) {
|
|
35217
|
+
logger.debug(`parseCurationResponse error: ${error2.message}`, "curator");
|
|
35214
35218
|
return {
|
|
35215
35219
|
session_summary: "",
|
|
35216
35220
|
memories: []
|
|
@@ -35314,7 +35318,6 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
35314
35318
|
options: {
|
|
35315
35319
|
systemPrompt,
|
|
35316
35320
|
permissionMode: "bypassPermissions",
|
|
35317
|
-
maxTurns: 1,
|
|
35318
35321
|
model: "claude-opus-4-5-20251101"
|
|
35319
35322
|
}
|
|
35320
35323
|
});
|
|
@@ -35326,8 +35329,14 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
35326
35329
|
}
|
|
35327
35330
|
}
|
|
35328
35331
|
if (!resultText) {
|
|
35332
|
+
logger.debug("Curator SDK: No result text returned from Agent SDK", "curator");
|
|
35329
35333
|
return { session_summary: "", memories: [] };
|
|
35330
35334
|
}
|
|
35335
|
+
logger.debug(`Curator SDK raw response (${resultText.length} chars):`, "curator");
|
|
35336
|
+
if (logger.isVerbose()) {
|
|
35337
|
+
const preview = resultText.length > 3000 ? resultText.slice(0, 3000) + "...[truncated]" : resultText;
|
|
35338
|
+
console.log(preview);
|
|
35339
|
+
}
|
|
35331
35340
|
return this.parseCurationResponse(resultText);
|
|
35332
35341
|
}
|
|
35333
35342
|
_formatConversationTranscript(messages) {
|
|
@@ -35374,7 +35383,7 @@ ${content}
|
|
|
35374
35383
|
];
|
|
35375
35384
|
const response = await client.messages.create({
|
|
35376
35385
|
model: "claude-sonnet-4-20250514",
|
|
35377
|
-
max_tokens:
|
|
35386
|
+
max_tokens: 64000,
|
|
35378
35387
|
system: systemPrompt,
|
|
35379
35388
|
messages: conversationMessages
|
|
35380
35389
|
});
|
|
@@ -35394,7 +35403,7 @@ ${content}
|
|
|
35394
35403
|
const args = [];
|
|
35395
35404
|
let command = this._config.cliCommand;
|
|
35396
35405
|
if (type === "claude-code") {
|
|
35397
|
-
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json"
|
|
35406
|
+
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json");
|
|
35398
35407
|
} else {
|
|
35399
35408
|
command = "gemini";
|
|
35400
35409
|
args.push("--resume", sessionId, "-p", `${systemPrompt}
|
|
@@ -35405,7 +35414,8 @@ ${userMessage}`, "--output-format", "json");
|
|
|
35405
35414
|
cwd: cwd2,
|
|
35406
35415
|
env: {
|
|
35407
35416
|
...process.env,
|
|
35408
|
-
MEMORY_CURATOR_ACTIVE: "1"
|
|
35417
|
+
MEMORY_CURATOR_ACTIVE: "1",
|
|
35418
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000"
|
|
35409
35419
|
},
|
|
35410
35420
|
stdout: "pipe",
|
|
35411
35421
|
stderr: "pipe"
|
|
@@ -35416,37 +35426,59 @@ ${userMessage}`, "--output-format", "json");
|
|
|
35416
35426
|
]);
|
|
35417
35427
|
const exitCode = await proc.exited;
|
|
35418
35428
|
if (exitCode !== 0) {
|
|
35429
|
+
logger.debug(`Curator CLI exited with code ${exitCode}`, "curator");
|
|
35430
|
+
if (stderr) {
|
|
35431
|
+
logger.debug(`Curator stderr: ${stderr}`, "curator");
|
|
35432
|
+
}
|
|
35419
35433
|
return { session_summary: "", memories: [] };
|
|
35420
35434
|
}
|
|
35435
|
+
logger.debug(`Curator CLI raw stdout (${stdout.length} chars):`, "curator");
|
|
35436
|
+
if (logger.isVerbose()) {
|
|
35437
|
+
const preview = stdout.length > 2000 ? stdout.slice(0, 2000) + "...[truncated]" : stdout;
|
|
35438
|
+
console.log(preview);
|
|
35439
|
+
}
|
|
35421
35440
|
try {
|
|
35422
35441
|
const cliOutput = JSON.parse(stdout);
|
|
35423
35442
|
let resultObj;
|
|
35424
35443
|
if (Array.isArray(cliOutput)) {
|
|
35425
35444
|
resultObj = cliOutput.find((item) => item.type === "result");
|
|
35426
35445
|
if (!resultObj) {
|
|
35446
|
+
logger.debug("Curator: No result object found in CLI output array", "curator");
|
|
35427
35447
|
return { session_summary: "", memories: [] };
|
|
35428
35448
|
}
|
|
35429
35449
|
} else {
|
|
35430
35450
|
resultObj = cliOutput;
|
|
35431
35451
|
}
|
|
35432
35452
|
if (resultObj.type === "error" || resultObj.is_error === true) {
|
|
35453
|
+
logger.debug(`Curator: Error response from CLI: ${JSON.stringify(resultObj).slice(0, 500)}`, "curator");
|
|
35433
35454
|
return { session_summary: "", memories: [] };
|
|
35434
35455
|
}
|
|
35435
35456
|
let aiResponse = "";
|
|
35436
35457
|
if (typeof resultObj.result === "string") {
|
|
35437
35458
|
aiResponse = resultObj.result;
|
|
35438
35459
|
} else {
|
|
35460
|
+
logger.debug(`Curator: result field is not a string: ${typeof resultObj.result}`, "curator");
|
|
35439
35461
|
return { session_summary: "", memories: [] };
|
|
35440
35462
|
}
|
|
35463
|
+
logger.debug(`Curator AI response (${aiResponse.length} chars):`, "curator");
|
|
35464
|
+
if (logger.isVerbose()) {
|
|
35465
|
+
const preview = aiResponse.length > 3000 ? aiResponse.slice(0, 3000) + "...[truncated]" : aiResponse;
|
|
35466
|
+
console.log(preview);
|
|
35467
|
+
}
|
|
35441
35468
|
const codeBlockMatch = aiResponse.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
35442
35469
|
if (codeBlockMatch) {
|
|
35443
35470
|
aiResponse = codeBlockMatch[1].trim();
|
|
35444
35471
|
}
|
|
35445
35472
|
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/)?.[0];
|
|
35446
35473
|
if (jsonMatch) {
|
|
35474
|
+
logger.debug(`Curator: Found JSON object (${jsonMatch.length} chars), parsing...`, "curator");
|
|
35447
35475
|
return this.parseCurationResponse(jsonMatch);
|
|
35476
|
+
} else {
|
|
35477
|
+
logger.debug("Curator: No JSON object found in AI response", "curator");
|
|
35448
35478
|
}
|
|
35449
|
-
} catch {
|
|
35479
|
+
} catch (error2) {
|
|
35480
|
+
logger.debug(`Curator: Parse error: ${error2.message}`, "curator");
|
|
35481
|
+
}
|
|
35450
35482
|
return { session_summary: "", memories: [] };
|
|
35451
35483
|
}
|
|
35452
35484
|
}
|
package/dist/server/index.js
CHANGED
|
@@ -42980,10 +42980,11 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
42980
42980
|
try {
|
|
42981
42981
|
const jsonMatch = responseJson.match(/\{[\s\S]*\}/)?.[0];
|
|
42982
42982
|
if (!jsonMatch) {
|
|
42983
|
+
logger.debug("parseCurationResponse: No JSON object found in response", "curator");
|
|
42983
42984
|
throw new Error("No JSON object found in response");
|
|
42984
42985
|
}
|
|
42985
42986
|
const data = JSON.parse(jsonMatch);
|
|
42986
|
-
|
|
42987
|
+
const result = {
|
|
42987
42988
|
session_summary: data.session_summary ?? "",
|
|
42988
42989
|
interaction_tone: data.interaction_tone,
|
|
42989
42990
|
project_snapshot: data.project_snapshot ? {
|
|
@@ -42998,7 +42999,10 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
42998
42999
|
} : undefined,
|
|
42999
43000
|
memories: this._parseMemories(data.memories ?? [])
|
|
43000
43001
|
};
|
|
43001
|
-
|
|
43002
|
+
logger.debug(`Curator parsed: ${result.memories.length} memories, summary: ${result.session_summary ? "yes" : "no"}, snapshot: ${result.project_snapshot ? "yes" : "no"}`, "curator");
|
|
43003
|
+
return result;
|
|
43004
|
+
} catch (error2) {
|
|
43005
|
+
logger.debug(`parseCurationResponse error: ${error2.message}`, "curator");
|
|
43002
43006
|
return {
|
|
43003
43007
|
session_summary: "",
|
|
43004
43008
|
memories: []
|
|
@@ -43102,7 +43106,6 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
43102
43106
|
options: {
|
|
43103
43107
|
systemPrompt,
|
|
43104
43108
|
permissionMode: "bypassPermissions",
|
|
43105
|
-
maxTurns: 1,
|
|
43106
43109
|
model: "claude-opus-4-5-20251101"
|
|
43107
43110
|
}
|
|
43108
43111
|
});
|
|
@@ -43114,8 +43117,14 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
43114
43117
|
}
|
|
43115
43118
|
}
|
|
43116
43119
|
if (!resultText) {
|
|
43120
|
+
logger.debug("Curator SDK: No result text returned from Agent SDK", "curator");
|
|
43117
43121
|
return { session_summary: "", memories: [] };
|
|
43118
43122
|
}
|
|
43123
|
+
logger.debug(`Curator SDK raw response (${resultText.length} chars):`, "curator");
|
|
43124
|
+
if (logger.isVerbose()) {
|
|
43125
|
+
const preview = resultText.length > 3000 ? resultText.slice(0, 3000) + "...[truncated]" : resultText;
|
|
43126
|
+
console.log(preview);
|
|
43127
|
+
}
|
|
43119
43128
|
return this.parseCurationResponse(resultText);
|
|
43120
43129
|
}
|
|
43121
43130
|
_formatConversationTranscript(messages) {
|
|
@@ -43162,7 +43171,7 @@ ${content}
|
|
|
43162
43171
|
];
|
|
43163
43172
|
const response = await client.messages.create({
|
|
43164
43173
|
model: "claude-sonnet-4-20250514",
|
|
43165
|
-
max_tokens:
|
|
43174
|
+
max_tokens: 64000,
|
|
43166
43175
|
system: systemPrompt,
|
|
43167
43176
|
messages: conversationMessages
|
|
43168
43177
|
});
|
|
@@ -43182,7 +43191,7 @@ ${content}
|
|
|
43182
43191
|
const args = [];
|
|
43183
43192
|
let command = this._config.cliCommand;
|
|
43184
43193
|
if (type === "claude-code") {
|
|
43185
|
-
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json"
|
|
43194
|
+
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json");
|
|
43186
43195
|
} else {
|
|
43187
43196
|
command = "gemini";
|
|
43188
43197
|
args.push("--resume", sessionId, "-p", `${systemPrompt}
|
|
@@ -43193,7 +43202,8 @@ ${userMessage}`, "--output-format", "json");
|
|
|
43193
43202
|
cwd: cwd2,
|
|
43194
43203
|
env: {
|
|
43195
43204
|
...process.env,
|
|
43196
|
-
MEMORY_CURATOR_ACTIVE: "1"
|
|
43205
|
+
MEMORY_CURATOR_ACTIVE: "1",
|
|
43206
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000"
|
|
43197
43207
|
},
|
|
43198
43208
|
stdout: "pipe",
|
|
43199
43209
|
stderr: "pipe"
|
|
@@ -43204,37 +43214,59 @@ ${userMessage}`, "--output-format", "json");
|
|
|
43204
43214
|
]);
|
|
43205
43215
|
const exitCode = await proc.exited;
|
|
43206
43216
|
if (exitCode !== 0) {
|
|
43217
|
+
logger.debug(`Curator CLI exited with code ${exitCode}`, "curator");
|
|
43218
|
+
if (stderr) {
|
|
43219
|
+
logger.debug(`Curator stderr: ${stderr}`, "curator");
|
|
43220
|
+
}
|
|
43207
43221
|
return { session_summary: "", memories: [] };
|
|
43208
43222
|
}
|
|
43223
|
+
logger.debug(`Curator CLI raw stdout (${stdout.length} chars):`, "curator");
|
|
43224
|
+
if (logger.isVerbose()) {
|
|
43225
|
+
const preview = stdout.length > 2000 ? stdout.slice(0, 2000) + "...[truncated]" : stdout;
|
|
43226
|
+
console.log(preview);
|
|
43227
|
+
}
|
|
43209
43228
|
try {
|
|
43210
43229
|
const cliOutput = JSON.parse(stdout);
|
|
43211
43230
|
let resultObj;
|
|
43212
43231
|
if (Array.isArray(cliOutput)) {
|
|
43213
43232
|
resultObj = cliOutput.find((item) => item.type === "result");
|
|
43214
43233
|
if (!resultObj) {
|
|
43234
|
+
logger.debug("Curator: No result object found in CLI output array", "curator");
|
|
43215
43235
|
return { session_summary: "", memories: [] };
|
|
43216
43236
|
}
|
|
43217
43237
|
} else {
|
|
43218
43238
|
resultObj = cliOutput;
|
|
43219
43239
|
}
|
|
43220
43240
|
if (resultObj.type === "error" || resultObj.is_error === true) {
|
|
43241
|
+
logger.debug(`Curator: Error response from CLI: ${JSON.stringify(resultObj).slice(0, 500)}`, "curator");
|
|
43221
43242
|
return { session_summary: "", memories: [] };
|
|
43222
43243
|
}
|
|
43223
43244
|
let aiResponse = "";
|
|
43224
43245
|
if (typeof resultObj.result === "string") {
|
|
43225
43246
|
aiResponse = resultObj.result;
|
|
43226
43247
|
} else {
|
|
43248
|
+
logger.debug(`Curator: result field is not a string: ${typeof resultObj.result}`, "curator");
|
|
43227
43249
|
return { session_summary: "", memories: [] };
|
|
43228
43250
|
}
|
|
43251
|
+
logger.debug(`Curator AI response (${aiResponse.length} chars):`, "curator");
|
|
43252
|
+
if (logger.isVerbose()) {
|
|
43253
|
+
const preview = aiResponse.length > 3000 ? aiResponse.slice(0, 3000) + "...[truncated]" : aiResponse;
|
|
43254
|
+
console.log(preview);
|
|
43255
|
+
}
|
|
43229
43256
|
const codeBlockMatch = aiResponse.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
43230
43257
|
if (codeBlockMatch) {
|
|
43231
43258
|
aiResponse = codeBlockMatch[1].trim();
|
|
43232
43259
|
}
|
|
43233
43260
|
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/)?.[0];
|
|
43234
43261
|
if (jsonMatch) {
|
|
43262
|
+
logger.debug(`Curator: Found JSON object (${jsonMatch.length} chars), parsing...`, "curator");
|
|
43235
43263
|
return this.parseCurationResponse(jsonMatch);
|
|
43264
|
+
} else {
|
|
43265
|
+
logger.debug("Curator: No JSON object found in AI response", "curator");
|
|
43236
43266
|
}
|
|
43237
|
-
} catch {
|
|
43267
|
+
} catch (error2) {
|
|
43268
|
+
logger.debug(`Curator: Parse error: ${error2.message}`, "curator");
|
|
43269
|
+
}
|
|
43238
43270
|
return { session_summary: "", memories: [] };
|
|
43239
43271
|
}
|
|
43240
43272
|
}
|
package/dist/server/index.mjs
CHANGED
|
@@ -42960,10 +42960,11 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
42960
42960
|
try {
|
|
42961
42961
|
const jsonMatch = responseJson.match(/\{[\s\S]*\}/)?.[0];
|
|
42962
42962
|
if (!jsonMatch) {
|
|
42963
|
+
logger.debug("parseCurationResponse: No JSON object found in response", "curator");
|
|
42963
42964
|
throw new Error("No JSON object found in response");
|
|
42964
42965
|
}
|
|
42965
42966
|
const data = JSON.parse(jsonMatch);
|
|
42966
|
-
|
|
42967
|
+
const result = {
|
|
42967
42968
|
session_summary: data.session_summary ?? "",
|
|
42968
42969
|
interaction_tone: data.interaction_tone,
|
|
42969
42970
|
project_snapshot: data.project_snapshot ? {
|
|
@@ -42978,7 +42979,10 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
42978
42979
|
} : undefined,
|
|
42979
42980
|
memories: this._parseMemories(data.memories ?? [])
|
|
42980
42981
|
};
|
|
42981
|
-
|
|
42982
|
+
logger.debug(`Curator parsed: ${result.memories.length} memories, summary: ${result.session_summary ? "yes" : "no"}, snapshot: ${result.project_snapshot ? "yes" : "no"}`, "curator");
|
|
42983
|
+
return result;
|
|
42984
|
+
} catch (error2) {
|
|
42985
|
+
logger.debug(`parseCurationResponse error: ${error2.message}`, "curator");
|
|
42982
42986
|
return {
|
|
42983
42987
|
session_summary: "",
|
|
42984
42988
|
memories: []
|
|
@@ -43082,7 +43086,6 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
43082
43086
|
options: {
|
|
43083
43087
|
systemPrompt,
|
|
43084
43088
|
permissionMode: "bypassPermissions",
|
|
43085
|
-
maxTurns: 1,
|
|
43086
43089
|
model: "claude-opus-4-5-20251101"
|
|
43087
43090
|
}
|
|
43088
43091
|
});
|
|
@@ -43094,8 +43097,14 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
43094
43097
|
}
|
|
43095
43098
|
}
|
|
43096
43099
|
if (!resultText) {
|
|
43100
|
+
logger.debug("Curator SDK: No result text returned from Agent SDK", "curator");
|
|
43097
43101
|
return { session_summary: "", memories: [] };
|
|
43098
43102
|
}
|
|
43103
|
+
logger.debug(`Curator SDK raw response (${resultText.length} chars):`, "curator");
|
|
43104
|
+
if (logger.isVerbose()) {
|
|
43105
|
+
const preview = resultText.length > 3000 ? resultText.slice(0, 3000) + "...[truncated]" : resultText;
|
|
43106
|
+
console.log(preview);
|
|
43107
|
+
}
|
|
43099
43108
|
return this.parseCurationResponse(resultText);
|
|
43100
43109
|
}
|
|
43101
43110
|
_formatConversationTranscript(messages) {
|
|
@@ -43142,7 +43151,7 @@ ${content}
|
|
|
43142
43151
|
];
|
|
43143
43152
|
const response = await client.messages.create({
|
|
43144
43153
|
model: "claude-sonnet-4-20250514",
|
|
43145
|
-
max_tokens:
|
|
43154
|
+
max_tokens: 64000,
|
|
43146
43155
|
system: systemPrompt,
|
|
43147
43156
|
messages: conversationMessages
|
|
43148
43157
|
});
|
|
@@ -43162,7 +43171,7 @@ ${content}
|
|
|
43162
43171
|
const args = [];
|
|
43163
43172
|
let command = this._config.cliCommand;
|
|
43164
43173
|
if (type === "claude-code") {
|
|
43165
|
-
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json"
|
|
43174
|
+
args.push("--resume", sessionId, "-p", userMessage, "--append-system-prompt", systemPrompt, "--output-format", "json");
|
|
43166
43175
|
} else {
|
|
43167
43176
|
command = "gemini";
|
|
43168
43177
|
args.push("--resume", sessionId, "-p", `${systemPrompt}
|
|
@@ -43173,7 +43182,8 @@ ${userMessage}`, "--output-format", "json");
|
|
|
43173
43182
|
cwd: cwd2,
|
|
43174
43183
|
env: {
|
|
43175
43184
|
...process.env,
|
|
43176
|
-
MEMORY_CURATOR_ACTIVE: "1"
|
|
43185
|
+
MEMORY_CURATOR_ACTIVE: "1",
|
|
43186
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000"
|
|
43177
43187
|
},
|
|
43178
43188
|
stdout: "pipe",
|
|
43179
43189
|
stderr: "pipe"
|
|
@@ -43184,37 +43194,59 @@ ${userMessage}`, "--output-format", "json");
|
|
|
43184
43194
|
]);
|
|
43185
43195
|
const exitCode = await proc.exited;
|
|
43186
43196
|
if (exitCode !== 0) {
|
|
43197
|
+
logger.debug(`Curator CLI exited with code ${exitCode}`, "curator");
|
|
43198
|
+
if (stderr) {
|
|
43199
|
+
logger.debug(`Curator stderr: ${stderr}`, "curator");
|
|
43200
|
+
}
|
|
43187
43201
|
return { session_summary: "", memories: [] };
|
|
43188
43202
|
}
|
|
43203
|
+
logger.debug(`Curator CLI raw stdout (${stdout.length} chars):`, "curator");
|
|
43204
|
+
if (logger.isVerbose()) {
|
|
43205
|
+
const preview = stdout.length > 2000 ? stdout.slice(0, 2000) + "...[truncated]" : stdout;
|
|
43206
|
+
console.log(preview);
|
|
43207
|
+
}
|
|
43189
43208
|
try {
|
|
43190
43209
|
const cliOutput = JSON.parse(stdout);
|
|
43191
43210
|
let resultObj;
|
|
43192
43211
|
if (Array.isArray(cliOutput)) {
|
|
43193
43212
|
resultObj = cliOutput.find((item) => item.type === "result");
|
|
43194
43213
|
if (!resultObj) {
|
|
43214
|
+
logger.debug("Curator: No result object found in CLI output array", "curator");
|
|
43195
43215
|
return { session_summary: "", memories: [] };
|
|
43196
43216
|
}
|
|
43197
43217
|
} else {
|
|
43198
43218
|
resultObj = cliOutput;
|
|
43199
43219
|
}
|
|
43200
43220
|
if (resultObj.type === "error" || resultObj.is_error === true) {
|
|
43221
|
+
logger.debug(`Curator: Error response from CLI: ${JSON.stringify(resultObj).slice(0, 500)}`, "curator");
|
|
43201
43222
|
return { session_summary: "", memories: [] };
|
|
43202
43223
|
}
|
|
43203
43224
|
let aiResponse = "";
|
|
43204
43225
|
if (typeof resultObj.result === "string") {
|
|
43205
43226
|
aiResponse = resultObj.result;
|
|
43206
43227
|
} else {
|
|
43228
|
+
logger.debug(`Curator: result field is not a string: ${typeof resultObj.result}`, "curator");
|
|
43207
43229
|
return { session_summary: "", memories: [] };
|
|
43208
43230
|
}
|
|
43231
|
+
logger.debug(`Curator AI response (${aiResponse.length} chars):`, "curator");
|
|
43232
|
+
if (logger.isVerbose()) {
|
|
43233
|
+
const preview = aiResponse.length > 3000 ? aiResponse.slice(0, 3000) + "...[truncated]" : aiResponse;
|
|
43234
|
+
console.log(preview);
|
|
43235
|
+
}
|
|
43209
43236
|
const codeBlockMatch = aiResponse.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
43210
43237
|
if (codeBlockMatch) {
|
|
43211
43238
|
aiResponse = codeBlockMatch[1].trim();
|
|
43212
43239
|
}
|
|
43213
43240
|
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/)?.[0];
|
|
43214
43241
|
if (jsonMatch) {
|
|
43242
|
+
logger.debug(`Curator: Found JSON object (${jsonMatch.length} chars), parsing...`, "curator");
|
|
43215
43243
|
return this.parseCurationResponse(jsonMatch);
|
|
43244
|
+
} else {
|
|
43245
|
+
logger.debug("Curator: No JSON object found in AI response", "curator");
|
|
43216
43246
|
}
|
|
43217
|
-
} catch {
|
|
43247
|
+
} catch (error2) {
|
|
43248
|
+
logger.debug(`Curator: Parse error: ${error2.message}`, "curator");
|
|
43249
|
+
}
|
|
43218
43250
|
return { session_summary: "", memories: [] };
|
|
43219
43251
|
}
|
|
43220
43252
|
}
|
package/hooks/claude/curation.ts
CHANGED
|
@@ -38,9 +38,13 @@ async function main() {
|
|
|
38
38
|
|
|
39
39
|
const sessionId = input.session_id || 'unknown'
|
|
40
40
|
const cwd = process.env.CLAUDE_PROJECT_DIR || input.cwd || process.cwd()
|
|
41
|
-
const trigger = input.trigger || 'pre_compact'
|
|
42
41
|
const hookEvent = input.hook_event_name || 'PreCompact'
|
|
43
42
|
|
|
43
|
+
// Determine trigger type from hook event name (more reliable than input.trigger)
|
|
44
|
+
// PreCompact = context is being compacted, session still active
|
|
45
|
+
// SessionEnd/Stop = session is ending
|
|
46
|
+
const trigger = hookEvent === 'PreCompact' ? 'pre_compact' : 'session_end'
|
|
47
|
+
|
|
44
48
|
const projectId = getProjectId(cwd)
|
|
45
49
|
|
|
46
50
|
console.error(info(`🧠 Curating memories (${hookEvent})...`))
|
|
@@ -54,7 +58,7 @@ async function main() {
|
|
|
54
58
|
session_id: sessionId,
|
|
55
59
|
project_id: projectId,
|
|
56
60
|
claude_session_id: sessionId,
|
|
57
|
-
trigger
|
|
61
|
+
trigger,
|
|
58
62
|
cwd,
|
|
59
63
|
}),
|
|
60
64
|
signal: AbortSignal.timeout(5000),
|
package/package.json
CHANGED
package/src/core/curator.ts
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
import { homedir } from 'os'
|
|
7
7
|
import { join } from 'path'
|
|
8
8
|
import { existsSync } from 'fs'
|
|
9
|
+
import { readdir } from 'fs/promises'
|
|
9
10
|
import type { CuratedMemory, CurationResult, CurationTrigger, ContextType } from '../types/memory.ts'
|
|
10
11
|
import { logger } from '../utils/logger.ts'
|
|
12
|
+
import { parseSessionFile, type ParsedMessage } from './session-parser.ts'
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Get the correct Claude CLI command path
|
|
@@ -401,8 +403,23 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
401
403
|
throw new Error('No JSON object found in response')
|
|
402
404
|
}
|
|
403
405
|
|
|
406
|
+
// Log JSON structure for debugging
|
|
407
|
+
logger.debug(`parseCurationResponse: Attempting to parse ${jsonMatch.length} chars`, 'curator')
|
|
408
|
+
|
|
404
409
|
// Simple parse - match Python's approach
|
|
405
|
-
|
|
410
|
+
let data: any
|
|
411
|
+
try {
|
|
412
|
+
data = JSON.parse(jsonMatch)
|
|
413
|
+
} catch (parseErr: any) {
|
|
414
|
+
// Log more details about where parse failed
|
|
415
|
+
logger.debug(`parseCurationResponse: JSON.parse failed: ${parseErr.message}`, 'curator')
|
|
416
|
+
logger.debug(`parseCurationResponse: Last 100 chars: '${jsonMatch.slice(-100)}'`, 'curator')
|
|
417
|
+
// Try to find where the JSON breaks
|
|
418
|
+
const openBraces = (jsonMatch.match(/\{/g) || []).length
|
|
419
|
+
const closeBraces = (jsonMatch.match(/\}/g) || []).length
|
|
420
|
+
logger.debug(`parseCurationResponse: Brace count - open: ${openBraces}, close: ${closeBraces}`, 'curator')
|
|
421
|
+
throw parseErr
|
|
422
|
+
}
|
|
406
423
|
|
|
407
424
|
const result: CurationResult = {
|
|
408
425
|
session_summary: data.session_summary ?? '',
|
|
@@ -640,7 +657,7 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
640
657
|
|
|
641
658
|
const response = await client.messages.create({
|
|
642
659
|
model: 'claude-sonnet-4-20250514',
|
|
643
|
-
max_tokens:
|
|
660
|
+
max_tokens: 64000,
|
|
644
661
|
system: systemPrompt,
|
|
645
662
|
messages: conversationMessages,
|
|
646
663
|
})
|
|
@@ -664,6 +681,75 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
664
681
|
return this.curateWithSDK(segment.messages, triggerType)
|
|
665
682
|
}
|
|
666
683
|
|
|
684
|
+
/**
|
|
685
|
+
* Find and curate from a session file directly
|
|
686
|
+
* Uses SDK mode to avoid CLI output truncation issues
|
|
687
|
+
*/
|
|
688
|
+
async curateFromSessionFile(
|
|
689
|
+
sessionId: string,
|
|
690
|
+
triggerType: CurationTrigger = 'session_end',
|
|
691
|
+
cwd?: string
|
|
692
|
+
): Promise<CurationResult> {
|
|
693
|
+
// Find the session file
|
|
694
|
+
const sessionFile = await this._findSessionFile(sessionId, cwd)
|
|
695
|
+
if (!sessionFile) {
|
|
696
|
+
logger.debug(`Curator: Could not find session file for ${sessionId}`, 'curator')
|
|
697
|
+
return { session_summary: '', memories: [] }
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
logger.debug(`Curator: Found session file: ${sessionFile}`, 'curator')
|
|
701
|
+
|
|
702
|
+
// Parse the session
|
|
703
|
+
const session = await parseSessionFile(sessionFile)
|
|
704
|
+
if (session.messages.length === 0) {
|
|
705
|
+
logger.debug('Curator: Session has no messages', 'curator')
|
|
706
|
+
return { session_summary: '', memories: [] }
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
logger.debug(`Curator: Parsed ${session.messages.length} messages, ~${session.metadata.estimatedTokens} tokens`, 'curator')
|
|
710
|
+
|
|
711
|
+
// Use SDK mode with the parsed messages
|
|
712
|
+
return this.curateWithSDK(session.messages as any, triggerType)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Find the session file path given a session ID
|
|
717
|
+
*/
|
|
718
|
+
private async _findSessionFile(sessionId: string, cwd?: string): Promise<string | null> {
|
|
719
|
+
const projectsDir = join(homedir(), '.claude', 'projects')
|
|
720
|
+
|
|
721
|
+
// If we have cwd, try to derive the project folder name
|
|
722
|
+
if (cwd) {
|
|
723
|
+
// Convert cwd to Claude's folder naming: /home/user/project -> -home-user-project
|
|
724
|
+
const projectFolder = cwd.replace(/\//g, '-').replace(/^-/, '-')
|
|
725
|
+
const sessionPath = join(projectsDir, projectFolder, `${sessionId}.jsonl`)
|
|
726
|
+
if (existsSync(sessionPath)) {
|
|
727
|
+
return sessionPath
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// Also try the exact folder name (cwd might already be encoded)
|
|
731
|
+
const altPath = join(projectsDir, cwd.split('/').pop() || '', `${sessionId}.jsonl`)
|
|
732
|
+
if (existsSync(altPath)) {
|
|
733
|
+
return altPath
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Search all project folders for the session ID
|
|
738
|
+
try {
|
|
739
|
+
const projectFolders = await readdir(projectsDir)
|
|
740
|
+
for (const folder of projectFolders) {
|
|
741
|
+
const sessionPath = join(projectsDir, folder, `${sessionId}.jsonl`)
|
|
742
|
+
if (existsSync(sessionPath)) {
|
|
743
|
+
return sessionPath
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
} catch {
|
|
747
|
+
// Projects dir doesn't exist
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
return null
|
|
751
|
+
}
|
|
752
|
+
|
|
667
753
|
/**
|
|
668
754
|
* Curate using CLI subprocess (for hook mode)
|
|
669
755
|
* Resumes a session and asks it to curate
|
|
@@ -700,11 +786,15 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
700
786
|
}
|
|
701
787
|
|
|
702
788
|
// Execute CLI
|
|
789
|
+
logger.debug(`Curator: Spawning CLI with CLAUDE_CODE_MAX_OUTPUT_TOKENS=64000`, 'curator')
|
|
790
|
+
logger.debug(`Curator: Command: ${command} ${args.slice(0, 3).join(' ')}...`, 'curator')
|
|
791
|
+
|
|
703
792
|
const proc = Bun.spawn([command, ...args], {
|
|
704
793
|
cwd,
|
|
705
794
|
env: {
|
|
706
795
|
...process.env,
|
|
707
796
|
MEMORY_CURATOR_ACTIVE: '1', // Prevent recursive hook triggering
|
|
797
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: '64000', // Max output to avoid truncation
|
|
708
798
|
},
|
|
709
799
|
stdout: 'pipe',
|
|
710
800
|
stderr: 'pipe',
|
|
@@ -717,16 +807,19 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
717
807
|
])
|
|
718
808
|
const exitCode = await proc.exited
|
|
719
809
|
|
|
810
|
+
logger.debug(`Curator CLI exit code: ${exitCode}`, 'curator')
|
|
811
|
+
if (stderr && stderr.trim()) {
|
|
812
|
+
logger.debug(`Curator stderr (${stderr.length} chars): ${stderr.slice(0, 500)}`, 'curator')
|
|
813
|
+
}
|
|
814
|
+
|
|
720
815
|
if (exitCode !== 0) {
|
|
721
|
-
logger.debug(`Curator CLI exited with code ${exitCode}`, 'curator')
|
|
722
|
-
if (stderr) {
|
|
723
|
-
logger.debug(`Curator stderr: ${stderr}`, 'curator')
|
|
724
|
-
}
|
|
725
816
|
return { session_summary: '', memories: [] }
|
|
726
817
|
}
|
|
727
818
|
|
|
728
819
|
// Log raw response in verbose mode
|
|
729
820
|
logger.debug(`Curator CLI raw stdout (${stdout.length} chars):`, 'curator')
|
|
821
|
+
// Always log the last 100 chars to see where output ends
|
|
822
|
+
logger.debug(`Curator: stdout ends with: '${stdout.slice(-100)}'`, 'curator')
|
|
730
823
|
if (logger.isVerbose()) {
|
|
731
824
|
// Show first 2000 chars to avoid flooding console
|
|
732
825
|
const preview = stdout.length > 2000 ? stdout.slice(0, 2000) + '...[truncated]' : stdout
|
|
@@ -777,14 +870,43 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
777
870
|
// Remove markdown code blocks if present (```json ... ```)
|
|
778
871
|
const codeBlockMatch = aiResponse.match(/```(?:json)?\s*([\s\S]*?)```/)
|
|
779
872
|
if (codeBlockMatch) {
|
|
873
|
+
logger.debug(`Curator: Code block matched, extracting ${codeBlockMatch[1]!.length} chars`, 'curator')
|
|
780
874
|
aiResponse = codeBlockMatch[1]!.trim()
|
|
875
|
+
} else {
|
|
876
|
+
logger.debug(`Curator: No code block found, using raw response`, 'curator')
|
|
877
|
+
// Log the last 200 chars to see where truncation happened
|
|
878
|
+
if (aiResponse.length > 200) {
|
|
879
|
+
logger.debug(`Curator: Last 200 chars of response: ${aiResponse.slice(-200)}`, 'curator')
|
|
880
|
+
}
|
|
781
881
|
}
|
|
782
882
|
|
|
783
883
|
// Now find the JSON object (same regex as Python)
|
|
784
884
|
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/)?.[0]
|
|
785
885
|
if (jsonMatch) {
|
|
786
886
|
logger.debug(`Curator: Found JSON object (${jsonMatch.length} chars), parsing...`, 'curator')
|
|
787
|
-
|
|
887
|
+
|
|
888
|
+
// Detect likely truncation: JSON much smaller than response
|
|
889
|
+
const likelyTruncated = jsonMatch.length < aiResponse.length * 0.5
|
|
890
|
+
|
|
891
|
+
if (likelyTruncated) {
|
|
892
|
+
logger.debug(`Curator: WARNING - JSON (${jsonMatch.length}) much smaller than response (${aiResponse.length}) - likely truncated`, 'curator')
|
|
893
|
+
// Find the last } position and log what's around it
|
|
894
|
+
const lastBrace = aiResponse.lastIndexOf('}')
|
|
895
|
+
logger.debug(`Curator: Last } at position ${lastBrace}, char before: '${aiResponse[lastBrace-1]}', char after: '${aiResponse[lastBrace+1] || 'EOF'}'`, 'curator')
|
|
896
|
+
// Log chars around the cut point
|
|
897
|
+
const cutPoint = jsonMatch.length
|
|
898
|
+
logger.debug(`Curator: Around match end (${cutPoint}): '...${aiResponse.slice(Math.max(0, cutPoint-50), cutPoint+50)}...'`, 'curator')
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
const result = this.parseCurationResponse(jsonMatch)
|
|
902
|
+
|
|
903
|
+
// If we got 0 memories and likely truncated, try SDK fallback
|
|
904
|
+
if (result.memories.length === 0 && likelyTruncated) {
|
|
905
|
+
logger.debug('Curator: CLI mode returned 0 memories with truncation detected, trying SDK fallback...', 'curator')
|
|
906
|
+
return this._fallbackToSDK(sessionId, triggerType, cwd)
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
return result
|
|
788
910
|
} else {
|
|
789
911
|
logger.debug('Curator: No JSON object found in AI response', 'curator')
|
|
790
912
|
}
|
|
@@ -793,7 +915,31 @@ This session has ended. Please curate the memories from this conversation accord
|
|
|
793
915
|
logger.debug(`Curator: Parse error: ${error.message}`, 'curator')
|
|
794
916
|
}
|
|
795
917
|
|
|
796
|
-
|
|
918
|
+
// CLI mode failed - try SDK fallback
|
|
919
|
+
logger.debug('Curator: CLI mode failed, trying SDK fallback...', 'curator')
|
|
920
|
+
return this._fallbackToSDK(sessionId, triggerType, cwd)
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Fallback to SDK mode when CLI mode fails (e.g., output truncation)
|
|
925
|
+
*/
|
|
926
|
+
private async _fallbackToSDK(
|
|
927
|
+
sessionId: string,
|
|
928
|
+
triggerType: CurationTrigger,
|
|
929
|
+
cwd?: string
|
|
930
|
+
): Promise<CurationResult> {
|
|
931
|
+
try {
|
|
932
|
+
const result = await this.curateFromSessionFile(sessionId, triggerType, cwd)
|
|
933
|
+
if (result.memories.length > 0) {
|
|
934
|
+
logger.debug(`Curator: SDK fallback succeeded with ${result.memories.length} memories`, 'curator')
|
|
935
|
+
} else {
|
|
936
|
+
logger.debug('Curator: SDK fallback also returned 0 memories', 'curator')
|
|
937
|
+
}
|
|
938
|
+
return result
|
|
939
|
+
} catch (error: any) {
|
|
940
|
+
logger.debug(`Curator: SDK fallback failed: ${error.message}`, 'curator')
|
|
941
|
+
return { session_summary: '', memories: [] }
|
|
942
|
+
}
|
|
797
943
|
}
|
|
798
944
|
}
|
|
799
945
|
|