newmark-agent 0.5.7 → 0.5.9
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.js +3 -3
- package/dist/cli.js +1 -1
- package/dist/conversation-utility-host.bundle.cjs +830 -595
- package/dist/core/agent.d.ts +1 -1
- package/dist/core/agent.js +57 -5
- package/dist/core/agentKernelRunner.js +43 -8
- package/dist/core/emptyResponseRetry.d.ts +16 -0
- package/dist/core/emptyResponseRetry.js +25 -0
- package/dist/core/memoryLab.d.ts +17 -0
- package/dist/core/memoryLab.js +43 -1
- package/dist/core/terminalOutputBuffer.d.ts +24 -0
- package/dist/core/terminalOutputBuffer.js +92 -0
- package/dist/core/toolPolicy.d.ts +1 -0
- package/dist/core/toolPolicy.js +16 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/llm/provider.d.ts +4 -4
- package/dist/llm/provider.js +55 -21
- package/dist/main.js +12 -3
- package/dist/providers/chat-completions.adapter.js +17 -4
- package/dist/providers/provider-events.d.ts +7 -0
- package/dist/providers/provider-events.js +40 -0
- package/dist/providers/responses.adapter.js +23 -9
- package/dist/tools/index.js +42 -10
- package/dist/ui/index.html +73 -19
- package/dist/wsl-agent-host.bundle.cjs +830 -595
- package/package.json +3 -1
|
@@ -4281,6 +4281,234 @@ var require_jpeg_js = __commonJS({
|
|
|
4281
4281
|
}
|
|
4282
4282
|
});
|
|
4283
4283
|
|
|
4284
|
+
// src/core/flow.ts
|
|
4285
|
+
var fs6, path7, FlowEngine;
|
|
4286
|
+
var init_flow = __esm({
|
|
4287
|
+
"src/core/flow.ts"() {
|
|
4288
|
+
"use strict";
|
|
4289
|
+
fs6 = __toESM(require("fs"));
|
|
4290
|
+
path7 = __toESM(require("path"));
|
|
4291
|
+
FlowEngine = class _FlowEngine {
|
|
4292
|
+
static load(dir, name50) {
|
|
4293
|
+
const p = path7.join(dir, `${name50}.Flow.json`);
|
|
4294
|
+
try {
|
|
4295
|
+
return JSON.parse(fs6.readFileSync(p, "utf-8").replace(/^\uFEFF/, ""));
|
|
4296
|
+
} catch {
|
|
4297
|
+
return null;
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
static save(dir, workflow) {
|
|
4301
|
+
const p = path7.join(dir, `${workflow.name}.Flow.json`);
|
|
4302
|
+
fs6.writeFileSync(p, JSON.stringify(workflow, null, 2), "utf-8");
|
|
4303
|
+
}
|
|
4304
|
+
static delete(dir, name50) {
|
|
4305
|
+
const p = path7.join(dir, `${name50}.Flow.json`);
|
|
4306
|
+
if (fs6.existsSync(p)) fs6.unlinkSync(p);
|
|
4307
|
+
}
|
|
4308
|
+
static listAll(dir) {
|
|
4309
|
+
try {
|
|
4310
|
+
return fs6.readdirSync(dir).filter((f3) => f3.endsWith(".Flow.json")).map((f3) => f3.replace(".Flow.json", "")).sort();
|
|
4311
|
+
} catch {
|
|
4312
|
+
return [];
|
|
4313
|
+
}
|
|
4314
|
+
}
|
|
4315
|
+
static describeWorkflow(wf) {
|
|
4316
|
+
const comps = [...wf.components].sort((a3, b2) => a3.id - b2.id);
|
|
4317
|
+
if (comps.length === 0) return "";
|
|
4318
|
+
const parts = [];
|
|
4319
|
+
for (const c3 of comps) {
|
|
4320
|
+
if (c3.type === "dialog") {
|
|
4321
|
+
parts.push(c3.mode.charAt(0).toUpperCase() + c3.mode.slice(1));
|
|
4322
|
+
} else {
|
|
4323
|
+
const label = c3.prompt.replace(/\{#prompt#\}/g, "<i>").replace(/\n/g, " ").slice(0, 22);
|
|
4324
|
+
parts.push(`?${label}?`);
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4327
|
+
return parts.join(" \u2192 ");
|
|
4328
|
+
}
|
|
4329
|
+
static validate(wf) {
|
|
4330
|
+
const errors = [];
|
|
4331
|
+
if (!wf.components || wf.components.length === 0) {
|
|
4332
|
+
errors.push({ message: "No components defined." });
|
|
4333
|
+
return errors;
|
|
4334
|
+
}
|
|
4335
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4336
|
+
for (const c3 of wf.components) {
|
|
4337
|
+
if (typeof c3.id === "number") ids.add(c3.id);
|
|
4338
|
+
}
|
|
4339
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
4340
|
+
for (const c3 of wf.components) {
|
|
4341
|
+
if (seenIds.has(c3.id)) {
|
|
4342
|
+
errors.push({ componentId: c3.id, message: `Duplicate component ID: ${c3.id}` });
|
|
4343
|
+
}
|
|
4344
|
+
seenIds.add(c3.id);
|
|
4345
|
+
if (c3.type === "dialog") {
|
|
4346
|
+
const mode = c3.mode.toLowerCase();
|
|
4347
|
+
if (!["build", "plan", "goal"].includes(mode)) {
|
|
4348
|
+
errors.push({ componentId: c3.id, message: `Invalid dialog mode '${c3.mode}' (must be build/plan/goal)` });
|
|
4349
|
+
}
|
|
4350
|
+
} else if (c3.type === "logic") {
|
|
4351
|
+
if (!ids.has(c3.goto_true)) {
|
|
4352
|
+
errors.push({ componentId: c3.id, message: `goto_true=${c3.goto_true} not found` });
|
|
4353
|
+
}
|
|
4354
|
+
if (!ids.has(c3.goto_false)) {
|
|
4355
|
+
errors.push({ componentId: c3.id, message: `goto_false=${c3.goto_false} not found` });
|
|
4356
|
+
}
|
|
4357
|
+
} else {
|
|
4358
|
+
errors.push({ componentId: c3.id, message: `Unknown component type '${c3.type}'` });
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
return errors;
|
|
4362
|
+
}
|
|
4363
|
+
static detectCycles(wf) {
|
|
4364
|
+
const comps = [...wf.components].sort((a3, b2) => a3.id - b2.id);
|
|
4365
|
+
if (comps.length === 0) return [];
|
|
4366
|
+
const idToIdx = /* @__PURE__ */ new Map();
|
|
4367
|
+
comps.forEach((c3, i4) => idToIdx.set(c3.id, i4));
|
|
4368
|
+
const graph = /* @__PURE__ */ new Map();
|
|
4369
|
+
for (let index = 0; index < comps.length; index++) {
|
|
4370
|
+
const c3 = comps[index];
|
|
4371
|
+
graph.set(c3.id, []);
|
|
4372
|
+
if (c3.type === "dialog") {
|
|
4373
|
+
const next = comps[index + 1];
|
|
4374
|
+
if (next) graph.get(c3.id).push(next.id);
|
|
4375
|
+
} else if (c3.type === "logic") {
|
|
4376
|
+
if (idToIdx.has(c3.goto_true)) graph.get(c3.id).push(c3.goto_true);
|
|
4377
|
+
if (idToIdx.has(c3.goto_false)) graph.get(c3.id).push(c3.goto_false);
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
const WHITE = 0, GRAY = 1, BLACK = 2;
|
|
4381
|
+
const color2 = /* @__PURE__ */ new Map();
|
|
4382
|
+
for (const c3 of comps) color2.set(c3.id, WHITE);
|
|
4383
|
+
const cycles = [];
|
|
4384
|
+
const dfsPath = [];
|
|
4385
|
+
function dfs(node) {
|
|
4386
|
+
color2.set(node, GRAY);
|
|
4387
|
+
dfsPath.push(node);
|
|
4388
|
+
for (const nb of graph.get(node) || []) {
|
|
4389
|
+
if (!color2.has(nb)) continue;
|
|
4390
|
+
if (color2.get(nb) === GRAY) {
|
|
4391
|
+
const start = dfsPath.indexOf(nb);
|
|
4392
|
+
cycles.push(dfsPath.slice(start));
|
|
4393
|
+
} else if (color2.get(nb) === WHITE) {
|
|
4394
|
+
dfs(nb);
|
|
4395
|
+
}
|
|
4396
|
+
}
|
|
4397
|
+
dfsPath.pop();
|
|
4398
|
+
color2.set(node, BLACK);
|
|
4399
|
+
}
|
|
4400
|
+
for (const c3 of comps) {
|
|
4401
|
+
if (color2.get(c3.id) === WHITE) dfs(c3.id);
|
|
4402
|
+
}
|
|
4403
|
+
const unique2 = [];
|
|
4404
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4405
|
+
for (const cyc of cycles) {
|
|
4406
|
+
const key3 = [...cyc].sort((a3, b2) => a3 - b2).join(",");
|
|
4407
|
+
if (!seen.has(key3)) {
|
|
4408
|
+
seen.add(key3);
|
|
4409
|
+
unique2.push(cyc);
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
return unique2;
|
|
4413
|
+
}
|
|
4414
|
+
static getCycleWarnings(wf) {
|
|
4415
|
+
const cycles = _FlowEngine.detectCycles(wf);
|
|
4416
|
+
return cycles.map(
|
|
4417
|
+
(cyc) => `[!] Potential logic cycle in '${wf.name}': components [${cyc.join(", ")}] can form a loop.`
|
|
4418
|
+
);
|
|
4419
|
+
}
|
|
4420
|
+
static findWorkflow(name50, dir) {
|
|
4421
|
+
const names = _FlowEngine.listAll(dir);
|
|
4422
|
+
if (names.length === 0) return null;
|
|
4423
|
+
if (names.includes(name50)) return name50;
|
|
4424
|
+
const nameLower = name50.toLowerCase();
|
|
4425
|
+
for (const n3 of names) {
|
|
4426
|
+
if (n3.toLowerCase() === nameLower) return n3;
|
|
4427
|
+
}
|
|
4428
|
+
for (const n3 of names) {
|
|
4429
|
+
if (n3.toLowerCase().includes(nameLower)) return n3;
|
|
4430
|
+
}
|
|
4431
|
+
return null;
|
|
4432
|
+
}
|
|
4433
|
+
static autoTrigger(text, dir) {
|
|
4434
|
+
const names = _FlowEngine.listAll(dir);
|
|
4435
|
+
const textLower = text.toLowerCase();
|
|
4436
|
+
const results = [];
|
|
4437
|
+
for (const n3 of names) {
|
|
4438
|
+
const nLower = n3.toLowerCase();
|
|
4439
|
+
if (nLower === textLower) {
|
|
4440
|
+
results.push({ name: n3, score: 1 });
|
|
4441
|
+
} else if (textLower.includes(nLower) || nLower.includes(textLower)) {
|
|
4442
|
+
const longer = nLower.length > textLower.length ? nLower : textLower;
|
|
4443
|
+
const shorter = nLower.length > textLower.length ? textLower : nLower;
|
|
4444
|
+
const ratio = shorter.length / Math.max(longer.length, 1);
|
|
4445
|
+
results.push({ name: n3, score: 0.5 + 0.4 * Math.min(ratio, 1) });
|
|
4446
|
+
} else {
|
|
4447
|
+
const words = nLower.split(/[\s_-]+/).filter((w) => w.length > 0);
|
|
4448
|
+
const matchCount = words.filter((w) => textLower.includes(w)).length;
|
|
4449
|
+
if (matchCount > 0) {
|
|
4450
|
+
results.push({ name: n3, score: 0.2 + 0.6 * (matchCount / Math.max(words.length, 1)) });
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
results.sort((a3, b2) => b2.score - a3.score);
|
|
4455
|
+
return results;
|
|
4456
|
+
}
|
|
4457
|
+
static buildDialogPrompt(component, userInput) {
|
|
4458
|
+
const raw = component.prompt;
|
|
4459
|
+
const ui = userInput || "";
|
|
4460
|
+
const hasPlaceholder = raw.includes("{#prompt#}");
|
|
4461
|
+
if (component.mode === "plan" && ui) {
|
|
4462
|
+
if (hasPlaceholder) {
|
|
4463
|
+
return raw.replace(/\{#prompt#\}/g, ui);
|
|
4464
|
+
} else {
|
|
4465
|
+
return `Plan: ${raw}
|
|
4466
|
+
User context: ${ui}`;
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
return hasPlaceholder ? raw.replace(/\{#prompt#\}/g, ui) : raw;
|
|
4470
|
+
}
|
|
4471
|
+
static generateSequence(workflow, start, input) {
|
|
4472
|
+
const orderedComponents = [...workflow.components];
|
|
4473
|
+
const seq = [];
|
|
4474
|
+
let cur = start;
|
|
4475
|
+
let count = 0;
|
|
4476
|
+
const max2 = workflow.components.length + 10;
|
|
4477
|
+
while (count < max2) {
|
|
4478
|
+
count++;
|
|
4479
|
+
const comp = workflow.components.find((c3) => c3.id === cur);
|
|
4480
|
+
if (!comp) break;
|
|
4481
|
+
if (comp.type === "dialog") {
|
|
4482
|
+
const expanded = _FlowEngine.buildDialogPrompt(comp, input);
|
|
4483
|
+
seq.push({ id: comp.id, mode: comp.mode, prompt: expanded, isLogic: false });
|
|
4484
|
+
const index = orderedComponents.findIndex((item) => item.id === comp.id);
|
|
4485
|
+
if (index < 0 || index + 1 >= orderedComponents.length) break;
|
|
4486
|
+
cur = orderedComponents[index + 1].id;
|
|
4487
|
+
} else {
|
|
4488
|
+
seq.push({
|
|
4489
|
+
id: comp.id,
|
|
4490
|
+
prompt: comp.prompt.replace(/\{#prompt#\}/g, input),
|
|
4491
|
+
isLogic: true,
|
|
4492
|
+
gotoTrue: comp.goto_true,
|
|
4493
|
+
gotoFalse: comp.goto_false
|
|
4494
|
+
});
|
|
4495
|
+
break;
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4498
|
+
return seq;
|
|
4499
|
+
}
|
|
4500
|
+
static resolveGoto(workflow, cur, cond) {
|
|
4501
|
+
const comp = workflow.components.find((c3) => c3.id === cur);
|
|
4502
|
+
if (comp?.type === "logic") {
|
|
4503
|
+
return cond ? comp.goto_true : comp.goto_false;
|
|
4504
|
+
}
|
|
4505
|
+
const index = workflow.components.findIndex((component) => component.id === cur);
|
|
4506
|
+
return index >= 0 && index + 1 < workflow.components.length ? workflow.components[index + 1].id : -1;
|
|
4507
|
+
}
|
|
4508
|
+
};
|
|
4509
|
+
}
|
|
4510
|
+
});
|
|
4511
|
+
|
|
4284
4512
|
// node_modules/regenerator-runtime/runtime.js
|
|
4285
4513
|
var require_runtime = __commonJS({
|
|
4286
4514
|
"node_modules/regenerator-runtime/runtime.js"(exports2, module2) {
|
|
@@ -326027,234 +326255,6 @@ var require_readability = __commonJS({
|
|
|
326027
326255
|
}
|
|
326028
326256
|
});
|
|
326029
326257
|
|
|
326030
|
-
// src/core/flow.ts
|
|
326031
|
-
var fs16, path18, FlowEngine;
|
|
326032
|
-
var init_flow = __esm({
|
|
326033
|
-
"src/core/flow.ts"() {
|
|
326034
|
-
"use strict";
|
|
326035
|
-
fs16 = __toESM(require("fs"));
|
|
326036
|
-
path18 = __toESM(require("path"));
|
|
326037
|
-
FlowEngine = class _FlowEngine {
|
|
326038
|
-
static load(dir, name50) {
|
|
326039
|
-
const p = path18.join(dir, `${name50}.Flow.json`);
|
|
326040
|
-
try {
|
|
326041
|
-
return JSON.parse(fs16.readFileSync(p, "utf-8").replace(/^\uFEFF/, ""));
|
|
326042
|
-
} catch {
|
|
326043
|
-
return null;
|
|
326044
|
-
}
|
|
326045
|
-
}
|
|
326046
|
-
static save(dir, workflow) {
|
|
326047
|
-
const p = path18.join(dir, `${workflow.name}.Flow.json`);
|
|
326048
|
-
fs16.writeFileSync(p, JSON.stringify(workflow, null, 2), "utf-8");
|
|
326049
|
-
}
|
|
326050
|
-
static delete(dir, name50) {
|
|
326051
|
-
const p = path18.join(dir, `${name50}.Flow.json`);
|
|
326052
|
-
if (fs16.existsSync(p)) fs16.unlinkSync(p);
|
|
326053
|
-
}
|
|
326054
|
-
static listAll(dir) {
|
|
326055
|
-
try {
|
|
326056
|
-
return fs16.readdirSync(dir).filter((f3) => f3.endsWith(".Flow.json")).map((f3) => f3.replace(".Flow.json", "")).sort();
|
|
326057
|
-
} catch {
|
|
326058
|
-
return [];
|
|
326059
|
-
}
|
|
326060
|
-
}
|
|
326061
|
-
static describeWorkflow(wf) {
|
|
326062
|
-
const comps = [...wf.components].sort((a3, b2) => a3.id - b2.id);
|
|
326063
|
-
if (comps.length === 0) return "";
|
|
326064
|
-
const parts = [];
|
|
326065
|
-
for (const c3 of comps) {
|
|
326066
|
-
if (c3.type === "dialog") {
|
|
326067
|
-
parts.push(c3.mode.charAt(0).toUpperCase() + c3.mode.slice(1));
|
|
326068
|
-
} else {
|
|
326069
|
-
const label = c3.prompt.replace(/\{#prompt#\}/g, "<i>").replace(/\n/g, " ").slice(0, 22);
|
|
326070
|
-
parts.push(`?${label}?`);
|
|
326071
|
-
}
|
|
326072
|
-
}
|
|
326073
|
-
return parts.join(" \u2192 ");
|
|
326074
|
-
}
|
|
326075
|
-
static validate(wf) {
|
|
326076
|
-
const errors = [];
|
|
326077
|
-
if (!wf.components || wf.components.length === 0) {
|
|
326078
|
-
errors.push({ message: "No components defined." });
|
|
326079
|
-
return errors;
|
|
326080
|
-
}
|
|
326081
|
-
const ids = /* @__PURE__ */ new Set();
|
|
326082
|
-
for (const c3 of wf.components) {
|
|
326083
|
-
if (typeof c3.id === "number") ids.add(c3.id);
|
|
326084
|
-
}
|
|
326085
|
-
const seenIds = /* @__PURE__ */ new Set();
|
|
326086
|
-
for (const c3 of wf.components) {
|
|
326087
|
-
if (seenIds.has(c3.id)) {
|
|
326088
|
-
errors.push({ componentId: c3.id, message: `Duplicate component ID: ${c3.id}` });
|
|
326089
|
-
}
|
|
326090
|
-
seenIds.add(c3.id);
|
|
326091
|
-
if (c3.type === "dialog") {
|
|
326092
|
-
const mode = c3.mode.toLowerCase();
|
|
326093
|
-
if (!["build", "plan", "goal"].includes(mode)) {
|
|
326094
|
-
errors.push({ componentId: c3.id, message: `Invalid dialog mode '${c3.mode}' (must be build/plan/goal)` });
|
|
326095
|
-
}
|
|
326096
|
-
} else if (c3.type === "logic") {
|
|
326097
|
-
if (!ids.has(c3.goto_true)) {
|
|
326098
|
-
errors.push({ componentId: c3.id, message: `goto_true=${c3.goto_true} not found` });
|
|
326099
|
-
}
|
|
326100
|
-
if (!ids.has(c3.goto_false)) {
|
|
326101
|
-
errors.push({ componentId: c3.id, message: `goto_false=${c3.goto_false} not found` });
|
|
326102
|
-
}
|
|
326103
|
-
} else {
|
|
326104
|
-
errors.push({ componentId: c3.id, message: `Unknown component type '${c3.type}'` });
|
|
326105
|
-
}
|
|
326106
|
-
}
|
|
326107
|
-
return errors;
|
|
326108
|
-
}
|
|
326109
|
-
static detectCycles(wf) {
|
|
326110
|
-
const comps = [...wf.components].sort((a3, b2) => a3.id - b2.id);
|
|
326111
|
-
if (comps.length === 0) return [];
|
|
326112
|
-
const idToIdx = /* @__PURE__ */ new Map();
|
|
326113
|
-
comps.forEach((c3, i4) => idToIdx.set(c3.id, i4));
|
|
326114
|
-
const graph = /* @__PURE__ */ new Map();
|
|
326115
|
-
for (let index = 0; index < comps.length; index++) {
|
|
326116
|
-
const c3 = comps[index];
|
|
326117
|
-
graph.set(c3.id, []);
|
|
326118
|
-
if (c3.type === "dialog") {
|
|
326119
|
-
const next = comps[index + 1];
|
|
326120
|
-
if (next) graph.get(c3.id).push(next.id);
|
|
326121
|
-
} else if (c3.type === "logic") {
|
|
326122
|
-
if (idToIdx.has(c3.goto_true)) graph.get(c3.id).push(c3.goto_true);
|
|
326123
|
-
if (idToIdx.has(c3.goto_false)) graph.get(c3.id).push(c3.goto_false);
|
|
326124
|
-
}
|
|
326125
|
-
}
|
|
326126
|
-
const WHITE = 0, GRAY = 1, BLACK = 2;
|
|
326127
|
-
const color2 = /* @__PURE__ */ new Map();
|
|
326128
|
-
for (const c3 of comps) color2.set(c3.id, WHITE);
|
|
326129
|
-
const cycles = [];
|
|
326130
|
-
const dfsPath = [];
|
|
326131
|
-
function dfs(node) {
|
|
326132
|
-
color2.set(node, GRAY);
|
|
326133
|
-
dfsPath.push(node);
|
|
326134
|
-
for (const nb of graph.get(node) || []) {
|
|
326135
|
-
if (!color2.has(nb)) continue;
|
|
326136
|
-
if (color2.get(nb) === GRAY) {
|
|
326137
|
-
const start = dfsPath.indexOf(nb);
|
|
326138
|
-
cycles.push(dfsPath.slice(start));
|
|
326139
|
-
} else if (color2.get(nb) === WHITE) {
|
|
326140
|
-
dfs(nb);
|
|
326141
|
-
}
|
|
326142
|
-
}
|
|
326143
|
-
dfsPath.pop();
|
|
326144
|
-
color2.set(node, BLACK);
|
|
326145
|
-
}
|
|
326146
|
-
for (const c3 of comps) {
|
|
326147
|
-
if (color2.get(c3.id) === WHITE) dfs(c3.id);
|
|
326148
|
-
}
|
|
326149
|
-
const unique2 = [];
|
|
326150
|
-
const seen = /* @__PURE__ */ new Set();
|
|
326151
|
-
for (const cyc of cycles) {
|
|
326152
|
-
const key3 = [...cyc].sort((a3, b2) => a3 - b2).join(",");
|
|
326153
|
-
if (!seen.has(key3)) {
|
|
326154
|
-
seen.add(key3);
|
|
326155
|
-
unique2.push(cyc);
|
|
326156
|
-
}
|
|
326157
|
-
}
|
|
326158
|
-
return unique2;
|
|
326159
|
-
}
|
|
326160
|
-
static getCycleWarnings(wf) {
|
|
326161
|
-
const cycles = _FlowEngine.detectCycles(wf);
|
|
326162
|
-
return cycles.map(
|
|
326163
|
-
(cyc) => `[!] Potential logic cycle in '${wf.name}': components [${cyc.join(", ")}] can form a loop.`
|
|
326164
|
-
);
|
|
326165
|
-
}
|
|
326166
|
-
static findWorkflow(name50, dir) {
|
|
326167
|
-
const names = _FlowEngine.listAll(dir);
|
|
326168
|
-
if (names.length === 0) return null;
|
|
326169
|
-
if (names.includes(name50)) return name50;
|
|
326170
|
-
const nameLower = name50.toLowerCase();
|
|
326171
|
-
for (const n3 of names) {
|
|
326172
|
-
if (n3.toLowerCase() === nameLower) return n3;
|
|
326173
|
-
}
|
|
326174
|
-
for (const n3 of names) {
|
|
326175
|
-
if (n3.toLowerCase().includes(nameLower)) return n3;
|
|
326176
|
-
}
|
|
326177
|
-
return null;
|
|
326178
|
-
}
|
|
326179
|
-
static autoTrigger(text, dir) {
|
|
326180
|
-
const names = _FlowEngine.listAll(dir);
|
|
326181
|
-
const textLower = text.toLowerCase();
|
|
326182
|
-
const results = [];
|
|
326183
|
-
for (const n3 of names) {
|
|
326184
|
-
const nLower = n3.toLowerCase();
|
|
326185
|
-
if (nLower === textLower) {
|
|
326186
|
-
results.push({ name: n3, score: 1 });
|
|
326187
|
-
} else if (textLower.includes(nLower) || nLower.includes(textLower)) {
|
|
326188
|
-
const longer = nLower.length > textLower.length ? nLower : textLower;
|
|
326189
|
-
const shorter = nLower.length > textLower.length ? textLower : nLower;
|
|
326190
|
-
const ratio = shorter.length / Math.max(longer.length, 1);
|
|
326191
|
-
results.push({ name: n3, score: 0.5 + 0.4 * Math.min(ratio, 1) });
|
|
326192
|
-
} else {
|
|
326193
|
-
const words = nLower.split(/[\s_-]+/).filter((w) => w.length > 0);
|
|
326194
|
-
const matchCount = words.filter((w) => textLower.includes(w)).length;
|
|
326195
|
-
if (matchCount > 0) {
|
|
326196
|
-
results.push({ name: n3, score: 0.2 + 0.6 * (matchCount / Math.max(words.length, 1)) });
|
|
326197
|
-
}
|
|
326198
|
-
}
|
|
326199
|
-
}
|
|
326200
|
-
results.sort((a3, b2) => b2.score - a3.score);
|
|
326201
|
-
return results;
|
|
326202
|
-
}
|
|
326203
|
-
static buildDialogPrompt(component, userInput) {
|
|
326204
|
-
const raw = component.prompt;
|
|
326205
|
-
const ui = userInput || "";
|
|
326206
|
-
const hasPlaceholder = raw.includes("{#prompt#}");
|
|
326207
|
-
if (component.mode === "plan" && ui) {
|
|
326208
|
-
if (hasPlaceholder) {
|
|
326209
|
-
return raw.replace(/\{#prompt#\}/g, ui);
|
|
326210
|
-
} else {
|
|
326211
|
-
return `Plan: ${raw}
|
|
326212
|
-
User context: ${ui}`;
|
|
326213
|
-
}
|
|
326214
|
-
}
|
|
326215
|
-
return hasPlaceholder ? raw.replace(/\{#prompt#\}/g, ui) : raw;
|
|
326216
|
-
}
|
|
326217
|
-
static generateSequence(workflow, start, input) {
|
|
326218
|
-
const orderedComponents = [...workflow.components];
|
|
326219
|
-
const seq = [];
|
|
326220
|
-
let cur = start;
|
|
326221
|
-
let count = 0;
|
|
326222
|
-
const max2 = workflow.components.length + 10;
|
|
326223
|
-
while (count < max2) {
|
|
326224
|
-
count++;
|
|
326225
|
-
const comp = workflow.components.find((c3) => c3.id === cur);
|
|
326226
|
-
if (!comp) break;
|
|
326227
|
-
if (comp.type === "dialog") {
|
|
326228
|
-
const expanded = _FlowEngine.buildDialogPrompt(comp, input);
|
|
326229
|
-
seq.push({ id: comp.id, mode: comp.mode, prompt: expanded, isLogic: false });
|
|
326230
|
-
const index = orderedComponents.findIndex((item) => item.id === comp.id);
|
|
326231
|
-
if (index < 0 || index + 1 >= orderedComponents.length) break;
|
|
326232
|
-
cur = orderedComponents[index + 1].id;
|
|
326233
|
-
} else {
|
|
326234
|
-
seq.push({
|
|
326235
|
-
id: comp.id,
|
|
326236
|
-
prompt: comp.prompt.replace(/\{#prompt#\}/g, input),
|
|
326237
|
-
isLogic: true,
|
|
326238
|
-
gotoTrue: comp.goto_true,
|
|
326239
|
-
gotoFalse: comp.goto_false
|
|
326240
|
-
});
|
|
326241
|
-
break;
|
|
326242
|
-
}
|
|
326243
|
-
}
|
|
326244
|
-
return seq;
|
|
326245
|
-
}
|
|
326246
|
-
static resolveGoto(workflow, cur, cond) {
|
|
326247
|
-
const comp = workflow.components.find((c3) => c3.id === cur);
|
|
326248
|
-
if (comp?.type === "logic") {
|
|
326249
|
-
return cond ? comp.goto_true : comp.goto_false;
|
|
326250
|
-
}
|
|
326251
|
-
const index = workflow.components.findIndex((component) => component.id === cur);
|
|
326252
|
-
return index >= 0 && index + 1 < workflow.components.length ? workflow.components[index + 1].id : -1;
|
|
326253
|
-
}
|
|
326254
|
-
};
|
|
326255
|
-
}
|
|
326256
|
-
});
|
|
326257
|
-
|
|
326258
326258
|
// src/core/agentKernel/agent-loop.ts
|
|
326259
326259
|
async function runAgentLoop(prompts, config, signal) {
|
|
326260
326260
|
throwIfAborted3(signal);
|
|
@@ -328709,6 +328709,30 @@ function parseProviderSse(raw) {
|
|
|
328709
328709
|
}
|
|
328710
328710
|
return events;
|
|
328711
328711
|
}
|
|
328712
|
+
function assembleCompatibleToolArguments(parts) {
|
|
328713
|
+
const nonEmpty = (parts || []).map(String).filter((part) => part && part !== "null");
|
|
328714
|
+
if (!nonEmpty.length) return "{}";
|
|
328715
|
+
const isJsonObject = (value) => {
|
|
328716
|
+
try {
|
|
328717
|
+
const parsed = JSON.parse(value);
|
|
328718
|
+
return !!parsed && typeof parsed === "object" && !Array.isArray(parsed);
|
|
328719
|
+
} catch {
|
|
328720
|
+
return false;
|
|
328721
|
+
}
|
|
328722
|
+
};
|
|
328723
|
+
const incremental = nonEmpty.join("");
|
|
328724
|
+
if (isJsonObject(incremental)) return incremental;
|
|
328725
|
+
let compatible = "";
|
|
328726
|
+
for (const incoming of nonEmpty) {
|
|
328727
|
+
if (!compatible) compatible = incoming;
|
|
328728
|
+
else if (incoming === compatible) continue;
|
|
328729
|
+
else if (incoming.startsWith(compatible)) compatible = incoming;
|
|
328730
|
+
else if (compatible.startsWith(incoming)) continue;
|
|
328731
|
+
else compatible += incoming;
|
|
328732
|
+
}
|
|
328733
|
+
if (isJsonObject(compatible)) return compatible;
|
|
328734
|
+
return [...nonEmpty].reverse().find(isJsonObject) || compatible;
|
|
328735
|
+
}
|
|
328712
328736
|
function isContentPolicyBlocked(json) {
|
|
328713
328737
|
const choices = Array.isArray(json.choices) ? json.choices : [];
|
|
328714
328738
|
const choice = choices[0] || {};
|
|
@@ -328937,6 +328961,8 @@ var ChatCompletionsAdapter = class {
|
|
|
328937
328961
|
let contentPolicyBlocked = false;
|
|
328938
328962
|
let emittedContent = false;
|
|
328939
328963
|
let emittedTool = false;
|
|
328964
|
+
let emittedReasoning = false;
|
|
328965
|
+
let explicitCompletion = false;
|
|
328940
328966
|
try {
|
|
328941
328967
|
while (true) {
|
|
328942
328968
|
const { done, value } = await readProviderStreamChunk(reader, signal);
|
|
@@ -328948,7 +328974,10 @@ var ChatCompletionsAdapter = class {
|
|
|
328948
328974
|
const trimmed = line.trim();
|
|
328949
328975
|
if (!trimmed.startsWith("data: ")) continue;
|
|
328950
328976
|
const data = trimmed.slice(6);
|
|
328951
|
-
if (data === "[DONE]")
|
|
328977
|
+
if (data === "[DONE]") {
|
|
328978
|
+
explicitCompletion = true;
|
|
328979
|
+
continue;
|
|
328980
|
+
}
|
|
328952
328981
|
let json;
|
|
328953
328982
|
try {
|
|
328954
328983
|
json = JSON.parse(data);
|
|
@@ -328961,11 +328990,16 @@ var ChatCompletionsAdapter = class {
|
|
|
328961
328990
|
}
|
|
328962
328991
|
if (isContentPolicyBlocked(json)) contentPolicyBlocked = true;
|
|
328963
328992
|
const choices = Array.isArray(json.choices) ? json.choices : [];
|
|
328964
|
-
const
|
|
328993
|
+
const choice = choices[0];
|
|
328994
|
+
if (choice?.finish_reason !== void 0 && choice.finish_reason !== null) explicitCompletion = true;
|
|
328995
|
+
const delta = choice?.delta;
|
|
328965
328996
|
if (!delta) continue;
|
|
328966
328997
|
if (delta.reasoning_content) {
|
|
328967
328998
|
const reasoning = this.extractText(delta.reasoning_content);
|
|
328968
|
-
if (reasoning)
|
|
328999
|
+
if (reasoning) {
|
|
329000
|
+
emittedReasoning = true;
|
|
329001
|
+
yield { type: "reasoning.summary.delta", delta: reasoning };
|
|
329002
|
+
}
|
|
328969
329003
|
}
|
|
328970
329004
|
const textDelta = this.extractText(delta.content);
|
|
328971
329005
|
if (textDelta) {
|
|
@@ -329010,13 +329044,17 @@ var ChatCompletionsAdapter = class {
|
|
|
329010
329044
|
type: "tool_call.completed",
|
|
329011
329045
|
id: currentToolCall.id,
|
|
329012
329046
|
name: currentToolCall.name,
|
|
329013
|
-
arguments: currentToolCall.argumentParts
|
|
329047
|
+
arguments: assembleCompatibleToolArguments(currentToolCall.argumentParts)
|
|
329014
329048
|
};
|
|
329015
329049
|
}
|
|
329016
329050
|
} else if (!emittedContent && !emittedTool && contentPolicyBlocked) {
|
|
329017
329051
|
yield { type: "response.failed", error: "[Error] Content policy refusal (content_filter)." };
|
|
329018
329052
|
return;
|
|
329019
329053
|
}
|
|
329054
|
+
if (!explicitCompletion && !emittedContent && !emittedTool && !emittedReasoning) {
|
|
329055
|
+
yield { type: "response.failed", error: "[LLM Error] Chat stream ended before an explicit completion." };
|
|
329056
|
+
return;
|
|
329057
|
+
}
|
|
329020
329058
|
yield { type: "response.completed" };
|
|
329021
329059
|
} finally {
|
|
329022
329060
|
reader.releaseLock();
|
|
@@ -329213,6 +329251,7 @@ var ResponsesAdapter = class {
|
|
|
329213
329251
|
const key3 = `${String(payload.item_id || "")}:${String(payload.summary_index || 0)}`;
|
|
329214
329252
|
const delta = this.extractText(payload.delta);
|
|
329215
329253
|
if (delta) {
|
|
329254
|
+
emittedContent = true;
|
|
329216
329255
|
reasoningSummaries.set(key3, (reasoningSummaries.get(key3) || "") + delta);
|
|
329217
329256
|
yield { type: "reasoning.summary.delta", delta };
|
|
329218
329257
|
}
|
|
@@ -329243,7 +329282,7 @@ var ResponsesAdapter = class {
|
|
|
329243
329282
|
calls.set(key3, {
|
|
329244
329283
|
id: String(item.call_id || item.id || key3),
|
|
329245
329284
|
name: String(item.name || ""),
|
|
329246
|
-
|
|
329285
|
+
argumentParts: item.arguments ? [String(item.arguments)] : [],
|
|
329247
329286
|
emitted: false
|
|
329248
329287
|
});
|
|
329249
329288
|
}
|
|
@@ -329251,9 +329290,9 @@ var ResponsesAdapter = class {
|
|
|
329251
329290
|
}
|
|
329252
329291
|
if (eventType === "response.function_call_arguments.delta") {
|
|
329253
329292
|
const key3 = String(payload.item_id || payload.call_id || payload.output_index || "");
|
|
329254
|
-
const call = calls.get(key3) || { id: String(payload.call_id || key3), name: String(payload.name || ""),
|
|
329293
|
+
const call = calls.get(key3) || { id: String(payload.call_id || key3), name: String(payload.name || ""), argumentParts: [], emitted: false };
|
|
329255
329294
|
const delta = String(payload.delta || "");
|
|
329256
|
-
call.
|
|
329295
|
+
if (delta) call.argumentParts.push(delta);
|
|
329257
329296
|
calls.set(key3, call);
|
|
329258
329297
|
yield { type: "tool_call.arguments.delta", id: call.id, delta };
|
|
329259
329298
|
continue;
|
|
@@ -329265,19 +329304,20 @@ var ResponsesAdapter = class {
|
|
|
329265
329304
|
const call = calls.get(key3) || {
|
|
329266
329305
|
id: String(item.call_id || item.id || key3),
|
|
329267
329306
|
name: String(item.name || ""),
|
|
329268
|
-
|
|
329307
|
+
argumentParts: item.arguments ? [String(item.arguments)] : [],
|
|
329269
329308
|
emitted: false
|
|
329270
329309
|
};
|
|
329271
329310
|
call.id = String(item.call_id || call.id);
|
|
329272
329311
|
call.name = String(item.name || call.name);
|
|
329273
|
-
|
|
329312
|
+
if (typeof item.arguments === "string" && item.arguments) call.argumentParts.push(item.arguments);
|
|
329274
329313
|
if (!call.emitted) {
|
|
329275
329314
|
call.emitted = true;
|
|
329315
|
+
const argumentsJson = assembleCompatibleToolArguments(call.argumentParts);
|
|
329276
329316
|
yield { type: "tool_call.started", id: call.id, name: call.name };
|
|
329277
|
-
if (
|
|
329278
|
-
yield { type: "tool_call.arguments.delta", id: call.id, delta:
|
|
329317
|
+
if (argumentsJson !== "{}") {
|
|
329318
|
+
yield { type: "tool_call.arguments.delta", id: call.id, delta: argumentsJson };
|
|
329279
329319
|
}
|
|
329280
|
-
yield { type: "tool_call.completed", id: call.id, name: call.name, arguments:
|
|
329320
|
+
yield { type: "tool_call.completed", id: call.id, name: call.name, arguments: argumentsJson };
|
|
329281
329321
|
}
|
|
329282
329322
|
calls.set(key3, call);
|
|
329283
329323
|
}
|
|
@@ -329302,8 +329342,14 @@ var ResponsesAdapter = class {
|
|
|
329302
329342
|
} else if (!completed) {
|
|
329303
329343
|
yield { type: "response.failed", error: "[LLM Error] Responses stream ended before response.completed." };
|
|
329304
329344
|
} else if (!emittedContent && calls.size === 0) {
|
|
329305
|
-
yield { type: "response.failed", error: "[Error]
|
|
329345
|
+
yield { type: "response.failed", error: "[Error] Provider returned an empty response." };
|
|
329306
329346
|
} else {
|
|
329347
|
+
for (const call of calls.values()) {
|
|
329348
|
+
if (call.emitted) continue;
|
|
329349
|
+
const argumentsJson = assembleCompatibleToolArguments(call.argumentParts);
|
|
329350
|
+
yield { type: "tool_call.started", id: call.id, name: call.name };
|
|
329351
|
+
yield { type: "tool_call.completed", id: call.id, name: call.name, arguments: argumentsJson };
|
|
329352
|
+
}
|
|
329307
329353
|
yield { type: "response.completed" };
|
|
329308
329354
|
}
|
|
329309
329355
|
} finally {
|
|
@@ -330182,7 +330228,7 @@ ${responsePath}
|
|
|
330182
330228
|
* `provider_adapters_v2` context flag. Request serialization and SSE
|
|
330183
330229
|
* normalization are delegated to the shared provider adapters while the
|
|
330184
330230
|
* transport orchestration (loopback node-http, fetch -> node-http fallback,
|
|
330185
|
-
*
|
|
330231
|
+
* cancellation-only streaming and the 4xx Chat -> Responses downgrade) stay here.
|
|
330186
330232
|
* The emitted request body and StreamToken stream are byte-equivalent to
|
|
330187
330233
|
* the legacy inlined path.
|
|
330188
330234
|
*/
|
|
@@ -330319,9 +330365,9 @@ ${responsePath}
|
|
|
330319
330365
|
}
|
|
330320
330366
|
/**
|
|
330321
330367
|
* Loopback-aware transport injected into adapter `execute`. Streaming
|
|
330322
|
-
* requests retain the fetch-to-node fallback for transport failures
|
|
330323
|
-
*
|
|
330324
|
-
*
|
|
330368
|
+
* requests retain the fetch-to-node fallback for transport failures. They
|
|
330369
|
+
* have no response deadline; only caller cancellation or a concrete
|
|
330370
|
+
* transport/provider failure may end the request.
|
|
330325
330371
|
*/
|
|
330326
330372
|
buildProviderAdapterTransport() {
|
|
330327
330373
|
return async (request, signal) => {
|
|
@@ -330331,7 +330377,7 @@ ${responsePath}
|
|
|
330331
330377
|
const forwardAbort = () => abort.abort(signal?.reason);
|
|
330332
330378
|
if (signal?.aborted) forwardAbort();
|
|
330333
330379
|
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
330334
|
-
const effectiveTimeout =
|
|
330380
|
+
const effectiveTimeout = 0;
|
|
330335
330381
|
const timer = effectiveTimeout > 0 ? setTimeout(() => abort.abort(providerTimeoutError(effectiveTimeout)), effectiveTimeout) : void 0;
|
|
330336
330382
|
try {
|
|
330337
330383
|
try {
|
|
@@ -330476,7 +330522,7 @@ ${responsePath}
|
|
|
330476
330522
|
const forwardAbort = () => abort.abort(signal?.reason);
|
|
330477
330523
|
if (signal?.aborted) forwardAbort();
|
|
330478
330524
|
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
330479
|
-
const effectiveTimeout =
|
|
330525
|
+
const effectiveTimeout = 0;
|
|
330480
330526
|
const timeout = effectiveTimeout > 0 ? setTimeout(() => abort.abort(providerTimeoutError(effectiveTimeout)), effectiveTimeout) : void 0;
|
|
330481
330527
|
let reader = null;
|
|
330482
330528
|
try {
|
|
@@ -330508,10 +330554,14 @@ ${responsePath}
|
|
|
330508
330554
|
}
|
|
330509
330555
|
const decoder = new TextDecoder();
|
|
330510
330556
|
let buffer = "";
|
|
330511
|
-
|
|
330557
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
330558
|
+
const toolCallOrder = [];
|
|
330559
|
+
let syntheticToolIndex = 0;
|
|
330560
|
+
let lastToolIndex = 0;
|
|
330512
330561
|
let currentReasoningContent = "";
|
|
330513
330562
|
let contentPolicyBlocked = false;
|
|
330514
330563
|
let emittedContent = false;
|
|
330564
|
+
let explicitCompletion = false;
|
|
330515
330565
|
const streamSignal = signal || new AbortController().signal;
|
|
330516
330566
|
while (true) {
|
|
330517
330567
|
const { done, value } = await readProviderStreamChunk(reader, streamSignal);
|
|
@@ -330523,7 +330573,10 @@ ${responsePath}
|
|
|
330523
330573
|
const trimmed = line.trim();
|
|
330524
330574
|
if (!trimmed.startsWith("data: ")) continue;
|
|
330525
330575
|
const data = trimmed.slice(6);
|
|
330526
|
-
if (data === "[DONE]")
|
|
330576
|
+
if (data === "[DONE]") {
|
|
330577
|
+
explicitCompletion = true;
|
|
330578
|
+
continue;
|
|
330579
|
+
}
|
|
330527
330580
|
try {
|
|
330528
330581
|
const json = JSON.parse(data);
|
|
330529
330582
|
if (json.usage) yield { type: "usage", text: "", usage: extractProviderUsage(json) };
|
|
@@ -330541,24 +330594,44 @@ ${responsePath}
|
|
|
330541
330594
|
}
|
|
330542
330595
|
if (delta.tool_calls) {
|
|
330543
330596
|
for (const tc of delta.tool_calls) {
|
|
330544
|
-
|
|
330545
|
-
|
|
330546
|
-
|
|
330547
|
-
|
|
330548
|
-
|
|
330549
|
-
|
|
330550
|
-
|
|
330597
|
+
const rawIndex = Number(tc.index);
|
|
330598
|
+
const index = Number.isInteger(rawIndex) && rawIndex >= 0 ? rawIndex : tc.id ? syntheticToolIndex++ : lastToolIndex;
|
|
330599
|
+
lastToolIndex = index;
|
|
330600
|
+
let call = toolCalls.get(index);
|
|
330601
|
+
if (!call && (tc.id || tc.function?.name)) {
|
|
330602
|
+
call = { id: tc.id || "", name: tc.function?.name || "", argumentParts: [] };
|
|
330603
|
+
toolCalls.set(index, call);
|
|
330604
|
+
toolCallOrder.push(index);
|
|
330551
330605
|
}
|
|
330606
|
+
if (!call) continue;
|
|
330607
|
+
if (tc.id && !call.id) call.id = tc.id;
|
|
330608
|
+
if (tc.function?.name && !call.name) call.name = tc.function.name;
|
|
330609
|
+
if (tc.function?.arguments) call.argumentParts.push(tc.function.arguments);
|
|
330552
330610
|
}
|
|
330553
330611
|
}
|
|
330554
330612
|
} catch {
|
|
330555
330613
|
}
|
|
330556
330614
|
}
|
|
330557
330615
|
}
|
|
330558
|
-
if (
|
|
330559
|
-
|
|
330616
|
+
if (toolCallOrder.length) {
|
|
330617
|
+
for (const index of toolCallOrder) {
|
|
330618
|
+
const call = toolCalls.get(index);
|
|
330619
|
+
if (!call) continue;
|
|
330620
|
+
yield {
|
|
330621
|
+
type: "tool_call",
|
|
330622
|
+
text: "",
|
|
330623
|
+
toolCall: {
|
|
330624
|
+
id: call.id,
|
|
330625
|
+
name: call.name,
|
|
330626
|
+
arguments: assembleCompatibleToolArguments(call.argumentParts)
|
|
330627
|
+
},
|
|
330628
|
+
reasoningContent: currentReasoningContent || void 0
|
|
330629
|
+
};
|
|
330630
|
+
}
|
|
330560
330631
|
} else if (!emittedContent && contentPolicyBlocked) {
|
|
330561
330632
|
yield { type: "text", text: "[Error] Content policy refusal (content_filter)." };
|
|
330633
|
+
} else if (!explicitCompletion && !emittedContent && !currentReasoningContent) {
|
|
330634
|
+
yield { type: "text", text: "[LLM Error] GitHub Models stream ended before an explicit completion." };
|
|
330562
330635
|
}
|
|
330563
330636
|
} finally {
|
|
330564
330637
|
reader?.releaseLock();
|
|
@@ -331245,8 +331318,8 @@ async function fuzzyDiscoverWithoutGuide(input, explicit, preferredModels = [])
|
|
|
331245
331318
|
}
|
|
331246
331319
|
|
|
331247
331320
|
// src/tools/index.ts
|
|
331248
|
-
var
|
|
331249
|
-
var
|
|
331321
|
+
var fs15 = __toESM(require("fs"));
|
|
331322
|
+
var path17 = __toESM(require("path"));
|
|
331250
331323
|
var crypto8 = __toESM(require("crypto"));
|
|
331251
331324
|
var import_url2 = require("url");
|
|
331252
331325
|
|
|
@@ -331590,7 +331663,8 @@ var MemoryLabManager = class {
|
|
|
331590
331663
|
"Use memory_lab_read to inspect index.json before deciding what memory is relevant.",
|
|
331591
331664
|
"Use memory_lab_query for bounded task-relevant retrieval; do not inject the complete index when a focused query is sufficient.",
|
|
331592
331665
|
"Use memory_lab_read with component/name/slug to read a component core markdown file.",
|
|
331593
|
-
"Use memory_lab_update only when the user asks to create or update durable memory
|
|
331666
|
+
"Use memory_lab_update only when the user asks to create or update durable memory. Create with name, tags, and content; patch an existing component with component plus only changed fields.",
|
|
331667
|
+
"For small body edits prefer contentAppend or oldText/newText over resending the complete content.",
|
|
331594
331668
|
"For an existing component, pass expectedUpdatedAt from the latest read/query result. A stale update is rejected instead of overwriting newer memory.",
|
|
331595
331669
|
"Use memory_lab_delete only when the user explicitly asks to forget/remove durable memory. Delete moves the prior revision to Memory Lab/archive and records a policy event.",
|
|
331596
331670
|
"Every mutation should include a concise reason and source. ADD, UPDATE, and DELETE decisions are append-only in policy.jsonl and are recoverable from archive.",
|
|
@@ -331698,6 +331772,39 @@ var MemoryLabManager = class {
|
|
|
331698
331772
|
source: String(input.source || "").trim()
|
|
331699
331773
|
};
|
|
331700
331774
|
}
|
|
331775
|
+
preparePatch(input) {
|
|
331776
|
+
const selector2 = String(input.component || "").trim();
|
|
331777
|
+
if (!selector2) throw new Error("Memory component is required for a patch.");
|
|
331778
|
+
const current = this.read(selector2);
|
|
331779
|
+
if (!current.ok || !current.component) throw new Error(current.error || `Memory component not found: ${selector2}`);
|
|
331780
|
+
const existing = current.component.meta;
|
|
331781
|
+
const oldContent = current.component.content;
|
|
331782
|
+
let content = input.content !== void 0 ? String(input.content) : oldContent;
|
|
331783
|
+
if (input.contentAppend !== void 0) content = `${oldContent}${String(input.contentAppend)}`;
|
|
331784
|
+
if (input.oldText !== void 0) {
|
|
331785
|
+
const oldText = String(input.oldText);
|
|
331786
|
+
if (!oldText) throw new Error("oldText must not be empty.");
|
|
331787
|
+
const matches = oldContent.split(oldText).length - 1;
|
|
331788
|
+
if (!matches) throw new Error("oldText was not found in the Memory Lab component.");
|
|
331789
|
+
if (matches > 1 && input.replaceAll !== true) throw new Error(`oldText matched ${matches} places; pass replaceAll=true or a unique fragment.`);
|
|
331790
|
+
content = input.replaceAll === true ? oldContent.split(oldText).join(String(input.newText || "")) : oldContent.replace(oldText, String(input.newText || ""));
|
|
331791
|
+
}
|
|
331792
|
+
const name50 = input.name === void 0 ? existing.name : String(input.name);
|
|
331793
|
+
if (this.slugify(name50) !== current.component.slug) {
|
|
331794
|
+
throw new Error("Renaming a Memory Lab component is not supported by incremental patch; create the new component then delete the old one.");
|
|
331795
|
+
}
|
|
331796
|
+
return this.prepareUpdate({
|
|
331797
|
+
name: name50,
|
|
331798
|
+
description: input.description === void 0 ? existing.description : String(input.description),
|
|
331799
|
+
tags: input.tags === void 0 ? existing.tags : input.tags,
|
|
331800
|
+
tagPaths: input.tagPaths === void 0 ? existing.tagPaths : input.tagPaths,
|
|
331801
|
+
content,
|
|
331802
|
+
kind: input.kind === void 0 ? existing.kind : input.kind,
|
|
331803
|
+
expectedUpdatedAt: String(input.expectedUpdatedAt || existing.updatedAt),
|
|
331804
|
+
reason: input.reason,
|
|
331805
|
+
source: input.source
|
|
331806
|
+
});
|
|
331807
|
+
}
|
|
331701
331808
|
update(prepared) {
|
|
331702
331809
|
this.ensure();
|
|
331703
331810
|
const index = this.loadIndex();
|
|
@@ -332244,20 +332351,23 @@ ${JSON.stringify(payload, null, 2)}`;
|
|
|
332244
332351
|
}
|
|
332245
332352
|
};
|
|
332246
332353
|
|
|
332354
|
+
// src/tools/index.ts
|
|
332355
|
+
init_flow();
|
|
332356
|
+
|
|
332247
332357
|
// src/core/compat.ts
|
|
332248
|
-
var
|
|
332249
|
-
var
|
|
332358
|
+
var fs7 = __toESM(require("fs"));
|
|
332359
|
+
var path8 = __toESM(require("path"));
|
|
332250
332360
|
var os2 = __toESM(require("os"));
|
|
332251
332361
|
function readJson(filePath) {
|
|
332252
332362
|
try {
|
|
332253
|
-
return JSON.parse(
|
|
332363
|
+
return JSON.parse(fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, ""));
|
|
332254
332364
|
} catch {
|
|
332255
332365
|
return null;
|
|
332256
332366
|
}
|
|
332257
332367
|
}
|
|
332258
332368
|
function readJsonLoose(filePath) {
|
|
332259
332369
|
try {
|
|
332260
|
-
const withoutBom =
|
|
332370
|
+
const withoutBom = fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
|
|
332261
332371
|
const withoutComments = withoutBom.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|\s)\/\/.*$/gm, "$1");
|
|
332262
332372
|
return JSON.parse(withoutComments);
|
|
332263
332373
|
} catch {
|
|
@@ -332338,7 +332448,7 @@ function normalizeToolResult(output, metadata) {
|
|
|
332338
332448
|
return { ok: !error, output, error, metadata };
|
|
332339
332449
|
}
|
|
332340
332450
|
function componentPaths(root2, value) {
|
|
332341
|
-
return asStringArray(value).map((item) =>
|
|
332451
|
+
return asStringArray(value).map((item) => path8.resolve(root2, item));
|
|
332342
332452
|
}
|
|
332343
332453
|
function manifestComponentPaths(root2, manifest, ...keys) {
|
|
332344
332454
|
for (const key3 of keys) {
|
|
@@ -332349,7 +332459,7 @@ function manifestComponentPaths(root2, manifest, ...keys) {
|
|
|
332349
332459
|
function discoverComponentFiles(root2, relativeDirs, extension, maxDepth = 2) {
|
|
332350
332460
|
const files = [];
|
|
332351
332461
|
for (const dir of relativeDirs) {
|
|
332352
|
-
files.push(...listFilesRecursive(
|
|
332462
|
+
files.push(...listFilesRecursive(path8.join(root2, dir), extension, maxDepth));
|
|
332353
332463
|
}
|
|
332354
332464
|
return Array.from(new Set(files)).sort();
|
|
332355
332465
|
}
|
|
@@ -332374,12 +332484,12 @@ function collectMcpServers(...values) {
|
|
|
332374
332484
|
function defaultComponentWarnings(kind, components) {
|
|
332375
332485
|
const warnings = [];
|
|
332376
332486
|
for (const item of components) {
|
|
332377
|
-
if (
|
|
332487
|
+
if (path8.isAbsolute(item) && !fs7.existsSync(item)) warnings.push(`${kind} path does not exist: ${item}`);
|
|
332378
332488
|
}
|
|
332379
332489
|
return warnings;
|
|
332380
332490
|
}
|
|
332381
332491
|
function normalizeCodexPlugin(root2, manifest) {
|
|
332382
|
-
const name50 = asString(manifest.name) ||
|
|
332492
|
+
const name50 = asString(manifest.name) || path8.basename(root2);
|
|
332383
332493
|
const components = {
|
|
332384
332494
|
skills: manifestComponentPaths(root2, manifest, "skills"),
|
|
332385
332495
|
agents: manifestComponentPaths(root2, manifest, "agents"),
|
|
@@ -332410,7 +332520,7 @@ function normalizeCodexPlugin(root2, manifest) {
|
|
|
332410
332520
|
};
|
|
332411
332521
|
}
|
|
332412
332522
|
function normalizeClaudePlugin(root2, manifest) {
|
|
332413
|
-
const name50 = asString(manifest.name) ||
|
|
332523
|
+
const name50 = asString(manifest.name) || path8.basename(root2);
|
|
332414
332524
|
const experimental = nestedRecord(manifest.experimental);
|
|
332415
332525
|
const components = {
|
|
332416
332526
|
skills: manifestComponentPaths(root2, manifest, "skills"),
|
|
@@ -332448,7 +332558,7 @@ function normalizeClaudePlugin(root2, manifest) {
|
|
|
332448
332558
|
};
|
|
332449
332559
|
}
|
|
332450
332560
|
function normalizeNewmarkPlugin(root2, manifest) {
|
|
332451
|
-
const name50 = asString(manifest.name) ||
|
|
332561
|
+
const name50 = asString(manifest.name) || path8.basename(root2);
|
|
332452
332562
|
return {
|
|
332453
332563
|
id: `newmark:${name50}`,
|
|
332454
332564
|
ecosystem: "newmark",
|
|
@@ -332477,7 +332587,7 @@ function findPluginRoots(root2, maxDepth = 5) {
|
|
|
332477
332587
|
if (depth > maxDepth) return;
|
|
332478
332588
|
let entries;
|
|
332479
332589
|
try {
|
|
332480
|
-
entries =
|
|
332590
|
+
entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
332481
332591
|
} catch {
|
|
332482
332592
|
return;
|
|
332483
332593
|
}
|
|
@@ -332486,7 +332596,7 @@ function findPluginRoots(root2, maxDepth = 5) {
|
|
|
332486
332596
|
}
|
|
332487
332597
|
for (const entry of entries) {
|
|
332488
332598
|
if (!entry.isDirectory() || skip.has(entry.name) || entry.name.startsWith("release.locked-")) continue;
|
|
332489
|
-
walk4(
|
|
332599
|
+
walk4(path8.join(dir, entry.name), depth + 1);
|
|
332490
332600
|
}
|
|
332491
332601
|
};
|
|
332492
332602
|
walk4(root2, 0);
|
|
@@ -332495,20 +332605,20 @@ function findPluginRoots(root2, maxDepth = 5) {
|
|
|
332495
332605
|
function discoverPluginManifests(root2) {
|
|
332496
332606
|
const manifests = [];
|
|
332497
332607
|
for (const pluginRoot of findPluginRoots(root2)) {
|
|
332498
|
-
const codexPath =
|
|
332499
|
-
const claudePath =
|
|
332500
|
-
const newmarkPath =
|
|
332501
|
-
const codex =
|
|
332502
|
-
const claude =
|
|
332503
|
-
const newmark =
|
|
332608
|
+
const codexPath = path8.join(pluginRoot, ".codex-plugin", "plugin.json");
|
|
332609
|
+
const claudePath = path8.join(pluginRoot, ".claude-plugin", "plugin.json");
|
|
332610
|
+
const newmarkPath = path8.join(pluginRoot, ".newmark-plugin", "plugin.json");
|
|
332611
|
+
const codex = fs7.existsSync(codexPath) ? readJson(codexPath) : null;
|
|
332612
|
+
const claude = fs7.existsSync(claudePath) ? readJson(claudePath) : null;
|
|
332613
|
+
const newmark = fs7.existsSync(newmarkPath) ? readJson(newmarkPath) : null;
|
|
332504
332614
|
if (codex && typeof codex === "object") manifests.push(normalizeCodexPlugin(pluginRoot, codex));
|
|
332505
332615
|
if (claude && typeof claude === "object") manifests.push(normalizeClaudePlugin(pluginRoot, claude));
|
|
332506
332616
|
if (newmark && typeof newmark === "object") manifests.push(normalizeNewmarkPlugin(pluginRoot, newmark));
|
|
332507
332617
|
}
|
|
332508
332618
|
const projectOpencode = readOpenCodeManifest(root2, "project");
|
|
332509
332619
|
if (projectOpencode) manifests.push(projectOpencode);
|
|
332510
|
-
const userOpenCodeRoot =
|
|
332511
|
-
if (
|
|
332620
|
+
const userOpenCodeRoot = path8.join(os2.homedir(), ".config", "opencode");
|
|
332621
|
+
if (path8.resolve(userOpenCodeRoot) !== path8.resolve(path8.join(root2, ".opencode"))) {
|
|
332512
332622
|
const userOpenCode = readOpenCodeManifest(userOpenCodeRoot, "user");
|
|
332513
332623
|
if (userOpenCode) manifests.push(userOpenCode);
|
|
332514
332624
|
}
|
|
@@ -332516,20 +332626,20 @@ function discoverPluginManifests(root2) {
|
|
|
332516
332626
|
}
|
|
332517
332627
|
function readOpenCodeConfig(root2) {
|
|
332518
332628
|
const candidates = [
|
|
332519
|
-
|
|
332520
|
-
|
|
332521
|
-
|
|
332522
|
-
|
|
332629
|
+
path8.join(root2, "opencode.json"),
|
|
332630
|
+
path8.join(root2, "opencode.jsonc"),
|
|
332631
|
+
path8.join(root2, ".opencode", "opencode.json"),
|
|
332632
|
+
path8.join(root2, ".opencode", "opencode.jsonc")
|
|
332523
332633
|
];
|
|
332524
332634
|
for (const filePath of candidates) {
|
|
332525
|
-
if (
|
|
332635
|
+
if (fs7.existsSync(filePath)) return { path: filePath, value: readJsonLoose(filePath) };
|
|
332526
332636
|
}
|
|
332527
332637
|
return null;
|
|
332528
332638
|
}
|
|
332529
332639
|
function readOpenCodeManifest(root2, scope) {
|
|
332530
|
-
const localRoot = scope === "project" ?
|
|
332531
|
-
const opencodeToolsDir =
|
|
332532
|
-
const opencodePluginsDir =
|
|
332640
|
+
const localRoot = scope === "project" ? path8.join(root2, ".opencode") : root2;
|
|
332641
|
+
const opencodeToolsDir = path8.join(localRoot, "tools");
|
|
332642
|
+
const opencodePluginsDir = path8.join(localRoot, "plugins");
|
|
332533
332643
|
const tools = listCodeFiles(opencodeToolsDir);
|
|
332534
332644
|
const pluginFiles = listCodeFiles(opencodePluginsDir);
|
|
332535
332645
|
const config = readOpenCodeConfig(root2);
|
|
@@ -332570,18 +332680,18 @@ function readOpenCodeManifest(root2, scope) {
|
|
|
332570
332680
|
}
|
|
332571
332681
|
function discoverOpenCodeInstructionFiles(projectRoot, localRoot) {
|
|
332572
332682
|
const candidates = [
|
|
332573
|
-
|
|
332574
|
-
|
|
332575
|
-
|
|
332576
|
-
|
|
332577
|
-
|
|
332683
|
+
path8.join(projectRoot, "AGENTS.md"),
|
|
332684
|
+
path8.join(projectRoot, ".opencode", "instructions.md"),
|
|
332685
|
+
path8.join(projectRoot, ".opencode", "AGENTS.md"),
|
|
332686
|
+
path8.join(localRoot, "instructions.md"),
|
|
332687
|
+
path8.join(localRoot, "AGENTS.md")
|
|
332578
332688
|
];
|
|
332579
|
-
return Array.from(new Set(candidates.filter((filePath) =>
|
|
332689
|
+
return Array.from(new Set(candidates.filter((filePath) => fs7.existsSync(filePath)))).sort();
|
|
332580
332690
|
}
|
|
332581
332691
|
function dedupeManifests(manifests) {
|
|
332582
332692
|
const seen = /* @__PURE__ */ new Set();
|
|
332583
332693
|
return manifests.filter((item) => {
|
|
332584
|
-
const key3 = `${item.id}:${
|
|
332694
|
+
const key3 = `${item.id}:${path8.resolve(item.root)}`;
|
|
332585
332695
|
if (seen.has(key3)) return false;
|
|
332586
332696
|
seen.add(key3);
|
|
332587
332697
|
return true;
|
|
@@ -332589,14 +332699,14 @@ function dedupeManifests(manifests) {
|
|
|
332589
332699
|
}
|
|
332590
332700
|
function listCodeFiles(dir) {
|
|
332591
332701
|
try {
|
|
332592
|
-
return
|
|
332702
|
+
return fs7.readdirSync(dir, { withFileTypes: true }).filter((e3) => e3.isFile() && /\.(?:c?js|mjs|ts)$/.test(e3.name)).map((e3) => path8.join(dir, e3.name)).sort();
|
|
332593
332703
|
} catch {
|
|
332594
332704
|
return [];
|
|
332595
332705
|
}
|
|
332596
332706
|
}
|
|
332597
332707
|
function parseFrontmatterMarkdown(filePath) {
|
|
332598
332708
|
try {
|
|
332599
|
-
const content =
|
|
332709
|
+
const content = fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
|
|
332600
332710
|
const match = content.match(/^---\s*([\s\S]*?)\s*---\s*/);
|
|
332601
332711
|
if (!match) return { metadata: {}, body: content };
|
|
332602
332712
|
const metadata = {};
|
|
@@ -332625,7 +332735,7 @@ function parseMetadataValue(raw) {
|
|
|
332625
332735
|
function parseSimpleToml(filePath) {
|
|
332626
332736
|
try {
|
|
332627
332737
|
const metadata = {};
|
|
332628
|
-
const content =
|
|
332738
|
+
const content = fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
|
|
332629
332739
|
const multiline = null;
|
|
332630
332740
|
if (multiline) return metadata;
|
|
332631
332741
|
const lines = content.split(/\r?\n/);
|
|
@@ -332659,7 +332769,7 @@ function parseSimpleToml(filePath) {
|
|
|
332659
332769
|
}
|
|
332660
332770
|
}
|
|
332661
332771
|
function agentPresetFromMetadata(filePath, ecosystem, metadata, body = "") {
|
|
332662
|
-
const name50 = asString(metadata.name) ||
|
|
332772
|
+
const name50 = asString(metadata.name) || path8.basename(filePath).replace(/\.(?:toml|md)$/i, "");
|
|
332663
332773
|
const description = asString(metadata.description);
|
|
332664
332774
|
const instructions = asString(metadata.developer_instructions || metadata.instructions || metadata.prompt) || body.trim();
|
|
332665
332775
|
if (!name50 || !description) return null;
|
|
@@ -332687,12 +332797,12 @@ function listFilesRecursive(root2, extension, maxDepth = 4) {
|
|
|
332687
332797
|
if (depth > maxDepth) return;
|
|
332688
332798
|
let entries;
|
|
332689
332799
|
try {
|
|
332690
|
-
entries =
|
|
332800
|
+
entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
332691
332801
|
} catch {
|
|
332692
332802
|
return;
|
|
332693
332803
|
}
|
|
332694
332804
|
for (const entry of entries) {
|
|
332695
|
-
const full =
|
|
332805
|
+
const full = path8.join(dir, entry.name);
|
|
332696
332806
|
if (entry.isFile() && extension.test(entry.name)) results.push(full);
|
|
332697
332807
|
if (entry.isDirectory() && !entry.name.startsWith(".git") && entry.name !== "node_modules") walk4(full, depth + 1);
|
|
332698
332808
|
}
|
|
@@ -332703,10 +332813,10 @@ function listFilesRecursive(root2, extension, maxDepth = 4) {
|
|
|
332703
332813
|
function discoverAgentPresets(root2) {
|
|
332704
332814
|
const presets = [];
|
|
332705
332815
|
const codexDirs = [
|
|
332706
|
-
|
|
332707
|
-
|
|
332708
|
-
|
|
332709
|
-
|
|
332816
|
+
path8.join(root2, ".codex", "agents"),
|
|
332817
|
+
path8.join(root2, ".agents", "agents"),
|
|
332818
|
+
path8.join(os2.homedir(), ".codex", "agents"),
|
|
332819
|
+
path8.join(os2.homedir(), ".agents", "agents")
|
|
332710
332820
|
];
|
|
332711
332821
|
for (const dir of codexDirs) {
|
|
332712
332822
|
for (const filePath of listFilesRecursive(dir, /\.toml$/i, 1)) {
|
|
@@ -332715,14 +332825,14 @@ function discoverAgentPresets(root2) {
|
|
|
332715
332825
|
}
|
|
332716
332826
|
}
|
|
332717
332827
|
const claudeDirs = [
|
|
332718
|
-
|
|
332719
|
-
|
|
332720
|
-
|
|
332828
|
+
path8.join(root2, ".claude", "agents"),
|
|
332829
|
+
path8.join(os2.homedir(), ".claude", "agents"),
|
|
332830
|
+
path8.join(os2.homedir(), ".config", "opencode", "agents")
|
|
332721
332831
|
];
|
|
332722
332832
|
for (const dir of claudeDirs) {
|
|
332723
332833
|
for (const filePath of listFilesRecursive(dir, /\.md$/i, 1)) {
|
|
332724
332834
|
const parsed = parseFrontmatterMarkdown(filePath);
|
|
332725
|
-
const ecosystem = filePath.includes(`${
|
|
332835
|
+
const ecosystem = filePath.includes(`${path8.sep}.config${path8.sep}opencode${path8.sep}`) ? "opencode" : "claude-code";
|
|
332726
332836
|
const preset = agentPresetFromMetadata(filePath, ecosystem, parsed.metadata, parsed.body);
|
|
332727
332837
|
if (preset) presets.push(preset);
|
|
332728
332838
|
}
|
|
@@ -332759,15 +332869,15 @@ function findAgentPreset(root2, selector2) {
|
|
|
332759
332869
|
preset.id,
|
|
332760
332870
|
preset.name,
|
|
332761
332871
|
`${preset.ecosystem}:${preset.name}`,
|
|
332762
|
-
|
|
332872
|
+
path8.basename(preset.path)
|
|
332763
332873
|
].map((value) => String(value || "").toLowerCase());
|
|
332764
|
-
return keys.includes(normalized) ||
|
|
332874
|
+
return keys.includes(normalized) || path8.resolve(preset.path).toLowerCase() === path8.resolve(wanted).toLowerCase();
|
|
332765
332875
|
}) || null;
|
|
332766
332876
|
}
|
|
332767
332877
|
|
|
332768
332878
|
// src/tools/terminalTakeover.ts
|
|
332769
|
-
var
|
|
332770
|
-
var
|
|
332879
|
+
var fs8 = __toESM(require("fs"));
|
|
332880
|
+
var path9 = __toESM(require("path"));
|
|
332771
332881
|
var import_child_process2 = require("child_process");
|
|
332772
332882
|
var import_crypto5 = require("crypto");
|
|
332773
332883
|
var ROOT_TERMINAL_ACTOR_ID = "00000000-0000-4000-8000-000000000001";
|
|
@@ -332782,7 +332892,7 @@ function isoNow() {
|
|
|
332782
332892
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
332783
332893
|
}
|
|
332784
332894
|
function canonicalPersistenceRoot(root2) {
|
|
332785
|
-
const resolved =
|
|
332895
|
+
const resolved = path9.resolve(root2 || process.cwd());
|
|
332786
332896
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
332787
332897
|
}
|
|
332788
332898
|
function portableWorkspacePath(input) {
|
|
@@ -332791,7 +332901,7 @@ function portableWorkspacePath(input) {
|
|
|
332791
332901
|
if (wsl) return `${wsl[1].toLowerCase()}:/${String(wsl[2] || "").replace(/^\/+|\/+$/g, "")}`.replace(/\/$/, "");
|
|
332792
332902
|
const drive = /^([a-zA-Z]):(?:\/(.*))?$/.exec(raw);
|
|
332793
332903
|
if (drive) return `${drive[1].toLowerCase()}:/${String(drive[2] || "").replace(/^\/+|\/+$/g, "")}`.replace(/\/$/, "");
|
|
332794
|
-
const resolved =
|
|
332904
|
+
const resolved = path9.resolve(raw).replace(/\\/g, "/").replace(/\/+$/g, "");
|
|
332795
332905
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
332796
332906
|
}
|
|
332797
332907
|
function terminalTakeoverWorkspaceId(workspacePath) {
|
|
@@ -332886,12 +332996,12 @@ function nodePtyHasConptyDll() {
|
|
|
332886
332996
|
if (process.platform !== "win32") return false;
|
|
332887
332997
|
try {
|
|
332888
332998
|
const packageJson = require.resolve("node-pty/package.json");
|
|
332889
|
-
const packageRoot =
|
|
332999
|
+
const packageRoot = path9.dirname(packageJson);
|
|
332890
333000
|
return [
|
|
332891
|
-
|
|
332892
|
-
|
|
332893
|
-
|
|
332894
|
-
].some((candidate) =>
|
|
333001
|
+
path9.join(packageRoot, "build", "Release", "conpty", "conpty.dll"),
|
|
333002
|
+
path9.join(packageRoot, "build", "Debug", "conpty", "conpty.dll"),
|
|
333003
|
+
path9.join(packageRoot, "prebuilds", `${process.platform}-${process.arch}`, "conpty", "conpty.dll")
|
|
333004
|
+
].some((candidate) => fs8.existsSync(candidate));
|
|
332895
333005
|
} catch {
|
|
332896
333006
|
return false;
|
|
332897
333007
|
}
|
|
@@ -333124,7 +333234,7 @@ function spawnTakeoverPty(shell, cwd, env, cols, rows) {
|
|
|
333124
333234
|
};
|
|
333125
333235
|
}
|
|
333126
333236
|
function persistencePath(root2) {
|
|
333127
|
-
return
|
|
333237
|
+
return path9.join(root2, "Terminal", "Takeover.json");
|
|
333128
333238
|
}
|
|
333129
333239
|
function validPersistedRecord(input) {
|
|
333130
333240
|
if (!input || typeof input !== "object") return null;
|
|
@@ -333165,7 +333275,7 @@ function ensurePersistenceLoaded(rootRaw) {
|
|
|
333165
333275
|
if (loaded) return loaded;
|
|
333166
333276
|
const records = /* @__PURE__ */ new Map();
|
|
333167
333277
|
try {
|
|
333168
|
-
const parsed = JSON.parse(
|
|
333278
|
+
const parsed = JSON.parse(fs8.readFileSync(persistencePath(root2), "utf-8"));
|
|
333169
333279
|
if (Array.isArray(parsed.records)) {
|
|
333170
333280
|
for (const input of parsed.records) {
|
|
333171
333281
|
const record = validPersistedRecord(input);
|
|
@@ -333183,19 +333293,19 @@ function persistEndedRecords(rootRaw) {
|
|
|
333183
333293
|
const output = { version: 1, updatedAt: isoNow(), records };
|
|
333184
333294
|
const filePath = persistencePath(root2);
|
|
333185
333295
|
const tempPath = `${filePath}.tmp-${process.pid}-${(0, import_crypto5.randomUUID)()}`;
|
|
333186
|
-
|
|
333187
|
-
const fd =
|
|
333296
|
+
fs8.mkdirSync(path9.dirname(filePath), { recursive: true });
|
|
333297
|
+
const fd = fs8.openSync(tempPath, "w");
|
|
333188
333298
|
try {
|
|
333189
|
-
|
|
333190
|
-
|
|
333299
|
+
fs8.writeFileSync(fd, JSON.stringify(output, null, 2), "utf-8");
|
|
333300
|
+
fs8.fsyncSync(fd);
|
|
333191
333301
|
} finally {
|
|
333192
|
-
|
|
333302
|
+
fs8.closeSync(fd);
|
|
333193
333303
|
}
|
|
333194
333304
|
try {
|
|
333195
|
-
|
|
333305
|
+
fs8.renameSync(tempPath, filePath);
|
|
333196
333306
|
} catch (error) {
|
|
333197
333307
|
try {
|
|
333198
|
-
|
|
333308
|
+
fs8.rmSync(tempPath, { force: true });
|
|
333199
333309
|
} catch {
|
|
333200
333310
|
}
|
|
333201
333311
|
throw error;
|
|
@@ -333424,8 +333534,8 @@ function runTerminalTakeover(input) {
|
|
|
333424
333534
|
}
|
|
333425
333535
|
|
|
333426
333536
|
// src/tools/computerUse.ts
|
|
333427
|
-
var
|
|
333428
|
-
var
|
|
333537
|
+
var fs9 = __toESM(require("fs"));
|
|
333538
|
+
var path10 = __toESM(require("path"));
|
|
333429
333539
|
var crypto6 = __toESM(require("crypto"));
|
|
333430
333540
|
var os3 = __toESM(require("os"));
|
|
333431
333541
|
|
|
@@ -333633,8 +333743,8 @@ async function runPowerShell(script, timeout = 3e4, lane = "action") {
|
|
|
333633
333743
|
return await runPersistentPowerShell(script, timeout, lane);
|
|
333634
333744
|
}
|
|
333635
333745
|
function tempScreenshotDir() {
|
|
333636
|
-
const dir =
|
|
333637
|
-
|
|
333746
|
+
const dir = path10.join(os3.tmpdir(), "newmark-computer-use");
|
|
333747
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
333638
333748
|
const now2 = Date.now();
|
|
333639
333749
|
if (now2 - lastScreenshotCleanupAt >= SCREENSHOT_CLEANUP_INTERVAL_MS) {
|
|
333640
333750
|
lastScreenshotCleanupAt = now2;
|
|
@@ -333656,7 +333766,7 @@ function ephemeralScreenshotPath(kind, directory = tempScreenshotDir(), createdA
|
|
|
333656
333766
|
const pid = Math.max(1, Math.floor(Number(ownerPid) || process.pid));
|
|
333657
333767
|
const timestamp = Math.max(0, Math.floor(Number(createdAt) || Date.now()));
|
|
333658
333768
|
const nonce = /^[a-f0-9]{8}$/i.test(String(suffix)) ? String(suffix).toLowerCase() : crypto6.randomBytes(4).toString("hex");
|
|
333659
|
-
return
|
|
333769
|
+
return path10.join(directory, `${kind}-p${pid}-t${timestamp}-${nonce}.jpg`);
|
|
333660
333770
|
}
|
|
333661
333771
|
function isProcessAlive(pid) {
|
|
333662
333772
|
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
@@ -333669,14 +333779,14 @@ function isProcessAlive(pid) {
|
|
|
333669
333779
|
}
|
|
333670
333780
|
}
|
|
333671
333781
|
function cleanupStaleScreenshots(options = {}) {
|
|
333672
|
-
const directory = options.directory ||
|
|
333782
|
+
const directory = options.directory || path10.join(os3.tmpdir(), "newmark-computer-use");
|
|
333673
333783
|
const now2 = Number.isFinite(Number(options.now)) ? Number(options.now) : Date.now();
|
|
333674
333784
|
const processAlive = options.isProcessAlive || isProcessAlive;
|
|
333675
333785
|
const ownedPattern = /^(?:observe|app)-p([1-9]\d*)-t(\d{10,16})-[a-f0-9]{8}\.jpg$/i;
|
|
333676
333786
|
const legacyPattern = /^(?:observe|app)-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z-[a-f0-9]{8}\.jpg$/i;
|
|
333677
333787
|
let names = [];
|
|
333678
333788
|
try {
|
|
333679
|
-
names =
|
|
333789
|
+
names = fs9.readdirSync(directory);
|
|
333680
333790
|
} catch {
|
|
333681
333791
|
return { removed: 0 };
|
|
333682
333792
|
}
|
|
@@ -333685,10 +333795,10 @@ function cleanupStaleScreenshots(options = {}) {
|
|
|
333685
333795
|
const owned = ownedPattern.exec(name50);
|
|
333686
333796
|
const isLegacy = !owned && legacyPattern.test(name50);
|
|
333687
333797
|
if (!owned && !isLegacy) continue;
|
|
333688
|
-
const filePath =
|
|
333798
|
+
const filePath = path10.join(directory, name50);
|
|
333689
333799
|
let stats;
|
|
333690
333800
|
try {
|
|
333691
|
-
stats =
|
|
333801
|
+
stats = fs9.lstatSync(filePath);
|
|
333692
333802
|
if (!stats.isFile() || stats.isSymbolicLink()) continue;
|
|
333693
333803
|
} catch {
|
|
333694
333804
|
continue;
|
|
@@ -333712,7 +333822,7 @@ function cleanupStaleScreenshots(options = {}) {
|
|
|
333712
333822
|
}
|
|
333713
333823
|
if (!shouldRemove) continue;
|
|
333714
333824
|
try {
|
|
333715
|
-
|
|
333825
|
+
fs9.unlinkSync(filePath);
|
|
333716
333826
|
removed += 1;
|
|
333717
333827
|
} catch {
|
|
333718
333828
|
}
|
|
@@ -333735,7 +333845,7 @@ function captureBounds(maxWidth, maxHeight) {
|
|
|
333735
333845
|
}
|
|
333736
333846
|
function removeEphemeralScreenshot(outPath) {
|
|
333737
333847
|
try {
|
|
333738
|
-
|
|
333848
|
+
fs9.unlinkSync(outPath);
|
|
333739
333849
|
} catch {
|
|
333740
333850
|
}
|
|
333741
333851
|
}
|
|
@@ -333811,7 +333921,7 @@ async function startTakeoverOverlay(durationMs = 0, input = {}) {
|
|
|
333811
333921
|
const width = 2;
|
|
333812
333922
|
const speedSeconds = 3;
|
|
333813
333923
|
const ownerPid = Math.max(0, Math.floor(Number(input.ownerPid ?? process.pid) || 0));
|
|
333814
|
-
const scriptPath =
|
|
333924
|
+
const scriptPath = path10.join(tempScreenshotDir(), `takeover-overlay-${timestampName()}-${crypto6.randomBytes(4).toString("hex")}.ps1`);
|
|
333815
333925
|
const script = [
|
|
333816
333926
|
"Add-Type -AssemblyName System.Windows.Forms",
|
|
333817
333927
|
"Add-Type -AssemblyName System.Drawing",
|
|
@@ -333950,7 +334060,7 @@ async function startTakeoverOverlay(durationMs = 0, input = {}) {
|
|
|
333950
334060
|
"[System.Windows.Forms.Application]::Run()",
|
|
333951
334061
|
"try { Remove-Item -LiteralPath $PSCommandPath -Force -ErrorAction SilentlyContinue } catch {}"
|
|
333952
334062
|
].filter(Boolean).join("\r\n");
|
|
333953
|
-
|
|
334063
|
+
fs9.writeFileSync(scriptPath, `\uFEFF${script}`, "utf8");
|
|
333954
334064
|
const createCommand = [
|
|
333955
334065
|
`$cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File ' + ${psQuote(`"${scriptPath}"`)}`,
|
|
333956
334066
|
`$startup = ([wmiclass]'Win32_ProcessStartup').CreateInstance()`,
|
|
@@ -333963,7 +334073,7 @@ async function startTakeoverOverlay(durationMs = 0, input = {}) {
|
|
|
333963
334073
|
const pid = Number(String(result.output || "").trim().split(/\r?\n/).pop() || 0);
|
|
333964
334074
|
if (!Number.isFinite(pid) || pid <= 0 || !result.ok) {
|
|
333965
334075
|
try {
|
|
333966
|
-
|
|
334076
|
+
fs9.unlinkSync(scriptPath);
|
|
333967
334077
|
} catch {
|
|
333968
334078
|
}
|
|
333969
334079
|
return { ok: false, action: "takeover_start", error: result.output || "Overlay failed to start." };
|
|
@@ -333990,7 +334100,7 @@ function parseJsonArray(text) {
|
|
|
333990
334100
|
return [];
|
|
333991
334101
|
}
|
|
333992
334102
|
function observationKey(workspacePath, ownerId) {
|
|
333993
|
-
return `${
|
|
334103
|
+
return `${path10.resolve(workspacePath || process.cwd()).toLowerCase()}::${String(ownerId || "direct")}`;
|
|
333994
334104
|
}
|
|
333995
334105
|
function sceneGeneration(apps, elements) {
|
|
333996
334106
|
const seed = [
|
|
@@ -334206,7 +334316,7 @@ async function cropScreenshot(workspacePath, ownerId, allowEphemeralVisionImage,
|
|
|
334206
334316
|
...parsed
|
|
334207
334317
|
};
|
|
334208
334318
|
if (includeRawUi) payload.perception.elements = elements;
|
|
334209
|
-
const imageAvailable = parsed.image_available === true &&
|
|
334319
|
+
const imageAvailable = parsed.image_available === true && fs9.existsSync(outPath);
|
|
334210
334320
|
if (allowEphemeralVisionImage && imageAvailable) {
|
|
334211
334321
|
payload.vision_image_path = outPath;
|
|
334212
334322
|
retainedForVision = true;
|
|
@@ -334469,7 +334579,7 @@ async function screenshot(workspacePath, ownerId, allowEphemeralVisionImage, inc
|
|
|
334469
334579
|
...parsed
|
|
334470
334580
|
};
|
|
334471
334581
|
if (includeRawUi) payload.perception.elements = ui.elements;
|
|
334472
|
-
const imageAvailable = parsed.image_available === true &&
|
|
334582
|
+
const imageAvailable = parsed.image_available === true && fs9.existsSync(outPath);
|
|
334473
334583
|
if (allowEphemeralVisionImage && imageAvailable) {
|
|
334474
334584
|
payload.vision_image_path = outPath;
|
|
334475
334585
|
retainedForVision = true;
|
|
@@ -334793,13 +334903,13 @@ async function runComputerUse(options) {
|
|
|
334793
334903
|
}
|
|
334794
334904
|
|
|
334795
334905
|
// src/core/ssh.ts
|
|
334796
|
-
var
|
|
334797
|
-
var
|
|
334906
|
+
var fs11 = __toESM(require("fs"));
|
|
334907
|
+
var path12 = __toESM(require("path"));
|
|
334798
334908
|
|
|
334799
334909
|
// src/core/asyncProcess.ts
|
|
334800
334910
|
var import_child_process4 = require("child_process");
|
|
334801
|
-
var
|
|
334802
|
-
var
|
|
334911
|
+
var fs10 = __toESM(require("fs/promises"));
|
|
334912
|
+
var path11 = __toESM(require("path"));
|
|
334803
334913
|
var STOP_SETTLEMENT_WATCHDOG_MS = 500;
|
|
334804
334914
|
function signalMessage(signal) {
|
|
334805
334915
|
const reason = signal?.reason;
|
|
@@ -334809,7 +334919,7 @@ function signalMessage(signal) {
|
|
|
334809
334919
|
}
|
|
334810
334920
|
function trustedWindowsTaskkillPath() {
|
|
334811
334921
|
const windowsRoot = String(process.env.SystemRoot || process.env.WINDIR || "C:\\Windows");
|
|
334812
|
-
return
|
|
334922
|
+
return path11.join(windowsRoot, "System32", "taskkill.exe");
|
|
334813
334923
|
}
|
|
334814
334924
|
function stopProcessTree(child) {
|
|
334815
334925
|
const pid = child.pid;
|
|
@@ -334978,7 +335088,7 @@ async function runAsyncWindowsBatch(command, args, options = {}) {
|
|
|
334978
335088
|
}
|
|
334979
335089
|
async function accessible(filePath) {
|
|
334980
335090
|
try {
|
|
334981
|
-
await
|
|
335091
|
+
await fs10.access(filePath);
|
|
334982
335092
|
return true;
|
|
334983
335093
|
} catch {
|
|
334984
335094
|
return false;
|
|
@@ -334987,14 +335097,14 @@ async function accessible(filePath) {
|
|
|
334987
335097
|
async function resolveWindowsLauncher(command) {
|
|
334988
335098
|
const clean = String(command || "").trim();
|
|
334989
335099
|
if (!clean) return "";
|
|
334990
|
-
if (
|
|
334991
|
-
const absolute =
|
|
335100
|
+
if (path11.isAbsolute(clean) || /[\\/]/.test(clean)) {
|
|
335101
|
+
const absolute = path11.resolve(clean);
|
|
334992
335102
|
return await accessible(absolute) ? absolute : "";
|
|
334993
335103
|
}
|
|
334994
|
-
for (const entry of String(process.env.PATH || "").split(
|
|
335104
|
+
for (const entry of String(process.env.PATH || "").split(path11.delimiter)) {
|
|
334995
335105
|
const directory = entry.trim().replace(/^"|"$/g, "");
|
|
334996
335106
|
if (!directory) continue;
|
|
334997
|
-
const candidate =
|
|
335107
|
+
const candidate = path11.join(directory, clean);
|
|
334998
335108
|
if (await accessible(candidate)) return candidate;
|
|
334999
335109
|
}
|
|
335000
335110
|
return "";
|
|
@@ -335002,11 +335112,11 @@ async function resolveWindowsLauncher(command) {
|
|
|
335002
335112
|
async function resolveNpmBatchTarget(batchPath) {
|
|
335003
335113
|
let source = "";
|
|
335004
335114
|
try {
|
|
335005
|
-
source = await
|
|
335115
|
+
source = await fs10.readFile(batchPath, "utf8");
|
|
335006
335116
|
} catch {
|
|
335007
335117
|
return null;
|
|
335008
335118
|
}
|
|
335009
|
-
const directory =
|
|
335119
|
+
const directory = path11.dirname(batchPath);
|
|
335010
335120
|
let relativeScript = "";
|
|
335011
335121
|
const direct = /(?:%~dp0|%dp0%)\\?([^"\r\n]+)"\s+%\*/i.exec(source);
|
|
335012
335122
|
if (direct) relativeScript = direct[1];
|
|
@@ -335020,10 +335130,10 @@ async function resolveNpmBatchTarget(batchPath) {
|
|
|
335020
335130
|
}
|
|
335021
335131
|
}
|
|
335022
335132
|
if (!relativeScript) return null;
|
|
335023
|
-
const scriptPath =
|
|
335024
|
-
const directoryPrefix = `${
|
|
335133
|
+
const scriptPath = path11.resolve(directory, relativeScript.replace(/\\/g, path11.sep));
|
|
335134
|
+
const directoryPrefix = `${path11.resolve(directory).toLowerCase()}${path11.sep}`;
|
|
335025
335135
|
if (!scriptPath.toLowerCase().startsWith(directoryPrefix) || !await accessible(scriptPath)) return null;
|
|
335026
|
-
const siblingNode =
|
|
335136
|
+
const siblingNode = path11.join(directory, "node.exe");
|
|
335027
335137
|
const nodePath = await accessible(siblingNode) ? siblingNode : await resolveWindowsLauncher("node.exe") || await resolveWindowsLauncher("node");
|
|
335028
335138
|
return nodePath ? { nodePath, scriptPath } : null;
|
|
335029
335139
|
}
|
|
@@ -335066,19 +335176,19 @@ var SshManager = class {
|
|
|
335066
335176
|
rootPath;
|
|
335067
335177
|
runner;
|
|
335068
335178
|
storePath() {
|
|
335069
|
-
return
|
|
335179
|
+
return path12.join(this.rootPath, "Work", "SSH.json");
|
|
335070
335180
|
}
|
|
335071
335181
|
ensureStore() {
|
|
335072
335182
|
try {
|
|
335073
|
-
|
|
335074
|
-
if (!
|
|
335183
|
+
fs11.mkdirSync(path12.join(this.rootPath, "Work"), { recursive: true });
|
|
335184
|
+
if (!fs11.existsSync(this.storePath())) fs11.writeFileSync(this.storePath(), "[]", "utf-8");
|
|
335075
335185
|
} catch {
|
|
335076
335186
|
}
|
|
335077
335187
|
}
|
|
335078
335188
|
readRaw() {
|
|
335079
335189
|
this.ensureStore();
|
|
335080
335190
|
try {
|
|
335081
|
-
const parsed = JSON.parse(
|
|
335191
|
+
const parsed = JSON.parse(fs11.readFileSync(this.storePath(), "utf-8").replace(/^\uFEFF/, ""));
|
|
335082
335192
|
if (!Array.isArray(parsed)) return [];
|
|
335083
335193
|
return parsed.map((item) => this.normalize(item)).filter((item) => !!item);
|
|
335084
335194
|
} catch {
|
|
@@ -335087,7 +335197,7 @@ var SshManager = class {
|
|
|
335087
335197
|
}
|
|
335088
335198
|
writeRaw(items) {
|
|
335089
335199
|
this.ensureStore();
|
|
335090
|
-
|
|
335200
|
+
fs11.writeFileSync(this.storePath(), JSON.stringify(items, null, 2), "utf-8");
|
|
335091
335201
|
}
|
|
335092
335202
|
normalize(raw) {
|
|
335093
335203
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
@@ -335267,8 +335377,8 @@ var SshManager = class {
|
|
|
335267
335377
|
};
|
|
335268
335378
|
|
|
335269
335379
|
// src/core/workspace.ts
|
|
335270
|
-
var
|
|
335271
|
-
var
|
|
335380
|
+
var fs12 = __toESM(require("fs"));
|
|
335381
|
+
var path13 = __toESM(require("path"));
|
|
335272
335382
|
var crypto7 = __toESM(require("crypto"));
|
|
335273
335383
|
function lastEmbeddedWindowsPath(input) {
|
|
335274
335384
|
const matcher = /[A-Za-z]:[\\/]/g;
|
|
@@ -335287,22 +335397,22 @@ function normalizeHostWorkspacePath(input, platform = process.platform) {
|
|
|
335287
335397
|
const raw = String(input || "").trim();
|
|
335288
335398
|
const embeddedWindowsPath = lastEmbeddedWindowsPath(raw);
|
|
335289
335399
|
if (platform === "win32") {
|
|
335290
|
-
if (embeddedWindowsPath) return
|
|
335400
|
+
if (embeddedWindowsPath) return path13.win32.normalize(embeddedWindowsPath.replace(/\//g, "\\"));
|
|
335291
335401
|
const wsl = /^\/mnt\/([a-zA-Z])(?:\/(.*))?$/.exec(raw.replace(/\\/g, "/"));
|
|
335292
|
-
if (wsl) return
|
|
335293
|
-
return
|
|
335402
|
+
if (wsl) return path13.win32.normalize(`${wsl[1].toUpperCase()}:\\${String(wsl[2] || "").replace(/\//g, "\\")}`);
|
|
335403
|
+
return path13.win32.resolve(raw || ".");
|
|
335294
335404
|
}
|
|
335295
335405
|
if (platform === "linux" && embeddedWindowsPath) {
|
|
335296
335406
|
const drive = embeddedWindowsPath[0].toLowerCase();
|
|
335297
335407
|
const rest = embeddedWindowsPath.slice(3).replace(/\\/g, "/").replace(/^\/+/, "");
|
|
335298
|
-
return
|
|
335408
|
+
return path13.posix.resolve(`/mnt/${drive}/${rest}`);
|
|
335299
335409
|
}
|
|
335300
|
-
return
|
|
335410
|
+
return path13.posix.resolve(raw || ".");
|
|
335301
335411
|
}
|
|
335302
335412
|
function isPathInside(parent, child) {
|
|
335303
335413
|
try {
|
|
335304
|
-
const relative6 =
|
|
335305
|
-
return relative6 === "" || !!relative6 && !relative6.startsWith("..") && !
|
|
335414
|
+
const relative6 = path13.relative(path13.resolve(parent), path13.resolve(child));
|
|
335415
|
+
return relative6 === "" || !!relative6 && !relative6.startsWith("..") && !path13.isAbsolute(relative6);
|
|
335306
335416
|
} catch {
|
|
335307
335417
|
return false;
|
|
335308
335418
|
}
|
|
@@ -335310,7 +335420,7 @@ function isPathInside(parent, child) {
|
|
|
335310
335420
|
function isProtectedInstallWorkspacePath(candidate) {
|
|
335311
335421
|
const value = String(candidate || "").trim();
|
|
335312
335422
|
if (!value) return false;
|
|
335313
|
-
const roots = [
|
|
335423
|
+
const roots = [path13.dirname(process.execPath)];
|
|
335314
335424
|
if (process.platform === "win32") {
|
|
335315
335425
|
roots.push(
|
|
335316
335426
|
process.env.ProgramFiles || "",
|
|
@@ -335318,7 +335428,7 @@ function isProtectedInstallWorkspacePath(candidate) {
|
|
|
335318
335428
|
process.env.ProgramW6432 || ""
|
|
335319
335429
|
);
|
|
335320
335430
|
}
|
|
335321
|
-
const resolved =
|
|
335431
|
+
const resolved = path13.resolve(value);
|
|
335322
335432
|
return roots.filter(Boolean).some((root2) => isPathInside(root2, resolved));
|
|
335323
335433
|
}
|
|
335324
335434
|
var WorkspaceManager = class {
|
|
@@ -335328,16 +335438,16 @@ var WorkspaceManager = class {
|
|
|
335328
335438
|
this.detached = options.detached === true;
|
|
335329
335439
|
this.pcHash = this.loadPcHash();
|
|
335330
335440
|
if (this.detached) return;
|
|
335331
|
-
const workDir =
|
|
335441
|
+
const workDir = path13.join(rootPath, "Work");
|
|
335332
335442
|
try {
|
|
335333
|
-
|
|
335443
|
+
fs12.mkdirSync(workDir, { recursive: true });
|
|
335334
335444
|
} catch {
|
|
335335
335445
|
}
|
|
335336
335446
|
for (const fn of ["Local.json", "External.json"]) {
|
|
335337
|
-
const p =
|
|
335338
|
-
if (!
|
|
335447
|
+
const p = path13.join(workDir, fn);
|
|
335448
|
+
if (!fs12.existsSync(p)) {
|
|
335339
335449
|
try {
|
|
335340
|
-
|
|
335450
|
+
fs12.writeFileSync(p, "[]", "utf-8");
|
|
335341
335451
|
} catch {
|
|
335342
335452
|
}
|
|
335343
335453
|
}
|
|
@@ -335358,7 +335468,7 @@ var WorkspaceManager = class {
|
|
|
335358
335468
|
detached;
|
|
335359
335469
|
loadPcHash() {
|
|
335360
335470
|
try {
|
|
335361
|
-
const h2 =
|
|
335471
|
+
const h2 = fs12.readFileSync(path13.join(this.rootPath, "PC_Hash.config"), "utf-8");
|
|
335362
335472
|
return h2.trim();
|
|
335363
335473
|
} catch {
|
|
335364
335474
|
return "";
|
|
@@ -335373,19 +335483,19 @@ var WorkspaceManager = class {
|
|
|
335373
335483
|
if (this.external.length !== before) this.saveExternal();
|
|
335374
335484
|
}
|
|
335375
335485
|
scan() {
|
|
335376
|
-
const w =
|
|
335377
|
-
if (!
|
|
335486
|
+
const w = path13.join(this.rootPath, "Work");
|
|
335487
|
+
if (!fs12.existsSync(w)) return;
|
|
335378
335488
|
let internalChanged = false;
|
|
335379
335489
|
let externalChanged = false;
|
|
335380
335490
|
try {
|
|
335381
|
-
const local = JSON.parse(
|
|
335491
|
+
const local = JSON.parse(fs12.readFileSync(path13.join(w, "Local.json"), "utf-8"));
|
|
335382
335492
|
this.internal = Array.isArray(local) ? local.map((item) => this.normalizeInternalWorkspace(item, (changed) => {
|
|
335383
335493
|
internalChanged = internalChanged || changed;
|
|
335384
335494
|
})) : [];
|
|
335385
335495
|
} catch {
|
|
335386
335496
|
}
|
|
335387
335497
|
try {
|
|
335388
|
-
const ext = JSON.parse(
|
|
335498
|
+
const ext = JSON.parse(fs12.readFileSync(path13.join(w, "External.json"), "utf-8"));
|
|
335389
335499
|
const normalized = Array.isArray(ext) ? ext.map((item) => this.normalizeExternalWorkspace(item, (changed) => {
|
|
335390
335500
|
externalChanged = externalChanged || changed;
|
|
335391
335501
|
})) : [];
|
|
@@ -335396,13 +335506,13 @@ var WorkspaceManager = class {
|
|
|
335396
335506
|
});
|
|
335397
335507
|
} catch {
|
|
335398
335508
|
}
|
|
335399
|
-
for (const entry of
|
|
335509
|
+
for (const entry of fs12.readdirSync(w, { withFileTypes: true })) {
|
|
335400
335510
|
if (entry.isDirectory() && !["Local.json", "External.json", ".ssh"].includes(entry.name)) {
|
|
335401
335511
|
if (!this.internal.find((wi) => wi.name === entry.name)) {
|
|
335402
335512
|
this.internal.push({
|
|
335403
|
-
id: this.stableWorkspaceId("local",
|
|
335513
|
+
id: this.stableWorkspaceId("local", path13.join(w, entry.name)),
|
|
335404
335514
|
name: entry.name,
|
|
335405
|
-
path:
|
|
335515
|
+
path: path13.join(w, entry.name),
|
|
335406
335516
|
isInternal: true,
|
|
335407
335517
|
hostBinding: "",
|
|
335408
335518
|
icon: entry.name.charAt(0).toUpperCase()
|
|
@@ -335415,9 +335525,9 @@ var WorkspaceManager = class {
|
|
|
335415
335525
|
if (externalChanged) this.saveExternal();
|
|
335416
335526
|
}
|
|
335417
335527
|
normalizeInternalWorkspace(input, markChanged) {
|
|
335418
|
-
const rawName = String(input?.name ||
|
|
335528
|
+
const rawName = String(input?.name || path13.basename(String(input?.path || "")) || "").trim();
|
|
335419
335529
|
const name50 = rawName || (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace("T", "_").slice(0, 15);
|
|
335420
|
-
const expectedPath =
|
|
335530
|
+
const expectedPath = path13.join(this.rootPath, "Work", name50);
|
|
335421
335531
|
const id = this.stableWorkspaceId("local", expectedPath);
|
|
335422
335532
|
if (normalizeHostWorkspacePath(String(input?.path || "")) !== normalizeHostWorkspacePath(expectedPath) || input?.isInternal !== true || input?.id !== id) markChanged(true);
|
|
335423
335533
|
return {
|
|
@@ -335438,11 +335548,11 @@ var WorkspaceManager = class {
|
|
|
335438
335548
|
return {
|
|
335439
335549
|
...input,
|
|
335440
335550
|
id,
|
|
335441
|
-
name: String(input?.name ||
|
|
335551
|
+
name: String(input?.name || path13.basename(workspacePath) || id),
|
|
335442
335552
|
path: workspacePath,
|
|
335443
335553
|
isInternal: false,
|
|
335444
335554
|
hostBinding: String(input?.hostBinding || ""),
|
|
335445
|
-
icon: String(input?.icon ||
|
|
335555
|
+
icon: String(input?.icon || path13.basename(workspacePath).charAt(0).toUpperCase()),
|
|
335446
335556
|
kind
|
|
335447
335557
|
};
|
|
335448
335558
|
}
|
|
@@ -335463,11 +335573,11 @@ var WorkspaceManager = class {
|
|
|
335463
335573
|
const resolved = normalizeHostWorkspacePath(target);
|
|
335464
335574
|
let real = resolved;
|
|
335465
335575
|
try {
|
|
335466
|
-
real =
|
|
335576
|
+
real = fs12.existsSync(resolved) ? fs12.realpathSync.native(resolved) : resolved;
|
|
335467
335577
|
} catch {
|
|
335468
335578
|
real = resolved;
|
|
335469
335579
|
}
|
|
335470
|
-
const normalized =
|
|
335580
|
+
const normalized = path13.normalize(real).replace(/[\\/]+$/, "");
|
|
335471
335581
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
335472
335582
|
}
|
|
335473
335583
|
stableWorkspaceId(kind, workspacePath) {
|
|
@@ -335493,8 +335603,8 @@ var WorkspaceManager = class {
|
|
|
335493
335603
|
isInsideRoot(target) {
|
|
335494
335604
|
const root2 = this.canonicalWorkspacePath(this.rootPath);
|
|
335495
335605
|
const candidate = this.canonicalWorkspacePath(target);
|
|
335496
|
-
const rel =
|
|
335497
|
-
return rel === "" || !!rel && !rel.startsWith("..") && !
|
|
335606
|
+
const rel = path13.relative(root2, candidate);
|
|
335607
|
+
return rel === "" || !!rel && !rel.startsWith("..") && !path13.isAbsolute(rel);
|
|
335498
335608
|
}
|
|
335499
335609
|
canonicalRemotePath(target) {
|
|
335500
335610
|
let cleaned = String(target || "").trim().replace(/\\/g, "/").replace(/\/+$/g, "");
|
|
@@ -335523,13 +335633,13 @@ var WorkspaceManager = class {
|
|
|
335523
335633
|
return deduped;
|
|
335524
335634
|
}
|
|
335525
335635
|
statePath() {
|
|
335526
|
-
return
|
|
335636
|
+
return path13.join(this.rootPath, "Work", "State.json");
|
|
335527
335637
|
}
|
|
335528
335638
|
readState() {
|
|
335529
335639
|
const p = this.statePath();
|
|
335530
|
-
if (!
|
|
335640
|
+
if (!fs12.existsSync(p)) return {};
|
|
335531
335641
|
try {
|
|
335532
|
-
const raw =
|
|
335642
|
+
const raw = fs12.readFileSync(p, "utf-8").replace(/^\uFEFF/, "");
|
|
335533
335643
|
const parsed = JSON.parse(raw);
|
|
335534
335644
|
if (parsed && typeof parsed === "object") return parsed;
|
|
335535
335645
|
} catch {
|
|
@@ -335550,8 +335660,8 @@ var WorkspaceManager = class {
|
|
|
335550
335660
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
335551
335661
|
};
|
|
335552
335662
|
try {
|
|
335553
|
-
|
|
335554
|
-
|
|
335663
|
+
fs12.mkdirSync(path13.dirname(p), { recursive: true });
|
|
335664
|
+
fs12.writeFileSync(p, JSON.stringify(state, null, 2), "utf-8");
|
|
335555
335665
|
} catch {
|
|
335556
335666
|
}
|
|
335557
335667
|
}
|
|
@@ -335610,17 +335720,17 @@ var WorkspaceManager = class {
|
|
|
335610
335720
|
}
|
|
335611
335721
|
saveInternal() {
|
|
335612
335722
|
if (this.detached) return;
|
|
335613
|
-
const p =
|
|
335723
|
+
const p = path13.join(this.rootPath, "Work", "Local.json");
|
|
335614
335724
|
this.internal = this.dedupeByPath(this.internal);
|
|
335615
335725
|
this.sortWorkspaces();
|
|
335616
|
-
|
|
335726
|
+
fs12.writeFileSync(p, JSON.stringify(this.internal, null, 2), "utf-8");
|
|
335617
335727
|
}
|
|
335618
335728
|
saveExternal() {
|
|
335619
335729
|
if (this.detached) return;
|
|
335620
|
-
const p =
|
|
335730
|
+
const p = path13.join(this.rootPath, "Work", "External.json");
|
|
335621
335731
|
this.external = this.dedupeByPath(this.external);
|
|
335622
335732
|
this.sortWorkspaces();
|
|
335623
|
-
|
|
335733
|
+
fs12.writeFileSync(p, JSON.stringify(this.external, null, 2), "utf-8");
|
|
335624
335734
|
}
|
|
335625
335735
|
sleepSync(ms) {
|
|
335626
335736
|
if (ms <= 0) return;
|
|
@@ -335628,48 +335738,48 @@ var WorkspaceManager = class {
|
|
|
335628
335738
|
Atomics.wait(new Int32Array(buffer), 0, 0, ms);
|
|
335629
335739
|
}
|
|
335630
335740
|
isInternalWorkspacePath(target) {
|
|
335631
|
-
const workRoot =
|
|
335632
|
-
const resolved =
|
|
335633
|
-
const rel =
|
|
335634
|
-
return !!rel && !rel.startsWith("..") && !
|
|
335741
|
+
const workRoot = path13.resolve(this.rootPath, "Work");
|
|
335742
|
+
const resolved = path13.resolve(target);
|
|
335743
|
+
const rel = path13.relative(workRoot, resolved);
|
|
335744
|
+
return !!rel && !rel.startsWith("..") && !path13.isAbsolute(rel);
|
|
335635
335745
|
}
|
|
335636
335746
|
clearReadOnlyRecursive(target) {
|
|
335637
|
-
if (!
|
|
335638
|
-
const stat =
|
|
335747
|
+
if (!fs12.existsSync(target)) return;
|
|
335748
|
+
const stat = fs12.lstatSync(target);
|
|
335639
335749
|
try {
|
|
335640
|
-
|
|
335750
|
+
fs12.chmodSync(target, stat.mode | 448);
|
|
335641
335751
|
} catch {
|
|
335642
335752
|
}
|
|
335643
335753
|
if (!stat.isDirectory()) return;
|
|
335644
|
-
for (const entry of
|
|
335645
|
-
this.clearReadOnlyRecursive(
|
|
335754
|
+
for (const entry of fs12.readdirSync(target)) {
|
|
335755
|
+
this.clearReadOnlyRecursive(path13.join(target, entry));
|
|
335646
335756
|
}
|
|
335647
335757
|
}
|
|
335648
335758
|
removeInternalDirectory(target) {
|
|
335649
|
-
const resolved =
|
|
335759
|
+
const resolved = path13.resolve(target);
|
|
335650
335760
|
if (!this.isInternalWorkspacePath(resolved)) return false;
|
|
335651
|
-
if (!
|
|
335761
|
+
if (!fs12.existsSync(resolved)) return true;
|
|
335652
335762
|
const delays = [0, 50, 100, 200, 400, 800, 1200];
|
|
335653
335763
|
for (const delay of delays) {
|
|
335654
335764
|
this.sleepSync(delay);
|
|
335655
335765
|
try {
|
|
335656
|
-
|
|
335766
|
+
fs12.rmSync(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
335657
335767
|
} catch {
|
|
335658
335768
|
}
|
|
335659
|
-
if (!
|
|
335769
|
+
if (!fs12.existsSync(resolved)) return true;
|
|
335660
335770
|
try {
|
|
335661
335771
|
this.clearReadOnlyRecursive(resolved);
|
|
335662
|
-
|
|
335772
|
+
fs12.rmSync(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
335663
335773
|
} catch {
|
|
335664
335774
|
}
|
|
335665
|
-
if (!
|
|
335775
|
+
if (!fs12.existsSync(resolved)) return true;
|
|
335666
335776
|
}
|
|
335667
335777
|
return false;
|
|
335668
335778
|
}
|
|
335669
335779
|
createInternal(name50) {
|
|
335670
335780
|
const n3 = name50 || (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace("T", "_").slice(0, 15);
|
|
335671
|
-
const d3 =
|
|
335672
|
-
|
|
335781
|
+
const d3 = path13.join(this.rootPath, "Work", n3);
|
|
335782
|
+
fs12.mkdirSync(d3, { recursive: true });
|
|
335673
335783
|
const existing = this.findWorkspaceByPath(d3);
|
|
335674
335784
|
if (existing) {
|
|
335675
335785
|
this.current = existing;
|
|
@@ -335691,15 +335801,15 @@ var WorkspaceManager = class {
|
|
|
335691
335801
|
return ws;
|
|
335692
335802
|
}
|
|
335693
335803
|
addExternal(p) {
|
|
335694
|
-
const resolved =
|
|
335695
|
-
if (!
|
|
335804
|
+
const resolved = path13.resolve(p);
|
|
335805
|
+
if (!fs12.existsSync(resolved) || this.isInsideRoot(resolved)) return null;
|
|
335696
335806
|
const existing = this.findWorkspaceByPath(resolved);
|
|
335697
335807
|
if (existing) {
|
|
335698
335808
|
this.current = existing;
|
|
335699
335809
|
this.saveState();
|
|
335700
335810
|
return existing;
|
|
335701
335811
|
}
|
|
335702
|
-
const name50 =
|
|
335812
|
+
const name50 = path13.basename(resolved);
|
|
335703
335813
|
const ws = {
|
|
335704
335814
|
id: this.stableWorkspaceId("local", resolved),
|
|
335705
335815
|
name: name50,
|
|
@@ -335717,10 +335827,10 @@ var WorkspaceManager = class {
|
|
|
335717
335827
|
addSshExternal(input) {
|
|
335718
335828
|
if (!input.sshConnectionId || !input.remotePath || !input.remotePcHash) return null;
|
|
335719
335829
|
const remotePath = this.canonicalRemotePath(input.remotePath);
|
|
335720
|
-
const baseName = (input.name ||
|
|
335830
|
+
const baseName = (input.name || path13.basename(remotePath.replace(/[\\/]+$/, "")) || input.sshConnectionId || "ssh-workspace").trim();
|
|
335721
335831
|
const safeName = baseName.replace(/[<>:"/\\|?*\x00-\x1F]/g, "-").replace(/\s+/g, " ").trim() || "ssh-workspace";
|
|
335722
|
-
const shadowRoot = input.localPath ?
|
|
335723
|
-
|
|
335832
|
+
const shadowRoot = input.localPath ? path13.resolve(input.localPath) : path13.join(this.rootPath, "Work", ".ssh", `${input.sshConnectionId}-${crypto7.createHash("sha256").update(remotePath).digest("hex").slice(0, 16)}`);
|
|
335833
|
+
fs12.mkdirSync(shadowRoot, { recursive: true });
|
|
335724
335834
|
const existing = this.findSshWorkspaceByRemotePath(input.sshConnectionId, remotePath);
|
|
335725
335835
|
const ws = {
|
|
335726
335836
|
...existing || {},
|
|
@@ -335802,7 +335912,7 @@ var WorkspaceManager = class {
|
|
|
335802
335912
|
currentAgentPrompt() {
|
|
335803
335913
|
if (!this.current) return null;
|
|
335804
335914
|
try {
|
|
335805
|
-
return
|
|
335915
|
+
return fs12.readFileSync(path13.join(this.current.path, "agent.md"), "utf-8");
|
|
335806
335916
|
} catch {
|
|
335807
335917
|
return null;
|
|
335808
335918
|
}
|
|
@@ -335811,8 +335921,8 @@ var WorkspaceManager = class {
|
|
|
335811
335921
|
const perm = this.config.getStr("workspace", "access_permission");
|
|
335812
335922
|
if (perm === "full_access") return true;
|
|
335813
335923
|
if (!this.current) return perm !== "no_outside_access";
|
|
335814
|
-
const rel =
|
|
335815
|
-
const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !
|
|
335924
|
+
const rel = path13.relative(path13.resolve(this.current.path), path13.resolve(target));
|
|
335925
|
+
const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !path13.isAbsolute(rel);
|
|
335816
335926
|
if (inside2) return true;
|
|
335817
335927
|
return perm !== "no_outside_access";
|
|
335818
335928
|
}
|
|
@@ -335895,6 +336005,7 @@ var PLAN_COMPUTER_USE_ACTIONS = ["observe", "app_list", "app_observe"];
|
|
|
335895
336005
|
var PLAN_BROWSER_USE_ACTIONS = ["observe", "navigate", "wait", "extract"];
|
|
335896
336006
|
var PLAN_COMPUTER_USE_ACTION_SET = new Set(PLAN_COMPUTER_USE_ACTIONS);
|
|
335897
336007
|
var PLAN_BROWSER_USE_ACTION_SET = new Set(PLAN_BROWSER_USE_ACTIONS);
|
|
336008
|
+
var CHAT_WEB_TOOLS = /* @__PURE__ */ new Set(["web_search", "web_fetch"]);
|
|
335898
336009
|
var CONCURRENCY_SAFE_TOOLS = /* @__PURE__ */ new Set([
|
|
335899
336010
|
"pwd",
|
|
335900
336011
|
"read",
|
|
@@ -335928,6 +336039,13 @@ function evaluateToolPolicy(request) {
|
|
|
335928
336039
|
const availability = toolAvailability(name50);
|
|
335929
336040
|
const base2 = { availability, settingsVisible: availability === "configurable" };
|
|
335930
336041
|
if (!name50) return { ...base2, allowed: false, reason: "[permission] Tool name is required." };
|
|
336042
|
+
if (request.mode === "chat" && !CHAT_WEB_TOOLS.has(name50)) {
|
|
336043
|
+
return {
|
|
336044
|
+
...base2,
|
|
336045
|
+
allowed: false,
|
|
336046
|
+
reason: `[permission] Chat mode only allows web_search and web_fetch. It has no workspace, host, application, memory, task, or other write access. Blocked: ${name50}`
|
|
336047
|
+
};
|
|
336048
|
+
}
|
|
335931
336049
|
if (request.mode === "plan") {
|
|
335932
336050
|
if (name50 === "computer_use") {
|
|
335933
336051
|
const action = String(request.args?.action || "").trim();
|
|
@@ -335969,6 +336087,13 @@ function planModePolicyPrompt() {
|
|
|
335969
336087
|
"Runtime policy rejects stale or hidden mutating tool calls even if a prompt asks for them."
|
|
335970
336088
|
].join(" ");
|
|
335971
336089
|
}
|
|
336090
|
+
function chatModePolicyPrompt() {
|
|
336091
|
+
return [
|
|
336092
|
+
"Chat mode is a narrow web-evidence mode.",
|
|
336093
|
+
"Only web_search and web_fetch are available; every workspace, host, application, memory, task, browser-control, and write capability is denied at runtime.",
|
|
336094
|
+
"Search the web for relevant evidence, fetch primary or authoritative sources when useful, then summarize and answer promptly instead of expanding into a long-running task."
|
|
336095
|
+
].join(" ");
|
|
336096
|
+
}
|
|
335972
336097
|
var DELETE_VERB_SOURCE = "(?:remove-item|rmdir|unlink|erase|del|rm|rd|ri)";
|
|
335973
336098
|
var DELETE_VERB_BOUNDARY = new RegExp(`(?:^|[\\s;&|()\\n])${DELETE_VERB_SOURCE}(?:\\s|$)`, "i");
|
|
335974
336099
|
function hasDeletionVerb(text) {
|
|
@@ -336250,7 +336375,7 @@ function rejectPendingUtilityHostTools(reason) {
|
|
|
336250
336375
|
}
|
|
336251
336376
|
|
|
336252
336377
|
// src/core/nativeBash.ts
|
|
336253
|
-
var
|
|
336378
|
+
var path14 = __toESM(require("path"));
|
|
336254
336379
|
var import_module = require("module");
|
|
336255
336380
|
var MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
336256
336381
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -336338,11 +336463,11 @@ function normalizedTimeout(timeoutMs) {
|
|
|
336338
336463
|
}
|
|
336339
336464
|
function virtualCwd(workspaceRoot, requestedCwd) {
|
|
336340
336465
|
if (!requestedCwd) return "/";
|
|
336341
|
-
const root2 =
|
|
336342
|
-
const cwd =
|
|
336343
|
-
const relative6 =
|
|
336344
|
-
if (relative6.startsWith("..") ||
|
|
336345
|
-
return relative6 ? `/${relative6.split(
|
|
336466
|
+
const root2 = path14.resolve(workspaceRoot);
|
|
336467
|
+
const cwd = path14.resolve(requestedCwd);
|
|
336468
|
+
const relative6 = path14.relative(root2, cwd);
|
|
336469
|
+
if (relative6.startsWith("..") || path14.isAbsolute(relative6)) return "/";
|
|
336470
|
+
return relative6 ? `/${relative6.split(path14.sep).join("/")}` : "/";
|
|
336346
336471
|
}
|
|
336347
336472
|
function combineAbortSignals(signal, timeoutMs) {
|
|
336348
336473
|
const controller = new AbortController();
|
|
@@ -336368,7 +336493,7 @@ function createBash(workspaceRoot, timeoutMs) {
|
|
|
336368
336493
|
const justBash = loadJustBash();
|
|
336369
336494
|
if (!justBash) throw new Error("Native Bash runtime unavailable");
|
|
336370
336495
|
const fs26 = new justBash.ReadWriteFs({
|
|
336371
|
-
root:
|
|
336496
|
+
root: path14.resolve(workspaceRoot),
|
|
336372
336497
|
maxFileReadSize: MAX_OUTPUT_BYTES * 8,
|
|
336373
336498
|
allowSymlinks: false
|
|
336374
336499
|
});
|
|
@@ -336457,12 +336582,12 @@ async function executeWorkspaceBash(script, workspaceRoot, options = {}) {
|
|
|
336457
336582
|
}
|
|
336458
336583
|
|
|
336459
336584
|
// src/core/toolArgumentValidator.ts
|
|
336460
|
-
var
|
|
336461
|
-
var
|
|
336585
|
+
var fs13 = require("fs");
|
|
336586
|
+
var path15 = require("path");
|
|
336462
336587
|
var typeBoxCompilerPath = [
|
|
336463
|
-
|
|
336464
|
-
|
|
336465
|
-
].find((candidate) =>
|
|
336588
|
+
path15.join(__dirname, "..", "typebox-compile.bundle.cjs"),
|
|
336589
|
+
path15.join(__dirname, "typebox-compile.bundle.cjs")
|
|
336590
|
+
].find((candidate) => fs13.existsSync(candidate));
|
|
336466
336591
|
if (!typeBoxCompilerPath) throw new Error("Bundled TypeBox compiler is missing from the Newmark runtime.");
|
|
336467
336592
|
var { Compile } = require(typeBoxCompilerPath);
|
|
336468
336593
|
function closeToolArgumentSchema(input) {
|
|
@@ -336552,8 +336677,8 @@ function formatValidationErrors(name50, errors) {
|
|
|
336552
336677
|
}
|
|
336553
336678
|
|
|
336554
336679
|
// src/core/localOcr.ts
|
|
336555
|
-
var
|
|
336556
|
-
var
|
|
336680
|
+
var fs14 = __toESM(require("fs"));
|
|
336681
|
+
var path16 = __toESM(require("path"));
|
|
336557
336682
|
var AGENT_REPAIR_PROMPT = [
|
|
336558
336683
|
"The local OCR output is approximate Chinese/English fallback evidence.",
|
|
336559
336684
|
"Repair likely OCR substitutions, spacing, and line breaks using the visible UI/PDF context and the user task.",
|
|
@@ -336586,12 +336711,12 @@ var LocalOcrEngine = class {
|
|
|
336586
336711
|
return await this.recognize(dataUrlBuffer(dataUrl), signal, profile);
|
|
336587
336712
|
}
|
|
336588
336713
|
async recognizeFile(filePath, signal) {
|
|
336589
|
-
const absolute =
|
|
336590
|
-
const extension =
|
|
336714
|
+
const absolute = path16.resolve(filePath);
|
|
336715
|
+
const extension = path16.extname(absolute).toLowerCase();
|
|
336591
336716
|
if (![".png", ".jpg", ".jpeg", ".bmp"].includes(extension)) {
|
|
336592
336717
|
throw new Error("Local OCR only accepts PNG, JPEG, or BMP images.");
|
|
336593
336718
|
}
|
|
336594
|
-
const stat =
|
|
336719
|
+
const stat = fs14.statSync(absolute);
|
|
336595
336720
|
if (!stat.isFile() || stat.size <= 0 || stat.size > 12 * 1024 * 1024) {
|
|
336596
336721
|
throw new Error("Local OCR image must be a regular file no larger than 12 MB.");
|
|
336597
336722
|
}
|
|
@@ -336645,7 +336770,7 @@ var LocalOcrEngine = class {
|
|
|
336645
336770
|
const tesseract = require_src();
|
|
336646
336771
|
const worker = await tesseract.createWorker("chi_sim+eng", tesseract.OEM.LSTM_ONLY, {
|
|
336647
336772
|
langPath: tessdataPath,
|
|
336648
|
-
cachePath:
|
|
336773
|
+
cachePath: path16.join(this.rootPath, "cache", "ocr-runtime"),
|
|
336649
336774
|
cacheMethod: "none",
|
|
336650
336775
|
gzip: true,
|
|
336651
336776
|
logger: () => void 0
|
|
@@ -336653,14 +336778,14 @@ var LocalOcrEngine = class {
|
|
|
336653
336778
|
return worker;
|
|
336654
336779
|
}
|
|
336655
336780
|
prepareLanguageCache() {
|
|
336656
|
-
const target =
|
|
336657
|
-
|
|
336781
|
+
const target = path16.join(this.rootPath, "cache", "ocr-tessdata");
|
|
336782
|
+
fs14.mkdirSync(target, { recursive: true });
|
|
336658
336783
|
for (const language of ["eng", "chi_sim"]) {
|
|
336659
|
-
const destination =
|
|
336660
|
-
if (
|
|
336661
|
-
const packageRoot =
|
|
336662
|
-
const source =
|
|
336663
|
-
|
|
336784
|
+
const destination = path16.join(target, `${language}.traineddata.gz`);
|
|
336785
|
+
if (fs14.existsSync(destination) && fs14.statSync(destination).size > 0) continue;
|
|
336786
|
+
const packageRoot = path16.dirname(require.resolve(`@tesseract.js-data/${language}/package.json`));
|
|
336787
|
+
const source = path16.join(packageRoot, "4.0.0_best_int", `${language}.traineddata.gz`);
|
|
336788
|
+
fs14.copyFileSync(source, destination);
|
|
336664
336789
|
}
|
|
336665
336790
|
return target;
|
|
336666
336791
|
}
|
|
@@ -336799,8 +336924,8 @@ function normalizeCrossEnvPath(value, wsPath) {
|
|
|
336799
336924
|
const posix3 = windowsDrivePathToPosix(raw);
|
|
336800
336925
|
if (posix3) return posix3;
|
|
336801
336926
|
}
|
|
336802
|
-
if (
|
|
336803
|
-
return
|
|
336927
|
+
if (path17.isAbsolute(raw)) return raw;
|
|
336928
|
+
return path17.join(wsPath, raw);
|
|
336804
336929
|
}
|
|
336805
336930
|
function translateWindowsPathsForWslBash(script) {
|
|
336806
336931
|
if (!process.env.NEWMARK_WSL_DISTRO) return script;
|
|
@@ -336814,7 +336939,7 @@ function translateWindowsPathsForWslBash(script) {
|
|
|
336814
336939
|
function computerUseOwner(context, wsPath) {
|
|
336815
336940
|
const conversationId = String(context.conversationId || "").trim();
|
|
336816
336941
|
if (conversationId) return `conversation:${conversationId}`;
|
|
336817
|
-
const resolved =
|
|
336942
|
+
const resolved = path17.resolve(context.workspacePath || wsPath || process.cwd());
|
|
336818
336943
|
const workspaceHash = crypto8.createHash("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
336819
336944
|
return `direct:${workspaceHash}`;
|
|
336820
336945
|
}
|
|
@@ -336896,7 +337021,7 @@ function computerUseSessionScope(context, wsPath, owner) {
|
|
|
336896
337021
|
return {
|
|
336897
337022
|
runtimeKey: browserUseScope(context, wsPath).runtimeKey,
|
|
336898
337023
|
ownerLabel: owner,
|
|
336899
|
-
workspacePath:
|
|
337024
|
+
workspacePath: path17.resolve(wsPath || process.cwd())
|
|
336900
337025
|
};
|
|
336901
337026
|
}
|
|
336902
337027
|
function acquireComputerUseLock(action, owner, wsPath, context = {}, dryRun = false) {
|
|
@@ -337091,7 +337216,7 @@ var ToolExecutor = class {
|
|
|
337091
337216
|
t3("subagent_send", "Persist a mailbox message to a same-conversation peer agent. Target by exact id (preferred) or name.", { id: { type: "string", description: "Exact peer id from subagent_list." }, name: { type: "string", description: "Convenience peer name." }, message: { type: "string" }, prompt: { type: "string", description: "Legacy alias for message." }, kind: { type: "string", enum: ["directive", "question", "result", "handoff"] }, reply_to: { type: "string" }, correlation_id: { type: "string" } }, []),
|
|
337092
337217
|
t3("subagent_result", "Return the persisted transcript, mailbox summary, status, and latest result for a peer agent. Target by exact id (preferred) or name.", { id: { type: "string", description: "Exact peer id from subagent_list." }, name: { type: "string", description: "Convenience peer name." } }, []),
|
|
337093
337218
|
t3("subagent_close", "Close a same-conversation peer. Root can close any peer; a peer can close only itself. Target by exact id (preferred) or name.", { id: { type: "string", description: "Exact peer id from subagent_list." }, name: { type: "string", description: "Convenience peer name." } }, []),
|
|
337094
|
-
t3("linked_plan", "Read or update the current conversation linked Markdown plan. Update requires the
|
|
337219
|
+
t3("linked_plan", "Read or incrementally update the current conversation linked Markdown plan. Update requires expected_revision. Prefer append or old_text/new_text for local changes; markdown remains the legacy full replacement path.", { action: { type: "string", enum: ["get", "update"] }, markdown: { type: "string" }, append: { type: "string" }, old_text: { type: "string" }, new_text: { type: "string" }, replace_all: { type: "boolean" }, expected_revision: { type: "number" } }, ["action"]),
|
|
337095
337220
|
t3("build_history_query", "Read the concrete public work details (tool calls, results, file changes, guides) of one historical Build Block. Call it proactively when the current task continues, fixes, verifies, or depends on earlier work: reuse the returned activity instead of re-investigating from scratch. Do not call it merely to answer completion status already exposed by the prompt. Select by newest-to-oldest history_index, or by run_id returned from an earlier query. Every activity/guide content is bounded to max_chars (default 2000) to keep the read lean and cache-friendly.", { history_index: { type: "number", minimum: 1, description: "1-based historical Build Block index from the request ledger; 1 is the newest previous task." }, run_id: { type: "string", description: "Exact run id returned by an earlier build_history_query result." }, max_events: { type: "number", minimum: 1, maximum: 200, description: "Maximum trailing public work events; defaults to 80." }, max_chars: { type: "number", minimum: 100, maximum: 4e3, description: "Per-event/per-guide content character bound; defaults to 2000." } }, []),
|
|
337096
337221
|
t3("context_compress", "Actively compress the LLM context history for this conversation. This collapses older history entries into a concise summary while preserving the recent tail, which reduces context tokens and cost. IMPORTANT: it affects only the LLM context (what the model sees); the displayed conversation history shown to the user is never altered. Call this when the conversation is long, token pressure is high, or you judge that older turns are no longer needed in full. Idempotent and safe: repeated calls produce incremental summaries.", { keep_recent: { type: "number", minimum: 2, maximum: 60, description: "Recent message count to keep uncompressed at the tail. Defaults to the configured keep_recent_messages." }, force: { type: "boolean", description: "Compress even if the context is not yet over the automatic threshold. Defaults to false." } }, []),
|
|
337097
337222
|
t3("context_history_manage", "Manage the LLM context history for this conversation without affecting the displayed conversation history. This is the active context-management surface. The hot cache stays bounded; evicted folded segments remain in a conversation-isolated append-only cold archive and are loaded only by explicit search/read/restore calls. Actions: list returns a bounded index of current context entries; remove declares one long-term entry for unload (see below); summarize folds a contiguous current range; restore reinserts a folded segment when its summary marker is still present; search finds matching hot or archived segments; read returns one bounded segment without injecting the whole archive; status reports budgets, hot cache, cold archive, the protected recent zone, and pending removals. The recent context tail and last user message are protected from remove/summarize unless dangerous is true. For cache-optimization, remove ONLY targets long-term history (never the protected recent tail or last user message) and does NOT unload immediately: the declared entry stays in context for the rest of the current Build Block so the provider prefix cache stays stable, then is physically removed when the Block ends \u2014 applying to subsequent Blocks only.", {
|
|
@@ -337121,11 +337246,11 @@ var ToolExecutor = class {
|
|
|
337121
337246
|
t3("skill_download", "Download a skill", { name: { type: "string" }, source: { type: "string" } }, ["name", "source"]),
|
|
337122
337247
|
t3("skill", "Search enabled skill metadata or load one exact skill body on demand. Use query when unsure, then name to load the selected skill.", { query: { type: "string", maxLength: 200 }, name: { type: "string", maxLength: 200 } }, []),
|
|
337123
337248
|
t3("flow_list", "List available Newmark Flow workflows from the Flow folder so the agent can choose one.", {}, []),
|
|
337124
|
-
t3("flow_save", "
|
|
337249
|
+
t3("flow_save", "Create or incrementally update a Newmark Flow workflow. Use action=upsert with one component or action=delete with component_id and confirm=true for local edits. action=replace plus components remains the legacy full replacement path.", { name: { type: "string" }, action: { type: "string", enum: ["replace", "upsert", "delete"] }, components: { type: "array" }, component: { type: "object" }, component_id: { type: "number" }, confirm: { type: "boolean" } }, ["name"]),
|
|
337125
337250
|
t3("flow_run", "Trigger an existing Newmark Flow workflow by name with optional input and start component.", { name: { type: "string" }, input: { type: "string" }, start: { type: "number" } }, ["name"]),
|
|
337126
337251
|
t3("memory_lab_read", "Read Memory Lab index.json, its path, and usage instructions. Optionally pass component/name/slug to read a memory component core markdown.", { component: { type: "string" }, name: { type: "string" }, slug: { type: "string" } }, []),
|
|
337127
337252
|
t3("memory_lab_query", "Retrieve a bounded task-relevant Memory Lab set with deterministic scoring and adaptive early stopping. Prefer this over loading the complete index when a focused query is sufficient.", { query: { type: "string", minLength: 1 }, limit: { type: "number", minimum: 1, maximum: 12 }, max_chars: { type: "number", minimum: 1e3, maximum: 48e3 } }, ["query"]),
|
|
337128
|
-
t3("memory_lab_update", "
|
|
337253
|
+
t3("memory_lab_update", "Create or incrementally patch a Memory Lab component. Create with name/tags/content. For an existing component pass component plus expectedUpdatedAt and only changed fields; prefer contentAppend or oldText/newText for small body edits. Prior revisions are archived and stale writes fail closed.", { component: { type: "string" }, name: { type: "string" }, description: { type: "string" }, tags: { type: "array", items: { type: "string" } }, tagPaths: { type: "array", items: { type: "array", items: { type: "string" } } }, content: { type: "string" }, contentAppend: { type: "string" }, oldText: { type: "string" }, newText: { type: "string" }, replaceAll: { type: "boolean" }, kind: { type: "string", enum: ["file", "folder"] }, expectedUpdatedAt: { type: "string" }, reason: { type: "string" }, source: { type: "string" } }, []),
|
|
337129
337254
|
t3("memory_lab_delete", "DELETE obsolete durable memory only when the user explicitly asks to forget/remove it. The prior revision is moved to Memory Lab/archive and the Policy decision is logged.", { component: { type: "string" }, name: { type: "string" }, slug: { type: "string" }, expectedUpdatedAt: { type: "string" }, reason: { type: "string" }, source: { type: "string" } }, []),
|
|
337130
337255
|
t3("memory_lab_reindex", "Rebuild and organize Memory Lab index links. Routed through Agent runtime when invoked by the model.", {}, []),
|
|
337131
337256
|
t3("automation_list", "List persisted Newmark automations so the agent can inspect scheduled work.", {}, []),
|
|
@@ -337447,13 +337572,13 @@ var ToolExecutor = class {
|
|
|
337447
337572
|
}
|
|
337448
337573
|
case "pdf_read": {
|
|
337449
337574
|
const pdfPath = resolve16(g2("path"));
|
|
337450
|
-
if (
|
|
337451
|
-
const stat =
|
|
337575
|
+
if (path17.extname(pdfPath).toLowerCase() !== ".pdf") return "[pdf_read error] path must end in .pdf.";
|
|
337576
|
+
const stat = fs15.statSync(pdfPath);
|
|
337452
337577
|
if (!stat.isFile() || stat.size <= 0 || stat.size > 250 * 1024 * 1024) {
|
|
337453
337578
|
return "[pdf_read error] PDF must be a regular file no larger than 250 MB.";
|
|
337454
337579
|
}
|
|
337455
337580
|
const maxChars = Math.max(500, Math.min(1e5, Number(args.max_chars || 5e4)));
|
|
337456
|
-
const textLayer = extractPdfTextLayer(
|
|
337581
|
+
const textLayer = extractPdfTextLayer(fs15.readFileSync(pdfPath)).slice(0, maxChars);
|
|
337457
337582
|
const readableCount = (textLayer.match(/[A-Za-z0-9\u3400-\u9fff]/g) || []).length;
|
|
337458
337583
|
if (readableCount >= 20) {
|
|
337459
337584
|
return JSON.stringify({
|
|
@@ -337672,7 +337797,7 @@ var ToolExecutor = class {
|
|
|
337672
337797
|
case "flow_list":
|
|
337673
337798
|
return this.flowList();
|
|
337674
337799
|
case "flow_save":
|
|
337675
|
-
return this.flowSave(g2("name"), args
|
|
337800
|
+
return this.flowSave(g2("name"), args);
|
|
337676
337801
|
case "flow_run":
|
|
337677
337802
|
return `[flow_run] Routed to Agent runtime: ${g2("name")}`;
|
|
337678
337803
|
case "memory_lab_read":
|
|
@@ -337729,8 +337854,8 @@ var ToolExecutor = class {
|
|
|
337729
337854
|
}
|
|
337730
337855
|
}
|
|
337731
337856
|
isInside(parent, child) {
|
|
337732
|
-
const rel =
|
|
337733
|
-
return rel === "" || !!rel && !rel.startsWith("..") && !
|
|
337857
|
+
const rel = path17.relative(path17.resolve(parent), path17.resolve(child));
|
|
337858
|
+
return rel === "" || !!rel && !rel.startsWith("..") && !path17.isAbsolute(rel);
|
|
337734
337859
|
}
|
|
337735
337860
|
hostSupportsTool(name50) {
|
|
337736
337861
|
if (name50.startsWith("browser_") && !this.hostProfile.electronBrowser) return false;
|
|
@@ -337842,7 +337967,7 @@ var ToolExecutor = class {
|
|
|
337842
337967
|
if (!token || /^https?:\/\//i.test(token) || token.startsWith("-")) continue;
|
|
337843
337968
|
if (!this.looksLikePath(token)) continue;
|
|
337844
337969
|
const withoutWildcard = token.replace(/[\\/][*?][^\\/]*$/g, "");
|
|
337845
|
-
refs.push(
|
|
337970
|
+
refs.push(path17.resolve(normalizeCrossEnvPath(withoutWildcard, wsPath)));
|
|
337846
337971
|
}
|
|
337847
337972
|
return Array.from(new Set(refs));
|
|
337848
337973
|
}
|
|
@@ -337893,7 +338018,7 @@ var ToolExecutor = class {
|
|
|
337893
338018
|
}
|
|
337894
338019
|
fread(p) {
|
|
337895
338020
|
try {
|
|
337896
|
-
const c3 =
|
|
338021
|
+
const c3 = fs15.readFileSync(p, "utf-8");
|
|
337897
338022
|
return c3.length > 3e4 ? c3.slice(0, 3e4) + "...\n[truncated]" : c3;
|
|
337898
338023
|
} catch (e3) {
|
|
337899
338024
|
return `[read] ${e3}`;
|
|
@@ -337901,8 +338026,8 @@ var ToolExecutor = class {
|
|
|
337901
338026
|
}
|
|
337902
338027
|
fwrite(p, content) {
|
|
337903
338028
|
try {
|
|
337904
|
-
|
|
337905
|
-
|
|
338029
|
+
fs15.mkdirSync(path17.dirname(p), { recursive: true });
|
|
338030
|
+
fs15.writeFileSync(p, content, "utf-8");
|
|
337906
338031
|
return `[write] OK: ${p}`;
|
|
337907
338032
|
} catch (e3) {
|
|
337908
338033
|
return `[write] ${e3}`;
|
|
@@ -337910,10 +338035,10 @@ var ToolExecutor = class {
|
|
|
337910
338035
|
}
|
|
337911
338036
|
fedit(p, oldStr, newStr) {
|
|
337912
338037
|
try {
|
|
337913
|
-
const c3 =
|
|
338038
|
+
const c3 = fs15.readFileSync(p, "utf-8");
|
|
337914
338039
|
if (!c3.includes(oldStr)) return `[edit] String not found in ${p}.`;
|
|
337915
338040
|
const updated = c3.replace(oldStr, newStr);
|
|
337916
|
-
|
|
338041
|
+
fs15.writeFileSync(p, updated, "utf-8");
|
|
337917
338042
|
return `[edit] OK: ${p}`;
|
|
337918
338043
|
} catch (e3) {
|
|
337919
338044
|
return `[edit] ${e3}`;
|
|
@@ -337922,12 +338047,12 @@ var ToolExecutor = class {
|
|
|
337922
338047
|
fdelete(p) {
|
|
337923
338048
|
try {
|
|
337924
338049
|
if (/[*?]/.test(p)) return "[delete_file] Refused: wildcard paths are not allowed. Delete one file per call.";
|
|
337925
|
-
const resolved =
|
|
337926
|
-
const stat =
|
|
338050
|
+
const resolved = path17.resolve(p);
|
|
338051
|
+
const stat = fs15.lstatSync(resolved);
|
|
337927
338052
|
if (stat.isDirectory()) {
|
|
337928
338053
|
return "[delete_file] Refused: deleting a directory is not allowed. Delete files one by one under Agent supervision.";
|
|
337929
338054
|
}
|
|
337930
|
-
|
|
338055
|
+
fs15.unlinkSync(resolved);
|
|
337931
338056
|
return `[delete_file] OK: ${resolved}`;
|
|
337932
338057
|
} catch (e3) {
|
|
337933
338058
|
return `[delete_file] ${e3 instanceof Error ? e3.message : String(e3)}`;
|
|
@@ -337951,11 +338076,11 @@ var ToolExecutor = class {
|
|
|
337951
338076
|
const results = [];
|
|
337952
338077
|
const walk4 = (d3, depth) => {
|
|
337953
338078
|
if (depth > 5 || results.length >= 80) return;
|
|
337954
|
-
for (const entry of
|
|
337955
|
-
const full =
|
|
338079
|
+
for (const entry of fs15.readdirSync(d3, { withFileTypes: true })) {
|
|
338080
|
+
const full = path17.join(d3, entry.name);
|
|
337956
338081
|
if (entry.isFile()) {
|
|
337957
338082
|
try {
|
|
337958
|
-
const content =
|
|
338083
|
+
const content = fs15.readFileSync(full, "utf-8");
|
|
337959
338084
|
for (const [i4, line] of content.split("\n").entries()) {
|
|
337960
338085
|
if (re.test(line)) {
|
|
337961
338086
|
results.push(`${entry.name}:${i4 + 1}:${line.trim()}`);
|
|
@@ -338171,29 +338296,53 @@ ${String(result.data)}`);
|
|
|
338171
338296
|
try {
|
|
338172
338297
|
const resp = await this.proxyFetch(src, { signal });
|
|
338173
338298
|
const content = await resp.text();
|
|
338174
|
-
const dir =
|
|
338175
|
-
|
|
338176
|
-
|
|
338299
|
+
const dir = path17.join(this.root, "skills", name50);
|
|
338300
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
338301
|
+
fs15.writeFileSync(path17.join(dir, "SKILL.md"), content, "utf-8");
|
|
338177
338302
|
return `[skill] Downloaded '${name50}'`;
|
|
338178
338303
|
} catch (e3) {
|
|
338179
338304
|
return `[skill] ${e3}`;
|
|
338180
338305
|
}
|
|
338181
338306
|
}
|
|
338182
338307
|
flowList() {
|
|
338183
|
-
const dir =
|
|
338308
|
+
const dir = path17.join(this.root, "Flow");
|
|
338184
338309
|
try {
|
|
338185
|
-
const files =
|
|
338310
|
+
const files = fs15.readdirSync(dir).filter((f3) => f3.endsWith(".Flow.json")).sort();
|
|
338186
338311
|
if (!files.length) return "[flow_list] No workflows found.";
|
|
338187
338312
|
return files.map((f3) => f3.replace(/\.Flow\.json$/, "")).join("\n");
|
|
338188
338313
|
} catch (e3) {
|
|
338189
338314
|
return `[flow_list] ${e3}`;
|
|
338190
338315
|
}
|
|
338191
338316
|
}
|
|
338192
|
-
flowSave(name50,
|
|
338317
|
+
flowSave(name50, input) {
|
|
338193
338318
|
const cleanName = (name50 || "").replace(/[<>:"/\\|?*]/g, "-").trim();
|
|
338194
338319
|
if (!cleanName) return "[flow_save] Workflow name is required.";
|
|
338195
|
-
|
|
338196
|
-
const
|
|
338320
|
+
const dir = path17.join(this.root, "Flow");
|
|
338321
|
+
const target = path17.join(dir, `${cleanName}.Flow.json`);
|
|
338322
|
+
const action = String(input.action || (Array.isArray(input.components) ? "replace" : "upsert")).toLowerCase();
|
|
338323
|
+
let componentsRaw = input.components;
|
|
338324
|
+
if (action === "upsert") {
|
|
338325
|
+
if (!input.component || typeof input.component !== "object") return "[flow_save] component is required for action=upsert.";
|
|
338326
|
+
const existing = FlowEngine.load(dir, cleanName)?.components || [];
|
|
338327
|
+
const component = input.component;
|
|
338328
|
+
const requestedId = Number(component.id);
|
|
338329
|
+
if (!Number.isFinite(requestedId)) return "[flow_save] component.id is required for action=upsert.";
|
|
338330
|
+
componentsRaw = [...existing.filter((item) => item.id !== requestedId), component].sort((a3, b2) => Number(a3.id) - Number(b2.id));
|
|
338331
|
+
} else if (action === "delete") {
|
|
338332
|
+
if (input.confirm !== true) return "[flow_save] action=delete requires confirm=true.";
|
|
338333
|
+
const componentId = Number(input.component_id);
|
|
338334
|
+
if (!Number.isFinite(componentId)) return "[flow_save] component_id is required for action=delete.";
|
|
338335
|
+
const existing = FlowEngine.load(dir, cleanName);
|
|
338336
|
+
if (!existing) return `[flow_save] Workflow not found: ${cleanName}`;
|
|
338337
|
+
const remaining = existing.components.filter((item) => item.id !== componentId);
|
|
338338
|
+
if (remaining.length === existing.components.length) return `[flow_save] Component not found: ${componentId}`;
|
|
338339
|
+
componentsRaw = remaining;
|
|
338340
|
+
} else if (action !== "replace") {
|
|
338341
|
+
return `[flow_save] Unknown action: ${action}`;
|
|
338342
|
+
}
|
|
338343
|
+
if (!Array.isArray(componentsRaw)) return "[flow_save] components must be an array for action=replace.";
|
|
338344
|
+
const componentInputs = componentsRaw;
|
|
338345
|
+
const components = componentInputs.map((raw, idx) => {
|
|
338197
338346
|
const c3 = raw;
|
|
338198
338347
|
const type = c3.type === "logic" ? "logic" : "dialog";
|
|
338199
338348
|
if (type === "logic") {
|
|
@@ -338214,10 +338363,9 @@ ${String(result.data)}`);
|
|
|
338214
338363
|
};
|
|
338215
338364
|
});
|
|
338216
338365
|
const workflow = { name: cleanName, components };
|
|
338217
|
-
|
|
338218
|
-
|
|
338219
|
-
|
|
338220
|
-
return `[flow_save] OK: ${cleanName}.Flow.json`;
|
|
338366
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
338367
|
+
fs15.writeFileSync(target, JSON.stringify(workflow, null, 2), "utf-8");
|
|
338368
|
+
return `[flow_save] OK (${action}): ${cleanName}.Flow.json`;
|
|
338221
338369
|
}
|
|
338222
338370
|
memoryLabRead(selector2) {
|
|
338223
338371
|
const lab2 = new MemoryLabManager(this.root);
|
|
@@ -338277,10 +338425,10 @@ ${String(result.data)}`);
|
|
|
338277
338425
|
return this.gh(args, ws, signal);
|
|
338278
338426
|
}
|
|
338279
338427
|
async fileAudit(target, ws, includeRemote, baseRef, signal) {
|
|
338280
|
-
const resolvedTarget =
|
|
338281
|
-
const exists =
|
|
338282
|
-
const stat = exists ?
|
|
338283
|
-
const repoRoot = await this.findGitRoot(exists && stat?.isDirectory() ? resolvedTarget :
|
|
338428
|
+
const resolvedTarget = path17.resolve(target || ws);
|
|
338429
|
+
const exists = fs15.existsSync(resolvedTarget);
|
|
338430
|
+
const stat = exists ? fs15.statSync(resolvedTarget) : null;
|
|
338431
|
+
const repoRoot = await this.findGitRoot(exists && stat?.isDirectory() ? resolvedTarget : path17.dirname(resolvedTarget), ws, signal);
|
|
338284
338432
|
const audit = {
|
|
338285
338433
|
ok: true,
|
|
338286
338434
|
target: resolvedTarget,
|
|
@@ -338307,11 +338455,11 @@ ${String(result.data)}`);
|
|
|
338307
338455
|
};
|
|
338308
338456
|
if (stat.isFile()) {
|
|
338309
338457
|
const hash = crypto8.createHash("sha256");
|
|
338310
|
-
hash.update(
|
|
338458
|
+
hash.update(fs15.readFileSync(target));
|
|
338311
338459
|
base2.sha256 = hash.digest("hex").toUpperCase();
|
|
338312
338460
|
}
|
|
338313
338461
|
if (stat.isDirectory()) {
|
|
338314
|
-
base2.entries =
|
|
338462
|
+
base2.entries = fs15.readdirSync(target).slice(0, 200).sort();
|
|
338315
338463
|
}
|
|
338316
338464
|
return base2;
|
|
338317
338465
|
}
|
|
@@ -338320,14 +338468,14 @@ ${String(result.data)}`);
|
|
|
338320
338468
|
const out = await this.gitExecAt(candidate, ["rev-parse", "--show-toplevel"], signal);
|
|
338321
338469
|
if (!out.startsWith("[git]") && !out.includes("not a git repository")) {
|
|
338322
338470
|
const root2 = out.split(/\r?\n/)[0].trim();
|
|
338323
|
-
if (root2 &&
|
|
338471
|
+
if (root2 && fs15.existsSync(root2)) return path17.resolve(root2);
|
|
338324
338472
|
}
|
|
338325
338473
|
}
|
|
338326
338474
|
return null;
|
|
338327
338475
|
}
|
|
338328
338476
|
async gitFileAudit(repoRoot, target, baseRef, signal) {
|
|
338329
|
-
const rel =
|
|
338330
|
-
const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !
|
|
338477
|
+
const rel = path17.relative(repoRoot, target).replace(/\\/g, "/");
|
|
338478
|
+
const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !path17.isAbsolute(rel);
|
|
338331
338479
|
if (!inside2) return { repository: repoRoot, tracked: false, note: "Path is outside the detected repository." };
|
|
338332
338480
|
const branch = await this.gitExecAt(repoRoot, ["branch", "--show-current"], signal);
|
|
338333
338481
|
const status = rel === "" ? await this.gitExecAt(repoRoot, ["status", "--short"], signal) : await this.gitExecAt(repoRoot, ["status", "--short", "--", rel], signal);
|
|
@@ -338385,7 +338533,7 @@ ${String(result.data)}`);
|
|
|
338385
338533
|
}
|
|
338386
338534
|
async githubFileAudit(repoRoot, target, remote, signal) {
|
|
338387
338535
|
const repo = `${remote.owner}/${remote.name}`;
|
|
338388
|
-
const rel =
|
|
338536
|
+
const rel = path17.relative(repoRoot, target).replace(/\\/g, "/");
|
|
338389
338537
|
const branch = (await this.gitExecAt(repoRoot, ["branch", "--show-current"], signal)).trim();
|
|
338390
338538
|
const encodedPath = rel && rel !== "." ? rel.split("/").map((part) => encodeURIComponent(part)).join("/") : "";
|
|
338391
338539
|
const repoInfo = await this.ghJson(["api", `repos/${repo}`, "--jq", "{name: .full_name, private: .private, default_branch: .default_branch, fork: .fork, html_url: .html_url}"], repoRoot, signal);
|
|
@@ -338409,8 +338557,8 @@ ${String(result.data)}`);
|
|
|
338409
338557
|
};
|
|
338410
338558
|
}
|
|
338411
338559
|
async repoSecurityAudit(target, ws, baseRef, signal) {
|
|
338412
|
-
const resolvedTarget =
|
|
338413
|
-
const repoRoot = await this.findGitRoot(
|
|
338560
|
+
const resolvedTarget = path17.resolve(target || ws);
|
|
338561
|
+
const repoRoot = await this.findGitRoot(fs15.existsSync(resolvedTarget) && fs15.statSync(resolvedTarget).isDirectory() ? resolvedTarget : path17.dirname(resolvedTarget), ws, signal);
|
|
338414
338562
|
if (!repoRoot) {
|
|
338415
338563
|
return JSON.stringify({
|
|
338416
338564
|
ok: true,
|
|
@@ -338508,12 +338656,12 @@ ${String(result.data)}`);
|
|
|
338508
338656
|
const findings = [];
|
|
338509
338657
|
for (const rel of Array.from(files).sort()) {
|
|
338510
338658
|
if (findings.length >= 40) break;
|
|
338511
|
-
const full =
|
|
338512
|
-
if (!
|
|
338513
|
-
if (
|
|
338659
|
+
const full = path17.join(repoRoot, rel);
|
|
338660
|
+
if (!fs15.existsSync(full) || !fs15.statSync(full).isFile()) continue;
|
|
338661
|
+
if (fs15.statSync(full).size > 512 * 1024) continue;
|
|
338514
338662
|
let text = "";
|
|
338515
338663
|
try {
|
|
338516
|
-
text =
|
|
338664
|
+
text = fs15.readFileSync(full, "utf-8");
|
|
338517
338665
|
} catch {
|
|
338518
338666
|
continue;
|
|
338519
338667
|
}
|
|
@@ -338543,12 +338691,12 @@ ${String(result.data)}`);
|
|
|
338543
338691
|
const findings = [];
|
|
338544
338692
|
for (const rel of Array.from(files).sort()) {
|
|
338545
338693
|
if (findings.length >= 40) break;
|
|
338546
|
-
const full =
|
|
338547
|
-
if (!
|
|
338548
|
-
if (
|
|
338694
|
+
const full = path17.join(repoRoot, rel);
|
|
338695
|
+
if (!fs15.existsSync(full) || !fs15.statSync(full).isFile()) continue;
|
|
338696
|
+
if (fs15.statSync(full).size > 512 * 1024) continue;
|
|
338549
338697
|
let text = "";
|
|
338550
338698
|
try {
|
|
338551
|
-
text =
|
|
338699
|
+
text = fs15.readFileSync(full, "utf-8");
|
|
338552
338700
|
} catch {
|
|
338553
338701
|
continue;
|
|
338554
338702
|
}
|
|
@@ -338565,7 +338713,7 @@ ${String(result.data)}`);
|
|
|
338565
338713
|
releaseExcludedPathFindings(repoRoot, ignoredFilesRaw) {
|
|
338566
338714
|
const sensitive = /^(config\.json|agent\.md|PC_Hash\.config|Work\/|archive\/|skills\/|Memory Lab\/|Design\.md|release\/|_local\/|_ref\/|vendor\/)/i;
|
|
338567
338715
|
const fromIgnored = String(ignoredFilesRaw || "").split(/\r?\n/).map((line) => line.trim().replace(/\\/g, "/")).filter((line) => line && sensitive.test(line));
|
|
338568
|
-
const direct = ["config.json", "agent.md", "PC_Hash.config", "Work", "archive", "skills", "Memory Lab", "Design.md", "release", "_local", "_ref", "vendor"].filter((rel) =>
|
|
338716
|
+
const direct = ["config.json", "agent.md", "PC_Hash.config", "Work", "archive", "skills", "Memory Lab", "Design.md", "release", "_local", "_ref", "vendor"].filter((rel) => fs15.existsSync(path17.join(repoRoot, rel))).map((rel) => rel.replace(/\\/g, "/"));
|
|
338569
338717
|
return Array.from(/* @__PURE__ */ new Set([...fromIgnored, ...direct])).slice(0, 80);
|
|
338570
338718
|
}
|
|
338571
338719
|
async ghJson(args, ws, signal) {
|
|
@@ -339369,8 +339517,8 @@ function sharedSubagentManager(key3, options) {
|
|
|
339369
339517
|
}
|
|
339370
339518
|
|
|
339371
339519
|
// src/core/skills.ts
|
|
339372
|
-
var
|
|
339373
|
-
var
|
|
339520
|
+
var fs16 = __toESM(require("fs"));
|
|
339521
|
+
var path18 = __toESM(require("path"));
|
|
339374
339522
|
var os4 = __toESM(require("os"));
|
|
339375
339523
|
var import_crypto9 = require("crypto");
|
|
339376
339524
|
var SkillsManager = class {
|
|
@@ -339379,13 +339527,13 @@ var SkillsManager = class {
|
|
|
339379
339527
|
marketSourcesPath;
|
|
339380
339528
|
metadataCache = /* @__PURE__ */ new Map();
|
|
339381
339529
|
constructor(root2) {
|
|
339382
|
-
this.skillsDir =
|
|
339383
|
-
this.metaPath =
|
|
339384
|
-
this.marketSourcesPath =
|
|
339385
|
-
|
|
339530
|
+
this.skillsDir = path18.join(root2, "skills");
|
|
339531
|
+
this.metaPath = path18.join(this.skillsDir, ".skills.json");
|
|
339532
|
+
this.marketSourcesPath = path18.join(this.skillsDir, ".market-sources.json");
|
|
339533
|
+
fs16.mkdirSync(this.skillsDir, { recursive: true });
|
|
339386
339534
|
}
|
|
339387
339535
|
list() {
|
|
339388
|
-
return
|
|
339536
|
+
return fs16.readdirSync(this.skillsDir, { withFileTypes: true }).filter((e3) => e3.isDirectory() && !e3.name.startsWith(".")).map((e3) => e3.name);
|
|
339389
339537
|
}
|
|
339390
339538
|
listDetailed() {
|
|
339391
339539
|
return this.list().map((name50) => this.infoFor(name50, this.getPath(name50), "project", true));
|
|
@@ -339406,48 +339554,48 @@ var SkillsManager = class {
|
|
|
339406
339554
|
}
|
|
339407
339555
|
load(name50) {
|
|
339408
339556
|
const reference = String(name50 || "").trim().toLowerCase();
|
|
339409
|
-
const skill = this.active().find((item) => item.name.toLowerCase() === reference ||
|
|
339557
|
+
const skill = this.active().find((item) => item.name.toLowerCase() === reference || path18.basename(item.path).toLowerCase() === reference);
|
|
339410
339558
|
if (!skill) return null;
|
|
339411
|
-
const skillPath =
|
|
339412
|
-
const content =
|
|
339559
|
+
const skillPath = path18.join(skill.path, "SKILL.md");
|
|
339560
|
+
const content = fs16.readFileSync(skillPath, "utf-8");
|
|
339413
339561
|
const files = this.sampleSkillFiles(skill.path, 10);
|
|
339414
339562
|
return { skill, content, files };
|
|
339415
339563
|
}
|
|
339416
339564
|
has(name50) {
|
|
339417
|
-
return
|
|
339565
|
+
return fs16.existsSync(path18.join(this.skillsDir, name50, "SKILL.md"));
|
|
339418
339566
|
}
|
|
339419
339567
|
getPath(name50) {
|
|
339420
|
-
return
|
|
339568
|
+
return path18.join(this.skillsDir, name50);
|
|
339421
339569
|
}
|
|
339422
339570
|
async download(name50, url) {
|
|
339423
|
-
const dir =
|
|
339424
|
-
|
|
339571
|
+
const dir = path18.join(this.skillsDir, name50);
|
|
339572
|
+
fs16.mkdirSync(dir, { recursive: true });
|
|
339425
339573
|
if (!url.startsWith("http")) return `[skill] Not a URL: ${url}`;
|
|
339426
339574
|
try {
|
|
339427
339575
|
const resp = await fetch(url);
|
|
339428
339576
|
const content = await resp.text();
|
|
339429
|
-
|
|
339577
|
+
fs16.writeFileSync(path18.join(dir, "SKILL.md"), content, "utf-8");
|
|
339430
339578
|
return `[skill] Downloaded '${name50}'`;
|
|
339431
339579
|
} catch (e3) {
|
|
339432
339580
|
return `[skill] ${e3}`;
|
|
339433
339581
|
}
|
|
339434
339582
|
}
|
|
339435
339583
|
installFromLocal(sourceDir, targetName) {
|
|
339436
|
-
const skillPath =
|
|
339437
|
-
if (!
|
|
339584
|
+
const skillPath = path18.join(sourceDir, "SKILL.md");
|
|
339585
|
+
if (!fs16.existsSync(skillPath)) return false;
|
|
339438
339586
|
const info = this.parseSkillInfo(sourceDir);
|
|
339439
|
-
const cleanName = this.cleanName(targetName || info.name ||
|
|
339587
|
+
const cleanName = this.cleanName(targetName || info.name || path18.basename(sourceDir));
|
|
339440
339588
|
if (!cleanName) return false;
|
|
339441
|
-
const dest =
|
|
339442
|
-
|
|
339443
|
-
|
|
339589
|
+
const dest = path18.join(this.skillsDir, cleanName);
|
|
339590
|
+
fs16.rmSync(dest, { recursive: true, force: true });
|
|
339591
|
+
fs16.cpSync(sourceDir, dest, { recursive: true });
|
|
339444
339592
|
this.setEnabled(cleanName, true);
|
|
339445
339593
|
return true;
|
|
339446
339594
|
}
|
|
339447
339595
|
remove(name50) {
|
|
339448
|
-
const dir =
|
|
339449
|
-
if (
|
|
339450
|
-
|
|
339596
|
+
const dir = path18.join(this.skillsDir, name50);
|
|
339597
|
+
if (fs16.existsSync(dir)) {
|
|
339598
|
+
fs16.rmSync(dir, { recursive: true, force: true });
|
|
339451
339599
|
const meta = this.loadMeta();
|
|
339452
339600
|
meta.disabled = meta.disabled.filter((n3) => n3 !== name50);
|
|
339453
339601
|
this.saveMeta(meta);
|
|
@@ -339496,7 +339644,7 @@ var SkillsManager = class {
|
|
|
339496
339644
|
type,
|
|
339497
339645
|
enabled: input.enabled !== false,
|
|
339498
339646
|
url: url || void 0,
|
|
339499
|
-
path: sourcePath ?
|
|
339647
|
+
path: sourcePath ? path18.resolve(sourcePath) : void 0,
|
|
339500
339648
|
addedAt: existing?.addedAt || now2,
|
|
339501
339649
|
updatedAt: now2
|
|
339502
339650
|
};
|
|
@@ -339534,17 +339682,17 @@ var SkillsManager = class {
|
|
|
339534
339682
|
const items = [];
|
|
339535
339683
|
for (const info of this.listDetailed()) items.push(info);
|
|
339536
339684
|
const roots = [
|
|
339537
|
-
{ root:
|
|
339538
|
-
{ root:
|
|
339539
|
-
{ root:
|
|
339540
|
-
{ root:
|
|
339541
|
-
{ root:
|
|
339542
|
-
{ root:
|
|
339685
|
+
{ root: path18.join(this.skillsDir, "..", ".agents", "skills"), source: "codex" },
|
|
339686
|
+
{ root: path18.join(this.skillsDir, "..", ".claude", "skills"), source: "claude" },
|
|
339687
|
+
{ root: path18.join(os4.homedir(), ".agents", "skills"), source: "user" },
|
|
339688
|
+
{ root: path18.join(os4.homedir(), ".codex", "skills"), source: "codex" },
|
|
339689
|
+
{ root: path18.join(os4.homedir(), ".claude", "skills"), source: "claude" },
|
|
339690
|
+
{ root: path18.join(os4.homedir(), ".config", "opencode", "skills"), source: "opencode" }
|
|
339543
339691
|
];
|
|
339544
339692
|
for (const entry of roots) {
|
|
339545
339693
|
for (const dir of this.findSkillDirs(entry.root, 4, 240)) {
|
|
339546
339694
|
const parsed = this.parseSkillInfo(dir);
|
|
339547
|
-
const name50 = this.cleanName(parsed.name ||
|
|
339695
|
+
const name50 = this.cleanName(parsed.name || path18.basename(dir));
|
|
339548
339696
|
if (!name50 || items.some((i4) => i4.name === name50 && i4.source !== "remote")) continue;
|
|
339549
339697
|
items.push({
|
|
339550
339698
|
name: name50,
|
|
@@ -339561,9 +339709,9 @@ var SkillsManager = class {
|
|
|
339561
339709
|
});
|
|
339562
339710
|
}
|
|
339563
339711
|
}
|
|
339564
|
-
for (const dir of this.findPluginSkillDirs(
|
|
339712
|
+
for (const dir of this.findPluginSkillDirs(path18.join(this.skillsDir, ".."), 5, 240)) {
|
|
339565
339713
|
const parsed = this.parseSkillInfo(dir);
|
|
339566
|
-
const name50 = this.cleanName(parsed.name ||
|
|
339714
|
+
const name50 = this.cleanName(parsed.name || path18.basename(dir));
|
|
339567
339715
|
if (!name50 || items.some((i4) => i4.name === name50 && i4.source !== "remote")) continue;
|
|
339568
339716
|
items.push({
|
|
339569
339717
|
name: name50,
|
|
@@ -339620,8 +339768,8 @@ var SkillsManager = class {
|
|
|
339620
339768
|
}
|
|
339621
339769
|
loadMeta() {
|
|
339622
339770
|
try {
|
|
339623
|
-
if (
|
|
339624
|
-
const raw = JSON.parse(
|
|
339771
|
+
if (fs16.existsSync(this.metaPath)) {
|
|
339772
|
+
const raw = JSON.parse(fs16.readFileSync(this.metaPath, "utf-8"));
|
|
339625
339773
|
return { disabled: Array.isArray(raw.disabled) ? raw.disabled.map(String) : [] };
|
|
339626
339774
|
}
|
|
339627
339775
|
} catch {
|
|
@@ -339629,7 +339777,7 @@ var SkillsManager = class {
|
|
|
339629
339777
|
return { disabled: [] };
|
|
339630
339778
|
}
|
|
339631
339779
|
saveMeta(meta) {
|
|
339632
|
-
|
|
339780
|
+
fs16.writeFileSync(this.metaPath, JSON.stringify({ disabled: meta.disabled }, null, 2), "utf-8");
|
|
339633
339781
|
}
|
|
339634
339782
|
builtinMarketSources() {
|
|
339635
339783
|
return [{
|
|
@@ -339643,8 +339791,8 @@ var SkillsManager = class {
|
|
|
339643
339791
|
}
|
|
339644
339792
|
loadMarketSources() {
|
|
339645
339793
|
try {
|
|
339646
|
-
if (!
|
|
339647
|
-
const raw = JSON.parse(
|
|
339794
|
+
if (!fs16.existsSync(this.marketSourcesPath)) return [];
|
|
339795
|
+
const raw = JSON.parse(fs16.readFileSync(this.marketSourcesPath, "utf-8"));
|
|
339648
339796
|
if (!Array.isArray(raw.sources)) return [];
|
|
339649
339797
|
return raw.sources.map((source) => this.normalizeMarketSource(source)).filter((source) => !!source);
|
|
339650
339798
|
} catch {
|
|
@@ -339653,7 +339801,7 @@ var SkillsManager = class {
|
|
|
339653
339801
|
}
|
|
339654
339802
|
saveMarketSources(sources) {
|
|
339655
339803
|
const normalized = sources.filter((s3) => !s3.builtin).map((s3) => this.normalizeMarketSource(s3)).filter((source) => !!source);
|
|
339656
|
-
|
|
339804
|
+
fs16.writeFileSync(this.marketSourcesPath, JSON.stringify({ sources: normalized }, null, 2), "utf-8");
|
|
339657
339805
|
}
|
|
339658
339806
|
normalizeMarketSource(raw) {
|
|
339659
339807
|
if (!raw || typeof raw !== "object") return null;
|
|
@@ -339673,7 +339821,7 @@ var SkillsManager = class {
|
|
|
339673
339821
|
type,
|
|
339674
339822
|
enabled: source.enabled !== false,
|
|
339675
339823
|
url: url || void 0,
|
|
339676
|
-
path: sourcePath ?
|
|
339824
|
+
path: sourcePath ? path18.resolve(sourcePath) : void 0,
|
|
339677
339825
|
builtin: source.builtin === true,
|
|
339678
339826
|
addedAt: source.addedAt ? String(source.addedAt) : void 0,
|
|
339679
339827
|
updatedAt: source.updatedAt ? String(source.updatedAt) : void 0
|
|
@@ -339724,11 +339872,11 @@ var SkillsManager = class {
|
|
|
339724
339872
|
return rawItems.slice(0, 1e3).map((entry) => this.marketInfoFromCatalogEntry(entry, source, installed)).filter((item) => !!item);
|
|
339725
339873
|
}
|
|
339726
339874
|
readCatalogText(source) {
|
|
339727
|
-
const catalogPath = source.path ?
|
|
339728
|
-
if (catalogPath &&
|
|
339875
|
+
const catalogPath = source.path ? path18.resolve(source.path) : "";
|
|
339876
|
+
if (catalogPath && fs16.existsSync(catalogPath)) return fs16.readFileSync(catalogPath, "utf-8");
|
|
339729
339877
|
const url = source.url || "";
|
|
339730
|
-
if (url.startsWith("file://")) return
|
|
339731
|
-
if (url && !url.startsWith("http")) return
|
|
339878
|
+
if (url.startsWith("file://")) return fs16.readFileSync(new URL(url), "utf-8");
|
|
339879
|
+
if (url && !url.startsWith("http")) return fs16.readFileSync(path18.resolve(url), "utf-8");
|
|
339732
339880
|
return "";
|
|
339733
339881
|
}
|
|
339734
339882
|
async discoverJsonMarketSourceAsync(source, installed) {
|
|
@@ -339788,7 +339936,7 @@ var SkillsManager = class {
|
|
|
339788
339936
|
}
|
|
339789
339937
|
marketInfoFromLocalDir(dir, source, installed) {
|
|
339790
339938
|
const parsed = this.parseSkillInfo(dir);
|
|
339791
|
-
const name50 = this.cleanName(parsed.name ||
|
|
339939
|
+
const name50 = this.cleanName(parsed.name || path18.basename(dir));
|
|
339792
339940
|
if (!name50) return null;
|
|
339793
339941
|
return {
|
|
339794
339942
|
name: name50,
|
|
@@ -339813,9 +339961,9 @@ var SkillsManager = class {
|
|
|
339813
339961
|
}
|
|
339814
339962
|
parseSkillInfo(dir) {
|
|
339815
339963
|
try {
|
|
339816
|
-
const skillPath =
|
|
339817
|
-
const stat =
|
|
339818
|
-
const content =
|
|
339964
|
+
const skillPath = path18.join(dir, "SKILL.md");
|
|
339965
|
+
const stat = fs16.statSync(skillPath);
|
|
339966
|
+
const content = fs16.readFileSync(skillPath, "utf-8");
|
|
339819
339967
|
const digest = (0, import_crypto9.createHash)("sha256").update(content).digest("hex");
|
|
339820
339968
|
const fingerprint2 = `${stat.mtimeMs}:${stat.size}:${digest}`;
|
|
339821
339969
|
const cached = this.metadataCache.get(skillPath);
|
|
@@ -339848,7 +339996,7 @@ var SkillsManager = class {
|
|
|
339848
339996
|
};
|
|
339849
339997
|
this.metadataCache.set(skillPath, {
|
|
339850
339998
|
fingerprint: fingerprint2,
|
|
339851
|
-
info: { ...parsed, path: dir, enabled: this.isEnabled(
|
|
339999
|
+
info: { ...parsed, path: dir, enabled: this.isEnabled(path18.basename(dir)), installed: true, source: "project" }
|
|
339852
340000
|
});
|
|
339853
340001
|
return parsed;
|
|
339854
340002
|
} catch {
|
|
@@ -339865,13 +340013,13 @@ var SkillsManager = class {
|
|
|
339865
340013
|
if (files.length >= limit || depth > 2) return;
|
|
339866
340014
|
let entries = [];
|
|
339867
340015
|
try {
|
|
339868
|
-
entries =
|
|
340016
|
+
entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
339869
340017
|
} catch {
|
|
339870
340018
|
return;
|
|
339871
340019
|
}
|
|
339872
340020
|
for (const entry of entries) {
|
|
339873
340021
|
if (files.length >= limit || entry.name === "SKILL.md" || entry.name.startsWith(".")) continue;
|
|
339874
|
-
const target =
|
|
340022
|
+
const target = path18.join(dir, entry.name);
|
|
339875
340023
|
if (entry.isDirectory()) walk4(target, depth + 1);
|
|
339876
340024
|
else if (entry.isFile()) files.push(target);
|
|
339877
340025
|
}
|
|
@@ -339885,7 +340033,7 @@ var SkillsManager = class {
|
|
|
339885
340033
|
if (results.length >= maxItems || depth > maxDepth) return;
|
|
339886
340034
|
let entries;
|
|
339887
340035
|
try {
|
|
339888
|
-
entries =
|
|
340036
|
+
entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
339889
340037
|
} catch {
|
|
339890
340038
|
return;
|
|
339891
340039
|
}
|
|
@@ -339895,7 +340043,7 @@ var SkillsManager = class {
|
|
|
339895
340043
|
}
|
|
339896
340044
|
for (const e3 of entries) {
|
|
339897
340045
|
if (!e3.isDirectory() || e3.name.startsWith(".git") || e3.name === "node_modules") continue;
|
|
339898
|
-
walk4(
|
|
340046
|
+
walk4(path18.join(dir, e3.name), depth + 1);
|
|
339899
340047
|
}
|
|
339900
340048
|
};
|
|
339901
340049
|
walk4(root2, 0);
|
|
@@ -339907,19 +340055,19 @@ var SkillsManager = class {
|
|
|
339907
340055
|
if (results.length >= maxItems || depth > maxDepth) return;
|
|
339908
340056
|
let entries;
|
|
339909
340057
|
try {
|
|
339910
|
-
entries =
|
|
340058
|
+
entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
339911
340059
|
} catch {
|
|
339912
340060
|
return;
|
|
339913
340061
|
}
|
|
339914
340062
|
const hasPluginManifest = entries.some((e3) => e3.isDirectory() && (e3.name === ".codex-plugin" || e3.name === ".claude-plugin"));
|
|
339915
340063
|
if (hasPluginManifest) {
|
|
339916
340064
|
for (const skillsDir of ["skills", "Skills"]) {
|
|
339917
|
-
results.push(...this.findSkillDirs(
|
|
340065
|
+
results.push(...this.findSkillDirs(path18.join(dir, skillsDir), 3, maxItems - results.length));
|
|
339918
340066
|
}
|
|
339919
340067
|
}
|
|
339920
340068
|
for (const e3 of entries) {
|
|
339921
340069
|
if (!e3.isDirectory() || e3.name.startsWith(".git") || e3.name === "node_modules" || e3.name === "release" || e3.name.startsWith("release.locked-")) continue;
|
|
339922
|
-
walk4(
|
|
340070
|
+
walk4(path18.join(dir, e3.name), depth + 1);
|
|
339923
340071
|
}
|
|
339924
340072
|
};
|
|
339925
340073
|
walk4(root2, 0);
|
|
@@ -339947,25 +340095,25 @@ var SkillsManager = class {
|
|
|
339947
340095
|
if (!description) warnings.push("Missing required frontmatter field: description.");
|
|
339948
340096
|
if (name50 && !/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,119}$/.test(name50)) warnings.push("Skill name contains characters outside the portable Agent Skills subset.");
|
|
339949
340097
|
if (description && description.length > 1e3) warnings.push("Description is longer than recommended for skill discovery.");
|
|
339950
|
-
const folderName =
|
|
340098
|
+
const folderName = path18.basename(dir);
|
|
339951
340099
|
if (name50 && folderName && this.cleanName(name50) !== this.cleanName(folderName)) warnings.push("Skill name does not match containing folder name.");
|
|
339952
340100
|
return warnings;
|
|
339953
340101
|
}
|
|
339954
340102
|
pluginIdForSkill(dir) {
|
|
339955
|
-
let current =
|
|
340103
|
+
let current = path18.resolve(dir);
|
|
339956
340104
|
for (let i4 = 0; i4 < 6; i4++) {
|
|
339957
|
-
const codex =
|
|
339958
|
-
const claude =
|
|
340105
|
+
const codex = path18.join(current, ".codex-plugin", "plugin.json");
|
|
340106
|
+
const claude = path18.join(current, ".claude-plugin", "plugin.json");
|
|
339959
340107
|
for (const filePath of [codex, claude]) {
|
|
339960
340108
|
try {
|
|
339961
|
-
if (
|
|
339962
|
-
const raw = JSON.parse(
|
|
340109
|
+
if (fs16.existsSync(filePath)) {
|
|
340110
|
+
const raw = JSON.parse(fs16.readFileSync(filePath, "utf-8"));
|
|
339963
340111
|
if (raw?.name) return String(raw.name);
|
|
339964
340112
|
}
|
|
339965
340113
|
} catch {
|
|
339966
340114
|
}
|
|
339967
340115
|
}
|
|
339968
|
-
const parent =
|
|
340116
|
+
const parent = path18.dirname(current);
|
|
339969
340117
|
if (parent === current) break;
|
|
339970
340118
|
current = parent;
|
|
339971
340119
|
}
|
|
@@ -340511,6 +340659,22 @@ function createToolchainCore() {
|
|
|
340511
340659
|
return { registry: new ToolRegistry(), catalog: new CapabilityCatalog() };
|
|
340512
340660
|
}
|
|
340513
340661
|
|
|
340662
|
+
// src/core/emptyResponseRetry.ts
|
|
340663
|
+
var EMPTY_RESPONSE_RETRY_DELAYS_MS = [200, 800, 2e3, 1e4, 6e4];
|
|
340664
|
+
var MAX_EMPTY_RESPONSE_RETRIES = EMPTY_RESPONSE_RETRY_DELAYS_MS.length;
|
|
340665
|
+
var MAX_CONSECUTIVE_EMPTY_RESPONSES = MAX_EMPTY_RESPONSE_RETRIES + 1;
|
|
340666
|
+
function emptyResponseRetryDelayMs(consecutiveEmptyResponses) {
|
|
340667
|
+
return EMPTY_RESPONSE_RETRY_DELAYS_MS[Math.max(0, consecutiveEmptyResponses - 1)] ?? 0;
|
|
340668
|
+
}
|
|
340669
|
+
function observeEmptyResponseOutcome(consecutiveEmptyResponses, emptyResponse) {
|
|
340670
|
+
const nextCount = emptyResponse ? consecutiveEmptyResponses + 1 : 0;
|
|
340671
|
+
return {
|
|
340672
|
+
consecutiveEmptyResponses: nextCount,
|
|
340673
|
+
retry: emptyResponse && nextCount <= MAX_EMPTY_RESPONSE_RETRIES,
|
|
340674
|
+
terminate: emptyResponse && nextCount > MAX_EMPTY_RESPONSE_RETRIES
|
|
340675
|
+
};
|
|
340676
|
+
}
|
|
340677
|
+
|
|
340514
340678
|
// src/core/agentKernelRunner.ts
|
|
340515
340679
|
var publicStreamFilters = /* @__PURE__ */ new WeakMap();
|
|
340516
340680
|
var brokerOnlyAssistantBuffers = /* @__PURE__ */ new WeakMap();
|
|
@@ -340662,7 +340826,7 @@ function kernelTurnFailed(agent, turn) {
|
|
|
340662
340826
|
return turn.stopReason === "error" || agent.isLlmErrorText(turn.text);
|
|
340663
340827
|
}
|
|
340664
340828
|
function providerTurnIsEmpty(turn) {
|
|
340665
|
-
return /provider returned an empty response/i.test(`${turn.errorMessage}
|
|
340829
|
+
return !turn.activity && /provider returned an empty response/i.test(`${turn.errorMessage}
|
|
340666
340830
|
${turn.text}`);
|
|
340667
340831
|
}
|
|
340668
340832
|
function removeTrailingFailedAssistant(agent, messages) {
|
|
@@ -340671,6 +340835,12 @@ function removeTrailingFailedAssistant(agent, messages) {
|
|
|
340671
340835
|
const text = KernelMessageText(last);
|
|
340672
340836
|
if (last.stopReason === "error" || agent.isLlmErrorText(text)) messages.pop();
|
|
340673
340837
|
}
|
|
340838
|
+
function removeTrailingThoughtOnlyAssistant(messages) {
|
|
340839
|
+
const last = messages[messages.length - 1];
|
|
340840
|
+
if (last?.role !== "assistant") return;
|
|
340841
|
+
const hasToolCall = last.content.some((content) => content.type === "toolCall");
|
|
340842
|
+
if (!KernelMessageText(last).trim() && !hasToolCall) messages.pop();
|
|
340843
|
+
}
|
|
340674
340844
|
function normalizePublicProviderError(error, secrets = []) {
|
|
340675
340845
|
let raw = "";
|
|
340676
340846
|
if (error instanceof Error) {
|
|
@@ -340796,8 +340966,17 @@ async function runAgentKernel(agent) {
|
|
|
340796
340966
|
const tokens = [];
|
|
340797
340967
|
const runOnce = async (promptMessages, appendPromptToAgentHistory) => {
|
|
340798
340968
|
let lastAssistant = null;
|
|
340969
|
+
let observedActivity = false;
|
|
340970
|
+
let observedThought = false;
|
|
340799
340971
|
const unsubscribe = kernel2.subscribe(async (event) => {
|
|
340800
340972
|
await handleKernelEvent(agent, event, tokens);
|
|
340973
|
+
if (event.type === "message_update") {
|
|
340974
|
+
const delta = event.assistantMessageEvent;
|
|
340975
|
+
const deltaText = typeof delta.delta === "string" ? delta.delta : "";
|
|
340976
|
+
const thoughtDelta = delta.type === "thinking_delta" && !!deltaText.trim();
|
|
340977
|
+
observedThought = observedThought || thoughtDelta;
|
|
340978
|
+
observedActivity = observedActivity || thoughtDelta || delta.type === "text_delta" && !!deltaText.trim() || delta.type === "toolcall_end";
|
|
340979
|
+
}
|
|
340801
340980
|
if (event.type === "message_end" && event.message.role === "assistant") {
|
|
340802
340981
|
lastAssistant = event.message;
|
|
340803
340982
|
}
|
|
@@ -340815,11 +340994,13 @@ async function runAgentKernel(agent) {
|
|
|
340815
340994
|
const assistant = lastAssistant;
|
|
340816
340995
|
const text = assistant ? KernelMessageText(assistant) : "";
|
|
340817
340996
|
const hasToolCall = !!assistant?.content?.some((content) => content.type === "toolCall");
|
|
340818
|
-
const emptyResponse = !assistant || !text.trim() && !hasToolCall && String(assistant?.stopReason || "") !== "aborted";
|
|
340997
|
+
const emptyResponse = !assistant || !text.trim() && !hasToolCall && !observedActivity && String(assistant?.stopReason || "") !== "aborted";
|
|
340819
340998
|
return {
|
|
340820
340999
|
text: emptyResponse ? "[Error] Provider returned an empty response." : text,
|
|
340821
341000
|
stopReason: String(assistant?.stopReason || ""),
|
|
340822
|
-
errorMessage: String(assistant?.errorMessage || (emptyResponse ? "Provider returned an empty response." : ""))
|
|
341001
|
+
errorMessage: String(assistant?.errorMessage || (emptyResponse ? "Provider returned an empty response." : "")),
|
|
341002
|
+
activity: observedActivity || !!text.trim() || hasToolCall,
|
|
341003
|
+
thoughtOnly: observedThought && !text.trim() && !hasToolCall && !["error", "aborted"].includes(String(assistant?.stopReason || ""))
|
|
340823
341004
|
};
|
|
340824
341005
|
} finally {
|
|
340825
341006
|
unsubscribe();
|
|
@@ -340865,14 +341046,22 @@ async function runAgentKernel(agent) {
|
|
|
340865
341046
|
fallback: { from: modelBeforeKernelRun, to: agent.model, providerId: agent.activeDeployment()?.providerId }
|
|
340866
341047
|
});
|
|
340867
341048
|
}
|
|
340868
|
-
let
|
|
340869
|
-
|
|
341049
|
+
let consecutiveEmptyResponses = 0;
|
|
341050
|
+
for (; ; ) {
|
|
341051
|
+
const emptyResponseState = observeEmptyResponseOutcome(consecutiveEmptyResponses, providerTurnIsEmpty(lastTurn));
|
|
341052
|
+
consecutiveEmptyResponses = emptyResponseState.consecutiveEmptyResponses;
|
|
341053
|
+
if (lastTurn.thoughtOnly) {
|
|
341054
|
+
removeTrailingThoughtOnlyAssistant(kernel2.state.messages);
|
|
341055
|
+
lastTurn = await runWithCompressionResume([], false);
|
|
341056
|
+
continue;
|
|
341057
|
+
}
|
|
341058
|
+
if (!emptyResponseState.retry) break;
|
|
340870
341059
|
removeTrailingFailedAssistant(agent, kernel2.state.messages);
|
|
340871
|
-
|
|
340872
|
-
const notice = `[Model retry] Provider returned an empty response; retrying the same deployment (${
|
|
341060
|
+
const retryNumber = consecutiveEmptyResponses;
|
|
341061
|
+
const notice = `[Model retry] Provider returned an empty response; retrying the same deployment (${retryNumber}/${MAX_EMPTY_RESPONSE_RETRIES}) after ${emptyResponseRetryDelayMs(consecutiveEmptyResponses)}ms.`;
|
|
340873
341062
|
tokens.push({ type: "text", text: notice });
|
|
340874
341063
|
agent.recordWorkStatus(notice);
|
|
340875
|
-
await agent.waitForPlannedRouteRetry();
|
|
341064
|
+
await agent.waitForPlannedRouteRetry(emptyResponseRetryDelayMs(consecutiveEmptyResponses));
|
|
340876
341065
|
lastTurn = await runWithCompressionResume([], false);
|
|
340877
341066
|
}
|
|
340878
341067
|
let routeRetries = 0;
|
|
@@ -341068,7 +341257,7 @@ async function runAgentKernel(agent) {
|
|
|
341068
341257
|
return;
|
|
341069
341258
|
}
|
|
341070
341259
|
if (textStarted) finalContent.push({ type: "text", text });
|
|
341071
|
-
if (!finalContent.length) {
|
|
341260
|
+
if (!finalContent.length && !thinking.trim()) {
|
|
341072
341261
|
text = "[Error] Provider returned an empty response.";
|
|
341073
341262
|
finalContent.push({ type: "text", text });
|
|
341074
341263
|
}
|
|
@@ -344952,7 +345141,7 @@ var Agent4 = class _Agent {
|
|
|
344952
345141
|
this.config.set("skills", "auto_download", "disabled");
|
|
344953
345142
|
}
|
|
344954
345143
|
const modeStr = this.config.getStr("agent", "default_mode");
|
|
344955
|
-
this.mode = ["plan", "goal", "flow"].includes(modeStr) ? modeStr : "build";
|
|
345144
|
+
this.mode = ["plan", "chat", "goal", "flow"].includes(modeStr) ? modeStr : "build";
|
|
344956
345145
|
const inputStr = this.config.getStr("general", "default_input");
|
|
344957
345146
|
this.inputMode = inputStr === "next" ? "next" : "guide";
|
|
344958
345147
|
const configuredModel = this.config.getStr("models", "default_model");
|
|
@@ -345120,6 +345309,7 @@ var Agent4 = class _Agent {
|
|
|
345120
345309
|
return this.toolchainCore;
|
|
345121
345310
|
}
|
|
345122
345311
|
setMode(m2) {
|
|
345312
|
+
if (!["build", "plan", "chat", "goal", "flow"].includes(m2)) m2 = "build";
|
|
345123
345313
|
if (m2 === "goal" && !this.goal) {
|
|
345124
345314
|
this.goal = new GoalStateImpl("Set your objective");
|
|
345125
345315
|
}
|
|
@@ -345652,7 +345842,12 @@ var Agent4 = class _Agent {
|
|
|
345652
345842
|
beginRouteAttempt() {
|
|
345653
345843
|
this.routeAttemptStartedAt = Date.now();
|
|
345654
345844
|
}
|
|
345655
|
-
async waitForPlannedRouteRetry() {
|
|
345845
|
+
async waitForPlannedRouteRetry(explicitDelayMs) {
|
|
345846
|
+
if (explicitDelayMs !== void 0) {
|
|
345847
|
+
if (explicitDelayMs <= 0) return;
|
|
345848
|
+
await new Promise((resolve16) => setTimeout(resolve16, explicitDelayMs));
|
|
345849
|
+
return;
|
|
345850
|
+
}
|
|
345656
345851
|
const waitBudgetMs = Math.max(0, Math.min(15e3, this.lastRouteDecision?.retryBudgetMs ?? 5e3));
|
|
345657
345852
|
const delay = Math.max(0, Math.min(waitBudgetMs, this.lastRouteRetryDelayMs));
|
|
345658
345853
|
this.lastRouteRetryDelayMs = 0;
|
|
@@ -349482,7 +349677,20 @@ ${summary}`, segment, "local-summarize", true);
|
|
|
349482
349677
|
if (action === "get") return JSON.stringify({ ok: true, linkedPlan: this.getLinkedPlan() }, null, 2);
|
|
349483
349678
|
if (action !== "update") return JSON.stringify({ ok: false, error: `Unknown linked_plan action: ${action}` });
|
|
349484
349679
|
const expectedRevision = Number(input.expected_revision ?? input.expectedRevision);
|
|
349485
|
-
|
|
349680
|
+
const current = this.getLinkedPlan();
|
|
349681
|
+
let markdown = input.markdown === void 0 ? current.markdown : String(input.markdown);
|
|
349682
|
+
if (input.append !== void 0) markdown = `${current.markdown}${String(input.append)}`;
|
|
349683
|
+
if (input.old_text !== void 0 || input.oldText !== void 0) {
|
|
349684
|
+
const oldText = String(input.old_text ?? input.oldText ?? "");
|
|
349685
|
+
if (!oldText) throw new Error("linked_plan old_text must not be empty.");
|
|
349686
|
+
const matches = current.markdown.split(oldText).length - 1;
|
|
349687
|
+
if (!matches) throw new Error("linked_plan old_text was not found.");
|
|
349688
|
+
const replaceAll = input.replace_all === true || input.replaceAll === true;
|
|
349689
|
+
if (matches > 1 && !replaceAll) throw new Error(`linked_plan old_text matched ${matches} places; pass replace_all=true or a unique fragment.`);
|
|
349690
|
+
const newText = String(input.new_text ?? input.newText ?? "");
|
|
349691
|
+
markdown = replaceAll ? current.markdown.split(oldText).join(newText) : current.markdown.replace(oldText, newText);
|
|
349692
|
+
}
|
|
349693
|
+
return JSON.stringify({ ok: true, linkedPlan: this.updateLinkedPlan(markdown, expectedRevision) }, null, 2);
|
|
349486
349694
|
} catch (error) {
|
|
349487
349695
|
return JSON.stringify({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
349488
349696
|
}
|
|
@@ -351784,7 +351992,24 @@ ${this.formatAutomation(item)}` : `[automation_toggle] Not found: ${id}`;
|
|
|
351784
351992
|
}));
|
|
351785
351993
|
}
|
|
351786
351994
|
case "memory_lab_update": {
|
|
351787
|
-
const
|
|
351995
|
+
const selector2 = String(params.component || params.slug || "").trim();
|
|
351996
|
+
const prepared = selector2 ? this.memoryLab.preparePatch({
|
|
351997
|
+
component: selector2,
|
|
351998
|
+
name: params.name === void 0 ? void 0 : String(params.name),
|
|
351999
|
+
description: params.description === void 0 ? void 0 : String(params.description),
|
|
352000
|
+
tags: params.tags === void 0 ? void 0 : Array.isArray(params.tags) ? params.tags.map(String) : String(params.tags).split(/[,,\n]+/),
|
|
352001
|
+
tagPaths: params.tagPaths === void 0 ? void 0 : Array.isArray(params.tagPaths) ? params.tagPaths.filter(Array.isArray).map((pathValue) => pathValue.map(String)) : [],
|
|
352002
|
+
content: params.content === void 0 ? void 0 : String(params.content),
|
|
352003
|
+
contentAppend: params.contentAppend === void 0 && params.content_append === void 0 ? void 0 : String(params.contentAppend ?? params.content_append),
|
|
352004
|
+
oldText: params.oldText === void 0 && params.old_text === void 0 ? void 0 : String(params.oldText ?? params.old_text),
|
|
352005
|
+
newText: String(params.newText ?? params.new_text ?? ""),
|
|
352006
|
+
replaceAll: params.replaceAll === true || params.replace_all === true,
|
|
352007
|
+
kind: params.kind === void 0 ? void 0 : params.kind === "folder" ? "folder" : "file",
|
|
352008
|
+
expectedUpdatedAt: String(params.expectedUpdatedAt || params.expected_updated_at || ""),
|
|
352009
|
+
reason: String(params.reason || ""),
|
|
352010
|
+
source: String(params.source || "")
|
|
352011
|
+
}) : void 0;
|
|
352012
|
+
const result = await this.updateMemoryLab(prepared || {
|
|
351788
352013
|
name: String(params.name || ""),
|
|
351789
352014
|
description: String(params.description || ""),
|
|
351790
352015
|
tags: Array.isArray(params.tags) ? params.tags.map(String) : String(params.tags || "").split(/[,,\n]+/),
|
|
@@ -352787,6 +353012,8 @@ When using file tools (read, write, edit, glob), use ABSOLUTE paths rooted at th
|
|
|
352787
353012
|
parts.push(this.buildFeatureDisclosurePrompt());
|
|
352788
353013
|
if (this.mode === "plan") parts.push(`[Plan Tool Policy]
|
|
352789
353014
|
${planModePolicyPrompt()}`);
|
|
353015
|
+
if (this.mode === "chat") parts.push(`[Chat Tool Policy]
|
|
353016
|
+
${chatModePolicyPrompt()}`);
|
|
352790
353017
|
const pm = this.config.getStr("workspace", "prompt_mode") || "both";
|
|
352791
353018
|
const injectedPrompts = /* @__PURE__ */ new Set();
|
|
352792
353019
|
if ((pm === "global_only" || pm === "both") && globalPrompt) {
|
|
@@ -352908,7 +353135,7 @@ ${custom}`);
|
|
|
352908
353135
|
`- Language policy: general.language=${language}; the UI can switch this at runtime and each turn must obey the current value. auto follows the user's dominant input language, en replies in English, zh replies in Simplified Chinese. Keep code, commands, file paths, JSON keys, model/provider names, tool names, quoted source text, and user-provided literals exactly as required by their source language.`,
|
|
352909
353136
|
`- Workspace permissions: access_permission=${permission}; file tools are checked before execution and blocked when they exceed the configured workspace boundary.`,
|
|
352910
353137
|
`- Remote repository safety: when the active workspace or any target path is inside a GitHub/remote-backed repository, proactively use repo_security_audit and file_audit before git_push, gh_pr_create, release packaging, public reporting, or cloud-side audit. Treat public remotes as public disclosure surfaces and keep private URLs, secrets, privacy addresses (credential URLs, private network addresses, local user paths), local runtime state, archives, Memory Lab, Work, config, and release outputs out of commits and summaries. git_push/gh_pr_create hard-block on detected high-risk findings until a second review resolves them and the action is retried with security_review_confirmed=true.`,
|
|
352911
|
-
`- Mode engine: current mode=${this.modeName()}; Build works autonomously, Plan is fully read-only
|
|
353138
|
+
`- Mode engine: current mode=${this.modeName()}; Build works autonomously, Plan is fully read-only, Chat only performs web search/fetch evidence gathering and prompt synthesis, Goal continues until completion unless paused, Flow follows saved workflow components.`,
|
|
352912
353139
|
`- Input mode: ${input}; Guide injects immediately, Next queues user intent for the following build turn.`,
|
|
352913
353140
|
`- Option feedback: ${this.buildQuestionPolicyPrompt(optionFeedback)}`,
|
|
352914
353141
|
`- Model policy: current model=${this.model || "(unset)"}, intelligence=${this.intelligence}, auto-switch=${modelSwitch}.`,
|
|
@@ -352974,6 +353201,14 @@ ${custom}`);
|
|
|
352974
353201
|
'Only after the durable linked plan has actually been updated and the plan is complete, expose the fixed mode handoff asking whether execution should begin. Offer exactly these two choices in the user language: "\u662F\uFF0C\u6267\u884C\u6B64\u8BA1\u5212" / "\u5426\uFF0C\u8BF7\u8865\u5145____" (or "Yes, execute this plan" / "No, please supplement _____"). This fixed handoff remains required when discretionary questions are disabled.',
|
|
352975
353202
|
"A positive choice starts a new Build-mode input. A negative choice remains in Plan mode so the user can supply the missing details."
|
|
352976
353203
|
]).join("\n");
|
|
353204
|
+
case "chat":
|
|
353205
|
+
return withLanguage([
|
|
353206
|
+
"CHAT MODE.",
|
|
353207
|
+
"Use only web_search and web_fetch. You have no workspace, host, application, memory, task, browser-control, or write permissions.",
|
|
353208
|
+
"Perform an online search to gather evidence before answering. Fetch primary or authoritative pages when the search snippets are insufficient.",
|
|
353209
|
+
"After sufficient evidence is collected, summarize and answer the user as soon as possible. Stay concise and do not turn the request into a long-running Build, Plan, Goal, or Flow task.",
|
|
353210
|
+
"Distinguish sourced facts from uncertainty and include useful source links in the final answer."
|
|
353211
|
+
]).join("\n");
|
|
352977
353212
|
case "goal": {
|
|
352978
353213
|
const g2 = this.goal?.history() || "";
|
|
352979
353214
|
const paused = this.goal?.paused ? "\n[GOAL PAUSED by user. Wait for resume.]" : "\n[Continue working until the goal is achieved.]";
|