newmark-agent 0.5.8 → 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.
@@ -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, input2) {
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, input2);
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, input2),
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, input2) {
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, input2);
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, input2),
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);
@@ -331322,8 +331322,8 @@ async function fuzzyDiscoverWithoutGuide(input2, explicit, preferredModels = [])
331322
331322
  }
331323
331323
 
331324
331324
  // src/tools/index.ts
331325
- var fs14 = __toESM(require("fs"));
331326
- var path16 = __toESM(require("path"));
331325
+ var fs15 = __toESM(require("fs"));
331326
+ var path17 = __toESM(require("path"));
331327
331327
  var crypto8 = __toESM(require("crypto"));
331328
331328
  var import_url2 = require("url");
331329
331329
 
@@ -331667,7 +331667,8 @@ var MemoryLabManager = class {
331667
331667
  "Use memory_lab_read to inspect index.json before deciding what memory is relevant.",
331668
331668
  "Use memory_lab_query for bounded task-relevant retrieval; do not inject the complete index when a focused query is sufficient.",
331669
331669
  "Use memory_lab_read with component/name/slug to read a component core markdown file.",
331670
- "Use memory_lab_update only when the user asks to create or update durable memory, passing name, description, tags, optional tagPaths, content, and optional kind=file|folder.",
331670
+ "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.",
331671
+ "For small body edits prefer contentAppend or oldText/newText over resending the complete content.",
331671
331672
  "For an existing component, pass expectedUpdatedAt from the latest read/query result. A stale update is rejected instead of overwriting newer memory.",
331672
331673
  "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.",
331673
331674
  "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.",
@@ -331775,6 +331776,39 @@ var MemoryLabManager = class {
331775
331776
  source: String(input2.source || "").trim()
331776
331777
  };
331777
331778
  }
