poe-code 3.0.311 → 3.0.313
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/memory-mcp.js +8 -1
- package/dist/cli/commands/memory-mcp.js.map +1 -1
- package/dist/cli/commands/memory.js +42 -12
- package/dist/cli/commands/memory.js.map +1 -1
- package/dist/index.js +235 -101
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/markdown-reader/dist/core/document.js +6 -0
- package/packages/markdown-reader/dist/core/read-section.js +4 -0
- package/packages/markdown-reader/dist/core/resolve.js +6 -3
- package/packages/markdown-reader/dist/core/scan.js +28 -1
- package/packages/markdown-reader/dist/mcp/tools.js +11 -4
- package/packages/memory/dist/agent-response.d.ts +2 -0
- package/packages/memory/dist/agent-response.js +38 -0
- package/packages/memory/dist/cache.js +13 -9
- package/packages/memory/dist/explain.js +2 -25
- package/packages/memory/dist/frontmatter.js +5 -1
- package/packages/memory/dist/index.js +92 -55
- package/packages/memory/dist/index.js.map +4 -4
- package/packages/memory/dist/install.js +12 -4
- package/packages/memory/dist/paths.js +15 -0
- package/packages/memory/dist/query.js +2 -25
- package/packages/memory/dist/search.js +2 -2
- package/packages/memory/dist/write.js +14 -1
package/dist/index.js
CHANGED
|
@@ -3473,21 +3473,21 @@ function sliceOffsetMap(offsets, start, end) {
|
|
|
3473
3473
|
}
|
|
3474
3474
|
function createOffsetMap(input, absoluteStart = 0) {
|
|
3475
3475
|
const offsets = new Array(input.length + 1).fill(absoluteStart);
|
|
3476
|
-
let
|
|
3476
|
+
let byteOffset2 = absoluteStart;
|
|
3477
3477
|
let index = 0;
|
|
3478
3478
|
while (index < input.length) {
|
|
3479
|
-
offsets[index] =
|
|
3479
|
+
offsets[index] = byteOffset2;
|
|
3480
3480
|
const codePoint = input.codePointAt(index) ?? 0;
|
|
3481
3481
|
const codeUnitLength = codePoint > 65535 ? 2 : 1;
|
|
3482
3482
|
const byteLength = codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
|
|
3483
3483
|
for (let offsetIndex = 1; offsetIndex < codeUnitLength; offsetIndex += 1) {
|
|
3484
|
-
offsets[index + offsetIndex] =
|
|
3484
|
+
offsets[index + offsetIndex] = byteOffset2;
|
|
3485
3485
|
}
|
|
3486
|
-
|
|
3486
|
+
byteOffset2 += byteLength;
|
|
3487
3487
|
index += codeUnitLength;
|
|
3488
|
-
offsets[index] =
|
|
3488
|
+
offsets[index] = byteOffset2;
|
|
3489
3489
|
}
|
|
3490
|
-
offsets[input.length] =
|
|
3490
|
+
offsets[input.length] = byteOffset2;
|
|
3491
3491
|
return offsets;
|
|
3492
3492
|
}
|
|
3493
3493
|
var INLINE_HTML_TAGS;
|
|
@@ -4102,21 +4102,21 @@ function getTextNodeSourceOffsets(node) {
|
|
|
4102
4102
|
}
|
|
4103
4103
|
function createOffsetMap2(input, absoluteStart = 0, absoluteEnd) {
|
|
4104
4104
|
const offsets = new Array(input.length + 1).fill(absoluteStart);
|
|
4105
|
-
let
|
|
4105
|
+
let byteOffset2 = absoluteStart;
|
|
4106
4106
|
let index = 0;
|
|
4107
4107
|
while (index < input.length) {
|
|
4108
|
-
offsets[index] =
|
|
4108
|
+
offsets[index] = byteOffset2;
|
|
4109
4109
|
const codePoint = input.codePointAt(index) ?? 0;
|
|
4110
4110
|
const codeUnitLength = codePoint > 65535 ? 2 : 1;
|
|
4111
4111
|
const byteLength = codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
|
|
4112
4112
|
for (let offsetIndex = 1; offsetIndex < codeUnitLength; offsetIndex += 1) {
|
|
4113
|
-
offsets[index + offsetIndex] =
|
|
4113
|
+
offsets[index + offsetIndex] = byteOffset2;
|
|
4114
4114
|
}
|
|
4115
|
-
|
|
4115
|
+
byteOffset2 += byteLength;
|
|
4116
4116
|
index += codeUnitLength;
|
|
4117
|
-
offsets[index] =
|
|
4117
|
+
offsets[index] = byteOffset2;
|
|
4118
4118
|
}
|
|
4119
|
-
offsets[input.length] = absoluteEnd ??
|
|
4119
|
+
offsets[input.length] = absoluteEnd ?? byteOffset2;
|
|
4120
4120
|
return offsets;
|
|
4121
4121
|
}
|
|
4122
4122
|
function createMappedText(value, offsets) {
|
|
@@ -16932,6 +16932,9 @@ async function configuredTimeout(options) {
|
|
|
16932
16932
|
async function cacheEnabled(options) {
|
|
16933
16933
|
return (await resolveMemoryConfig(options)).cacheEnabled;
|
|
16934
16934
|
}
|
|
16935
|
+
async function mcpWritesAllowed(options) {
|
|
16936
|
+
return (await resolveMemoryConfig(options)).mcpWritesAllowed;
|
|
16937
|
+
}
|
|
16935
16938
|
async function defaultQueryBudget(options) {
|
|
16936
16939
|
return (await resolveMemoryConfig(options)).defaultQueryBudget;
|
|
16937
16940
|
}
|
|
@@ -21298,9 +21301,9 @@ function createContainerJob(containerId, runner, engine, context, detachedJobCon
|
|
|
21298
21301
|
const sinceCondition = opts?.since === void 0 ? "" : ` && test $(stat -c %Y ${logFile} 2>/dev/null || stat -f %m ${logFile}) -ge ${Math.ceil(
|
|
21299
21302
|
opts.since.getTime() / 1e3
|
|
21300
21303
|
)}`;
|
|
21301
|
-
let
|
|
21304
|
+
let byteOffset2 = opts?.sinceByte ?? 0;
|
|
21302
21305
|
let pendingBytes = Buffer.alloc(0);
|
|
21303
|
-
let pendingByteOffset =
|
|
21306
|
+
let pendingByteOffset = byteOffset2;
|
|
21304
21307
|
while (true) {
|
|
21305
21308
|
const stdout = await runAndReadBytes(runner, {
|
|
21306
21309
|
command: engine,
|
|
@@ -21310,7 +21313,7 @@ function createContainerJob(containerId, runner, engine, context, detachedJobCon
|
|
|
21310
21313
|
containerId,
|
|
21311
21314
|
"sh",
|
|
21312
21315
|
"-c",
|
|
21313
|
-
`test -f ${logFile}${sinceCondition} && tail -c +${
|
|
21316
|
+
`test -f ${logFile}${sinceCondition} && tail -c +${byteOffset2 + 1} ${logFile} || true`
|
|
21314
21317
|
],
|
|
21315
21318
|
stdout: "pipe",
|
|
21316
21319
|
stderr: "pipe"
|
|
@@ -21318,7 +21321,7 @@ function createContainerJob(containerId, runner, engine, context, detachedJobCon
|
|
|
21318
21321
|
if (stdout.byteLength > 0) {
|
|
21319
21322
|
const combined = pendingBytes.byteLength === 0 ? stdout : Buffer.concat([pendingBytes, stdout]);
|
|
21320
21323
|
const completeLength = completeUtf8PrefixLength(combined);
|
|
21321
|
-
|
|
21324
|
+
byteOffset2 += stdout.byteLength;
|
|
21322
21325
|
pendingBytes = combined.subarray(completeLength);
|
|
21323
21326
|
const data = combined.subarray(0, completeLength).toString("utf8");
|
|
21324
21327
|
if (data.length > 0) {
|
|
@@ -26084,19 +26087,19 @@ async function* streamLogFile(env, jobId, opts) {
|
|
|
26084
26087
|
assertSafeJobId2(jobId);
|
|
26085
26088
|
const fs28 = env.fs ?? nodeFs3;
|
|
26086
26089
|
const file = jobLogPath(jobId);
|
|
26087
|
-
let
|
|
26090
|
+
let byteOffset2 = opts.sinceByte ?? (opts.since === void 0 ? 0 : await readCurrentByteLength(fs28, file));
|
|
26088
26091
|
let pendingBytes = Buffer.alloc(0);
|
|
26089
|
-
let pendingByteOffset =
|
|
26092
|
+
let pendingByteOffset = byteOffset2;
|
|
26090
26093
|
while (true) {
|
|
26091
26094
|
if (opts.since !== void 0 && !await wasModifiedSince(fs28, file, opts.since)) {
|
|
26092
26095
|
await waitForLogChange(fs28, file);
|
|
26093
26096
|
continue;
|
|
26094
26097
|
}
|
|
26095
|
-
const result = await readLogChunk(fs28, file,
|
|
26098
|
+
const result = await readLogChunk(fs28, file, byteOffset2);
|
|
26096
26099
|
if (result !== null) {
|
|
26097
26100
|
const combined = pendingBytes.length === 0 ? result.bytes : Buffer.concat([pendingBytes, result.bytes]);
|
|
26098
26101
|
const completeLength = completeUtf8PrefixLength2(combined);
|
|
26099
|
-
|
|
26102
|
+
byteOffset2 = result.nextByteOffset;
|
|
26100
26103
|
pendingBytes = combined.subarray(completeLength);
|
|
26101
26104
|
const data = combined.subarray(0, completeLength).toString("utf8");
|
|
26102
26105
|
if (data.length > 0) {
|
|
@@ -26163,13 +26166,13 @@ function assertSafeJobId2(jobId) {
|
|
|
26163
26166
|
throw new Error(`Invalid job id "${jobId}". Job ids must be single filename components.`);
|
|
26164
26167
|
}
|
|
26165
26168
|
}
|
|
26166
|
-
async function readLogChunk(fs28, file,
|
|
26169
|
+
async function readLogChunk(fs28, file, byteOffset2) {
|
|
26167
26170
|
const contents = await readFileIfExists3(fs28, file);
|
|
26168
|
-
if (contents === null ||
|
|
26171
|
+
if (contents === null || byteOffset2 >= contents.byteLength) {
|
|
26169
26172
|
return null;
|
|
26170
26173
|
}
|
|
26171
26174
|
return {
|
|
26172
|
-
bytes: contents.subarray(
|
|
26175
|
+
bytes: contents.subarray(byteOffset2),
|
|
26173
26176
|
nextByteOffset: contents.byteLength
|
|
26174
26177
|
};
|
|
26175
26178
|
}
|
|
@@ -70934,7 +70937,8 @@ function scanMarkdown(source) {
|
|
|
70934
70937
|
if (ast.type !== "root") {
|
|
70935
70938
|
return [];
|
|
70936
70939
|
}
|
|
70937
|
-
const
|
|
70940
|
+
const htmlCommentRanges = collectHtmlCommentRanges(source);
|
|
70941
|
+
const headings = ast.children.filter(isHeadingNode).filter((heading) => !isInsideHtmlComment(getRequiredRange(heading).start, htmlCommentRanges));
|
|
70938
70942
|
if (headings.length === 0) {
|
|
70939
70943
|
return [];
|
|
70940
70944
|
}
|
|
@@ -70955,6 +70959,30 @@ function scanMarkdown(source) {
|
|
|
70955
70959
|
applyNumbers(sections, baselineDepth);
|
|
70956
70960
|
return sections;
|
|
70957
70961
|
}
|
|
70962
|
+
function collectHtmlCommentRanges(source) {
|
|
70963
|
+
const ranges = [];
|
|
70964
|
+
let searchStart = 0;
|
|
70965
|
+
while (searchStart < source.length) {
|
|
70966
|
+
const commentStart = source.indexOf("<!--", searchStart);
|
|
70967
|
+
if (commentStart === -1) {
|
|
70968
|
+
return ranges;
|
|
70969
|
+
}
|
|
70970
|
+
const commentEndMarker = source.indexOf("-->", commentStart + "<!--".length);
|
|
70971
|
+
const commentEnd = commentEndMarker === -1 ? source.length : commentEndMarker + "-->".length;
|
|
70972
|
+
ranges.push({
|
|
70973
|
+
start: byteOffset(source, commentStart),
|
|
70974
|
+
end: byteOffset(source, commentEnd)
|
|
70975
|
+
});
|
|
70976
|
+
searchStart = commentEnd;
|
|
70977
|
+
}
|
|
70978
|
+
return ranges;
|
|
70979
|
+
}
|
|
70980
|
+
function isInsideHtmlComment(offset, ranges) {
|
|
70981
|
+
return ranges.some((range) => offset >= range.start && offset < range.end);
|
|
70982
|
+
}
|
|
70983
|
+
function byteOffset(source, index) {
|
|
70984
|
+
return Buffer.byteLength(source.slice(0, index), "utf8");
|
|
70985
|
+
}
|
|
70958
70986
|
function isHeadingNode(node) {
|
|
70959
70987
|
return node.type === "heading";
|
|
70960
70988
|
}
|
|
@@ -71050,6 +71078,9 @@ async function loadMarkdownDocument(file, dependencies = {}) {
|
|
|
71050
71078
|
};
|
|
71051
71079
|
}
|
|
71052
71080
|
function resolveMarkdownPath(file, cwd = process.cwd()) {
|
|
71081
|
+
if (file.trim().length === 0) {
|
|
71082
|
+
throw new UserError("invalid file: expected a non-empty path");
|
|
71083
|
+
}
|
|
71053
71084
|
return path92.isAbsolute(file) ? file : path92.resolve(cwd, file);
|
|
71054
71085
|
}
|
|
71055
71086
|
function sliceMarkdownBytes(source, start, end) {
|
|
@@ -71085,6 +71116,9 @@ function hasYamlLikeLeadingFrontmatter(source) {
|
|
|
71085
71116
|
if (lines[0] !== "---") {
|
|
71086
71117
|
return false;
|
|
71087
71118
|
}
|
|
71119
|
+
if (lines[1]?.trim().length === 0) {
|
|
71120
|
+
return false;
|
|
71121
|
+
}
|
|
71088
71122
|
for (const line of lines.slice(1)) {
|
|
71089
71123
|
const trimmed = line.trim();
|
|
71090
71124
|
if (trimmed.length === 0) {
|
|
@@ -71150,16 +71184,19 @@ var init_read_markdown = __esm({
|
|
|
71150
71184
|
// packages/markdown-reader/src/core/resolve.ts
|
|
71151
71185
|
function resolveSection(sections, id) {
|
|
71152
71186
|
const trimmedId = id.trim();
|
|
71187
|
+
if (trimmedId.length === 0) {
|
|
71188
|
+
throw new UserError("invalid section: expected a non-empty section id");
|
|
71189
|
+
}
|
|
71190
|
+
const sectionByNumber = sections.find((section) => section.number === trimmedId);
|
|
71191
|
+
if (sectionByNumber !== void 0) {
|
|
71192
|
+
return sectionByNumber;
|
|
71193
|
+
}
|
|
71153
71194
|
const unnumberedTitleMatch = sections.find(
|
|
71154
71195
|
(section) => section.number === null && section.title === trimmedId
|
|
71155
71196
|
);
|
|
71156
71197
|
if (unnumberedTitleMatch !== void 0) {
|
|
71157
71198
|
return unnumberedTitleMatch;
|
|
71158
71199
|
}
|
|
71159
|
-
const sectionByNumber = sections.find((section) => section.number === trimmedId);
|
|
71160
|
-
if (sectionByNumber !== void 0) {
|
|
71161
|
-
return sectionByNumber;
|
|
71162
|
-
}
|
|
71163
71200
|
const titleMatches = sections.filter((section) => section.title === trimmedId);
|
|
71164
71201
|
if (titleMatches.length === 1) {
|
|
71165
71202
|
return titleMatches[0];
|
|
@@ -71181,6 +71218,9 @@ var init_resolve5 = __esm({
|
|
|
71181
71218
|
// packages/markdown-reader/src/core/read-section.ts
|
|
71182
71219
|
function createReadSection(dependencies = {}) {
|
|
71183
71220
|
return async function readSection2(params) {
|
|
71221
|
+
if (params.section.trim().length === 0) {
|
|
71222
|
+
throw new UserError("invalid section: expected a non-empty section id");
|
|
71223
|
+
}
|
|
71184
71224
|
const { source, sections } = await loadMarkdownDocument(params.file, dependencies);
|
|
71185
71225
|
const section = resolveSection(sections, params.section);
|
|
71186
71226
|
const end = params.includeChildren === false ? section.bodyEndNoChildren : section.bodyEnd;
|
|
@@ -71201,6 +71241,7 @@ var init_read_section = __esm({
|
|
|
71201
71241
|
"use strict";
|
|
71202
71242
|
init_document();
|
|
71203
71243
|
init_resolve5();
|
|
71244
|
+
init_src21();
|
|
71204
71245
|
readSection = createReadSection();
|
|
71205
71246
|
}
|
|
71206
71247
|
});
|
|
@@ -71215,8 +71256,14 @@ var init_tools2 = __esm({
|
|
|
71215
71256
|
init_read_markdown();
|
|
71216
71257
|
init_read_section();
|
|
71217
71258
|
readParams = S.Object({
|
|
71218
|
-
file: S.String({ description: "Path to the markdown file" }),
|
|
71219
|
-
depth: S.Optional(
|
|
71259
|
+
file: S.String({ description: "Path to the markdown file", minLength: 1 }),
|
|
71260
|
+
depth: S.Optional(
|
|
71261
|
+
S.Number({
|
|
71262
|
+
description: "Limit TOC to headings at depth <= n",
|
|
71263
|
+
jsonType: "integer",
|
|
71264
|
+
minimum: 0
|
|
71265
|
+
})
|
|
71266
|
+
)
|
|
71220
71267
|
});
|
|
71221
71268
|
tocEntryResult = S.Object({
|
|
71222
71269
|
depth: S.Number(),
|
|
@@ -71236,8 +71283,11 @@ var init_tools2 = __esm({
|
|
|
71236
71283
|
handler: async ({ params }) => readMarkdown(params)
|
|
71237
71284
|
});
|
|
71238
71285
|
readSectionParams = S.Object({
|
|
71239
|
-
file: S.String({ description: "Path to the markdown file" }),
|
|
71240
|
-
section: S.String({
|
|
71286
|
+
file: S.String({ description: "Path to the markdown file", minLength: 1 }),
|
|
71287
|
+
section: S.String({
|
|
71288
|
+
description: "Numeric path or exact heading text to read",
|
|
71289
|
+
minLength: 1
|
|
71290
|
+
}),
|
|
71241
71291
|
includeChildren: S.Optional(S.Boolean({ description: "Include nested child sections" }))
|
|
71242
71292
|
});
|
|
71243
71293
|
readSectionTool = defineCommand({
|
|
@@ -100415,6 +100465,9 @@ async function assertMemoryRootIsNotSymlink(root) {
|
|
|
100415
100465
|
try {
|
|
100416
100466
|
const stat33 = await fs12.lstat(currentPath);
|
|
100417
100467
|
if (stat33.isSymbolicLink()) {
|
|
100468
|
+
if (await isAllowedMacSystemAlias(currentPath)) {
|
|
100469
|
+
continue;
|
|
100470
|
+
}
|
|
100418
100471
|
throw new MemoryPathError(`Memory root "${root}" cannot be a symbolic link.`);
|
|
100419
100472
|
}
|
|
100420
100473
|
} catch (error3) {
|
|
@@ -100425,6 +100478,17 @@ async function assertMemoryRootIsNotSymlink(root) {
|
|
|
100425
100478
|
}
|
|
100426
100479
|
}
|
|
100427
100480
|
}
|
|
100481
|
+
async function isAllowedMacSystemAlias(currentPath) {
|
|
100482
|
+
if (currentPath !== "/var") {
|
|
100483
|
+
return false;
|
|
100484
|
+
}
|
|
100485
|
+
try {
|
|
100486
|
+
const target = await fs12.readlink(currentPath);
|
|
100487
|
+
return target === "/private/var" || target === "private/var";
|
|
100488
|
+
} catch {
|
|
100489
|
+
return false;
|
|
100490
|
+
}
|
|
100491
|
+
}
|
|
100428
100492
|
function isMissing(error3) {
|
|
100429
100493
|
return hasOwnErrorCode27(error3, "ENOENT");
|
|
100430
100494
|
}
|
|
@@ -100574,7 +100638,11 @@ function serializeFrontmatter(frontmatter, body) {
|
|
|
100574
100638
|
return stringifyFrontmatter(serialized, body);
|
|
100575
100639
|
}
|
|
100576
100640
|
function parseSourceRef(serialized) {
|
|
100577
|
-
const
|
|
100641
|
+
const parts = serialized.split("#");
|
|
100642
|
+
if (parts.length > 2) {
|
|
100643
|
+
throw new Error(`Invalid source ref "${serialized}".`);
|
|
100644
|
+
}
|
|
100645
|
+
const [rawPath, rawAnchor] = parts;
|
|
100578
100646
|
const normalizedPath = rawPath?.trim();
|
|
100579
100647
|
if (normalizedPath === void 0 || normalizedPath.length === 0) {
|
|
100580
100648
|
throw new Error(`Invalid source ref "${serialized}".`);
|
|
@@ -100828,7 +100896,7 @@ async function searchMemory(root, query) {
|
|
|
100828
100896
|
if (normalizedQuery.length === 0) {
|
|
100829
100897
|
throw new Error("Search query cannot be empty.");
|
|
100830
100898
|
}
|
|
100831
|
-
const relPaths = await collectMarkdownRelPaths(root);
|
|
100899
|
+
const relPaths = await collectMarkdownRelPaths(root, MEMORY_PAGES_DIR_RELPATH);
|
|
100832
100900
|
const hits = [];
|
|
100833
100901
|
for (const relPath of relPaths) {
|
|
100834
100902
|
await assertNoSymlinkSegments(root, relPath);
|
|
@@ -101351,7 +101419,7 @@ async function appendToPage(root, relPath, content, opts) {
|
|
|
101351
101419
|
const before = await snapshot(root);
|
|
101352
101420
|
await fs19.mkdir(path158.dirname(pagePath), { recursive: true });
|
|
101353
101421
|
await assertNoSymlinkSegments(root, pageRelPath);
|
|
101354
|
-
const parsed = originalPage
|
|
101422
|
+
const parsed = parseAppendTarget(originalPage, pageRelPath);
|
|
101355
101423
|
try {
|
|
101356
101424
|
await writeFileAtomically7(
|
|
101357
101425
|
pagePath,
|
|
@@ -101363,6 +101431,18 @@ async function appendToPage(root, relPath, content, opts) {
|
|
|
101363
101431
|
throw error3;
|
|
101364
101432
|
}
|
|
101365
101433
|
}
|
|
101434
|
+
function parseAppendTarget(originalPage, relPath) {
|
|
101435
|
+
if (originalPage === void 0) {
|
|
101436
|
+
return { frontmatter: {}, body: "" };
|
|
101437
|
+
}
|
|
101438
|
+
try {
|
|
101439
|
+
return parseFrontmatter4(originalPage);
|
|
101440
|
+
} catch (error3) {
|
|
101441
|
+
const message2 = error3 instanceof Error ? error3.message : String(error3);
|
|
101442
|
+
console.warn(`Failed to parse frontmatter for "${relPath}": ${message2}`);
|
|
101443
|
+
return { frontmatter: {}, body: originalPage };
|
|
101444
|
+
}
|
|
101445
|
+
}
|
|
101366
101446
|
async function clearMemory(root) {
|
|
101367
101447
|
await assertMemoryRootIsNotSymlink(root);
|
|
101368
101448
|
const stagedRoot = `${root}.clear-${randomUUID43()}`;
|
|
@@ -101728,17 +101808,21 @@ async function clearCache(root, opts = {}) {
|
|
|
101728
101808
|
async function assertIngestCachePathIsNotSymlink(root) {
|
|
101729
101809
|
await assertNoSymlinkSegments(root, MEMORY_INGEST_CACHE_DIR_RELPATH);
|
|
101730
101810
|
}
|
|
101731
|
-
function parseCacheEntry(value,
|
|
101811
|
+
function parseCacheEntry(value, requestedKey) {
|
|
101732
101812
|
const object = expectRecord2(value);
|
|
101813
|
+
const key2 = expectString2(getOwnEntry36(object, "key"), "key");
|
|
101814
|
+
if (key2 !== requestedKey) {
|
|
101815
|
+
throw new Error(`Cache entry key "${key2}" does not match requested key "${requestedKey}".`);
|
|
101816
|
+
}
|
|
101733
101817
|
return {
|
|
101734
|
-
key:
|
|
101818
|
+
key: key2,
|
|
101735
101819
|
ingestedAt: expectString2(getOwnEntry36(object, "ingestedAt"), "ingestedAt"),
|
|
101736
101820
|
sourceLabel: expectString2(getOwnEntry36(object, "sourceLabel"), "sourceLabel"),
|
|
101737
101821
|
diff: parseMemoryDiff(getOwnEntry36(object, "diff")),
|
|
101738
|
-
exitCode:
|
|
101739
|
-
durationMs:
|
|
101740
|
-
memoryTokens:
|
|
101741
|
-
sourceTokens:
|
|
101822
|
+
exitCode: expectNonNegativeInteger2(getOwnEntry36(object, "exitCode"), "exitCode"),
|
|
101823
|
+
durationMs: expectNonNegativeInteger2(getOwnEntry36(object, "durationMs"), "durationMs"),
|
|
101824
|
+
memoryTokens: expectNonNegativeInteger2(getOwnEntry36(object, "memoryTokens"), "memoryTokens"),
|
|
101825
|
+
sourceTokens: expectNonNegativeInteger2(getOwnEntry36(object, "sourceTokens"), "sourceTokens"),
|
|
101742
101826
|
promptTemplateVersion: expectString2(
|
|
101743
101827
|
getOwnEntry36(object, "promptTemplateVersion"),
|
|
101744
101828
|
"promptTemplateVersion"
|
|
@@ -101766,9 +101850,9 @@ function expectString2(value, field) {
|
|
|
101766
101850
|
}
|
|
101767
101851
|
return value;
|
|
101768
101852
|
}
|
|
101769
|
-
function
|
|
101770
|
-
if (typeof value !== "number" || Number.
|
|
101771
|
-
throw new Error(`Expected
|
|
101853
|
+
function expectNonNegativeInteger2(value, field) {
|
|
101854
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
101855
|
+
throw new Error(`Expected non-negative integer at "${field}".`);
|
|
101772
101856
|
}
|
|
101773
101857
|
return value;
|
|
101774
101858
|
}
|
|
@@ -102427,7 +102511,7 @@ async function installMemory(options) {
|
|
|
102427
102511
|
}
|
|
102428
102512
|
throw error3;
|
|
102429
102513
|
}
|
|
102430
|
-
mcpConfigPath = options.agent
|
|
102514
|
+
mcpConfigPath = resolveMcpConfigPath(options.agent, options.homeDir, options.platform);
|
|
102431
102515
|
}
|
|
102432
102516
|
return {
|
|
102433
102517
|
skillInstalled: !options.mcpOnly,
|
|
@@ -102436,6 +102520,14 @@ async function installMemory(options) {
|
|
|
102436
102520
|
mcpConfigPath
|
|
102437
102521
|
};
|
|
102438
102522
|
}
|
|
102523
|
+
function resolveMcpConfigPath(agent3, homeDir, platform) {
|
|
102524
|
+
const support = resolveAgentSupport3(agent3);
|
|
102525
|
+
if (support.status !== "supported" || support.config === void 0) {
|
|
102526
|
+
throw new Error(`Unsupported agent: ${agent3}`);
|
|
102527
|
+
}
|
|
102528
|
+
const configFile = typeof support.config.configFile === "function" ? support.config.configFile(platform) : support.config.configFile;
|
|
102529
|
+
return configFile.startsWith("~/") ? path164.join(homeDir, configFile.slice(2)) : configFile;
|
|
102530
|
+
}
|
|
102439
102531
|
async function removeInstalledSkill(options, skillPath) {
|
|
102440
102532
|
const baseDir = options.scope === "global" ? options.homeDir : options.cwd;
|
|
102441
102533
|
const displayPath = skillPath.startsWith("~/") ? skillPath.slice(2) : skillPath;
|
|
@@ -102456,6 +102548,45 @@ var init_install3 = __esm({
|
|
|
102456
102548
|
}
|
|
102457
102549
|
});
|
|
102458
102550
|
|
|
102551
|
+
// packages/memory/src/agent-response.ts
|
|
102552
|
+
function parseMemoryAgentResponse(stdout) {
|
|
102553
|
+
let value;
|
|
102554
|
+
try {
|
|
102555
|
+
value = JSON.parse(stdout);
|
|
102556
|
+
} catch {
|
|
102557
|
+
throw new Error("Memory agent returned invalid JSON output.");
|
|
102558
|
+
}
|
|
102559
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
102560
|
+
throw new Error("Memory agent returned an invalid result payload.");
|
|
102561
|
+
}
|
|
102562
|
+
const result = value;
|
|
102563
|
+
if (typeof result.answer !== "string" || !Array.isArray(result.citations) || !isNonNegativeInteger(result.tokensUsed) || !result.citations.every(isQueryCitation)) {
|
|
102564
|
+
throw new Error("Memory agent returned an invalid result payload.");
|
|
102565
|
+
}
|
|
102566
|
+
return {
|
|
102567
|
+
answer: result.answer,
|
|
102568
|
+
citations: result.citations,
|
|
102569
|
+
tokensUsed: result.tokensUsed
|
|
102570
|
+
};
|
|
102571
|
+
}
|
|
102572
|
+
function isQueryCitation(value) {
|
|
102573
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
102574
|
+
return false;
|
|
102575
|
+
}
|
|
102576
|
+
const citation = value;
|
|
102577
|
+
return typeof citation.relPath === "string" && (citation.section === void 0 || typeof citation.section === "string") && typeof citation.confidence === "string" && validCitationConfidences.has(citation.confidence);
|
|
102578
|
+
}
|
|
102579
|
+
function isNonNegativeInteger(value) {
|
|
102580
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
102581
|
+
}
|
|
102582
|
+
var validCitationConfidences;
|
|
102583
|
+
var init_agent_response = __esm({
|
|
102584
|
+
"packages/memory/src/agent-response.ts"() {
|
|
102585
|
+
"use strict";
|
|
102586
|
+
validCitationConfidences = /* @__PURE__ */ new Set(["extracted", "inferred", "ambiguous"]);
|
|
102587
|
+
}
|
|
102588
|
+
});
|
|
102589
|
+
|
|
102459
102590
|
// packages/memory/src/query.ts
|
|
102460
102591
|
import * as fs25 from "node:fs/promises";
|
|
102461
102592
|
import path165 from "node:path";
|
|
@@ -102478,7 +102609,7 @@ async function queryMemory(root, options) {
|
|
|
102478
102609
|
const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
|
|
102479
102610
|
const context = await selectQueryContext(root, options.question, options.budget);
|
|
102480
102611
|
const spawned = await spawn5(agentId, { prompt: context.prompt });
|
|
102481
|
-
const result =
|
|
102612
|
+
const result = parseMemoryAgentResponse(spawned.stdout);
|
|
102482
102613
|
return {
|
|
102483
102614
|
answer: result.answer,
|
|
102484
102615
|
citations: result.citations,
|
|
@@ -102487,26 +102618,6 @@ async function queryMemory(root, options) {
|
|
|
102487
102618
|
exitCode: spawned.exitCode
|
|
102488
102619
|
};
|
|
102489
102620
|
}
|
|
102490
|
-
function parseQueryResponse(stdout) {
|
|
102491
|
-
let value;
|
|
102492
|
-
try {
|
|
102493
|
-
value = JSON.parse(stdout);
|
|
102494
|
-
} catch {
|
|
102495
|
-
throw new Error("Memory agent returned invalid JSON output.");
|
|
102496
|
-
}
|
|
102497
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
102498
|
-
throw new Error("Memory agent returned an invalid result payload.");
|
|
102499
|
-
}
|
|
102500
|
-
const result = value;
|
|
102501
|
-
if (typeof result.answer !== "string" || !Array.isArray(result.citations) || typeof result.tokensUsed !== "number" || !Number.isFinite(result.tokensUsed)) {
|
|
102502
|
-
throw new Error("Memory agent returned an invalid result payload.");
|
|
102503
|
-
}
|
|
102504
|
-
return {
|
|
102505
|
-
answer: result.answer,
|
|
102506
|
-
citations: result.citations,
|
|
102507
|
-
tokensUsed: result.tokensUsed
|
|
102508
|
-
};
|
|
102509
|
-
}
|
|
102510
102621
|
async function selectQueryContext(root, question, budget) {
|
|
102511
102622
|
if (!Number.isFinite(budget) || budget < 0) {
|
|
102512
102623
|
throw new Error("budget must be a finite non-negative number");
|
|
@@ -102599,6 +102710,7 @@ var init_query = __esm({
|
|
|
102599
102710
|
init_src44();
|
|
102600
102711
|
init_src17();
|
|
102601
102712
|
init_src9();
|
|
102713
|
+
init_agent_response();
|
|
102602
102714
|
init_pages();
|
|
102603
102715
|
init_paths2();
|
|
102604
102716
|
}
|
|
@@ -102634,7 +102746,7 @@ async function explainPage(root, options) {
|
|
|
102634
102746
|
};
|
|
102635
102747
|
const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
|
|
102636
102748
|
const spawned = await spawn5(agentId, { prompt });
|
|
102637
|
-
const response =
|
|
102749
|
+
const response = parseMemoryAgentResponse(spawned.stdout);
|
|
102638
102750
|
return {
|
|
102639
102751
|
answer: response.answer,
|
|
102640
102752
|
citations: response.citations,
|
|
@@ -102645,26 +102757,6 @@ async function explainPage(root, options) {
|
|
|
102645
102757
|
outboundSources: targetPage.frontmatter.sources ?? []
|
|
102646
102758
|
};
|
|
102647
102759
|
}
|
|
102648
|
-
function parseExplainResponse(stdout) {
|
|
102649
|
-
let value;
|
|
102650
|
-
try {
|
|
102651
|
-
value = JSON.parse(stdout);
|
|
102652
|
-
} catch {
|
|
102653
|
-
throw new Error("Memory agent returned invalid JSON output.");
|
|
102654
|
-
}
|
|
102655
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
102656
|
-
throw new Error("Memory agent returned an invalid result payload.");
|
|
102657
|
-
}
|
|
102658
|
-
const response = value;
|
|
102659
|
-
if (typeof response.answer !== "string" || !Array.isArray(response.citations) || typeof response.tokensUsed !== "number" || !Number.isFinite(response.tokensUsed)) {
|
|
102660
|
-
throw new Error("Memory agent returned an invalid result payload.");
|
|
102661
|
-
}
|
|
102662
|
-
return {
|
|
102663
|
-
answer: response.answer,
|
|
102664
|
-
citations: response.citations,
|
|
102665
|
-
tokensUsed: response.tokensUsed
|
|
102666
|
-
};
|
|
102667
|
-
}
|
|
102668
102760
|
function collectRelatedPages(pages, targetRelPath, outboundSources) {
|
|
102669
102761
|
const memorySourcePaths = new Set(outboundSources.map((source) => source.path));
|
|
102670
102762
|
return pages.filter((page) => {
|
|
@@ -102708,6 +102800,7 @@ var init_explain = __esm({
|
|
|
102708
102800
|
init_src44();
|
|
102709
102801
|
init_src17();
|
|
102710
102802
|
init_src9();
|
|
102803
|
+
init_agent_response();
|
|
102711
102804
|
init_errors7();
|
|
102712
102805
|
init_pages();
|
|
102713
102806
|
init_query();
|
|
@@ -102802,7 +102895,7 @@ var init_src45 = __esm({
|
|
|
102802
102895
|
var SKILL_memory_default;
|
|
102803
102896
|
var init_SKILL_memory = __esm({
|
|
102804
102897
|
"packages/memory/src/templates/SKILL_memory.md"() {
|
|
102805
|
-
SKILL_memory_default = '## CLI \u2014 `poe-code memory <subcommand>`\n| Command | Purpose (when the agent should reach for it) |\n|---|---|\n| `init` | create `.poe-code/memory/` if missing; safe before first write |\n| `ls` | list pages + one-line descriptions; first step for recall questions |\n| `show <path>` | print one page verbatim after `ls` identifies a candidate |\n| `search <query>` | ripgrep over memory when the page is not obvious from `ls` |\n| `write <path> --reason <text>` | replace a page from stdin when authoring or rewriting |\n| `append <path>` | append stdin to a page; intended for `LOG.md`-style updates |\n| `edit <path>` | open `$EDITOR`; avoid from agents, prefer `write`/`append` |\n| `ingest <source>` | spawn an ingest agent to fold a file or URL into memory |\n| `query "<question>"` | answer a question from memory only, with citations |\n| `explain <path>` | summarize a page plus its inbound/outbound links |\n| `lint
|
|
102898
|
+
SKILL_memory_default = '## CLI \u2014 `poe-code memory <subcommand>`\n| Command | Purpose (when the agent should reach for it) |\n|---|---|\n| `init` | create `.poe-code/memory/` if missing; safe before first write |\n| `ls` | list pages + one-line descriptions; first step for recall questions |\n| `show <path>` | print one page verbatim after `ls` identifies a candidate |\n| `search <query>` | ripgrep over memory when the page is not obvious from `ls` |\n| `write <path> --reason <text>` | replace a page from stdin when authoring or rewriting |\n| `append <path>` | append stdin to a page; intended for `LOG.md`-style updates |\n| `edit <path>` | open `$EDITOR`; avoid from agents, prefer `write`/`append` |\n| `ingest <source>` | spawn an ingest agent to fold a file or URL into memory |\n| `query "<question>"` | answer a question from memory only, with citations |\n| `explain <path>` | summarize a page plus its inbound/outbound links |\n| `lint` | find stale citations, untagged claims, contradictions |\n| `status [--no-tokens]` | show counts, bytes, and token-reduction ratio |\n| `cache status` / `cache clear` | inspect or clear the ingest cache |\n| `clear --yes` | wipe memory; destructive, user-request only |\n| `install` | install this skill and register the `poe-code-memory` MCP server |\n\n## MCP \u2014 `poe-code-memory` server\n| Tool | Purpose |\n|---|---|\n| `list_pages` | enumerate pages (preferred over shelling out to `memory ls`) |\n| `read_page` | read one page (preferred over `memory show`) |\n| `search_memory` | search memory text (preferred over `memory search`) |\n| `append_to_page` | append to a page when writes are enabled |\n| `status` | read counts and token ratio |\n\n- Prefer MCP tools over shell commands when both surfaces are available.\n- Confidence-tag non-trivial claims with `extracted`, `inferred`, or `ambiguous`.\n- Keep memory edits focused; update the minimal relevant pages.\n- Never call `memory clear` without explicit user request.\n';
|
|
102806
102899
|
}
|
|
102807
102900
|
});
|
|
102808
102901
|
|
|
@@ -102874,6 +102967,28 @@ async function queryBudget(container, value) {
|
|
|
102874
102967
|
projectFilePath: container.env.projectConfigPath
|
|
102875
102968
|
});
|
|
102876
102969
|
}
|
|
102970
|
+
function parseDecimalNonNegativeInteger(value, label) {
|
|
102971
|
+
if (value === void 0) {
|
|
102972
|
+
return void 0;
|
|
102973
|
+
}
|
|
102974
|
+
if (!isDecimalNonNegativeIntegerText(value)) {
|
|
102975
|
+
throw new ValidationError(`${label} must be a decimal non-negative integer.`);
|
|
102976
|
+
}
|
|
102977
|
+
const parsed = Number(value);
|
|
102978
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
102979
|
+
throw new ValidationError(`${label} must be a decimal non-negative integer.`);
|
|
102980
|
+
}
|
|
102981
|
+
return parsed;
|
|
102982
|
+
}
|
|
102983
|
+
function isDecimalNonNegativeIntegerText(value) {
|
|
102984
|
+
if (value.length === 0) {
|
|
102985
|
+
return false;
|
|
102986
|
+
}
|
|
102987
|
+
if (value.length > 1 && value[0] === "0") {
|
|
102988
|
+
return false;
|
|
102989
|
+
}
|
|
102990
|
+
return [...value].every((char) => char >= "0" && char <= "9");
|
|
102991
|
+
}
|
|
102877
102992
|
async function readCommandContent(content) {
|
|
102878
102993
|
if (content !== void 0) {
|
|
102879
102994
|
return content;
|
|
@@ -103012,6 +103127,8 @@ function registerMemoryCommand(program, container) {
|
|
|
103012
103127
|
memory.command("edit").description("Open a page in $EDITOR.").argument("<path>", "Page path (relative to memory pages/)").option("--reason <text>", "Reason for the memory update", "edit").action(async (pagePath, options) => {
|
|
103013
103128
|
const flags = resolveCommandFlags(program);
|
|
103014
103129
|
const root = await resolveRoot(container);
|
|
103130
|
+
const mem = openMemory({ root });
|
|
103131
|
+
await assertInitialized(mem);
|
|
103015
103132
|
const relPath = resolvePageRelPath(pagePath);
|
|
103016
103133
|
const editor = resolveEditor4(container);
|
|
103017
103134
|
if (flags.dryRun) {
|
|
@@ -103030,10 +103147,7 @@ function registerMemoryCommand(program, container) {
|
|
|
103030
103147
|
const root = await resolveRoot(container);
|
|
103031
103148
|
const mem = openMemory({ root });
|
|
103032
103149
|
await assertInitialized(mem);
|
|
103033
|
-
const timeoutMs = options.timeoutMs
|
|
103034
|
-
if (timeoutMs !== void 0 && (!Number.isFinite(timeoutMs) || timeoutMs < 0)) {
|
|
103035
|
-
throw new ValidationError("Timeout must be a finite non-negative number.");
|
|
103036
|
-
}
|
|
103150
|
+
const timeoutMs = parseDecimalNonNegativeInteger(options.timeoutMs, "Timeout");
|
|
103037
103151
|
const result = await mem.ingest({
|
|
103038
103152
|
source: resolveIngestSource(container.env.cwd, source),
|
|
103039
103153
|
agent: options.agent,
|
|
@@ -103046,10 +103160,7 @@ function registerMemoryCommand(program, container) {
|
|
|
103046
103160
|
process.stdout.write(`${result.cacheHit ? "Cache hit" : "Ingested"}: ${result.diff.created.length} created, ${result.diff.updated.length} updated, ${result.diff.deleted.length} deleted.
|
|
103047
103161
|
`);
|
|
103048
103162
|
});
|
|
103049
|
-
memory.command("lint").description("Audit memory confidence and provenance claims.").
|
|
103050
|
-
if (options.fix) {
|
|
103051
|
-
throw new ValidationError("Automated memory lint repair is not available yet.");
|
|
103052
|
-
}
|
|
103163
|
+
memory.command("lint").description("Audit memory confidence and provenance claims.").action(async () => {
|
|
103053
103164
|
const root = await resolveRoot(container);
|
|
103054
103165
|
const mem = openMemory({ root });
|
|
103055
103166
|
await assertInitialized(mem);
|
|
@@ -103066,24 +103177,41 @@ function registerMemoryCommand(program, container) {
|
|
|
103066
103177
|
}
|
|
103067
103178
|
});
|
|
103068
103179
|
memory.command("query").description("Answer a question using memory-only context.").argument("<question>", "Question").option("--budget <tokens>", "Token budget").option("--agent <agent>", "Agent override").action(async (question, options) => {
|
|
103180
|
+
const flags = resolveCommandFlags(program);
|
|
103069
103181
|
const root = await resolveRoot(container);
|
|
103070
103182
|
const mem = openMemory({ root });
|
|
103071
103183
|
await assertInitialized(mem);
|
|
103184
|
+
const budget = await queryBudget(container, options.budget);
|
|
103185
|
+
if (flags.dryRun) {
|
|
103186
|
+
createExecutionResources(container, flags, "memory:query").logger.dryRun(
|
|
103187
|
+
`Would query memory with budget ${budget}.`
|
|
103188
|
+
);
|
|
103189
|
+
return;
|
|
103190
|
+
}
|
|
103072
103191
|
const result = await mem.query({
|
|
103073
103192
|
question,
|
|
103074
|
-
budget
|
|
103193
|
+
budget,
|
|
103075
103194
|
agent: options.agent
|
|
103076
103195
|
});
|
|
103077
103196
|
process.stdout.write(`${result.answer}
|
|
103078
103197
|
`);
|
|
103079
103198
|
});
|
|
103080
103199
|
memory.command("explain").description("Summarize a memory page and its relationships.").argument("<path>", "Page path (relative to memory pages/)").option("--budget <tokens>", "Token budget").option("--agent <agent>", "Agent override").action(async (pagePath, options) => {
|
|
103200
|
+
const flags = resolveCommandFlags(program);
|
|
103081
103201
|
const root = await resolveRoot(container);
|
|
103082
103202
|
const mem = openMemory({ root });
|
|
103083
103203
|
await assertInitialized(mem);
|
|
103204
|
+
const relPath = resolvePageRelPath(pagePath);
|
|
103205
|
+
const budget = await queryBudget(container, options.budget);
|
|
103206
|
+
if (flags.dryRun) {
|
|
103207
|
+
createExecutionResources(container, flags, "memory:explain").logger.dryRun(
|
|
103208
|
+
`Would explain ${relPath} with budget ${budget}.`
|
|
103209
|
+
);
|
|
103210
|
+
return;
|
|
103211
|
+
}
|
|
103084
103212
|
const result = await mem.explainPage({
|
|
103085
|
-
relPath
|
|
103086
|
-
budget
|
|
103213
|
+
relPath,
|
|
103214
|
+
budget,
|
|
103087
103215
|
agent: options.agent
|
|
103088
103216
|
});
|
|
103089
103217
|
process.stdout.write(`${result.answer}
|
|
@@ -103217,7 +103345,12 @@ function registerMemoryMcpCommand(program, container) {
|
|
|
103217
103345
|
projectConfigPath: container.env.projectConfigPath
|
|
103218
103346
|
});
|
|
103219
103347
|
const handle = openMemory({ root });
|
|
103220
|
-
const
|
|
103348
|
+
const allowWrites = options.allowWrites === true || await mcpWritesAllowed({
|
|
103349
|
+
fs: container.fs,
|
|
103350
|
+
filePath: container.env.configPath,
|
|
103351
|
+
projectFilePath: container.env.projectConfigPath
|
|
103352
|
+
});
|
|
103353
|
+
const { server } = await startMemoryMcpServer(handle, { allowWrites });
|
|
103221
103354
|
await server.listen();
|
|
103222
103355
|
});
|
|
103223
103356
|
}
|
|
@@ -103225,6 +103358,7 @@ var init_memory_mcp = __esm({
|
|
|
103225
103358
|
"src/cli/commands/memory-mcp.ts"() {
|
|
103226
103359
|
"use strict";
|
|
103227
103360
|
init_src45();
|
|
103361
|
+
init_src9();
|
|
103228
103362
|
}
|
|
103229
103363
|
});
|
|
103230
103364
|
|
|
@@ -137375,7 +137509,7 @@ var init_package2 = __esm({
|
|
|
137375
137509
|
"package.json"() {
|
|
137376
137510
|
package_default2 = {
|
|
137377
137511
|
name: "poe-code",
|
|
137378
|
-
version: "3.0.
|
|
137512
|
+
version: "3.0.313",
|
|
137379
137513
|
description: "CLI tool to configure Poe API for developer workflows.",
|
|
137380
137514
|
type: "module",
|
|
137381
137515
|
main: "./dist/index.js",
|