@questionbase/deskfree 0.4.4 → 0.4.7
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 +462 -143
- package/dist/bin.js.map +1 -1
- package/dist/cli/install.js +112 -12
- package/dist/cli/install.js.map +1 -1
- package/dist/cli/uninstall.js +43 -9
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/index.js +188 -72
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { execSync, execFileSync, execFile } from 'child_process';
|
|
4
|
-
import { writeFileSync, chmodSync, existsSync, unlinkSync,
|
|
4
|
+
import { mkdirSync, writeFileSync, chmodSync, existsSync, unlinkSync, appendFileSync, readdirSync, readFileSync, statSync, createWriteStream } from 'fs';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { dirname, join, extname } from 'path';
|
|
5
7
|
import { createRequire as createRequire$1 } from 'module';
|
|
6
|
-
import { join, dirname, extname } from 'path';
|
|
7
8
|
import { query, createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
|
|
8
9
|
import { z } from 'zod';
|
|
9
10
|
import { appendFile, readFile, mkdir, unlink } from 'fs/promises';
|
|
@@ -57,7 +58,90 @@ var install_exports = {};
|
|
|
57
58
|
__export(install_exports, {
|
|
58
59
|
install: () => install
|
|
59
60
|
});
|
|
60
|
-
function
|
|
61
|
+
function getMacPaths() {
|
|
62
|
+
const home = homedir();
|
|
63
|
+
const deskfreeDir = join(home, ".deskfree");
|
|
64
|
+
return {
|
|
65
|
+
deskfreeDir,
|
|
66
|
+
envFile: join(deskfreeDir, ".env"),
|
|
67
|
+
launcher: join(deskfreeDir, "launcher.sh"),
|
|
68
|
+
logDir: join(deskfreeDir, "logs"),
|
|
69
|
+
plist: join(home, "Library", "LaunchAgents", `${PLIST_LABEL}.plist`)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function installMac(token) {
|
|
73
|
+
const paths = getMacPaths();
|
|
74
|
+
let nodeBinDir;
|
|
75
|
+
try {
|
|
76
|
+
const nodePath = execSync("which node", { encoding: "utf8" }).trim();
|
|
77
|
+
nodeBinDir = dirname(nodePath);
|
|
78
|
+
} catch {
|
|
79
|
+
console.error("Error: node not found in PATH");
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
mkdirSync(paths.deskfreeDir, { recursive: true });
|
|
83
|
+
mkdirSync(paths.logDir, { recursive: true });
|
|
84
|
+
mkdirSync(dirname(paths.plist), { recursive: true });
|
|
85
|
+
writeFileSync(paths.envFile, `DESKFREE_LAUNCH=${token}
|
|
86
|
+
`, { mode: 384 });
|
|
87
|
+
chmodSync(paths.envFile, 384);
|
|
88
|
+
console.log(`Wrote ${paths.envFile}`);
|
|
89
|
+
const launcher = `#!/bin/bash
|
|
90
|
+
set -euo pipefail
|
|
91
|
+
|
|
92
|
+
export PATH="${nodeBinDir}:$PATH"
|
|
93
|
+
|
|
94
|
+
# Update to latest version before starting
|
|
95
|
+
npm install -g ${PACKAGE} 2>/dev/null || true
|
|
96
|
+
|
|
97
|
+
# Source env
|
|
98
|
+
set -a
|
|
99
|
+
source "${paths.envFile}"
|
|
100
|
+
set +a
|
|
101
|
+
|
|
102
|
+
exec deskfree-agent start
|
|
103
|
+
`;
|
|
104
|
+
writeFileSync(paths.launcher, launcher, { mode: 493 });
|
|
105
|
+
chmodSync(paths.launcher, 493);
|
|
106
|
+
console.log(`Wrote ${paths.launcher}`);
|
|
107
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
108
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
109
|
+
<plist version="1.0">
|
|
110
|
+
<dict>
|
|
111
|
+
<key>Label</key>
|
|
112
|
+
<string>${PLIST_LABEL}</string>
|
|
113
|
+
<key>ProgramArguments</key>
|
|
114
|
+
<array>
|
|
115
|
+
<string>${paths.launcher}</string>
|
|
116
|
+
</array>
|
|
117
|
+
<key>KeepAlive</key>
|
|
118
|
+
<true/>
|
|
119
|
+
<key>RunAtLoad</key>
|
|
120
|
+
<true/>
|
|
121
|
+
<key>StandardOutPath</key>
|
|
122
|
+
<string>${join(paths.logDir, "stdout.log")}</string>
|
|
123
|
+
<key>StandardErrorPath</key>
|
|
124
|
+
<string>${join(paths.logDir, "stderr.log")}</string>
|
|
125
|
+
<key>ThrottleInterval</key>
|
|
126
|
+
<integer>10</integer>
|
|
127
|
+
</dict>
|
|
128
|
+
</plist>
|
|
129
|
+
`;
|
|
130
|
+
writeFileSync(paths.plist, plist);
|
|
131
|
+
console.log(`Wrote ${paths.plist}`);
|
|
132
|
+
try {
|
|
133
|
+
execSync(`launchctl bootout gui/$(id -u) ${paths.plist}`, {
|
|
134
|
+
stdio: "ignore"
|
|
135
|
+
});
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
execSync(`launchctl bootstrap gui/$(id -u) ${paths.plist}`);
|
|
139
|
+
console.log(`
|
|
140
|
+
Service ${PLIST_LABEL} installed and started.`);
|
|
141
|
+
console.log(`Check status: launchctl print gui/$(id -u)/${PLIST_LABEL}`);
|
|
142
|
+
console.log(`Logs: tail -f ${join(paths.logDir, "stdout.log")}`);
|
|
143
|
+
}
|
|
144
|
+
function installLinux(token) {
|
|
61
145
|
if (process.getuid?.() !== 0) {
|
|
62
146
|
console.error("Error: install must be run as root (use sudo)");
|
|
63
147
|
process.exit(1);
|
|
@@ -69,10 +153,12 @@ function install(token) {
|
|
|
69
153
|
console.error("Error: npx not found in PATH");
|
|
70
154
|
process.exit(1);
|
|
71
155
|
}
|
|
72
|
-
writeFileSync(
|
|
73
|
-
`, {
|
|
74
|
-
|
|
75
|
-
|
|
156
|
+
writeFileSync(SYSTEMD_ENV_FILE, `DESKFREE_LAUNCH=${token}
|
|
157
|
+
`, {
|
|
158
|
+
mode: 384
|
|
159
|
+
});
|
|
160
|
+
chmodSync(SYSTEMD_ENV_FILE, 384);
|
|
161
|
+
console.log(`Wrote ${SYSTEMD_ENV_FILE}`);
|
|
76
162
|
const unit = `[Unit]
|
|
77
163
|
Description=DeskFree Agent
|
|
78
164
|
After=network-online.target
|
|
@@ -80,8 +166,9 @@ Wants=network-online.target
|
|
|
80
166
|
|
|
81
167
|
[Service]
|
|
82
168
|
Type=simple
|
|
169
|
+
ExecStartPre=${npxPath} ${PACKAGE} --version
|
|
83
170
|
ExecStart=${npxPath} ${PACKAGE} start
|
|
84
|
-
EnvironmentFile=${
|
|
171
|
+
EnvironmentFile=${SYSTEMD_ENV_FILE}
|
|
85
172
|
Environment=NODE_ENV=production
|
|
86
173
|
Restart=always
|
|
87
174
|
RestartSec=10
|
|
@@ -89,21 +176,33 @@ RestartSec=10
|
|
|
89
176
|
[Install]
|
|
90
177
|
WantedBy=multi-user.target
|
|
91
178
|
`;
|
|
92
|
-
writeFileSync(
|
|
93
|
-
console.log(`Wrote ${
|
|
179
|
+
writeFileSync(SYSTEMD_SERVICE_FILE, unit);
|
|
180
|
+
console.log(`Wrote ${SYSTEMD_SERVICE_FILE}`);
|
|
94
181
|
execSync("systemctl daemon-reload");
|
|
95
182
|
execSync(`systemctl enable ${SERVICE_NAME}`);
|
|
96
183
|
execSync(`systemctl start ${SERVICE_NAME}`);
|
|
97
|
-
console.log(`
|
|
184
|
+
console.log(`
|
|
185
|
+
Service ${SERVICE_NAME} installed and started.`);
|
|
98
186
|
console.log(`Check status: systemctl status ${SERVICE_NAME}`);
|
|
99
187
|
}
|
|
100
|
-
|
|
188
|
+
function install(token) {
|
|
189
|
+
if (process.platform === "darwin") {
|
|
190
|
+
installMac(token);
|
|
191
|
+
} else if (process.platform === "linux") {
|
|
192
|
+
installLinux(token);
|
|
193
|
+
} else {
|
|
194
|
+
console.error(`Unsupported platform: ${process.platform}`);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
var SERVICE_NAME, PACKAGE, PLIST_LABEL, SYSTEMD_SERVICE_FILE, SYSTEMD_ENV_FILE;
|
|
101
199
|
var init_install = __esm({
|
|
102
200
|
"src/cli/install.ts"() {
|
|
103
201
|
SERVICE_NAME = "deskfree-agent";
|
|
104
|
-
SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
105
|
-
ENV_FILE = `/etc/${SERVICE_NAME}.env`;
|
|
106
202
|
PACKAGE = "@questionbase/deskfree@latest";
|
|
203
|
+
PLIST_LABEL = "com.deskfree.agent";
|
|
204
|
+
SYSTEMD_SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
205
|
+
SYSTEMD_ENV_FILE = `/etc/${SERVICE_NAME}.env`;
|
|
107
206
|
}
|
|
108
207
|
});
|
|
109
208
|
|
|
@@ -112,7 +211,28 @@ var uninstall_exports = {};
|
|
|
112
211
|
__export(uninstall_exports, {
|
|
113
212
|
uninstall: () => uninstall
|
|
114
213
|
});
|
|
115
|
-
function
|
|
214
|
+
function uninstallMac() {
|
|
215
|
+
const home = homedir();
|
|
216
|
+
const plist = join(home, "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
|
|
217
|
+
const deskfreeDir = join(home, ".deskfree");
|
|
218
|
+
const envFile = join(deskfreeDir, ".env");
|
|
219
|
+
const launcher = join(deskfreeDir, "launcher.sh");
|
|
220
|
+
try {
|
|
221
|
+
execSync(`launchctl bootout gui/$(id -u) ${plist}`, { stdio: "ignore" });
|
|
222
|
+
} catch {
|
|
223
|
+
}
|
|
224
|
+
for (const file of [plist, envFile, launcher]) {
|
|
225
|
+
if (existsSync(file)) {
|
|
226
|
+
unlinkSync(file);
|
|
227
|
+
console.log(`Removed ${file}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
console.log(`Service ${PLIST_LABEL2} uninstalled.`);
|
|
231
|
+
console.log(
|
|
232
|
+
`Note: logs and state in ${deskfreeDir} were preserved. Remove manually if desired.`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
function uninstallLinux() {
|
|
116
236
|
if (process.getuid?.() !== 0) {
|
|
117
237
|
console.error("Error: uninstall must be run as root (use sudo)");
|
|
118
238
|
process.exit(1);
|
|
@@ -125,23 +245,104 @@ function uninstall() {
|
|
|
125
245
|
execSync(`systemctl disable ${SERVICE_NAME2}`, { stdio: "ignore" });
|
|
126
246
|
} catch {
|
|
127
247
|
}
|
|
128
|
-
if (existsSync(
|
|
129
|
-
unlinkSync(
|
|
130
|
-
console.log(`Removed ${
|
|
248
|
+
if (existsSync(SYSTEMD_SERVICE_FILE2)) {
|
|
249
|
+
unlinkSync(SYSTEMD_SERVICE_FILE2);
|
|
250
|
+
console.log(`Removed ${SYSTEMD_SERVICE_FILE2}`);
|
|
131
251
|
}
|
|
132
|
-
if (existsSync(
|
|
133
|
-
unlinkSync(
|
|
134
|
-
console.log(`Removed ${
|
|
252
|
+
if (existsSync(SYSTEMD_ENV_FILE2)) {
|
|
253
|
+
unlinkSync(SYSTEMD_ENV_FILE2);
|
|
254
|
+
console.log(`Removed ${SYSTEMD_ENV_FILE2}`);
|
|
135
255
|
}
|
|
136
256
|
execSync("systemctl daemon-reload");
|
|
137
257
|
console.log(`Service ${SERVICE_NAME2} uninstalled.`);
|
|
138
258
|
}
|
|
139
|
-
|
|
259
|
+
function uninstall() {
|
|
260
|
+
if (process.platform === "darwin") {
|
|
261
|
+
uninstallMac();
|
|
262
|
+
} else if (process.platform === "linux") {
|
|
263
|
+
uninstallLinux();
|
|
264
|
+
} else {
|
|
265
|
+
console.error(`Unsupported platform: ${process.platform}`);
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
var SERVICE_NAME2, PLIST_LABEL2, SYSTEMD_SERVICE_FILE2, SYSTEMD_ENV_FILE2;
|
|
140
270
|
var init_uninstall = __esm({
|
|
141
271
|
"src/cli/uninstall.ts"() {
|
|
142
272
|
SERVICE_NAME2 = "deskfree-agent";
|
|
143
|
-
|
|
144
|
-
|
|
273
|
+
PLIST_LABEL2 = "com.deskfree.agent";
|
|
274
|
+
SYSTEMD_SERVICE_FILE2 = `/etc/systemd/system/${SERVICE_NAME2}.service`;
|
|
275
|
+
SYSTEMD_ENV_FILE2 = `/etc/${SERVICE_NAME2}.env`;
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// src/cli/status.ts
|
|
280
|
+
var status_exports = {};
|
|
281
|
+
__export(status_exports, {
|
|
282
|
+
status: () => status
|
|
283
|
+
});
|
|
284
|
+
function statusMac() {
|
|
285
|
+
const home = homedir();
|
|
286
|
+
const plist = join(home, "Library", "LaunchAgents", `${PLIST_LABEL3}.plist`);
|
|
287
|
+
if (!existsSync(plist)) {
|
|
288
|
+
console.log("DeskFree Agent is not installed.");
|
|
289
|
+
console.log(`Run: npx @questionbase/deskfree@latest install <token>`);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
console.log("DeskFree Agent (macOS LaunchAgent)\n");
|
|
293
|
+
try {
|
|
294
|
+
const output = execSync(
|
|
295
|
+
`launchctl print gui/$(id -u)/${PLIST_LABEL3} 2>&1`,
|
|
296
|
+
{ encoding: "utf8" }
|
|
297
|
+
);
|
|
298
|
+
const pidMatch = output.match(/pid\s*=\s*(\d+)/);
|
|
299
|
+
const stateMatch = output.match(/state\s*=\s*(\w+)/);
|
|
300
|
+
if (pidMatch) console.log(` PID: ${pidMatch[1]}`);
|
|
301
|
+
if (stateMatch) console.log(` State: ${stateMatch[1]}`);
|
|
302
|
+
const logDir = join(home, ".deskfree", "logs");
|
|
303
|
+
console.log(` Logs: ${logDir}/stdout.log`);
|
|
304
|
+
console.log(` Plist: ${plist}`);
|
|
305
|
+
} catch {
|
|
306
|
+
console.log(" Status: not running (service may be unloaded)");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function statusLinux() {
|
|
310
|
+
const serviceFile = `/etc/systemd/system/${SYSTEMD_SERVICE_NAME}.service`;
|
|
311
|
+
if (!existsSync(serviceFile)) {
|
|
312
|
+
console.log("DeskFree Agent is not installed.");
|
|
313
|
+
console.log(`Run: sudo npx @questionbase/deskfree@latest install <token>`);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
console.log("DeskFree Agent (systemd service)\n");
|
|
317
|
+
try {
|
|
318
|
+
const output = execSync(
|
|
319
|
+
`systemctl status ${SYSTEMD_SERVICE_NAME} --no-pager 2>&1`,
|
|
320
|
+
{ encoding: "utf8" }
|
|
321
|
+
);
|
|
322
|
+
console.log(output);
|
|
323
|
+
} catch (err) {
|
|
324
|
+
if (err && typeof err === "object" && "stdout" in err) {
|
|
325
|
+
console.log(err.stdout);
|
|
326
|
+
} else {
|
|
327
|
+
console.log(" Status: unknown (could not query systemd)");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function status() {
|
|
332
|
+
if (process.platform === "darwin") {
|
|
333
|
+
statusMac();
|
|
334
|
+
} else if (process.platform === "linux") {
|
|
335
|
+
statusLinux();
|
|
336
|
+
} else {
|
|
337
|
+
console.error(`Unsupported platform: ${process.platform}`);
|
|
338
|
+
process.exit(1);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
var PLIST_LABEL3, SYSTEMD_SERVICE_NAME;
|
|
342
|
+
var init_status = __esm({
|
|
343
|
+
"src/cli/status.ts"() {
|
|
344
|
+
PLIST_LABEL3 = "com.deskfree.agent";
|
|
345
|
+
SYSTEMD_SERVICE_NAME = "deskfree-agent";
|
|
145
346
|
}
|
|
146
347
|
});
|
|
147
348
|
function toErrorMessage(error) {
|
|
@@ -2554,6 +2755,41 @@ function createWorkerTools(client, options) {
|
|
|
2554
2755
|
return errorResult(err);
|
|
2555
2756
|
}
|
|
2556
2757
|
}),
|
|
2758
|
+
createTool(WORKER_TOOLS.PROPOSE, async (params) => {
|
|
2759
|
+
try {
|
|
2760
|
+
const context = validateStringParam(params, "context", false);
|
|
2761
|
+
const taskId = validateStringParam(params, "taskId", false);
|
|
2762
|
+
const rawTasks = params.tasks;
|
|
2763
|
+
if (!Array.isArray(rawTasks) || rawTasks.length === 0) {
|
|
2764
|
+
throw new Error("tasks must be a non-empty array of task objects");
|
|
2765
|
+
}
|
|
2766
|
+
const tasks = rawTasks;
|
|
2767
|
+
for (let i = 0; i < tasks.length; i++) {
|
|
2768
|
+
const task = tasks[i];
|
|
2769
|
+
if (!task || typeof task !== "object") {
|
|
2770
|
+
throw new Error(`tasks[${i}] must be an object`);
|
|
2771
|
+
}
|
|
2772
|
+
if (!task.title || typeof task.title !== "string" || task.title.trim() === "") {
|
|
2773
|
+
throw new Error(`tasks[${i}].title must be a non-empty string`);
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
await client.proposePlan({
|
|
2777
|
+
context,
|
|
2778
|
+
tasks,
|
|
2779
|
+
taskId
|
|
2780
|
+
});
|
|
2781
|
+
return {
|
|
2782
|
+
content: [
|
|
2783
|
+
{
|
|
2784
|
+
type: "text",
|
|
2785
|
+
text: `Proposal created with ${tasks.length} task(s)`
|
|
2786
|
+
}
|
|
2787
|
+
]
|
|
2788
|
+
};
|
|
2789
|
+
} catch (err) {
|
|
2790
|
+
return errorResult(err);
|
|
2791
|
+
}
|
|
2792
|
+
}),
|
|
2557
2793
|
createTool(WORKER_TOOLS.COMPLETE_TASK, async (params) => {
|
|
2558
2794
|
try {
|
|
2559
2795
|
const taskId = validateStringParam(params, "taskId", true);
|
|
@@ -6411,96 +6647,96 @@ var init_dist = __esm({
|
|
|
6411
6647
|
this.statusCode = statusCode;
|
|
6412
6648
|
}
|
|
6413
6649
|
static fromResponse(response, procedure, responseText) {
|
|
6414
|
-
const
|
|
6650
|
+
const status2 = response.status;
|
|
6415
6651
|
const statusText = response.statusText;
|
|
6416
|
-
if (
|
|
6652
|
+
if (status2 === 401) {
|
|
6417
6653
|
return new _DeskFreeError(
|
|
6418
6654
|
"auth",
|
|
6419
6655
|
procedure,
|
|
6420
|
-
`Authentication failed: ${
|
|
6656
|
+
`Authentication failed: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6421
6657
|
"Your bot token is invalid or has expired. Please check your authentication credentials.",
|
|
6422
|
-
|
|
6658
|
+
status2
|
|
6423
6659
|
);
|
|
6424
6660
|
}
|
|
6425
|
-
if (
|
|
6661
|
+
if (status2 === 403) {
|
|
6426
6662
|
return new _DeskFreeError(
|
|
6427
6663
|
"auth",
|
|
6428
6664
|
procedure,
|
|
6429
|
-
`Authorization failed: ${
|
|
6665
|
+
`Authorization failed: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6430
6666
|
"Your bot does not have permission to perform this action. Contact your administrator.",
|
|
6431
|
-
|
|
6667
|
+
status2
|
|
6432
6668
|
);
|
|
6433
6669
|
}
|
|
6434
|
-
if (
|
|
6670
|
+
if (status2 === 400) {
|
|
6435
6671
|
return new _DeskFreeError(
|
|
6436
6672
|
"client",
|
|
6437
6673
|
procedure,
|
|
6438
|
-
`Bad request: ${
|
|
6674
|
+
`Bad request: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6439
6675
|
"The request was invalid. Please check your input parameters and try again.",
|
|
6440
|
-
|
|
6676
|
+
status2
|
|
6441
6677
|
);
|
|
6442
6678
|
}
|
|
6443
|
-
if (
|
|
6679
|
+
if (status2 === 404) {
|
|
6444
6680
|
return new _DeskFreeError(
|
|
6445
6681
|
"client",
|
|
6446
6682
|
procedure,
|
|
6447
|
-
`Resource not found: ${
|
|
6683
|
+
`Resource not found: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6448
6684
|
procedure.includes("task") ? "The specified task was not found or is not available. Use deskfree_state to see available tasks." : "The requested resource was not found. Please check your input and try again.",
|
|
6449
|
-
|
|
6685
|
+
status2
|
|
6450
6686
|
);
|
|
6451
6687
|
}
|
|
6452
|
-
if (
|
|
6688
|
+
if (status2 === 409) {
|
|
6453
6689
|
return new _DeskFreeError(
|
|
6454
6690
|
"client",
|
|
6455
6691
|
procedure,
|
|
6456
|
-
`Conflict: ${
|
|
6692
|
+
`Conflict: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6457
6693
|
procedure.includes("start_task") || procedure.includes("claim") ? "The resource is already in use by another process. Use deskfree_state to see current status and try a different resource." : "The request conflicts with the current state of the resource. Please refresh and try again.",
|
|
6458
|
-
|
|
6694
|
+
status2
|
|
6459
6695
|
);
|
|
6460
6696
|
}
|
|
6461
|
-
if (
|
|
6697
|
+
if (status2 === 422) {
|
|
6462
6698
|
return new _DeskFreeError(
|
|
6463
6699
|
"client",
|
|
6464
6700
|
procedure,
|
|
6465
|
-
`Validation failed: ${
|
|
6701
|
+
`Validation failed: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6466
6702
|
"The request data failed validation. Please check all required fields and data formats.",
|
|
6467
|
-
|
|
6703
|
+
status2
|
|
6468
6704
|
);
|
|
6469
6705
|
}
|
|
6470
|
-
if (
|
|
6706
|
+
if (status2 === 429) {
|
|
6471
6707
|
return new _DeskFreeError(
|
|
6472
6708
|
"client",
|
|
6473
6709
|
procedure,
|
|
6474
|
-
`Rate limit exceeded: ${
|
|
6710
|
+
`Rate limit exceeded: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6475
6711
|
"Too many requests. Please wait a moment before trying again.",
|
|
6476
|
-
|
|
6712
|
+
status2
|
|
6477
6713
|
);
|
|
6478
6714
|
}
|
|
6479
|
-
if (
|
|
6480
|
-
const serverErrorMessage =
|
|
6715
|
+
if (status2 >= 500 && status2 < 600) {
|
|
6716
|
+
const serverErrorMessage = status2 === 502 || status2 === 503 ? "DeskFree service is temporarily unavailable due to maintenance or high load. Please try again in a few minutes." : status2 === 504 ? "The request timed out on the server. This may be due to high load. Please try again with a smaller request or wait a few minutes." : "DeskFree service encountered an internal error. Please try again in a few minutes.";
|
|
6481
6717
|
return new _DeskFreeError(
|
|
6482
6718
|
"server",
|
|
6483
6719
|
procedure,
|
|
6484
|
-
`Server error: ${
|
|
6720
|
+
`Server error: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6485
6721
|
serverErrorMessage,
|
|
6486
|
-
|
|
6722
|
+
status2
|
|
6487
6723
|
);
|
|
6488
6724
|
}
|
|
6489
|
-
if (
|
|
6725
|
+
if (status2 >= 400 && status2 < 500) {
|
|
6490
6726
|
return new _DeskFreeError(
|
|
6491
6727
|
"client",
|
|
6492
6728
|
procedure,
|
|
6493
|
-
`Client error: ${
|
|
6729
|
+
`Client error: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6494
6730
|
"The request was not accepted by the server. Please check your input and try again.",
|
|
6495
|
-
|
|
6731
|
+
status2
|
|
6496
6732
|
);
|
|
6497
6733
|
}
|
|
6498
6734
|
return new _DeskFreeError(
|
|
6499
6735
|
"client",
|
|
6500
6736
|
procedure,
|
|
6501
|
-
`HTTP error: ${
|
|
6502
|
-
`Request failed with error ${
|
|
6503
|
-
|
|
6737
|
+
`HTTP error: ${status2} ${statusText} \u2014 ${responseText}`,
|
|
6738
|
+
`Request failed with error ${status2}. Please try again or contact support if the problem persists.`,
|
|
6739
|
+
status2
|
|
6504
6740
|
);
|
|
6505
6741
|
}
|
|
6506
6742
|
static timeout(procedure, timeoutMs) {
|
|
@@ -7361,7 +7597,10 @@ You are the orchestrator. Your job: turn human intent into approved tasks, then
|
|
|
7361
7597
|
**Match the human's energy.** Short message \u2192 short reply. Casual tone \u2192 casual response. Don't over-explain, don't lecture, don't pad responses.
|
|
7362
7598
|
|
|
7363
7599
|
You do NOT claim tasks, complete tasks, or do work directly \u2014 you have no access to deskfree_start_task or deskfree_complete_task. Use \`deskfree_dispatch_worker\` to dispatch a worker for each approved task.
|
|
7364
|
-
- When a human writes in a task thread, decide:
|
|
7600
|
+
- When a human writes in a task thread, decide:
|
|
7601
|
+
- **Continuation of the same task?** \u2192 reopen and dispatch a worker.
|
|
7602
|
+
- **New/different work request?** \u2192 propose it as a new task (don't reopen the old one or do the work yourself).
|
|
7603
|
+
- **Just confirmation or deferred?** \u2192 leave it for now.
|
|
7365
7604
|
- Estimate token cost per task \u2014 consider files to read, reasoning, output.`;
|
|
7366
7605
|
DESKFREE_WORKER_DIRECTIVE = `## DeskFree Worker
|
|
7367
7606
|
You are a worker sub-agent. Your first message contains pre-loaded context \u2014 use it directly.
|
|
@@ -7797,8 +8036,6 @@ function runOrchestrator(opts) {
|
|
|
7797
8036
|
return query({
|
|
7798
8037
|
prompt,
|
|
7799
8038
|
options: {
|
|
7800
|
-
debug: true,
|
|
7801
|
-
debugFile: "/dev/stderr",
|
|
7802
8039
|
stderr: (data) => {
|
|
7803
8040
|
process.stderr.write(`[orchestrator-sdk] ${data}
|
|
7804
8041
|
`);
|
|
@@ -7816,18 +8053,7 @@ function runOrchestrator(opts) {
|
|
|
7816
8053
|
"deskfree-orchestrator": orchestratorServer
|
|
7817
8054
|
},
|
|
7818
8055
|
tools: [],
|
|
7819
|
-
allowedTools:
|
|
7820
|
-
"mcp__deskfree-orchestrator__*",
|
|
7821
|
-
"Read",
|
|
7822
|
-
"Write",
|
|
7823
|
-
"Edit",
|
|
7824
|
-
"Bash",
|
|
7825
|
-
"Glob",
|
|
7826
|
-
"Grep",
|
|
7827
|
-
"WebSearch",
|
|
7828
|
-
"WebFetch",
|
|
7829
|
-
"NotebookEdit"
|
|
7830
|
-
],
|
|
8056
|
+
allowedTools: ORCHESTRATOR_ALLOWED_TOOLS,
|
|
7831
8057
|
disallowedTools: DISALLOWED_BUILTIN_TOOLS
|
|
7832
8058
|
}
|
|
7833
8059
|
});
|
|
@@ -7848,18 +8074,7 @@ function runHeartbeat(opts) {
|
|
|
7848
8074
|
"deskfree-orchestrator": orchestratorServer
|
|
7849
8075
|
},
|
|
7850
8076
|
tools: [],
|
|
7851
|
-
allowedTools:
|
|
7852
|
-
"mcp__deskfree-orchestrator__*",
|
|
7853
|
-
"Read",
|
|
7854
|
-
"Write",
|
|
7855
|
-
"Edit",
|
|
7856
|
-
"Bash",
|
|
7857
|
-
"Glob",
|
|
7858
|
-
"Grep",
|
|
7859
|
-
"WebSearch",
|
|
7860
|
-
"WebFetch",
|
|
7861
|
-
"NotebookEdit"
|
|
7862
|
-
],
|
|
8077
|
+
allowedTools: ORCHESTRATOR_ALLOWED_TOOLS,
|
|
7863
8078
|
disallowedTools: DISALLOWED_BUILTIN_TOOLS
|
|
7864
8079
|
}
|
|
7865
8080
|
});
|
|
@@ -7882,11 +8097,19 @@ function runOneShotWorker(opts) {
|
|
|
7882
8097
|
}
|
|
7883
8098
|
});
|
|
7884
8099
|
}
|
|
7885
|
-
var MAX_ORCHESTRATOR_TURNS, DISALLOWED_BUILTIN_TOOLS;
|
|
8100
|
+
var MAX_ORCHESTRATOR_TURNS, ORCHESTRATOR_ALLOWED_TOOLS, DISALLOWED_BUILTIN_TOOLS;
|
|
7886
8101
|
var init_orchestrator = __esm({
|
|
7887
8102
|
"src/agents/orchestrator.ts"() {
|
|
7888
8103
|
init_dist();
|
|
7889
8104
|
MAX_ORCHESTRATOR_TURNS = 20;
|
|
8105
|
+
ORCHESTRATOR_ALLOWED_TOOLS = [
|
|
8106
|
+
"mcp__deskfree-orchestrator__*",
|
|
8107
|
+
"Read",
|
|
8108
|
+
"Glob",
|
|
8109
|
+
"Grep",
|
|
8110
|
+
"WebSearch",
|
|
8111
|
+
"WebFetch"
|
|
8112
|
+
];
|
|
7890
8113
|
DISALLOWED_BUILTIN_TOOLS = [
|
|
7891
8114
|
"TodoWrite",
|
|
7892
8115
|
"AskUserQuestion",
|
|
@@ -8051,6 +8274,86 @@ var init_health_state = __esm({
|
|
|
8051
8274
|
}
|
|
8052
8275
|
});
|
|
8053
8276
|
|
|
8277
|
+
// src/util/logger.ts
|
|
8278
|
+
var logger_exports = {};
|
|
8279
|
+
__export(logger_exports, {
|
|
8280
|
+
createLogger: () => createLogger,
|
|
8281
|
+
enableFileLogging: () => enableFileLogging,
|
|
8282
|
+
getLogFilePath: () => getLogFilePath,
|
|
8283
|
+
logger: () => logger
|
|
8284
|
+
});
|
|
8285
|
+
function enableFileLogging(filePath) {
|
|
8286
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
8287
|
+
logFilePath = filePath;
|
|
8288
|
+
}
|
|
8289
|
+
function getLogFilePath() {
|
|
8290
|
+
return logFilePath;
|
|
8291
|
+
}
|
|
8292
|
+
function rotateIfNeeded() {
|
|
8293
|
+
if (!logFilePath) return;
|
|
8294
|
+
try {
|
|
8295
|
+
const stat = statSync(logFilePath);
|
|
8296
|
+
if (stat.size <= MAX_LOG_FILE_BYTES) return;
|
|
8297
|
+
const content = readFileSync(logFilePath, "utf8");
|
|
8298
|
+
const half = Math.floor(content.length / 2);
|
|
8299
|
+
const newlineIdx = content.indexOf("\n", half);
|
|
8300
|
+
const trimmed = newlineIdx >= 0 ? content.slice(newlineIdx + 1) : content.slice(half);
|
|
8301
|
+
writeFileSync(logFilePath, trimmed);
|
|
8302
|
+
} catch {
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8305
|
+
function createLogger(component, minLevel = "info") {
|
|
8306
|
+
const minLevelNum = LEVELS[minLevel];
|
|
8307
|
+
function log(level, message, fields) {
|
|
8308
|
+
if (LEVELS[level] < minLevelNum) return;
|
|
8309
|
+
const entry = {
|
|
8310
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8311
|
+
level,
|
|
8312
|
+
component,
|
|
8313
|
+
msg: message,
|
|
8314
|
+
...fields
|
|
8315
|
+
};
|
|
8316
|
+
const line = JSON.stringify(entry);
|
|
8317
|
+
if (level === "error" || level === "warn") {
|
|
8318
|
+
process.stderr.write(line + "\n");
|
|
8319
|
+
} else {
|
|
8320
|
+
process.stdout.write(line + "\n");
|
|
8321
|
+
}
|
|
8322
|
+
if (logFilePath) {
|
|
8323
|
+
try {
|
|
8324
|
+
appendFileSync(logFilePath, line + "\n");
|
|
8325
|
+
if (++writesSinceCheck >= ROTATION_CHECK_INTERVAL) {
|
|
8326
|
+
writesSinceCheck = 0;
|
|
8327
|
+
rotateIfNeeded();
|
|
8328
|
+
}
|
|
8329
|
+
} catch {
|
|
8330
|
+
}
|
|
8331
|
+
}
|
|
8332
|
+
}
|
|
8333
|
+
return {
|
|
8334
|
+
debug: (msg, fields) => log("debug", msg, fields),
|
|
8335
|
+
info: (msg, fields) => log("info", msg, fields),
|
|
8336
|
+
warn: (msg, fields) => log("warn", msg, fields),
|
|
8337
|
+
error: (msg, fields) => log("error", msg, fields)
|
|
8338
|
+
};
|
|
8339
|
+
}
|
|
8340
|
+
var LEVELS, MAX_LOG_FILE_BYTES, ROTATION_CHECK_INTERVAL, logFilePath, writesSinceCheck, logger;
|
|
8341
|
+
var init_logger = __esm({
|
|
8342
|
+
"src/util/logger.ts"() {
|
|
8343
|
+
LEVELS = {
|
|
8344
|
+
debug: 0,
|
|
8345
|
+
info: 1,
|
|
8346
|
+
warn: 2,
|
|
8347
|
+
error: 3
|
|
8348
|
+
};
|
|
8349
|
+
MAX_LOG_FILE_BYTES = 5 * 1024 * 1024;
|
|
8350
|
+
ROTATION_CHECK_INTERVAL = 500;
|
|
8351
|
+
logFilePath = null;
|
|
8352
|
+
writesSinceCheck = 0;
|
|
8353
|
+
logger = createLogger("runtime");
|
|
8354
|
+
}
|
|
8355
|
+
});
|
|
8356
|
+
|
|
8054
8357
|
// src/gateway/polling.ts
|
|
8055
8358
|
async function pollAndDeliver(client, accountId, stateDir, cursor, onMessage, log) {
|
|
8056
8359
|
const ctx = { accountId };
|
|
@@ -11755,8 +12058,6 @@ var init_wrapper = __esm({
|
|
|
11755
12058
|
wrapper_default2 = import_websocket2.default;
|
|
11756
12059
|
}
|
|
11757
12060
|
});
|
|
11758
|
-
|
|
11759
|
-
// src/gateway/ws-gateway.ts
|
|
11760
12061
|
function nextBackoff(state2) {
|
|
11761
12062
|
const delay = Math.min(
|
|
11762
12063
|
BACKOFF_INITIAL_MS * Math.pow(BACKOFF_FACTOR, state2.attempt),
|
|
@@ -11936,11 +12237,11 @@ async function runWebSocketConnection(opts) {
|
|
|
11936
12237
|
}, PING_INTERVAL_MS);
|
|
11937
12238
|
if (opts.getWorkerStatus) {
|
|
11938
12239
|
try {
|
|
11939
|
-
const
|
|
12240
|
+
const status2 = opts.getWorkerStatus();
|
|
11940
12241
|
ws.send(
|
|
11941
12242
|
JSON.stringify({
|
|
11942
12243
|
action: "heartbeatResponse",
|
|
11943
|
-
...
|
|
12244
|
+
...status2
|
|
11944
12245
|
})
|
|
11945
12246
|
);
|
|
11946
12247
|
} catch (err) {
|
|
@@ -12010,11 +12311,11 @@ async function runWebSocketConnection(opts) {
|
|
|
12010
12311
|
} else if (msg.action === "heartbeatRequest") {
|
|
12011
12312
|
if (opts.getWorkerStatus && ws.readyState === wrapper_default2.OPEN) {
|
|
12012
12313
|
try {
|
|
12013
|
-
const
|
|
12314
|
+
const status2 = opts.getWorkerStatus();
|
|
12014
12315
|
ws.send(
|
|
12015
12316
|
JSON.stringify({
|
|
12016
12317
|
action: "heartbeatResponse",
|
|
12017
|
-
...
|
|
12318
|
+
...status2
|
|
12018
12319
|
})
|
|
12019
12320
|
);
|
|
12020
12321
|
} catch (err) {
|
|
@@ -12029,6 +12330,49 @@ async function runWebSocketConnection(opts) {
|
|
|
12029
12330
|
cleanup();
|
|
12030
12331
|
ws.close(1e3, "reload");
|
|
12031
12332
|
process.kill(process.pid, "SIGTERM");
|
|
12333
|
+
} else if (msg.action === "logs") {
|
|
12334
|
+
const MAX_RESPONSE_BYTES = 12e4;
|
|
12335
|
+
const lineCount = msg.lines ?? 200;
|
|
12336
|
+
try {
|
|
12337
|
+
const logFile = getLogFilePath();
|
|
12338
|
+
if (!logFile) {
|
|
12339
|
+
ws.send(
|
|
12340
|
+
JSON.stringify({
|
|
12341
|
+
action: "logsResponse",
|
|
12342
|
+
lines: [],
|
|
12343
|
+
error: "File logging not enabled"
|
|
12344
|
+
})
|
|
12345
|
+
);
|
|
12346
|
+
} else {
|
|
12347
|
+
const content = readFileSync(logFile, "utf8");
|
|
12348
|
+
const allLines = content.split("\n").filter(Boolean);
|
|
12349
|
+
let tail = allLines.slice(-lineCount);
|
|
12350
|
+
while (tail.length > 1) {
|
|
12351
|
+
const payload = JSON.stringify({
|
|
12352
|
+
action: "logsResponse",
|
|
12353
|
+
lines: tail
|
|
12354
|
+
});
|
|
12355
|
+
if (Buffer.byteLength(payload) <= MAX_RESPONSE_BYTES) break;
|
|
12356
|
+
tail = tail.slice(Math.ceil(tail.length * 0.25));
|
|
12357
|
+
}
|
|
12358
|
+
ws.send(
|
|
12359
|
+
JSON.stringify({
|
|
12360
|
+
action: "logsResponse",
|
|
12361
|
+
lines: tail
|
|
12362
|
+
})
|
|
12363
|
+
);
|
|
12364
|
+
}
|
|
12365
|
+
} catch (err) {
|
|
12366
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
12367
|
+
log.warn(`Failed to read logs: ${errMsg}`);
|
|
12368
|
+
ws.send(
|
|
12369
|
+
JSON.stringify({
|
|
12370
|
+
action: "logsResponse",
|
|
12371
|
+
lines: [],
|
|
12372
|
+
error: errMsg
|
|
12373
|
+
})
|
|
12374
|
+
);
|
|
12375
|
+
}
|
|
12032
12376
|
}
|
|
12033
12377
|
} catch (err) {
|
|
12034
12378
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -12147,6 +12491,7 @@ var PING_INTERVAL_MS, POLL_FALLBACK_INTERVAL_MS, WS_CONNECTION_TIMEOUT_MS, WS_PO
|
|
|
12147
12491
|
var init_ws_gateway = __esm({
|
|
12148
12492
|
"src/gateway/ws-gateway.ts"() {
|
|
12149
12493
|
init_health_state();
|
|
12494
|
+
init_logger();
|
|
12150
12495
|
init_polling();
|
|
12151
12496
|
init_dist();
|
|
12152
12497
|
init_wrapper();
|
|
@@ -12641,21 +12986,35 @@ function scheduleDailyCycle(label, run, hour, timezone, signal, log) {
|
|
|
12641
12986
|
}
|
|
12642
12987
|
function msUntilNextLocalHour(hour, timezone) {
|
|
12643
12988
|
const now = Date.now();
|
|
12644
|
-
const
|
|
12989
|
+
const hourFmt = new Intl.DateTimeFormat("en-US", {
|
|
12645
12990
|
timeZone: timezone,
|
|
12646
12991
|
hour: "numeric",
|
|
12647
12992
|
hour12: false
|
|
12648
12993
|
});
|
|
12994
|
+
const detailFmt = new Intl.DateTimeFormat("en-US", {
|
|
12995
|
+
timeZone: timezone,
|
|
12996
|
+
minute: "numeric",
|
|
12997
|
+
second: "numeric"
|
|
12998
|
+
});
|
|
12649
12999
|
for (let offsetMs = 6e4; offsetMs <= 25 * 36e5; offsetMs += 36e5) {
|
|
12650
13000
|
const candidateMs = now + offsetMs;
|
|
12651
|
-
const parts =
|
|
13001
|
+
const parts = hourFmt.formatToParts(new Date(candidateMs));
|
|
12652
13002
|
const hourPart = parts.find((p) => p.type === "hour");
|
|
12653
13003
|
const candidateHour = parseInt(hourPart?.value ?? "-1", 10);
|
|
12654
13004
|
if (candidateHour === hour) {
|
|
12655
|
-
const
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
13005
|
+
const detailParts = detailFmt.formatToParts(new Date(candidateMs));
|
|
13006
|
+
const localMinute = parseInt(
|
|
13007
|
+
detailParts.find((p) => p.type === "minute")?.value ?? "0",
|
|
13008
|
+
10
|
|
13009
|
+
);
|
|
13010
|
+
const localSecond = parseInt(
|
|
13011
|
+
detailParts.find((p) => p.type === "second")?.value ?? "0",
|
|
13012
|
+
10
|
|
13013
|
+
);
|
|
13014
|
+
const snappedMs = candidateMs - localMinute * 6e4 - localSecond * 1e3;
|
|
13015
|
+
if (snappedMs > now + 6e4) {
|
|
13016
|
+
return snappedMs - now;
|
|
13017
|
+
}
|
|
12659
13018
|
}
|
|
12660
13019
|
}
|
|
12661
13020
|
return 24 * 36e5;
|
|
@@ -12751,50 +13110,6 @@ var init_registry = __esm({
|
|
|
12751
13110
|
"src/tools/registry.ts"() {
|
|
12752
13111
|
}
|
|
12753
13112
|
});
|
|
12754
|
-
|
|
12755
|
-
// src/util/logger.ts
|
|
12756
|
-
var logger_exports = {};
|
|
12757
|
-
__export(logger_exports, {
|
|
12758
|
-
createLogger: () => createLogger,
|
|
12759
|
-
logger: () => logger
|
|
12760
|
-
});
|
|
12761
|
-
function createLogger(component, minLevel = "info") {
|
|
12762
|
-
const minLevelNum = LEVELS[minLevel];
|
|
12763
|
-
function log(level, message, fields) {
|
|
12764
|
-
if (LEVELS[level] < minLevelNum) return;
|
|
12765
|
-
const entry = {
|
|
12766
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12767
|
-
level,
|
|
12768
|
-
component,
|
|
12769
|
-
msg: message,
|
|
12770
|
-
...fields
|
|
12771
|
-
};
|
|
12772
|
-
const line = JSON.stringify(entry);
|
|
12773
|
-
if (level === "error" || level === "warn") {
|
|
12774
|
-
process.stderr.write(line + "\n");
|
|
12775
|
-
} else {
|
|
12776
|
-
process.stdout.write(line + "\n");
|
|
12777
|
-
}
|
|
12778
|
-
}
|
|
12779
|
-
return {
|
|
12780
|
-
debug: (msg, fields) => log("debug", msg, fields),
|
|
12781
|
-
info: (msg, fields) => log("info", msg, fields),
|
|
12782
|
-
warn: (msg, fields) => log("warn", msg, fields),
|
|
12783
|
-
error: (msg, fields) => log("error", msg, fields)
|
|
12784
|
-
};
|
|
12785
|
-
}
|
|
12786
|
-
var LEVELS, logger;
|
|
12787
|
-
var init_logger = __esm({
|
|
12788
|
-
"src/util/logger.ts"() {
|
|
12789
|
-
LEVELS = {
|
|
12790
|
-
debug: 0,
|
|
12791
|
-
info: 1,
|
|
12792
|
-
warn: 2,
|
|
12793
|
-
error: 3
|
|
12794
|
-
};
|
|
12795
|
-
logger = createLogger("runtime");
|
|
12796
|
-
}
|
|
12797
|
-
});
|
|
12798
13113
|
function checkRateLimit(userId) {
|
|
12799
13114
|
const now = Date.now();
|
|
12800
13115
|
const entry = rateLimitMap.get(userId);
|
|
@@ -13246,8 +13561,6 @@ function runWorker(opts) {
|
|
|
13246
13561
|
return query({
|
|
13247
13562
|
prompt,
|
|
13248
13563
|
options: {
|
|
13249
|
-
debug: true,
|
|
13250
|
-
debugFile: "/dev/stderr",
|
|
13251
13564
|
stderr: (data) => {
|
|
13252
13565
|
process.stderr.write(`[worker-sdk] ${data}
|
|
13253
13566
|
`);
|
|
@@ -13651,7 +13964,7 @@ ${userMessage}
|
|
|
13651
13964
|
try {
|
|
13652
13965
|
await client.reportUsage({
|
|
13653
13966
|
taskId,
|
|
13654
|
-
estimatedCost: result.total_cost_usd
|
|
13967
|
+
estimatedCost: Math.round(result.total_cost_usd * 1e6) / 1e6
|
|
13655
13968
|
});
|
|
13656
13969
|
} catch {
|
|
13657
13970
|
log.warn(`Failed to report usage for task ${taskId}`);
|
|
@@ -13865,6 +14178,9 @@ async function startAgent(opts) {
|
|
|
13865
14178
|
}
|
|
13866
14179
|
mkdirSync(config.stateDir, { recursive: true });
|
|
13867
14180
|
mkdirSync(config.toolsDir, { recursive: true });
|
|
14181
|
+
const logFile = join(config.stateDir, "runtime.log");
|
|
14182
|
+
enableFileLogging(logFile);
|
|
14183
|
+
log.info(`File logging enabled: ${logFile}`);
|
|
13868
14184
|
if (config.tools.length > 0) {
|
|
13869
14185
|
log.info(`Installing ${config.tools.length} tool package(s)...`);
|
|
13870
14186
|
await installTools(config.tools, config.toolsDir, log);
|
|
@@ -14105,6 +14421,9 @@ if (command === "install") {
|
|
|
14105
14421
|
} else if (command === "uninstall") {
|
|
14106
14422
|
const { uninstall: uninstall2 } = await Promise.resolve().then(() => (init_uninstall(), uninstall_exports));
|
|
14107
14423
|
uninstall2();
|
|
14424
|
+
} else if (command === "status") {
|
|
14425
|
+
const { status: status2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
14426
|
+
status2();
|
|
14108
14427
|
} else {
|
|
14109
14428
|
let handleShutdown = function(signal) {
|
|
14110
14429
|
log.info(`Received ${signal} \u2014 shutting down...`);
|