flavor-code 1.2.11 → 1.2.13
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/README.md +36 -35
- package/README.zh-CN.md +36 -35
- package/dist/{app-MXWPZBEU.js → app-Z3YWFIBB.js} +5 -3
- package/dist/astgraph/db.mjs +237 -0
- package/dist/astgraph/extract.mjs +239 -0
- package/dist/astgraph/flavor-plugin.json +25 -0
- package/dist/astgraph/grammars.mjs +68 -0
- package/dist/astgraph/index.js +301 -0
- package/dist/astgraph/indexer.mjs +175 -0
- package/dist/astgraph/query.mjs +165 -0
- package/dist/astgraph/resolve.mjs +93 -0
- package/dist/astgraph/vendor/tree-sitter-javascript.wasm +0 -0
- package/dist/astgraph/vendor/tree-sitter-tsx.wasm +0 -0
- package/dist/astgraph/vendor/tree-sitter-typescript.wasm +0 -0
- package/dist/astgraph/vendor/tree-sitter.js +3980 -0
- package/dist/astgraph/vendor/tree-sitter.wasm +0 -0
- package/dist/astgraph/vendor/zod/LICENSE +21 -0
- package/dist/astgraph/vendor/zod/index.js +4 -0
- package/dist/astgraph/vendor/zod/locales/index.js +1 -0
- package/dist/astgraph/vendor/zod/locales/package.json +7 -0
- package/dist/astgraph/vendor/zod/package.json +135 -0
- package/dist/astgraph/vendor/zod/v4/classic/checks.js +1 -0
- package/dist/astgraph/vendor/zod/v4/classic/coerce.js +17 -0
- package/dist/astgraph/vendor/zod/v4/classic/compat.js +31 -0
- package/dist/astgraph/vendor/zod/v4/classic/errors.js +48 -0
- package/dist/astgraph/vendor/zod/v4/classic/external.js +20 -0
- package/dist/astgraph/vendor/zod/v4/classic/from-json-schema.js +599 -0
- package/dist/astgraph/vendor/zod/v4/classic/index.js +4 -0
- package/dist/astgraph/vendor/zod/v4/classic/iso.js +30 -0
- package/dist/astgraph/vendor/zod/v4/classic/package.json +7 -0
- package/dist/astgraph/vendor/zod/v4/classic/parse.js +15 -0
- package/dist/astgraph/vendor/zod/v4/classic/schemas.js +1395 -0
- package/dist/astgraph/vendor/zod/v4/core/api.js +1087 -0
- package/dist/astgraph/vendor/zod/v4/core/checks.js +575 -0
- package/dist/astgraph/vendor/zod/v4/core/core.js +78 -0
- package/dist/astgraph/vendor/zod/v4/core/doc.js +35 -0
- package/dist/astgraph/vendor/zod/v4/core/errors.js +185 -0
- package/dist/astgraph/vendor/zod/v4/core/index.js +16 -0
- package/dist/astgraph/vendor/zod/v4/core/json-schema-generator.js +95 -0
- package/dist/astgraph/vendor/zod/v4/core/json-schema-processors.js +601 -0
- package/dist/astgraph/vendor/zod/v4/core/json-schema.js +1 -0
- package/dist/astgraph/vendor/zod/v4/core/package.json +7 -0
- package/dist/astgraph/vendor/zod/v4/core/parse.js +93 -0
- package/dist/astgraph/vendor/zod/v4/core/regexes.js +139 -0
- package/dist/astgraph/vendor/zod/v4/core/registries.js +51 -0
- package/dist/astgraph/vendor/zod/v4/core/schemas.js +2239 -0
- package/dist/astgraph/vendor/zod/v4/core/standard-schema.js +1 -0
- package/dist/astgraph/vendor/zod/v4/core/to-json-schema.js +448 -0
- package/dist/astgraph/vendor/zod/v4/core/util.js +674 -0
- package/dist/astgraph/vendor/zod/v4/core/versions.js +5 -0
- package/dist/astgraph/vendor/zod/v4/index.js +3 -0
- package/dist/astgraph/vendor/zod/v4/locales/ar.js +106 -0
- package/dist/astgraph/vendor/zod/v4/locales/az.js +105 -0
- package/dist/astgraph/vendor/zod/v4/locales/be.js +156 -0
- package/dist/astgraph/vendor/zod/v4/locales/bg.js +120 -0
- package/dist/astgraph/vendor/zod/v4/locales/ca.js +107 -0
- package/dist/astgraph/vendor/zod/v4/locales/cs.js +111 -0
- package/dist/astgraph/vendor/zod/v4/locales/da.js +115 -0
- package/dist/astgraph/vendor/zod/v4/locales/de.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/el.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/en.js +113 -0
- package/dist/astgraph/vendor/zod/v4/locales/eo.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/es.js +132 -0
- package/dist/astgraph/vendor/zod/v4/locales/fa.js +114 -0
- package/dist/astgraph/vendor/zod/v4/locales/fi.js +112 -0
- package/dist/astgraph/vendor/zod/v4/locales/fr-CA.js +107 -0
- package/dist/astgraph/vendor/zod/v4/locales/fr.js +125 -0
- package/dist/astgraph/vendor/zod/v4/locales/he.js +214 -0
- package/dist/astgraph/vendor/zod/v4/locales/hr.js +122 -0
- package/dist/astgraph/vendor/zod/v4/locales/hu.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/hy.js +147 -0
- package/dist/astgraph/vendor/zod/v4/locales/id.js +106 -0
- package/dist/astgraph/vendor/zod/v4/locales/index.js +52 -0
- package/dist/astgraph/vendor/zod/v4/locales/is.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/it.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/ja.js +107 -0
- package/dist/astgraph/vendor/zod/v4/locales/ka.js +112 -0
- package/dist/astgraph/vendor/zod/v4/locales/kh.js +5 -0
- package/dist/astgraph/vendor/zod/v4/locales/km.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/ko.js +111 -0
- package/dist/astgraph/vendor/zod/v4/locales/lt.js +203 -0
- package/dist/astgraph/vendor/zod/v4/locales/mk.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/ms.js +107 -0
- package/dist/astgraph/vendor/zod/v4/locales/nl.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/no.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/ota.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/package.json +7 -0
- package/dist/astgraph/vendor/zod/v4/locales/pl.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/ps.js +114 -0
- package/dist/astgraph/vendor/zod/v4/locales/pt.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/ro.js +119 -0
- package/dist/astgraph/vendor/zod/v4/locales/ru.js +156 -0
- package/dist/astgraph/vendor/zod/v4/locales/sl.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/sv.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/ta.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/th.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/tr.js +105 -0
- package/dist/astgraph/vendor/zod/v4/locales/ua.js +5 -0
- package/dist/astgraph/vendor/zod/v4/locales/uk.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/ur.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/uz.js +110 -0
- package/dist/astgraph/vendor/zod/v4/locales/vi.js +108 -0
- package/dist/astgraph/vendor/zod/v4/locales/yo.js +107 -0
- package/dist/astgraph/vendor/zod/v4/locales/zh-CN.js +109 -0
- package/dist/astgraph/vendor/zod/v4/locales/zh-TW.js +107 -0
- package/dist/astgraph/vendor/zod/v4/mini/checks.js +1 -0
- package/dist/astgraph/vendor/zod/v4/mini/coerce.js +22 -0
- package/dist/astgraph/vendor/zod/v4/mini/external.js +14 -0
- package/dist/astgraph/vendor/zod/v4/mini/index.js +3 -0
- package/dist/astgraph/vendor/zod/v4/mini/iso.js +34 -0
- package/dist/astgraph/vendor/zod/v4/mini/package.json +7 -0
- package/dist/astgraph/vendor/zod/v4/mini/parse.js +1 -0
- package/dist/astgraph/vendor/zod/v4/mini/schemas.js +961 -0
- package/dist/astgraph/vendor/zod/v4/package.json +7 -0
- package/dist/{chunk-EY6KE7L2.js → chunk-G6Q2Y2A7.js} +1 -1
- package/dist/{chunk-OT5XIN6G.js → chunk-Y5MZDG7I.js} +161 -18
- package/dist/cli.js +3 -3
- package/dist/desktop/main.js +161 -18
- package/dist/desktop-renderer/assets/{index-sgEm4kjf.js → index-CCnSpff0.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/init/project.d.ts +8 -0
- package/dist/models/structured.d.ts +14 -0
- package/dist/permissions/engine.d.ts +2 -0
- package/dist/plugins/types.d.ts +2 -2
- package/dist/sdk/index.js +2 -2
- package/dist/tools/shell.d.ts +1 -1
- package/dist/tools/types.d.ts +2 -0
- package/dist/ui/session.d.ts +4 -1
- package/package.json +5 -3
|
@@ -152,11 +152,12 @@ var PermissionEngine = class {
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
const inside = paths.every((path) => classifyPath(this.#lexicalWorkspace, this.#workspace, path).inside);
|
|
155
|
+
const isRead = READ_TOOLS.has(request.tool) || request.readOnly === true;
|
|
155
156
|
if (this.#profile === "d2c") return this.#d2cDecision(request, inside);
|
|
156
157
|
if (this.#mode === "plan") {
|
|
157
|
-
return
|
|
158
|
+
return isRead ? { decision: "allow" } : { decision: "deny", reason: "Plan mode is read-only" };
|
|
158
159
|
}
|
|
159
|
-
if (
|
|
160
|
+
if (isRead) {
|
|
160
161
|
return { decision: "allow" };
|
|
161
162
|
}
|
|
162
163
|
if (DESTRUCTIVE_TOOLS.has(request.tool)) {
|
|
@@ -179,7 +180,7 @@ var PermissionEngine = class {
|
|
|
179
180
|
if ((request.paths?.length ?? 0) > 0 && !inside) {
|
|
180
181
|
return { decision: "deny", reason: "D2C tools must remain in the workspace" };
|
|
181
182
|
}
|
|
182
|
-
if (READ_TOOLS.has(request.tool)) return { decision: "allow" };
|
|
183
|
+
if (READ_TOOLS.has(request.tool) || request.readOnly === true) return { decision: "allow" };
|
|
183
184
|
if (isDeletionTool(request.tool)) {
|
|
184
185
|
return { decision: "ask", reason: "Deletion requires approval", allowAlways: false };
|
|
185
186
|
}
|
|
@@ -504,7 +505,7 @@ function redactSecrets(input, secrets) {
|
|
|
504
505
|
|
|
505
506
|
// src/init/project.ts
|
|
506
507
|
import { lstat, mkdir, readdir, readFile, realpath, writeFile } from "fs/promises";
|
|
507
|
-
import { readFileSync } from "fs";
|
|
508
|
+
import { copyFileSync, mkdirSync, readdirSync, readFileSync } from "fs";
|
|
508
509
|
import { basename, dirname as dirname2, isAbsolute as isAbsolute2, join, relative as relative2, sep as sep2 } from "path";
|
|
509
510
|
import { fileURLToPath } from "url";
|
|
510
511
|
var GENERATED_START = "<!-- flavor-code:start -->";
|
|
@@ -769,6 +770,7 @@ async function inspectProject(cwd) {
|
|
|
769
770
|
languages.add("Python");
|
|
770
771
|
}
|
|
771
772
|
const gitignorePath = await pathKind(join(cwd, ".gitignore"), root) === "file" ? ".gitignore" : void 0;
|
|
773
|
+
const hasCodeGraph = await pathKind(join(cwd, ".flavor", "astgraph", "index.db"), root) === "file";
|
|
772
774
|
return {
|
|
773
775
|
cwd,
|
|
774
776
|
projectName,
|
|
@@ -784,6 +786,7 @@ async function inspectProject(cwd) {
|
|
|
784
786
|
instructionFiles,
|
|
785
787
|
configFiles,
|
|
786
788
|
...gitignorePath === void 0 ? {} : { gitignorePath },
|
|
789
|
+
hasCodeGraph,
|
|
787
790
|
cautions
|
|
788
791
|
};
|
|
789
792
|
}
|
|
@@ -804,6 +807,12 @@ function renderGeneratedSection(facts, newline) {
|
|
|
804
807
|
"Do not inspect dependency directories or generated output unless explicitly required.",
|
|
805
808
|
...facts.cautions
|
|
806
809
|
];
|
|
810
|
+
const searchSection = facts.hasCodeGraph ? [
|
|
811
|
+
"",
|
|
812
|
+
"## Search",
|
|
813
|
+
"",
|
|
814
|
+
"- A code graph index is available (`.flavor/astgraph/index.db`): pair `ast_search` with `grep`/`glob` to locate symbols, and use `ast_callers`/`ast_callees`/`ast_impact`/`ast_context` to trace reachability instead of reading files broadly."
|
|
815
|
+
] : [];
|
|
807
816
|
return [
|
|
808
817
|
GENERATED_START,
|
|
809
818
|
"## Overview",
|
|
@@ -815,6 +824,7 @@ function renderGeneratedSection(facts, newline) {
|
|
|
815
824
|
"## Layout",
|
|
816
825
|
"",
|
|
817
826
|
bulletList(facts.sourceDirectories, "No conventional source directories detected.", true, newline),
|
|
827
|
+
...searchSection,
|
|
818
828
|
"",
|
|
819
829
|
"## Build",
|
|
820
830
|
"",
|
|
@@ -964,9 +974,30 @@ async function copyCodeIslandPlugin(cwd) {
|
|
|
964
974
|
await writeFile(join(pluginDir, name), content);
|
|
965
975
|
}
|
|
966
976
|
}
|
|
977
|
+
var ASTGRAPH_SRC_DIR = join(dirname2(fileURLToPath(import.meta.url)), "astgraph");
|
|
978
|
+
async function copyAstgraphPlugin(cwd) {
|
|
979
|
+
const pluginDir = join(cwd, ".flavor", "plugins", "astgraph");
|
|
980
|
+
try {
|
|
981
|
+
await lstat(pluginDir);
|
|
982
|
+
return;
|
|
983
|
+
} catch (error) {
|
|
984
|
+
if (!isMissingPathError(error)) throw error;
|
|
985
|
+
}
|
|
986
|
+
copyDirectory(ASTGRAPH_SRC_DIR, pluginDir);
|
|
987
|
+
}
|
|
988
|
+
function copyDirectory(from, to) {
|
|
989
|
+
mkdirSync(to, { recursive: true, mode: 448 });
|
|
990
|
+
for (const entry2 of readdirSync(from, { withFileTypes: true })) {
|
|
991
|
+
const source = join(from, entry2.name);
|
|
992
|
+
const target = join(to, entry2.name);
|
|
993
|
+
if (entry2.isDirectory()) copyDirectory(source, target);
|
|
994
|
+
else if (entry2.isFile()) copyFileSync(source, target);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
967
997
|
async function initializeFlavor(cwd) {
|
|
968
998
|
await ensureFlavorDirectories(cwd);
|
|
969
999
|
await copyCodeIslandPlugin(cwd);
|
|
1000
|
+
await copyAstgraphPlugin(cwd);
|
|
970
1001
|
await createExampleFlavorConfig(cwd);
|
|
971
1002
|
const facts = await inspectProject(cwd);
|
|
972
1003
|
const path = join(cwd, "FLAVOR.md");
|
|
@@ -3415,7 +3446,7 @@ var FlavorSession = class {
|
|
|
3415
3446
|
} catch {
|
|
3416
3447
|
}
|
|
3417
3448
|
}
|
|
3418
|
-
const command = parseSlashCommand(prompt, this.#services.pluginCommands(), skillNames);
|
|
3449
|
+
const command = parseSlashCommand(prompt, this.#services.pluginCommands().map(({ name }) => name), skillNames);
|
|
3419
3450
|
if (command !== null) await this.#dispatch(command, controller.signal);
|
|
3420
3451
|
else for await (const event of this.#services.run(prompt, controller.signal, {
|
|
3421
3452
|
getSteeringMessages: () => this.#drainMessages("steer").map((item) => item.text),
|
|
@@ -6148,6 +6179,7 @@ function withStructuredOutput(options) {
|
|
|
6148
6179
|
}
|
|
6149
6180
|
const tool = modelToolFromZod(options.name, options.description, options.schema);
|
|
6150
6181
|
const maxAttempts = retry.maxRetries + 1;
|
|
6182
|
+
const jsonSchema = tool.inputSchema;
|
|
6151
6183
|
const model = {
|
|
6152
6184
|
async *stream(request) {
|
|
6153
6185
|
let candidate;
|
|
@@ -6181,6 +6213,7 @@ function withStructuredOutput(options) {
|
|
|
6181
6213
|
candidate = void 0;
|
|
6182
6214
|
rawCandidate = void 0;
|
|
6183
6215
|
let candidateCount = 0;
|
|
6216
|
+
let textCandidate = "";
|
|
6184
6217
|
let attemptError;
|
|
6185
6218
|
let usage;
|
|
6186
6219
|
for await (const event of adapter.stream(modelRequest)) {
|
|
@@ -6198,6 +6231,8 @@ function withStructuredOutput(options) {
|
|
|
6198
6231
|
rawCandidate = event.rawInput;
|
|
6199
6232
|
secrets.add(event.rawInput);
|
|
6200
6233
|
attemptError = event.error;
|
|
6234
|
+
} else if (event.type === "text") {
|
|
6235
|
+
textCandidate += event.text;
|
|
6201
6236
|
} else if (event.type === "usage") {
|
|
6202
6237
|
usage = { inputTokens: event.inputTokens, outputTokens: event.outputTokens };
|
|
6203
6238
|
} else if (event.type === "done") {
|
|
@@ -6208,6 +6243,17 @@ function withStructuredOutput(options) {
|
|
|
6208
6243
|
}
|
|
6209
6244
|
if (usage !== void 0) yield { type: "usage", ...usage };
|
|
6210
6245
|
if (attemptError === void 0) {
|
|
6246
|
+
if (candidateCount === 0 && textCandidate.trim() !== "") {
|
|
6247
|
+
const extracted = extractJsonObject(textCandidate);
|
|
6248
|
+
if (extracted !== void 0) {
|
|
6249
|
+
candidate = extracted;
|
|
6250
|
+
candidateCount = 1;
|
|
6251
|
+
rawCandidate = textCandidate;
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
if (candidateCount === 1 && candidate !== null && typeof candidate === "object") {
|
|
6255
|
+
candidate = coerceByJsonSchema(candidate, jsonSchema);
|
|
6256
|
+
}
|
|
6211
6257
|
if (candidateCount !== 1) {
|
|
6212
6258
|
attemptError = {
|
|
6213
6259
|
code: "invalid_tool_arguments",
|
|
@@ -6280,6 +6326,86 @@ function withStructuredOutput(options) {
|
|
|
6280
6326
|
function strictJsonSchema(schema) {
|
|
6281
6327
|
return ensureStrictSchema(z7.toJSONSchema(schema));
|
|
6282
6328
|
}
|
|
6329
|
+
function extractJsonObject(text) {
|
|
6330
|
+
const trimmed = text.trim();
|
|
6331
|
+
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/u);
|
|
6332
|
+
const candidates = fenced !== null && fenced[1] !== void 0 ? [fenced[1].trim(), trimmed] : [trimmed];
|
|
6333
|
+
for (const candidate of candidates) {
|
|
6334
|
+
try {
|
|
6335
|
+
const parsed = JSON.parse(candidate);
|
|
6336
|
+
if (parsed !== null && typeof parsed === "object") return parsed;
|
|
6337
|
+
} catch {
|
|
6338
|
+
}
|
|
6339
|
+
}
|
|
6340
|
+
const start = trimmed.indexOf("{");
|
|
6341
|
+
if (start >= 0) {
|
|
6342
|
+
let depth = 0;
|
|
6343
|
+
let inString = false;
|
|
6344
|
+
let escaped = false;
|
|
6345
|
+
for (let index = start; index < trimmed.length; index += 1) {
|
|
6346
|
+
const char = trimmed[index];
|
|
6347
|
+
if (inString) {
|
|
6348
|
+
if (escaped) escaped = false;
|
|
6349
|
+
else if (char === "\\") escaped = true;
|
|
6350
|
+
else if (char === '"') inString = false;
|
|
6351
|
+
continue;
|
|
6352
|
+
}
|
|
6353
|
+
if (char === '"') inString = true;
|
|
6354
|
+
else if (char === "{") depth += 1;
|
|
6355
|
+
else if (char === "}") {
|
|
6356
|
+
depth -= 1;
|
|
6357
|
+
if (depth === 0) {
|
|
6358
|
+
try {
|
|
6359
|
+
const parsed = JSON.parse(trimmed.slice(start, index + 1));
|
|
6360
|
+
if (parsed !== null && typeof parsed === "object") return parsed;
|
|
6361
|
+
} catch {
|
|
6362
|
+
return void 0;
|
|
6363
|
+
}
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
}
|
|
6368
|
+
return void 0;
|
|
6369
|
+
}
|
|
6370
|
+
function coerceByJsonSchema(value, schema) {
|
|
6371
|
+
if (schema === null || schema === void 0 || typeof schema !== "object") return value;
|
|
6372
|
+
const node = schema;
|
|
6373
|
+
const branches = [
|
|
6374
|
+
...Array.isArray(node.anyOf) ? node.anyOf : [],
|
|
6375
|
+
...Array.isArray(node.allOf) ? node.allOf : []
|
|
6376
|
+
].filter((branch) => branch !== null && typeof branch === "object");
|
|
6377
|
+
const types = [];
|
|
6378
|
+
const pushTypes = (candidate) => {
|
|
6379
|
+
if (typeof candidate.type === "string") types.push(candidate.type);
|
|
6380
|
+
else if (Array.isArray(candidate.type)) types.push(...candidate.type);
|
|
6381
|
+
};
|
|
6382
|
+
pushTypes(node);
|
|
6383
|
+
for (const branch of branches) pushTypes(branch);
|
|
6384
|
+
if (types.includes("null") && (value === null || value === void 0)) return value;
|
|
6385
|
+
if ((types.includes("number") || types.includes("integer")) && typeof value === "string" && value.trim() !== "") {
|
|
6386
|
+
const numeric = Number(value);
|
|
6387
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
6388
|
+
}
|
|
6389
|
+
if (types.includes("boolean") && typeof value === "string") {
|
|
6390
|
+
const lowered = value.trim().toLowerCase();
|
|
6391
|
+
if (lowered === "true") return true;
|
|
6392
|
+
if (lowered === "false") return false;
|
|
6393
|
+
}
|
|
6394
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
6395
|
+
const properties = node.properties ?? branches.find((branch) => branch.properties)?.properties;
|
|
6396
|
+
if (properties !== void 0) {
|
|
6397
|
+
const output = {};
|
|
6398
|
+
for (const [key, child] of Object.entries(value)) {
|
|
6399
|
+
output[key] = properties[key] !== void 0 ? coerceByJsonSchema(child, properties[key]) : child;
|
|
6400
|
+
}
|
|
6401
|
+
return output;
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6404
|
+
if (types.includes("array") && Array.isArray(value) && node.items !== void 0) {
|
|
6405
|
+
return value.map((item) => coerceByJsonSchema(item, node.items));
|
|
6406
|
+
}
|
|
6407
|
+
return value;
|
|
6408
|
+
}
|
|
6283
6409
|
function modelToolFromZod(name, description, schema) {
|
|
6284
6410
|
return { name, description, inputSchema: strictJsonSchema(schema) };
|
|
6285
6411
|
}
|
|
@@ -6642,6 +6768,14 @@ var AgentLoop = class {
|
|
|
6642
6768
|
toolCalls.push({ id: collected.id, name: collected.name, input: validation.input });
|
|
6643
6769
|
continue;
|
|
6644
6770
|
}
|
|
6771
|
+
if (collected.kind === "valid") {
|
|
6772
|
+
const coerced = coerceByJsonSchema(collected.input, strictJsonSchema(definition.inputSchema));
|
|
6773
|
+
const revalidation = this.#options.runtime.validate({ ...collected, input: coerced });
|
|
6774
|
+
if (revalidation.ok) {
|
|
6775
|
+
toolCalls.push({ id: collected.id, name: collected.name, input: revalidation.input });
|
|
6776
|
+
continue;
|
|
6777
|
+
}
|
|
6778
|
+
}
|
|
6645
6779
|
const repairModelId = this.#options.fallbackModelId ?? this.#options.modelId;
|
|
6646
6780
|
const invalidOutput = collected.kind === "invalid" ? collected.rawInput : serializeToolInput(collected.input);
|
|
6647
6781
|
const structured = withStructuredOutput({
|
|
@@ -7141,7 +7275,8 @@ var ToolRuntime = class {
|
|
|
7141
7275
|
const request = {
|
|
7142
7276
|
agent: context.agent,
|
|
7143
7277
|
tool: tool.name,
|
|
7144
|
-
...tool.permissions?.(input) ?? { paths: tool.paths(input) }
|
|
7278
|
+
...tool.permissions?.(input) ?? { paths: tool.paths(input) },
|
|
7279
|
+
...tool.readOnly === true ? { readOnly: true } : {}
|
|
7145
7280
|
};
|
|
7146
7281
|
let permission = this.#permissions.decide(request);
|
|
7147
7282
|
const nonCacheableApproval = request.allowAlways === false || permission.allowAlways === false;
|
|
@@ -9214,7 +9349,9 @@ var ShellInput = z14.object({
|
|
|
9214
9349
|
args: z14.array(z14.string()),
|
|
9215
9350
|
cwd: z14.string().min(1).nullable().optional(),
|
|
9216
9351
|
timeoutMs: z14.coerce.number().int().positive().max(864e5).nullable().optional(),
|
|
9217
|
-
|
|
9352
|
+
// Accepts booleans and their string forms (weak-typed models emit "true");
|
|
9353
|
+
// kept transform-free so the schema converts to JSON Schema for providers.
|
|
9354
|
+
background: z14.union([z14.boolean(), z14.string().refine((value) => value === "true" || value === "false")]).optional()
|
|
9218
9355
|
});
|
|
9219
9356
|
function createShellTool(workspace, options = {}) {
|
|
9220
9357
|
const root = resolve11(workspace);
|
|
@@ -9230,7 +9367,7 @@ function createShellTool(workspace, options = {}) {
|
|
|
9230
9367
|
inputSchema: ShellInput,
|
|
9231
9368
|
paths: (input) => [workingDirectory(root, input.cwd ?? void 0)],
|
|
9232
9369
|
summarize: (input) => [input.command, ...input.args].join(" "),
|
|
9233
|
-
presentCall: (input) => ({ kind: "terminal", variant: "command", title: input.background ? "Starting background command" : "Running command", command: [input.command, ...input.args].join(" "), state: "running" }),
|
|
9370
|
+
presentCall: (input) => ({ kind: "terminal", variant: "command", title: backgroundFlag(input.background) ? "Starting background command" : "Running command", command: [input.command, ...input.args].join(" "), state: "running" }),
|
|
9234
9371
|
permissions: (input) => ({
|
|
9235
9372
|
paths: [workingDirectory(root, input.cwd ?? void 0)],
|
|
9236
9373
|
command: input.command,
|
|
@@ -9247,7 +9384,7 @@ function createShellTool(workspace, options = {}) {
|
|
|
9247
9384
|
} : { kind: "terminal", variant: "command", title: [input.command, ...input.args].join(" "), command: [input.command, ...input.args].join(" "), stdout: output.stdout, stderr: output.stderr, exitCode: output.exitCode, state: output.terminationReason === "cancelled" ? "cancelled" : output.exitCode === 0 ? "completed" : "failed", truncated: output.truncated },
|
|
9248
9385
|
execute: async (input, signal, context) => {
|
|
9249
9386
|
const timeoutMs = input.timeoutMs ?? defaultTimeoutMs;
|
|
9250
|
-
if (input.background
|
|
9387
|
+
if (backgroundFlag(input.background)) {
|
|
9251
9388
|
if (options.jobs === void 0) throw new Error("Background shell requires a JobRegistry");
|
|
9252
9389
|
const cancellation = new AbortController();
|
|
9253
9390
|
const job = options.jobs.create({
|
|
@@ -9497,6 +9634,9 @@ var AdaptiveOutputDecoder = class {
|
|
|
9497
9634
|
return text;
|
|
9498
9635
|
}
|
|
9499
9636
|
};
|
|
9637
|
+
function backgroundFlag(value) {
|
|
9638
|
+
return value === true || value === "true";
|
|
9639
|
+
}
|
|
9500
9640
|
function workingDirectory(root, cwd = ".") {
|
|
9501
9641
|
const candidate = resolve11(root, cwd);
|
|
9502
9642
|
const delta = relative10(root, candidate);
|
|
@@ -11325,7 +11465,7 @@ var PluginHost = class {
|
|
|
11325
11465
|
return writeFile6(allowed, data2);
|
|
11326
11466
|
}
|
|
11327
11467
|
}) }),
|
|
11328
|
-
registerCommand: (name, value) => register("command", name, [value]),
|
|
11468
|
+
registerCommand: (name, value, description) => register("command", name, [value, description]),
|
|
11329
11469
|
registerTool: (name, value) => register("tool", name, [value]),
|
|
11330
11470
|
registerHook: (name, value, options) => register("hook", name, [value, options]),
|
|
11331
11471
|
registerSkillRoot: (name, root) => {
|
|
@@ -16925,7 +17065,8 @@ import { z as z27 } from "zod";
|
|
|
16925
17065
|
import { resolve as resolve23 } from "path";
|
|
16926
17066
|
var Id = z27.string().regex(/^term-[a-f0-9-]+$/);
|
|
16927
17067
|
var OpenInput = z27.object({ cwd: z27.string().optional(), shell: z27.string().optional(), args: z27.array(z27.string()).optional(), columns: z27.coerce.number().int().min(10).max(500).optional(), rows: z27.coerce.number().int().min(2).max(300).optional() });
|
|
16928
|
-
var
|
|
17068
|
+
var OptionalBoolean = z27.union([z27.boolean(), z27.string().refine((value) => value === "true" || value === "false")]);
|
|
17069
|
+
var WriteInput2 = z27.object({ id: Id, data: z27.string().max(1e5), enter: OptionalBoolean.optional() });
|
|
16929
17070
|
var ReadInput3 = z27.object({ id: Id, cursor: z27.coerce.number().int().min(0).optional() });
|
|
16930
17071
|
var ResizeInput = z27.object({ id: Id, columns: z27.coerce.number().int().min(10).max(500), rows: z27.coerce.number().int().min(2).max(300) });
|
|
16931
17072
|
var CloseInput = z27.object({ id: Id });
|
|
@@ -16954,8 +17095,9 @@ function createTerminalTools(terminals, workspace = process.cwd()) {
|
|
|
16954
17095
|
paths: () => [],
|
|
16955
17096
|
permissions: (input) => ({ paths: [], command: input.data, args: [] }),
|
|
16956
17097
|
execute: async (input, _signal, context) => {
|
|
16957
|
-
|
|
16958
|
-
|
|
17098
|
+
const enter = input.enter === true || input.enter === "true";
|
|
17099
|
+
terminals.write(input.id, owner(context), input.data + (enter ? "\r" : ""));
|
|
17100
|
+
return { id: input.id, written: input.data.length + (enter ? 1 : 0) };
|
|
16959
17101
|
}
|
|
16960
17102
|
},
|
|
16961
17103
|
{
|
|
@@ -17832,15 +17974,16 @@ async function createProductionRuntime(options) {
|
|
|
17832
17974
|
projectPluginDirs: [join19(workspace, ".flavor", "plugins")],
|
|
17833
17975
|
config,
|
|
17834
17976
|
registrations: {
|
|
17835
|
-
command(name, handler) {
|
|
17977
|
+
command(name, handler, description) {
|
|
17836
17978
|
if (typeof handler !== "function") throw new Error(`Plugin command "${name}" must be a function.`);
|
|
17837
17979
|
if (name !== name.toLowerCase()) throw new Error(`Plugin command "${name}" must be lowercase.`);
|
|
17838
17980
|
if (MVP_COMMANDS.includes(name) || name === "ide" || pluginCommands.has(name)) {
|
|
17839
17981
|
throw new Error(`Plugin command "${name}" conflicts with a built-in or registered command.`);
|
|
17840
17982
|
}
|
|
17841
|
-
|
|
17983
|
+
const desc = typeof description === "string" && description.trim().length > 0 ? description.trim() : void 0;
|
|
17984
|
+
pluginCommands.set(name, desc === void 0 ? { handler } : { handler, description: desc });
|
|
17842
17985
|
return () => {
|
|
17843
|
-
if (pluginCommands.get(name) === handler) pluginCommands.delete(name);
|
|
17986
|
+
if (pluginCommands.get(name)?.handler === handler) pluginCommands.delete(name);
|
|
17844
17987
|
};
|
|
17845
17988
|
},
|
|
17846
17989
|
tool(name, tool) {
|
|
@@ -18937,9 +19080,9 @@ ${renderMemoryDocument(entries)}`;
|
|
|
18937
19080
|
return removed === 0 ? "No cold long-term memories to remove." : `Forgot ${removed} cold memory ${removed === 1 ? "entry" : "entries"} and removed ${filesRemoved} task ${filesRemoved === 1 ? "file" : "files"}.`;
|
|
18938
19081
|
},
|
|
18939
19082
|
finishTask: () => finalizeMemoryTask(true),
|
|
18940
|
-
pluginCommands: () => [...pluginCommands.
|
|
19083
|
+
pluginCommands: () => [...pluginCommands.entries()].map(([name, entry2]) => entry2.description === void 0 ? { name } : { name, description: entry2.description }).sort((left, right) => left.name.localeCompare(right.name)),
|
|
18941
19084
|
runPluginCommand: async (name, args, signal) => {
|
|
18942
|
-
const handler = pluginCommands.get(name);
|
|
19085
|
+
const handler = pluginCommands.get(name)?.handler;
|
|
18943
19086
|
if (handler === void 0) throw new Error(`Plugin command /${name} is no longer registered.`);
|
|
18944
19087
|
signal.throwIfAborted();
|
|
18945
19088
|
return awaitWithSignal(Promise.resolve(handler(args, { workspace, signal })), signal);
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module"; const require = createRequire(impor
|
|
|
3
3
|
import {
|
|
4
4
|
FlavorRpcServer,
|
|
5
5
|
TraceRecorder
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-G6Q2Y2A7.js";
|
|
7
7
|
import {
|
|
8
8
|
staticTaskLines
|
|
9
9
|
} from "./chunk-KKIBYDJI.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
packageVersion,
|
|
23
23
|
redactErrorText,
|
|
24
24
|
runPalBroker
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-Y5MZDG7I.js";
|
|
26
26
|
import {
|
|
27
27
|
McpServerConfigSchema,
|
|
28
28
|
McpServerNameSchema,
|
|
@@ -800,7 +800,7 @@ async function runInteractiveCli(props) {
|
|
|
800
800
|
const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
|
|
801
801
|
import("./claude-ink-ORUA7GWG.js"),
|
|
802
802
|
import("react"),
|
|
803
|
-
import("./app-
|
|
803
|
+
import("./app-Z3YWFIBB.js")
|
|
804
804
|
]);
|
|
805
805
|
const instance = await render(createElement(
|
|
806
806
|
AlternateScreen,
|