poe-code 3.0.282 → 3.0.284
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 +25 -2
- package/dist/index.js.map +2 -2
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/terminal-pilot/dist/cli.js +24 -1
- package/packages/terminal-pilot/dist/cli.js.map +2 -2
- package/packages/terminal-pilot/dist/testing/cli-repl.js +24 -1
- package/packages/terminal-pilot/dist/testing/cli-repl.js.map +2 -2
- package/packages/terminal-pilot/dist/testing/qa-cli.js +24 -1
- package/packages/terminal-pilot/dist/testing/qa-cli.js.map +2 -2
- package/packages/toolcraft/dist/cli.js +24 -1
- package/packages/toolcraft-codemode/dist/execute.js +9 -2
- package/packages/toolcraft-codemode/dist/host-modules.js +3 -0
- package/packages/toolcraft-codemode/dist/search.js +15 -6
- package/packages/toolcraft-codemode/dist/tree.js +14 -3
|
@@ -588,6 +588,20 @@ function parseArrayValue(value, schema, label) {
|
|
|
588
588
|
}
|
|
589
589
|
return splitArrayInput(value).map((item) => parseScalarValue(item, itemSchema, label));
|
|
590
590
|
}
|
|
591
|
+
function isNegativeNumericArrayToken(token, schema) {
|
|
592
|
+
if (!token.startsWith("-") || token.startsWith("--")) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
const itemSchema = unwrapOptional(schema.item);
|
|
596
|
+
if (itemSchema.kind !== "number") {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
const items = splitArrayInput(token);
|
|
600
|
+
return (items.length > 0 && items.every((item) => isValidNumberSchemaValue(Number(item), itemSchema)));
|
|
601
|
+
}
|
|
602
|
+
function isNextArrayOptionToken(token, schema) {
|
|
603
|
+
return token.startsWith("-") && !isNegativeNumericArrayToken(token, schema);
|
|
604
|
+
}
|
|
591
605
|
function validateArrayBounds(value, schema, label) {
|
|
592
606
|
if (schema.minItems !== undefined && value.length < schema.minItems) {
|
|
593
607
|
throw new UserError(`Invalid value for "${label}". Expected an array with at least ${schema.minItems} items, got array(${value.length}).`);
|
|
@@ -2044,7 +2058,7 @@ function consumeFieldValue(args, index, schema, label, inlineValue) {
|
|
|
2044
2058
|
let cursor = index + 1;
|
|
2045
2059
|
while (cursor < args.length) {
|
|
2046
2060
|
const token = args[cursor] ?? "";
|
|
2047
|
-
if (token
|
|
2061
|
+
if (isNextArrayOptionToken(token, schema)) {
|
|
2048
2062
|
break;
|
|
2049
2063
|
}
|
|
2050
2064
|
const parsed = parseArrayValue(token, schema, label);
|
|
@@ -2817,6 +2831,12 @@ function handleRunError(error, options) {
|
|
|
2817
2831
|
}));
|
|
2818
2832
|
return;
|
|
2819
2833
|
}
|
|
2834
|
+
logger.error(appendUsagePointer(formatCommanderErrorMessage(error), {
|
|
2835
|
+
rootUsageName: options.rootUsageName,
|
|
2836
|
+
commandPath: options.commandPath.length > 0
|
|
2837
|
+
? options.commandPath
|
|
2838
|
+
: findCurrentCommanderCommandPath(options.program, options.argv ?? process.argv)
|
|
2839
|
+
}));
|
|
2820
2840
|
return;
|
|
2821
2841
|
}
|
|
2822
2842
|
if (isHttpErrorLike(error)) {
|
|
@@ -2831,6 +2851,9 @@ function handleRunError(error, options) {
|
|
|
2831
2851
|
}
|
|
2832
2852
|
process.exitCode = 1;
|
|
2833
2853
|
}
|
|
2854
|
+
function formatCommanderErrorMessage(error) {
|
|
2855
|
+
return error.message.startsWith("error:") ? error.message : `error: ${error.message}`;
|
|
2856
|
+
}
|
|
2834
2857
|
function formatInvalidEnumMessage(label, value, values, opts = {}) {
|
|
2835
2858
|
const suggestions = suggest(value, opts.candidates ?? values.map((candidate) => String(candidate)), opts);
|
|
2836
2859
|
const suggestionLine = suggestions.length > 0 ? ` Did you mean: ${suggestions.join(", ")}?\n` : " ";
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { Budget, lint, run } from "@poe-code/safejs/core";
|
|
2
|
-
import { defineCommand } from "toolcraft";
|
|
2
|
+
import { defineCommand, UserError } from "toolcraft";
|
|
3
3
|
import { S } from "toolcraft-schema";
|
|
4
4
|
import { getOwnErrorCode } from "./error-codes.js";
|
|
5
5
|
import { buildHostModules } from "./host-modules.js";
|
|
6
6
|
const executeParams = S.Object({
|
|
7
|
-
source: S.String({
|
|
7
|
+
source: S.String({
|
|
8
|
+
description: "SafeJS source to execute.",
|
|
9
|
+
minLength: 1,
|
|
10
|
+
pattern: "\\S"
|
|
11
|
+
})
|
|
8
12
|
});
|
|
9
13
|
function createBudget(options) {
|
|
10
14
|
return new Budget({
|
|
@@ -90,6 +94,9 @@ export function makeExecuteCommand({ root, sdk, entries, budget, scope = ["mcp",
|
|
|
90
94
|
scope,
|
|
91
95
|
params: executeParams,
|
|
92
96
|
handler: async ({ params }) => {
|
|
97
|
+
if (params.source.trim().length === 0) {
|
|
98
|
+
throw new UserError("source must not be empty or whitespace");
|
|
99
|
+
}
|
|
93
100
|
const { lintModules, modules } = await buildHostModules(root, sdk, entries);
|
|
94
101
|
let diagnostics;
|
|
95
102
|
try {
|
|
@@ -16,6 +16,9 @@ function resolveSdkMember(sdk, path) {
|
|
|
16
16
|
if (typeof current !== "object" && typeof current !== "function") {
|
|
17
17
|
return undefined;
|
|
18
18
|
}
|
|
19
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
19
22
|
current = current[segment];
|
|
20
23
|
}
|
|
21
24
|
return current;
|
|
@@ -4,18 +4,21 @@ import { resolveCommandEntries } from "./tree.js";
|
|
|
4
4
|
const K1 = 1.5;
|
|
5
5
|
const B = 0.75;
|
|
6
6
|
const FALLBACK_LIMIT = 10;
|
|
7
|
+
const SEARCH_DETAILS = ["brief", "detailed", "full"];
|
|
7
8
|
const searchParams = S.Object({
|
|
8
9
|
query: S.String({ description: "Search query." }),
|
|
9
|
-
limit: S.Optional(S.Number({
|
|
10
|
-
|
|
10
|
+
limit: S.Optional(S.Number({
|
|
11
|
+
description: "Maximum result count.",
|
|
12
|
+
jsonType: "integer",
|
|
13
|
+
minimum: 0
|
|
14
|
+
})),
|
|
15
|
+
detail: S.Optional(S.Enum(SEARCH_DETAILS, {
|
|
11
16
|
description: "Result detail level."
|
|
12
17
|
}))
|
|
13
18
|
});
|
|
14
19
|
function isWordCharacter(character) {
|
|
15
20
|
const code = character.charCodeAt(0);
|
|
16
|
-
return (
|
|
17
|
-
(code >= 48 && code <= 57) ||
|
|
18
|
-
character === "_");
|
|
21
|
+
return (code >= 97 && code <= 122) || (code >= 48 && code <= 57) || character === "_";
|
|
19
22
|
}
|
|
20
23
|
function tokenize(value) {
|
|
21
24
|
const tokens = [];
|
|
@@ -89,6 +92,12 @@ function normalizeLimit(limit) {
|
|
|
89
92
|
}
|
|
90
93
|
return limit;
|
|
91
94
|
}
|
|
95
|
+
function normalizeDetail(detail) {
|
|
96
|
+
if (SEARCH_DETAILS.includes(detail)) {
|
|
97
|
+
return detail;
|
|
98
|
+
}
|
|
99
|
+
throw new UserError(`detail must be one of: ${SEARCH_DETAILS.join(", ")}, received ${JSON.stringify(detail)}`);
|
|
100
|
+
}
|
|
92
101
|
function toSearchResult(entry, detail) {
|
|
93
102
|
const result = {
|
|
94
103
|
path: entry.path,
|
|
@@ -115,7 +124,7 @@ export function makeSearchCommand({ entries, defaults = {}, scope = ["mcp", "sdk
|
|
|
115
124
|
if (limit === 0) {
|
|
116
125
|
return [];
|
|
117
126
|
}
|
|
118
|
-
const detail = params.detail ?? defaults.detail ?? "brief";
|
|
127
|
+
const detail = normalizeDetail(params.detail ?? defaults.detail ?? "brief");
|
|
119
128
|
const indexedEntries = resolvedEntries.map(indexEntry);
|
|
120
129
|
const frequencies = documentFrequencies(indexedEntries);
|
|
121
130
|
const averageLength = averageDocumentLength(indexedEntries);
|
|
@@ -22,7 +22,9 @@ function splitWords(value) {
|
|
|
22
22
|
const isUppercase = character !== lower && character === upper;
|
|
23
23
|
const previous = value[index - 1];
|
|
24
24
|
const next = value[index + 1];
|
|
25
|
-
const previousIsLowercase = previous !== undefined &&
|
|
25
|
+
const previousIsLowercase = previous !== undefined &&
|
|
26
|
+
previous === previous.toLowerCase() &&
|
|
27
|
+
previous !== previous.toUpperCase();
|
|
26
28
|
const nextIsLowercase = next !== undefined && next === next.toLowerCase() && next !== next.toUpperCase();
|
|
27
29
|
if (isUppercase && current.length > 0 && (previousIsLowercase || nextIsLowercase)) {
|
|
28
30
|
words.push(current.toLowerCase());
|
|
@@ -44,6 +46,13 @@ export function formatSdkSegment(segment) {
|
|
|
44
46
|
export function formatModuleSegment(segment) {
|
|
45
47
|
return splitWords(segment).join("_");
|
|
46
48
|
}
|
|
49
|
+
function formatNamedModuleSegment(segment, kind) {
|
|
50
|
+
const formatted = formatModuleSegment(segment);
|
|
51
|
+
if (formatted.length === 0) {
|
|
52
|
+
throw new Error(`Codemode ${kind} name "${segment}" must include at least one non-separator character.`);
|
|
53
|
+
}
|
|
54
|
+
return formatted;
|
|
55
|
+
}
|
|
47
56
|
function commandIsExecutable(command) {
|
|
48
57
|
return command.scope.includes("sdk");
|
|
49
58
|
}
|
|
@@ -61,7 +70,9 @@ export async function resolveCommandTree(root, options = {}) {
|
|
|
61
70
|
const exportsByGroupPath = new Map();
|
|
62
71
|
const paths = new Set();
|
|
63
72
|
function visit(group, groupSegments) {
|
|
64
|
-
const groupPath = groupSegments
|
|
73
|
+
const groupPath = groupSegments
|
|
74
|
+
.map((segment) => formatNamedModuleSegment(segment, "group"))
|
|
75
|
+
.join(".");
|
|
65
76
|
for (const child of group.children) {
|
|
66
77
|
if (child.kind === "group") {
|
|
67
78
|
visit(child, [...groupSegments, child.name]);
|
|
@@ -70,7 +81,7 @@ export async function resolveCommandTree(root, options = {}) {
|
|
|
70
81
|
if (!commandIsExecutable(child)) {
|
|
71
82
|
continue;
|
|
72
83
|
}
|
|
73
|
-
const name =
|
|
84
|
+
const name = formatNamedModuleSegment(child.name, "command");
|
|
74
85
|
const path = groupPath.length === 0 ? name : `${groupPath}.${name}`;
|
|
75
86
|
if (paths.has(path)) {
|
|
76
87
|
throw new Error(`Duplicate codemode command path "${path}".`);
|