@foxden-app/foxclaw 0.13.2 → 0.13.3
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/CHANGELOG.md +12 -0
- package/dist/dsh/client.js +13 -4
- package/dist/main.js +1 -1
- package/dist/service/backend_setup.d.ts +2 -1
- package/dist/service/backend_setup.js +15 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable FoxClaw changes are listed here. Each release note is bilingual so GitHub Releases and the npm package are useful to both Chinese and English readers.
|
|
4
4
|
|
|
5
|
+
## 0.13.3 - 2026-10-06
|
|
6
|
+
|
|
7
|
+
### 中文
|
|
8
|
+
|
|
9
|
+
- 修复从 Telegram 添加 DSH 时,安装成功却因读取 FoxClaw `.env` 中的代理变量而启动失败。DSH 在独立运行目录启动,继续继承服务环境;会话工作目录由 ACP 单独指定。
|
|
10
|
+
- 源码模式显式加载 DSH 的 tsx 和 TypeScript 配置,保持源码模块解析正常。补充后端安装、启动校验、启用及失败阶段日志,方便定位面板接入问题。
|
|
11
|
+
|
|
12
|
+
### English
|
|
13
|
+
|
|
14
|
+
- Fixed DSH setup failing after installation when its launch directory caused it to read proxy settings from FoxClaw's `.env`. Launch in an isolated runtime directory, inherit the service environment, and pass session workspaces separately through ACP.
|
|
15
|
+
- Resolve the DSH source checkout's tsx loader and TypeScript configuration explicitly. Added provisioning stage, duration and failure logs for backend setup diagnostics.
|
|
16
|
+
|
|
5
17
|
## 0.13.2 - 2026-10-06
|
|
6
18
|
|
|
7
19
|
### 中文
|
package/dist/dsh/client.js
CHANGED
|
@@ -5,6 +5,7 @@ import fs from 'node:fs/promises';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
7
7
|
import { createHash } from 'node:crypto';
|
|
8
|
+
import { createRequire } from 'node:module';
|
|
8
9
|
import { ClientApp, ndJsonStream, PROTOCOL_VERSION } from '@agentclientprotocol/sdk';
|
|
9
10
|
/** An owned ACP process; protocol stdout stays separate from diagnostics. */
|
|
10
11
|
export class DshClient extends EventEmitter {
|
|
@@ -65,19 +66,27 @@ export class DshClient extends EventEmitter {
|
|
|
65
66
|
}
|
|
66
67
|
await fs.writeFile(patchPath, `- insert:\n - id: foxclaw-permissions\n name: ${JSON.stringify(pathToFileURL(pluginPath).href)}\n config:\n policyPath: ${JSON.stringify(this.policyPath)}\n`, { mode: 0o600 });
|
|
67
68
|
const args = ['--profile', this.options.profile, ...this.options.patches.flatMap(p => ['--patch', path.resolve(p)]), '--patch', patchPath];
|
|
69
|
+
const env = { ...process.env, ...(this.options.home ? { DSH_HOME: this.options.home } : {}) };
|
|
68
70
|
let command = this.options.cliBin;
|
|
69
|
-
|
|
71
|
+
// DSH reads .env in its launch directory. The service directory belongs to
|
|
72
|
+
// FoxClaw; session/new supplies the actual workspace independently.
|
|
73
|
+
const cwd = path.dirname(this.policyPath);
|
|
70
74
|
if (this.options.sourceDir) {
|
|
71
|
-
|
|
75
|
+
const sourceDir = path.resolve(this.options.sourceDir);
|
|
76
|
+
const tsx = createRequire(path.join(sourceDir, 'package.json')).resolve('tsx/esm');
|
|
77
|
+
env.TSX_TSCONFIG_PATH = path.join(sourceDir, 'tsconfig.json');
|
|
72
78
|
command = process.execPath;
|
|
73
|
-
args.unshift('--import',
|
|
79
|
+
args.unshift('--import', pathToFileURL(tsx).href, path.join(sourceDir, 'apps/cli/src/bin.ts'));
|
|
74
80
|
}
|
|
75
81
|
else if (/\.[cm]?js$/.test(command)) {
|
|
76
82
|
args.unshift(path.resolve(command));
|
|
77
83
|
command = process.execPath;
|
|
78
84
|
}
|
|
85
|
+
else if (command.includes('/') || command.includes('\\')) {
|
|
86
|
+
command = path.resolve(command);
|
|
87
|
+
}
|
|
79
88
|
signal?.throwIfAborted();
|
|
80
|
-
const child = spawn(command, args, { cwd, env
|
|
89
|
+
const child = spawn(command, args, { cwd, env, stdio: 'pipe', windowsHide: true });
|
|
81
90
|
this.process = child;
|
|
82
91
|
this.stderr = '';
|
|
83
92
|
this.optionsBySession.clear();
|
package/dist/main.js
CHANGED
|
@@ -720,7 +720,7 @@ async function runServeCli() {
|
|
|
720
720
|
codexCliBin: config.codexCliBin,
|
|
721
721
|
agyCliBin: config.antigravityCliBin,
|
|
722
722
|
});
|
|
723
|
-
const backendSetup = new BackendSetupManager([createDshSetupDefinition(logger)], config.envPath ?? DEFAULT_ENV_PATH, async () => (await selfUpdater.readStatus())?.state !== 'pending');
|
|
723
|
+
const backendSetup = new BackendSetupManager([createDshSetupDefinition(logger)], config.envPath ?? DEFAULT_ENV_PATH, async () => (await selfUpdater.readStatus())?.state !== 'pending', logger);
|
|
724
724
|
supervisor.register('backend-setup', { stop: () => backendSetup.stop() });
|
|
725
725
|
sharedAntigravityAuth = new AntigravityAuthManager(config.antigravityAuthDir, logger);
|
|
726
726
|
sharedAntigravityApp = new AntigravityAppClient(config.antigravityCliBin, logger);
|
|
@@ -30,11 +30,12 @@ export interface BackendSetupDefinition {
|
|
|
30
30
|
export declare class BackendSetupManager {
|
|
31
31
|
private readonly envPath;
|
|
32
32
|
private readonly canConfigure;
|
|
33
|
+
private readonly logger?;
|
|
33
34
|
readonly definitions: ReadonlyMap<string, BackendSetupDefinition>;
|
|
34
35
|
private readonly targets;
|
|
35
36
|
private active;
|
|
36
37
|
private stopped;
|
|
37
|
-
constructor(definitions: BackendSetupDefinition[], envPath: string, canConfigure?: () => Promise<boolean
|
|
38
|
+
constructor(definitions: BackendSetupDefinition[], envPath: string, canConfigure?: () => Promise<boolean>, logger?: Logger | undefined);
|
|
38
39
|
get busy(): boolean;
|
|
39
40
|
attach(target: (factory: BackendFactory) => void): () => void;
|
|
40
41
|
enable(id: string, candidate?: BackendCandidate): Promise<void>;
|
|
@@ -6,13 +6,15 @@ import { spawn } from 'node:child_process';
|
|
|
6
6
|
export class BackendSetupManager {
|
|
7
7
|
envPath;
|
|
8
8
|
canConfigure;
|
|
9
|
+
logger;
|
|
9
10
|
definitions;
|
|
10
11
|
targets = new Set();
|
|
11
12
|
active = null;
|
|
12
13
|
stopped = false;
|
|
13
|
-
constructor(definitions, envPath, canConfigure = async () => true) {
|
|
14
|
+
constructor(definitions, envPath, canConfigure = async () => true, logger) {
|
|
14
15
|
this.envPath = envPath;
|
|
15
16
|
this.canConfigure = canConfigure;
|
|
17
|
+
this.logger = logger;
|
|
16
18
|
this.definitions = new Map(definitions.map(definition => [definition.id, definition]));
|
|
17
19
|
}
|
|
18
20
|
get busy() { return this.active !== null; }
|
|
@@ -35,19 +37,31 @@ export class BackendSetupManager {
|
|
|
35
37
|
let finish;
|
|
36
38
|
const done = new Promise(resolve => { finish = resolve; });
|
|
37
39
|
this.active = { controller, done };
|
|
40
|
+
const started = Date.now();
|
|
41
|
+
let stage = 'preflight';
|
|
38
42
|
try {
|
|
39
43
|
if (!await this.canConfigure())
|
|
40
44
|
throw new Error('A service update is running; try again when it finishes');
|
|
41
45
|
controller.signal.throwIfAborted();
|
|
46
|
+
stage = candidate ? 'validate' : 'install';
|
|
47
|
+
this.logger?.info('backend.setup.started', { backendId: id, stage });
|
|
42
48
|
const selected = candidate ?? await definition.install?.(controller.signal);
|
|
43
49
|
if (!selected)
|
|
44
50
|
throw new Error('This backend requires a local installation');
|
|
51
|
+
stage = 'validate';
|
|
52
|
+
this.logger?.info('backend.setup.validate', { backendId: id });
|
|
45
53
|
await definition.validate(selected, controller.signal);
|
|
46
54
|
controller.signal.throwIfAborted();
|
|
47
55
|
const factory = definition.factory(selected);
|
|
56
|
+
stage = 'activate';
|
|
48
57
|
writeBackendEnv(this.envPath, selected.updates);
|
|
49
58
|
for (const target of this.targets)
|
|
50
59
|
target(factory);
|
|
60
|
+
this.logger?.info('backend.setup.succeeded', { backendId: id, durationMs: Date.now() - started });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
this.logger?.error('backend.setup.failed', { backendId: id, stage, durationMs: Date.now() - started, error: safeSetupError(error) });
|
|
64
|
+
throw error;
|
|
51
65
|
}
|
|
52
66
|
finally {
|
|
53
67
|
this.active = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foxden-app/foxclaw",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"description": "Foxden local execution claw for controlling Codex, OpenCode, Antigravity, and DeepSeek Harness from trusted chat interfaces.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|