331779
+ preparePatch(input2) {
331780
+ const selector2 = String(input2.component || "").trim();
331781
+ if (!selector2) throw new Error("Memory component is required for a patch.");
331782
+ const current = this.read(selector2);
331783
+ if (!current.ok || !current.component) throw new Error(current.error || `Memory component not found: ${selector2}`);
331784
+ const existing = current.component.meta;
331785
+ const oldContent = current.component.content;
331786
+ let content = input2.content !== void 0 ? String(input2.content) : oldContent;
331787
+ if (input2.contentAppend !== void 0) content = `${oldContent}${String(input2.contentAppend)}`;
331788
+ if (input2.oldText !== void 0) {
331789
+ const oldText = String(input2.oldText);
331790
+ if (!oldText) throw new Error("oldText must not be empty.");
331791
+ const matches = oldContent.split(oldText).length - 1;
331792
+ if (!matches) throw new Error("oldText was not found in the Memory Lab component.");
331793
+ if (matches > 1 && input2.replaceAll !== true) throw new Error(`oldText matched ${matches} places; pass replaceAll=true or a unique fragment.`);
331794
+ content = input2.replaceAll === true ? oldContent.split(oldText).join(String(input2.newText || "")) : oldContent.replace(oldText, String(input2.newText || ""));
331795
+ }
331796
+ const name50 = input2.name === void 0 ? existing.name : String(input2.name);
331797
+ if (this.slugify(name50) !== current.component.slug) {
331798
+ throw new Error("Renaming a Memory Lab component is not supported by incremental patch; create the new component then delete the old one.");
331799
+ }
331800
+ return this.prepareUpdate({
331801
+ name: name50,
331802
+ description: input2.description === void 0 ? existing.description : String(input2.description),
331803
+ tags: input2.tags === void 0 ? existing.tags : input2.tags,
331804
+ tagPaths: input2.tagPaths === void 0 ? existing.tagPaths : input2.tagPaths,
331805
+ content,
331806
+ kind: input2.kind === void 0 ? existing.kind : input2.kind,
331807
+ expectedUpdatedAt: String(input2.expectedUpdatedAt || existing.updatedAt),
331808
+ reason: input2.reason,
331809
+ source: input2.source
331810
+ });
331811
+ }
331778
331812
  update(prepared) {
331779
331813
  this.ensure();
331780
331814
  const index = this.loadIndex();
@@ -332321,20 +332355,23 @@ ${JSON.stringify(payload, null, 2)}`;
332321
332355
  }
332322
332356
  };
332323
332357
 
332358
+ // src/tools/index.ts
332359
+ init_flow();
332360
+
332324
332361
  // src/core/compat.ts
332325
- var fs6 = __toESM(require("fs"));
332326
- var path7 = __toESM(require("path"));
332362
+ var fs7 = __toESM(require("fs"));
332363
+ var path8 = __toESM(require("path"));
332327
332364
  var os2 = __toESM(require("os"));
332328
332365
  function readJson(filePath) {
332329
332366
  try {
332330
- return JSON.parse(fs6.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, ""));
332367
+ return JSON.parse(fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, ""));
332331
332368
  } catch {
332332
332369
  return null;
332333
332370
  }
332334
332371
  }
332335
332372
  function readJsonLoose(filePath) {
332336
332373
  try {
332337
- const withoutBom = fs6.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
332374
+ const withoutBom = fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
332338
332375
  const withoutComments = withoutBom.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|\s)\/\/.*$/gm, "$1");
332339
332376
  return JSON.parse(withoutComments);
332340
332377
  } catch {
@@ -332415,7 +332452,7 @@ function normalizeToolResult(output, metadata) {
332415
332452
  return { ok: !error, output, error, metadata };
332416
332453
  }
332417
332454
  function componentPaths(root2, value) {
332418
- return asStringArray(value).map((item) => path7.resolve(root2, item));
332455
+ return asStringArray(value).map((item) => path8.resolve(root2, item));
332419
332456
  }
332420
332457
  function manifestComponentPaths(root2, manifest, ...keys) {
332421
332458
  for (const key3 of keys) {
@@ -332426,7 +332463,7 @@ function manifestComponentPaths(root2, manifest, ...keys) {
332426
332463
  function discoverComponentFiles(root2, relativeDirs, extension, maxDepth = 2) {
332427
332464
  const files = [];
332428
332465
  for (const dir of relativeDirs) {
332429
- files.push(...listFilesRecursive(path7.join(root2, dir), extension, maxDepth));
332466
+ files.push(...listFilesRecursive(path8.join(root2, dir), extension, maxDepth));
332430
332467
  }
332431
332468
  return Array.from(new Set(files)).sort();
332432
332469
  }
@@ -332451,12 +332488,12 @@ function collectMcpServers(...values) {
332451
332488
  function defaultComponentWarnings(kind, components) {
332452
332489
  const warnings = [];
332453
332490
  for (const item of components) {
332454
- if (path7.isAbsolute(item) && !fs6.existsSync(item)) warnings.push(`${kind} path does not exist: ${item}`);
332491
+ if (path8.isAbsolute(item) && !fs7.existsSync(item)) warnings.push(`${kind} path does not exist: ${item}`);
332455
332492
  }
332456
332493
  return warnings;
332457
332494
  }
332458
332495
  function normalizeCodexPlugin(root2, manifest) {
332459
- const name50 = asString(manifest.name) || path7.basename(root2);
332496
+ const name50 = asString(manifest.name) || path8.basename(root2);
332460
332497
  const components = {
332461
332498
  skills: manifestComponentPaths(root2, manifest, "skills"),
332462
332499
  agents: manifestComponentPaths(root2, manifest, "agents"),
@@ -332487,7 +332524,7 @@ function normalizeCodexPlugin(root2, manifest) {
332487
332524
  };
332488
332525
  }
332489
332526
  function normalizeClaudePlugin(root2, manifest) {
332490
- const name50 = asString(manifest.name) || path7.basename(root2);
332527
+ const name50 = asString(manifest.name) || path8.basename(root2);
332491
332528
  const experimental = nestedRecord(manifest.experimental);
332492
332529
  const components = {
332493
332530
  skills: manifestComponentPaths(root2, manifest, "skills"),
@@ -332525,7 +332562,7 @@ function normalizeClaudePlugin(root2, manifest) {
332525
332562
  };
332526
332563
  }
332527
332564
  function normalizeNewmarkPlugin(root2, manifest) {
332528
- const name50 = asString(manifest.name) || path7.basename(root2);
332565
+ const name50 = asString(manifest.name) || path8.basename(root2);
332529
332566
  return {
332530
332567
  id: `newmark:${name50}`,
332531
332568
  ecosystem: "newmark",
@@ -332554,7 +332591,7 @@ function findPluginRoots(root2, maxDepth = 5) {
332554
332591
  if (depth > maxDepth) return;
332555
332592
  let entries;
332556
332593
  try {
332557
- entries = fs6.readdirSync(dir, { withFileTypes: true });
332594
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
332558
332595
  } catch {
332559
332596
  return;
332560
332597
  }
@@ -332563,7 +332600,7 @@ function findPluginRoots(root2, maxDepth = 5) {
332563
332600
  }
332564
332601
  for (const entry of entries) {
332565
332602
  if (!entry.isDirectory() || skip.has(entry.name) || entry.name.startsWith("release.locked-")) continue;
332566
- walk4(path7.join(dir, entry.name), depth + 1);
332603
+ walk4(path8.join(dir, entry.name), depth + 1);
332567
332604
  }
332568
332605
  };
332569
332606
  walk4(root2, 0);
@@ -332572,20 +332609,20 @@ function findPluginRoots(root2, maxDepth = 5) {
332572
332609
  function discoverPluginManifests(root2) {
332573
332610
  const manifests = [];
332574
332611
  for (const pluginRoot of findPluginRoots(root2)) {
332575
- const codexPath = path7.join(pluginRoot, ".codex-plugin", "plugin.json");
332576
- const claudePath = path7.join(pluginRoot, ".claude-plugin", "plugin.json");
332577
- const newmarkPath = path7.join(pluginRoot, ".newmark-plugin", "plugin.json");
332578
- const codex = fs6.existsSync(codexPath) ? readJson(codexPath) : null;
332579
- const claude = fs6.existsSync(claudePath) ? readJson(claudePath) : null;
332580
- const newmark = fs6.existsSync(newmarkPath) ? readJson(newmarkPath) : null;
332612
+ const codexPath = path8.join(pluginRoot, ".codex-plugin", "plugin.json");
332613
+ const claudePath = path8.join(pluginRoot, ".claude-plugin", "plugin.json");
332614
+ const newmarkPath = path8.join(pluginRoot, ".newmark-plugin", "plugin.json");
332615
+ const codex = fs7.existsSync(codexPath) ? readJson(codexPath) : null;
332616
+ const claude = fs7.existsSync(claudePath) ? readJson(claudePath) : null;
332617
+ const newmark = fs7.existsSync(newmarkPath) ? readJson(newmarkPath) : null;
332581
332618
  if (codex && typeof codex === "object") manifests.push(normalizeCodexPlugin(pluginRoot, codex));
332582
332619
  if (claude && typeof claude === "object") manifests.push(normalizeClaudePlugin(pluginRoot, claude));
332583
332620
  if (newmark && typeof newmark === "object") manifests.push(normalizeNewmarkPlugin(pluginRoot, newmark));
332584
332621
  }
332585
332622
  const projectOpencode = readOpenCodeManifest(root2, "project");
332586
332623
  if (projectOpencode) manifests.push(projectOpencode);
332587
- const userOpenCodeRoot = path7.join(os2.homedir(), ".config", "opencode");
332588
- if (path7.resolve(userOpenCodeRoot) !== path7.resolve(path7.join(root2, ".opencode"))) {
332624
+ const userOpenCodeRoot = path8.join(os2.homedir(), ".config", "opencode");
332625
+ if (path8.resolve(userOpenCodeRoot) !== path8.resolve(path8.join(root2, ".opencode"))) {
332589
332626
  const userOpenCode = readOpenCodeManifest(userOpenCodeRoot, "user");
332590
332627
  if (userOpenCode) manifests.push(userOpenCode);
332591
332628
  }
@@ -332593,20 +332630,20 @@ function discoverPluginManifests(root2) {
332593
332630
  }
332594
332631
  function readOpenCodeConfig(root2) {
332595
332632
  const candidates = [
332596
- path7.join(root2, "opencode.json"),
332597
- path7.join(root2, "opencode.jsonc"),
332598
- path7.join(root2, ".opencode", "opencode.json"),
332599
- path7.join(root2, ".opencode", "opencode.jsonc")
332633
+ path8.join(root2, "opencode.json"),
332634
+ path8.join(root2, "opencode.jsonc"),
332635
+ path8.join(root2, ".opencode", "opencode.json"),
332636
+ path8.join(root2, ".opencode", "opencode.jsonc")
332600
332637
  ];
332601
332638
  for (const filePath of candidates) {
332602
- if (fs6.existsSync(filePath)) return { path: filePath, value: readJsonLoose(filePath) };
332639
+ if (fs7.existsSync(filePath)) return { path: filePath, value: readJsonLoose(filePath) };
332603
332640
  }
332604
332641
  return null;
332605
332642
  }
332606
332643
  function readOpenCodeManifest(root2, scope) {
332607
- const localRoot = scope === "project" ? path7.join(root2, ".opencode") : root2;
332608
- const opencodeToolsDir = path7.join(localRoot, "tools");
332609
- const opencodePluginsDir = path7.join(localRoot, "plugins");
332644
+ const localRoot = scope === "project" ? path8.join(root2, ".opencode") : root2;
332645
+ const opencodeToolsDir = path8.join(localRoot, "tools");
332646
+ const opencodePluginsDir = path8.join(localRoot, "plugins");
332610
332647
  const tools = listCodeFiles(opencodeToolsDir);
332611
332648
  const pluginFiles = listCodeFiles(opencodePluginsDir);
332612
332649
  const config = readOpenCodeConfig(root2);
@@ -332647,18 +332684,18 @@ function readOpenCodeManifest(root2, scope) {
332647
332684
  }
332648
332685
  function discoverOpenCodeInstructionFiles(projectRoot, localRoot) {
332649
332686
  const candidates = [
332650
- path7.join(projectRoot, "AGENTS.md"),
332651
- path7.join(projectRoot, ".opencode", "instructions.md"),
332652
- path7.join(projectRoot, ".opencode", "AGENTS.md"),
332653
- path7.join(localRoot, "instructions.md"),
332654
- path7.join(localRoot, "AGENTS.md")
332687
+ path8.join(projectRoot, "AGENTS.md"),
332688
+ path8.join(projectRoot, ".opencode", "instructions.md"),
332689
+ path8.join(projectRoot, ".opencode", "AGENTS.md"),
332690
+ path8.join(localRoot, "instructions.md"),
332691
+ path8.join(localRoot, "AGENTS.md")
332655
332692
  ];
332656
- return Array.from(new Set(candidates.filter((filePath) => fs6.existsSync(filePath)))).sort();
332693
+ return Array.from(new Set(candidates.filter((filePath) => fs7.existsSync(filePath)))).sort();
332657
332694
  }
332658
332695
  function dedupeManifests(manifests) {
332659
332696
  const seen = /* @__PURE__ */ new Set();
332660
332697
  return manifests.filter((item) => {
332661
- const key3 = `${item.id}:${path7.resolve(item.root)}`;
332698
+ const key3 = `${item.id}:${path8.resolve(item.root)}`;
332662
332699
  if (seen.has(key3)) return false;
332663
332700
  seen.add(key3);
332664
332701
  return true;
@@ -332666,14 +332703,14 @@ function dedupeManifests(manifests) {
332666
332703
  }
332667
332704
  function listCodeFiles(dir) {
332668
332705
  try {
332669
- return fs6.readdirSync(dir, { withFileTypes: true }).filter((e3) => e3.isFile() && /\.(?:c?js|mjs|ts)$/.test(e3.name)).map((e3) => path7.join(dir, e3.name)).sort();
332706
+ 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();
332670
332707
  } catch {
332671
332708
  return [];
332672
332709
  }
332673
332710
  }
332674
332711
  function parseFrontmatterMarkdown(filePath) {
332675
332712
  try {
332676
- const content = fs6.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
332713
+ const content = fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
332677
332714
  const match = content.match(/^---\s*([\s\S]*?)\s*---\s*/);
332678
332715
  if (!match) return { metadata: {}, body: content };
332679
332716
  const metadata = {};
@@ -332702,7 +332739,7 @@ function parseMetadataValue(raw) {
332702
332739
  function parseSimpleToml(filePath) {
332703
332740
  try {
332704
332741
  const metadata = {};
332705
- const content = fs6.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
332742
+ const content = fs7.readFileSync(filePath, "utf-8").replace(/^\uFEFF/, "");
332706
332743
  const multiline = null;
332707
332744
  if (multiline) return metadata;
332708
332745
  const lines = content.split(/\r?\n/);
@@ -332736,7 +332773,7 @@ function parseSimpleToml(filePath) {
332736
332773
  }
332737
332774
  }
332738
332775
  function agentPresetFromMetadata(filePath, ecosystem, metadata, body = "") {
332739
- const name50 = asString(metadata.name) || path7.basename(filePath).replace(/\.(?:toml|md)$/i, "");
332776
+ const name50 = asString(metadata.name) || path8.basename(filePath).replace(/\.(?:toml|md)$/i, "");
332740
332777
  const description = asString(metadata.description);
332741
332778
  const instructions = asString(metadata.developer_instructions || metadata.instructions || metadata.prompt) || body.trim();
332742
332779
  if (!name50 || !description) return null;
@@ -332764,12 +332801,12 @@ function listFilesRecursive(root2, extension, maxDepth = 4) {
332764
332801
  if (depth > maxDepth) return;
332765
332802
  let entries;
332766
332803
  try {
332767
- entries = fs6.readdirSync(dir, { withFileTypes: true });
332804
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
332768
332805
  } catch {
332769
332806
  return;
332770
332807
  }
332771
332808
  for (const entry of entries) {
332772
- const full = path7.join(dir, entry.name);
332809
+ const full = path8.join(dir, entry.name);
332773
332810
  if (entry.isFile() && extension.test(entry.name)) results.push(full);
332774
332811
  if (entry.isDirectory() && !entry.name.startsWith(".git") && entry.name !== "node_modules") walk4(full, depth + 1);
332775
332812
  }
@@ -332780,10 +332817,10 @@ function listFilesRecursive(root2, extension, maxDepth = 4) {
332780
332817
  function discoverAgentPresets(root2) {
332781
332818
  const presets = [];
332782
332819
  const codexDirs = [
332783
- path7.join(root2, ".codex", "agents"),
332784
- path7.join(root2, ".agents", "agents"),
332785
- path7.join(os2.homedir(), ".codex", "agents"),
332786
- path7.join(os2.homedir(), ".agents", "agents")
332820
+ path8.join(root2, ".codex", "agents"),
332821
+ path8.join(root2, ".agents", "agents"),
332822
+ path8.join(os2.homedir(), ".codex", "agents"),
332823
+ path8.join(os2.homedir(), ".agents", "agents")
332787
332824
  ];
332788
332825
  for (const dir of codexDirs) {
332789
332826
  for (const filePath of listFilesRecursive(dir, /\.toml$/i, 1)) {
@@ -332792,14 +332829,14 @@ function discoverAgentPresets(root2) {
332792
332829
  }
332793
332830
  }
332794
332831
  const claudeDirs = [
332795
- path7.join(root2, ".claude", "agents"),
332796
- path7.join(os2.homedir(), ".claude", "agents"),
332797
- path7.join(os2.homedir(), ".config", "opencode", "agents")
332832
+ path8.join(root2, ".claude", "agents"),
332833
+ path8.join(os2.homedir(), ".claude", "agents"),
332834
+ path8.join(os2.homedir(), ".config", "opencode", "agents")
332798
332835
  ];
332799
332836
  for (const dir of claudeDirs) {
332800
332837
  for (const filePath of listFilesRecursive(dir, /\.md$/i, 1)) {
332801
332838
  const parsed = parseFrontmatterMarkdown(filePath);
332802
- const ecosystem = filePath.includes(`${path7.sep}.config${path7.sep}opencode${path7.sep}`) ? "opencode" : "claude-code";
332839
+ const ecosystem = filePath.includes(`${path8.sep}.config${path8.sep}opencode${path8.sep}`) ? "opencode" : "claude-code";
332803
332840
  const preset = agentPresetFromMetadata(filePath, ecosystem, parsed.metadata, parsed.body);
332804
332841
  if (preset) presets.push(preset);
332805
332842
  }
@@ -332836,15 +332873,15 @@ function findAgentPreset(root2, selector2) {
332836
332873
  preset.id,
332837
332874
  preset.name,
332838
332875
  `${preset.ecosystem}:${preset.name}`,
332839
- path7.basename(preset.path)
332876
+ path8.basename(preset.path)
332840
332877
  ].map((value) => String(value || "").toLowerCase());
332841
- return keys.includes(normalized) || path7.resolve(preset.path).toLowerCase() === path7.resolve(wanted).toLowerCase();
332878
+ return keys.includes(normalized) || path8.resolve(preset.path).toLowerCase() === path8.resolve(wanted).toLowerCase();
332842
332879
  }) || null;
332843
332880
  }
332844
332881
 
332845
332882
  // src/tools/terminalTakeover.ts
332846
- var fs7 = __toESM(require("fs"));
332847
- var path8 = __toESM(require("path"));
332883
+ var fs8 = __toESM(require("fs"));
332884
+ var path9 = __toESM(require("path"));
332848
332885
  var import_child_process2 = require("child_process");
332849
332886
  var import_crypto5 = require("crypto");
332850
332887
  var ROOT_TERMINAL_ACTOR_ID = "00000000-0000-4000-8000-000000000001";
@@ -332859,7 +332896,7 @@ function isoNow() {
332859
332896
  return (/* @__PURE__ */ new Date()).toISOString();
332860
332897
  }
332861
332898
  function canonicalPersistenceRoot(root2) {
332862
- const resolved = path8.resolve(root2 || process.cwd());
332899
+ const resolved = path9.resolve(root2 || process.cwd());
332863
332900
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
332864
332901
  }
332865
332902
  function portableWorkspacePath(input2) {
@@ -332868,7 +332905,7 @@ function portableWorkspacePath(input2) {
332868
332905
  if (wsl) return `${wsl[1].toLowerCase()}:/${String(wsl[2] || "").replace(/^\/+|\/+$/g, "")}`.replace(/\/$/, "");
332869
332906
  const drive = /^([a-zA-Z]):(?:\/(.*))?$/.exec(raw);
332870
332907
  if (drive) return `${drive[1].toLowerCase()}:/${String(drive[2] || "").replace(/^\/+|\/+$/g, "")}`.replace(/\/$/, "");
332871
- const resolved = path8.resolve(raw).replace(/\\/g, "/").replace(/\/+$/g, "");
332908
+ const resolved = path9.resolve(raw).replace(/\\/g, "/").replace(/\/+$/g, "");
332872
332909
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
332873
332910
  }
332874
332911
  function terminalTakeoverWorkspaceId(workspacePath) {
@@ -332963,12 +333000,12 @@ function nodePtyHasConptyDll() {
332963
333000
  if (process.platform !== "win32") return false;
332964
333001
  try {
332965
333002
  const packageJson = require.resolve("node-pty/package.json");
332966
- const packageRoot = path8.dirname(packageJson);
333003
+ const packageRoot = path9.dirname(packageJson);
332967
333004
  return [
332968
- path8.join(packageRoot, "build", "Release", "conpty", "conpty.dll"),
332969
- path8.join(packageRoot, "build", "Debug", "conpty", "conpty.dll"),
332970
- path8.join(packageRoot, "prebuilds", `${process.platform}-${process.arch}`, "conpty", "conpty.dll")
332971
- ].some((candidate) => fs7.existsSync(candidate));
333005
+ path9.join(packageRoot, "build", "Release", "conpty", "conpty.dll"),
333006
+ path9.join(packageRoot, "build", "Debug", "conpty", "conpty.dll"),
333007
+ path9.join(packageRoot, "prebuilds", `${process.platform}-${process.arch}`, "conpty", "conpty.dll")
333008
+ ].some((candidate) => fs8.existsSync(candidate));
332972
333009
  } catch {
332973
333010
  return false;
332974
333011
  }
@@ -333201,7 +333238,7 @@ function spawnTakeoverPty(shell, cwd, env, cols, rows) {
333201
333238
  };
333202
333239
  }
333203
333240
  function persistencePath(root2) {
333204
- return path8.join(root2, "Terminal", "Takeover.json");
333241
+ return path9.join(root2, "Terminal", "Takeover.json");
333205
333242
  }
333206
333243
  function validPersistedRecord(input2) {
333207
333244
  if (!input2 || typeof input2 !== "object") return null;
@@ -333242,7 +333279,7 @@ function ensurePersistenceLoaded(rootRaw) {
333242
333279
  if (loaded) return loaded;
333243
333280
  const records = /* @__PURE__ */ new Map();
333244
333281
  try {
333245
- const parsed = JSON.parse(fs7.readFileSync(persistencePath(root2), "utf-8"));
333282
+ const parsed = JSON.parse(fs8.readFileSync(persistencePath(root2), "utf-8"));
333246
333283
  if (Array.isArray(parsed.records)) {
333247
333284
  for (const input2 of parsed.records) {
333248
333285
  const record = validPersistedRecord(input2);
@@ -333260,19 +333297,19 @@ function persistEndedRecords(rootRaw) {
333260
333297
  const output = { version: 1, updatedAt: isoNow(), records };
333261
333298
  const filePath = persistencePath(root2);
333262
333299
  const tempPath = `${filePath}.tmp-${process.pid}-${(0, import_crypto5.randomUUID)()}`;
333263
- fs7.mkdirSync(path8.dirname(filePath), { recursive: true });
333264
- const fd = fs7.openSync(tempPath, "w");
333300
+ fs8.mkdirSync(path9.dirname(filePath), { recursive: true });
333301
+ const fd = fs8.openSync(tempPath, "w");
333265
333302
  try {
333266
- fs7.writeFileSync(fd, JSON.stringify(output, null, 2), "utf-8");
333267
- fs7.fsyncSync(fd);
333303
+ fs8.writeFileSync(fd, JSON.stringify(output, null, 2), "utf-8");
333304
+ fs8.fsyncSync(fd);
333268
333305
  } finally {
333269
- fs7.closeSync(fd);
333306
+ fs8.closeSync(fd);
333270
333307
  }
333271
333308
  try {
333272
- fs7.renameSync(tempPath, filePath);
333309
+ fs8.renameSync(tempPath, filePath);
333273
333310
  } catch (error) {
333274
333311
  try {
333275
- fs7.rmSync(tempPath, { force: true });
333312
+ fs8.rmSync(tempPath, { force: true });
333276
333313
  } catch {
333277
333314
  }
333278
333315
  throw error;
@@ -333505,8 +333542,8 @@ function runTerminalTakeover(input2) {
333505
333542
  }
333506
333543
 
333507
333544
  // src/tools/computerUse.ts
333508
- var fs8 = __toESM(require("fs"));
333509
- var path9 = __toESM(require("path"));
333545
+ var fs9 = __toESM(require("fs"));
333546
+ var path10 = __toESM(require("path"));
333510
333547
  var crypto6 = __toESM(require("crypto"));
333511
333548
  var os3 = __toESM(require("os"));
333512
333549
 
@@ -333714,8 +333751,8 @@ async function runPowerShell(script, timeout = 3e4, lane = "action") {
333714
333751
  return await runPersistentPowerShell(script, timeout, lane);
333715
333752
  }
333716
333753
  function tempScreenshotDir() {
333717
- const dir = path9.join(os3.tmpdir(), "newmark-computer-use");
333718
- fs8.mkdirSync(dir, { recursive: true });
333754
+ const dir = path10.join(os3.tmpdir(), "newmark-computer-use");
333755
+ fs9.mkdirSync(dir, { recursive: true });
333719
333756
  const now2 = Date.now();
333720
333757
  if (now2 - lastScreenshotCleanupAt >= SCREENSHOT_CLEANUP_INTERVAL_MS) {
333721
333758
  lastScreenshotCleanupAt = now2;
@@ -333737,7 +333774,7 @@ function ephemeralScreenshotPath(kind, directory = tempScreenshotDir(), createdA
333737
333774
  const pid = Math.max(1, Math.floor(Number(ownerPid) || process.pid));
333738
333775
  const timestamp = Math.max(0, Math.floor(Number(createdAt) || Date.now()));
333739
333776
  const nonce = /^[a-f0-9]{8}$/i.test(String(suffix)) ? String(suffix).toLowerCase() : crypto6.randomBytes(4).toString("hex");
333740
- return path9.join(directory, `${kind}-p${pid}-t${timestamp}-${nonce}.jpg`);
333777
+ return path10.join(directory, `${kind}-p${pid}-t${timestamp}-${nonce}.jpg`);
333741
333778
  }
333742
333779
  function isProcessAlive(pid) {
333743
333780
  if (!Number.isSafeInteger(pid) || pid <= 0) return false;
@@ -333750,14 +333787,14 @@ function isProcessAlive(pid) {
333750
333787
  }
333751
333788
  }
333752
333789
  function cleanupStaleScreenshots(options = {}) {
333753
- const directory = options.directory || path9.join(os3.tmpdir(), "newmark-computer-use");
333790
+ const directory = options.directory || path10.join(os3.tmpdir(), "newmark-computer-use");
333754
333791
  const now2 = Number.isFinite(Number(options.now)) ? Number(options.now) : Date.now();
333755
333792
  const processAlive = options.isProcessAlive || isProcessAlive;
333756
333793
  const ownedPattern = /^(?:observe|app)-p([1-9]\d*)-t(\d{10,16})-[a-f0-9]{8}\.jpg$/i;
333757
333794
  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;
333758
333795
  let names = [];
333759
333796
  try {
333760
- names = fs8.readdirSync(directory);
333797
+ names = fs9.readdirSync(directory);
333761
333798
  } catch {
333762
333799
  return { removed: 0 };
333763
333800
  }
@@ -333766,10 +333803,10 @@ function cleanupStaleScreenshots(options = {}) {
333766
333803
  const owned = ownedPattern.exec(name50);
333767
333804
  const isLegacy = !owned && legacyPattern.test(name50);
333768
333805
  if (!owned && !isLegacy) continue;
333769
- const filePath = path9.join(directory, name50);
333806
+ const filePath = path10.join(directory, name50);
333770
333807
  let stats;
333771
333808
  try {
333772
- stats = fs8.lstatSync(filePath);
333809
+ stats = fs9.lstatSync(filePath);
333773
333810
  if (!stats.isFile() || stats.isSymbolicLink()) continue;
333774
333811
  } catch {
333775
333812
  continue;
@@ -333793,7 +333830,7 @@ function cleanupStaleScreenshots(options = {}) {
333793
333830
  }
333794
333831
  if (!shouldRemove) continue;
333795
333832
  try {
333796
- fs8.unlinkSync(filePath);
333833
+ fs9.unlinkSync(filePath);
333797
333834
  removed += 1;
333798
333835
  } catch {
333799
333836
  }
@@ -333816,7 +333853,7 @@ function captureBounds(maxWidth, maxHeight) {
333816
333853
  }
333817
333854
  function removeEphemeralScreenshot(outPath) {
333818
333855
  try {
333819
- fs8.unlinkSync(outPath);
333856
+ fs9.unlinkSync(outPath);
333820
333857
  } catch {
333821
333858
  }
333822
333859
  }
@@ -333892,7 +333929,7 @@ async function startTakeoverOverlay(durationMs = 0, input2 = {}) {
333892
333929
  const width = 2;
333893
333930
  const speedSeconds = 3;
333894
333931
  const ownerPid = Math.max(0, Math.floor(Number(input2.ownerPid ?? process.pid) || 0));
333895
- const scriptPath = path9.join(tempScreenshotDir(), `takeover-overlay-${timestampName()}-${crypto6.randomBytes(4).toString("hex")}.ps1`);
333932
+ const scriptPath = path10.join(tempScreenshotDir(), `takeover-overlay-${timestampName()}-${crypto6.randomBytes(4).toString("hex")}.ps1`);
333896
333933
  const script = [
333897
333934
  "Add-Type -AssemblyName System.Windows.Forms",
333898
333935
  "Add-Type -AssemblyName System.Drawing",
@@ -334031,7 +334068,7 @@ async function startTakeoverOverlay(durationMs = 0, input2 = {}) {
334031
334068
  "[System.Windows.Forms.Application]::Run()",
334032
334069
  "try { Remove-Item -LiteralPath $PSCommandPath -Force -ErrorAction SilentlyContinue } catch {}"
334033
334070
  ].filter(Boolean).join("\r\n");
334034
- fs8.writeFileSync(scriptPath, `\uFEFF${script}`, "utf8");
334071
+ fs9.writeFileSync(scriptPath, `\uFEFF${script}`, "utf8");
334035
334072
  const createCommand = [
334036
334073
  `$cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File ' + ${psQuote(`"${scriptPath}"`)}`,
334037
334074
  `$startup = ([wmiclass]'Win32_ProcessStartup').CreateInstance()`,
@@ -334044,7 +334081,7 @@ async function startTakeoverOverlay(durationMs = 0, input2 = {}) {
334044
334081
  const pid = Number(String(result.output || "").trim().split(/\r?\n/).pop() || 0);
334045
334082
  if (!Number.isFinite(pid) || pid <= 0 || !result.ok) {
334046
334083
  try {
334047
- fs8.unlinkSync(scriptPath);
334084
+ fs9.unlinkSync(scriptPath);
334048
334085
  } catch {
334049
334086
  }
334050
334087
  return { ok: false, action: "takeover_start", error: result.output || "Overlay failed to start." };
@@ -334071,7 +334108,7 @@ function parseJsonArray(text) {
334071
334108
  return [];
334072
334109
  }
334073
334110
  function observationKey(workspacePath, ownerId) {
334074
- return `${path9.resolve(workspacePath || process.cwd()).toLowerCase()}::${String(ownerId || "direct")}`;
334111
+ return `${path10.resolve(workspacePath || process.cwd()).toLowerCase()}::${String(ownerId || "direct")}`;
334075
334112
  }
334076
334113
  function sceneGeneration(apps, elements) {
334077
334114
  const seed = [
@@ -334287,7 +334324,7 @@ async function cropScreenshot(workspacePath, ownerId, allowEphemeralVisionImage,
334287
334324
  ...parsed
334288
334325
  };
334289
334326
  if (includeRawUi) payload.perception.elements = elements;
334290
- const imageAvailable = parsed.image_available === true && fs8.existsSync(outPath);
334327
+ const imageAvailable = parsed.image_available === true && fs9.existsSync(outPath);
334291
334328
  if (allowEphemeralVisionImage && imageAvailable) {
334292
334329
  payload.vision_image_path = outPath;
334293
334330
  retainedForVision = true;
@@ -334550,7 +334587,7 @@ async function screenshot(workspacePath, ownerId, allowEphemeralVisionImage, inc
334550
334587
  ...parsed
334551
334588
  };
334552
334589
  if (includeRawUi) payload.perception.elements = ui.elements;
334553
- const imageAvailable = parsed.image_available === true && fs8.existsSync(outPath);
334590
+ const imageAvailable = parsed.image_available === true && fs9.existsSync(outPath);
334554
334591
  if (allowEphemeralVisionImage && imageAvailable) {
334555
334592
  payload.vision_image_path = outPath;
334556
334593
  retainedForVision = true;
@@ -334874,13 +334911,13 @@ async function runComputerUse(options) {
334874
334911
  }
334875
334912
 
334876
334913
  // src/core/ssh.ts
334877
- var fs10 = __toESM(require("fs"));
334878
- var path11 = __toESM(require("path"));
334914
+ var fs11 = __toESM(require("fs"));
334915
+ var path12 = __toESM(require("path"));
334879
334916
 
334880
334917
  // src/core/asyncProcess.ts
334881
334918
  var import_child_process4 = require("child_process");
334882
- var fs9 = __toESM(require("fs/promises"));
334883
- var path10 = __toESM(require("path"));
334919
+ var fs10 = __toESM(require("fs/promises"));
334920
+ var path11 = __toESM(require("path"));
334884
334921
  var STOP_SETTLEMENT_WATCHDOG_MS = 500;
334885
334922
  function signalMessage(signal) {
334886
334923
  const reason = signal?.reason;
@@ -334890,7 +334927,7 @@ function signalMessage(signal) {
334890
334927
  }
334891
334928
  function trustedWindowsTaskkillPath() {
334892
334929
  const windowsRoot = String(process.env.SystemRoot || process.env.WINDIR || "C:\\Windows");
334893
- return path10.join(windowsRoot, "System32", "taskkill.exe");
334930
+ return path11.join(windowsRoot, "System32", "taskkill.exe");
334894
334931
  }
334895
334932
  function stopProcessTree(child) {
334896
334933
  const pid = child.pid;
@@ -335059,7 +335096,7 @@ async function runAsyncWindowsBatch(command, args, options = {}) {
335059
335096
  }
335060
335097
  async function accessible(filePath) {
335061
335098
  try {
335062
- await fs9.access(filePath);
335099
+ await fs10.access(filePath);
335063
335100
  return true;
335064
335101
  } catch {
335065
335102
  return false;
@@ -335068,14 +335105,14 @@ async function accessible(filePath) {
335068
335105
  async function resolveWindowsLauncher(command) {
335069
335106
  const clean = String(command || "").trim();
335070
335107
  if (!clean) return "";
335071
- if (path10.isAbsolute(clean) || /[\\/]/.test(clean)) {
335072
- const absolute = path10.resolve(clean);
335108
+ if (path11.isAbsolute(clean) || /[\\/]/.test(clean)) {
335109
+ const absolute = path11.resolve(clean);
335073
335110
  return await accessible(absolute) ? absolute : "";
335074
335111
  }
335075
- for (const entry of String(process.env.PATH || "").split(path10.delimiter)) {
335112
+ for (const entry of String(process.env.PATH || "").split(path11.delimiter)) {
335076
335113
  const directory = entry.trim().replace(/^"|"$/g, "");
335077
335114
  if (!directory) continue;
335078
- const candidate = path10.join(directory, clean);
335115
+ const candidate = path11.join(directory, clean);
335079
335116
  if (await accessible(candidate)) return candidate;
335080
335117
  }
335081
335118
  return "";
@@ -335083,11 +335120,11 @@ async function resolveWindowsLauncher(command) {
335083
335120
  async function resolveNpmBatchTarget(batchPath) {
335084
335121
  let source = "";
335085
335122
  try {
335086
- source = await fs9.readFile(batchPath, "utf8");
335123
+ source = await fs10.readFile(batchPath, "utf8");
335087
335124
  } catch {
335088
335125
  return null;
335089
335126
  }
335090
- const directory = path10.dirname(batchPath);
335127
+ const directory = path11.dirname(batchPath);
335091
335128
  let relativeScript = "";
335092
335129
  const direct = /(?:%~dp0|%dp0%)\\?([^"\r\n]+)"\s+%\*/i.exec(source);
335093
335130
  if (direct) relativeScript = direct[1];
@@ -335101,10 +335138,10 @@ async function resolveNpmBatchTarget(batchPath) {
335101
335138
  }
335102
335139
  }
335103
335140
  if (!relativeScript) return null;
335104
- const scriptPath = path10.resolve(directory, relativeScript.replace(/\\/g, path10.sep));
335105
- const directoryPrefix = `${path10.resolve(directory).toLowerCase()}${path10.sep}`;
335141
+ const scriptPath = path11.resolve(directory, relativeScript.replace(/\\/g, path11.sep));
335142
+ const directoryPrefix = `${path11.resolve(directory).toLowerCase()}${path11.sep}`;
335106
335143
  if (!scriptPath.toLowerCase().startsWith(directoryPrefix) || !await accessible(scriptPath)) return null;
335107
- const siblingNode = path10.join(directory, "node.exe");
335144
+ const siblingNode = path11.join(directory, "node.exe");
335108
335145
  const nodePath = await accessible(siblingNode) ? siblingNode : await resolveWindowsLauncher("node.exe") || await resolveWindowsLauncher("node");
335109
335146
  return nodePath ? { nodePath, scriptPath } : null;
335110
335147
  }
@@ -335147,19 +335184,19 @@ var SshManager = class {
335147
335184
  rootPath;
335148
335185
  runner;
335149
335186
  storePath() {
335150
- return path11.join(this.rootPath, "Work", "SSH.json");
335187
+ return path12.join(this.rootPath, "Work", "SSH.json");
335151
335188
  }
335152
335189
  ensureStore() {
335153
335190
  try {
335154
- fs10.mkdirSync(path11.join(this.rootPath, "Work"), { recursive: true });
335155
- if (!fs10.existsSync(this.storePath())) fs10.writeFileSync(this.storePath(), "[]", "utf-8");
335191
+ fs11.mkdirSync(path12.join(this.rootPath, "Work"), { recursive: true });
335192
+ if (!fs11.existsSync(this.storePath())) fs11.writeFileSync(this.storePath(), "[]", "utf-8");
335156
335193
  } catch {
335157
335194
  }
335158
335195
  }
335159
335196
  readRaw() {
335160
335197
  this.ensureStore();
335161
335198
  try {
335162
- const parsed = JSON.parse(fs10.readFileSync(this.storePath(), "utf-8").replace(/^\uFEFF/, ""));
335199
+ const parsed = JSON.parse(fs11.readFileSync(this.storePath(), "utf-8").replace(/^\uFEFF/, ""));
335163
335200
  if (!Array.isArray(parsed)) return [];
335164
335201
  return parsed.map((item) => this.normalize(item)).filter((item) => !!item);
335165
335202
  } catch {
@@ -335168,7 +335205,7 @@ var SshManager = class {
335168
335205
  }
335169
335206
  writeRaw(items) {
335170
335207
  this.ensureStore();
335171
- fs10.writeFileSync(this.storePath(), JSON.stringify(items, null, 2), "utf-8");
335208
+ fs11.writeFileSync(this.storePath(), JSON.stringify(items, null, 2), "utf-8");
335172
335209
  }
335173
335210
  normalize(raw) {
335174
335211
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
@@ -335348,8 +335385,8 @@ var SshManager = class {
335348
335385
  };
335349
335386
 
335350
335387
  // src/core/workspace.ts
335351
- var fs11 = __toESM(require("fs"));
335352
- var path12 = __toESM(require("path"));
335388
+ var fs12 = __toESM(require("fs"));
335389
+ var path13 = __toESM(require("path"));
335353
335390
  var crypto7 = __toESM(require("crypto"));
335354
335391
  function lastEmbeddedWindowsPath(input2) {
335355
335392
  const matcher = /[A-Za-z]:[\\/]/g;
@@ -335368,22 +335405,22 @@ function normalizeHostWorkspacePath(input2, platform = process.platform) {
335368
335405
  const raw = String(input2 || "").trim();
335369
335406
  const embeddedWindowsPath = lastEmbeddedWindowsPath(raw);
335370
335407
  if (platform === "win32") {
335371
- if (embeddedWindowsPath) return path12.win32.normalize(embeddedWindowsPath.replace(/\//g, "\\"));
335408
+ if (embeddedWindowsPath) return path13.win32.normalize(embeddedWindowsPath.replace(/\//g, "\\"));
335372
335409
  const wsl = /^\/mnt\/([a-zA-Z])(?:\/(.*))?$/.exec(raw.replace(/\\/g, "/"));
335373
- if (wsl) return path12.win32.normalize(`${wsl[1].toUpperCase()}:\\${String(wsl[2] || "").replace(/\//g, "\\")}`);
335374
- return path12.win32.resolve(raw || ".");
335410
+ if (wsl) return path13.win32.normalize(`${wsl[1].toUpperCase()}:\\${String(wsl[2] || "").replace(/\//g, "\\")}`);
335411
+ return path13.win32.resolve(raw || ".");
335375
335412
  }
335376
335413
  if (platform === "linux" && embeddedWindowsPath) {
335377
335414
  const drive = embeddedWindowsPath[0].toLowerCase();
335378
335415
  const rest = embeddedWindowsPath.slice(3).replace(/\\/g, "/").replace(/^\/+/, "");
335379
- return path12.posix.resolve(`/mnt/${drive}/${rest}`);
335416
+ return path13.posix.resolve(`/mnt/${drive}/${rest}`);
335380
335417
  }
335381
- return path12.posix.resolve(raw || ".");
335418
+ return path13.posix.resolve(raw || ".");
335382
335419
  }
335383
335420
  function isPathInside(parent, child) {
335384
335421
  try {
335385
- const relative6 = path12.relative(path12.resolve(parent), path12.resolve(child));
335386
- return relative6 === "" || !!relative6 && !relative6.startsWith("..") && !path12.isAbsolute(relative6);
335422
+ const relative6 = path13.relative(path13.resolve(parent), path13.resolve(child));
335423
+ return relative6 === "" || !!relative6 && !relative6.startsWith("..") && !path13.isAbsolute(relative6);
335387
335424
  } catch {
335388
335425
  return false;
335389
335426
  }
@@ -335391,7 +335428,7 @@ function isPathInside(parent, child) {
335391
335428
  function isProtectedInstallWorkspacePath(candidate) {
335392
335429
  const value = String(candidate || "").trim();
335393
335430
  if (!value) return false;
335394
- const roots = [path12.dirname(process.execPath)];
335431
+ const roots = [path13.dirname(process.execPath)];
335395
335432
  if (process.platform === "win32") {
335396
335433
  roots.push(
335397
335434
  process.env.ProgramFiles || "",
@@ -335399,7 +335436,7 @@ function isProtectedInstallWorkspacePath(candidate) {
335399
335436
  process.env.ProgramW6432 || ""
335400
335437
  );
335401
335438
  }
335402
- const resolved = path12.resolve(value);
335439
+ const resolved = path13.resolve(value);
335403
335440
  return roots.filter(Boolean).some((root2) => isPathInside(root2, resolved));
335404
335441
  }
335405
335442
  var WorkspaceManager = class {
@@ -335409,16 +335446,16 @@ var WorkspaceManager = class {
335409
335446
  this.detached = options.detached === true;
335410
335447
  this.pcHash = this.loadPcHash();
335411
335448
  if (this.detached) return;
335412
- const workDir = path12.join(rootPath, "Work");
335449
+ const workDir = path13.join(rootPath, "Work");
335413
335450
  try {
335414
- fs11.mkdirSync(workDir, { recursive: true });
335451
+ fs12.mkdirSync(workDir, { recursive: true });
335415
335452
  } catch {
335416
335453
  }
335417
335454
  for (const fn of ["Local.json", "External.json"]) {
335418
- const p = path12.join(workDir, fn);
335419
- if (!fs11.existsSync(p)) {
335455
+ const p = path13.join(workDir, fn);
335456
+ if (!fs12.existsSync(p)) {
335420
335457
  try {
335421
- fs11.writeFileSync(p, "[]", "utf-8");
335458
+ fs12.writeFileSync(p, "[]", "utf-8");
335422
335459
  } catch {
335423
335460
  }
335424
335461
  }
@@ -335439,7 +335476,7 @@ var WorkspaceManager = class {
335439
335476
  detached;
335440
335477
  loadPcHash() {
335441
335478
  try {
335442
- const h2 = fs11.readFileSync(path12.join(this.rootPath, "PC_Hash.config"), "utf-8");
335479
+ const h2 = fs12.readFileSync(path13.join(this.rootPath, "PC_Hash.config"), "utf-8");
335443
335480
  return h2.trim();
335444
335481
  } catch {
335445
335482
  return "";
@@ -335454,19 +335491,19 @@ var WorkspaceManager = class {
335454
335491
  if (this.external.length !== before) this.saveExternal();
335455
335492
  }
335456
335493
  scan() {
335457
- const w = path12.join(this.rootPath, "Work");
335458
- if (!fs11.existsSync(w)) return;
335494
+ const w = path13.join(this.rootPath, "Work");
335495
+ if (!fs12.existsSync(w)) return;
335459
335496
  let internalChanged = false;
335460
335497
  let externalChanged = false;
335461
335498
  try {
335462
- const local = JSON.parse(fs11.readFileSync(path12.join(w, "Local.json"), "utf-8"));
335499
+ const local = JSON.parse(fs12.readFileSync(path13.join(w, "Local.json"), "utf-8"));
335463
335500
  this.internal = Array.isArray(local) ? local.map((item) => this.normalizeInternalWorkspace(item, (changed) => {
335464
335501
  internalChanged = internalChanged || changed;
335465
335502
  })) : [];
335466
335503
  } catch {
335467
335504
  }
335468
335505
  try {
335469
- const ext = JSON.parse(fs11.readFileSync(path12.join(w, "External.json"), "utf-8"));
335506
+ const ext = JSON.parse(fs12.readFileSync(path13.join(w, "External.json"), "utf-8"));
335470
335507
  const normalized = Array.isArray(ext) ? ext.map((item) => this.normalizeExternalWorkspace(item, (changed) => {
335471
335508
  externalChanged = externalChanged || changed;
335472
335509
  })) : [];
@@ -335477,13 +335514,13 @@ var WorkspaceManager = class {
335477
335514
  });
335478
335515
  } catch {
335479
335516
  }
335480
- for (const entry of fs11.readdirSync(w, { withFileTypes: true })) {
335517
+ for (const entry of fs12.readdirSync(w, { withFileTypes: true })) {
335481
335518
  if (entry.isDirectory() && !["Local.json", "External.json", ".ssh"].includes(entry.name)) {
335482
335519
  if (!this.internal.find((wi) => wi.name === entry.name)) {
335483
335520
  this.internal.push({
335484
- id: this.stableWorkspaceId("local", path12.join(w, entry.name)),
335521
+ id: this.stableWorkspaceId("local", path13.join(w, entry.name)),
335485
335522
  name: entry.name,
335486
- path: path12.join(w, entry.name),
335523
+ path: path13.join(w, entry.name),
335487
335524
  isInternal: true,
335488
335525
  hostBinding: "",
335489
335526
  icon: entry.name.charAt(0).toUpperCase()
@@ -335496,9 +335533,9 @@ var WorkspaceManager = class {
335496
335533
  if (externalChanged) this.saveExternal();
335497
335534
  }
335498
335535
  normalizeInternalWorkspace(input2, markChanged) {
335499
- const rawName = String(input2?.name || path12.basename(String(input2?.path || "")) || "").trim();
335536
+ const rawName = String(input2?.name || path13.basename(String(input2?.path || "")) || "").trim();
335500
335537
  const name50 = rawName || (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace("T", "_").slice(0, 15);
335501
- const expectedPath = path12.join(this.rootPath, "Work", name50);
335538
+ const expectedPath = path13.join(this.rootPath, "Work", name50);
335502
335539
  const id = this.stableWorkspaceId("local", expectedPath);
335503
335540
  if (normalizeHostWorkspacePath(String(input2?.path || "")) !== normalizeHostWorkspacePath(expectedPath) || input2?.isInternal !== true || input2?.id !== id) markChanged(true);
335504
335541
  return {
@@ -335519,11 +335556,11 @@ var WorkspaceManager = class {
335519
335556
  return {
335520
335557
  ...input2,
335521
335558
  id,
335522
- name: String(input2?.name || path12.basename(workspacePath) || id),
335559
+ name: String(input2?.name || path13.basename(workspacePath) || id),
335523
335560
  path: workspacePath,
335524
335561
  isInternal: false,
335525
335562
  hostBinding: String(input2?.hostBinding || ""),
335526
- icon: String(input2?.icon || path12.basename(workspacePath).charAt(0).toUpperCase()),
335563
+ icon: String(input2?.icon || path13.basename(workspacePath).charAt(0).toUpperCase()),
335527
335564
  kind
335528
335565
  };
335529
335566
  }
@@ -335544,11 +335581,11 @@ var WorkspaceManager = class {
335544
335581
  const resolved = normalizeHostWorkspacePath(target);
335545
335582
  let real = resolved;
335546
335583
  try {
335547
- real = fs11.existsSync(resolved) ? fs11.realpathSync.native(resolved) : resolved;
335584
+ real = fs12.existsSync(resolved) ? fs12.realpathSync.native(resolved) : resolved;
335548
335585
  } catch {
335549
335586
  real = resolved;
335550
335587
  }
335551
- const normalized = path12.normalize(real).replace(/[\\/]+$/, "");
335588
+ const normalized = path13.normalize(real).replace(/[\\/]+$/, "");
335552
335589
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
335553
335590
  }
335554
335591
  stableWorkspaceId(kind, workspacePath) {
@@ -335574,8 +335611,8 @@ var WorkspaceManager = class {
335574
335611
  isInsideRoot(target) {
335575
335612
  const root2 = this.canonicalWorkspacePath(this.rootPath);
335576
335613
  const candidate = this.canonicalWorkspacePath(target);
335577
- const rel = path12.relative(root2, candidate);
335578
- return rel === "" || !!rel && !rel.startsWith("..") && !path12.isAbsolute(rel);
335614
+ const rel = path13.relative(root2, candidate);
335615
+ return rel === "" || !!rel && !rel.startsWith("..") && !path13.isAbsolute(rel);
335579
335616
  }
335580
335617
  canonicalRemotePath(target) {
335581
335618
  let cleaned = String(target || "").trim().replace(/\\/g, "/").replace(/\/+$/g, "");
@@ -335604,13 +335641,13 @@ var WorkspaceManager = class {
335604
335641
  return deduped;
335605
335642
  }
335606
335643
  statePath() {
335607
- return path12.join(this.rootPath, "Work", "State.json");
335644
+ return path13.join(this.rootPath, "Work", "State.json");
335608
335645
  }
335609
335646
  readState() {
335610
335647
  const p = this.statePath();
335611
- if (!fs11.existsSync(p)) return {};
335648
+ if (!fs12.existsSync(p)) return {};
335612
335649
  try {
335613
- const raw = fs11.readFileSync(p, "utf-8").replace(/^\uFEFF/, "");
335650
+ const raw = fs12.readFileSync(p, "utf-8").replace(/^\uFEFF/, "");
335614
335651
  const parsed = JSON.parse(raw);
335615
335652
  if (parsed && typeof parsed === "object") return parsed;
335616
335653
  } catch {
@@ -335631,8 +335668,8 @@ var WorkspaceManager = class {
335631
335668
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
335632
335669
  };
335633
335670
  try {
335634
- fs11.mkdirSync(path12.dirname(p), { recursive: true });
335635
- fs11.writeFileSync(p, JSON.stringify(state, null, 2), "utf-8");
335671
+ fs12.mkdirSync(path13.dirname(p), { recursive: true });
335672
+ fs12.writeFileSync(p, JSON.stringify(state, null, 2), "utf-8");
335636
335673
  } catch {
335637
335674
  }
335638
335675
  }
@@ -335691,17 +335728,17 @@ var WorkspaceManager = class {
335691
335728
  }
335692
335729
  saveInternal() {
335693
335730
  if (this.detached) return;
335694
- const p = path12.join(this.rootPath, "Work", "Local.json");
335731
+ const p = path13.join(this.rootPath, "Work", "Local.json");
335695
335732
  this.internal = this.dedupeByPath(this.internal);
335696
335733
  this.sortWorkspaces();
335697
- fs11.writeFileSync(p, JSON.stringify(this.internal, null, 2), "utf-8");
335734
+ fs12.writeFileSync(p, JSON.stringify(this.internal, null, 2), "utf-8");
335698
335735
  }
335699
335736
  saveExternal() {
335700
335737
  if (this.detached) return;
335701
- const p = path12.join(this.rootPath, "Work", "External.json");
335738
+ const p = path13.join(this.rootPath, "Work", "External.json");
335702
335739
  this.external = this.dedupeByPath(this.external);
335703
335740
  this.sortWorkspaces();
335704
- fs11.writeFileSync(p, JSON.stringify(this.external, null, 2), "utf-8");
335741
+ fs12.writeFileSync(p, JSON.stringify(this.external, null, 2), "utf-8");
335705
335742
  }
335706
335743
  sleepSync(ms) {
335707
335744
  if (ms <= 0) return;
@@ -335709,48 +335746,48 @@ var WorkspaceManager = class {
335709
335746
  Atomics.wait(new Int32Array(buffer), 0, 0, ms);
335710
335747
  }
335711
335748
  isInternalWorkspacePath(target) {
335712
- const workRoot = path12.resolve(this.rootPath, "Work");
335713
- const resolved = path12.resolve(target);
335714
- const rel = path12.relative(workRoot, resolved);
335715
- return !!rel && !rel.startsWith("..") && !path12.isAbsolute(rel);
335749
+ const workRoot = path13.resolve(this.rootPath, "Work");
335750
+ const resolved = path13.resolve(target);
335751
+ const rel = path13.relative(workRoot, resolved);
335752
+ return !!rel && !rel.startsWith("..") && !path13.isAbsolute(rel);
335716
335753
  }
335717
335754
  clearReadOnlyRecursive(target) {
335718
- if (!fs11.existsSync(target)) return;
335719
- const stat = fs11.lstatSync(target);
335755
+ if (!fs12.existsSync(target)) return;
335756
+ const stat = fs12.lstatSync(target);
335720
335757
  try {
335721
- fs11.chmodSync(target, stat.mode | 448);
335758
+ fs12.chmodSync(target, stat.mode | 448);
335722
335759
  } catch {
335723
335760
  }
335724
335761
  if (!stat.isDirectory()) return;
335725
- for (const entry of fs11.readdirSync(target)) {
335726
- this.clearReadOnlyRecursive(path12.join(target, entry));
335762
+ for (const entry of fs12.readdirSync(target)) {
335763
+ this.clearReadOnlyRecursive(path13.join(target, entry));
335727
335764
  }
335728
335765
  }
335729
335766
  removeInternalDirectory(target) {
335730
- const resolved = path12.resolve(target);
335767
+ const resolved = path13.resolve(target);
335731
335768
  if (!this.isInternalWorkspacePath(resolved)) return false;
335732
- if (!fs11.existsSync(resolved)) return true;
335769
+ if (!fs12.existsSync(resolved)) return true;
335733
335770
  const delays = [0, 50, 100, 200, 400, 800, 1200];
335734
335771
  for (const delay of delays) {
335735
335772
  this.sleepSync(delay);
335736
335773
  try {
335737
- fs11.rmSync(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
335774
+ fs12.rmSync(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
335738
335775
  } catch {
335739
335776
  }
335740
- if (!fs11.existsSync(resolved)) return true;
335777
+ if (!fs12.existsSync(resolved)) return true;
335741
335778
  try {
335742
335779
  this.clearReadOnlyRecursive(resolved);
335743
- fs11.rmSync(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
335780
+ fs12.rmSync(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
335744
335781
  } catch {
335745
335782
  }
335746
- if (!fs11.existsSync(resolved)) return true;
335783
+ if (!fs12.existsSync(resolved)) return true;
335747
335784
  }
335748
335785
  return false;
335749
335786
  }
335750
335787
  createInternal(name50) {
335751
335788
  const n3 = name50 || (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace("T", "_").slice(0, 15);
335752
- const d3 = path12.join(this.rootPath, "Work", n3);
335753
- fs11.mkdirSync(d3, { recursive: true });
335789
+ const d3 = path13.join(this.rootPath, "Work", n3);
335790
+ fs12.mkdirSync(d3, { recursive: true });
335754
335791
  const existing = this.findWorkspaceByPath(d3);
335755
335792
  if (existing) {
335756
335793
  this.current = existing;
@@ -335772,15 +335809,15 @@ var WorkspaceManager = class {
335772
335809
  return ws;
335773
335810
  }
335774
335811
  addExternal(p) {
335775
- const resolved = path12.resolve(p);
335776
- if (!fs11.existsSync(resolved) || this.isInsideRoot(resolved)) return null;
335812
+ const resolved = path13.resolve(p);
335813
+ if (!fs12.existsSync(resolved) || this.isInsideRoot(resolved)) return null;
335777
335814
  const existing = this.findWorkspaceByPath(resolved);
335778
335815
  if (existing) {
335779
335816
  this.current = existing;
335780
335817
  this.saveState();
335781
335818
  return existing;
335782
335819
  }
335783
- const name50 = path12.basename(resolved);
335820
+ const name50 = path13.basename(resolved);
335784
335821
  const ws = {
335785
335822
  id: this.stableWorkspaceId("local", resolved),
335786
335823
  name: name50,
@@ -335798,10 +335835,10 @@ var WorkspaceManager = class {
335798
335835
  addSshExternal(input2) {
335799
335836
  if (!input2.sshConnectionId || !input2.remotePath || !input2.remotePcHash) return null;
335800
335837
  const remotePath = this.canonicalRemotePath(input2.remotePath);
335801
- const baseName = (input2.name || path12.basename(remotePath.replace(/[\\/]+$/, "")) || input2.sshConnectionId || "ssh-workspace").trim();
335838
+ const baseName = (input2.name || path13.basename(remotePath.replace(/[\\/]+$/, "")) || input2.sshConnectionId || "ssh-workspace").trim();
335802
335839
  const safeName = baseName.replace(/[<>:"/\\|?*\x00-\x1F]/g, "-").replace(/\s+/g, " ").trim() || "ssh-workspace";
335803
- const shadowRoot = input2.localPath ? path12.resolve(input2.localPath) : path12.join(this.rootPath, "Work", ".ssh", `${input2.sshConnectionId}-${crypto7.createHash("sha256").update(remotePath).digest("hex").slice(0, 16)}`);
335804
- fs11.mkdirSync(shadowRoot, { recursive: true });
335840
+ const shadowRoot = input2.localPath ? path13.resolve(input2.localPath) : path13.join(this.rootPath, "Work", ".ssh", `${input2.sshConnectionId}-${crypto7.createHash("sha256").update(remotePath).digest("hex").slice(0, 16)}`);
335841
+ fs12.mkdirSync(shadowRoot, { recursive: true });
335805
335842
  const existing = this.findSshWorkspaceByRemotePath(input2.sshConnectionId, remotePath);
335806
335843
  const ws = {
335807
335844
  ...existing || {},
@@ -335883,7 +335920,7 @@ var WorkspaceManager = class {
335883
335920
  currentAgentPrompt() {
335884
335921
  if (!this.current) return null;
335885
335922
  try {
335886
- return fs11.readFileSync(path12.join(this.current.path, "agent.md"), "utf-8");
335923
+ return fs12.readFileSync(path13.join(this.current.path, "agent.md"), "utf-8");
335887
335924
  } catch {
335888
335925
  return null;
335889
335926
  }
@@ -335892,8 +335929,8 @@ var WorkspaceManager = class {
335892
335929
  const perm = this.config.getStr("workspace", "access_permission");
335893
335930
  if (perm === "full_access") return true;
335894
335931
  if (!this.current) return perm !== "no_outside_access";
335895
- const rel = path12.relative(path12.resolve(this.current.path), path12.resolve(target));
335896
- const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !path12.isAbsolute(rel);
335932
+ const rel = path13.relative(path13.resolve(this.current.path), path13.resolve(target));
335933
+ const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !path13.isAbsolute(rel);
335897
335934
  if (inside2) return true;
335898
335935
  return perm !== "no_outside_access";
335899
335936
  }
@@ -335976,6 +336013,7 @@ var PLAN_COMPUTER_USE_ACTIONS = ["observe", "app_list", "app_observe"];
335976
336013
  var PLAN_BROWSER_USE_ACTIONS = ["observe", "navigate", "wait", "extract"];
335977
336014
  var PLAN_COMPUTER_USE_ACTION_SET = new Set(PLAN_COMPUTER_USE_ACTIONS);
335978
336015
  var PLAN_BROWSER_USE_ACTION_SET = new Set(PLAN_BROWSER_USE_ACTIONS);
336016
+ var CHAT_WEB_TOOLS = /* @__PURE__ */ new Set(["web_search", "web_fetch"]);
335979
336017
  var CONCURRENCY_SAFE_TOOLS = /* @__PURE__ */ new Set([
335980
336018
  "pwd",
335981
336019
  "read",
@@ -336009,6 +336047,13 @@ function evaluateToolPolicy(request) {
336009
336047
  const availability = toolAvailability(name50);
336010
336048
  const base2 = { availability, settingsVisible: availability === "configurable" };
336011
336049
  if (!name50) return { ...base2, allowed: false, reason: "[permission] Tool name is required." };
336050
+ if (request.mode === "chat" && !CHAT_WEB_TOOLS.has(name50)) {
336051
+ return {
336052
+ ...base2,
336053
+ allowed: false,
336054
+ 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}`
336055
+ };
336056
+ }
336012
336057
  if (request.mode === "plan") {
336013
336058
  if (name50 === "computer_use") {
336014
336059
  const action = String(request.args?.action || "").trim();
@@ -336050,6 +336095,13 @@ function planModePolicyPrompt() {
336050
336095
  "Runtime policy rejects stale or hidden mutating tool calls even if a prompt asks for them."
336051
336096
  ].join(" ");
336052
336097
  }
336098
+ function chatModePolicyPrompt() {
336099
+ return [
336100
+ "Chat mode is a narrow web-evidence mode.",
336101
+ "Only web_search and web_fetch are available; every workspace, host, application, memory, task, browser-control, and write capability is denied at runtime.",
336102
+ "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."
336103
+ ].join(" ");
336104
+ }
336053
336105
  var DELETE_VERB_SOURCE = "(?:remove-item|rmdir|unlink|erase|del|rm|rd|ri)";
336054
336106
  var DELETE_VERB_BOUNDARY = new RegExp(`(?:^|[\\s;&|()\\n])${DELETE_VERB_SOURCE}(?:\\s|$)`, "i");
336055
336107
  function hasDeletionVerb(text) {
@@ -336327,7 +336379,7 @@ function requestUtilityHostTool(tool, args, context, timeoutMs = 12e4, signal) {
336327
336379
  }
336328
336380
 
336329
336381
  // src/core/nativeBash.ts
336330
- var path13 = __toESM(require("path"));
336382
+ var path14 = __toESM(require("path"));
336331
336383
  var import_module = require("module");
336332
336384
  var MAX_OUTPUT_BYTES = 1024 * 1024;
336333
336385
  var DEFAULT_TIMEOUT_MS = 3e4;
@@ -336415,11 +336467,11 @@ function normalizedTimeout(timeoutMs) {
336415
336467
  }
336416
336468
  function virtualCwd(workspaceRoot, requestedCwd) {
336417
336469
  if (!requestedCwd) return "/";
336418
- const root2 = path13.resolve(workspaceRoot);
336419
- const cwd = path13.resolve(requestedCwd);
336420
- const relative6 = path13.relative(root2, cwd);
336421
- if (relative6.startsWith("..") || path13.isAbsolute(relative6)) return "/";
336422
- return relative6 ? `/${relative6.split(path13.sep).join("/")}` : "/";
336470
+ const root2 = path14.resolve(workspaceRoot);
336471
+ const cwd = path14.resolve(requestedCwd);
336472
+ const relative6 = path14.relative(root2, cwd);
336473
+ if (relative6.startsWith("..") || path14.isAbsolute(relative6)) return "/";
336474
+ return relative6 ? `/${relative6.split(path14.sep).join("/")}` : "/";
336423
336475
  }
336424
336476
  function combineAbortSignals(signal, timeoutMs) {
336425
336477
  const controller = new AbortController();
@@ -336445,7 +336497,7 @@ function createBash(workspaceRoot, timeoutMs) {
336445
336497
  const justBash = loadJustBash();
336446
336498
  if (!justBash) throw new Error("Native Bash runtime unavailable");
336447
336499
  const fs27 = new justBash.ReadWriteFs({
336448
- root: path13.resolve(workspaceRoot),
336500
+ root: path14.resolve(workspaceRoot),
336449
336501
  maxFileReadSize: MAX_OUTPUT_BYTES * 8,
336450
336502
  allowSymlinks: false
336451
336503
  });
@@ -336534,12 +336586,12 @@ async function executeWorkspaceBash(script, workspaceRoot, options = {}) {
336534
336586
  }
336535
336587
 
336536
336588
  // src/core/toolArgumentValidator.ts
336537
- var fs12 = require("fs");
336538
- var path14 = require("path");
336589
+ var fs13 = require("fs");
336590
+ var path15 = require("path");
336539
336591
  var typeBoxCompilerPath = [
336540
- path14.join(__dirname, "..", "typebox-compile.bundle.cjs"),
336541
- path14.join(__dirname, "typebox-compile.bundle.cjs")
336542
- ].find((candidate) => fs12.existsSync(candidate));
336592
+ path15.join(__dirname, "..", "typebox-compile.bundle.cjs"),
336593
+ path15.join(__dirname, "typebox-compile.bundle.cjs")
336594
+ ].find((candidate) => fs13.existsSync(candidate));
336543
336595
  if (!typeBoxCompilerPath) throw new Error("Bundled TypeBox compiler is missing from the Newmark runtime.");
336544
336596
  var { Compile } = require(typeBoxCompilerPath);
336545
336597
  function closeToolArgumentSchema(input2) {
@@ -336629,8 +336681,8 @@ function formatValidationErrors(name50, errors) {
336629
336681
  }
336630
336682
 
336631
336683
  // src/core/localOcr.ts
336632
- var fs13 = __toESM(require("fs"));
336633
- var path15 = __toESM(require("path"));
336684
+ var fs14 = __toESM(require("fs"));
336685
+ var path16 = __toESM(require("path"));
336634
336686
  var AGENT_REPAIR_PROMPT = [
336635
336687
  "The local OCR output is approximate Chinese/English fallback evidence.",
336636
336688
  "Repair likely OCR substitutions, spacing, and line breaks using the visible UI/PDF context and the user task.",
@@ -336663,12 +336715,12 @@ var LocalOcrEngine = class {
336663
336715
  return await this.recognize(dataUrlBuffer(dataUrl), signal, profile);
336664
336716
  }
336665
336717
  async recognizeFile(filePath, signal) {
336666
- const absolute = path15.resolve(filePath);
336667
- const extension = path15.extname(absolute).toLowerCase();
336718
+ const absolute = path16.resolve(filePath);
336719
+ const extension = path16.extname(absolute).toLowerCase();
336668
336720
  if (![".png", ".jpg", ".jpeg", ".bmp"].includes(extension)) {
336669
336721
  throw new Error("Local OCR only accepts PNG, JPEG, or BMP images.");
336670
336722
  }
336671
- const stat = fs13.statSync(absolute);
336723
+ const stat = fs14.statSync(absolute);
336672
336724
  if (!stat.isFile() || stat.size <= 0 || stat.size > 12 * 1024 * 1024) {
336673
336725
  throw new Error("Local OCR image must be a regular file no larger than 12 MB.");
336674
336726
  }
@@ -336722,7 +336774,7 @@ var LocalOcrEngine = class {
336722
336774
  const tesseract = require_src();
336723
336775
  const worker = await tesseract.createWorker("chi_sim+eng", tesseract.OEM.LSTM_ONLY, {
336724
336776
  langPath: tessdataPath,
336725
- cachePath: path15.join(this.rootPath, "cache", "ocr-runtime"),
336777
+ cachePath: path16.join(this.rootPath, "cache", "ocr-runtime"),
336726
336778
  cacheMethod: "none",
336727
336779
  gzip: true,
336728
336780
  logger: () => void 0
@@ -336730,14 +336782,14 @@ var LocalOcrEngine = class {
336730
336782
  return worker;
336731
336783
  }
336732
336784
  prepareLanguageCache() {
336733
- const target = path15.join(this.rootPath, "cache", "ocr-tessdata");
336734
- fs13.mkdirSync(target, { recursive: true });
336785
+ const target = path16.join(this.rootPath, "cache", "ocr-tessdata");
336786
+ fs14.mkdirSync(target, { recursive: true });
336735
336787
  for (const language of ["eng", "chi_sim"]) {
336736
- const destination = path15.join(target, `${language}.traineddata.gz`);
336737
- if (fs13.existsSync(destination) && fs13.statSync(destination).size > 0) continue;
336738
- const packageRoot = path15.dirname(require.resolve(`@tesseract.js-data/${language}/package.json`));
336739
- const source = path15.join(packageRoot, "4.0.0_best_int", `${language}.traineddata.gz`);
336740
- fs13.copyFileSync(source, destination);
336788
+ const destination = path16.join(target, `${language}.traineddata.gz`);
336789
+ if (fs14.existsSync(destination) && fs14.statSync(destination).size > 0) continue;
336790
+ const packageRoot = path16.dirname(require.resolve(`@tesseract.js-data/${language}/package.json`));
336791
+ const source = path16.join(packageRoot, "4.0.0_best_int", `${language}.traineddata.gz`);
336792
+ fs14.copyFileSync(source, destination);
336741
336793
  }
336742
336794
  return target;
336743
336795
  }
@@ -336876,8 +336928,8 @@ function normalizeCrossEnvPath(value, wsPath) {
336876
336928
  const posix3 = windowsDrivePathToPosix(raw);
336877
336929
  if (posix3) return posix3;
336878
336930
  }
336879
- if (path16.isAbsolute(raw)) return raw;
336880
- return path16.join(wsPath, raw);
336931
+ if (path17.isAbsolute(raw)) return raw;
336932
+ return path17.join(wsPath, raw);
336881
336933
  }
336882
336934
  function translateWindowsPathsForWslBash(script) {
336883
336935
  if (!process.env.NEWMARK_WSL_DISTRO) return script;
@@ -336891,7 +336943,7 @@ function translateWindowsPathsForWslBash(script) {
336891
336943
  function computerUseOwner(context, wsPath) {
336892
336944
  const conversationId = String(context.conversationId || "").trim();
336893
336945
  if (conversationId) return `conversation:${conversationId}`;
336894
- const resolved = path16.resolve(context.workspacePath || wsPath || process.cwd());
336946
+ const resolved = path17.resolve(context.workspacePath || wsPath || process.cwd());
336895
336947
  const workspaceHash = crypto8.createHash("sha256").update(resolved).digest("hex").slice(0, 12);
336896
336948
  return `direct:${workspaceHash}`;
336897
336949
  }
@@ -336973,7 +337025,7 @@ function computerUseSessionScope(context, wsPath, owner) {
336973
337025
  return {
336974
337026
  runtimeKey: browserUseScope(context, wsPath).runtimeKey,
336975
337027
  ownerLabel: owner,
336976
- workspacePath: path16.resolve(wsPath || process.cwd())
337028
+ workspacePath: path17.resolve(wsPath || process.cwd())
336977
337029
  };
336978
337030
  }
336979
337031
  function acquireComputerUseLock(action, owner, wsPath, context = {}, dryRun = false) {
@@ -337168,7 +337220,7 @@ var ToolExecutor = class {
337168
337220
  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" } }, []),
337169
337221
  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." } }, []),
337170
337222
  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." } }, []),
337171
- t3("linked_plan", "Read or update the current conversation linked Markdown plan. Update requires the current expected_revision.", { action: { type: "string", enum: ["get", "update"] }, markdown: { type: "string" }, expected_revision: { type: "number" } }, ["action"]),
337223
+ 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"]),
337172
337224
  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." } }, []),
337173
337225
  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." } }, []),
337174
337226
  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.", {
@@ -337198,11 +337250,11 @@ var ToolExecutor = class {
337198
337250
  t3("skill_download", "Download a skill", { name: { type: "string" }, source: { type: "string" } }, ["name", "source"]),
337199
337251
  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 } }, []),
337200
337252
  t3("flow_list", "List available Newmark Flow workflows from the Flow folder so the agent can choose one.", {}, []),
337201
- t3("flow_save", "Design or update a Newmark Flow workflow. Components must be an array of dialog/logic objects compatible with *.Flow.json.", { name: { type: "string" }, components: { type: "array" } }, ["name", "components"]),
337253
+ 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"]),
337202
337254
  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"]),
337203
337255
  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" } }, []),
337204
337256
  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"]),
337205
- t3("memory_lab_update", "ADD or UPDATE a Memory Lab component. Existing memory should include expectedUpdatedAt from the latest read/query so stale writes fail closed. Prior revisions are archived and the Policy decision is logged.", { name: { type: "string" }, description: { type: "string" }, tags: { type: "array", items: { type: "string" } }, tagPaths: { type: "array", items: { type: "array", items: { type: "string" } } }, content: { type: "string" }, kind: { type: "string", enum: ["file", "folder"] }, expectedUpdatedAt: { type: "string" }, reason: { type: "string" }, source: { type: "string" } }, ["name", "tags", "content"]),
337257
+ 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" } }, []),
337206
337258
  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" } }, []),
337207
337259
  t3("memory_lab_reindex", "Rebuild and organize Memory Lab index links. Routed through Agent runtime when invoked by the model.", {}, []),
337208
337260
  t3("automation_list", "List persisted Newmark automations so the agent can inspect scheduled work.", {}, []),
@@ -337524,13 +337576,13 @@ var ToolExecutor = class {
337524
337576
  }
337525
337577
  case "pdf_read": {
337526
337578
  const pdfPath = resolve16(g2("path"));
337527
- if (path16.extname(pdfPath).toLowerCase() !== ".pdf") return "[pdf_read error] path must end in .pdf.";
337528
- const stat = fs14.statSync(pdfPath);
337579
+ if (path17.extname(pdfPath).toLowerCase() !== ".pdf") return "[pdf_read error] path must end in .pdf.";
337580
+ const stat = fs15.statSync(pdfPath);
337529
337581
  if (!stat.isFile() || stat.size <= 0 || stat.size > 250 * 1024 * 1024) {
337530
337582
  return "[pdf_read error] PDF must be a regular file no larger than 250 MB.";
337531
337583
  }
337532
337584
  const maxChars = Math.max(500, Math.min(1e5, Number(args.max_chars || 5e4)));
337533
- const textLayer = extractPdfTextLayer(fs14.readFileSync(pdfPath)).slice(0, maxChars);
337585
+ const textLayer = extractPdfTextLayer(fs15.readFileSync(pdfPath)).slice(0, maxChars);
337534
337586
  const readableCount = (textLayer.match(/[A-Za-z0-9\u3400-\u9fff]/g) || []).length;
337535
337587
  if (readableCount >= 20) {
337536
337588
  return JSON.stringify({
@@ -337749,7 +337801,7 @@ var ToolExecutor = class {
337749
337801
  case "flow_list":
337750
337802
  return this.flowList();
337751
337803
  case "flow_save":
337752
- return this.flowSave(g2("name"), args.components);
337804
+ return this.flowSave(g2("name"), args);
337753
337805
  case "flow_run":
337754
337806
  return `[flow_run] Routed to Agent runtime: ${g2("name")}`;
337755
337807
  case "memory_lab_read":
@@ -337806,8 +337858,8 @@ var ToolExecutor = class {
337806
337858
  }
337807
337859
  }
337808
337860
  isInside(parent, child) {
337809
- const rel = path16.relative(path16.resolve(parent), path16.resolve(child));
337810
- return rel === "" || !!rel && !rel.startsWith("..") && !path16.isAbsolute(rel);
337861
+ const rel = path17.relative(path17.resolve(parent), path17.resolve(child));
337862
+ return rel === "" || !!rel && !rel.startsWith("..") && !path17.isAbsolute(rel);
337811
337863
  }
337812
337864
  hostSupportsTool(name50) {
337813
337865
  if (name50.startsWith("browser_") && !this.hostProfile.electronBrowser) return false;
@@ -337919,7 +337971,7 @@ var ToolExecutor = class {
337919
337971
  if (!token || /^https?:\/\//i.test(token) || token.startsWith("-")) continue;
337920
337972
  if (!this.looksLikePath(token)) continue;
337921
337973
  const withoutWildcard = token.replace(/[\\/][*?][^\\/]*$/g, "");
337922
- refs.push(path16.resolve(normalizeCrossEnvPath(withoutWildcard, wsPath)));
337974
+ refs.push(path17.resolve(normalizeCrossEnvPath(withoutWildcard, wsPath)));
337923
337975
  }
337924
337976
  return Array.from(new Set(refs));
337925
337977
  }
@@ -337970,7 +338022,7 @@ var ToolExecutor = class {
337970
338022
  }
337971
338023
  fread(p) {
337972
338024
  try {
337973
- const c3 = fs14.readFileSync(p, "utf-8");
338025
+ const c3 = fs15.readFileSync(p, "utf-8");
337974
338026
  return c3.length > 3e4 ? c3.slice(0, 3e4) + "...\n[truncated]" : c3;
337975
338027
  } catch (e3) {
337976
338028
  return `[read] ${e3}`;
@@ -337978,8 +338030,8 @@ var ToolExecutor = class {
337978
338030
  }
337979
338031
  fwrite(p, content) {
337980
338032
  try {
337981
- fs14.mkdirSync(path16.dirname(p), { recursive: true });
337982
- fs14.writeFileSync(p, content, "utf-8");
338033
+ fs15.mkdirSync(path17.dirname(p), { recursive: true });
338034
+ fs15.writeFileSync(p, content, "utf-8");
337983
338035
  return `[write] OK: ${p}`;
337984
338036
  } catch (e3) {
337985
338037
  return `[write] ${e3}`;
@@ -337987,10 +338039,10 @@ var ToolExecutor = class {
337987
338039
  }
337988
338040
  fedit(p, oldStr, newStr) {
337989
338041
  try {
337990
- const c3 = fs14.readFileSync(p, "utf-8");
338042
+ const c3 = fs15.readFileSync(p, "utf-8");
337991
338043
  if (!c3.includes(oldStr)) return `[edit] String not found in ${p}.`;
337992
338044
  const updated = c3.replace(oldStr, newStr);
337993
- fs14.writeFileSync(p, updated, "utf-8");
338045
+ fs15.writeFileSync(p, updated, "utf-8");
337994
338046
  return `[edit] OK: ${p}`;
337995
338047
  } catch (e3) {
337996
338048
  return `[edit] ${e3}`;
@@ -337999,12 +338051,12 @@ var ToolExecutor = class {
337999
338051
  fdelete(p) {
338000
338052
  try {
338001
338053
  if (/[*?]/.test(p)) return "[delete_file] Refused: wildcard paths are not allowed. Delete one file per call.";
338002
- const resolved = path16.resolve(p);
338003
- const stat = fs14.lstatSync(resolved);
338054
+ const resolved = path17.resolve(p);
338055
+ const stat = fs15.lstatSync(resolved);
338004
338056
  if (stat.isDirectory()) {
338005
338057
  return "[delete_file] Refused: deleting a directory is not allowed. Delete files one by one under Agent supervision.";
338006
338058
  }
338007
- fs14.unlinkSync(resolved);
338059
+ fs15.unlinkSync(resolved);
338008
338060
  return `[delete_file] OK: ${resolved}`;
338009
338061
  } catch (e3) {
338010
338062
  return `[delete_file] ${e3 instanceof Error ? e3.message : String(e3)}`;
@@ -338028,11 +338080,11 @@ var ToolExecutor = class {
338028
338080
  const results = [];
338029
338081
  const walk4 = (d3, depth) => {
338030
338082
  if (depth > 5 || results.length >= 80) return;
338031
- for (const entry of fs14.readdirSync(d3, { withFileTypes: true })) {
338032
- const full = path16.join(d3, entry.name);
338083
+ for (const entry of fs15.readdirSync(d3, { withFileTypes: true })) {
338084
+ const full = path17.join(d3, entry.name);
338033
338085
  if (entry.isFile()) {
338034
338086
  try {
338035
- const content = fs14.readFileSync(full, "utf-8");
338087
+ const content = fs15.readFileSync(full, "utf-8");
338036
338088
  for (const [i4, line] of content.split("\n").entries()) {
338037
338089
  if (re.test(line)) {
338038
338090
  results.push(`${entry.name}:${i4 + 1}:${line.trim()}`);
@@ -338248,29 +338300,53 @@ ${String(result.data)}`);
338248
338300
  try {
338249
338301
  const resp = await this.proxyFetch(src, { signal });
338250
338302
  const content = await resp.text();
338251
- const dir = path16.join(this.root, "skills", name50);
338252
- fs14.mkdirSync(dir, { recursive: true });
338253
- fs14.writeFileSync(path16.join(dir, "SKILL.md"), content, "utf-8");
338303
+ const dir = path17.join(this.root, "skills", name50);
338304
+ fs15.mkdirSync(dir, { recursive: true });
338305
+ fs15.writeFileSync(path17.join(dir, "SKILL.md"), content, "utf-8");
338254
338306
  return `[skill] Downloaded '${name50}'`;
338255
338307
  } catch (e3) {
338256
338308
  return `[skill] ${e3}`;
338257
338309
  }
338258
338310
  }
338259
338311
  flowList() {
338260
- const dir = path16.join(this.root, "Flow");
338312
+ const dir = path17.join(this.root, "Flow");
338261
338313
  try {
338262
- const files = fs14.readdirSync(dir).filter((f3) => f3.endsWith(".Flow.json")).sort();
338314
+ const files = fs15.readdirSync(dir).filter((f3) => f3.endsWith(".Flow.json")).sort();
338263
338315
  if (!files.length) return "[flow_list] No workflows found.";
338264
338316
  return files.map((f3) => f3.replace(/\.Flow\.json$/, "")).join("\n");
338265
338317
  } catch (e3) {
338266
338318
  return `[flow_list] ${e3}`;
338267
338319
  }
338268
338320
  }
338269
- flowSave(name50, componentsRaw) {
338321
+ flowSave(name50, input2) {
338270
338322
  const cleanName = (name50 || "").replace(/[<>:"/\\|?*]/g, "-").trim();
338271
338323
  if (!cleanName) return "[flow_save] Workflow name is required.";
338272
- if (!Array.isArray(componentsRaw)) return "[flow_save] components must be an array.";
338273
- const components = componentsRaw.map((raw, idx) => {
338324
+ const dir = path17.join(this.root, "Flow");
338325
+ const target = path17.join(dir, `${cleanName}.Flow.json`);
338326
+ const action = String(input2.action || (Array.isArray(input2.components) ? "replace" : "upsert")).toLowerCase();
338327
+ let componentsRaw = input2.components;
338328
+ if (action === "upsert") {
338329
+ if (!input2.component || typeof input2.component !== "object") return "[flow_save] component is required for action=upsert.";
338330
+ const existing = FlowEngine.load(dir, cleanName)?.components || [];
338331
+ const component = input2.component;
338332
+ const requestedId = Number(component.id);
338333
+ if (!Number.isFinite(requestedId)) return "[flow_save] component.id is required for action=upsert.";
338334
+ componentsRaw = [...existing.filter((item) => item.id !== requestedId), component].sort((a3, b2) => Number(a3.id) - Number(b2.id));
338335
+ } else if (action === "delete") {
338336
+ if (input2.confirm !== true) return "[flow_save] action=delete requires confirm=true.";
338337
+ const componentId = Number(input2.component_id);
338338
+ if (!Number.isFinite(componentId)) return "[flow_save] component_id is required for action=delete.";
338339
+ const existing = FlowEngine.load(dir, cleanName);
338340
+ if (!existing) return `[flow_save] Workflow not found: ${cleanName}`;
338341
+ const remaining = existing.components.filter((item) => item.id !== componentId);
338342
+ if (remaining.length === existing.components.length) return `[flow_save] Component not found: ${componentId}`;
338343
+ componentsRaw = remaining;
338344
+ } else if (action !== "replace") {
338345
+ return `[flow_save] Unknown action: ${action}`;
338346
+ }
338347
+ if (!Array.isArray(componentsRaw)) return "[flow_save] components must be an array for action=replace.";
338348
+ const componentInputs = componentsRaw;
338349
+ const components = componentInputs.map((raw, idx) => {
338274
338350
  const c3 = raw;
338275
338351
  const type = c3.type === "logic" ? "logic" : "dialog";
338276
338352
  if (type === "logic") {
@@ -338291,10 +338367,9 @@ ${String(result.data)}`);
338291
338367
  };
338292
338368
  });
338293
338369
  const workflow = { name: cleanName, components };
338294
- const dir = path16.join(this.root, "Flow");
338295
- fs14.mkdirSync(dir, { recursive: true });
338296
- fs14.writeFileSync(path16.join(dir, `${cleanName}.Flow.json`), JSON.stringify(workflow, null, 2), "utf-8");
338297
- return `[flow_save] OK: ${cleanName}.Flow.json`;
338370
+ fs15.mkdirSync(dir, { recursive: true });
338371
+ fs15.writeFileSync(target, JSON.stringify(workflow, null, 2), "utf-8");
338372
+ return `[flow_save] OK (${action}): ${cleanName}.Flow.json`;
338298
338373
  }
338299
338374
  memoryLabRead(selector2) {
338300
338375
  const lab2 = new MemoryLabManager(this.root);
@@ -338354,10 +338429,10 @@ ${String(result.data)}`);
338354
338429
  return this.gh(args, ws, signal);
338355
338430
  }
338356
338431
  async fileAudit(target, ws, includeRemote, baseRef, signal) {
338357
- const resolvedTarget = path16.resolve(target || ws);
338358
- const exists = fs14.existsSync(resolvedTarget);
338359
- const stat = exists ? fs14.statSync(resolvedTarget) : null;
338360
- const repoRoot = await this.findGitRoot(exists && stat?.isDirectory() ? resolvedTarget : path16.dirname(resolvedTarget), ws, signal);
338432
+ const resolvedTarget = path17.resolve(target || ws);
338433
+ const exists = fs15.existsSync(resolvedTarget);
338434
+ const stat = exists ? fs15.statSync(resolvedTarget) : null;
338435
+ const repoRoot = await this.findGitRoot(exists && stat?.isDirectory() ? resolvedTarget : path17.dirname(resolvedTarget), ws, signal);
338361
338436
  const audit = {
338362
338437
  ok: true,
338363
338438
  target: resolvedTarget,
@@ -338384,11 +338459,11 @@ ${String(result.data)}`);
338384
338459
  };
338385
338460
  if (stat.isFile()) {
338386
338461
  const hash = crypto8.createHash("sha256");
338387
- hash.update(fs14.readFileSync(target));
338462
+ hash.update(fs15.readFileSync(target));
338388
338463
  base2.sha256 = hash.digest("hex").toUpperCase();
338389
338464
  }
338390
338465
  if (stat.isDirectory()) {
338391
- base2.entries = fs14.readdirSync(target).slice(0, 200).sort();
338466
+ base2.entries = fs15.readdirSync(target).slice(0, 200).sort();
338392
338467
  }
338393
338468
  return base2;
338394
338469
  }
@@ -338397,14 +338472,14 @@ ${String(result.data)}`);
338397
338472
  const out = await this.gitExecAt(candidate, ["rev-parse", "--show-toplevel"], signal);
338398
338473
  if (!out.startsWith("[git]") && !out.includes("not a git repository")) {
338399
338474
  const root2 = out.split(/\r?\n/)[0].trim();
338400
- if (root2 && fs14.existsSync(root2)) return path16.resolve(root2);
338475
+ if (root2 && fs15.existsSync(root2)) return path17.resolve(root2);
338401
338476
  }
338402
338477
  }
338403
338478
  return null;
338404
338479
  }
338405
338480
  async gitFileAudit(repoRoot, target, baseRef, signal) {
338406
- const rel = path16.relative(repoRoot, target).replace(/\\/g, "/");
338407
- const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !path16.isAbsolute(rel);
338481
+ const rel = path17.relative(repoRoot, target).replace(/\\/g, "/");
338482
+ const inside2 = rel === "" || !!rel && !rel.startsWith("..") && !path17.isAbsolute(rel);
338408
338483
  if (!inside2) return { repository: repoRoot, tracked: false, note: "Path is outside the detected repository." };
338409
338484
  const branch = await this.gitExecAt(repoRoot, ["branch", "--show-current"], signal);
338410
338485
  const status = rel === "" ? await this.gitExecAt(repoRoot, ["status", "--short"], signal) : await this.gitExecAt(repoRoot, ["status", "--short", "--", rel], signal);
@@ -338462,7 +338537,7 @@ ${String(result.data)}`);
338462
338537
  }
338463
338538
  async githubFileAudit(repoRoot, target, remote, signal) {
338464
338539
  const repo = `${remote.owner}/${remote.name}`;
338465
- const rel = path16.relative(repoRoot, target).replace(/\\/g, "/");
338540
+ const rel = path17.relative(repoRoot, target).replace(/\\/g, "/");
338466
338541
  const branch = (await this.gitExecAt(repoRoot, ["branch", "--show-current"], signal)).trim();
338467
338542
  const encodedPath = rel && rel !== "." ? rel.split("/").map((part) => encodeURIComponent(part)).join("/") : "";
338468
338543
  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);
@@ -338486,8 +338561,8 @@ ${String(result.data)}`);
338486
338561
  };
338487
338562
  }
338488
338563
  async repoSecurityAudit(target, ws, baseRef, signal) {
338489
- const resolvedTarget = path16.resolve(target || ws);
338490
- const repoRoot = await this.findGitRoot(fs14.existsSync(resolvedTarget) && fs14.statSync(resolvedTarget).isDirectory() ? resolvedTarget : path16.dirname(resolvedTarget), ws, signal);
338564
+ const resolvedTarget = path17.resolve(target || ws);
338565
+ const repoRoot = await this.findGitRoot(fs15.existsSync(resolvedTarget) && fs15.statSync(resolvedTarget).isDirectory() ? resolvedTarget : path17.dirname(resolvedTarget), ws, signal);
338491
338566
  if (!repoRoot) {
338492
338567
  return JSON.stringify({
338493
338568
  ok: true,
@@ -338585,12 +338660,12 @@ ${String(result.data)}`);
338585
338660
  const findings = [];
338586
338661
  for (const rel of Array.from(files).sort()) {
338587
338662
  if (findings.length >= 40) break;
338588
- const full = path16.join(repoRoot, rel);
338589
- if (!fs14.existsSync(full) || !fs14.statSync(full).isFile()) continue;
338590
- if (fs14.statSync(full).size > 512 * 1024) continue;
338663
+ const full = path17.join(repoRoot, rel);
338664
+ if (!fs15.existsSync(full) || !fs15.statSync(full).isFile()) continue;
338665
+ if (fs15.statSync(full).size > 512 * 1024) continue;
338591
338666
  let text = "";
338592
338667
  try {
338593
- text = fs14.readFileSync(full, "utf-8");
338668
+ text = fs15.readFileSync(full, "utf-8");
338594
338669
  } catch {
338595
338670
  continue;
338596
338671
  }
@@ -338620,12 +338695,12 @@ ${String(result.data)}`);
338620
338695
  const findings = [];
338621
338696
  for (const rel of Array.from(files).sort()) {
338622
338697
  if (findings.length >= 40) break;
338623
- const full = path16.join(repoRoot, rel);
338624
- if (!fs14.existsSync(full) || !fs14.statSync(full).isFile()) continue;
338625
- if (fs14.statSync(full).size > 512 * 1024) continue;
338698
+ const full = path17.join(repoRoot, rel);
338699
+ if (!fs15.existsSync(full) || !fs15.statSync(full).isFile()) continue;
338700
+ if (fs15.statSync(full).size > 512 * 1024) continue;
338626
338701
  let text = "";
338627
338702
  try {
338628
- text = fs14.readFileSync(full, "utf-8");
338703
+ text = fs15.readFileSync(full, "utf-8");
338629
338704
  } catch {
338630
338705
  continue;
338631
338706
  }
@@ -338642,7 +338717,7 @@ ${String(result.data)}`);
338642
338717
  releaseExcludedPathFindings(repoRoot, ignoredFilesRaw) {
338643
338718
  const sensitive = /^(config\.json|agent\.md|PC_Hash\.config|Work\/|archive\/|skills\/|Memory Lab\/|Design\.md|release\/|_local\/|_ref\/|vendor\/)/i;
338644
338719
  const fromIgnored = String(ignoredFilesRaw || "").split(/\r?\n/).map((line) => line.trim().replace(/\\/g, "/")).filter((line) => line && sensitive.test(line));
338645
- const direct = ["config.json", "agent.md", "PC_Hash.config", "Work", "archive", "skills", "Memory Lab", "Design.md", "release", "_local", "_ref", "vendor"].filter((rel) => fs14.existsSync(path16.join(repoRoot, rel))).map((rel) => rel.replace(/\\/g, "/"));
338720
+ 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, "/"));
338646
338721
  return Array.from(/* @__PURE__ */ new Set([...fromIgnored, ...direct])).slice(0, 80);
338647
338722
  }
338648
338723
  async ghJson(args, ws, signal) {
@@ -339446,8 +339521,8 @@ function sharedSubagentManager(key3, options) {
339446
339521
  }
339447
339522
 
339448
339523
  // src/core/skills.ts
339449
- var fs15 = __toESM(require("fs"));
339450
- var path17 = __toESM(require("path"));
339524
+ var fs16 = __toESM(require("fs"));
339525
+ var path18 = __toESM(require("path"));
339451
339526
  var os4 = __toESM(require("os"));
339452
339527
  var import_crypto9 = require("crypto");
339453
339528
  var SkillsManager = class {
@@ -339456,13 +339531,13 @@ var SkillsManager = class {
339456
339531
  marketSourcesPath;
339457
339532
  metadataCache = /* @__PURE__ */ new Map();
339458
339533
  constructor(root2) {
339459
- this.skillsDir = path17.join(root2, "skills");
339460
- this.metaPath = path17.join(this.skillsDir, ".skills.json");
339461
- this.marketSourcesPath = path17.join(this.skillsDir, ".market-sources.json");
339462
- fs15.mkdirSync(this.skillsDir, { recursive: true });
339534
+ this.skillsDir = path18.join(root2, "skills");
339535
+ this.metaPath = path18.join(this.skillsDir, ".skills.json");
339536
+ this.marketSourcesPath = path18.join(this.skillsDir, ".market-sources.json");
339537
+ fs16.mkdirSync(this.skillsDir, { recursive: true });
339463
339538
  }
339464
339539
  list() {
339465
- return fs15.readdirSync(this.skillsDir, { withFileTypes: true }).filter((e3) => e3.isDirectory() && !e3.name.startsWith(".")).map((e3) => e3.name);
339540
+ return fs16.readdirSync(this.skillsDir, { withFileTypes: true }).filter((e3) => e3.isDirectory() && !e3.name.startsWith(".")).map((e3) => e3.name);
339466
339541
  }
339467
339542
  listDetailed() {
339468
339543
  return this.list().map((name50) => this.infoFor(name50, this.getPath(name50), "project", true));
@@ -339483,48 +339558,48 @@ var SkillsManager = class {
339483
339558
  }
339484
339559
  load(name50) {
339485
339560
  const reference = String(name50 || "").trim().toLowerCase();
339486
- const skill = this.active().find((item) => item.name.toLowerCase() === reference || path17.basename(item.path).toLowerCase() === reference);
339561
+ const skill = this.active().find((item) => item.name.toLowerCase() === reference || path18.basename(item.path).toLowerCase() === reference);
339487
339562
  if (!skill) return null;
339488
- const skillPath = path17.join(skill.path, "SKILL.md");
339489
- const content = fs15.readFileSync(skillPath, "utf-8");
339563
+ const skillPath = path18.join(skill.path, "SKILL.md");
339564
+ const content = fs16.readFileSync(skillPath, "utf-8");
339490
339565
  const files = this.sampleSkillFiles(skill.path, 10);
339491
339566
  return { skill, content, files };
339492
339567
  }
339493
339568
  has(name50) {
339494
- return fs15.existsSync(path17.join(this.skillsDir, name50, "SKILL.md"));
339569
+ return fs16.existsSync(path18.join(this.skillsDir, name50, "SKILL.md"));
339495
339570
  }
339496
339571
  getPath(name50) {
339497
- return path17.join(this.skillsDir, name50);
339572
+ return path18.join(this.skillsDir, name50);
339498
339573
  }
339499
339574
  async download(name50, url) {
339500
- const dir = path17.join(this.skillsDir, name50);
339501
- fs15.mkdirSync(dir, { recursive: true });
339575
+ const dir = path18.join(this.skillsDir, name50);
339576
+ fs16.mkdirSync(dir, { recursive: true });
339502
339577
  if (!url.startsWith("http")) return `[skill] Not a URL: ${url}`;
339503
339578
  try {
339504
339579
  const resp = await fetch(url);
339505
339580
  const content = await resp.text();
339506
- fs15.writeFileSync(path17.join(dir, "SKILL.md"), content, "utf-8");
339581
+ fs16.writeFileSync(path18.join(dir, "SKILL.md"), content, "utf-8");
339507
339582
  return `[skill] Downloaded '${name50}'`;
339508
339583
  } catch (e3) {
339509
339584
  return `[skill] ${e3}`;
339510
339585
  }
339511
339586
  }
339512
339587
  installFromLocal(sourceDir, targetName) {
339513
- const skillPath = path17.join(sourceDir, "SKILL.md");
339514
- if (!fs15.existsSync(skillPath)) return false;
339588
+ const skillPath = path18.join(sourceDir, "SKILL.md");
339589
+ if (!fs16.existsSync(skillPath)) return false;
339515
339590
  const info = this.parseSkillInfo(sourceDir);
339516
- const cleanName = this.cleanName(targetName || info.name || path17.basename(sourceDir));
339591
+ const cleanName = this.cleanName(targetName || info.name || path18.basename(sourceDir));
339517
339592
  if (!cleanName) return false;
339518
- const dest = path17.join(this.skillsDir, cleanName);
339519
- fs15.rmSync(dest, { recursive: true, force: true });
339520
- fs15.cpSync(sourceDir, dest, { recursive: true });
339593
+ const dest = path18.join(this.skillsDir, cleanName);
339594
+ fs16.rmSync(dest, { recursive: true, force: true });
339595
+ fs16.cpSync(sourceDir, dest, { recursive: true });
339521
339596
  this.setEnabled(cleanName, true);
339522
339597
  return true;
339523
339598
  }
339524
339599
  remove(name50) {
339525
- const dir = path17.join(this.skillsDir, name50);
339526
- if (fs15.existsSync(dir)) {
339527
- fs15.rmSync(dir, { recursive: true, force: true });
339600
+ const dir = path18.join(this.skillsDir, name50);
339601
+ if (fs16.existsSync(dir)) {
339602
+ fs16.rmSync(dir, { recursive: true, force: true });
339528
339603
  const meta = this.loadMeta();
339529
339604
  meta.disabled = meta.disabled.filter((n3) => n3 !== name50);
339530
339605
  this.saveMeta(meta);
@@ -339573,7 +339648,7 @@ var SkillsManager = class {
339573
339648
  type,
339574
339649
  enabled: input2.enabled !== false,
339575
339650
  url: url || void 0,
339576
- path: sourcePath ? path17.resolve(sourcePath) : void 0,
339651
+ path: sourcePath ? path18.resolve(sourcePath) : void 0,
339577
339652
  addedAt: existing?.addedAt || now2,
339578
339653
  updatedAt: now2
339579
339654
  };
@@ -339611,17 +339686,17 @@ var SkillsManager = class {
339611
339686
  const items = [];
339612
339687
  for (const info of this.listDetailed()) items.push(info);
339613
339688
  const roots = [
339614
- { root: path17.join(this.skillsDir, "..", ".agents", "skills"), source: "codex" },
339615
- { root: path17.join(this.skillsDir, "..", ".claude", "skills"), source: "claude" },
339616
- { root: path17.join(os4.homedir(), ".agents", "skills"), source: "user" },
339617
- { root: path17.join(os4.homedir(), ".codex", "skills"), source: "codex" },
339618
- { root: path17.join(os4.homedir(), ".claude", "skills"), source: "claude" },
339619
- { root: path17.join(os4.homedir(), ".config", "opencode", "skills"), source: "opencode" }
339689
+ { root: path18.join(this.skillsDir, "..", ".agents", "skills"), source: "codex" },
339690
+ { root: path18.join(this.skillsDir, "..", ".claude", "skills"), source: "claude" },
339691
+ { root: path18.join(os4.homedir(), ".agents", "skills"), source: "user" },
339692
+ { root: path18.join(os4.homedir(), ".codex", "skills"), source: "codex" },
339693
+ { root: path18.join(os4.homedir(), ".claude", "skills"), source: "claude" },
339694
+ { root: path18.join(os4.homedir(), ".config", "opencode", "skills"), source: "opencode" }
339620
339695
  ];
339621
339696
  for (const entry of roots) {
339622
339697
  for (const dir of this.findSkillDirs(entry.root, 4, 240)) {
339623
339698
  const parsed = this.parseSkillInfo(dir);
339624
- const name50 = this.cleanName(parsed.name || path17.basename(dir));
339699
+ const name50 = this.cleanName(parsed.name || path18.basename(dir));
339625
339700
  if (!name50 || items.some((i4) => i4.name === name50 && i4.source !== "remote")) continue;
339626
339701
  items.push({
339627
339702
  name: name50,
@@ -339638,9 +339713,9 @@ var SkillsManager = class {
339638
339713
  });
339639
339714
  }
339640
339715
  }
339641
- for (const dir of this.findPluginSkillDirs(path17.join(this.skillsDir, ".."), 5, 240)) {
339716
+ for (const dir of this.findPluginSkillDirs(path18.join(this.skillsDir, ".."), 5, 240)) {
339642
339717
  const parsed = this.parseSkillInfo(dir);
339643
- const name50 = this.cleanName(parsed.name || path17.basename(dir));
339718
+ const name50 = this.cleanName(parsed.name || path18.basename(dir));
339644
339719
  if (!name50 || items.some((i4) => i4.name === name50 && i4.source !== "remote")) continue;
339645
339720
  items.push({
339646
339721
  name: name50,
@@ -339697,8 +339772,8 @@ var SkillsManager = class {
339697
339772
  }
339698
339773
  loadMeta() {
339699
339774
  try {
339700
- if (fs15.existsSync(this.metaPath)) {
339701
- const raw = JSON.parse(fs15.readFileSync(this.metaPath, "utf-8"));
339775
+ if (fs16.existsSync(this.metaPath)) {
339776
+ const raw = JSON.parse(fs16.readFileSync(this.metaPath, "utf-8"));
339702
339777
  return { disabled: Array.isArray(raw.disabled) ? raw.disabled.map(String) : [] };
339703
339778
  }
339704
339779
  } catch {
@@ -339706,7 +339781,7 @@ var SkillsManager = class {
339706
339781
  return { disabled: [] };
339707
339782
  }
339708
339783
  saveMeta(meta) {
339709
- fs15.writeFileSync(this.metaPath, JSON.stringify({ disabled: meta.disabled }, null, 2), "utf-8");
339784
+ fs16.writeFileSync(this.metaPath, JSON.stringify({ disabled: meta.disabled }, null, 2), "utf-8");
339710
339785
  }
339711
339786
  builtinMarketSources() {
339712
339787
  return [{
@@ -339720,8 +339795,8 @@ var SkillsManager = class {
339720
339795
  }
339721
339796
  loadMarketSources() {
339722
339797
  try {
339723
- if (!fs15.existsSync(this.marketSourcesPath)) return [];
339724
- const raw = JSON.parse(fs15.readFileSync(this.marketSourcesPath, "utf-8"));
339798
+ if (!fs16.existsSync(this.marketSourcesPath)) return [];
339799
+ const raw = JSON.parse(fs16.readFileSync(this.marketSourcesPath, "utf-8"));
339725
339800
  if (!Array.isArray(raw.sources)) return [];
339726
339801
  return raw.sources.map((source) => this.normalizeMarketSource(source)).filter((source) => !!source);
339727
339802
  } catch {
@@ -339730,7 +339805,7 @@ var SkillsManager = class {
339730
339805
  }
339731
339806
  saveMarketSources(sources) {
339732
339807
  const normalized = sources.filter((s3) => !s3.builtin).map((s3) => this.normalizeMarketSource(s3)).filter((source) => !!source);
339733
- fs15.writeFileSync(this.marketSourcesPath, JSON.stringify({ sources: normalized }, null, 2), "utf-8");
339808
+ fs16.writeFileSync(this.marketSourcesPath, JSON.stringify({ sources: normalized }, null, 2), "utf-8");
339734
339809
  }
339735
339810
  normalizeMarketSource(raw) {
339736
339811
  if (!raw || typeof raw !== "object") return null;
@@ -339750,7 +339825,7 @@ var SkillsManager = class {
339750
339825
  type,
339751
339826
  enabled: source.enabled !== false,
339752
339827
  url: url || void 0,
339753
- path: sourcePath ? path17.resolve(sourcePath) : void 0,
339828
+ path: sourcePath ? path18.resolve(sourcePath) : void 0,
339754
339829
  builtin: source.builtin === true,
339755
339830
  addedAt: source.addedAt ? String(source.addedAt) : void 0,
339756
339831
  updatedAt: source.updatedAt ? String(source.updatedAt) : void 0
@@ -339801,11 +339876,11 @@ var SkillsManager = class {
339801
339876
  return rawItems.slice(0, 1e3).map((entry) => this.marketInfoFromCatalogEntry(entry, source, installed)).filter((item) => !!item);
339802
339877
  }
339803
339878
  readCatalogText(source) {
339804
- const catalogPath = source.path ? path17.resolve(source.path) : "";
339805
- if (catalogPath && fs15.existsSync(catalogPath)) return fs15.readFileSync(catalogPath, "utf-8");
339879
+ const catalogPath = source.path ? path18.resolve(source.path) : "";
339880
+ if (catalogPath && fs16.existsSync(catalogPath)) return fs16.readFileSync(catalogPath, "utf-8");
339806
339881
  const url = source.url || "";
339807
- if (url.startsWith("file://")) return fs15.readFileSync(new URL(url), "utf-8");
339808
- if (url && !url.startsWith("http")) return fs15.readFileSync(path17.resolve(url), "utf-8");
339882
+ if (url.startsWith("file://")) return fs16.readFileSync(new URL(url), "utf-8");
339883
+ if (url && !url.startsWith("http")) return fs16.readFileSync(path18.resolve(url), "utf-8");
339809
339884
  return "";
339810
339885
  }
339811
339886
  async discoverJsonMarketSourceAsync(source, installed) {
@@ -339865,7 +339940,7 @@ var SkillsManager = class {
339865
339940
  }
339866
339941
  marketInfoFromLocalDir(dir, source, installed) {
339867
339942
  const parsed = this.parseSkillInfo(dir);
339868
- const name50 = this.cleanName(parsed.name || path17.basename(dir));
339943
+ const name50 = this.cleanName(parsed.name || path18.basename(dir));
339869
339944
  if (!name50) return null;
339870
339945
  return {
339871
339946
  name: name50,
@@ -339890,9 +339965,9 @@ var SkillsManager = class {
339890
339965
  }
339891
339966
  parseSkillInfo(dir) {
339892
339967
  try {
339893
- const skillPath = path17.join(dir, "SKILL.md");
339894
- const stat = fs15.statSync(skillPath);
339895
- const content = fs15.readFileSync(skillPath, "utf-8");
339968
+ const skillPath = path18.join(dir, "SKILL.md");
339969
+ const stat = fs16.statSync(skillPath);
339970
+ const content = fs16.readFileSync(skillPath, "utf-8");
339896
339971
  const digest = (0, import_crypto9.createHash)("sha256").update(content).digest("hex");
339897
339972
  const fingerprint2 = `${stat.mtimeMs}:${stat.size}:${digest}`;
339898
339973
  const cached = this.metadataCache.get(skillPath);
@@ -339925,7 +340000,7 @@ var SkillsManager = class {
339925
340000
  };
339926
340001
  this.metadataCache.set(skillPath, {
339927
340002
  fingerprint: fingerprint2,
339928
- info: { ...parsed, path: dir, enabled: this.isEnabled(path17.basename(dir)), installed: true, source: "project" }
340003
+ info: { ...parsed, path: dir, enabled: this.isEnabled(path18.basename(dir)), installed: true, source: "project" }
339929
340004
  });
339930
340005
  return parsed;
339931
340006
  } catch {
@@ -339942,13 +340017,13 @@ var SkillsManager = class {
339942
340017
  if (files.length >= limit || depth > 2) return;
339943
340018
  let entries = [];
339944
340019
  try {
339945
- entries = fs15.readdirSync(dir, { withFileTypes: true });
340020
+ entries = fs16.readdirSync(dir, { withFileTypes: true });
339946
340021
  } catch {
339947
340022
  return;
339948
340023
  }
339949
340024
  for (const entry of entries) {
339950
340025
  if (files.length >= limit || entry.name === "SKILL.md" || entry.name.startsWith(".")) continue;
339951
- const target = path17.join(dir, entry.name);
340026
+ const target = path18.join(dir, entry.name);
339952
340027
  if (entry.isDirectory()) walk4(target, depth + 1);
339953
340028
  else if (entry.isFile()) files.push(target);
339954
340029
  }
@@ -339962,7 +340037,7 @@ var SkillsManager = class {
339962
340037
  if (results.length >= maxItems || depth > maxDepth) return;
339963
340038
  let entries;
339964
340039
  try {
339965
- entries = fs15.readdirSync(dir, { withFileTypes: true });
340040
+ entries = fs16.readdirSync(dir, { withFileTypes: true });
339966
340041
  } catch {
339967
340042
  return;
339968
340043
  }
@@ -339972,7 +340047,7 @@ var SkillsManager = class {
339972
340047
  }
339973
340048
  for (const e3 of entries) {
339974
340049
  if (!e3.isDirectory() || e3.name.startsWith(".git") || e3.name === "node_modules") continue;
339975
- walk4(path17.join(dir, e3.name), depth + 1);
340050
+ walk4(path18.join(dir, e3.name), depth + 1);
339976
340051
  }
339977
340052
  };
339978
340053
  walk4(root2, 0);
@@ -339984,19 +340059,19 @@ var SkillsManager = class {
339984
340059
  if (results.length >= maxItems || depth > maxDepth) return;
339985
340060
  let entries;
339986
340061
  try {
339987
- entries = fs15.readdirSync(dir, { withFileTypes: true });
340062
+ entries = fs16.readdirSync(dir, { withFileTypes: true });
339988
340063
  } catch {
339989
340064
  return;
339990
340065
  }
339991
340066
  const hasPluginManifest = entries.some((e3) => e3.isDirectory() && (e3.name === ".codex-plugin" || e3.name === ".claude-plugin"));
339992
340067
  if (hasPluginManifest) {
339993
340068
  for (const skillsDir of ["skills", "Skills"]) {
339994
- results.push(...this.findSkillDirs(path17.join(dir, skillsDir), 3, maxItems - results.length));
340069
+ results.push(...this.findSkillDirs(path18.join(dir, skillsDir), 3, maxItems - results.length));
339995
340070
  }
339996
340071
  }
339997
340072
  for (const e3 of entries) {
339998
340073
  if (!e3.isDirectory() || e3.name.startsWith(".git") || e3.name === "node_modules" || e3.name === "release" || e3.name.startsWith("release.locked-")) continue;
339999
- walk4(path17.join(dir, e3.name), depth + 1);
340074
+ walk4(path18.join(dir, e3.name), depth + 1);
340000
340075
  }
340001
340076
  };
340002
340077
  walk4(root2, 0);
@@ -340024,25 +340099,25 @@ var SkillsManager = class {
340024
340099
  if (!description) warnings.push("Missing required frontmatter field: description.");
340025
340100
  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.");
340026
340101
  if (description && description.length > 1e3) warnings.push("Description is longer than recommended for skill discovery.");
340027
- const folderName = path17.basename(dir);
340102
+ const folderName = path18.basename(dir);
340028
340103
  if (name50 && folderName && this.cleanName(name50) !== this.cleanName(folderName)) warnings.push("Skill name does not match containing folder name.");
340029
340104
  return warnings;
340030
340105
  }
340031
340106
  pluginIdForSkill(dir) {
340032
- let current = path17.resolve(dir);
340107
+ let current = path18.resolve(dir);
340033
340108
  for (let i4 = 0; i4 < 6; i4++) {
340034
- const codex = path17.join(current, ".codex-plugin", "plugin.json");
340035
- const claude = path17.join(current, ".claude-plugin", "plugin.json");
340109
+ const codex = path18.join(current, ".codex-plugin", "plugin.json");
340110
+ const claude = path18.join(current, ".claude-plugin", "plugin.json");
340036
340111
  for (const filePath of [codex, claude]) {
340037
340112
  try {
340038
- if (fs15.existsSync(filePath)) {
340039
- const raw = JSON.parse(fs15.readFileSync(filePath, "utf-8"));
340113
+ if (fs16.existsSync(filePath)) {
340114
+ const raw = JSON.parse(fs16.readFileSync(filePath, "utf-8"));
340040
340115
  if (raw?.name) return String(raw.name);
340041
340116
  }
340042
340117
  } catch {
340043
340118
  }
340044
340119
  }
340045
- const parent = path17.dirname(current);
340120
+ const parent = path18.dirname(current);
340046
340121
  if (parent === current) break;
340047
340122
  current = parent;
340048
340123
  }
@@ -345070,7 +345145,7 @@ var Agent4 = class _Agent {
345070
345145
  this.config.set("skills", "auto_download", "disabled");
345071
345146
  }
345072
345147
  const modeStr = this.config.getStr("agent", "default_mode");
345073
- this.mode = ["plan", "goal", "flow"].includes(modeStr) ? modeStr : "build";
345148
+ this.mode = ["plan", "chat", "goal", "flow"].includes(modeStr) ? modeStr : "build";
345074
345149
  const inputStr = this.config.getStr("general", "default_input");
345075
345150
  this.inputMode = inputStr === "next" ? "next" : "guide";
345076
345151
  const configuredModel = this.config.getStr("models", "default_model");
@@ -345238,6 +345313,7 @@ var Agent4 = class _Agent {
345238
345313
  return this.toolchainCore;
345239
345314
  }
345240
345315
  setMode(m2) {
345316
+ if (!["build", "plan", "chat", "goal", "flow"].includes(m2)) m2 = "build";
345241
345317
  if (m2 === "goal" && !this.goal) {
345242
345318
  this.goal = new GoalStateImpl("Set your objective");
345243
345319
  }
@@ -349605,7 +349681,20 @@ ${summary}`, segment, "local-summarize", true);
349605
349681
  if (action === "get") return JSON.stringify({ ok: true, linkedPlan: this.getLinkedPlan() }, null, 2);
349606
349682
  if (action !== "update") return JSON.stringify({ ok: false, error: `Unknown linked_plan action: ${action}` });
349607
349683
  const expectedRevision = Number(input2.expected_revision ?? input2.expectedRevision);
349608
- return JSON.stringify({ ok: true, linkedPlan: this.updateLinkedPlan(String(input2.markdown || ""), expectedRevision) }, null, 2);
349684
+ const current = this.getLinkedPlan();
349685
+ let markdown = input2.markdown === void 0 ? current.markdown : String(input2.markdown);
349686
+ if (input2.append !== void 0) markdown = `${current.markdown}${String(input2.append)}`;
349687
+ if (input2.old_text !== void 0 || input2.oldText !== void 0) {
349688
+ const oldText = String(input2.old_text ?? input2.oldText ?? "");
349689
+ if (!oldText) throw new Error("linked_plan old_text must not be empty.");
349690
+ const matches = current.markdown.split(oldText).length - 1;
349691
+ if (!matches) throw new Error("linked_plan old_text was not found.");
349692
+ const replaceAll = input2.replace_all === true || input2.replaceAll === true;
349693
+ if (matches > 1 && !replaceAll) throw new Error(`linked_plan old_text matched ${matches} places; pass replace_all=true or a unique fragment.`);
349694
+ const newText = String(input2.new_text ?? input2.newText ?? "");
349695
+ markdown = replaceAll ? current.markdown.split(oldText).join(newText) : current.markdown.replace(oldText, newText);
349696
+ }
349697
+ return JSON.stringify({ ok: true, linkedPlan: this.updateLinkedPlan(markdown, expectedRevision) }, null, 2);
349609
349698
  } catch (error) {
349610
349699
  return JSON.stringify({ ok: false, error: error instanceof Error ? error.message : String(error) });
349611
349700
  }
@@ -351907,7 +351996,24 @@ ${this.formatAutomation(item)}` : `[automation_toggle] Not found: ${id}`;
351907
351996
  }));
351908
351997
  }
351909
351998
  case "memory_lab_update": {
351910
- const result = await this.updateMemoryLab({
351999
+ const selector2 = String(params.component || params.slug || "").trim();
352000
+ const prepared = selector2 ? this.memoryLab.preparePatch({
352001
+ component: selector2,
352002
+ name: params.name === void 0 ? void 0 : String(params.name),
352003
+ description: params.description === void 0 ? void 0 : String(params.description),
352004
+ tags: params.tags === void 0 ? void 0 : Array.isArray(params.tags) ? params.tags.map(String) : String(params.tags).split(/[,,\n]+/),
352005
+ tagPaths: params.tagPaths === void 0 ? void 0 : Array.isArray(params.tagPaths) ? params.tagPaths.filter(Array.isArray).map((pathValue) => pathValue.map(String)) : [],
352006
+ content: params.content === void 0 ? void 0 : String(params.content),
352007
+ contentAppend: params.contentAppend === void 0 && params.content_append === void 0 ? void 0 : String(params.contentAppend ?? params.content_append),
352008
+ oldText: params.oldText === void 0 && params.old_text === void 0 ? void 0 : String(params.oldText ?? params.old_text),
352009
+ newText: String(params.newText ?? params.new_text ?? ""),
352010
+ replaceAll: params.replaceAll === true || params.replace_all === true,
352011
+ kind: params.kind === void 0 ? void 0 : params.kind === "folder" ? "folder" : "file",
352012
+ expectedUpdatedAt: String(params.expectedUpdatedAt || params.expected_updated_at || ""),
352013
+ reason: String(params.reason || ""),
352014
+ source: String(params.source || "")
352015
+ }) : void 0;
352016
+ const result = await this.updateMemoryLab(prepared || {
351911
352017
  name: String(params.name || ""),
351912
352018
  description: String(params.description || ""),
351913
352019
  tags: Array.isArray(params.tags) ? params.tags.map(String) : String(params.tags || "").split(/[,,\n]+/),
@@ -352910,6 +353016,8 @@ When using file tools (read, write, edit, glob), use ABSOLUTE paths rooted at th
352910
353016
  parts.push(this.buildFeatureDisclosurePrompt());
352911
353017
  if (this.mode === "plan") parts.push(`[Plan Tool Policy]
352912
353018
  ${planModePolicyPrompt()}`);
353019
+ if (this.mode === "chat") parts.push(`[Chat Tool Policy]
353020
+ ${chatModePolicyPrompt()}`);
352913
353021
  const pm = this.config.getStr("workspace", "prompt_mode") || "both";
352914
353022
  const injectedPrompts = /* @__PURE__ */ new Set();
352915
353023
  if ((pm === "global_only" || pm === "both") && globalPrompt) {
@@ -353031,7 +353139,7 @@ ${custom}`);
353031
353139
  `- 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.`,
353032
353140
  `- Workspace permissions: access_permission=${permission}; file tools are checked before execution and blocked when they exceed the configured workspace boundary.`,
353033
353141
  `- 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.`,
353034
- `- Mode engine: current mode=${this.modeName()}; Build works autonomously, Plan is fully read-only with no file modifications, Goal continues until completion unless paused, Flow follows saved workflow components.`,
353142
+ `- 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.`,
353035
353143
  `- Input mode: ${input2}; Guide injects immediately, Next queues user intent for the following build turn.`,
353036
353144
  `- Option feedback: ${this.buildQuestionPolicyPrompt(optionFeedback)}`,
353037
353145
  `- Model policy: current model=${this.model || "(unset)"}, intelligence=${this.intelligence}, auto-switch=${modelSwitch}.`,
@@ -353097,6 +353205,14 @@ ${custom}`);
353097
353205
  '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.',
353098
353206
  "A positive choice starts a new Build-mode input. A negative choice remains in Plan mode so the user can supply the missing details."
353099
353207
  ]).join("\n");
353208
+ case "chat":
353209
+ return withLanguage([
353210
+ "CHAT MODE.",
353211
+ "Use only web_search and web_fetch. You have no workspace, host, application, memory, task, browser-control, or write permissions.",
353212
+ "Perform an online search to gather evidence before answering. Fetch primary or authoritative pages when the search snippets are insufficient.",
353213
+ "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.",
353214
+ "Distinguish sourced facts from uncertainty and include useful source links in the final answer."
353215
+ ]).join("\n");
353100
353216
  case "goal": {
353101
353217
  const g2 = this.goal?.history() || "";
353102
353218
  const paused = this.goal?.paused ? "\n[GOAL PAUSED by user. Wait for resume.]" : "\n[Continue working until the goal is achieved.]";