@questionbase/deskfree 0.4.3 → 0.4.5

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/bin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { execSync, execFile } from 'child_process';
3
+ import { execSync, execFileSync, execFile } from 'child_process';
4
4
  import { writeFileSync, chmodSync, existsSync, unlinkSync, mkdirSync, readdirSync, readFileSync, createWriteStream } from 'fs';
5
5
  import { createRequire as createRequire$1 } from 'module';
6
6
  import { join, dirname, extname } from 'path';
@@ -7793,18 +7793,17 @@ Send a brief main-thread message via \`deskfree_send_message\`:
7793
7793
  }
7794
7794
  });
7795
7795
  function runOrchestrator(opts) {
7796
- const { prompt, orchestratorServer, model, sessionId } = opts;
7796
+ const { prompt, orchestratorServer, model, sessionId, claudeCodePath } = opts;
7797
7797
  return query({
7798
7798
  prompt,
7799
7799
  options: {
7800
- debug: true,
7801
- debugFile: "/dev/stderr",
7802
7800
  stderr: (data) => {
7803
7801
  process.stderr.write(`[orchestrator-sdk] ${data}
7804
7802
  `);
7805
7803
  },
7806
7804
  systemPrompt: DESKFREE_AGENT_DIRECTIVE,
7807
7805
  model,
7806
+ ...claudeCodePath ? { pathToClaudeCodeExecutable: claudeCodePath } : {},
7808
7807
  maxTurns: MAX_ORCHESTRATOR_TURNS,
7809
7808
  permissionMode: "bypassPermissions",
7810
7809
  allowDangerouslySkipPermissions: true,
@@ -7832,12 +7831,13 @@ function runOrchestrator(opts) {
7832
7831
  });
7833
7832
  }
7834
7833
  function runHeartbeat(opts) {
7835
- const { prompt, orchestratorServer, model } = opts;
7834
+ const { prompt, orchestratorServer, model, claudeCodePath } = opts;
7836
7835
  return query({
7837
7836
  prompt,
7838
7837
  options: {
7839
7838
  systemPrompt: DESKFREE_AGENT_DIRECTIVE,
7840
7839
  model,
7840
+ ...claudeCodePath ? { pathToClaudeCodeExecutable: claudeCodePath } : {},
7841
7841
  maxTurns: MAX_ORCHESTRATOR_TURNS,
7842
7842
  permissionMode: "bypassPermissions",
7843
7843
  allowDangerouslySkipPermissions: true,
@@ -7959,8 +7959,27 @@ function loadConfig() {
7959
7959
  };
7960
7960
  }
7961
7961
  function mergeWithRemoteConfig(local, remote) {
7962
+ const stateDirOverridden = !!process.env["DESKFREE_STATE_DIR"];
7963
+ const toolsDirOverridden = !!process.env["DESKFREE_TOOLS_DIR"];
7964
+ const stateDir = stateDirOverridden ? local.stateDir : isDocker ? local.stateDir : `.deskfree/${remote.botId}/state`;
7965
+ const toolsDir = toolsDirOverridden ? local.toolsDir : isDocker ? local.toolsDir : `.deskfree/${remote.botId}/tools`;
7966
+ let claudeCodePath;
7967
+ if (remote.provider === "claude-code") {
7968
+ try {
7969
+ claudeCodePath = execFileSync("which", ["claude"], {
7970
+ encoding: "utf8"
7971
+ }).trim();
7972
+ } catch {
7973
+ throw new Error(
7974
+ 'Provider is "claude-code" but the `claude` CLI was not found on PATH. Install Claude Code first: https://docs.anthropic.com/en/docs/claude-code'
7975
+ );
7976
+ }
7977
+ }
7962
7978
  return {
7963
7979
  ...local,
7980
+ stateDir,
7981
+ toolsDir,
7982
+ claudeCodePath,
7964
7983
  wsUrl: process.env["DESKFREE_WS_URL"] ?? remote.wsUrl,
7965
7984
  model: process.env["DESKFREE_MODEL"] ?? remote.model,
7966
7985
  awsRegion: process.env["AWS_REGION"] ?? remote.awsRegion,
@@ -13037,7 +13056,8 @@ async function routeMessage(message, client, deps, sessionStore, config) {
13037
13056
  prompt,
13038
13057
  orchestratorServer: deps.createOrchestratorServer(),
13039
13058
  model: deps.model,
13040
- sessionId: existingSessionId
13059
+ sessionId: existingSessionId,
13060
+ claudeCodePath: deps.claudeCodePath
13041
13061
  });
13042
13062
  let fullText = "";
13043
13063
  let capturedSessionId = null;
@@ -13629,7 +13649,7 @@ ${userMessage}
13629
13649
  try {
13630
13650
  await client.reportUsage({
13631
13651
  taskId,
13632
- estimatedCost: result.total_cost_usd
13652
+ estimatedCost: Math.round(result.total_cost_usd * 1e6) / 1e6
13633
13653
  });
13634
13654
  } catch {
13635
13655
  log.warn(`Failed to report usage for task ${taskId}`);
@@ -13771,7 +13791,16 @@ function startHealthServer(port, log) {
13771
13791
  log.info(`Health server listening on port ${port}`);
13772
13792
  });
13773
13793
  server.on("error", (err) => {
13774
- log.warn(`Health server error: ${err.message}`);
13794
+ if (err.code === "EADDRINUSE") {
13795
+ log.info(`Port ${port} in use, requesting OS-assigned port...`);
13796
+ server.listen(0, () => {
13797
+ const addr = server.address();
13798
+ const assignedPort = typeof addr === "object" && addr ? addr.port : "unknown";
13799
+ log.info(`Health server listening on port ${assignedPort}`);
13800
+ });
13801
+ } else {
13802
+ log.warn(`Health server error: ${err.message}`);
13803
+ }
13775
13804
  });
13776
13805
  return {
13777
13806
  close() {
@@ -13779,7 +13808,7 @@ function startHealthServer(port, log) {
13779
13808
  }
13780
13809
  };
13781
13810
  }
13782
- function scheduleHeartbeat(createOrchServer, model, intervalMs, signal, log) {
13811
+ function scheduleHeartbeat(createOrchServer, model, intervalMs, signal, log, claudeCodePath) {
13783
13812
  if (intervalMs <= 0) return;
13784
13813
  let running = false;
13785
13814
  async function tick() {
@@ -13790,7 +13819,8 @@ function scheduleHeartbeat(createOrchServer, model, intervalMs, signal, log) {
13790
13819
  const result = runHeartbeat({
13791
13820
  prompt: DESKFREE_HEARTBEAT_DIRECTIVE,
13792
13821
  orchestratorServer: createOrchServer(),
13793
- model
13822
+ model,
13823
+ claudeCodePath
13794
13824
  });
13795
13825
  for await (const _ of result) {
13796
13826
  }
@@ -13812,8 +13842,6 @@ async function startAgent(opts) {
13812
13842
  const log = opts?.log ?? createLogger("agent", localConfig.logLevel);
13813
13843
  const abortController = new AbortController();
13814
13844
  log.info("DeskFree Agent Runtime starting...");
13815
- mkdirSync(localConfig.stateDir, { recursive: true });
13816
- mkdirSync(localConfig.toolsDir, { recursive: true });
13817
13845
  const client = new DeskFreeClient(localConfig.botToken, localConfig.apiUrl);
13818
13846
  const errorReporter = initErrorReporter(client, log);
13819
13847
  initializeHealth("unknown");
@@ -13826,12 +13854,15 @@ async function startAgent(opts) {
13826
13854
  wsUrl: config.wsUrl,
13827
13855
  model: config.model,
13828
13856
  region: config.awsRegion,
13829
- tools: config.tools.length
13857
+ tools: config.tools.length,
13858
+ botId: config.botId
13830
13859
  });
13831
13860
  } catch (err) {
13832
13861
  const msg = err instanceof Error ? err.message : String(err);
13833
13862
  throw new Error(`Failed to bootstrap config from API: ${msg}`);
13834
13863
  }
13864
+ mkdirSync(config.stateDir, { recursive: true });
13865
+ mkdirSync(config.toolsDir, { recursive: true });
13835
13866
  if (config.tools.length > 0) {
13836
13867
  log.info(`Installing ${config.tools.length} tool package(s)...`);
13837
13868
  await installTools(config.tools, config.toolsDir, log);
@@ -13912,7 +13943,8 @@ async function startAgent(opts) {
13912
13943
  {
13913
13944
  createOrchestratorServer: createOrchServer,
13914
13945
  workerManager,
13915
- model: config.model
13946
+ model: config.model,
13947
+ claudeCodePath: config.claudeCodePath
13916
13948
  },
13917
13949
  sessionStore,
13918
13950
  {
@@ -13927,7 +13959,8 @@ async function startAgent(opts) {
13927
13959
  config.model,
13928
13960
  config.heartbeatIntervalMs,
13929
13961
  abortController.signal,
13930
- log
13962
+ log,
13963
+ config.claudeCodePath
13931
13964
  );
13932
13965
  if (config.memoryFileId && config.sleepHour !== null && config.timezone) {
13933
13966
  const memoryFileId = config.memoryFileId;