@slock-ai/daemon 0.38.0 → 0.39.0

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.
@@ -973,7 +973,7 @@ server.tool(
973
973
  1. By task number: claim existing tasks shown in list_tasks. Use task_numbers=[1, 3].
974
974
  2. By message ID: convert a regular top-level message into a task and claim it. Use message_ids=["a1b2c3d4"]. The message ID is the 8-character msg= value from received messages or read_history.
975
975
 
976
- Thread messages cannot be claimed or converted into tasks. If a task is in "todo" status, claiming auto-advances it to "in_progress". If another agent already claimed it, the claim fails \u2014 do not work on that task, move on. Always claim before starting any work to prevent duplicate effort.`,
976
+ Thread messages and system messages (e.g. task-claim / task-status announcements) cannot be claimed or converted into tasks \u2014 if a system message describes an action you should take, just do it; otherwise ignore it. If a task is in "todo" status, claiming auto-advances it to "in_progress". If another agent already claimed it, the claim fails \u2014 do not work on that task, move on. Always claim before starting any work to prevent duplicate effort.`,
977
977
  {
978
978
  channel: z.string().describe("The channel \u2014 e.g. '#engineering'"),
979
979
  task_numbers: z.array(z.number()).optional().describe("Task numbers to claim (from list_tasks output, e.g. [1, 3])"),
@@ -7,7 +7,6 @@ import {
7
7
  import path10 from "path";
8
8
  import os4 from "os";
9
9
  import { createRequire } from "module";
10
- import { execSync as execSync2 } from "child_process";
11
10
  import { accessSync } from "fs";
12
11
  import { fileURLToPath } from "url";
13
12
 
@@ -232,7 +231,7 @@ var RUNTIMES = [
232
231
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
233
232
  { id: "kimi", displayName: "Kimi CLI", binary: "kimi", supported: true },
234
233
  { id: "copilot", displayName: "Copilot CLI", binary: "copilot", supported: true },
235
- { id: "cursor", displayName: "Cursor CLI", binary: "agent", supported: true },
234
+ { id: "cursor", displayName: "Cursor CLI", binary: "cursor-agent", supported: true },
236
235
  { id: "gemini", displayName: "Gemini CLI", binary: "gemini", supported: true }
237
236
  ];
238
237
  var PLAN_CONFIG = {
@@ -353,6 +352,8 @@ Header fields:
353
352
  - \`time=\` \u2014 timestamp.
354
353
  - \`type=\` \u2014 sender kind. Values are \`human\`, \`agent\`, or \`system\`.
355
354
 
355
+ \`type=system\` messages announce state changes in the channel (task events, channel archived/unarchived, etc.). They are informational \u2014 don't reply to them unless they clearly request action (e.g. a task was just assigned to you). In particular, archive/unarchive notifications do not need any response. If a channel is archived, further writes there will be rejected.
356
+
356
357
  ### Sending messages
357
358
 
358
359
  - **Reply to a channel**: \`send_message(target="#channel-name", content="...")\`
@@ -590,11 +591,34 @@ import path from "path";
590
591
  function normalizeExecOutput(raw) {
591
592
  return Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw ?? "");
592
593
  }
594
+ function resolveCommandOnWindows(command, env, execFileSyncFn) {
595
+ const script = "$cmd = Get-Command -Name $args[0] -ErrorAction Stop | Select-Object -First 1; if ($cmd.Path) { $cmd.Path } elseif ($cmd.Source) { $cmd.Source } elseif ($cmd.Definition) { $cmd.Definition }";
596
+ try {
597
+ const output = normalizeExecOutput(execFileSyncFn("powershell.exe", [
598
+ "-NoProfile",
599
+ "-NonInteractive",
600
+ "-Command",
601
+ script,
602
+ "--%",
603
+ command
604
+ ], {
605
+ stdio: ["ignore", "pipe", "ignore"],
606
+ env
607
+ }));
608
+ const resolved = output.trim().split(/\r?\n/)[0];
609
+ return resolved || command;
610
+ } catch {
611
+ return null;
612
+ }
613
+ }
593
614
  function resolveCommandOnPath(command, deps = {}) {
594
615
  const platform = deps.platform ?? process.platform;
595
616
  const env = deps.env ?? process.env;
596
617
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
597
- const locator = platform === "win32" ? "where" : "which";
618
+ if (platform === "win32") {
619
+ return resolveCommandOnWindows(command, env, execFileSyncFn);
620
+ }
621
+ const locator = "which";
598
622
  try {
599
623
  const output = normalizeExecOutput(execFileSyncFn(locator, [command], {
600
624
  stdio: ["ignore", "pipe", "ignore"],
@@ -1466,7 +1490,7 @@ var CursorDriver = class {
1466
1490
  }
1467
1491
  args.push(ctx.prompt);
1468
1492
  const spawnEnv = { ...process.env, FORCE_COLOR: "0", NO_COLOR: "1", ...ctx.config.envVars || {} };
1469
- const proc = spawn4("agent", args, {
1493
+ const proc = spawn4("cursor-agent", args, {
1470
1494
  cwd: ctx.workingDirectory,
1471
1495
  stdio: ["pipe", "pipe", "pipe"],
1472
1496
  env: spawnEnv,
@@ -2156,13 +2180,15 @@ var AgentProcessManager = class _AgentProcessManager {
2156
2180
  chatBridgePath;
2157
2181
  sendToServer;
2158
2182
  daemonApiKey;
2183
+ serverUrl;
2159
2184
  dataDir;
2160
2185
  driverResolver;
2161
2186
  defaultAgentEnvVarsProvider;
2162
- constructor(chatBridgePath, sendToServer, daemonApiKey, opts = {}) {
2187
+ constructor(chatBridgePath, sendToServer, daemonApiKey, opts) {
2163
2188
  this.chatBridgePath = chatBridgePath;
2164
2189
  this.sendToServer = sendToServer;
2165
2190
  this.daemonApiKey = daemonApiKey;
2191
+ this.serverUrl = opts.serverUrl;
2166
2192
  this.dataDir = opts.dataDir || DATA_DIR;
2167
2193
  this.driverResolver = opts.driverResolver || getDriver;
2168
2194
  this.defaultAgentEnvVarsProvider = opts.defaultAgentEnvVarsProvider || null;
@@ -2417,27 +2443,28 @@ Use read_history to catch up on the channels listed above, then stop. Read each
2417
2443
  }
2418
2444
  }
2419
2445
  async buildSpawnConfig(agentId, config) {
2446
+ const baseConfig = config.serverUrl === this.serverUrl ? config : { ...config, serverUrl: this.serverUrl };
2420
2447
  if (!this.defaultAgentEnvVarsProvider) {
2421
- return config;
2448
+ return baseConfig;
2422
2449
  }
2423
2450
  try {
2424
2451
  const defaultEnvVars = await this.defaultAgentEnvVarsProvider({
2425
- runtime: config.runtime,
2426
- model: config.model,
2427
- envVars: config.envVars
2452
+ runtime: baseConfig.runtime,
2453
+ model: baseConfig.model,
2454
+ envVars: baseConfig.envVars
2428
2455
  });
2429
2456
  if (!defaultEnvVars || Object.keys(defaultEnvVars).length === 0) {
2430
- return config;
2457
+ return baseConfig;
2431
2458
  }
2432
2459
  const mergedEnvVars = {
2433
2460
  ...defaultEnvVars,
2434
- ...config.envVars ?? {}
2461
+ ...baseConfig.envVars ?? {}
2435
2462
  };
2436
- if (this.sameEnvVars(mergedEnvVars, config.envVars)) {
2437
- return config;
2463
+ if (this.sameEnvVars(mergedEnvVars, baseConfig.envVars)) {
2464
+ return baseConfig;
2438
2465
  }
2439
2466
  return {
2440
- ...config,
2467
+ ...baseConfig,
2441
2468
  envVars: mergedEnvVars
2442
2469
  };
2443
2470
  } catch (error) {
@@ -2445,7 +2472,7 @@ Use read_history to catch up on the channels listed above, then stop. Read each
2445
2472
  logger.warn(
2446
2473
  `[Agent ${agentId}] Failed to resolve default runtime env vars \u2014 continuing without machine-level defaults (${reason})`
2447
2474
  );
2448
- return config;
2475
+ return baseConfig;
2449
2476
  }
2450
2477
  }
2451
2478
  sameEnvVars(left, right) {
@@ -3122,7 +3149,6 @@ function resolveChatBridgePath(moduleUrl = import.meta.url) {
3122
3149
  function detectRuntimes() {
3123
3150
  const ids = [];
3124
3151
  const versions = {};
3125
- const cmd = process.platform === "win32" ? "where" : "which";
3126
3152
  for (const runtime of RUNTIMES) {
3127
3153
  try {
3128
3154
  const probe = getDriver(runtime.id).probe?.();
@@ -3133,15 +3159,16 @@ function detectRuntimes() {
3133
3159
  }
3134
3160
  } catch {
3135
3161
  }
3136
- try {
3137
- execSync2(`${cmd} ${runtime.binary}`, { stdio: "pipe" });
3162
+ const detectionBinaries = [runtime.binary];
3163
+ for (const binary of detectionBinaries) {
3164
+ const resolved = resolveCommandOnPath(binary);
3165
+ if (!resolved) continue;
3138
3166
  ids.push(runtime.id);
3139
- try {
3140
- const version = execSync2(`${runtime.binary} --version`, { stdio: "pipe", timeout: 5e3 }).toString().trim().split("\n")[0];
3167
+ const version = readCommandVersion(binary);
3168
+ if (version) {
3141
3169
  versions[runtime.id] = version;
3142
- } catch {
3143
3170
  }
3144
- } catch {
3171
+ break;
3145
3172
  }
3146
3173
  }
3147
3174
  return { ids, versions };
@@ -3188,6 +3215,7 @@ var DaemonCore = class {
3188
3215
  let connection;
3189
3216
  const agentManagerOptions = {
3190
3217
  dataDir: options.dataDir,
3218
+ serverUrl: options.serverUrl,
3191
3219
  defaultAgentEnvVarsProvider: options.defaultAgentEnvVarsProvider
3192
3220
  };
3193
3221
  this.agentManager = options.agentManagerFactory ? options.agentManagerFactory(this.chatBridgePath, (msg) => connection.send(msg), options.apiKey, agentManagerOptions) : new AgentProcessManager(this.chatBridgePath, (msg) => connection.send(msg), options.apiKey, agentManagerOptions);
package/dist/core.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  resolveChatBridgePath,
9
9
  resolveWorkspaceDirectoryPath,
10
10
  scanWorkspaceDirectories
11
- } from "./chunk-GCL6DIFU.js";
11
+ } from "./chunk-72UW4SIL.js";
12
12
  import {
13
13
  subscribeDaemonLogs
14
14
  } from "./chunk-E6OOH3IC.js";
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
5
  parseDaemonCliArgs
6
- } from "./chunk-GCL6DIFU.js";
6
+ } from "./chunk-72UW4SIL.js";
7
7
  import "./chunk-E6OOH3IC.js";
8
8
 
9
9
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/daemon",
3
- "version": "0.38.0",
3
+ "version": "0.39.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "slock-daemon": "dist/index.js"