@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 +48 -15
- package/dist/bin.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +48 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ interface OrchestratorQueryOptions {
|
|
|
26
26
|
model: string;
|
|
27
27
|
/** Agent SDK session ID to resume (for multi-turn conversations). */
|
|
28
28
|
sessionId?: string;
|
|
29
|
+
/** Path to user's Claude Code executable (uses bundled CLI if omitted). */
|
|
30
|
+
claudeCodePath?: string;
|
|
29
31
|
}
|
|
30
32
|
/**
|
|
31
33
|
* Run the orchestrator agent. Returns an async iterable of SDKMessage events.
|
|
@@ -40,6 +42,8 @@ interface HeartbeatOptions {
|
|
|
40
42
|
prompt: string;
|
|
41
43
|
orchestratorServer: McpSdkServerConfigWithInstance;
|
|
42
44
|
model: string;
|
|
45
|
+
/** Path to user's Claude Code executable (uses bundled CLI if omitted). */
|
|
46
|
+
claudeCodePath?: string;
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
49
|
* Run a one-shot heartbeat query (no session persistence).
|
|
@@ -390,6 +394,8 @@ interface RuntimeConfig extends LocalConfig {
|
|
|
390
394
|
duskHour: number | null;
|
|
391
395
|
/** IANA timezone string (e.g. 'America/New_York') for sleep scheduling */
|
|
392
396
|
timezone: string | null;
|
|
397
|
+
/** Absolute path to the user's Claude Code executable (resolved for 'claude-code' provider) */
|
|
398
|
+
claudeCodePath: string | undefined;
|
|
393
399
|
}
|
|
394
400
|
/**
|
|
395
401
|
* Load local config from environment variables.
|
|
@@ -401,6 +407,10 @@ declare function loadConfig(): LocalConfig;
|
|
|
401
407
|
/**
|
|
402
408
|
* Merge local config with API-bootstrapped config.
|
|
403
409
|
* Env var overrides take precedence over API values for debugging/testing.
|
|
410
|
+
*
|
|
411
|
+
* When running multiple agents on the same machine, stateDir and toolsDir
|
|
412
|
+
* are automatically namespaced by botId (unless explicitly overridden via
|
|
413
|
+
* DESKFREE_STATE_DIR / DESKFREE_TOOLS_DIR env vars).
|
|
404
414
|
*/
|
|
405
415
|
declare function mergeWithRemoteConfig(local: LocalConfig, remote: RuntimeBootstrapConfig): RuntimeConfig;
|
|
406
416
|
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,9 @@ import { query, tool, createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk'
|
|
|
3
3
|
import { createRequire as createRequire$1 } from 'module';
|
|
4
4
|
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, unlinkSync, createWriteStream } from 'fs';
|
|
5
5
|
import { join, dirname, extname } from 'path';
|
|
6
|
+
import { execFileSync, execFile } from 'child_process';
|
|
6
7
|
import { z } from 'zod';
|
|
7
8
|
import { appendFile, readFile, mkdir, unlink } from 'fs/promises';
|
|
8
|
-
import { execFile } from 'child_process';
|
|
9
9
|
import { randomUUID } from 'crypto';
|
|
10
10
|
import { Readable } from 'stream';
|
|
11
11
|
import { pipeline } from 'stream/promises';
|
|
@@ -11295,18 +11295,17 @@ var DISALLOWED_BUILTIN_TOOLS = [
|
|
|
11295
11295
|
"Agent"
|
|
11296
11296
|
];
|
|
11297
11297
|
function runOrchestrator(opts) {
|
|
11298
|
-
const { prompt, orchestratorServer, model, sessionId } = opts;
|
|
11298
|
+
const { prompt, orchestratorServer, model, sessionId, claudeCodePath } = opts;
|
|
11299
11299
|
return query({
|
|
11300
11300
|
prompt,
|
|
11301
11301
|
options: {
|
|
11302
|
-
debug: true,
|
|
11303
|
-
debugFile: "/dev/stderr",
|
|
11304
11302
|
stderr: (data) => {
|
|
11305
11303
|
process.stderr.write(`[orchestrator-sdk] ${data}
|
|
11306
11304
|
`);
|
|
11307
11305
|
},
|
|
11308
11306
|
systemPrompt: DESKFREE_AGENT_DIRECTIVE,
|
|
11309
11307
|
model,
|
|
11308
|
+
...claudeCodePath ? { pathToClaudeCodeExecutable: claudeCodePath } : {},
|
|
11310
11309
|
maxTurns: MAX_ORCHESTRATOR_TURNS,
|
|
11311
11310
|
permissionMode: "bypassPermissions",
|
|
11312
11311
|
allowDangerouslySkipPermissions: true,
|
|
@@ -11334,12 +11333,13 @@ function runOrchestrator(opts) {
|
|
|
11334
11333
|
});
|
|
11335
11334
|
}
|
|
11336
11335
|
function runHeartbeat(opts) {
|
|
11337
|
-
const { prompt, orchestratorServer, model } = opts;
|
|
11336
|
+
const { prompt, orchestratorServer, model, claudeCodePath } = opts;
|
|
11338
11337
|
return query({
|
|
11339
11338
|
prompt,
|
|
11340
11339
|
options: {
|
|
11341
11340
|
systemPrompt: DESKFREE_AGENT_DIRECTIVE,
|
|
11342
11341
|
model,
|
|
11342
|
+
...claudeCodePath ? { pathToClaudeCodeExecutable: claudeCodePath } : {},
|
|
11343
11343
|
maxTurns: MAX_ORCHESTRATOR_TURNS,
|
|
11344
11344
|
permissionMode: "bypassPermissions",
|
|
11345
11345
|
allowDangerouslySkipPermissions: true,
|
|
@@ -11450,8 +11450,27 @@ function loadConfig() {
|
|
|
11450
11450
|
};
|
|
11451
11451
|
}
|
|
11452
11452
|
function mergeWithRemoteConfig(local, remote) {
|
|
11453
|
+
const stateDirOverridden = !!process.env["DESKFREE_STATE_DIR"];
|
|
11454
|
+
const toolsDirOverridden = !!process.env["DESKFREE_TOOLS_DIR"];
|
|
11455
|
+
const stateDir = stateDirOverridden ? local.stateDir : isDocker ? local.stateDir : `.deskfree/${remote.botId}/state`;
|
|
11456
|
+
const toolsDir = toolsDirOverridden ? local.toolsDir : isDocker ? local.toolsDir : `.deskfree/${remote.botId}/tools`;
|
|
11457
|
+
let claudeCodePath;
|
|
11458
|
+
if (remote.provider === "claude-code") {
|
|
11459
|
+
try {
|
|
11460
|
+
claudeCodePath = execFileSync("which", ["claude"], {
|
|
11461
|
+
encoding: "utf8"
|
|
11462
|
+
}).trim();
|
|
11463
|
+
} catch {
|
|
11464
|
+
throw new Error(
|
|
11465
|
+
'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'
|
|
11466
|
+
);
|
|
11467
|
+
}
|
|
11468
|
+
}
|
|
11453
11469
|
return {
|
|
11454
11470
|
...local,
|
|
11471
|
+
stateDir,
|
|
11472
|
+
toolsDir,
|
|
11473
|
+
claudeCodePath,
|
|
11455
11474
|
wsUrl: process.env["DESKFREE_WS_URL"] ?? remote.wsUrl,
|
|
11456
11475
|
model: process.env["DESKFREE_MODEL"] ?? remote.model,
|
|
11457
11476
|
awsRegion: process.env["AWS_REGION"] ?? remote.awsRegion,
|
|
@@ -12860,7 +12879,8 @@ async function routeMessage(message, client, deps, sessionStore, config) {
|
|
|
12860
12879
|
prompt,
|
|
12861
12880
|
orchestratorServer: deps.createOrchestratorServer(),
|
|
12862
12881
|
model: deps.model,
|
|
12863
|
-
sessionId: existingSessionId
|
|
12882
|
+
sessionId: existingSessionId,
|
|
12883
|
+
claudeCodePath: deps.claudeCodePath
|
|
12864
12884
|
});
|
|
12865
12885
|
let fullText = "";
|
|
12866
12886
|
let capturedSessionId = null;
|
|
@@ -13404,7 +13424,7 @@ ${userMessage}
|
|
|
13404
13424
|
try {
|
|
13405
13425
|
await client.reportUsage({
|
|
13406
13426
|
taskId,
|
|
13407
|
-
estimatedCost: result.total_cost_usd
|
|
13427
|
+
estimatedCost: Math.round(result.total_cost_usd * 1e6) / 1e6
|
|
13408
13428
|
});
|
|
13409
13429
|
} catch {
|
|
13410
13430
|
log.warn(`Failed to report usage for task ${taskId}`);
|
|
@@ -13538,7 +13558,16 @@ function startHealthServer(port, log) {
|
|
|
13538
13558
|
log.info(`Health server listening on port ${port}`);
|
|
13539
13559
|
});
|
|
13540
13560
|
server.on("error", (err) => {
|
|
13541
|
-
|
|
13561
|
+
if (err.code === "EADDRINUSE") {
|
|
13562
|
+
log.info(`Port ${port} in use, requesting OS-assigned port...`);
|
|
13563
|
+
server.listen(0, () => {
|
|
13564
|
+
const addr = server.address();
|
|
13565
|
+
const assignedPort = typeof addr === "object" && addr ? addr.port : "unknown";
|
|
13566
|
+
log.info(`Health server listening on port ${assignedPort}`);
|
|
13567
|
+
});
|
|
13568
|
+
} else {
|
|
13569
|
+
log.warn(`Health server error: ${err.message}`);
|
|
13570
|
+
}
|
|
13542
13571
|
});
|
|
13543
13572
|
return {
|
|
13544
13573
|
close() {
|
|
@@ -13546,7 +13575,7 @@ function startHealthServer(port, log) {
|
|
|
13546
13575
|
}
|
|
13547
13576
|
};
|
|
13548
13577
|
}
|
|
13549
|
-
function scheduleHeartbeat(createOrchServer, model, intervalMs, signal, log) {
|
|
13578
|
+
function scheduleHeartbeat(createOrchServer, model, intervalMs, signal, log, claudeCodePath) {
|
|
13550
13579
|
if (intervalMs <= 0) return;
|
|
13551
13580
|
let running = false;
|
|
13552
13581
|
async function tick() {
|
|
@@ -13557,7 +13586,8 @@ function scheduleHeartbeat(createOrchServer, model, intervalMs, signal, log) {
|
|
|
13557
13586
|
const result = runHeartbeat({
|
|
13558
13587
|
prompt: DESKFREE_HEARTBEAT_DIRECTIVE,
|
|
13559
13588
|
orchestratorServer: createOrchServer(),
|
|
13560
|
-
model
|
|
13589
|
+
model,
|
|
13590
|
+
claudeCodePath
|
|
13561
13591
|
});
|
|
13562
13592
|
for await (const _ of result) {
|
|
13563
13593
|
}
|
|
@@ -13579,8 +13609,6 @@ async function startAgent(opts) {
|
|
|
13579
13609
|
const log = opts?.log ?? createLogger("agent", localConfig.logLevel);
|
|
13580
13610
|
const abortController = new AbortController();
|
|
13581
13611
|
log.info("DeskFree Agent Runtime starting...");
|
|
13582
|
-
mkdirSync(localConfig.stateDir, { recursive: true });
|
|
13583
|
-
mkdirSync(localConfig.toolsDir, { recursive: true });
|
|
13584
13612
|
const client = new DeskFreeClient(localConfig.botToken, localConfig.apiUrl);
|
|
13585
13613
|
const errorReporter = initErrorReporter(client, log);
|
|
13586
13614
|
initializeHealth("unknown");
|
|
@@ -13593,12 +13621,15 @@ async function startAgent(opts) {
|
|
|
13593
13621
|
wsUrl: config.wsUrl,
|
|
13594
13622
|
model: config.model,
|
|
13595
13623
|
region: config.awsRegion,
|
|
13596
|
-
tools: config.tools.length
|
|
13624
|
+
tools: config.tools.length,
|
|
13625
|
+
botId: config.botId
|
|
13597
13626
|
});
|
|
13598
13627
|
} catch (err) {
|
|
13599
13628
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13600
13629
|
throw new Error(`Failed to bootstrap config from API: ${msg}`);
|
|
13601
13630
|
}
|
|
13631
|
+
mkdirSync(config.stateDir, { recursive: true });
|
|
13632
|
+
mkdirSync(config.toolsDir, { recursive: true });
|
|
13602
13633
|
if (config.tools.length > 0) {
|
|
13603
13634
|
log.info(`Installing ${config.tools.length} tool package(s)...`);
|
|
13604
13635
|
await installTools(config.tools, config.toolsDir, log);
|
|
@@ -13679,7 +13710,8 @@ async function startAgent(opts) {
|
|
|
13679
13710
|
{
|
|
13680
13711
|
createOrchestratorServer: createOrchServer,
|
|
13681
13712
|
workerManager,
|
|
13682
|
-
model: config.model
|
|
13713
|
+
model: config.model,
|
|
13714
|
+
claudeCodePath: config.claudeCodePath
|
|
13683
13715
|
},
|
|
13684
13716
|
sessionStore,
|
|
13685
13717
|
{
|
|
@@ -13694,7 +13726,8 @@ async function startAgent(opts) {
|
|
|
13694
13726
|
config.model,
|
|
13695
13727
|
config.heartbeatIntervalMs,
|
|
13696
13728
|
abortController.signal,
|
|
13697
|
-
log
|
|
13729
|
+
log,
|
|
13730
|
+
config.claudeCodePath
|
|
13698
13731
|
);
|
|
13699
13732
|
if (config.memoryFileId && config.sleepHour !== null && config.timezone) {
|
|
13700
13733
|
const memoryFileId = config.memoryFileId;
|