@markus-global/cli 0.4.23 → 0.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/markus.mjs CHANGED
@@ -4061,8 +4061,9 @@ var init_models = __esm({
4061
4061
  id: "deepseek",
4062
4062
  label: "DeepSeek",
4063
4063
  envKey: "DEEPSEEK_API_KEY",
4064
- defaultModel: "deepseek-chat",
4065
- models: ["deepseek-chat", "deepseek-coder", "deepseek-chat-v3"]
4064
+ baseUrl: "https://api.deepseek.com",
4065
+ defaultModel: "deepseek-v4-flash",
4066
+ models: ["deepseek-v4-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner"]
4066
4067
  }
4067
4068
  ];
4068
4069
  }
@@ -8324,8 +8325,16 @@ var init_tool_selector = __esm({
8324
8325
  result.push({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema });
8325
8326
  }
8326
8327
  }
8328
+ const seen = new Set(result.map((t) => t.name));
8327
8329
  result.push(this.buildDiscoverTool(opts.allTools, selected, opts.skillCatalog));
8328
- result.push({
8330
+ seen.add("discover_tools");
8331
+ const pushUnique = (tool) => {
8332
+ if (!seen.has(tool.name)) {
8333
+ seen.add(tool.name);
8334
+ result.push(tool);
8335
+ }
8336
+ };
8337
+ pushUnique({
8329
8338
  name: "notify_user",
8330
8339
  description: "Send a message to the user. The message appears in the agent chat and as a notification. Write a comprehensive body \u2014 the user sees the full content and may reply. Use for status updates, reports, alerts, and findings.",
8331
8340
  inputSchema: {
@@ -8339,7 +8348,7 @@ var init_tool_selector = __esm({
8339
8348
  required: ["title", "body"]
8340
8349
  }
8341
8350
  });
8342
- result.push({
8351
+ pushUnique({
8343
8352
  name: "request_user_approval",
8344
8353
  description: "Request a decision or approval from the user. The tool BLOCKS until the user responds. Use when you need human approval, a choice between options, or any user decision/input. Default options: Approve / Reject (reject requires a reason). You can provide custom options and optionally allow freeform text input.",
8345
8354
  inputSchema: {
@@ -8367,7 +8376,7 @@ var init_tool_selector = __esm({
8367
8376
  required: ["title", "description"]
8368
8377
  }
8369
8378
  });
8370
- result.push({
8379
+ pushUnique({
8371
8380
  name: "recall_activity",
8372
8381
  description: 'Query your own execution history. Use "list" to see recent activities, or "get" with an activity_id to see detailed tool call logs for a specific activity.',
8373
8382
  inputSchema: {
@@ -8668,7 +8677,7 @@ function createShellTool(security, workspacePath, agentMeta, policy, onCommandAp
8668
8677
  }
8669
8678
  }
8670
8679
  const finalCommand = injectGitCommitMeta(command, agentMeta);
8671
- return new Promise((resolve21) => {
8680
+ return new Promise((resolve20) => {
8672
8681
  const child = spawn("sh", ["-c", finalCommand], {
8673
8682
  cwd: effectiveCwd ?? void 0,
8674
8683
  stdio: ["ignore", "pipe", "pipe"],
@@ -8723,7 +8732,7 @@ function createShellTool(security, workspacePath, agentMeta, policy, onCommandAp
8723
8732
  flushOutput();
8724
8733
  }
8725
8734
  if (killed) {
8726
- resolve21(JSON.stringify({
8735
+ resolve20(JSON.stringify({
8727
8736
  status: "error",
8728
8737
  error: `Command timed out after ${timeoutMs}ms`,
8729
8738
  exitCode: code,
@@ -8731,7 +8740,7 @@ function createShellTool(security, workspacePath, agentMeta, policy, onCommandAp
8731
8740
  stderr: stderr.slice(0, 4e3)
8732
8741
  }));
8733
8742
  } else if (code !== 0) {
8734
- resolve21(JSON.stringify({
8743
+ resolve20(JSON.stringify({
8735
8744
  status: "error",
8736
8745
  error: stderr.trim() || `Process exited with code ${code}`,
8737
8746
  exitCode: code,
@@ -8739,7 +8748,7 @@ function createShellTool(security, workspacePath, agentMeta, policy, onCommandAp
8739
8748
  stderr: stderr.slice(0, 4e3)
8740
8749
  }));
8741
8750
  } else {
8742
- resolve21(JSON.stringify({
8751
+ resolve20(JSON.stringify({
8743
8752
  status: "success",
8744
8753
  stdout: stdout.trim() || void 0,
8745
8754
  stderr: stderr.trim() || void 0
@@ -8752,7 +8761,7 @@ function createShellTool(security, workspacePath, agentMeta, policy, onCommandAp
8752
8761
  clearTimeout(flushTimer);
8753
8762
  flushOutput();
8754
8763
  }
8755
- resolve21(JSON.stringify({
8764
+ resolve20(JSON.stringify({
8756
8765
  status: "error",
8757
8766
  error: err.message,
8758
8767
  stdout: stdout.slice(0, 4e3),
@@ -14852,8 +14861,8 @@ var init_custom_element_registry = __esm({
14852
14861
  } : (element) => element.localName === localName;
14853
14862
  registry.set(localName, { Class, check: check2 });
14854
14863
  if (waiting.has(localName)) {
14855
- for (const resolve21 of waiting.get(localName))
14856
- resolve21(Class);
14864
+ for (const resolve20 of waiting.get(localName))
14865
+ resolve20(Class);
14857
14866
  waiting.delete(localName);
14858
14867
  }
14859
14868
  ownerDocument.querySelectorAll(
@@ -14893,13 +14902,13 @@ var init_custom_element_registry = __esm({
14893
14902
  */
14894
14903
  whenDefined(localName) {
14895
14904
  const { registry, waiting } = this;
14896
- return new Promise((resolve21) => {
14905
+ return new Promise((resolve20) => {
14897
14906
  if (registry.has(localName))
14898
- resolve21(registry.get(localName).Class);
14907
+ resolve20(registry.get(localName).Class);
14899
14908
  else {
14900
14909
  if (!waiting.has(localName))
14901
14910
  waiting.set(localName, []);
14902
- waiting.get(localName).push(resolve21);
14911
+ waiting.get(localName).push(resolve20);
14903
14912
  }
14904
14913
  });
14905
14914
  }
@@ -41801,7 +41810,7 @@ var init_search = __esm({
41801
41810
 
41802
41811
  // ../core/dist/tools/patch.js
41803
41812
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, existsSync as existsSync13, unlinkSync } from "node:fs";
41804
- import { dirname as dirname4, resolve as resolve7 } from "node:path";
41813
+ import { dirname as dirname4 } from "node:path";
41805
41814
  function createPatchTool(security, workspacePath, policy) {
41806
41815
  const guard = security ?? defaultSecurityGuard;
41807
41816
  return {
@@ -41852,7 +41861,7 @@ function createPatchTool(security, workspacePath, policy) {
41852
41861
  if (!patches || !Array.isArray(patches) || patches.length === 0) {
41853
41862
  return JSON.stringify({ status: "error", error: "patches array is required and must not be empty" });
41854
41863
  }
41855
- const basePath = workspacePath ?? process.cwd();
41864
+ const resolvedPaths = [];
41856
41865
  const results = [];
41857
41866
  for (const patch of patches) {
41858
41867
  const { resolved: filePath, access } = resolveAndCheckAccess(patch.file, workspacePath, policy);
@@ -41893,6 +41902,7 @@ function createPatchTool(security, workspacePath, policy) {
41893
41902
  if (patch.action === "create" && !patch.content && patch.content !== "") {
41894
41903
  return JSON.stringify({ status: "error", error: `create action requires content for ${patch.file}` });
41895
41904
  }
41905
+ resolvedPaths.push(filePath);
41896
41906
  }
41897
41907
  if (dryRun) {
41898
41908
  return JSON.stringify({
@@ -41901,8 +41911,9 @@ function createPatchTool(security, workspacePath, policy) {
41901
41911
  patchCount: patches.length
41902
41912
  });
41903
41913
  }
41904
- for (const patch of patches) {
41905
- const filePath = resolve7(basePath, patch.file);
41914
+ for (let i = 0; i < patches.length; i++) {
41915
+ const patch = patches[i];
41916
+ const filePath = resolvedPaths[i];
41906
41917
  switch (patch.action) {
41907
41918
  case "edit": {
41908
41919
  let content = readFileSync9(filePath, "utf-8");
@@ -41958,7 +41969,7 @@ var init_patch = __esm({
41958
41969
 
41959
41970
  // ../core/dist/tools/process-manager.js
41960
41971
  import { spawn as spawn2 } from "node:child_process";
41961
- import { resolve as resolve8 } from "node:path";
41972
+ import { resolve as resolve7 } from "node:path";
41962
41973
  function onBackgroundCompletion(cb) {
41963
41974
  completionListeners.push(cb);
41964
41975
  return () => {
@@ -42020,8 +42031,8 @@ function createBackgroundExecTool(workspacePath) {
42020
42031
  const cwd = args["cwd"];
42021
42032
  const timeoutSec = args["timeout_seconds"] ?? 300;
42022
42033
  const basePath = workspacePath ?? process.cwd();
42023
- const effectiveCwd = cwd ? resolve8(basePath, cwd) : basePath;
42024
- if (workspacePath && !effectiveCwd.startsWith(resolve8(workspacePath))) {
42034
+ const effectiveCwd = cwd ? resolve7(basePath, cwd) : basePath;
42035
+ if (workspacePath && !effectiveCwd.startsWith(resolve7(workspacePath))) {
42025
42036
  return JSON.stringify({ status: "denied", error: "Working directory must be within workspace" });
42026
42037
  }
42027
42038
  const id = `bg_${++sessionCounter}_${Date.now()}`;
@@ -42285,7 +42296,7 @@ async function llmCallWithRetry(fn, label) {
42285
42296
  error: String(err).slice(0, SUBAGENT_ERROR_PREVIEW_CHARS),
42286
42297
  delay
42287
42298
  });
42288
- await new Promise((resolve21) => setTimeout(resolve21, delay));
42299
+ await new Promise((resolve20) => setTimeout(resolve20, delay));
42289
42300
  }
42290
42301
  }
42291
42302
  throw lastErr;
@@ -42358,7 +42369,7 @@ async function runSubagentLoop(ctx, task, opts) {
42358
42369
  metadata: { iteration: iterations, finishReason: response.finishReason }
42359
42370
  });
42360
42371
  if (response.finishReason === "max_tokens" && !response.toolCalls?.length) {
42361
- messages.push({ role: "assistant", content: response.content });
42372
+ messages.push({ role: "assistant", content: response.content, reasoningContent: response.reasoningContent });
42362
42373
  logEntries.push({ ts: (/* @__PURE__ */ new Date()).toISOString(), role: "assistant", content: response.content });
42363
42374
  messages.push({
42364
42375
  role: "user",
@@ -42368,7 +42379,8 @@ async function runSubagentLoop(ctx, task, opts) {
42368
42379
  messages.push({
42369
42380
  role: "assistant",
42370
42381
  content: response.content,
42371
- toolCalls: response.toolCalls
42382
+ toolCalls: response.toolCalls,
42383
+ reasoningContent: response.reasoningContent
42372
42384
  });
42373
42385
  logEntries.push({
42374
42386
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -42873,9 +42885,9 @@ ${typeLabel}${item.payload.content}`;
42873
42885
  */
42874
42886
  wakeIdleLoop() {
42875
42887
  if (this.idleResolve) {
42876
- const resolve21 = this.idleResolve;
42888
+ const resolve20 = this.idleResolve;
42877
42889
  this.idleResolve = void 0;
42878
- resolve21();
42890
+ resolve20();
42879
42891
  }
42880
42892
  }
42881
42893
  /**
@@ -42900,8 +42912,8 @@ ${typeLabel}${item.payload.content}`;
42900
42912
  const item = this.dequeue();
42901
42913
  if (item)
42902
42914
  return item;
42903
- await new Promise((resolve21) => {
42904
- this.idleResolve = resolve21;
42915
+ await new Promise((resolve20) => {
42916
+ this.idleResolve = resolve20;
42905
42917
  });
42906
42918
  const afterWake = this.dequeue();
42907
42919
  if (!afterWake) {
@@ -43448,7 +43460,7 @@ var init_attention = __esm({
43448
43460
  try {
43449
43461
  const processing = this.delegate?.processMailboxItem(item);
43450
43462
  const backstopMs = this.waitingForHumanApproval ? APPROVAL_WAIT_TIMEOUT_MS : MAILBOX_PROCESSING_TIMEOUT_MS;
43451
- const backstop = new Promise((resolve21) => setTimeout(() => resolve21(void 0), backstopMs));
43463
+ const backstop = new Promise((resolve20) => setTimeout(() => resolve20(void 0), backstopMs));
43452
43464
  const result = await Promise.race([
43453
43465
  processing?.then((r) => ({ done: true, reply: r })),
43454
43466
  backstop.then(() => ({ done: false, reply: void 0 }))
@@ -43554,8 +43566,8 @@ var init_attention = __esm({
43554
43566
  * The promise is single-use; call again to get a fresh one.
43555
43567
  */
43556
43568
  waitForPreemptionSignal() {
43557
- return new Promise((resolve21) => {
43558
- this.criticalInterruptResolve = resolve21;
43569
+ return new Promise((resolve20) => {
43570
+ this.criticalInterruptResolve = resolve20;
43559
43571
  });
43560
43572
  }
43561
43573
  /**
@@ -43802,7 +43814,7 @@ var init_attention = __esm({
43802
43814
  raw = response.content;
43803
43815
  break;
43804
43816
  }
43805
- messages.push({ role: "assistant", content: response.content, toolCalls: response.toolCalls });
43817
+ messages.push({ role: "assistant", content: response.content, toolCalls: response.toolCalls, reasoningContent: response.reasoningContent });
43806
43818
  for (const tc of response.toolCalls) {
43807
43819
  const handler4 = this.triageToolHandlers.get(tc.name);
43808
43820
  let result;
@@ -44302,7 +44314,7 @@ var init_task_queue = __esm({
44302
44314
  */
44303
44315
  async waitForAll() {
44304
44316
  while (this.runningTasks.size > 0 || this.queue.length > 0) {
44305
- await new Promise((resolve21) => setTimeout(resolve21, 100));
44317
+ await new Promise((resolve20) => setTimeout(resolve20, 100));
44306
44318
  }
44307
44319
  }
44308
44320
  };
@@ -44429,12 +44441,12 @@ var init_task_executor = __esm({
44429
44441
  * 等待任务完成
44430
44442
  */
44431
44443
  async waitForTaskCompletion(taskId2) {
44432
- return new Promise((resolve21) => {
44444
+ return new Promise((resolve20) => {
44433
44445
  const checkInterval = setInterval(() => {
44434
44446
  const task = this.taskQueue.getTaskStatus(taskId2);
44435
44447
  if (task && task.status !== TaskStatus.PENDING && task.status !== TaskStatus.RUNNING) {
44436
44448
  clearInterval(checkInterval);
44437
- resolve21(task);
44449
+ resolve20(task);
44438
44450
  }
44439
44451
  }, 100);
44440
44452
  });
@@ -44938,24 +44950,24 @@ function extensionForMime(mime) {
44938
44950
  async function checkMarkitdown() {
44939
44951
  if (markitdownAvailable !== null)
44940
44952
  return markitdownAvailable;
44941
- return new Promise((resolve21) => {
44953
+ return new Promise((resolve20) => {
44942
44954
  execFile2("markitdown", ["--help"], { timeout: 5e3 }, (err) => {
44943
44955
  markitdownAvailable = !err;
44944
44956
  if (!markitdownAvailable) {
44945
44957
  log16.info('markitdown CLI not found; file-to-text conversion will be limited. Install with: pip install "markitdown[all]"');
44946
44958
  }
44947
- resolve21(markitdownAvailable);
44959
+ resolve20(markitdownAvailable);
44948
44960
  });
44949
44961
  });
44950
44962
  }
44951
44963
  async function convertWithMarkitdown(filePath) {
44952
- return new Promise((resolve21, reject) => {
44964
+ return new Promise((resolve20, reject) => {
44953
44965
  execFile2("markitdown", [filePath], { timeout: 3e4, maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => {
44954
44966
  if (err) {
44955
44967
  reject(new Error(`markitdown failed: ${stderr || err.message}`));
44956
44968
  return;
44957
44969
  }
44958
- resolve21(stdout);
44970
+ resolve20(stdout);
44959
44971
  });
44960
44972
  });
44961
44973
  }
@@ -45414,14 +45426,14 @@ ${notification.stdoutTail}`);
45414
45426
  toolEventCollector: options?.toolEventCollector
45415
45427
  }
45416
45428
  };
45417
- return new Promise((resolve21, reject) => {
45429
+ return new Promise((resolve20, reject) => {
45418
45430
  this.mailbox.enqueue(sourceType, payload, {
45419
45431
  priority: options?.priority,
45420
45432
  metadata: {
45421
45433
  senderId,
45422
45434
  senderName: senderInfo?.name,
45423
45435
  senderRole: senderInfo?.role,
45424
- responsePromise: { resolve: resolve21, reject }
45436
+ responsePromise: { resolve: resolve20, reject }
45425
45437
  }
45426
45438
  });
45427
45439
  });
@@ -45443,14 +45455,14 @@ ${notification.stdoutTail}`);
45443
45455
  cancelToken
45444
45456
  }
45445
45457
  };
45446
- return new Promise((resolve21, reject) => {
45458
+ return new Promise((resolve20, reject) => {
45447
45459
  this.mailbox.enqueue("human_chat", payload, {
45448
45460
  priority: 0,
45449
45461
  metadata: {
45450
45462
  senderId,
45451
45463
  senderName: senderInfo?.name,
45452
45464
  senderRole: senderInfo?.role,
45453
- responsePromise: { resolve: resolve21, reject }
45465
+ responsePromise: { resolve: resolve20, reject }
45454
45466
  }
45455
45467
  });
45456
45468
  });
@@ -45478,12 +45490,12 @@ ${notification.stdoutTail}`);
45478
45490
  executionRound
45479
45491
  }
45480
45492
  };
45481
- return new Promise((resolve21, reject) => {
45493
+ return new Promise((resolve20, reject) => {
45482
45494
  this.mailbox.enqueue("task_status_update", payload, {
45483
45495
  priority: 1,
45484
45496
  metadata: {
45485
45497
  taskId: taskId2,
45486
- responsePromise: { resolve: resolve21, reject }
45498
+ responsePromise: { resolve: resolve20, reject }
45487
45499
  }
45488
45500
  });
45489
45501
  });
@@ -45501,13 +45513,13 @@ ${notification.stdoutTail}`);
45501
45513
  onLog
45502
45514
  }
45503
45515
  };
45504
- return new Promise((resolve21, reject) => {
45516
+ return new Promise((resolve20, reject) => {
45505
45517
  this.mailbox.enqueue("session_reply", payload, {
45506
45518
  metadata: {
45507
45519
  senderId,
45508
45520
  senderName: senderInfo?.name,
45509
45521
  senderRole: senderInfo?.role,
45510
- responsePromise: { resolve: resolve21, reject }
45522
+ responsePromise: { resolve: resolve20, reject }
45511
45523
  }
45512
45524
  });
45513
45525
  });
@@ -46891,7 +46903,7 @@ ${block}
46891
46903
  break;
46892
46904
  }
46893
46905
  if (response.finishReason === "max_tokens" && !response.toolCalls?.length) {
46894
- this.memory.appendMessage(sessionId, { role: "assistant", content: response.content });
46906
+ this.memory.appendMessage(sessionId, { role: "assistant", content: response.content, reasoningContent: response.reasoningContent });
46895
46907
  const contMsg = {
46896
46908
  role: "user",
46897
46909
  content: "[Continue from where you left off. Do not repeat what you already said.]"
@@ -46901,7 +46913,8 @@ ${block}
46901
46913
  this.memory.appendMessage(sessionId, {
46902
46914
  role: "assistant",
46903
46915
  content: response.content,
46904
- toolCalls: response.toolCalls
46916
+ toolCalls: response.toolCalls,
46917
+ reasoningContent: response.reasoningContent
46905
46918
  });
46906
46919
  const currentActId = this.state.currentActivity?.id;
46907
46920
  const toolResults = await Promise.all(response.toolCalls.map(async (tc) => {
@@ -47043,10 +47056,10 @@ ${chatYield.item.payload.content}`;
47043
47056
  const outputCheck = await this.guardrails.checkOutput(displayReply, { agentId: this.id });
47044
47057
  if (!outputCheck.passed) {
47045
47058
  const filtered = `[Response filtered: ${outputCheck.reason}]`;
47046
- this.memory.appendMessage(sessionId, { role: "assistant", content: filtered });
47059
+ this.memory.appendMessage(sessionId, { role: "assistant", content: filtered, reasoningContent: response.reasoningContent });
47047
47060
  return filtered;
47048
47061
  }
47049
- this.memory.appendMessage(sessionId, { role: "assistant", content: displayReply });
47062
+ this.memory.appendMessage(sessionId, { role: "assistant", content: displayReply, reasoningContent: response.reasoningContent });
47050
47063
  if (!isLightweight && displayReply.length > 50 && senderId) {
47051
47064
  this.memory.writeDailyLog(this.id, `[Chat with ${senderInfo?.name ?? senderId}] Q: ${userMessage.slice(0, 150)}... A: ${displayReply.slice(0, 300)}`);
47052
47065
  }
@@ -47219,7 +47232,8 @@ ${chatYield.item.payload.content}`;
47219
47232
  if (response.finishReason === "max_tokens" && !response.toolCalls?.length) {
47220
47233
  this.memory.appendMessage(this.currentSessionId, {
47221
47234
  role: "assistant",
47222
- content: response.content
47235
+ content: response.content,
47236
+ reasoningContent: response.reasoningContent
47223
47237
  });
47224
47238
  this.memory.appendMessage(this.currentSessionId, {
47225
47239
  role: "user",
@@ -47229,7 +47243,8 @@ ${chatYield.item.payload.content}`;
47229
47243
  this.memory.appendMessage(this.currentSessionId, {
47230
47244
  role: "assistant",
47231
47245
  content: response.content,
47232
- toolCalls: response.toolCalls
47246
+ toolCalls: response.toolCalls,
47247
+ reasoningContent: response.reasoningContent
47233
47248
  });
47234
47249
  const subagentProgressCb = (event) => {
47235
47250
  onEvent({
@@ -47351,10 +47366,10 @@ ${chatYield.item.payload.content}`;
47351
47366
  const outputCheck = await this.guardrails.checkOutput(displayReply, { agentId: this.id });
47352
47367
  if (!outputCheck.passed) {
47353
47368
  const filtered = `[Response filtered: ${outputCheck.reason}]`;
47354
- this.memory.appendMessage(this.currentSessionId, { role: "assistant", content: filtered });
47369
+ this.memory.appendMessage(this.currentSessionId, { role: "assistant", content: filtered, reasoningContent: response.reasoningContent });
47355
47370
  return filtered;
47356
47371
  }
47357
- this.memory.appendMessage(this.currentSessionId, { role: "assistant", content: displayReply });
47372
+ this.memory.appendMessage(this.currentSessionId, { role: "assistant", content: displayReply, reasoningContent: response.reasoningContent });
47358
47373
  if (streamChatActivityId && thinkingBuffer.trim()) {
47359
47374
  this.emitActivityLog(streamChatActivityId, "text", thinkingBuffer, { isThinking: true });
47360
47375
  }
@@ -47637,7 +47652,7 @@ ${chatYield.item.payload.content}`;
47637
47652
  }
47638
47653
  flushText();
47639
47654
  if (response.finishReason === "max_tokens" && !response.toolCalls?.length) {
47640
- this.memory.appendMessage(sessionId, { role: "assistant", content: response.content });
47655
+ this.memory.appendMessage(sessionId, { role: "assistant", content: response.content, reasoningContent: response.reasoningContent });
47641
47656
  this.memory.appendMessage(sessionId, {
47642
47657
  role: "user",
47643
47658
  content: "[Continue from where you left off. Do not repeat what you already said.]"
@@ -47646,7 +47661,8 @@ ${chatYield.item.payload.content}`;
47646
47661
  this.memory.appendMessage(sessionId, {
47647
47662
  role: "assistant",
47648
47663
  content: response.content,
47649
- toolCalls: response.toolCalls
47664
+ toolCalls: response.toolCalls,
47665
+ reasoningContent: response.reasoningContent
47650
47666
  });
47651
47667
  let interruptedDuringTools = false;
47652
47668
  for (const tc of response.toolCalls) {
@@ -47833,7 +47849,7 @@ ${yieldResult.item.payload.content}`
47833
47849
  if (!didSubmitReview && !cancelToken?.cancelled) {
47834
47850
  log17.warn("Task execution ending without task_submit_review \u2014 injecting final reminder", { taskId: taskId2, agentId: this.id });
47835
47851
  flushText();
47836
- this.memory.appendMessage(sessionId, { role: "assistant", content: response.content });
47852
+ this.memory.appendMessage(sessionId, { role: "assistant", content: response.content, reasoningContent: response.reasoningContent });
47837
47853
  this.memory.appendMessage(sessionId, {
47838
47854
  role: "user",
47839
47855
  content: [
@@ -47878,7 +47894,8 @@ ${yieldResult.item.payload.content}`
47878
47894
  this.memory.appendMessage(sessionId, {
47879
47895
  role: "assistant",
47880
47896
  content: response.content,
47881
- toolCalls: response.toolCalls
47897
+ toolCalls: response.toolCalls,
47898
+ reasoningContent: response.reasoningContent
47882
47899
  });
47883
47900
  for (const tc of response.toolCalls) {
47884
47901
  if (cancelToken?.cancelled)
@@ -47910,12 +47927,12 @@ ${yieldResult.item.payload.content}`
47910
47927
  } else {
47911
47928
  flushText();
47912
47929
  const finalReply = stripCompletionMarker(sanitizeLLMReply(response.content));
47913
- this.memory.appendMessage(sessionId, { role: "assistant", content: finalReply });
47930
+ this.memory.appendMessage(sessionId, { role: "assistant", content: finalReply, reasoningContent: response.reasoningContent });
47914
47931
  }
47915
47932
  } else {
47916
47933
  flushText();
47917
47934
  const finalReply = stripCompletionMarker(sanitizeLLMReply(response.content));
47918
- this.memory.appendMessage(sessionId, { role: "assistant", content: finalReply });
47935
+ this.memory.appendMessage(sessionId, { role: "assistant", content: finalReply, reasoningContent: response.reasoningContent });
47919
47936
  }
47920
47937
  emit("status", "execution_finished", {});
47921
47938
  this.metricsCollector.recordTaskCompletion(taskId2, "completed", Date.now() - taskStartMs);
@@ -48054,7 +48071,7 @@ ${yieldResult.item.payload.content}`
48054
48071
  break;
48055
48072
  flushText();
48056
48073
  if (response.finishReason === "max_tokens" && !response.toolCalls?.length) {
48057
- this.memory.appendMessage(sessionId, { role: "assistant", content: response.content });
48074
+ this.memory.appendMessage(sessionId, { role: "assistant", content: response.content, reasoningContent: response.reasoningContent });
48058
48075
  this.memory.appendMessage(sessionId, {
48059
48076
  role: "user",
48060
48077
  content: "[Continue from where you left off. Do not repeat what you already said.]"
@@ -48063,7 +48080,8 @@ ${yieldResult.item.payload.content}`
48063
48080
  this.memory.appendMessage(sessionId, {
48064
48081
  role: "assistant",
48065
48082
  content: response.content,
48066
- toolCalls: response.toolCalls
48083
+ toolCalls: response.toolCalls,
48084
+ reasoningContent: response.reasoningContent
48067
48085
  });
48068
48086
  for (const tc of response.toolCalls) {
48069
48087
  if (this.attentionController.hasInterruptPending()) {
@@ -48117,7 +48135,7 @@ ${yieldResult.item.payload.content}`
48117
48135
  flushText();
48118
48136
  const rawReply = sanitizeLLMReply(response.content);
48119
48137
  const displayReply = stripCompletionMarker(rawReply);
48120
- this.memory.appendMessage(sessionId, { role: "assistant", content: displayReply });
48138
+ this.memory.appendMessage(sessionId, { role: "assistant", content: displayReply, reasoningContent: response.reasoningContent });
48121
48139
  return rawReply;
48122
48140
  } catch (error) {
48123
48141
  if (textBuffer.trim()) {
@@ -48637,7 +48655,7 @@ ${escalationReason}`;
48637
48655
  error: String(error).slice(0, 200),
48638
48656
  delay
48639
48657
  });
48640
- await new Promise((resolve21) => setTimeout(resolve21, delay));
48658
+ await new Promise((resolve20) => setTimeout(resolve20, delay));
48641
48659
  }
48642
48660
  }
48643
48661
  throw lastError;
@@ -48913,7 +48931,7 @@ ${todayLog.slice(0, HEARTBEAT_DAILY_LOG_CHARS)}
48913
48931
  agentId: this.id,
48914
48932
  error: String(error).slice(0, 200)
48915
48933
  });
48916
- await new Promise((resolve21) => setTimeout(resolve21, delay));
48934
+ await new Promise((resolve20) => setTimeout(resolve20, delay));
48917
48935
  }
48918
48936
  }
48919
48937
  }
@@ -49207,7 +49225,7 @@ ${promo.content}` : promo.content;
49207
49225
 
49208
49226
  // ../core/dist/role-loader.js
49209
49227
  import { readFileSync as readFileSync11, existsSync as existsSync16, readdirSync as readdirSync3 } from "node:fs";
49210
- import { join as join11, resolve as resolve9 } from "node:path";
49228
+ import { join as join11, resolve as resolve8 } from "node:path";
49211
49229
  var RoleLoader;
49212
49230
  var init_role_loader = __esm({
49213
49231
  "../core/dist/role-loader.js"() {
@@ -49216,7 +49234,7 @@ var init_role_loader = __esm({
49216
49234
  RoleLoader = class {
49217
49235
  templateDirs;
49218
49236
  constructor(templateDirs) {
49219
- this.templateDirs = templateDirs ?? [resolve9(process.cwd(), "templates", "roles")];
49237
+ this.templateDirs = templateDirs ?? [resolve8(process.cwd(), "templates", "roles")];
49220
49238
  }
49221
49239
  getTemplateDirs() {
49222
49240
  return this.templateDirs;
@@ -49556,7 +49574,7 @@ var init_mcp_client = __esm({
49556
49574
  }
49557
49575
  }
49558
49576
  sendRequest(proc, method, params) {
49559
- return new Promise((resolve21, reject) => {
49577
+ return new Promise((resolve20, reject) => {
49560
49578
  const id = ++this.requestId;
49561
49579
  const message = JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n";
49562
49580
  const timeoutMs = method === "tools/call" ? 12e4 : 3e4;
@@ -49564,7 +49582,7 @@ var init_mcp_client = __esm({
49564
49582
  this.pendingRequests.delete(id);
49565
49583
  reject(new Error(`MCP request timeout for ${method} (id=${id}, ${timeoutMs}ms)`));
49566
49584
  }, timeoutMs);
49567
- this.pendingRequests.set(id, { resolve: resolve21, reject, method, timer, proc });
49585
+ this.pendingRequests.set(id, { resolve: resolve20, reject, method, timer, proc });
49568
49586
  proc.stdin?.write(message);
49569
49587
  });
49570
49588
  }
@@ -52385,11 +52403,11 @@ function createSettingsTools(ctx) {
52385
52403
  },
52386
52404
  base_url: {
52387
52405
  type: "string",
52388
- description: 'Optional base URL for the API (e.g. "https://api.deepseek.com/v1")'
52406
+ description: 'Optional base URL for the API (e.g. "https://api.deepseek.com")'
52389
52407
  },
52390
52408
  model: {
52391
52409
  type: "string",
52392
- description: 'Default model ID (e.g. "deepseek-chat")'
52410
+ description: 'Default model ID (e.g. "deepseek-v4-flash")'
52393
52411
  }
52394
52412
  },
52395
52413
  required: ["name", "model"]
@@ -52514,7 +52532,7 @@ function createSettingsTools(ctx) {
52514
52532
  },
52515
52533
  id: {
52516
52534
  type: "string",
52517
- description: 'Model ID (e.g. "deepseek-chat-v3")'
52535
+ description: 'Model ID (e.g. "deepseek-v4-flash")'
52518
52536
  },
52519
52537
  name: {
52520
52538
  type: "string",
@@ -55477,7 +55495,7 @@ var init_openai = __esm({
55477
55495
  };
55478
55496
  }
55479
55497
  if (m.toolCalls?.length) {
55480
- return {
55498
+ const msg = {
55481
55499
  role: "assistant",
55482
55500
  content: getTextContent(m.content) || null,
55483
55501
  tool_calls: m.toolCalls.map((tc) => ({
@@ -55486,6 +55504,17 @@ var init_openai = __esm({
55486
55504
  function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
55487
55505
  }))
55488
55506
  };
55507
+ if (m.reasoningContent)
55508
+ msg.reasoning_content = m.reasoningContent;
55509
+ return msg;
55510
+ }
55511
+ if (m.role === "assistant" && m.reasoningContent) {
55512
+ const msg = {
55513
+ role: "assistant",
55514
+ content: typeof m.content === "string" ? m.content : getTextContent(m.content),
55515
+ reasoning_content: m.reasoningContent
55516
+ };
55517
+ return msg;
55489
55518
  }
55490
55519
  if (Array.isArray(m.content)) {
55491
55520
  return {
@@ -55497,14 +55526,22 @@ var init_openai = __esm({
55497
55526
  });
55498
55527
  }
55499
55528
  convertTools(tools) {
55500
- return tools.map((t) => ({
55501
- type: "function",
55502
- function: {
55503
- name: t.name,
55504
- description: t.description,
55505
- parameters: t.inputSchema
55506
- }
55507
- }));
55529
+ const seen = /* @__PURE__ */ new Set();
55530
+ const unique = [];
55531
+ for (const t of tools) {
55532
+ if (seen.has(t.name))
55533
+ continue;
55534
+ seen.add(t.name);
55535
+ unique.push({
55536
+ type: "function",
55537
+ function: {
55538
+ name: t.name,
55539
+ description: t.description,
55540
+ parameters: t.inputSchema
55541
+ }
55542
+ });
55543
+ }
55544
+ return unique;
55508
55545
  }
55509
55546
  async chatStream(request, onEvent, signal) {
55510
55547
  const messages = this.convertMessages(request.messages);
@@ -55551,6 +55588,7 @@ var init_openai = __esm({
55551
55588
  throw new Error(`OpenAI API error ${res.status}: ${errText}`);
55552
55589
  }
55553
55590
  let content = "";
55591
+ let reasoningContent = "";
55554
55592
  const toolCalls = /* @__PURE__ */ new Map();
55555
55593
  let finishReason = "end_turn";
55556
55594
  let promptTokens = 0;
@@ -55576,9 +55614,10 @@ var init_openai = __esm({
55576
55614
  try {
55577
55615
  const chunk = JSON.parse(trimmed.slice(6));
55578
55616
  const choice = chunk.choices?.[0];
55579
- const reasoningContent = choice?.delta?.reasoning_details ?? choice?.delta?.thinking;
55580
- if (reasoningContent) {
55581
- onEvent({ type: "thinking_delta", thinking: reasoningContent });
55617
+ const deltaReasoning = choice?.delta?.reasoning_content ?? choice?.delta?.reasoning_details ?? choice?.delta?.thinking;
55618
+ if (deltaReasoning) {
55619
+ reasoningContent += deltaReasoning;
55620
+ onEvent({ type: "thinking_delta", thinking: deltaReasoning });
55582
55621
  }
55583
55622
  if (choice?.delta?.content) {
55584
55623
  content += choice.delta.content;
@@ -55629,12 +55668,15 @@ var init_openai = __esm({
55629
55668
  });
55630
55669
  const usage = { inputTokens: promptTokens, outputTokens: completionTokens };
55631
55670
  onEvent({ type: "message_end", usage, finishReason });
55632
- return {
55671
+ const streamResult = {
55633
55672
  content,
55634
55673
  toolCalls: resultToolCalls.length ? resultToolCalls : void 0,
55635
55674
  usage,
55636
55675
  finishReason
55637
55676
  };
55677
+ if (reasoningContent)
55678
+ streamResult.reasoningContent = reasoningContent;
55679
+ return streamResult;
55638
55680
  }
55639
55681
  convertResponse(data) {
55640
55682
  const choice = data.choices[0];
@@ -55651,7 +55693,7 @@ var init_openai = __esm({
55651
55693
  tool_calls: "tool_use",
55652
55694
  length: "max_tokens"
55653
55695
  };
55654
- return {
55696
+ const result = {
55655
55697
  content: typeof msg.content === "string" ? msg.content : "",
55656
55698
  toolCalls: toolCalls?.length ? toolCalls : void 0,
55657
55699
  usage: {
@@ -55660,6 +55702,9 @@ var init_openai = __esm({
55660
55702
  },
55661
55703
  finishReason: finishMap[choice.finish_reason] ?? "end_turn"
55662
55704
  };
55705
+ if (msg.reasoning_content)
55706
+ result.reasoningContent = msg.reasoning_content;
55707
+ return result;
55663
55708
  }
55664
55709
  };
55665
55710
  }
@@ -56393,7 +56438,7 @@ var init_oauth_manager = __esm({
56393
56438
  const state = randomBytes2(16).toString("hex");
56394
56439
  const port = config.callbackPort ?? 1455;
56395
56440
  const redirectUri = `http://localhost:${port}/auth/callback`;
56396
- const promise = new Promise((resolve21, reject) => {
56441
+ const promise = new Promise((resolve20, reject) => {
56397
56442
  const pending = {
56398
56443
  provider,
56399
56444
  state,
@@ -56402,7 +56447,7 @@ var init_oauth_manager = __esm({
56402
56447
  redirectUri,
56403
56448
  resolve: (tokens) => {
56404
56449
  const profile = this.profileStore.createOAuthProfile(provider, tokens, `${provider} (${tokens.accountId ?? "OAuth"})`);
56405
- resolve21(profile);
56450
+ resolve20(profile);
56406
56451
  },
56407
56452
  reject
56408
56453
  };
@@ -56758,7 +56803,7 @@ var init_router = __esm({
56758
56803
  */
56759
56804
  static isNonRetryableError(error) {
56760
56805
  const msg = error instanceof Error ? error.message : String(error);
56761
- return /\b(402|403|401)\b/.test(msg) || /insufficient balance/i.test(msg) || /not available in your region/i.test(msg) || /invalid.*api.*key/i.test(msg) || /authentication/i.test(msg);
56806
+ return /\b(401|402|403)\b/.test(msg) || /insufficient balance/i.test(msg) || /not available in your region/i.test(msg) || /invalid.*api.*key/i.test(msg) || /authentication/i.test(msg) || /\b400\b.*invalid_request_error/i.test(msg) || /reasoning_content.*must be passed back/i.test(msg);
56762
56807
  }
56763
56808
  /** Detect rate-limit (429) errors which should use a shorter circuit breaker cooldown. */
56764
56809
  static isRateLimitError(error) {
@@ -56971,14 +57016,25 @@ var init_router = __esm({
56971
57016
  return "simple";
56972
57017
  }
56973
57018
  selectProvider(request, explicit) {
56974
- if (explicit)
57019
+ if (explicit && this.isAvailable(explicit))
56975
57020
  return explicit;
57021
+ if (explicit && this.disabledProviders.has(explicit)) {
57022
+ log36.warn(`Explicit provider ${explicit} is disabled \u2014 falling through to auto-select`);
57023
+ }
56976
57024
  if (!this.autoSelect || this.providerTiers.length === 0) {
56977
57025
  if (this.isAvailable(this.defaultProvider) && this.providers.has(this.defaultProvider)) {
56978
57026
  return this.defaultProvider;
56979
57027
  }
56980
57028
  const healthy2 = [...this.providers.keys()].find((n) => this.isAvailable(n));
56981
- return healthy2 ?? this.defaultProvider;
57029
+ if (healthy2)
57030
+ return healthy2;
57031
+ const enabledAny2 = [...this.providers.keys()].find((n) => !this.disabledProviders.has(n));
57032
+ if (enabledAny2) {
57033
+ log36.warn(`All providers degraded \u2014 using enabled provider ${enabledAny2} as last resort`);
57034
+ return enabledAny2;
57035
+ }
57036
+ log36.warn("All providers disabled or degraded \u2014 using default as last resort");
57037
+ return this.defaultProvider;
56982
57038
  }
56983
57039
  const complexity = _LLMRouter.assessComplexity(request);
56984
57040
  const match = this.providerTiers.find((t) => t.complexity.includes(complexity) && this.providers.has(t.name) && this.isAvailable(t.name));
@@ -56991,7 +57047,12 @@ var init_router = __esm({
56991
57047
  log36.warn(`All tiered providers degraded for complexity=${complexity}, falling back to: ${healthy}`);
56992
57048
  return healthy;
56993
57049
  }
56994
- log36.warn("All providers degraded \u2014 using default as last resort");
57050
+ const enabledAny = [...this.providers.keys()].find((n) => !this.disabledProviders.has(n));
57051
+ if (enabledAny) {
57052
+ log36.warn(`All providers degraded \u2014 using enabled provider ${enabledAny} as last resort`);
57053
+ return enabledAny;
57054
+ }
57055
+ log36.warn("All providers disabled or degraded \u2014 using default as last resort");
56995
57056
  return this.defaultProvider;
56996
57057
  }
56997
57058
  getFallbacks(primary) {
@@ -57280,7 +57341,7 @@ var init_router = __esm({
57280
57341
  for (const [name, p] of this.providers.entries()) {
57281
57342
  providers[name] = { model: p.model, configured: true };
57282
57343
  }
57283
- for (const name of ["anthropic", "openai", "openai-codex", "google", "ollama", "minimax", "siliconflow", "openrouter", "zai"]) {
57344
+ for (const name of ["anthropic", "openai", "openai-codex", "google", "ollama", "minimax", "siliconflow", "openrouter", "zai", "deepseek"]) {
57284
57345
  if (!providers[name]) {
57285
57346
  providers[name] = { model: "", configured: false };
57286
57347
  }
@@ -57312,7 +57373,7 @@ var init_router = __esm({
57312
57373
  oauthAccountId: oauthProfile?.oauth?.accountId
57313
57374
  };
57314
57375
  }
57315
- for (const name of ["anthropic", "openai", "openai-codex", "google", "ollama", "minimax", "siliconflow", "openrouter", "zai"]) {
57376
+ for (const name of ["anthropic", "openai", "openai-codex", "google", "ollama", "minimax", "siliconflow", "openrouter", "zai", "deepseek"]) {
57316
57377
  if (!providers[name]) {
57317
57378
  const oauthProfile = this._profileStore?.getDefaultProfile(name);
57318
57379
  const builtinModels = BUILTIN_MODEL_CATALOG.filter((m) => m.provider === name);
@@ -57367,6 +57428,13 @@ var init_router = __esm({
57367
57428
  this.disabledProviders.delete(providerName);
57368
57429
  } else {
57369
57430
  this.disabledProviders.add(providerName);
57431
+ if (this.defaultProvider === providerName) {
57432
+ const replacement = [...this.providers.keys()].find((n) => !this.disabledProviders.has(n));
57433
+ if (replacement) {
57434
+ log36.info(`Default provider ${providerName} disabled \u2014 switching default to ${replacement}`);
57435
+ this.defaultProvider = replacement;
57436
+ }
57437
+ }
57370
57438
  }
57371
57439
  log36.info(`Provider ${providerName} ${enabled ? "enabled" : "disabled"}`);
57372
57440
  }
@@ -57479,7 +57547,8 @@ var init_router = __esm({
57479
57547
  siliconflow: "SiliconFlow",
57480
57548
  minimax: "MiniMax",
57481
57549
  openrouter: "OpenRouter",
57482
- zai: "ZAI"
57550
+ zai: "ZAI",
57551
+ deepseek: "DeepSeek"
57483
57552
  };
57484
57553
  BUILTIN_MODEL_CATALOG = [
57485
57554
  // Anthropic — https://docs.anthropic.com/claude/reference/input-and-output-sizes
@@ -57503,7 +57572,12 @@ var init_router = __esm({
57503
57572
  { id: "xiaomi/mimo-v2-pro", name: "MiMo-V2-Pro", provider: "openrouter", contextWindow: 1048576, maxOutputTokens: 131072, cost: { input: 1, output: 3, cacheRead: 0.2 }, reasoning: true, inputTypes: ["text"] },
57504
57573
  { id: "anthropic/claude-opus-4-6", name: "Claude Opus 4.6 (via OpenRouter)", provider: "openrouter", contextWindow: 1e6, maxOutputTokens: 128e3, cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, reasoning: true, inputTypes: ["text", "image"] },
57505
57574
  { id: "openai/gpt-5.4", name: "GPT-5.4 (via OpenRouter)", provider: "openrouter", contextWindow: 11e5, maxOutputTokens: 128e3, cost: { input: 2.5, output: 15, cacheRead: 0.25 }, reasoning: true, inputTypes: ["text", "image"] },
57506
- { id: "google/gemini-3-1-pro", name: "Gemini 3.1 Pro (via OpenRouter)", provider: "openrouter", contextWindow: 1e6, maxOutputTokens: 65536, cost: { input: 2, output: 12 }, reasoning: true, inputTypes: ["text", "image"] }
57575
+ { id: "google/gemini-3-1-pro", name: "Gemini 3.1 Pro (via OpenRouter)", provider: "openrouter", contextWindow: 1e6, maxOutputTokens: 65536, cost: { input: 2, output: 12 }, reasoning: true, inputTypes: ["text", "image"] },
57576
+ // DeepSeek — https://api-docs.deepseek.com/
57577
+ { id: "deepseek-v4-flash", name: "DeepSeek-V4-Flash", provider: "deepseek", contextWindow: 1e6, maxOutputTokens: 384e3, cost: { input: 0.14, output: 0.28, cacheRead: 0.028 }, reasoning: true, inputTypes: ["text"] },
57578
+ { id: "deepseek-v4-pro", name: "DeepSeek-V4-Pro", provider: "deepseek", contextWindow: 1e6, maxOutputTokens: 384e3, cost: { input: 1.67, output: 3.33, cacheRead: 0.14 }, reasoning: true, inputTypes: ["text"] },
57579
+ { id: "deepseek-chat", name: "DeepSeek-Chat (legacy)", provider: "deepseek", contextWindow: 65536, maxOutputTokens: 8192, cost: { input: 0.14, output: 0.28, cacheRead: 0.028 }, reasoning: false, inputTypes: ["text"] },
57580
+ { id: "deepseek-reasoner", name: "DeepSeek-Reasoner (legacy)", provider: "deepseek", contextWindow: 65536, maxOutputTokens: 8192, cost: { input: 0.55, output: 2.19, cacheRead: 0.14 }, reasoning: true, inputTypes: ["text"] }
57507
57581
  ];
57508
57582
  }
57509
57583
  });
@@ -58364,7 +58438,7 @@ var init_registry = __esm({
58364
58438
 
58365
58439
  // ../core/dist/skills/loader.js
58366
58440
  import { readFileSync as readFileSync15, readdirSync as readdirSync5, existsSync as existsSync20 } from "node:fs";
58367
- import { join as join16, resolve as resolve10 } from "node:path";
58441
+ import { join as join16, resolve as resolve9 } from "node:path";
58368
58442
  function resolveMcpServerPaths(servers, skillDir) {
58369
58443
  if (!servers)
58370
58444
  return void 0;
@@ -59330,7 +59404,7 @@ var init_composition = __esm({
59330
59404
 
59331
59405
  // ../core/dist/workflow/team-template.js
59332
59406
  import { readdirSync as readdirSync7, readFileSync as readFileSync17, existsSync as existsSync22 } from "node:fs";
59333
- import { join as join18, resolve as resolve11, dirname as dirname5 } from "node:path";
59407
+ import { join as join18, resolve as resolve10, dirname as dirname5 } from "node:path";
59334
59408
  import { fileURLToPath as fileURLToPath3 } from "node:url";
59335
59409
  function loadTeamTemplateFromDir(dirPath) {
59336
59410
  const fsHelper = { existsSync: existsSync22, readFileSync: (p, _enc) => readFileSync17(p, "utf-8"), join: join18 };
@@ -59371,16 +59445,16 @@ function createDefaultTeamTemplates() {
59371
59445
  const thisFile = fileURLToPath3(import.meta.url);
59372
59446
  const thisDir = dirname5(thisFile);
59373
59447
  const candidates = [
59374
- resolve11(thisDir, "..", "templates", "teams"),
59448
+ resolve10(thisDir, "..", "templates", "teams"),
59375
59449
  // npm global: dist/ → ../templates/teams
59376
- resolve11(thisDir, "..", "..", "..", "..", "templates", "teams"),
59450
+ resolve10(thisDir, "..", "..", "..", "..", "templates", "teams"),
59377
59451
  // monorepo: packages/core/dist/workflow/ → root
59378
- resolve11(process.cwd(), "templates", "teams")
59452
+ resolve10(process.cwd(), "templates", "teams")
59379
59453
  // cwd fallback
59380
59454
  ];
59381
59455
  templatesDir = candidates.find((d) => existsSync22(d)) ?? candidates[candidates.length - 1];
59382
59456
  } catch {
59383
- templatesDir = resolve11(process.cwd(), "templates", "teams");
59457
+ templatesDir = resolve10(process.cwd(), "templates", "teams");
59384
59458
  }
59385
59459
  if (!existsSync22(templatesDir)) {
59386
59460
  log47.warn(`Team templates directory not found: ${templatesDir}`);
@@ -60405,7 +60479,7 @@ var init_org_service = __esm({
60405
60479
 
60406
60480
  // ../org-manager/dist/task-service.js
60407
60481
  import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync14, readFileSync as readFileSync18, existsSync as existsSync24, cpSync } from "node:fs";
60408
- import { join as join20, resolve as resolve12 } from "node:path";
60482
+ import { join as join20, resolve as resolve11 } from "node:path";
60409
60483
  import { homedir as homedir11 } from "node:os";
60410
60484
  function formatLocalTimestamp(d = /* @__PURE__ */ new Date()) {
60411
60485
  const pad = (n) => String(n).padStart(2, "0");
@@ -60806,6 +60880,10 @@ var init_task_service = __esm({
60806
60880
  const lower = errorContent.toLowerCase();
60807
60881
  return lower.includes("econnreset") || lower.includes("econnrefused") || lower.includes("etimedout") || lower.includes("fetch failed") || lower.includes("aborterror") || lower.includes("aborted") || lower.includes("socket hang up") || lower.includes("network");
60808
60882
  }
60883
+ static isNonRetryableError(errorContent) {
60884
+ const lower = errorContent.toLowerCase();
60885
+ return lower.includes("invalid_request_error") && /\b400\b/.test(errorContent) || lower.includes("reasoning_content") || lower.includes("invalid api key") || lower.includes("insufficient balance") || /\b(401|402|403)\b/.test(errorContent) && !lower.includes("rate");
60886
+ }
60809
60887
  shouldRetryTask(taskId2, errorContent, retryAttempt, cancelled) {
60810
60888
  if (cancelled)
60811
60889
  return { shouldRetry: false, reason: "cancelled" };
@@ -60816,6 +60894,9 @@ var init_task_service = __esm({
60816
60894
  if (retryAttempt >= _TaskService.MAX_IN_PROGRESS_RETRIES) {
60817
60895
  return { shouldRetry: false, reason: `exceeded max retries (${_TaskService.MAX_IN_PROGRESS_RETRIES})` };
60818
60896
  }
60897
+ if (_TaskService.isNonRetryableError(errorContent)) {
60898
+ return { shouldRetry: false, reason: "non-retryable error (auth/billing/request)" };
60899
+ }
60819
60900
  const normalizedError = errorContent.replace(/\d{4}-\d{2}-\d{2}T[\d:.]+Z?/g, "").trim().slice(0, 200);
60820
60901
  const tracker = this.taskRetryErrors.get(taskId2);
60821
60902
  if (tracker && tracker.lastError === normalizedError) {
@@ -61785,7 +61866,7 @@ ${c.content}`;
61785
61866
  });
61786
61867
  if (this.hitlService && request.createdBy && request.createdBy !== "default") {
61787
61868
  this.hitlService.notify({
61788
- targetUserId: "default",
61869
+ targetUserId: "all",
61789
61870
  type: "task_created",
61790
61871
  title: `Task created: ${task.title}`,
61791
61872
  body: `Agent created task "${task.title}"`,
@@ -62052,7 +62133,7 @@ Action: ${guidance}` : ""
62052
62133
  const notifType = to === "completed" ? "task_completed" : to === "review" ? "task_review" : "task_failed";
62053
62134
  const priority = to === "failed" ? "high" : "normal";
62054
62135
  this.hitlService.notify({
62055
- targetUserId: "default",
62136
+ targetUserId: "all",
62056
62137
  type: notifType,
62057
62138
  title: to === "review" ? `Task ready for review: ${task.title}` : to === "completed" ? `Task completed: ${task.title}` : `Task failed: ${task.title}`,
62058
62139
  body: `Task "${task.title}" status changed to ${to}`,
@@ -62825,8 +62906,9 @@ Action: ${guidance}` : ""
62825
62906
  };
62826
62907
  writeFileSync14(join20(taskSharedDir, "manifest.json"), JSON.stringify(manifest, null, 2));
62827
62908
  for (const d of deliverables) {
62909
+ let src;
62828
62910
  if (d.type === "file" && d.reference) {
62829
- const src = resolve12(d.reference);
62911
+ src = resolve11(d.reference);
62830
62912
  if (existsSync24(src)) {
62831
62913
  try {
62832
62914
  const destName = src.split("/").pop() ?? "deliverable";
@@ -62836,8 +62918,9 @@ Action: ${guidance}` : ""
62836
62918
  }
62837
62919
  }
62838
62920
  }
62839
- if (d.type === "file" && d.summary && !existsSync24(d.reference)) {
62840
- const safeName = d.reference.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
62921
+ if (d.type === "file" && d.summary && src && !existsSync24(src)) {
62922
+ const baseName = d.reference.split("/").pop() ?? "deliverable";
62923
+ const safeName = baseName.replace(/[^a-zA-Z0-9_\u4e00-\u9fff.-]/g, "_").slice(0, 80);
62841
62924
  writeFileSync14(join20(taskSharedDir, `${safeName}.md`), d.summary);
62842
62925
  }
62843
62926
  }
@@ -64619,7 +64702,7 @@ var init_sse_handler = __esm({
64619
64702
  });
64620
64703
 
64621
64704
  // ../org-manager/dist/skill-service.js
64622
- import { join as join22, resolve as resolve13 } from "node:path";
64705
+ import { join as join22, resolve as resolve12 } from "node:path";
64623
64706
  import { existsSync as existsSync26, writeFileSync as writeFileSync16, mkdirSync as mkdirSync18, readFileSync as readFileSync20, readdirSync as readdirSync9, copyFileSync as copyFileSync3 } from "node:fs";
64624
64707
  import { homedir as homedir13 } from "node:os";
64625
64708
  import { execSync as execSync2 } from "node:child_process";
@@ -64754,7 +64837,7 @@ async function installSkill(request, skillRegistry) {
64754
64837
  let installed = false;
64755
64838
  let installMethod = "metadata-only";
64756
64839
  if (source === "builtin") {
64757
- const builtinDir = resolve13(process.cwd(), "templates", "skills", safeName);
64840
+ const builtinDir = resolve12(process.cwd(), "templates", "skills", safeName);
64758
64841
  if (existsSync26(builtinDir)) {
64759
64842
  mkdirSync18(targetDir, { recursive: true });
64760
64843
  for (const file of readdirSync9(builtinDir)) {
@@ -64898,7 +64981,7 @@ var init_skill_service = __esm({
64898
64981
 
64899
64982
  // ../org-manager/dist/api-server.js
64900
64983
  import { createServer as createServer2 } from "node:http";
64901
- import { join as join23, resolve as resolve14, dirname as dirname6 } from "node:path";
64984
+ import { join as join23, resolve as resolve13, dirname as dirname6 } from "node:path";
64902
64985
  import { readdirSync as readdirSync10, readFileSync as readFileSync21, existsSync as existsSync27, writeFileSync as writeFileSync17, mkdirSync as mkdirSync19, rmSync as rmSync3, statSync as statSync5 } from "node:fs";
64903
64986
  import { homedir as homedir14 } from "node:os";
64904
64987
  import { execSync as execSync3 } from "node:child_process";
@@ -68687,7 +68770,7 @@ EXPLANATION_END`;
68687
68770
  return;
68688
68771
  }
68689
68772
  if (path === "/api/skills/builtin" && req.method === "GET") {
68690
- const builtinDir = resolve14(process.cwd(), "templates", "skills");
68773
+ const builtinDir = resolve13(process.cwd(), "templates", "skills");
68691
68774
  const found = discoverSkillsInDir(builtinDir);
68692
68775
  const installedSkills = new Map((this.skillRegistry?.list() ?? []).map((s) => [s.name, s]));
68693
68776
  const skills = found.map(({ manifest, path: p }) => {
@@ -69756,10 +69839,10 @@ EXPLANATION_END`;
69756
69839
  if (path === "/api/templates/teams" && req.method === "GET") {
69757
69840
  try {
69758
69841
  const { readdirSync: readdirSync13, readFileSync: readFileSync27 } = await import("node:fs");
69759
- const { resolve: resolve21 } = await import("node:path");
69760
- const teamsDir = resolve21(process.cwd(), "templates", "teams");
69842
+ const { resolve: resolve20 } = await import("node:path");
69843
+ const teamsDir = resolve20(process.cwd(), "templates", "teams");
69761
69844
  const files = readdirSync13(teamsDir).filter((f) => f.endsWith(".json"));
69762
- const teams = files.map((f) => JSON.parse(readFileSync27(resolve21(teamsDir, f), "utf-8")));
69845
+ const teams = files.map((f) => JSON.parse(readFileSync27(resolve20(teamsDir, f), "utf-8")));
69763
69846
  this.json(res, 200, { templates: teams });
69764
69847
  } catch {
69765
69848
  this.json(res, 200, { templates: [] });
@@ -70310,7 +70393,9 @@ EXPLANATION_END`;
70310
70393
  return;
70311
70394
  }
70312
70395
  try {
70396
+ const prevDefault = this.llmRouter.getSettings().defaultProvider;
70313
70397
  this.llmRouter.setProviderEnabled(providerName, enabled);
70398
+ const newDefault = this.llmRouter.getSettings().defaultProvider;
70314
70399
  try {
70315
70400
  const { loadConfig: loadCfg } = await Promise.resolve().then(() => (init_dist(), dist_exports));
70316
70401
  const currentConfig = loadCfg(this.markusConfigPath);
@@ -70320,7 +70405,11 @@ EXPLANATION_END`;
70320
70405
  } else {
70321
70406
  providers[providerName] = { enabled };
70322
70407
  }
70323
- saveConfig({ llm: { providers } }, this.markusConfigPath);
70408
+ const configUpdates = { llm: { providers } };
70409
+ if (prevDefault !== newDefault) {
70410
+ configUpdates.llm.defaultProvider = newDefault;
70411
+ }
70412
+ saveConfig(configUpdates, this.markusConfigPath);
70324
70413
  } catch (e) {
70325
70414
  log57.warn("Failed to persist provider enabled state", { error: String(e) });
70326
70415
  }
@@ -70330,6 +70419,70 @@ EXPLANATION_END`;
70330
70419
  }
70331
70420
  return;
70332
70421
  }
70422
+ if (path.match(/^\/api\/settings\/llm\/providers\/[^/]+\/test$/) && req.method === "POST") {
70423
+ const auth = await this.requireAuth(req, res);
70424
+ if (!auth)
70425
+ return;
70426
+ if (!this.llmRouter) {
70427
+ this.json(res, 503, { error: "LLM router not available" });
70428
+ return;
70429
+ }
70430
+ const providerName = path.split("/")[5];
70431
+ const provider = this.llmRouter.getProvider(providerName);
70432
+ if (!provider) {
70433
+ this.json(res, 404, { ok: false, error: `Provider "${providerName}" not found or not configured` });
70434
+ return;
70435
+ }
70436
+ try {
70437
+ const startMs = Date.now();
70438
+ const response = await this.llmRouter.chat({
70439
+ messages: [{ role: "user", content: "Reply with exactly one word: hello" }],
70440
+ maxTokens: 32,
70441
+ temperature: 0
70442
+ }, providerName);
70443
+ const durationMs = Date.now() - startMs;
70444
+ const reply = (response.content ?? "").trim();
70445
+ if (!reply) {
70446
+ this.json(res, 200, {
70447
+ ok: false,
70448
+ error: "Model returned empty response \u2014 API key or model may be misconfigured",
70449
+ model: provider.model,
70450
+ durationMs
70451
+ });
70452
+ } else {
70453
+ this.json(res, 200, {
70454
+ ok: true,
70455
+ durationMs,
70456
+ model: provider.model,
70457
+ reply: reply.slice(0, 100),
70458
+ usage: response.usage
70459
+ });
70460
+ }
70461
+ } catch (err) {
70462
+ const raw = String(err);
70463
+ const statusMatch = raw.match(/(?:API error|status)\s+(\d{3})/i);
70464
+ const errorCode = statusMatch ? Number(statusMatch[1]) : void 0;
70465
+ let errorMsg = raw.replace(/^Error:\s*/, "");
70466
+ const jsonStart = errorMsg.indexOf("{");
70467
+ if (jsonStart >= 0) {
70468
+ try {
70469
+ const jsonStr = errorMsg.slice(jsonStart);
70470
+ const parsed = JSON.parse(jsonStr);
70471
+ if (parsed.error?.message) {
70472
+ errorMsg = `[${parsed.error.type ?? parsed.error.code ?? errorCode ?? "error"}] ${parsed.error.message}`;
70473
+ }
70474
+ } catch {
70475
+ }
70476
+ }
70477
+ this.json(res, 200, {
70478
+ ok: false,
70479
+ error: errorMsg.slice(0, 500),
70480
+ errorCode,
70481
+ model: provider.model
70482
+ });
70483
+ }
70484
+ return;
70485
+ }
70333
70486
  if (path === "/api/settings/env-models" && req.method === "GET") {
70334
70487
  const auth = await this.requireAuth(req, res);
70335
70488
  if (!auth)
@@ -70341,7 +70494,8 @@ EXPLANATION_END`;
70341
70494
  { provider: "siliconflow", displayName: "SiliconFlow", keyEnv: "SILICONFLOW_API_KEY", modelEnv: "SILICONFLOW_MODEL", baseUrlEnv: "SILICONFLOW_BASE_URL", defaultModel: "Qwen/Qwen3.5-35B-A3B", defaultBaseUrl: "https://api.siliconflow.cn/v1" },
70342
70495
  { provider: "minimax", displayName: "MiniMax", keyEnv: "MINIMAX_API_KEY", modelEnv: "MINIMAX_MODEL", baseUrlEnv: "MINIMAX_BASE_URL", defaultModel: "MiniMax-M2.7", defaultBaseUrl: "https://api.minimax.io/v1" },
70343
70496
  { provider: "openrouter", displayName: "OpenRouter", keyEnv: "OPENROUTER_API_KEY", modelEnv: "OPENROUTER_MODEL", baseUrlEnv: "OPENROUTER_BASE_URL", defaultModel: "xiaomi/mimo-v2-pro", defaultBaseUrl: "https://openrouter.ai/api/v1" },
70344
- { provider: "zai", displayName: "ZAI", keyEnv: "ZAI_API_KEY", modelEnv: "ZAI_MODEL", baseUrlEnv: "ZAI_BASE_URL", defaultModel: "glm-5.1", defaultBaseUrl: "https://api.z.ai/api/paas/v4" }
70497
+ { provider: "zai", displayName: "ZAI", keyEnv: "ZAI_API_KEY", modelEnv: "ZAI_MODEL", baseUrlEnv: "ZAI_BASE_URL", defaultModel: "glm-5.1", defaultBaseUrl: "https://api.z.ai/api/paas/v4" },
70498
+ { provider: "deepseek", displayName: "DeepSeek", keyEnv: "DEEPSEEK_API_KEY", modelEnv: "DEEPSEEK_MODEL", baseUrlEnv: "DEEPSEEK_BASE_URL", defaultModel: "deepseek-v4-flash", defaultBaseUrl: "https://api.deepseek.com" }
70345
70499
  ];
70346
70500
  const detected = [];
70347
70501
  for (const def of ENV_MODEL_MAP) {
@@ -70394,7 +70548,9 @@ EXPLANATION_END`;
70394
70548
  google: "GOOGLE_API_KEY",
70395
70549
  siliconflow: "SILICONFLOW_API_KEY",
70396
70550
  minimax: "MINIMAX_API_KEY",
70397
- openrouter: "OPENROUTER_API_KEY"
70551
+ openrouter: "OPENROUTER_API_KEY",
70552
+ zai: "ZAI_API_KEY",
70553
+ deepseek: "DEEPSEEK_API_KEY"
70398
70554
  };
70399
70555
  const apiKey = process.env[envKeyMap[pu.provider] ?? ""];
70400
70556
  if (!apiKey)
@@ -71013,14 +71169,14 @@ EXPLANATION_END`;
71013
71169
  return;
71014
71170
  }
71015
71171
  try {
71016
- const { resolve: resolve21, extname } = await import("node:path");
71172
+ const { resolve: resolve20, extname } = await import("node:path");
71017
71173
  const { existsSync: existsSync36, statSync: statSync6 } = await import("node:fs");
71018
71174
  const results = {};
71019
71175
  const mdExts = [".md", ".markdown"];
71020
71176
  const imageExts = [".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"];
71021
71177
  for (const p of paths.slice(0, 50)) {
71022
71178
  try {
71023
- const resolved = resolve21(p);
71179
+ const resolved = resolve20(p);
71024
71180
  if (!existsSync36(resolved)) {
71025
71181
  results[p] = { exists: false, isFile: false, type: "unknown" };
71026
71182
  continue;
@@ -71053,9 +71209,9 @@ EXPLANATION_END`;
71053
71209
  return;
71054
71210
  }
71055
71211
  try {
71056
- const { resolve: resolve21, extname } = await import("node:path");
71212
+ const { resolve: resolve20, extname } = await import("node:path");
71057
71213
  const { readFileSync: readFileSync27, existsSync: existsSync36, statSync: statSync6 } = await import("node:fs");
71058
- const resolved = resolve21(filePath);
71214
+ const resolved = resolve20(filePath);
71059
71215
  if (!existsSync36(resolved)) {
71060
71216
  this.json(res, 404, { error: "File not found" });
71061
71217
  return;
@@ -71103,10 +71259,10 @@ EXPLANATION_END`;
71103
71259
  return;
71104
71260
  }
71105
71261
  try {
71106
- const { resolve: resolve21, dirname: dirname11 } = await import("node:path");
71262
+ const { resolve: resolve20, dirname: dirname11 } = await import("node:path");
71107
71263
  const { existsSync: existsSync36, statSync: statSync6 } = await import("node:fs");
71108
71264
  const { exec: exec2 } = await import("node:child_process");
71109
- const resolved = resolve21(filePath);
71265
+ const resolved = resolve20(filePath);
71110
71266
  if (!existsSync36(resolved)) {
71111
71267
  this.json(res, 404, { error: "Path not found" });
71112
71268
  return;
@@ -71836,14 +71992,14 @@ EXPLANATION_END`;
71836
71992
  res.end(JSON.stringify(data));
71837
71993
  }
71838
71994
  readBody(req) {
71839
- return new Promise((resolve21, reject) => {
71995
+ return new Promise((resolve20, reject) => {
71840
71996
  const chunks = [];
71841
71997
  req.on("data", (chunk) => chunks.push(chunk));
71842
71998
  req.on("end", () => {
71843
71999
  try {
71844
- resolve21(JSON.parse(Buffer.concat(chunks).toString()));
72000
+ resolve20(JSON.parse(Buffer.concat(chunks).toString()));
71845
72001
  } catch {
71846
- resolve21({});
72002
+ resolve20({});
71847
72003
  }
71848
72004
  });
71849
72005
  req.on("error", reject);
@@ -72153,7 +72309,7 @@ var init_hitl_service = __esm({
72153
72309
  this.persistApproval(approval);
72154
72310
  log58.info(`Approval requested: ${id} by ${opts.agentName}`);
72155
72311
  this.notify({
72156
- targetUserId: opts.targetUserId ?? "default",
72312
+ targetUserId: opts.targetUserId ?? "all",
72157
72313
  type: "approval_request",
72158
72314
  title: `Approval needed: ${opts.title}`,
72159
72315
  body: opts.description,
@@ -72166,13 +72322,13 @@ var init_hitl_service = __esm({
72166
72322
  }
72167
72323
  async requestApprovalAndWait(opts) {
72168
72324
  const approval = this.requestApproval(opts);
72169
- return new Promise((resolve21) => {
72170
- this.pendingResolvers.set(approval.id, resolve21);
72325
+ return new Promise((resolve20) => {
72326
+ this.pendingResolvers.set(approval.id, resolve20);
72171
72327
  if (opts.expiresInMs) {
72172
72328
  setTimeout(() => {
72173
72329
  if (this.pendingResolvers.has(approval.id)) {
72174
72330
  this.pendingResolvers.delete(approval.id);
72175
- resolve21({ approved: false, comment: "Approval timed out" });
72331
+ resolve20({ approved: false, comment: "Approval timed out" });
72176
72332
  }
72177
72333
  }, opts.expiresInMs);
72178
72334
  }
@@ -72202,10 +72358,10 @@ var init_hitl_service = __esm({
72202
72358
  } catch {
72203
72359
  }
72204
72360
  }
72205
- const resolve21 = this.pendingResolvers.get(id);
72206
- if (resolve21) {
72361
+ const resolve20 = this.pendingResolvers.get(id);
72362
+ if (resolve20) {
72207
72363
  this.pendingResolvers.delete(id);
72208
- resolve21({ approved, comment, selectedOption });
72364
+ resolve20({ approved, comment, selectedOption });
72209
72365
  }
72210
72366
  return approval;
72211
72367
  }
@@ -72921,7 +73077,7 @@ var init_requirement_service = __esm({
72921
73077
  title: `Requirement approval: ${req.title}`,
72922
73078
  description: `Agent "${req.createdBy}" proposed requirement "${req.title}" (priority: ${req.priority}).`,
72923
73079
  details: { requirementId: req.id, priority: req.priority },
72924
- targetUserId: "default"
73080
+ targetUserId: "all"
72925
73081
  }).then((result) => {
72926
73082
  const current = this.requirements.get(req.id);
72927
73083
  if (!current || current.status !== "pending")
@@ -73054,7 +73210,7 @@ var init_requirement_service = __esm({
73054
73210
  title: `Requirement approval (resubmitted): ${req.title}`,
73055
73211
  description: `Agent "${req.createdBy}" resubmitted requirement "${req.title}" (priority: ${req.priority}).`,
73056
73212
  details: { requirementId: req.id, priority: req.priority },
73057
- targetUserId: "default"
73213
+ targetUserId: "all"
73058
73214
  }).then((result) => {
73059
73215
  const current = this.requirements.get(req.id);
73060
73216
  if (!current || current.status !== "pending")
@@ -73373,7 +73529,7 @@ var init_requirement_service = __esm({
73373
73529
  const title = decision === "approved" ? `Requirement approved: ${req.title}` : `Requirement rejected: ${req.title}`;
73374
73530
  const body = decision === "approved" ? `Requirement "${req.title}" has been approved and is now in progress.` : `Requirement "${req.title}" has been rejected.${reason ? ` Reason: ${reason}` : ""}`;
73375
73531
  this.hitlService.notify({
73376
- targetUserId: "default",
73532
+ targetUserId: "all",
73377
73533
  type: "requirement_decision",
73378
73534
  title,
73379
73535
  body,
@@ -77197,8 +77353,8 @@ CREATE INDEX IF NOT EXISTS idx_group_chat_members_group ON group_chat_members(gr
77197
77353
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(n.id, n.userId, n.type, n.title, n.body, n.priority, n.read ? 1 : 0, n.actionType, n.actionTarget, n.metadata ? JSON.stringify(n.metadata) : null, n.createdAt);
77198
77354
  }
77199
77355
  list(userId, opts) {
77200
- const conditions = ["(user_id = ? OR user_id = ?)"];
77201
- const params = [userId, "all"];
77356
+ const conditions = ["(user_id = ? OR user_id = ? OR user_id = ?)"];
77357
+ const params = [userId, "all", "default"];
77202
77358
  if (opts?.unreadOnly) {
77203
77359
  conditions.push("read = 0");
77204
77360
  }
@@ -77213,8 +77369,8 @@ CREATE INDEX IF NOT EXISTS idx_group_chat_members_group ON group_chat_members(gr
77213
77369
  return this.db.prepare(sql).all(...params).map((r) => this.mapRow(r));
77214
77370
  }
77215
77371
  count(userId, unreadOnly = false) {
77216
- const conditions = ["(user_id = ? OR user_id = ?)"];
77217
- const params = [userId, "all"];
77372
+ const conditions = ["(user_id = ? OR user_id = ? OR user_id = ?)"];
77373
+ const params = [userId, "all", "default"];
77218
77374
  if (unreadOnly)
77219
77375
  conditions.push("read = 0");
77220
77376
  const row = this.db.prepare(`SELECT COUNT(*) as cnt FROM user_notifications WHERE ${conditions.join(" AND ")}`).get(...params);
@@ -77225,7 +77381,7 @@ CREATE INDEX IF NOT EXISTS idx_group_chat_members_group ON group_chat_members(gr
77225
77381
  return info4.changes > 0;
77226
77382
  }
77227
77383
  markAllRead(userId) {
77228
- const info4 = this.db.prepare("UPDATE user_notifications SET read = 1 WHERE (user_id = ? OR user_id = ?) AND read = 0").run(userId, "all");
77384
+ const info4 = this.db.prepare("UPDATE user_notifications SET read = 1 WHERE (user_id = ? OR user_id = ? OR user_id = ?) AND read = 0").run(userId, "all", "default");
77229
77385
  return Number(info4.changes);
77230
77386
  }
77231
77387
  mapRow(r) {
@@ -78563,7 +78719,7 @@ var init_startupProgress = __esm({
78563
78719
  });
78564
78720
 
78565
78721
  // src/connector-service.ts
78566
- import { resolve as resolve15, join as join28, dirname as dirname8 } from "node:path";
78722
+ import { resolve as resolve14, join as join28, dirname as dirname8 } from "node:path";
78567
78723
  import { existsSync as existsSync31, readFileSync as readFileSync23, writeFileSync as writeFileSync19, mkdirSync as mkdirSync24, readdirSync as readdirSync12, cpSync as cpSync3 } from "node:fs";
78568
78724
  import { homedir as homedir18 } from "node:os";
78569
78725
  import { execSync as execSync4 } from "node:child_process";
@@ -78573,9 +78729,9 @@ function expandHome(p) {
78573
78729
  }
78574
78730
  function loadConnectors() {
78575
78731
  const connectors = /* @__PURE__ */ new Map();
78576
- const builtinDir = resolve15(__dirname3, "..", "connectors");
78732
+ const builtinDir = resolve14(__dirname3, "..", "connectors");
78577
78733
  loadFromDir(builtinDir, connectors);
78578
- const devDir = resolve15(process.cwd(), "packages", "cli", "connectors");
78734
+ const devDir = resolve14(process.cwd(), "packages", "cli", "connectors");
78579
78735
  if (devDir !== builtinDir) loadFromDir(devDir, connectors);
78580
78736
  const userDir = join28(homedir18(), ".markus", "connectors");
78581
78737
  loadFromDir(userDir, connectors);
@@ -78679,8 +78835,8 @@ function installSkillTemplate(connector) {
78679
78835
  const templateName = connector.integration.skillTemplateName;
78680
78836
  const candidates = [
78681
78837
  join28(homedir18(), ".markus", "templates", templateName),
78682
- resolve15(process.cwd(), "templates", templateName),
78683
- resolve15(__dirname3, "..", "templates", templateName)
78838
+ resolve14(process.cwd(), "templates", templateName),
78839
+ resolve14(__dirname3, "..", "templates", templateName)
78684
78840
  ];
78685
78841
  let sourceDir;
78686
78842
  for (const c of candidates) {
@@ -78744,11 +78900,11 @@ __export(init_exports, {
78744
78900
  quickInit: () => quickInit,
78745
78901
  registerInitCommand: () => registerInitCommand
78746
78902
  });
78747
- import { resolve as resolve16 } from "node:path";
78903
+ import { resolve as resolve15 } from "node:path";
78748
78904
  import { readFileSync as readFileSync24, existsSync as existsSync32, cpSync as cpSync4 } from "node:fs";
78749
78905
  import { homedir as homedir19 } from "node:os";
78750
78906
  function registerInitCommand(program2) {
78751
- program2.command("init").description("Setup wizard: configure LLM provider, API keys, and server settings").option("--force", "Overwrite existing configuration").option("--non-interactive", "Run without prompts (use env vars or --import-from)").option("--provider <name>", "LLM provider (anthropic/openai/google/minimax/siliconflow/zai/ollama)").option("--api-key <key>", "LLM API key").option("--port <port>", "API server port", "8056").option("--import-from <platform>", "Import LLM config from an installed agent platform (e.g. openclaw, hermes)").option("--auto-connect", "Auto-connect detected agent platforms after init").action(async (opts) => {
78907
+ program2.command("init").description("Setup wizard: configure LLM provider, API keys, and server settings").option("--force", "Overwrite existing configuration").option("--non-interactive", "Run without prompts (use env vars or --import-from)").option("--provider <name>", "LLM provider (anthropic/openai/google/minimax/siliconflow/zai/deepseek/ollama)").option("--api-key <key>", "LLM API key").option("--port <port>", "API server port", "8056").option("--import-from <platform>", "Import LLM config from an installed agent platform (e.g. openclaw, hermes)").option("--auto-connect", "Auto-connect detected agent platforms after init").action(async (opts) => {
78752
78908
  await quickInit({
78753
78909
  force: opts.force,
78754
78910
  nonInteractive: opts.nonInteractive,
@@ -78805,7 +78961,8 @@ async function quickInit(options) {
78805
78961
  siliconflow: "Qwen/Qwen3.5-35B-A3B",
78806
78962
  ollama: "llama3",
78807
78963
  openrouter: "xiaomi/mimo-v2-pro",
78808
- zai: "glm-5.1"
78964
+ zai: "glm-5.1",
78965
+ deepseek: "deepseek-v4-flash"
78809
78966
  };
78810
78967
  const ENV_KEY_MAP = [
78811
78968
  { provider: "anthropic", label: "Anthropic", envKey: "ANTHROPIC_API_KEY" },
@@ -78814,7 +78971,8 @@ async function quickInit(options) {
78814
78971
  { provider: "siliconflow", label: "SiliconFlow", envKey: "SILICONFLOW_API_KEY", baseUrl: "https://api.siliconflow.cn/v1" },
78815
78972
  { provider: "minimax", label: "MiniMax", envKey: "MINIMAX_API_KEY", baseUrl: "https://api.minimax.io/v1" },
78816
78973
  { provider: "openrouter", label: "OpenRouter", envKey: "OPENROUTER_API_KEY", baseUrl: "https://openrouter.ai/api/v1" },
78817
- { provider: "zai", label: "ZAI", envKey: "ZAI_API_KEY", baseUrl: "https://api.z.ai/api/paas/v4" }
78974
+ { provider: "zai", label: "ZAI", envKey: "ZAI_API_KEY", baseUrl: "https://api.z.ai/api/paas/v4" },
78975
+ { provider: "deepseek", label: "DeepSeek", envKey: "DEEPSEEK_API_KEY", baseUrl: "https://api.deepseek.com" }
78818
78976
  ];
78819
78977
  console.log(" [1/3] LLM Provider Configuration\n");
78820
78978
  const envProviders = [];
@@ -78973,7 +79131,8 @@ async function quickInit(options) {
78973
79131
  const baseUrlMap = {
78974
79132
  minimax: "https://api.minimax.io/v1",
78975
79133
  siliconflow: "https://api.siliconflow.cn/v1",
78976
- zai: "https://api.z.ai/api/paas/v4"
79134
+ zai: "https://api.z.ai/api/paas/v4",
79135
+ deepseek: "https://api.deepseek.com"
78977
79136
  };
78978
79137
  providers[provider] = {
78979
79138
  ...apiKey ? { apiKey } : {},
@@ -78986,7 +79145,7 @@ async function quickInit(options) {
78986
79145
  console.log(" Warning: No API key provided. Configure manually in ~/.markus/markus.json");
78987
79146
  }
78988
79147
  } else {
78989
- const provider = await ask(" LLM provider (anthropic/openai/google/minimax/siliconflow/zai/ollama)", "anthropic");
79148
+ const provider = await ask(" LLM provider (anthropic/openai/google/minimax/siliconflow/zai/deepseek/ollama)", "anthropic");
78990
79149
  defaultProvider = provider;
78991
79150
  let apiKey = "";
78992
79151
  if (provider !== "ollama") {
@@ -78996,7 +79155,8 @@ async function quickInit(options) {
78996
79155
  const baseUrlMap = {
78997
79156
  minimax: "https://api.minimax.io/v1",
78998
79157
  siliconflow: "https://api.siliconflow.cn/v1",
78999
- zai: "https://api.z.ai/api/paas/v4"
79158
+ zai: "https://api.z.ai/api/paas/v4",
79159
+ deepseek: "https://api.deepseek.com"
79000
79160
  };
79001
79161
  providers[provider] = {
79002
79162
  ...apiKey ? { apiKey } : {},
@@ -79032,7 +79192,7 @@ async function quickInit(options) {
79032
79192
  const userTemplatesDir = pathJoin(homedir19(), ".markus", "templates");
79033
79193
  const builtinTemplatesDir = resolveTemplatesDir("roles");
79034
79194
  if (builtinTemplatesDir && existsSync32(builtinTemplatesDir) && !existsSync32(userTemplatesDir)) {
79035
- const builtinRoot = resolve16(builtinTemplatesDir, "..");
79195
+ const builtinRoot = resolve15(builtinTemplatesDir, "..");
79036
79196
  mkdirSync26(userTemplatesDir, { recursive: true });
79037
79197
  cpSync4(builtinRoot, userTemplatesDir, { recursive: true });
79038
79198
  console.log(` Copied templates to ${userTemplatesDir}`);
@@ -79100,7 +79260,7 @@ var start_exports = {};
79100
79260
  __export(start_exports, {
79101
79261
  registerStartCommand: () => registerStartCommand
79102
79262
  });
79103
- import { resolve as resolve17, join as join29, dirname as dirname9 } from "node:path";
79263
+ import { resolve as resolve16, join as join29, dirname as dirname9 } from "node:path";
79104
79264
  import { existsSync as existsSync33 } from "node:fs";
79105
79265
  import { homedir as homedir20 } from "node:os";
79106
79266
  function registerStartCommand(program2) {
@@ -79195,6 +79355,19 @@ async function createServices(config) {
79195
79355
  defaultProvider = "zai";
79196
79356
  }
79197
79357
  }
79358
+ const deepseekKey = config.llm.providers["deepseek"]?.apiKey ?? process.env["DEEPSEEK_API_KEY"];
79359
+ if (deepseekKey) {
79360
+ providerConfigs["deepseek"] = {
79361
+ provider: "deepseek",
79362
+ model: config.llm.providers["deepseek"]?.model ?? process.env["DEEPSEEK_MODEL"] ?? "deepseek-v4-flash",
79363
+ apiKey: deepseekKey,
79364
+ baseUrl: config.llm.providers["deepseek"]?.baseUrl ?? process.env["DEEPSEEK_BASE_URL"] ?? "https://api.deepseek.com",
79365
+ timeoutMs: llmTimeoutMs
79366
+ };
79367
+ if (config.llm.defaultProvider === "deepseek") {
79368
+ defaultProvider = "deepseek";
79369
+ }
79370
+ }
79198
79371
  if (!providerConfigs[defaultProvider]) {
79199
79372
  const available = Object.keys(providerConfigs);
79200
79373
  if (available.length > 0) {
@@ -79338,7 +79511,7 @@ async function startServer(config, values) {
79338
79511
  startupLog("INFO", "\u6B63\u5728\u542F\u52A8\u670D\u52A1...");
79339
79512
  const currentPath = process.env["PATH"] ?? "";
79340
79513
  const extraPaths = [];
79341
- const selfBinDir = dirname9(resolve17(process.argv[1] ?? ""));
79514
+ const selfBinDir = dirname9(resolve16(process.argv[1] ?? ""));
79342
79515
  if (selfBinDir && !currentPath.includes(selfBinDir)) extraPaths.push(selfBinDir);
79343
79516
  const cwdBin = join29(process.cwd(), "node_modules", ".bin");
79344
79517
  if (existsSync33(cwdBin) && !currentPath.includes(cwdBin)) extraPaths.push(cwdBin);
@@ -79480,7 +79653,7 @@ async function startServer(config, values) {
79480
79653
  });
79481
79654
  agentManager.setUserNotifier((opts) => {
79482
79655
  hitlService.notify({
79483
- targetUserId: "default",
79656
+ targetUserId: "all",
79484
79657
  type: opts.type,
79485
79658
  title: opts.title,
79486
79659
  body: opts.body,
@@ -79547,7 +79720,7 @@ ${body}`;
79547
79720
  });
79548
79721
  const hasTask = !!taskId2;
79549
79722
  hitlService.notify({
79550
- targetUserId: "default",
79723
+ targetUserId: "all",
79551
79724
  type: "agent_report",
79552
79725
  title,
79553
79726
  body,
@@ -79581,7 +79754,7 @@ ${reason}`;
79581
79754
  isMainSession: true
79582
79755
  });
79583
79756
  hitlService.notify({
79584
- targetUserId: "default",
79757
+ targetUserId: "all",
79585
79758
  type: "system",
79586
79759
  title: "Agent needs help",
79587
79760
  body: reason,
@@ -79973,7 +80146,7 @@ ${reason}`;
79973
80146
  temperature: TRIAGE_TEMPERATURE,
79974
80147
  maxTokens: TRIAGE_MAX_TOKENS
79975
80148
  }, triageProvider);
79976
- return { content: response.content, toolCalls: response.toolCalls };
80149
+ return { content: response.content, toolCalls: response.toolCalls, reasoningContent: response.reasoningContent };
79977
80150
  });
79978
80151
  const triageToolMap = /* @__PURE__ */ new Map();
79979
80152
  const agentTools = agent.getTools();
@@ -80688,9 +80861,9 @@ var init_model = __esm({
80688
80861
  id: "deepseek",
80689
80862
  label: "DeepSeek",
80690
80863
  envKey: "DEEPSEEK_API_KEY",
80691
- baseUrl: "https://api.deepseek.com/v1",
80692
- defaultModel: "deepseek-chat",
80693
- models: ["deepseek-chat", "deepseek-coder", "deepseek-chat-v3"]
80864
+ baseUrl: "https://api.deepseek.com",
80865
+ defaultModel: "deepseek-v4-flash",
80866
+ models: ["deepseek-v4-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner"]
80694
80867
  }
80695
80868
  ];
80696
80869
  C = {
@@ -81085,7 +81258,7 @@ var init_doctor = __esm({
81085
81258
  { id: "siliconflow", label: "SiliconFlow", envKey: "SILICONFLOW_API_KEY", baseUrl: "https://api.siliconflow.cn/v1", defaultModel: "Qwen/Qwen3.5-35B-A3B" },
81086
81259
  { id: "openrouter", label: "OpenRouter", envKey: "OPENROUTER_API_KEY", baseUrl: "https://openrouter.ai/api/v1", defaultModel: "xiaomi/mimo-v2-pro:free" },
81087
81260
  { id: "zai", label: "ZAI", envKey: "ZAI_API_KEY", baseUrl: "https://api.z.ai/api/paas/v4", defaultModel: "glm-5.1" },
81088
- { id: "deepseek", label: "DeepSeek", envKey: "DEEPSEEK_API_KEY", baseUrl: "https://api.deepseek.com/v1", defaultModel: "deepseek-chat" }
81261
+ { id: "deepseek", label: "DeepSeek", envKey: "DEEPSEEK_API_KEY", baseUrl: "https://api.deepseek.com", defaultModel: "deepseek-v4-flash" }
81089
81262
  ];
81090
81263
  }
81091
81264
  });
@@ -81473,7 +81646,7 @@ var init_auth = __esm({
81473
81646
  { id: "siliconflow", label: "SiliconFlow", envKey: "SILICONFLOW_API_KEY", baseUrl: "https://api.siliconflow.cn/v1", defaultModel: "Qwen/Qwen3.5-35B-A3B" },
81474
81647
  { id: "openrouter", label: "OpenRouter", envKey: "OPENROUTER_API_KEY", baseUrl: "https://openrouter.ai/api/v1", defaultModel: "xiaomi/mimo-v2-pro:free" },
81475
81648
  { id: "zai", label: "ZAI", envKey: "ZAI_API_KEY", baseUrl: "https://api.z.ai/api/paas/v4", defaultModel: "glm-5.1" },
81476
- { id: "deepseek", label: "DeepSeek", envKey: "DEEPSEEK_API_KEY", defaultModel: "deepseek-chat" }
81649
+ { id: "deepseek", label: "DeepSeek", envKey: "DEEPSEEK_API_KEY", baseUrl: "https://api.deepseek.com", defaultModel: "deepseek-v4-flash" }
81477
81650
  ];
81478
81651
  PLACEHOLDER_PATTERNS3 = ["***", "your-", "dummy", "fake", "test-key", "replace-me"];
81479
81652
  }
@@ -83675,7 +83848,7 @@ __export(skill_exports, {
83675
83848
  registerSkillCommands: () => registerSkillCommands
83676
83849
  });
83677
83850
  import { writeFileSync as writeFileSync20, mkdirSync as mkdirSync25 } from "node:fs";
83678
- import { resolve as resolve18 } from "node:path";
83851
+ import { resolve as resolve17 } from "node:path";
83679
83852
  function registerSkillCommands(program2) {
83680
83853
  const root = program2.command("skill").description("Skills registry and local scaffold");
83681
83854
  root.command("list").action(async (_opts, cmd) => {
@@ -83763,7 +83936,7 @@ function registerSkillCommands(program2) {
83763
83936
  const g = cmd.optsWithGlobals();
83764
83937
  const out = { json: !!g.json };
83765
83938
  if (!opts.dir && !opts.name) fail("Specify --dir or --name");
83766
- const dir = resolve18(process.cwd(), opts.dir ?? opts.name);
83939
+ const dir = resolve17(process.cwd(), opts.dir ?? opts.name);
83767
83940
  mkdirSync25(dir, { recursive: true });
83768
83941
  const skillName = opts.name ?? (opts.dir ? opts.dir.replace(/.*[/\\]/, "") : "my-skill");
83769
83942
  const skillJson = {
@@ -83782,8 +83955,8 @@ Describe what this skill does for agents.
83782
83955
  ## Tools / behavior
83783
83956
 
83784
83957
  `;
83785
- writeFileSync20(resolve18(dir, "skill.json"), JSON.stringify(skillJson, null, 2) + "\n");
83786
- writeFileSync20(resolve18(dir, "SKILL.md"), skillMd);
83958
+ writeFileSync20(resolve17(dir, "skill.json"), JSON.stringify(skillJson, null, 2) + "\n");
83959
+ writeFileSync20(resolve17(dir, "SKILL.md"), skillMd);
83787
83960
  if (out.json) {
83788
83961
  console.log(JSON.stringify({ dir, files: ["skill.json", "SKILL.md"] }, null, 2));
83789
83962
  } else {
@@ -83807,12 +83980,12 @@ __export(system_exports, {
83807
83980
  });
83808
83981
  import { execSync as execSync6 } from "node:child_process";
83809
83982
  import { existsSync as existsSync34, readFileSync as readFileSync25 } from "node:fs";
83810
- import { resolve as resolve19, dirname as dirname10 } from "node:path";
83983
+ import { resolve as resolve18, dirname as dirname10 } from "node:path";
83811
83984
  import { fileURLToPath as fileURLToPath5 } from "node:url";
83812
83985
  function findMarkusRoot() {
83813
83986
  let dir = dirname10(fileURLToPath5(import.meta.url));
83814
83987
  for (let i = 0; i < 10; i++) {
83815
- if (existsSync34(resolve19(dir, "package.json")) && existsSync34(resolve19(dir, "packages"))) return dir;
83988
+ if (existsSync34(resolve18(dir, "package.json")) && existsSync34(resolve18(dir, "packages"))) return dir;
83816
83989
  dir = dirname10(dir);
83817
83990
  }
83818
83991
  return null;
@@ -83953,13 +84126,13 @@ function registerSystemCommands(program2) {
83953
84126
  if (markusRoot) {
83954
84127
  if (!info4.currentVersion) {
83955
84128
  try {
83956
- const pkg = JSON.parse(readFileSync25(resolve19(markusRoot, "package.json"), "utf-8"));
84129
+ const pkg = JSON.parse(readFileSync25(resolve18(markusRoot, "package.json"), "utf-8"));
83957
84130
  info4.currentVersion = pkg.version;
83958
84131
  } catch {
83959
84132
  }
83960
84133
  }
83961
84134
  try {
83962
- const isGit = existsSync34(resolve19(markusRoot, ".git"));
84135
+ const isGit = existsSync34(resolve18(markusRoot, ".git"));
83963
84136
  if (isGit) {
83964
84137
  info4.gitBranch = execSync6("git rev-parse --abbrev-ref HEAD", { cwd: markusRoot, encoding: "utf-8" }).trim();
83965
84138
  info4.gitCommit = execSync6("git rev-parse --short HEAD", { cwd: markusRoot, encoding: "utf-8" }).trim();
@@ -83998,7 +84171,7 @@ function registerSystemCommands(program2) {
83998
84171
  fail("Cannot locate Markus installation directory");
83999
84172
  return;
84000
84173
  }
84001
- if (!existsSync34(resolve19(markusRoot, ".git"))) {
84174
+ if (!existsSync34(resolve18(markusRoot, ".git"))) {
84002
84175
  fail("Markus installation is not a git repository. Update manually.");
84003
84176
  return;
84004
84177
  }
@@ -84563,7 +84736,7 @@ var init_settings2 = __esm({
84563
84736
  });
84564
84737
 
84565
84738
  // src/index.ts
84566
- import { resolve as resolve20 } from "node:path";
84739
+ import { resolve as resolve19 } from "node:path";
84567
84740
  import { readFileSync as readFileSync26, existsSync as existsSync35 } from "node:fs";
84568
84741
  import process2 from "node:process";
84569
84742
 
@@ -84587,7 +84760,7 @@ var {
84587
84760
  // src/index.ts
84588
84761
  init_dist();
84589
84762
  init_output();
84590
- var envPath = resolve20(process2.cwd(), ".env");
84763
+ var envPath = resolve19(process2.cwd(), ".env");
84591
84764
  if (existsSync35(envPath)) {
84592
84765
  for (const line of readFileSync26(envPath, "utf-8").split("\n")) {
84593
84766
  const trimmed = line.trim();