@jun133/athlete 0.0.6 → 0.0.8
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/README.md +12 -12
- package/dist/cli.js +180 -38
- package/dist/cli.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Athlete
|
|
2
2
|
|
|
3
|
-
<p align="center">
|
|
4
|
-
<strong
|
|
5
|
-
</p>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<img alt="
|
|
9
|
-
<img alt="durable runtime" src="https://img.shields.io/badge/durable-runtime-1f6feb?style=for-the-badge">
|
|
10
|
-
<img alt="checkpoint persisted" src="https://img.shields.io/badge/checkpoint-persisted-8250df?style=for-the-badge">
|
|
11
|
-
<img alt="runtime stats" src="https://img.shields.io/badge/runtime-stats-f59e0b?style=for-the-badge">
|
|
12
|
-
</p>
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>一个专注于解决问题与持续推进任务的智能体</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img alt="problem solving agent" src="https://img.shields.io/badge/problem--solving-agent-2ea44f?style=for-the-badge">
|
|
9
|
+
<img alt="durable runtime" src="https://img.shields.io/badge/durable-runtime-1f6feb?style=for-the-badge">
|
|
10
|
+
<img alt="checkpoint persisted" src="https://img.shields.io/badge/checkpoint-persisted-8250df?style=for-the-badge">
|
|
11
|
+
<img alt="runtime stats" src="https://img.shields.io/badge/runtime-stats-f59e0b?style=for-the-badge">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
一个专注于解决问题的智能体。
|
|
15
15
|
|
|
16
16
|
一个单纯的 LLM,往往擅长回答问题;一个加上 harness 的 LLM,才开始真正接住任务。它不只是“说下一句”,而是能在复杂任务里持续往前跑,知道什么时候该读文件、什么时候该调用工具、什么时候该拆任务、什么时候该把状态记下来,出了错以后还能接着做。✨
|
|
17
17
|
|
package/dist/cli.js
CHANGED
|
@@ -37,14 +37,14 @@ var init_package = __esm({
|
|
|
37
37
|
"package.json"() {
|
|
38
38
|
package_default = {
|
|
39
39
|
name: "@jun133/athlete",
|
|
40
|
-
version: "0.0.
|
|
41
|
-
description: "A
|
|
40
|
+
version: "0.0.8",
|
|
41
|
+
description: "A problem-solving agent focused on durable task execution.",
|
|
42
42
|
keywords: [
|
|
43
43
|
"athlete",
|
|
44
|
-
"cli",
|
|
45
|
-
"ai",
|
|
46
44
|
"agent",
|
|
47
|
-
"
|
|
45
|
+
"automation",
|
|
46
|
+
"runtime",
|
|
47
|
+
"problem-solving"
|
|
48
48
|
],
|
|
49
49
|
bin: {
|
|
50
50
|
athlete: "dist/cli.js"
|
|
@@ -8376,9 +8376,11 @@ var init_store5 = __esm({
|
|
|
8376
8376
|
async function reconcileTeamState(rootDir) {
|
|
8377
8377
|
const teamStore = new TeamStore(rootDir);
|
|
8378
8378
|
const taskStore = new TaskStore(rootDir);
|
|
8379
|
+
const executionStore = new ExecutionStore(rootDir);
|
|
8379
8380
|
const members = await teamStore.listMembers();
|
|
8380
8381
|
const staleMembers = [];
|
|
8381
8382
|
const releasedTasks = [];
|
|
8383
|
+
const closedExecutions = [];
|
|
8382
8384
|
for (const member of members) {
|
|
8383
8385
|
if (member.status === "shutdown" || typeof member.pid !== "number") {
|
|
8384
8386
|
continue;
|
|
@@ -8389,11 +8391,27 @@ async function reconcileTeamState(rootDir) {
|
|
|
8389
8391
|
staleMembers.push(await teamStore.updateMemberStatus(member.name, "shutdown"));
|
|
8390
8392
|
}
|
|
8391
8393
|
for (const member of staleMembers) {
|
|
8394
|
+
const runningExecutions = await executionStore.listRelevant({
|
|
8395
|
+
actorName: member.name,
|
|
8396
|
+
profile: "teammate",
|
|
8397
|
+
statuses: ["running"]
|
|
8398
|
+
});
|
|
8399
|
+
for (const execution of runningExecutions) {
|
|
8400
|
+
closedExecutions.push(
|
|
8401
|
+
await executionStore.close(execution.id, {
|
|
8402
|
+
status: "failed",
|
|
8403
|
+
summary: "teammate execution failed after worker exited unexpectedly",
|
|
8404
|
+
output: `Teammate worker '${member.name}' exited unexpectedly before reporting completion.`,
|
|
8405
|
+
statusDetail: "worker_exited_unexpectedly"
|
|
8406
|
+
})
|
|
8407
|
+
);
|
|
8408
|
+
}
|
|
8392
8409
|
releasedTasks.push(...await taskStore.releaseOwner(member.name));
|
|
8393
8410
|
}
|
|
8394
8411
|
return {
|
|
8395
8412
|
staleMembers,
|
|
8396
|
-
releasedTasks
|
|
8413
|
+
releasedTasks,
|
|
8414
|
+
closedExecutions
|
|
8397
8415
|
};
|
|
8398
8416
|
}
|
|
8399
8417
|
function isProcessAlive2(pid) {
|
|
@@ -8409,6 +8427,7 @@ var init_reconcile = __esm({
|
|
|
8409
8427
|
"src/team/reconcile.ts"() {
|
|
8410
8428
|
"use strict";
|
|
8411
8429
|
import_node_process2 = __toESM(require("process"));
|
|
8430
|
+
init_store3();
|
|
8412
8431
|
init_store5();
|
|
8413
8432
|
init_store4();
|
|
8414
8433
|
}
|
|
@@ -12672,7 +12691,7 @@ function buildStaticPromptBlocks(input) {
|
|
|
12672
12691
|
function buildIdentityContract(config, runtimeState) {
|
|
12673
12692
|
const identity = runtimeState.identity;
|
|
12674
12693
|
const lines = [
|
|
12675
|
-
"You are Athlete, a
|
|
12694
|
+
"You are Athlete, a problem-solving agent focused on durable task execution.",
|
|
12676
12695
|
"Use tools for real actions instead of role-playing filesystem, shell, browser, task, or team work.",
|
|
12677
12696
|
config.mode === "agent" ? "Mode: agent. You may edit files and run commands inside allowed roots." : "Mode: read-only. Inspect and analyze only; do not attempt mutating actions."
|
|
12678
12697
|
];
|
|
@@ -21244,6 +21263,86 @@ var init_session2 = __esm({
|
|
|
21244
21263
|
}
|
|
21245
21264
|
});
|
|
21246
21265
|
|
|
21266
|
+
// src/execution/reconcile.ts
|
|
21267
|
+
async function reconcileActiveExecutions(rootDir) {
|
|
21268
|
+
const store = new ExecutionStore(rootDir);
|
|
21269
|
+
const executions = await store.listRelevant({
|
|
21270
|
+
statuses: ["queued", "running"]
|
|
21271
|
+
});
|
|
21272
|
+
const reconciledExecutions = [];
|
|
21273
|
+
for (const execution of executions) {
|
|
21274
|
+
const reconciled = await reconcileExecution(store, execution);
|
|
21275
|
+
if (reconciled) {
|
|
21276
|
+
reconciledExecutions.push(reconciled);
|
|
21277
|
+
}
|
|
21278
|
+
}
|
|
21279
|
+
return {
|
|
21280
|
+
reconciledExecutions
|
|
21281
|
+
};
|
|
21282
|
+
}
|
|
21283
|
+
async function reconcileExecution(store, execution) {
|
|
21284
|
+
if (execution.launch === "inline") {
|
|
21285
|
+
return failExecution(store, execution, {
|
|
21286
|
+
summary: `${execution.profile} execution failed after the host process exited unexpectedly`,
|
|
21287
|
+
output: `Inline ${execution.profile} execution '${execution.id}' was interrupted because the host process exited before completion.`,
|
|
21288
|
+
statusDetail: "host_exited_unexpectedly"
|
|
21289
|
+
});
|
|
21290
|
+
}
|
|
21291
|
+
if (typeof execution.pid === "number") {
|
|
21292
|
+
if (isProcessAlive3(execution.pid)) {
|
|
21293
|
+
if (execution.status === "queued") {
|
|
21294
|
+
return store.start(execution.id, {
|
|
21295
|
+
pid: execution.pid,
|
|
21296
|
+
sessionId: execution.sessionId,
|
|
21297
|
+
cwd: execution.cwd,
|
|
21298
|
+
worktreeName: execution.worktreeName
|
|
21299
|
+
});
|
|
21300
|
+
}
|
|
21301
|
+
return null;
|
|
21302
|
+
}
|
|
21303
|
+
return failExecution(store, execution, {
|
|
21304
|
+
summary: `${execution.profile} execution failed after worker exited unexpectedly`,
|
|
21305
|
+
output: `Worker-backed ${execution.profile} execution '${execution.id}' exited unexpectedly before reporting completion.`,
|
|
21306
|
+
statusDetail: "worker_exited_unexpectedly"
|
|
21307
|
+
});
|
|
21308
|
+
}
|
|
21309
|
+
return failExecution(store, execution, {
|
|
21310
|
+
summary: `${execution.profile} execution failed because worker launch never completed`,
|
|
21311
|
+
output: `Worker-backed ${execution.profile} execution '${execution.id}' never reached a live worker before the host process exited.`,
|
|
21312
|
+
statusDetail: "worker_never_started"
|
|
21313
|
+
});
|
|
21314
|
+
}
|
|
21315
|
+
async function failExecution(store, execution, input) {
|
|
21316
|
+
const current = execution.status === "queued" ? await store.start(execution.id, {
|
|
21317
|
+
pid: execution.pid,
|
|
21318
|
+
sessionId: execution.sessionId,
|
|
21319
|
+
cwd: execution.cwd,
|
|
21320
|
+
worktreeName: execution.worktreeName
|
|
21321
|
+
}) : execution;
|
|
21322
|
+
return store.close(current.id, {
|
|
21323
|
+
status: "failed",
|
|
21324
|
+
summary: input.summary,
|
|
21325
|
+
output: input.output,
|
|
21326
|
+
statusDetail: input.statusDetail
|
|
21327
|
+
});
|
|
21328
|
+
}
|
|
21329
|
+
function isProcessAlive3(pid) {
|
|
21330
|
+
try {
|
|
21331
|
+
import_node_process3.default.kill(pid, 0);
|
|
21332
|
+
return true;
|
|
21333
|
+
} catch {
|
|
21334
|
+
return false;
|
|
21335
|
+
}
|
|
21336
|
+
}
|
|
21337
|
+
var import_node_process3;
|
|
21338
|
+
var init_reconcile2 = __esm({
|
|
21339
|
+
"src/execution/reconcile.ts"() {
|
|
21340
|
+
"use strict";
|
|
21341
|
+
import_node_process3 = __toESM(require("process"));
|
|
21342
|
+
init_store3();
|
|
21343
|
+
}
|
|
21344
|
+
});
|
|
21345
|
+
|
|
21247
21346
|
// src/orchestrator/taskLifecycleShared.ts
|
|
21248
21347
|
function leadActor() {
|
|
21249
21348
|
return LEAD_ACTOR;
|
|
@@ -22226,6 +22325,7 @@ var init_dispatch = __esm({
|
|
|
22226
22325
|
|
|
22227
22326
|
// src/orchestrator/progress.ts
|
|
22228
22327
|
async function loadOrchestratorProgress(input) {
|
|
22328
|
+
await reconcileActiveExecutions(input.rootDir);
|
|
22229
22329
|
await reconcileTeamState(input.rootDir);
|
|
22230
22330
|
await reconcileBackgroundJobs(input.rootDir);
|
|
22231
22331
|
const taskStore = new TaskStore(input.rootDir);
|
|
@@ -22306,6 +22406,7 @@ var init_progress2 = __esm({
|
|
|
22306
22406
|
"src/orchestrator/progress.ts"() {
|
|
22307
22407
|
"use strict";
|
|
22308
22408
|
init_background();
|
|
22409
|
+
init_reconcile2();
|
|
22309
22410
|
init_store3();
|
|
22310
22411
|
init_policyStore();
|
|
22311
22412
|
init_requestStore();
|
|
@@ -23001,66 +23102,66 @@ async function terminateKnownProcesses(pids) {
|
|
|
23001
23102
|
const terminated = [];
|
|
23002
23103
|
for (const pid of uniquePids) {
|
|
23003
23104
|
const killed = await terminateProcessTree(pid);
|
|
23004
|
-
if (killed || !
|
|
23105
|
+
if (killed || !isProcessAlive4(pid)) {
|
|
23005
23106
|
terminated.push(pid);
|
|
23006
23107
|
}
|
|
23007
23108
|
}
|
|
23008
23109
|
return terminated;
|
|
23009
23110
|
}
|
|
23010
|
-
function
|
|
23111
|
+
function isProcessAlive4(pid) {
|
|
23011
23112
|
if (!Number.isFinite(pid) || pid <= 0) {
|
|
23012
23113
|
return false;
|
|
23013
23114
|
}
|
|
23014
23115
|
try {
|
|
23015
|
-
|
|
23116
|
+
import_node_process4.default.kill(pid, 0);
|
|
23016
23117
|
return true;
|
|
23017
23118
|
} catch {
|
|
23018
23119
|
return false;
|
|
23019
23120
|
}
|
|
23020
23121
|
}
|
|
23021
23122
|
async function terminateProcessTree(pid) {
|
|
23022
|
-
if (!
|
|
23123
|
+
if (!isProcessAlive4(pid)) {
|
|
23023
23124
|
return false;
|
|
23024
23125
|
}
|
|
23025
|
-
if (
|
|
23126
|
+
if (import_node_process4.default.platform === "win32") {
|
|
23026
23127
|
await (0, import_execa5.execa)("taskkill", ["/PID", String(pid), "/T", "/F"], {
|
|
23027
23128
|
reject: false,
|
|
23028
23129
|
timeout: 1e4,
|
|
23029
23130
|
windowsHide: true
|
|
23030
23131
|
}).catch(() => null);
|
|
23031
23132
|
await waitForProcessExit(pid, 40, 50);
|
|
23032
|
-
return !
|
|
23133
|
+
return !isProcessAlive4(pid);
|
|
23033
23134
|
}
|
|
23034
23135
|
try {
|
|
23035
|
-
|
|
23136
|
+
import_node_process4.default.kill(pid, "SIGTERM");
|
|
23036
23137
|
} catch {
|
|
23037
23138
|
return false;
|
|
23038
23139
|
}
|
|
23039
23140
|
await waitForProcessExit(pid, 20, 50);
|
|
23040
|
-
if (!
|
|
23141
|
+
if (!isProcessAlive4(pid)) {
|
|
23041
23142
|
return true;
|
|
23042
23143
|
}
|
|
23043
23144
|
try {
|
|
23044
|
-
|
|
23145
|
+
import_node_process4.default.kill(pid, "SIGKILL");
|
|
23045
23146
|
} catch {
|
|
23046
23147
|
return false;
|
|
23047
23148
|
}
|
|
23048
23149
|
await waitForProcessExit(pid, 20, 50);
|
|
23049
|
-
return !
|
|
23150
|
+
return !isProcessAlive4(pid);
|
|
23050
23151
|
}
|
|
23051
23152
|
async function waitForProcessExit(pid, attempts, delayMs) {
|
|
23052
23153
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
23053
|
-
if (!
|
|
23154
|
+
if (!isProcessAlive4(pid)) {
|
|
23054
23155
|
return;
|
|
23055
23156
|
}
|
|
23056
23157
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
23057
23158
|
}
|
|
23058
23159
|
}
|
|
23059
|
-
var
|
|
23160
|
+
var import_node_process4, import_execa5;
|
|
23060
23161
|
var init_processControl = __esm({
|
|
23061
23162
|
"src/utils/processControl.ts"() {
|
|
23062
23163
|
"use strict";
|
|
23063
|
-
|
|
23164
|
+
import_node_process4 = __toESM(require("process"));
|
|
23064
23165
|
import_execa5 = require("execa");
|
|
23065
23166
|
}
|
|
23066
23167
|
});
|
|
@@ -23093,11 +23194,11 @@ async function collectRunningProcesses(cwd) {
|
|
|
23093
23194
|
];
|
|
23094
23195
|
}
|
|
23095
23196
|
async function terminateProcesses(processes) {
|
|
23096
|
-
const terminatedPids = await terminateKnownProcesses(processes.map((
|
|
23197
|
+
const terminatedPids = await terminateKnownProcesses(processes.map((process8) => process8.pid));
|
|
23097
23198
|
const terminated = new Set(terminatedPids);
|
|
23098
23199
|
return {
|
|
23099
23200
|
terminatedPids,
|
|
23100
|
-
failedPids: processes.map((
|
|
23201
|
+
failedPids: processes.map((process8) => process8.pid).filter((pid) => !terminated.has(pid))
|
|
23101
23202
|
};
|
|
23102
23203
|
}
|
|
23103
23204
|
var defaultInteractiveExitGuard;
|
|
@@ -23612,6 +23713,7 @@ async function handleLocalCommand(input, context, output) {
|
|
|
23612
23713
|
if (TASKS_COMMANDS.has(normalized) || TEAM_COMMANDS.has(normalized) || BACKGROUND_COMMANDS.has(normalized) || INBOX_COMMANDS.has(normalized) || WORKTREES_COMMANDS.has(normalized)) {
|
|
23613
23714
|
const projectContext = await loadProjectContext(context.cwd);
|
|
23614
23715
|
const rootDir = projectContext.stateRootDir;
|
|
23716
|
+
await reconcileActiveExecutions(rootDir).catch(() => null);
|
|
23615
23717
|
if (TASKS_COMMANDS.has(normalized)) {
|
|
23616
23718
|
await reconcileTeamState(rootDir).catch(() => null);
|
|
23617
23719
|
output.plain(await new TaskStore(rootDir).summarize());
|
|
@@ -23645,6 +23747,7 @@ var init_localCommands = __esm({
|
|
|
23645
23747
|
"use strict";
|
|
23646
23748
|
init_session2();
|
|
23647
23749
|
init_background();
|
|
23750
|
+
init_reconcile2();
|
|
23648
23751
|
init_projectContext();
|
|
23649
23752
|
init_reset();
|
|
23650
23753
|
init_store5();
|
|
@@ -23680,7 +23783,11 @@ var init_sessionDriver = __esm({
|
|
|
23680
23783
|
"src/interaction/sessionDriver.ts"() {
|
|
23681
23784
|
"use strict";
|
|
23682
23785
|
init_errors2();
|
|
23786
|
+
init_projectContext();
|
|
23787
|
+
init_background();
|
|
23788
|
+
init_reconcile2();
|
|
23683
23789
|
init_turn2();
|
|
23790
|
+
init_reconcile();
|
|
23684
23791
|
init_exitGuard();
|
|
23685
23792
|
init_localCommands();
|
|
23686
23793
|
InteractiveSessionDriver = class {
|
|
@@ -23693,6 +23800,7 @@ var init_sessionDriver = __esm({
|
|
|
23693
23800
|
turnAbortController = null;
|
|
23694
23801
|
lastInterruptNoticeAt = 0;
|
|
23695
23802
|
async run() {
|
|
23803
|
+
await this.reconcileInteractiveRuntime();
|
|
23696
23804
|
const releaseInterrupt = this.options.shell.input.bindInterrupt(() => {
|
|
23697
23805
|
this.handleInterrupt();
|
|
23698
23806
|
});
|
|
@@ -23716,6 +23824,17 @@ var init_sessionDriver = __esm({
|
|
|
23716
23824
|
releaseInterrupt();
|
|
23717
23825
|
}
|
|
23718
23826
|
}
|
|
23827
|
+
async reconcileInteractiveRuntime() {
|
|
23828
|
+
try {
|
|
23829
|
+
const projectContext = await loadProjectContext(this.options.cwd);
|
|
23830
|
+
const rootDir = projectContext.stateRootDir;
|
|
23831
|
+
await reconcileActiveExecutions(rootDir);
|
|
23832
|
+
await reconcileTeamState(rootDir);
|
|
23833
|
+
await reconcileBackgroundJobs(rootDir);
|
|
23834
|
+
} catch (error) {
|
|
23835
|
+
this.options.shell.output.warn(`Runtime recovery skipped: ${getErrorMessage(error)}`);
|
|
23836
|
+
}
|
|
23837
|
+
}
|
|
23719
23838
|
async handleInput(input) {
|
|
23720
23839
|
let localCommandResult;
|
|
23721
23840
|
try {
|
|
@@ -23755,7 +23874,7 @@ var init_sessionDriver = __esm({
|
|
|
23755
23874
|
return "quit";
|
|
23756
23875
|
}
|
|
23757
23876
|
this.options.shell.output.warn("Running background processes detected. Exiting now will kill them all.");
|
|
23758
|
-
this.options.shell.output.plain(runningProcesses.map((
|
|
23877
|
+
this.options.shell.output.plain(runningProcesses.map((process8) => process8.summary).join("\n"));
|
|
23759
23878
|
const confirmation = await this.options.shell.input.readInput(
|
|
23760
23879
|
"Kill all running background processes and exit? [y/N] "
|
|
23761
23880
|
);
|
|
@@ -23936,8 +24055,8 @@ var init_output = __esm({
|
|
|
23936
24055
|
async function readPersistentInput(promptLabel, onInterrupt) {
|
|
23937
24056
|
return new Promise((resolve) => {
|
|
23938
24057
|
const rl = import_node_readline.default.createInterface({
|
|
23939
|
-
input:
|
|
23940
|
-
output:
|
|
24058
|
+
input: import_node_process5.default.stdin,
|
|
24059
|
+
output: import_node_process5.default.stdout,
|
|
23941
24060
|
terminal: true
|
|
23942
24061
|
});
|
|
23943
24062
|
let settled = false;
|
|
@@ -23977,8 +24096,8 @@ async function readPersistentInput(promptLabel, onInterrupt) {
|
|
|
23977
24096
|
async function readMultilineInput(onInterrupt, promptLabel = "\u2026 ") {
|
|
23978
24097
|
return new Promise((resolve) => {
|
|
23979
24098
|
const rl = import_node_readline.default.createInterface({
|
|
23980
|
-
input:
|
|
23981
|
-
output:
|
|
24099
|
+
input: import_node_process5.default.stdin,
|
|
24100
|
+
output: import_node_process5.default.stdout,
|
|
23982
24101
|
terminal: true
|
|
23983
24102
|
});
|
|
23984
24103
|
const lines = [];
|
|
@@ -24028,11 +24147,31 @@ async function readMultilineInput(onInterrupt, promptLabel = "\u2026 ") {
|
|
|
24028
24147
|
}
|
|
24029
24148
|
function createReadlineInputPort() {
|
|
24030
24149
|
const listeners = /* @__PURE__ */ new Set();
|
|
24150
|
+
let releaseProcessInterrupt = null;
|
|
24031
24151
|
const notifyInterrupt = () => {
|
|
24032
24152
|
for (const listener of listeners) {
|
|
24033
24153
|
listener();
|
|
24034
24154
|
}
|
|
24035
24155
|
};
|
|
24156
|
+
const ensureProcessInterruptBinding = () => {
|
|
24157
|
+
if (releaseProcessInterrupt) {
|
|
24158
|
+
return;
|
|
24159
|
+
}
|
|
24160
|
+
const handler = () => {
|
|
24161
|
+
notifyInterrupt();
|
|
24162
|
+
};
|
|
24163
|
+
import_node_process5.default.on("SIGINT", handler);
|
|
24164
|
+
releaseProcessInterrupt = () => {
|
|
24165
|
+
import_node_process5.default.off("SIGINT", handler);
|
|
24166
|
+
releaseProcessInterrupt = null;
|
|
24167
|
+
};
|
|
24168
|
+
};
|
|
24169
|
+
const maybeReleaseProcessInterruptBinding = () => {
|
|
24170
|
+
if (listeners.size > 0) {
|
|
24171
|
+
return;
|
|
24172
|
+
}
|
|
24173
|
+
releaseProcessInterrupt?.();
|
|
24174
|
+
};
|
|
24036
24175
|
return {
|
|
24037
24176
|
async readInput(promptLabel = "> ") {
|
|
24038
24177
|
const value = await readPersistentInput(promptLabel, notifyInterrupt);
|
|
@@ -24047,17 +24186,20 @@ function createReadlineInputPort() {
|
|
|
24047
24186
|
},
|
|
24048
24187
|
bindInterrupt(handler) {
|
|
24049
24188
|
listeners.add(handler);
|
|
24189
|
+
ensureProcessInterruptBinding();
|
|
24050
24190
|
return () => {
|
|
24051
24191
|
listeners.delete(handler);
|
|
24192
|
+
maybeReleaseProcessInterruptBinding();
|
|
24052
24193
|
};
|
|
24053
24194
|
}
|
|
24054
24195
|
};
|
|
24055
24196
|
}
|
|
24056
|
-
var import_node_readline;
|
|
24197
|
+
var import_node_readline, import_node_process5;
|
|
24057
24198
|
var init_readlineInput = __esm({
|
|
24058
24199
|
"src/shell/cli/readlineInput.ts"() {
|
|
24059
24200
|
"use strict";
|
|
24060
24201
|
import_node_readline = __toESM(require("readline"));
|
|
24202
|
+
import_node_process5 = __toESM(require("process"));
|
|
24061
24203
|
}
|
|
24062
24204
|
});
|
|
24063
24205
|
|
|
@@ -24996,7 +25138,7 @@ async function runAgentExecution(rootDir, config, execution) {
|
|
|
24996
25138
|
} : null;
|
|
24997
25139
|
const store = new ExecutionStore(rootDir);
|
|
24998
25140
|
await store.start(execution.id, {
|
|
24999
|
-
pid:
|
|
25141
|
+
pid: import_node_process6.default.pid,
|
|
25000
25142
|
sessionId: session.id,
|
|
25001
25143
|
cwd: prepared.cwd,
|
|
25002
25144
|
worktreeName: prepared.worktree?.name
|
|
@@ -25050,7 +25192,7 @@ async function runAgentExecution(rootDir, config, execution) {
|
|
|
25050
25192
|
async function runCommandExecution(rootDir, execution) {
|
|
25051
25193
|
const store = new ExecutionStore(rootDir);
|
|
25052
25194
|
await store.start(execution.id, {
|
|
25053
|
-
pid:
|
|
25195
|
+
pid: import_node_process6.default.pid
|
|
25054
25196
|
});
|
|
25055
25197
|
try {
|
|
25056
25198
|
const result = await runCommandWithPolicy({
|
|
@@ -25105,7 +25247,7 @@ async function loadAgentSession(rootDir, execution, sessionStore, cwd) {
|
|
|
25105
25247
|
"working",
|
|
25106
25248
|
{
|
|
25107
25249
|
sessionId: saved.id,
|
|
25108
|
-
pid:
|
|
25250
|
+
pid: import_node_process6.default.pid
|
|
25109
25251
|
}
|
|
25110
25252
|
);
|
|
25111
25253
|
}
|
|
@@ -25176,11 +25318,11 @@ function readProcessOutput2(error) {
|
|
|
25176
25318
|
function isTimedOutError2(error) {
|
|
25177
25319
|
return Boolean(error.timedOut);
|
|
25178
25320
|
}
|
|
25179
|
-
var
|
|
25321
|
+
var import_node_process6;
|
|
25180
25322
|
var init_worker = __esm({
|
|
25181
25323
|
"src/execution/worker.ts"() {
|
|
25182
25324
|
"use strict";
|
|
25183
|
-
|
|
25325
|
+
import_node_process6 = __toESM(require("process"));
|
|
25184
25326
|
init_turn();
|
|
25185
25327
|
init_runTurn();
|
|
25186
25328
|
init_session2();
|
|
@@ -27254,10 +27396,10 @@ __export(processLock_exports, {
|
|
|
27254
27396
|
async function acquireTelegramProcessLock(options) {
|
|
27255
27397
|
const processId = options.processId ?? process.pid;
|
|
27256
27398
|
const pidFilePath = import_node_path54.default.join(options.stateDir, "service.pid");
|
|
27257
|
-
const
|
|
27399
|
+
const isProcessAlive5 = options.isProcessAlive ?? defaultIsProcessAlive;
|
|
27258
27400
|
await import_promises46.default.mkdir(options.stateDir, { recursive: true });
|
|
27259
27401
|
const existingPid = await readPidFile(pidFilePath);
|
|
27260
|
-
if (existingPid && existingPid !== processId && await
|
|
27402
|
+
if (existingPid && existingPid !== processId && await isProcessAlive5(existingPid)) {
|
|
27261
27403
|
throw new Error(
|
|
27262
27404
|
`Telegram service already running with PID ${existingPid}. Stop the existing process before starting a new one.`
|
|
27263
27405
|
);
|
|
@@ -29558,10 +29700,10 @@ __export(processLock_exports2, {
|
|
|
29558
29700
|
async function acquireWeixinProcessLock(options) {
|
|
29559
29701
|
const processId = options.processId ?? process.pid;
|
|
29560
29702
|
const pidFilePath = import_node_path61.default.join(options.stateDir, "service.pid");
|
|
29561
|
-
const
|
|
29703
|
+
const isProcessAlive5 = options.isProcessAlive ?? defaultIsProcessAlive2;
|
|
29562
29704
|
await import_promises52.default.mkdir(options.stateDir, { recursive: true });
|
|
29563
29705
|
const existingPid = await readPidFile2(pidFilePath);
|
|
29564
|
-
if (existingPid && existingPid !== processId && await
|
|
29706
|
+
if (existingPid && existingPid !== processId && await isProcessAlive5(existingPid)) {
|
|
29565
29707
|
throw new Error(`Weixin service already running with PID ${existingPid}. Stop the existing process before starting a new one.`);
|
|
29566
29708
|
}
|
|
29567
29709
|
await import_promises52.default.writeFile(pidFilePath, `${processId}
|
|
@@ -29814,7 +29956,7 @@ function buildCliProgram(dependencies = {}) {
|
|
|
29814
29956
|
const program = new import_commander.Command();
|
|
29815
29957
|
const resolveRuntime = dependencies.resolveRuntime ?? resolveCliRuntime;
|
|
29816
29958
|
const getCliOverrides = () => extractCliOverrides(program.opts());
|
|
29817
|
-
program.name("athlete").description("Athlete - a
|
|
29959
|
+
program.name("athlete").description("Athlete - a problem-solving agent focused on durable task execution.").version(package_default.version, "-v, --version", "Print the current Athlete version.").configureOutput({
|
|
29818
29960
|
writeOut: (text) => {
|
|
29819
29961
|
writeStdout(text);
|
|
29820
29962
|
},
|