sessix-server 0.3.6 → 0.3.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/index.js +24 -29
- package/dist/server.js +24 -29
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -403,7 +403,7 @@ var ProcessProvider = class {
|
|
|
403
403
|
* 并开始监听 stdout 的 NDJSON 输出。
|
|
404
404
|
*/
|
|
405
405
|
async startSession(opts) {
|
|
406
|
-
const { projectPath, message, sessionId: existingSessionId, model, permissionMode, effort, images } = opts;
|
|
406
|
+
const { projectPath, message, sessionId: existingSessionId, model, permissionMode, effort, images, fallbackModel, maxBudgetUsd } = opts;
|
|
407
407
|
const sessionId = existingSessionId ?? (0, import_uuid.v4)();
|
|
408
408
|
if (this.activeSessions.has(sessionId)) {
|
|
409
409
|
await this.killSession(sessionId);
|
|
@@ -419,10 +419,10 @@ var ProcessProvider = class {
|
|
|
419
419
|
summary: message.slice(0, 80)
|
|
420
420
|
};
|
|
421
421
|
const resume = opts.resume ?? !!existingSessionId;
|
|
422
|
-
const proc = this.spawnClaudeProcess(sessionId, projectPath, resume, model, permissionMode, effort);
|
|
422
|
+
const proc = this.spawnClaudeProcess(sessionId, projectPath, resume, model, permissionMode, effort, fallbackModel, maxBudgetUsd);
|
|
423
423
|
this.writeUserMessage(proc, message, sessionId, images);
|
|
424
424
|
session.pid = proc.pid;
|
|
425
|
-
this.activeSessions.set(sessionId, { session, process: proc, model, permissionMode, effort });
|
|
425
|
+
this.activeSessions.set(sessionId, { session, process: proc, model, permissionMode, effort, fallbackModel, maxBudgetUsd });
|
|
426
426
|
proc.on("error", (err) => {
|
|
427
427
|
console.error(`[ProcessProvider] Session ${sessionId} process error:`, err.message);
|
|
428
428
|
this.activeSessions.delete(sessionId);
|
|
@@ -494,7 +494,7 @@ var ProcessProvider = class {
|
|
|
494
494
|
}
|
|
495
495
|
const savedPendingQuestion = entry.pendingQuestion;
|
|
496
496
|
const newMode = permissionMode ?? entry.permissionMode;
|
|
497
|
-
const proc = this.spawnClaudeProcess(sessionId, entry.session.projectPath, true, entry.model, newMode, entry.effort);
|
|
497
|
+
const proc = this.spawnClaudeProcess(sessionId, entry.session.projectPath, true, entry.model, newMode, entry.effort, entry.fallbackModel, entry.maxBudgetUsd);
|
|
498
498
|
this.writeUserMessage(proc, message, sessionId, images);
|
|
499
499
|
entry.session.status = "running";
|
|
500
500
|
entry.session.lastActiveAt = Date.now();
|
|
@@ -544,14 +544,15 @@ var ProcessProvider = class {
|
|
|
544
544
|
/**
|
|
545
545
|
* 启动 claude CLI 进程(持久模式,stdin 保持开放接收多条消息)
|
|
546
546
|
*/
|
|
547
|
-
spawnClaudeProcess(sessionId, projectPath, resume = false, model, permissionMode, effort) {
|
|
547
|
+
spawnClaudeProcess(sessionId, projectPath, resume = false, model, permissionMode, effort, fallbackModel, maxBudgetUsd) {
|
|
548
548
|
const args = [
|
|
549
549
|
"--input-format",
|
|
550
550
|
"stream-json",
|
|
551
551
|
"--output-format",
|
|
552
552
|
"stream-json",
|
|
553
553
|
"--verbose",
|
|
554
|
-
"--include-partial-messages"
|
|
554
|
+
"--include-partial-messages",
|
|
555
|
+
"--include-hook-events"
|
|
555
556
|
];
|
|
556
557
|
if (resume) {
|
|
557
558
|
args.push("--resume", sessionId);
|
|
@@ -567,6 +568,12 @@ var ProcessProvider = class {
|
|
|
567
568
|
if (effort) {
|
|
568
569
|
args.push("--effort", effort);
|
|
569
570
|
}
|
|
571
|
+
if (fallbackModel) {
|
|
572
|
+
args.push("--fallback-model", fallbackModel);
|
|
573
|
+
}
|
|
574
|
+
if (maxBudgetUsd != null) {
|
|
575
|
+
args.push("--max-budget-usd", String(maxBudgetUsd));
|
|
576
|
+
}
|
|
570
577
|
const env = { ...process.env, SESSIX_SESSION_ID: sessionId };
|
|
571
578
|
delete env.CLAUDECODE;
|
|
572
579
|
const proc = (0, import_child_process.spawn)(CLAUDE_PATH, args, {
|
|
@@ -1677,7 +1684,7 @@ var SessionManager = class {
|
|
|
1677
1684
|
* 调用 provider.startSession(),订阅事件流,
|
|
1678
1685
|
* 将 ClaudeStreamEvent 包装为 ServerEvent 转发。
|
|
1679
1686
|
*/
|
|
1680
|
-
async createSession(projectPath, message, resumeSessionId, newSessionId, model, permissionMode, effort, images, agentType) {
|
|
1687
|
+
async createSession(projectPath, message, resumeSessionId, newSessionId, model, permissionMode, effort, images, agentType, fallbackModel, maxBudgetUsd) {
|
|
1681
1688
|
let resolvedAgentType = agentType ?? "claude-code";
|
|
1682
1689
|
if (!agentType && resumeSessionId && this.providerFactory) {
|
|
1683
1690
|
const codexProvider = this.providerFactory.getProvider("codex");
|
|
@@ -1694,7 +1701,9 @@ var SessionManager = class {
|
|
|
1694
1701
|
model,
|
|
1695
1702
|
permissionMode,
|
|
1696
1703
|
effort,
|
|
1697
|
-
images
|
|
1704
|
+
images,
|
|
1705
|
+
fallbackModel,
|
|
1706
|
+
maxBudgetUsd
|
|
1698
1707
|
});
|
|
1699
1708
|
this.sessionAgentType.set(session.id, resolvedAgentType);
|
|
1700
1709
|
this.lastBroadcastStatus.set(session.id, session.status);
|
|
@@ -2335,7 +2344,7 @@ var WsBridge = class _WsBridge {
|
|
|
2335
2344
|
onConnection(callback) {
|
|
2336
2345
|
this.connectionCallbacks.push(callback);
|
|
2337
2346
|
}
|
|
2338
|
-
/**
|
|
2347
|
+
/** 注册断开连接回调(任意客户端断开时触发,可通过 getConnectionCount() 判断是否全部断开) */
|
|
2339
2348
|
onDisconnect(callback) {
|
|
2340
2349
|
this.disconnectCallbacks.push(callback);
|
|
2341
2350
|
}
|
|
@@ -2449,7 +2458,7 @@ var WsBridge = class _WsBridge {
|
|
|
2449
2458
|
console.log(`[WsBridge] Client disconnected, connections: ${this.getConnectionCount()}`);
|
|
2450
2459
|
for (const cb of this.disconnectCallbacks) {
|
|
2451
2460
|
try {
|
|
2452
|
-
cb(
|
|
2461
|
+
cb();
|
|
2453
2462
|
} catch (err) {
|
|
2454
2463
|
console.error("[WsBridge] Disconnect callback error:", err);
|
|
2455
2464
|
}
|
|
@@ -3318,10 +3327,6 @@ var NotificationService = class {
|
|
|
3318
3327
|
setConnectionCountProvider(provider) {
|
|
3319
3328
|
this.connectionCountProvider = provider;
|
|
3320
3329
|
}
|
|
3321
|
-
/** 移除指定 WebSocket 关联的所有 push token */
|
|
3322
|
-
removeTokensByWs(ws) {
|
|
3323
|
-
this.expoChannel?.removeTokensByWs(ws);
|
|
3324
|
-
}
|
|
3325
3330
|
/** 获取全局待审批总数 */
|
|
3326
3331
|
getGlobalPendingCount() {
|
|
3327
3332
|
return this.globalPendingCountProvider?.() ?? 0;
|
|
@@ -3574,17 +3579,6 @@ var ExpoNotificationChannel = class {
|
|
|
3574
3579
|
this.soundPreferences.delete(token);
|
|
3575
3580
|
console.log(`[ExpoNotificationChannel] ${t("notification.tokenRemoved", { count: this.tokens.size })}`);
|
|
3576
3581
|
}
|
|
3577
|
-
/** 移除指定 WebSocket 关联的所有 token(设备断开时调用) */
|
|
3578
|
-
removeTokensByWs(ws) {
|
|
3579
|
-
for (const [token, tokenWs] of this.tokenWsMap) {
|
|
3580
|
-
if (tokenWs === ws) {
|
|
3581
|
-
this.tokens.delete(token);
|
|
3582
|
-
this.tokenWsMap.delete(token);
|
|
3583
|
-
this.soundPreferences.delete(token);
|
|
3584
|
-
console.log(`[ExpoNotificationChannel] Token removed on WS disconnect, remaining: ${this.tokens.size}`);
|
|
3585
|
-
}
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
3582
|
/** 更新某个 token 的音效偏好 */
|
|
3589
3583
|
setSoundPreferences(prefs) {
|
|
3590
3584
|
for (const token of this.tokens) {
|
|
@@ -4434,7 +4428,7 @@ var TerminalExecutor = class {
|
|
|
4434
4428
|
// src/utils/cliCapabilities.ts
|
|
4435
4429
|
var import_node_child_process8 = require("child_process");
|
|
4436
4430
|
var DEFAULT_CAPABILITIES = {
|
|
4437
|
-
effortLevels: ["low", "medium", "high", "max"]
|
|
4431
|
+
effortLevels: ["low", "medium", "high", "xhigh", "max"]
|
|
4438
4432
|
};
|
|
4439
4433
|
async function parseCliCapabilities() {
|
|
4440
4434
|
const claudePath = findClaudePath();
|
|
@@ -4643,7 +4637,9 @@ async function start(opts = {}) {
|
|
|
4643
4637
|
event.permissionMode,
|
|
4644
4638
|
event.effort,
|
|
4645
4639
|
event.images,
|
|
4646
|
-
event.agentType
|
|
4640
|
+
event.agentType,
|
|
4641
|
+
event.fallbackModel,
|
|
4642
|
+
event.maxBudgetUsd
|
|
4647
4643
|
);
|
|
4648
4644
|
wsBridge.broadcast({
|
|
4649
4645
|
type: "session_list",
|
|
@@ -4961,8 +4957,7 @@ async function start(opts = {}) {
|
|
|
4961
4957
|
terminalExecutor.onEvent((event) => {
|
|
4962
4958
|
wsBridge.broadcast(event);
|
|
4963
4959
|
});
|
|
4964
|
-
wsBridge.onDisconnect((
|
|
4965
|
-
notificationService.removeTokensByWs(ws);
|
|
4960
|
+
wsBridge.onDisconnect(() => {
|
|
4966
4961
|
if (wsBridge.getConnectionCount() === 0 && approvalProxy.getPendingCount() > 0) {
|
|
4967
4962
|
approvalProxy.approveAll(t("server.phoneDisconnected"));
|
|
4968
4963
|
}
|
package/dist/server.js
CHANGED
|
@@ -408,7 +408,7 @@ var ProcessProvider = class {
|
|
|
408
408
|
* 并开始监听 stdout 的 NDJSON 输出。
|
|
409
409
|
*/
|
|
410
410
|
async startSession(opts) {
|
|
411
|
-
const { projectPath, message, sessionId: existingSessionId, model, permissionMode, effort, images } = opts;
|
|
411
|
+
const { projectPath, message, sessionId: existingSessionId, model, permissionMode, effort, images, fallbackModel, maxBudgetUsd } = opts;
|
|
412
412
|
const sessionId = existingSessionId ?? (0, import_uuid.v4)();
|
|
413
413
|
if (this.activeSessions.has(sessionId)) {
|
|
414
414
|
await this.killSession(sessionId);
|
|
@@ -424,10 +424,10 @@ var ProcessProvider = class {
|
|
|
424
424
|
summary: message.slice(0, 80)
|
|
425
425
|
};
|
|
426
426
|
const resume = opts.resume ?? !!existingSessionId;
|
|
427
|
-
const proc = this.spawnClaudeProcess(sessionId, projectPath, resume, model, permissionMode, effort);
|
|
427
|
+
const proc = this.spawnClaudeProcess(sessionId, projectPath, resume, model, permissionMode, effort, fallbackModel, maxBudgetUsd);
|
|
428
428
|
this.writeUserMessage(proc, message, sessionId, images);
|
|
429
429
|
session.pid = proc.pid;
|
|
430
|
-
this.activeSessions.set(sessionId, { session, process: proc, model, permissionMode, effort });
|
|
430
|
+
this.activeSessions.set(sessionId, { session, process: proc, model, permissionMode, effort, fallbackModel, maxBudgetUsd });
|
|
431
431
|
proc.on("error", (err) => {
|
|
432
432
|
console.error(`[ProcessProvider] Session ${sessionId} process error:`, err.message);
|
|
433
433
|
this.activeSessions.delete(sessionId);
|
|
@@ -499,7 +499,7 @@ var ProcessProvider = class {
|
|
|
499
499
|
}
|
|
500
500
|
const savedPendingQuestion = entry.pendingQuestion;
|
|
501
501
|
const newMode = permissionMode ?? entry.permissionMode;
|
|
502
|
-
const proc = this.spawnClaudeProcess(sessionId, entry.session.projectPath, true, entry.model, newMode, entry.effort);
|
|
502
|
+
const proc = this.spawnClaudeProcess(sessionId, entry.session.projectPath, true, entry.model, newMode, entry.effort, entry.fallbackModel, entry.maxBudgetUsd);
|
|
503
503
|
this.writeUserMessage(proc, message, sessionId, images);
|
|
504
504
|
entry.session.status = "running";
|
|
505
505
|
entry.session.lastActiveAt = Date.now();
|
|
@@ -549,14 +549,15 @@ var ProcessProvider = class {
|
|
|
549
549
|
/**
|
|
550
550
|
* 启动 claude CLI 进程(持久模式,stdin 保持开放接收多条消息)
|
|
551
551
|
*/
|
|
552
|
-
spawnClaudeProcess(sessionId, projectPath, resume = false, model, permissionMode, effort) {
|
|
552
|
+
spawnClaudeProcess(sessionId, projectPath, resume = false, model, permissionMode, effort, fallbackModel, maxBudgetUsd) {
|
|
553
553
|
const args = [
|
|
554
554
|
"--input-format",
|
|
555
555
|
"stream-json",
|
|
556
556
|
"--output-format",
|
|
557
557
|
"stream-json",
|
|
558
558
|
"--verbose",
|
|
559
|
-
"--include-partial-messages"
|
|
559
|
+
"--include-partial-messages",
|
|
560
|
+
"--include-hook-events"
|
|
560
561
|
];
|
|
561
562
|
if (resume) {
|
|
562
563
|
args.push("--resume", sessionId);
|
|
@@ -572,6 +573,12 @@ var ProcessProvider = class {
|
|
|
572
573
|
if (effort) {
|
|
573
574
|
args.push("--effort", effort);
|
|
574
575
|
}
|
|
576
|
+
if (fallbackModel) {
|
|
577
|
+
args.push("--fallback-model", fallbackModel);
|
|
578
|
+
}
|
|
579
|
+
if (maxBudgetUsd != null) {
|
|
580
|
+
args.push("--max-budget-usd", String(maxBudgetUsd));
|
|
581
|
+
}
|
|
575
582
|
const env = { ...process.env, SESSIX_SESSION_ID: sessionId };
|
|
576
583
|
delete env.CLAUDECODE;
|
|
577
584
|
const proc = (0, import_child_process.spawn)(CLAUDE_PATH, args, {
|
|
@@ -1682,7 +1689,7 @@ var SessionManager = class {
|
|
|
1682
1689
|
* 调用 provider.startSession(),订阅事件流,
|
|
1683
1690
|
* 将 ClaudeStreamEvent 包装为 ServerEvent 转发。
|
|
1684
1691
|
*/
|
|
1685
|
-
async createSession(projectPath, message, resumeSessionId, newSessionId, model, permissionMode, effort, images, agentType) {
|
|
1692
|
+
async createSession(projectPath, message, resumeSessionId, newSessionId, model, permissionMode, effort, images, agentType, fallbackModel, maxBudgetUsd) {
|
|
1686
1693
|
let resolvedAgentType = agentType ?? "claude-code";
|
|
1687
1694
|
if (!agentType && resumeSessionId && this.providerFactory) {
|
|
1688
1695
|
const codexProvider = this.providerFactory.getProvider("codex");
|
|
@@ -1699,7 +1706,9 @@ var SessionManager = class {
|
|
|
1699
1706
|
model,
|
|
1700
1707
|
permissionMode,
|
|
1701
1708
|
effort,
|
|
1702
|
-
images
|
|
1709
|
+
images,
|
|
1710
|
+
fallbackModel,
|
|
1711
|
+
maxBudgetUsd
|
|
1703
1712
|
});
|
|
1704
1713
|
this.sessionAgentType.set(session.id, resolvedAgentType);
|
|
1705
1714
|
this.lastBroadcastStatus.set(session.id, session.status);
|
|
@@ -2340,7 +2349,7 @@ var WsBridge = class _WsBridge {
|
|
|
2340
2349
|
onConnection(callback) {
|
|
2341
2350
|
this.connectionCallbacks.push(callback);
|
|
2342
2351
|
}
|
|
2343
|
-
/**
|
|
2352
|
+
/** 注册断开连接回调(任意客户端断开时触发,可通过 getConnectionCount() 判断是否全部断开) */
|
|
2344
2353
|
onDisconnect(callback) {
|
|
2345
2354
|
this.disconnectCallbacks.push(callback);
|
|
2346
2355
|
}
|
|
@@ -2454,7 +2463,7 @@ var WsBridge = class _WsBridge {
|
|
|
2454
2463
|
console.log(`[WsBridge] Client disconnected, connections: ${this.getConnectionCount()}`);
|
|
2455
2464
|
for (const cb of this.disconnectCallbacks) {
|
|
2456
2465
|
try {
|
|
2457
|
-
cb(
|
|
2466
|
+
cb();
|
|
2458
2467
|
} catch (err) {
|
|
2459
2468
|
console.error("[WsBridge] Disconnect callback error:", err);
|
|
2460
2469
|
}
|
|
@@ -3323,10 +3332,6 @@ var NotificationService = class {
|
|
|
3323
3332
|
setConnectionCountProvider(provider) {
|
|
3324
3333
|
this.connectionCountProvider = provider;
|
|
3325
3334
|
}
|
|
3326
|
-
/** 移除指定 WebSocket 关联的所有 push token */
|
|
3327
|
-
removeTokensByWs(ws) {
|
|
3328
|
-
this.expoChannel?.removeTokensByWs(ws);
|
|
3329
|
-
}
|
|
3330
3335
|
/** 获取全局待审批总数 */
|
|
3331
3336
|
getGlobalPendingCount() {
|
|
3332
3337
|
return this.globalPendingCountProvider?.() ?? 0;
|
|
@@ -3579,17 +3584,6 @@ var ExpoNotificationChannel = class {
|
|
|
3579
3584
|
this.soundPreferences.delete(token);
|
|
3580
3585
|
console.log(`[ExpoNotificationChannel] ${t("notification.tokenRemoved", { count: this.tokens.size })}`);
|
|
3581
3586
|
}
|
|
3582
|
-
/** 移除指定 WebSocket 关联的所有 token(设备断开时调用) */
|
|
3583
|
-
removeTokensByWs(ws) {
|
|
3584
|
-
for (const [token, tokenWs] of this.tokenWsMap) {
|
|
3585
|
-
if (tokenWs === ws) {
|
|
3586
|
-
this.tokens.delete(token);
|
|
3587
|
-
this.tokenWsMap.delete(token);
|
|
3588
|
-
this.soundPreferences.delete(token);
|
|
3589
|
-
console.log(`[ExpoNotificationChannel] Token removed on WS disconnect, remaining: ${this.tokens.size}`);
|
|
3590
|
-
}
|
|
3591
|
-
}
|
|
3592
|
-
}
|
|
3593
3587
|
/** 更新某个 token 的音效偏好 */
|
|
3594
3588
|
setSoundPreferences(prefs) {
|
|
3595
3589
|
for (const token of this.tokens) {
|
|
@@ -4439,7 +4433,7 @@ var TerminalExecutor = class {
|
|
|
4439
4433
|
// src/utils/cliCapabilities.ts
|
|
4440
4434
|
var import_node_child_process8 = require("child_process");
|
|
4441
4435
|
var DEFAULT_CAPABILITIES = {
|
|
4442
|
-
effortLevels: ["low", "medium", "high", "max"]
|
|
4436
|
+
effortLevels: ["low", "medium", "high", "xhigh", "max"]
|
|
4443
4437
|
};
|
|
4444
4438
|
async function parseCliCapabilities() {
|
|
4445
4439
|
const claudePath = findClaudePath();
|
|
@@ -4648,7 +4642,9 @@ async function start(opts = {}) {
|
|
|
4648
4642
|
event.permissionMode,
|
|
4649
4643
|
event.effort,
|
|
4650
4644
|
event.images,
|
|
4651
|
-
event.agentType
|
|
4645
|
+
event.agentType,
|
|
4646
|
+
event.fallbackModel,
|
|
4647
|
+
event.maxBudgetUsd
|
|
4652
4648
|
);
|
|
4653
4649
|
wsBridge.broadcast({
|
|
4654
4650
|
type: "session_list",
|
|
@@ -4966,8 +4962,7 @@ async function start(opts = {}) {
|
|
|
4966
4962
|
terminalExecutor.onEvent((event) => {
|
|
4967
4963
|
wsBridge.broadcast(event);
|
|
4968
4964
|
});
|
|
4969
|
-
wsBridge.onDisconnect((
|
|
4970
|
-
notificationService.removeTokensByWs(ws);
|
|
4965
|
+
wsBridge.onDisconnect(() => {
|
|
4971
4966
|
if (wsBridge.getConnectionCount() === 0 && approvalProxy.getPendingCount() > 0) {
|
|
4972
4967
|
approvalProxy.approveAll(t("server.phoneDisconnected"));
|
|
4973
4968
|
}
|