chatroom-cli 1.127.0 → 1.128.1
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 +463 -92
- package/dist/index.js.map +16 -13
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -20251,6 +20251,16 @@ var init_agent_process_manager_service = __esm(() => {
|
|
|
20251
20251
|
init_check_agent_slot();
|
|
20252
20252
|
});
|
|
20253
20253
|
|
|
20254
|
+
// ../../services/backend/config/reliability.ts
|
|
20255
|
+
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, NATIVE_DELIVERY_RECONCILE_MS = 1e4, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, MACHINE_COMMAND_LEASE_RENEWAL_INTERVAL_MS = 20000, MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS, SCOPE_TARGET_STOP_TIMEOUT_MS = 1e4, AGENT_LIFECYCLE_OPERATION_TIMEOUT_MS = 120000, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
|
|
20256
|
+
var init_reliability = __esm(() => {
|
|
20257
|
+
DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
|
|
20258
|
+
DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
|
|
20259
|
+
MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS = 5 * 60000;
|
|
20260
|
+
CONNECTION_CLOSE_REQUEST_TTL_MS = 10 * 60000;
|
|
20261
|
+
ENHANCER_TERMINAL_JOB_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
20262
|
+
});
|
|
20263
|
+
|
|
20254
20264
|
// ../shared/src/domain/team-kind.ts
|
|
20255
20265
|
var TEAM_PRESET_IDS;
|
|
20256
20266
|
var init_team_kind = __esm(() => {
|
|
@@ -35229,8 +35239,10 @@ var init_agent_lifecycle_fact = __esm(() => {
|
|
|
35229
35239
|
function isDeliverableTaskStatus(status) {
|
|
35230
35240
|
return status === "pending" || status === "acknowledged";
|
|
35231
35241
|
}
|
|
35242
|
+
var ACTIVE_TASK_STATUSES;
|
|
35232
35243
|
var init_assigned_task = __esm(() => {
|
|
35233
35244
|
init_agent_role();
|
|
35245
|
+
ACTIVE_TASK_STATUSES = ["pending", "acknowledged", "in_progress"];
|
|
35234
35246
|
});
|
|
35235
35247
|
|
|
35236
35248
|
// src/daemon/infrastructure/local/harness/services/spawn-prompt.ts
|
|
@@ -35292,6 +35304,17 @@ var init_native_task_injector_logic = __esm(() => {
|
|
|
35292
35304
|
};
|
|
35293
35305
|
});
|
|
35294
35306
|
|
|
35307
|
+
// src/daemon/services/task-service/domain/usecase/uncovered-turn-nudge.ts
|
|
35308
|
+
function buildUncoveredTurnNudgePrompt(args2) {
|
|
35309
|
+
return [
|
|
35310
|
+
`Your previous turn ended, but task ${args2.taskId} has no handoff recorded.`,
|
|
35311
|
+
"If the work is complete, run `chatroom handoff` for this task now, as instructed in the task.",
|
|
35312
|
+
"If you are waiting on something (for example a background command or CI), do not end your turn: wait for it in the foreground, then run `chatroom handoff`.",
|
|
35313
|
+
"If you cannot do either, reply with one line saying what you are waiting on."
|
|
35314
|
+
].join(`
|
|
35315
|
+
`);
|
|
35316
|
+
}
|
|
35317
|
+
|
|
35295
35318
|
// ../../services/backend/src/domain/entities/participant.ts
|
|
35296
35319
|
var NATIVE_WAITING_ACTION = "native:waiting", NATIVE_TASK_INJECTED_ACTION = "native:task-injected", GET_NEXT_TASK_STARTED_ACTION = "get-next-task:started";
|
|
35297
35320
|
|
|
@@ -36324,16 +36347,6 @@ var init_parse_session_augmentation = __esm(() => {
|
|
|
36324
36347
|
init_team_agent_settings();
|
|
36325
36348
|
});
|
|
36326
36349
|
|
|
36327
|
-
// ../../services/backend/config/reliability.ts
|
|
36328
|
-
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, NATIVE_DELIVERY_RECONCILE_MS = 1e4, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, MACHINE_COMMAND_LEASE_RENEWAL_INTERVAL_MS = 20000, MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS, SCOPE_TARGET_STOP_TIMEOUT_MS = 1e4, AGENT_LIFECYCLE_OPERATION_TIMEOUT_MS = 120000, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
|
|
36329
|
-
var init_reliability = __esm(() => {
|
|
36330
|
-
DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
|
|
36331
|
-
DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
|
|
36332
|
-
MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS = 5 * 60000;
|
|
36333
|
-
CONNECTION_CLOSE_REQUEST_TTL_MS = 10 * 60000;
|
|
36334
|
-
ENHANCER_TERMINAL_JOB_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
36335
|
-
});
|
|
36336
|
-
|
|
36337
36350
|
// src/daemon/services/task-service/service/native-cold-session-before-inject.ts
|
|
36338
36351
|
function sleep3(ms) {
|
|
36339
36352
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
@@ -36603,7 +36616,7 @@ function resumeHarnessWithPrompt(task, deps, prompt, harnessSessionId) {
|
|
|
36603
36616
|
taskId,
|
|
36604
36617
|
error: error51
|
|
36605
36618
|
});
|
|
36606
|
-
return;
|
|
36619
|
+
return yield* exports_Effect.fail(resumeResult.failure);
|
|
36607
36620
|
}
|
|
36608
36621
|
yield* exports_Effect.tryPromise({
|
|
36609
36622
|
try: () => deps.audit.emit({
|
|
@@ -36732,6 +36745,8 @@ class AgentWorkManager {
|
|
|
36732
36745
|
nativeTaskDeliveryQueue;
|
|
36733
36746
|
deliveryTaskService;
|
|
36734
36747
|
recoveryGates = new Map;
|
|
36748
|
+
respawnStartRetries = new Map;
|
|
36749
|
+
respawnRestartSeq = 0;
|
|
36735
36750
|
disposed = false;
|
|
36736
36751
|
constructor(deps) {
|
|
36737
36752
|
this.deps = deps;
|
|
@@ -36763,7 +36778,10 @@ class AgentWorkManager {
|
|
|
36763
36778
|
releaseTaskAfterTurnFailure: deps.taskService.releaseTaskAfterTurnFailure,
|
|
36764
36779
|
recordDeliveryFailure: deps.taskService.recordDeliveryFailure,
|
|
36765
36780
|
clearDeliveryFailure: deps.taskService.clearDeliveryFailure,
|
|
36766
|
-
|
|
36781
|
+
recordTurnFailure: deps.taskService.recordTurnFailure,
|
|
36782
|
+
decideUncoveredTurnEnd: deps.taskService.decideUncoveredTurnEnd,
|
|
36783
|
+
confirmNudgeSent: deps.taskService.confirmNudgeSent,
|
|
36784
|
+
resetTurnTracking: deps.taskService.resetTurnTracking,
|
|
36767
36785
|
isRedeliveryExhausted: deps.taskService.isRedeliveryExhausted,
|
|
36768
36786
|
clearRedeliveryTracking: deps.taskService.clearRedeliveryTracking,
|
|
36769
36787
|
forgetStaleTask: deps.taskService.forgetStaleTask,
|
|
@@ -36789,6 +36807,7 @@ class AgentWorkManager {
|
|
|
36789
36807
|
this.unsubscribeTaskService = deps.taskService.subscribe((notification) => this.handleTaskServiceNotification(notification));
|
|
36790
36808
|
}
|
|
36791
36809
|
async handleAgentStarted(event) {
|
|
36810
|
+
this.cancelRespawnStart(recoveryKey(event.chatroomId, event.role), `agent_started:${event.reason ?? "unknown"}`);
|
|
36792
36811
|
await this.waitForRoleRecovery(event.chatroomId, event.role);
|
|
36793
36812
|
this.deps.agentTaskState.clear({ chatroomId: event.chatroomId, role: event.role });
|
|
36794
36813
|
if (event.reason === "user.start") {
|
|
@@ -36906,9 +36925,9 @@ class AgentWorkManager {
|
|
|
36906
36925
|
});
|
|
36907
36926
|
}, delay3);
|
|
36908
36927
|
}
|
|
36909
|
-
async
|
|
36928
|
+
async recoverTaskAfterTurnFailure(event, activeTask, phase) {
|
|
36910
36929
|
const { chatroomId, role } = event;
|
|
36911
|
-
const { exceeded } = await this.deps.taskService.
|
|
36930
|
+
const { exceeded } = await this.deps.taskService.recordTurnFailure({
|
|
36912
36931
|
chatroomId,
|
|
36913
36932
|
role,
|
|
36914
36933
|
taskId: activeTask.taskId
|
|
@@ -36937,7 +36956,7 @@ class AgentWorkManager {
|
|
|
36937
36956
|
const errorDetail = completion.error;
|
|
36938
36957
|
console.error(`[NativeDelivery:turn-failed] chatroom=${event.chatroomId} role=${event.role} task=${activeTask2?.taskId ?? "none"} turn=${completion.turnId} status=${completion.status} source=${completion.source} error=${errorDetail ?? "none"}`);
|
|
36939
36958
|
if (activeTask2) {
|
|
36940
|
-
const recovery = await this.
|
|
36959
|
+
const recovery = await this.recoverTaskAfterTurnFailure(event, activeTask2, "turn-failed");
|
|
36941
36960
|
if (recovery === "exceeded") {
|
|
36942
36961
|
this.deps.agentTaskState.clear({ chatroomId: event.chatroomId, role: event.role });
|
|
36943
36962
|
return { kind: "release-slot" };
|
|
@@ -36977,14 +36996,41 @@ class AgentWorkManager {
|
|
|
36977
36996
|
});
|
|
36978
36997
|
if (activeTask) {
|
|
36979
36998
|
const handoff = await this.deps.taskService.getLatestHandoff(event.chatroomId, event.role);
|
|
36980
|
-
|
|
36981
|
-
|
|
36982
|
-
|
|
36983
|
-
|
|
36999
|
+
const covered = handoff?.taskIds.includes(activeTask.taskId) ?? false;
|
|
37000
|
+
if (covered) {
|
|
37001
|
+
this.deps.taskService.resetTurnTracking({
|
|
37002
|
+
chatroomId: event.chatroomId,
|
|
37003
|
+
role: event.role,
|
|
37004
|
+
taskId: activeTask.taskId
|
|
37005
|
+
});
|
|
37006
|
+
} else {
|
|
37007
|
+
const decision = await this.deps.taskService.decideUncoveredTurnEnd({
|
|
37008
|
+
chatroomId: event.chatroomId,
|
|
37009
|
+
role: event.role,
|
|
37010
|
+
taskId: activeTask.taskId,
|
|
37011
|
+
sessionKey: sessionKeyFor(event.pid, event.slot.harnessSessionId)
|
|
37012
|
+
});
|
|
37013
|
+
if (decision.action === "nudge") {
|
|
37014
|
+
await this.enqueueTurnEndedWaitingFact(event);
|
|
37015
|
+
this.scheduleUncoveredAction(event, activeTask, "nudge");
|
|
37016
|
+
return { kind: "release-slot" };
|
|
36984
37017
|
}
|
|
37018
|
+
if (decision.action === "restart-session") {
|
|
37019
|
+
await this.enqueueTurnEndedWaitingFact(event);
|
|
37020
|
+
this.scheduleUncoveredAction(event, activeTask, "restart-session");
|
|
37021
|
+
return { kind: "release-slot" };
|
|
37022
|
+
}
|
|
37023
|
+
await this.enqueueTurnEndedWaitingFact(event);
|
|
37024
|
+
this.applyParkAction(event);
|
|
37025
|
+
return { kind: "release-slot" };
|
|
36985
37026
|
}
|
|
36986
37027
|
}
|
|
36987
37028
|
this.deps.agentTaskState.clear({ chatroomId: event.chatroomId, role: event.role });
|
|
37029
|
+
await this.enqueueTurnEndedWaitingFact(event);
|
|
37030
|
+
this.scheduleRoleDelivery(event.chatroomId, event.role);
|
|
37031
|
+
return { kind: "release-slot" };
|
|
37032
|
+
}
|
|
37033
|
+
async enqueueTurnEndedWaitingFact(event) {
|
|
36988
37034
|
try {
|
|
36989
37035
|
await this.deps.lifecycleOutbox.enqueue(buildAgentStatusFact({
|
|
36990
37036
|
chatroomId: event.chatroomId,
|
|
@@ -36994,8 +37040,244 @@ class AgentWorkManager {
|
|
|
36994
37040
|
} catch (error51) {
|
|
36995
37041
|
console.error(`[NativeDelivery:turn-ended-outbox-error] chatroom=${event.chatroomId} role=${event.role} error=${error51 instanceof Error ? error51.stack ?? error51.message : String(error51)}`);
|
|
36996
37042
|
}
|
|
37043
|
+
}
|
|
37044
|
+
scheduleUncoveredAction(event, task, action, attempt = 0, delayMs = 0) {
|
|
37045
|
+
setTimeout(() => {
|
|
37046
|
+
if (this.disposed)
|
|
37047
|
+
return;
|
|
37048
|
+
const run = action === "nudge" ? this.sendUncoveredNudge(event, task, attempt) : this.restartSessionForUncoveredTask(event, task);
|
|
37049
|
+
run.catch((error51) => {
|
|
37050
|
+
console.error(`[NativeDelivery:uncovered-action-error] action=${action} chatroom=${event.chatroomId} role=${event.role} task=${task.taskId} error=${error51 instanceof Error ? error51.stack ?? error51.message : String(error51)}`);
|
|
37051
|
+
});
|
|
37052
|
+
}, delayMs);
|
|
37053
|
+
}
|
|
37054
|
+
async sendUncoveredNudge(event, task, attempt = 0) {
|
|
37055
|
+
const { chatroomId, role } = event;
|
|
37056
|
+
const sessionKey = sessionKeyFor(event.pid, event.slot.harnessSessionId);
|
|
37057
|
+
const deliveryState = getRoleDeliveryState();
|
|
37058
|
+
if (!deliveryState.tryAcquireDelivery(chatroomId, role)) {
|
|
37059
|
+
console.log(`[NativeDelivery:uncovered-nudge-skipped] chatroom=${chatroomId} role=${role} task=${task.taskId} reason=delivery_busy`);
|
|
37060
|
+
if (attempt + 1 < MAX_UNCOVERED_NUDGE_SEND_ATTEMPTS) {
|
|
37061
|
+
this.scheduleUncoveredAction(event, task, "nudge", attempt + 1, UNCOVERED_NUDGE_RETRY_MS);
|
|
37062
|
+
return;
|
|
37063
|
+
}
|
|
37064
|
+
await this.escalateUndeliverableNudge(event, task, sessionKey);
|
|
37065
|
+
return;
|
|
37066
|
+
}
|
|
37067
|
+
const generation = deliveryState.getGeneration(chatroomId, role);
|
|
37068
|
+
try {
|
|
37069
|
+
const skipReason = this.uncoveredNudgeSkipReason(event, task);
|
|
37070
|
+
if (skipReason) {
|
|
37071
|
+
console.log(`[NativeDelivery:uncovered-nudge-skipped] chatroom=${chatroomId} role=${role} task=${task.taskId} reason=${skipReason}`);
|
|
37072
|
+
return;
|
|
37073
|
+
}
|
|
37074
|
+
try {
|
|
37075
|
+
await exports_Effect.runPromise(this.deps.agentMgr.resumeTurnForSlot({
|
|
37076
|
+
chatroomId,
|
|
37077
|
+
role,
|
|
37078
|
+
prompt: buildUncoveredTurnNudgePrompt({ taskId: task.taskId })
|
|
37079
|
+
}));
|
|
37080
|
+
} catch (error51) {
|
|
37081
|
+
console.error(`[NativeDelivery:uncovered-nudge] chatroom=${chatroomId} role=${role} task=${task.taskId} error=${error51 instanceof Error ? error51.stack ?? error51.message : String(error51)}`);
|
|
37082
|
+
await this.escalateUndeliverableNudge(event, task, sessionKey);
|
|
37083
|
+
return;
|
|
37084
|
+
}
|
|
37085
|
+
this.deps.taskService.confirmNudgeSent({ chatroomId, role, taskId: task.taskId, sessionKey });
|
|
37086
|
+
} finally {
|
|
37087
|
+
deliveryState.releaseDelivery(chatroomId, role, generation);
|
|
37088
|
+
}
|
|
37089
|
+
}
|
|
37090
|
+
async escalateUndeliverableNudge(event, task, sessionKey) {
|
|
37091
|
+
const decision = await this.deps.taskService.decideUncoveredTurnEnd({
|
|
37092
|
+
chatroomId: event.chatroomId,
|
|
37093
|
+
role: event.role,
|
|
37094
|
+
taskId: task.taskId,
|
|
37095
|
+
sessionKey,
|
|
37096
|
+
nudgeUnavailable: true
|
|
37097
|
+
});
|
|
37098
|
+
if (decision.action === "restart-session") {
|
|
37099
|
+
this.scheduleUncoveredAction(event, task, "restart-session");
|
|
37100
|
+
} else {
|
|
37101
|
+
this.applyParkAction(event);
|
|
37102
|
+
}
|
|
37103
|
+
}
|
|
37104
|
+
async restartSessionForUncoveredTask(event, task) {
|
|
37105
|
+
const { chatroomId, role, pid } = event;
|
|
37106
|
+
const config3 = this.deps.configurationService.get(chatroomId, role);
|
|
37107
|
+
const slot = this.deps.agentMgr.getSlot(chatroomId, role);
|
|
37108
|
+
const harness = config3?.agentHarness ?? slot?.harness;
|
|
37109
|
+
const model = config3?.model ?? slot?.model;
|
|
37110
|
+
const workingDir = config3?.workingDir ?? slot?.workingDir;
|
|
37111
|
+
if (!harness || !model || !workingDir) {
|
|
37112
|
+
console.error(`[NativeDelivery:uncovered-restart-failed] chatroom=${chatroomId} role=${role} task=${task.taskId} error=missing_agent_config`);
|
|
37113
|
+
const sessionKey = sessionKeyFor(event.pid, event.slot.harnessSessionId);
|
|
37114
|
+
await this.deps.taskService.decideUncoveredTurnEnd({
|
|
37115
|
+
chatroomId,
|
|
37116
|
+
role,
|
|
37117
|
+
taskId: task.taskId,
|
|
37118
|
+
sessionKey,
|
|
37119
|
+
nudgeUnavailable: true
|
|
37120
|
+
});
|
|
37121
|
+
this.applyParkAction(event);
|
|
37122
|
+
return;
|
|
37123
|
+
}
|
|
37124
|
+
const startInput = {
|
|
37125
|
+
chatroomId,
|
|
37126
|
+
role,
|
|
37127
|
+
agentHarness: harness,
|
|
37128
|
+
model,
|
|
37129
|
+
workingDir,
|
|
37130
|
+
reason: DaemonStartReasonCode.RESPAWN,
|
|
37131
|
+
wantResume: false
|
|
37132
|
+
};
|
|
37133
|
+
let outcome;
|
|
37134
|
+
try {
|
|
37135
|
+
outcome = await this.deps.runSerializedForAgent({ chatroomId, role, workingDir }, { timeoutMs: AGENT_LIFECYCLE_OPERATION_TIMEOUT_MS }, async (ops, context3) => {
|
|
37136
|
+
const current = this.deps.agentMgr.getSlot(chatroomId, role);
|
|
37137
|
+
if (this.deps.agentMgr.isStopRequested(chatroomId, role) || current?.pid !== pid || current?.harnessSessionId !== event.slot.harnessSessionId) {
|
|
37138
|
+
console.log(`[NativeDelivery:uncovered-restart-stale] chatroom=${chatroomId} role=${role} task=${task.taskId}`);
|
|
37139
|
+
return { kind: "skipped", reason: "stale_slot" };
|
|
37140
|
+
}
|
|
37141
|
+
await this.prepareRoleRecovery({ chatroomId, role });
|
|
37142
|
+
await ops.stopAgent({ chatroomId, role, reason: AgentStopReasonEnum["daemon.respawn"], pid, workingDir }, context3.signal);
|
|
37143
|
+
await this.recoverStoppedRole({ chatroomId, role, mode: "automatic" });
|
|
37144
|
+
return this.attemptRespawnStart(ops, startInput, context3.signal);
|
|
37145
|
+
});
|
|
37146
|
+
} catch (error51) {
|
|
37147
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
37148
|
+
console.error(`[NativeDelivery:uncovered-restart-failed] chatroom=${chatroomId} role=${role} task=${task.taskId} error=${message}`);
|
|
37149
|
+
if (this.recoveryGates.has(recoveryKey(chatroomId, role))) {
|
|
37150
|
+
this.scheduleRecoveryRetry(chatroomId, role);
|
|
37151
|
+
}
|
|
37152
|
+
return;
|
|
37153
|
+
}
|
|
37154
|
+
if (outcome.kind === "start-failed") {
|
|
37155
|
+
console.error(`[NativeDelivery:uncovered-restart-failed] chatroom=${chatroomId} role=${role} task=${task.taskId} attempt=1 of ${MAX_RESPAWN_START_ATTEMPTS} error=${outcome.error}`);
|
|
37156
|
+
this.beginRespawnStartRetries({ chatroomId, role, workingDir, startInput });
|
|
37157
|
+
}
|
|
37158
|
+
}
|
|
37159
|
+
async attemptRespawnStart(ops, startInput, signal) {
|
|
37160
|
+
try {
|
|
37161
|
+
const started = await ops.startAgent(startInput, signal);
|
|
37162
|
+
return started.success ? { kind: "started" } : { kind: "start-failed", error: started.error ?? "start_rejected" };
|
|
37163
|
+
} catch (error51) {
|
|
37164
|
+
return {
|
|
37165
|
+
kind: "start-failed",
|
|
37166
|
+
error: error51 instanceof Error ? error51.message : String(error51)
|
|
37167
|
+
};
|
|
37168
|
+
}
|
|
37169
|
+
}
|
|
37170
|
+
beginRespawnStartRetries(request3) {
|
|
37171
|
+
if (this.disposed)
|
|
37172
|
+
return;
|
|
37173
|
+
const key = recoveryKey(request3.chatroomId, request3.role);
|
|
37174
|
+
this.cancelRespawnStart(key, "superseded_by_new_restart");
|
|
37175
|
+
this.respawnRestartSeq += 1;
|
|
37176
|
+
const pending = {
|
|
37177
|
+
restartId: this.respawnRestartSeq,
|
|
37178
|
+
request: request3,
|
|
37179
|
+
attempts: 1
|
|
37180
|
+
};
|
|
37181
|
+
this.respawnStartRetries.set(key, pending);
|
|
37182
|
+
this.armRespawnStartRetry(key, pending);
|
|
37183
|
+
}
|
|
37184
|
+
armRespawnStartRetry(key, pending) {
|
|
37185
|
+
if (this.disposed)
|
|
37186
|
+
return;
|
|
37187
|
+
const delay3 = Math.min(30000, 1000 * 2 ** (pending.attempts - 1));
|
|
37188
|
+
pending.timer = setTimeout(() => {
|
|
37189
|
+
pending.timer = undefined;
|
|
37190
|
+
this.retryRespawnStart(key, pending.restartId).catch((error51) => {
|
|
37191
|
+
console.error(`[NativeDelivery:uncovered-restart-error] chatroom=${pending.request.chatroomId} role=${pending.request.role} error=${error51 instanceof Error ? error51.stack ?? error51.message : String(error51)}`);
|
|
37192
|
+
});
|
|
37193
|
+
}, delay3);
|
|
37194
|
+
}
|
|
37195
|
+
async retryRespawnStart(key, restartId) {
|
|
37196
|
+
const pending = this.respawnStartRetries.get(key);
|
|
37197
|
+
if (!pending || pending.restartId !== restartId || this.disposed)
|
|
37198
|
+
return;
|
|
37199
|
+
const { chatroomId, role, workingDir, startInput } = pending.request;
|
|
37200
|
+
if (this.deps.agentMgr.isStopRequested(chatroomId, role)) {
|
|
37201
|
+
this.cancelRespawnStart(key, "stop_requested");
|
|
37202
|
+
return;
|
|
37203
|
+
}
|
|
37204
|
+
const slot = this.deps.agentMgr.getSlot(chatroomId, role);
|
|
37205
|
+
if (slot && isSlotRunning(slot.state)) {
|
|
37206
|
+
this.cancelRespawnStart(key, "agent_already_running");
|
|
37207
|
+
return;
|
|
37208
|
+
}
|
|
37209
|
+
const outcome = await this.deps.runSerializedForAgent({ chatroomId, role, workingDir }, { timeoutMs: AGENT_LIFECYCLE_OPERATION_TIMEOUT_MS }, async (ops, context3) => {
|
|
37210
|
+
if (this.respawnStartRetries.get(key)?.restartId !== restartId) {
|
|
37211
|
+
return { kind: "skipped", reason: "superseded" };
|
|
37212
|
+
}
|
|
37213
|
+
if (this.deps.agentMgr.isStopRequested(chatroomId, role)) {
|
|
37214
|
+
return { kind: "skipped", reason: "stop_requested" };
|
|
37215
|
+
}
|
|
37216
|
+
const current2 = this.deps.agentMgr.getSlot(chatroomId, role);
|
|
37217
|
+
if (current2 && isSlotRunning(current2.state)) {
|
|
37218
|
+
return { kind: "skipped", reason: "agent_already_running" };
|
|
37219
|
+
}
|
|
37220
|
+
return this.attemptRespawnStart(ops, startInput, context3.signal);
|
|
37221
|
+
});
|
|
37222
|
+
if (outcome.kind === "skipped") {
|
|
37223
|
+
this.cancelRespawnStart(key, outcome.reason);
|
|
37224
|
+
return;
|
|
37225
|
+
}
|
|
37226
|
+
const current = this.respawnStartRetries.get(key);
|
|
37227
|
+
if (current?.restartId !== restartId)
|
|
37228
|
+
return;
|
|
37229
|
+
if (outcome.kind === "started") {
|
|
37230
|
+
this.cancelRespawnStart(key, "started");
|
|
37231
|
+
return;
|
|
37232
|
+
}
|
|
37233
|
+
current.attempts += 1;
|
|
37234
|
+
if (current.attempts >= MAX_RESPAWN_START_ATTEMPTS) {
|
|
37235
|
+
this.respawnStartRetries.delete(key);
|
|
37236
|
+
console.error(`[NativeDelivery:uncovered-restart-failed] attempts exhausted chatroom=${chatroomId} role=${role} attempts=${current.attempts} error=${outcome.error}`);
|
|
37237
|
+
return;
|
|
37238
|
+
}
|
|
37239
|
+
console.error(`[NativeDelivery:uncovered-restart-failed] chatroom=${chatroomId} role=${role} attempt=${current.attempts} of ${MAX_RESPAWN_START_ATTEMPTS} error=${outcome.error}`);
|
|
37240
|
+
this.armRespawnStartRetry(key, current);
|
|
37241
|
+
}
|
|
37242
|
+
cancelRespawnStart(key, reason) {
|
|
37243
|
+
const pending = this.respawnStartRetries.get(key);
|
|
37244
|
+
if (!pending)
|
|
37245
|
+
return;
|
|
37246
|
+
if (pending.timer)
|
|
37247
|
+
clearTimeout(pending.timer);
|
|
37248
|
+
pending.timer = undefined;
|
|
37249
|
+
this.respawnStartRetries.delete(key);
|
|
37250
|
+
if (reason === "started")
|
|
37251
|
+
return;
|
|
37252
|
+
console.log(`[NativeDelivery:uncovered-restart-cancelled] chatroom=${pending.request.chatroomId} role=${pending.request.role} attempts=${pending.attempts} reason=${reason}`);
|
|
37253
|
+
}
|
|
37254
|
+
uncoveredNudgeSkipReason(event, task) {
|
|
37255
|
+
const { chatroomId, role } = event;
|
|
37256
|
+
const slot = this.deps.agentMgr.getSlot(chatroomId, role);
|
|
37257
|
+
if (!slot || !isSlotRunning(slot.state))
|
|
37258
|
+
return "slot_not_running";
|
|
37259
|
+
if (slot.pid !== event.pid)
|
|
37260
|
+
return "pid_changed";
|
|
37261
|
+
if (slot.harnessSessionId !== event.slot.harnessSessionId)
|
|
37262
|
+
return "session_changed";
|
|
37263
|
+
if (!isTurnPhaseIdle(slot.nativeTurnPhase ?? "idle"))
|
|
37264
|
+
return "turn_not_idle";
|
|
37265
|
+
if (this.deps.agentMgr.isStopRequested(chatroomId, role))
|
|
37266
|
+
return "stop_requested";
|
|
37267
|
+
if (this.recoveryGates.has(recoveryKey(chatroomId, role)))
|
|
37268
|
+
return "recovery_in_progress";
|
|
37269
|
+
if (this.deps.agentTaskState.get({ chatroomId, role })?.taskId !== task.taskId) {
|
|
37270
|
+
return "task_not_active";
|
|
37271
|
+
}
|
|
37272
|
+
const current = this.deps.taskInboxState.getForRole(chatroomId, role, task.taskId);
|
|
37273
|
+
if (!current || !ACTIVE_TASK_STATUSES.includes(current.status)) {
|
|
37274
|
+
return "task_not_in_inbox";
|
|
37275
|
+
}
|
|
37276
|
+
return;
|
|
37277
|
+
}
|
|
37278
|
+
applyParkAction(event) {
|
|
37279
|
+
this.deps.agentTaskState.clear({ chatroomId: event.chatroomId, role: event.role });
|
|
36997
37280
|
this.scheduleRoleDelivery(event.chatroomId, event.role);
|
|
36998
|
-
return { kind: "release-slot" };
|
|
36999
37281
|
}
|
|
37000
37282
|
scheduleRoleDelivery(chatroomId, role) {
|
|
37001
37283
|
setTimeout(() => {
|
|
@@ -37006,6 +37288,12 @@ class AgentWorkManager {
|
|
|
37006
37288
|
}
|
|
37007
37289
|
dispose() {
|
|
37008
37290
|
this.disposed = true;
|
|
37291
|
+
for (const pending of this.respawnStartRetries.values()) {
|
|
37292
|
+
if (pending.timer)
|
|
37293
|
+
clearTimeout(pending.timer);
|
|
37294
|
+
pending.timer = undefined;
|
|
37295
|
+
}
|
|
37296
|
+
this.respawnStartRetries.clear();
|
|
37009
37297
|
for (const gate of this.recoveryGates.values()) {
|
|
37010
37298
|
if (gate.retryTimer)
|
|
37011
37299
|
clearTimeout(gate.retryTimer);
|
|
@@ -37217,13 +37505,16 @@ class AgentWorkManager {
|
|
|
37217
37505
|
this.deps.agentTaskState.start(args2);
|
|
37218
37506
|
}
|
|
37219
37507
|
}
|
|
37220
|
-
var recoveryKey = (chatroomId, role) => `${chatroomId}:${role.toLowerCase()}`;
|
|
37508
|
+
var MAX_RESPAWN_START_ATTEMPTS = 3, MAX_UNCOVERED_NUDGE_SEND_ATTEMPTS = 3, UNCOVERED_NUDGE_RETRY_MS = 250, recoveryKey = (chatroomId, role) => `${chatroomId}:${role.toLowerCase()}`, sessionKeyFor = (pid, harnessSessionId) => `${pid}:${harnessSessionId ?? "none"}`;
|
|
37221
37509
|
var init_agent_work_manager = __esm(() => {
|
|
37510
|
+
init_reliability();
|
|
37222
37511
|
init_agent();
|
|
37223
37512
|
init_chatroom_workspace_task_inbox();
|
|
37224
37513
|
init_dist();
|
|
37225
37514
|
init_agent_lifecycle_fact();
|
|
37226
37515
|
init_agent_slot();
|
|
37516
|
+
init_assigned_task();
|
|
37517
|
+
init_check_agent_slot();
|
|
37227
37518
|
init_native_task_injector_logic();
|
|
37228
37519
|
init_convex_native_task_delivery_gateway();
|
|
37229
37520
|
init_daemon_audit_port();
|
|
@@ -40322,6 +40613,27 @@ class TaskInboxState {
|
|
|
40322
40613
|
}
|
|
40323
40614
|
}
|
|
40324
40615
|
|
|
40616
|
+
// src/daemon/services/task-service/domain/usecase/uncovered-turn-ladder.ts
|
|
40617
|
+
function decideUncoveredTurnEnd(entry, sessionKey, opts = {}) {
|
|
40618
|
+
const current = entry ?? FRESH_ENTRY;
|
|
40619
|
+
if (isNudgeDue(current, sessionKey, opts))
|
|
40620
|
+
return { action: "nudge" };
|
|
40621
|
+
return current.sessionRestarts < MAX_SESSION_RESTARTS_PER_TASK ? { action: "restart-session" } : { action: "park" };
|
|
40622
|
+
}
|
|
40623
|
+
function isNudgeDue(entry, sessionKey, opts) {
|
|
40624
|
+
return !opts.nudgeUnavailable && entry.nudgedSessionKey !== sessionKey;
|
|
40625
|
+
}
|
|
40626
|
+
function withNudgeSent(entry, sessionKey) {
|
|
40627
|
+
return { nudgedSessionKey: sessionKey, sessionRestarts: entry?.sessionRestarts ?? 0 };
|
|
40628
|
+
}
|
|
40629
|
+
function withSessionRestart(entry) {
|
|
40630
|
+
return { nudgedSessionKey: undefined, sessionRestarts: (entry?.sessionRestarts ?? 0) + 1 };
|
|
40631
|
+
}
|
|
40632
|
+
var MAX_SESSION_RESTARTS_PER_TASK = 1, FRESH_ENTRY;
|
|
40633
|
+
var init_uncovered_turn_ladder = __esm(() => {
|
|
40634
|
+
FRESH_ENTRY = { sessionRestarts: 0 };
|
|
40635
|
+
});
|
|
40636
|
+
|
|
40325
40637
|
// src/daemon/services/task-service/service/task-service.ts
|
|
40326
40638
|
function createTaskService(deps) {
|
|
40327
40639
|
const gateway = createConvexNativeTaskDeliveryGateway(deps.backend);
|
|
@@ -40339,18 +40651,13 @@ function createTaskService(deps) {
|
|
|
40339
40651
|
let bootstrapRecoveryAttempts = 0;
|
|
40340
40652
|
let bootstrapRecoveryTimer;
|
|
40341
40653
|
let bootstrapRecoveryPromise;
|
|
40342
|
-
const
|
|
40343
|
-
const
|
|
40654
|
+
const TURN_FAILURE_RETRY_CAP = 3;
|
|
40655
|
+
const turnFailureCounts = new Map;
|
|
40656
|
+
const uncoveredLadder = new Map;
|
|
40344
40657
|
const redeliveryExhaustedKeys = new Set;
|
|
40345
40658
|
const redeliveryKey = (chatroomId, role, taskId) => `${chatroomId}:${role.toLowerCase()}:${taskId}`;
|
|
40346
|
-
const
|
|
40659
|
+
const parkTask = async (args2, attempts) => {
|
|
40347
40660
|
const key = redeliveryKey(args2.chatroomId, args2.role, args2.taskId);
|
|
40348
|
-
if (redeliveryExhaustedKeys.has(key))
|
|
40349
|
-
return { exceeded: true };
|
|
40350
|
-
const attempts = (turnEndAttemptCounts.get(key) ?? 0) + 1;
|
|
40351
|
-
turnEndAttemptCounts.set(key, attempts);
|
|
40352
|
-
if (attempts < REDIVERY_ATTEMPT_CAP)
|
|
40353
|
-
return { exceeded: false };
|
|
40354
40661
|
redeliveryExhaustedKeys.add(key);
|
|
40355
40662
|
try {
|
|
40356
40663
|
await gateway.recordDeliveryFailure({
|
|
@@ -40362,13 +40669,50 @@ function createTaskService(deps) {
|
|
|
40362
40669
|
} catch (error51) {
|
|
40363
40670
|
console.warn(`[TaskService] redelivery-exhausted failure record failed chatroom=${args2.chatroomId} role=${args2.role} task=${args2.taskId}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
40364
40671
|
}
|
|
40365
|
-
|
|
40672
|
+
const attemptsSuffix = attempts === undefined ? "" : ` attempts=${attempts}`;
|
|
40673
|
+
console.log(`[NativeDelivery:redelivery-exhausted] chatroom=${args2.chatroomId} role=${args2.role} task=${args2.taskId}${attemptsSuffix} — release/redelivery stopped; agent restart (user.start) resets`);
|
|
40674
|
+
};
|
|
40675
|
+
const recordTurnFailure = async (args2) => {
|
|
40676
|
+
const key = redeliveryKey(args2.chatroomId, args2.role, args2.taskId);
|
|
40677
|
+
if (redeliveryExhaustedKeys.has(key))
|
|
40678
|
+
return { exceeded: true };
|
|
40679
|
+
const attempts = (turnFailureCounts.get(key) ?? 0) + 1;
|
|
40680
|
+
turnFailureCounts.set(key, attempts);
|
|
40681
|
+
if (attempts < TURN_FAILURE_RETRY_CAP)
|
|
40682
|
+
return { exceeded: false };
|
|
40683
|
+
await parkTask(args2, attempts);
|
|
40366
40684
|
return { exceeded: true };
|
|
40367
40685
|
};
|
|
40686
|
+
const decideUncoveredTurnEnd2 = async (args2) => {
|
|
40687
|
+
const key = redeliveryKey(args2.chatroomId, args2.role, args2.taskId);
|
|
40688
|
+
if (redeliveryExhaustedKeys.has(key))
|
|
40689
|
+
return { action: "park" };
|
|
40690
|
+
turnFailureCounts.delete(key);
|
|
40691
|
+
const entry = uncoveredLadder.get(key);
|
|
40692
|
+
const decision = decideUncoveredTurnEnd(entry, args2.sessionKey, {
|
|
40693
|
+
nudgeUnavailable: args2.nudgeUnavailable ?? false
|
|
40694
|
+
});
|
|
40695
|
+
if (decision.action === "restart-session") {
|
|
40696
|
+
uncoveredLadder.set(key, withSessionRestart(entry));
|
|
40697
|
+
} else if (decision.action === "park") {
|
|
40698
|
+
await parkTask(args2);
|
|
40699
|
+
}
|
|
40700
|
+
return decision;
|
|
40701
|
+
};
|
|
40702
|
+
const confirmNudgeSent = (args2) => {
|
|
40703
|
+
const key = redeliveryKey(args2.chatroomId, args2.role, args2.taskId);
|
|
40704
|
+
uncoveredLadder.set(key, withNudgeSent(uncoveredLadder.get(key), args2.sessionKey));
|
|
40705
|
+
};
|
|
40706
|
+
const resetTurnTracking = (args2) => {
|
|
40707
|
+
const key = redeliveryKey(args2.chatroomId, args2.role, args2.taskId);
|
|
40708
|
+
turnFailureCounts.delete(key);
|
|
40709
|
+
uncoveredLadder.delete(key);
|
|
40710
|
+
};
|
|
40368
40711
|
const isRedeliveryExhausted = (args2) => redeliveryExhaustedKeys.has(redeliveryKey(args2.chatroomId, args2.role, args2.taskId));
|
|
40369
40712
|
const clearRedeliveryTrackingForTask = (chatroomId, role, taskId) => {
|
|
40370
40713
|
const key = redeliveryKey(chatroomId, role, taskId);
|
|
40371
|
-
|
|
40714
|
+
turnFailureCounts.delete(key);
|
|
40715
|
+
uncoveredLadder.delete(key);
|
|
40372
40716
|
redeliveryExhaustedKeys.delete(key);
|
|
40373
40717
|
};
|
|
40374
40718
|
const forgetStaleTask = ({
|
|
@@ -40398,9 +40742,13 @@ function createTaskService(deps) {
|
|
|
40398
40742
|
};
|
|
40399
40743
|
const clearRoleRedeliveryTracking = (chatroomId, role) => {
|
|
40400
40744
|
const prefix = `${chatroomId}:${role.toLowerCase()}:`;
|
|
40401
|
-
for (const key of [...
|
|
40745
|
+
for (const key of [...turnFailureCounts.keys()]) {
|
|
40402
40746
|
if (key.startsWith(prefix))
|
|
40403
|
-
|
|
40747
|
+
turnFailureCounts.delete(key);
|
|
40748
|
+
}
|
|
40749
|
+
for (const key of [...uncoveredLadder.keys()]) {
|
|
40750
|
+
if (key.startsWith(prefix))
|
|
40751
|
+
uncoveredLadder.delete(key);
|
|
40404
40752
|
}
|
|
40405
40753
|
for (const key of [...redeliveryExhaustedKeys]) {
|
|
40406
40754
|
if (key.startsWith(prefix))
|
|
@@ -40802,7 +41150,10 @@ function createTaskService(deps) {
|
|
|
40802
41150
|
taskId,
|
|
40803
41151
|
...expectedReason ? { expectedReason } : {}
|
|
40804
41152
|
}),
|
|
40805
|
-
|
|
41153
|
+
recordTurnFailure,
|
|
41154
|
+
decideUncoveredTurnEnd: decideUncoveredTurnEnd2,
|
|
41155
|
+
confirmNudgeSent,
|
|
41156
|
+
resetTurnTracking,
|
|
40806
41157
|
isRedeliveryExhausted,
|
|
40807
41158
|
clearRedeliveryTracking: ({ chatroomId, role }) => {
|
|
40808
41159
|
clearRoleRedeliveryTracking(chatroomId, role);
|
|
@@ -40817,6 +41168,7 @@ var init_task_service = __esm(() => {
|
|
|
40817
41168
|
init_task_inbox_acknowledgement_retry_watcher();
|
|
40818
41169
|
init_task_inbox_delivery_retry_watcher();
|
|
40819
41170
|
init_api3();
|
|
41171
|
+
init_uncovered_turn_ladder();
|
|
40820
41172
|
init_convex_native_task_delivery_gateway();
|
|
40821
41173
|
});
|
|
40822
41174
|
|
|
@@ -48728,6 +49080,14 @@ var init_pi_sdk_package = __esm(() => {
|
|
|
48728
49080
|
};
|
|
48729
49081
|
});
|
|
48730
49082
|
|
|
49083
|
+
// src/daemon/infrastructure/local/harness/services/pi-sdk/assistant-error.ts
|
|
49084
|
+
function assistantErrorOf(event) {
|
|
49085
|
+
if (event.message.role !== "assistant" || event.message.stopReason !== "error")
|
|
49086
|
+
return;
|
|
49087
|
+
return event.message.errorMessage ?? UNKNOWN_PROVIDER_ERROR;
|
|
49088
|
+
}
|
|
49089
|
+
var UNKNOWN_PROVIDER_ERROR = "unknown provider error";
|
|
49090
|
+
|
|
48731
49091
|
// src/daemon/infrastructure/local/harness/services/pi-sdk/pi-sdk-stream-adapter.ts
|
|
48732
49092
|
var PiSdkStreamAdapter;
|
|
48733
49093
|
var init_pi_sdk_stream_adapter = __esm(() => {
|
|
@@ -48735,6 +49095,7 @@ var init_pi_sdk_stream_adapter = __esm(() => {
|
|
|
48735
49095
|
PiSdkStreamAdapter = class PiSdkStreamAdapter extends NativeStreamAdapterBase {
|
|
48736
49096
|
textBuffer = "";
|
|
48737
49097
|
thinkingBuffer = "";
|
|
49098
|
+
lastAssistantError;
|
|
48738
49099
|
constructor(logPrefix, emitLogLine, activityEmitter) {
|
|
48739
49100
|
super(logPrefix, emitLogLine, activityEmitter);
|
|
48740
49101
|
}
|
|
@@ -48774,17 +49135,43 @@ var init_pi_sdk_stream_adapter = __esm(() => {
|
|
|
48774
49135
|
this.writeLine(formatAgentLogLine(this.logPrefix, "tool_result", `${event.toolName} result: ${resultStr}`));
|
|
48775
49136
|
break;
|
|
48776
49137
|
}
|
|
49138
|
+
case "message_end":
|
|
49139
|
+
this.recordAssistantOutcome(event);
|
|
49140
|
+
break;
|
|
48777
49141
|
case "agent_end":
|
|
48778
|
-
|
|
49142
|
+
if (event.willRetry)
|
|
49143
|
+
break;
|
|
49144
|
+
this.settleRun("pi-sdk.agent_end");
|
|
48779
49145
|
break;
|
|
48780
49146
|
default:
|
|
48781
49147
|
break;
|
|
48782
49148
|
}
|
|
48783
49149
|
}
|
|
49150
|
+
recordAssistantOutcome(event) {
|
|
49151
|
+
const message = event.message;
|
|
49152
|
+
if (message.role !== "assistant")
|
|
49153
|
+
return;
|
|
49154
|
+
this.lastAssistantError = assistantErrorOf(event);
|
|
49155
|
+
if (this.lastAssistantError === undefined)
|
|
49156
|
+
return;
|
|
49157
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, "run-error", `assistant error: ${this.lastAssistantError}`));
|
|
49158
|
+
}
|
|
49159
|
+
settleResolvedPrompt() {
|
|
49160
|
+
this.settleRun("pi-sdk.prompt.resolved");
|
|
49161
|
+
}
|
|
48784
49162
|
finish() {
|
|
48785
49163
|
this.flushText();
|
|
48786
49164
|
this.flushThinking();
|
|
48787
49165
|
}
|
|
49166
|
+
settleRun(source) {
|
|
49167
|
+
if (this.lastAssistantError !== undefined) {
|
|
49168
|
+
const error51 = this.lastAssistantError;
|
|
49169
|
+
if (this.completeTurn({ status: "failed", source, error: error51 }))
|
|
49170
|
+
this.notifyFailure(source);
|
|
49171
|
+
} else {
|
|
49172
|
+
this.completeTurn({ status: "completed", source });
|
|
49173
|
+
}
|
|
49174
|
+
}
|
|
48788
49175
|
appendText(delta) {
|
|
48789
49176
|
this.flushThinking();
|
|
48790
49177
|
this.textBuffer += delta;
|
|
@@ -48876,9 +49263,13 @@ function waitForResumeOrAbort4(session2) {
|
|
|
48876
49263
|
})
|
|
48877
49264
|
]);
|
|
48878
49265
|
}
|
|
48879
|
-
function
|
|
49266
|
+
async function createModelRuntime() {
|
|
49267
|
+
const sdk = await loadSdk4();
|
|
49268
|
+
return sdk.ModelRuntime.create();
|
|
49269
|
+
}
|
|
49270
|
+
function resolveRequiredModel(modelRuntime, model) {
|
|
48880
49271
|
const slash = model.indexOf("/");
|
|
48881
|
-
const resolved = slash === -1 ?
|
|
49272
|
+
const resolved = slash === -1 ? modelRuntime.getModels().find((entry) => entry.id === model) : modelRuntime.getModel(model.slice(0, slash), model.slice(slash + 1));
|
|
48882
49273
|
if (!resolved) {
|
|
48883
49274
|
throw new Error(`Pi model not found: ${model}`);
|
|
48884
49275
|
}
|
|
@@ -48912,10 +49303,8 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
48912
49303
|
}
|
|
48913
49304
|
async isInstalled() {
|
|
48914
49305
|
try {
|
|
48915
|
-
const
|
|
48916
|
-
|
|
48917
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
48918
|
-
return modelRegistry.getAvailable().length > 0;
|
|
49306
|
+
const modelRuntime = await createModelRuntime();
|
|
49307
|
+
return (await modelRuntime.getAvailable()).length > 0;
|
|
48919
49308
|
} catch (err) {
|
|
48920
49309
|
console.warn(`[pi-sdk] unavailable: ${formatPiSdkLoadError(err)}`);
|
|
48921
49310
|
return false;
|
|
@@ -48938,26 +49327,16 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
48938
49327
|
}
|
|
48939
49328
|
async listModels() {
|
|
48940
49329
|
try {
|
|
48941
|
-
const
|
|
48942
|
-
|
|
48943
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
48944
|
-
return modelRegistry.getAvailable().map((entry) => `${entry.provider}/${entry.id}`);
|
|
49330
|
+
const modelRuntime = await createModelRuntime();
|
|
49331
|
+
return (await modelRuntime.getAvailable()).map((entry) => `${entry.provider}/${entry.id}`);
|
|
48945
49332
|
} catch (err) {
|
|
48946
49333
|
console.warn(`[pi-sdk] listModels failed:`, err instanceof Error ? err.message : err);
|
|
48947
49334
|
return [];
|
|
48948
49335
|
}
|
|
48949
49336
|
}
|
|
48950
49337
|
async openResumedSession(args2) {
|
|
48951
|
-
const {
|
|
48952
|
-
|
|
48953
|
-
createAgentSession,
|
|
48954
|
-
DefaultResourceLoader,
|
|
48955
|
-
getAgentDir,
|
|
48956
|
-
ModelRegistry,
|
|
48957
|
-
SessionManager
|
|
48958
|
-
} = await loadSdk4();
|
|
48959
|
-
const authStorage = AuthStorage.create();
|
|
48960
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
49338
|
+
const { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } = await loadSdk4();
|
|
49339
|
+
const modelRuntime = await createModelRuntime();
|
|
48961
49340
|
const sessions = await SessionManager.list(args2.workingDir, getPiSessionDir(args2.workingDir));
|
|
48962
49341
|
const match5 = sessions.find((s) => s.id === args2.harnessSessionId);
|
|
48963
49342
|
if (!match5) {
|
|
@@ -48972,8 +49351,7 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
48972
49351
|
const { session: session2 } = await withTimeout(createAgentSession({
|
|
48973
49352
|
cwd: args2.workingDir,
|
|
48974
49353
|
sessionManager: SessionManager.open(match5.path, getPiSessionDir(args2.workingDir)),
|
|
48975
|
-
|
|
48976
|
-
modelRegistry,
|
|
49354
|
+
modelRuntime,
|
|
48977
49355
|
resourceLoader
|
|
48978
49356
|
}), SESSION_CREATE_TIMEOUT_MS2, "createAgentSession");
|
|
48979
49357
|
return session2;
|
|
@@ -49027,19 +49405,11 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
49027
49405
|
return keeper;
|
|
49028
49406
|
}
|
|
49029
49407
|
async createSession(args2) {
|
|
49030
|
-
const {
|
|
49031
|
-
|
|
49032
|
-
createAgentSession,
|
|
49033
|
-
DefaultResourceLoader,
|
|
49034
|
-
getAgentDir,
|
|
49035
|
-
ModelRegistry,
|
|
49036
|
-
SessionManager
|
|
49037
|
-
} = await loadSdk4();
|
|
49038
|
-
const authStorage = AuthStorage.create();
|
|
49039
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
49408
|
+
const { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } = await loadSdk4();
|
|
49409
|
+
const modelRuntime = await createModelRuntime();
|
|
49040
49410
|
const model = requireHarnessModel(args2.model, "pi-sdk spawn");
|
|
49041
49411
|
const parsed = parsePiSpawnModel(model);
|
|
49042
|
-
const resolvedModel = resolveRequiredModel(
|
|
49412
|
+
const resolvedModel = resolveRequiredModel(modelRuntime, parsed.model ?? model);
|
|
49043
49413
|
const thinkingLevel = resolvePiThinkingLevel(parsed?.thinking);
|
|
49044
49414
|
const agentDir = getAgentDir();
|
|
49045
49415
|
const resourceLoader = new DefaultResourceLoader({
|
|
@@ -49053,8 +49423,7 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
49053
49423
|
model: resolvedModel,
|
|
49054
49424
|
...thinkingLevel ? { thinkingLevel } : {},
|
|
49055
49425
|
sessionManager: SessionManager.create(getPiSessionDir(args2.workingDir)),
|
|
49056
|
-
|
|
49057
|
-
modelRegistry,
|
|
49426
|
+
modelRuntime,
|
|
49058
49427
|
resourceLoader
|
|
49059
49428
|
}), SESSION_CREATE_TIMEOUT_MS2, "createAgentSession");
|
|
49060
49429
|
return session2;
|
|
@@ -49201,9 +49570,7 @@ ${deferredResume}` : deferredResume;
|
|
|
49201
49570
|
exitSignal = "SIGTERM";
|
|
49202
49571
|
break;
|
|
49203
49572
|
}
|
|
49204
|
-
|
|
49205
|
-
adapter.completeTurn({ status: "completed", source: "pi-sdk.prompt.resolved" });
|
|
49206
|
-
}
|
|
49573
|
+
adapter.settleResolvedPrompt();
|
|
49207
49574
|
adapter.finish();
|
|
49208
49575
|
nextPrompt = null;
|
|
49209
49576
|
} catch (turnErr) {
|
|
@@ -122973,6 +123340,7 @@ class PiSdkSession {
|
|
|
122973
123340
|
listeners = new Set;
|
|
122974
123341
|
closed = false;
|
|
122975
123342
|
unsubscribe;
|
|
123343
|
+
lastAssistantError;
|
|
122976
123344
|
constructor(options) {
|
|
122977
123345
|
this.session = options.session;
|
|
122978
123346
|
this.opencodeSessionId = options.opencodeSessionId;
|
|
@@ -122988,14 +123356,21 @@ class PiSdkSession {
|
|
|
122988
123356
|
const text = input.parts.map((p) => p.text).join(`
|
|
122989
123357
|
`);
|
|
122990
123358
|
const messageId = randomUUID14();
|
|
123359
|
+
this.lastAssistantError = undefined;
|
|
122991
123360
|
const onSessionEvent = (event) => {
|
|
122992
123361
|
if (this.closed)
|
|
122993
123362
|
return;
|
|
123363
|
+
if (event.type === "message_end" && event.message.role === "assistant") {
|
|
123364
|
+
this.lastAssistantError = assistantErrorOf(event);
|
|
123365
|
+
}
|
|
122994
123366
|
this.emitFromPiEvent(event, messageId);
|
|
122995
123367
|
};
|
|
122996
123368
|
this.unsubscribe?.();
|
|
122997
123369
|
this.unsubscribe = this.session.subscribe(onSessionEvent);
|
|
122998
123370
|
await withTimeout(this.session.prompt(text), PROMPT_TIMEOUT_MS3, "session.prompt");
|
|
123371
|
+
if (this.lastAssistantError !== undefined) {
|
|
123372
|
+
throw new Error(this.lastAssistantError);
|
|
123373
|
+
}
|
|
122999
123374
|
this.emit({ type: "session.idle", payload: {}, timestamp: Date.now() });
|
|
123000
123375
|
}
|
|
123001
123376
|
onEvent(listener) {
|
|
@@ -123060,9 +123435,9 @@ async function loadSdk7() {
|
|
|
123060
123435
|
throw err;
|
|
123061
123436
|
}
|
|
123062
123437
|
}
|
|
123063
|
-
function resolveRequiredModel2(
|
|
123438
|
+
function resolveRequiredModel2(modelRuntime, model) {
|
|
123064
123439
|
const slash = model.indexOf("/");
|
|
123065
|
-
const resolved = slash === -1 ?
|
|
123440
|
+
const resolved = slash === -1 ? modelRuntime.getModels().find((entry) => entry.id === model) : modelRuntime.getModel(model.slice(0, slash), model.slice(slash + 1));
|
|
123066
123441
|
if (!resolved) {
|
|
123067
123442
|
throw new Error(`Pi model not found: ${model}`);
|
|
123068
123443
|
}
|
|
@@ -123075,15 +123450,13 @@ class PiSdkHarness {
|
|
|
123075
123450
|
cwd;
|
|
123076
123451
|
closed = false;
|
|
123077
123452
|
sessions = new Map;
|
|
123078
|
-
|
|
123079
|
-
|
|
123080
|
-
constructor(cwd, modelRegistry, authStorage) {
|
|
123453
|
+
modelRuntime;
|
|
123454
|
+
constructor(cwd, modelRuntime) {
|
|
123081
123455
|
this.cwd = cwd;
|
|
123082
|
-
this.
|
|
123083
|
-
this.authStorage = authStorage;
|
|
123456
|
+
this.modelRuntime = modelRuntime;
|
|
123084
123457
|
}
|
|
123085
123458
|
async models() {
|
|
123086
|
-
return this.
|
|
123459
|
+
return (await this.modelRuntime.getAvailable()).map((entry) => ({
|
|
123087
123460
|
id: `${entry.provider}/${entry.id}`,
|
|
123088
123461
|
name: entry.id,
|
|
123089
123462
|
provider: entry.provider
|
|
@@ -123094,7 +123467,7 @@ class PiSdkHarness {
|
|
|
123094
123467
|
}
|
|
123095
123468
|
async listProviders() {
|
|
123096
123469
|
const byProvider = new Map;
|
|
123097
|
-
for (const entry of this.
|
|
123470
|
+
for (const entry of await this.modelRuntime.getAvailable()) {
|
|
123098
123471
|
const models = byProvider.get(entry.provider) ?? [];
|
|
123099
123472
|
models.push({ modelID: entry.id, name: entry.id });
|
|
123100
123473
|
byProvider.set(entry.provider, models);
|
|
@@ -123170,7 +123543,7 @@ class PiSdkHarness {
|
|
|
123170
123543
|
const { createAgentSession, DefaultResourceLoader, getAgentDir } = await loadSdk7();
|
|
123171
123544
|
const parsed = args2.model ? parsePiSpawnModel(args2.model) : undefined;
|
|
123172
123545
|
const modelSlug = parsed?.model ?? args2.model;
|
|
123173
|
-
const resolvedModel = args2.requireModel ? resolveRequiredModel2(this.
|
|
123546
|
+
const resolvedModel = args2.requireModel ? resolveRequiredModel2(this.modelRuntime, requireHarnessModel(modelSlug, "pi-sdk openAgentSession")) : modelSlug ? resolveRequiredModel2(this.modelRuntime, modelSlug) : undefined;
|
|
123174
123547
|
const thinkingLevel = resolvePiThinkingLevel(parsed?.thinking);
|
|
123175
123548
|
if (args2.requireModel && !resolvedModel) {
|
|
123176
123549
|
throw new Error("No Pi model available — configure provider credentials in ~/.pi/agent/auth.json");
|
|
@@ -123184,8 +123557,7 @@ class PiSdkHarness {
|
|
|
123184
123557
|
const { session: session2 } = await withTimeout(createAgentSession({
|
|
123185
123558
|
cwd: this.cwd,
|
|
123186
123559
|
sessionManager: args2.sessionManager,
|
|
123187
|
-
|
|
123188
|
-
modelRegistry: this.modelRegistry,
|
|
123560
|
+
modelRuntime: this.modelRuntime,
|
|
123189
123561
|
resourceLoader,
|
|
123190
123562
|
...resolvedModel ? { model: resolvedModel } : {},
|
|
123191
123563
|
...thinkingLevel ? { thinkingLevel } : {}
|
|
@@ -123195,13 +123567,12 @@ class PiSdkHarness {
|
|
|
123195
123567
|
}
|
|
123196
123568
|
var SESSION_CREATE_TIMEOUT_MS3 = 60000, _sdkCache7, _sdkLoadError7, startPiSdkHarness = async (config4) => {
|
|
123197
123569
|
try {
|
|
123198
|
-
const
|
|
123199
|
-
const
|
|
123200
|
-
|
|
123201
|
-
if (modelRegistry.getAvailable().length === 0) {
|
|
123570
|
+
const sdk = await loadSdk7();
|
|
123571
|
+
const modelRuntime = await sdk.ModelRuntime.create();
|
|
123572
|
+
if ((await modelRuntime.getAvailable()).length === 0) {
|
|
123202
123573
|
throw new Error("No Pi models available");
|
|
123203
123574
|
}
|
|
123204
|
-
return new PiSdkHarness(config4.workingDir,
|
|
123575
|
+
return new PiSdkHarness(config4.workingDir, modelRuntime);
|
|
123205
123576
|
} catch (err) {
|
|
123206
123577
|
throw new Error(`pi-sdk unavailable: ${formatPiSdkLoadError(err)}`);
|
|
123207
123578
|
}
|
|
@@ -137899,4 +138270,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
137899
138270
|
});
|
|
137900
138271
|
program2.parse();
|
|
137901
138272
|
|
|
137902
|
-
//# debugId=
|
|
138273
|
+
//# debugId=7C84BEF97B16C1D064756E2164756E21
|