poe-code 3.0.283 → 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 +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -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
package/package.json
CHANGED
|
@@ -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}".`);
|