@bastani/atomic 0.8.26-alpha.3 → 0.8.26-alpha.5
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/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +12 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +12 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +12 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +7 -7
- package/dist/builtin/workflows/builtin/goal.ts +10 -10
- package/dist/builtin/workflows/builtin/open-claude-design.ts +4 -4
- package/dist/builtin/workflows/builtin/ralph.ts +18 -18
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +74 -74
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
10
|
+
|
|
11
|
+
## [0.8.26-alpha.4] - 2026-06-05
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Bumped package version for the Atomic 0.8.26-alpha.4 prerelease.
|
|
16
|
+
|
|
5
17
|
## [0.8.26-alpha.3] - 2026-06-05
|
|
6
18
|
|
|
7
19
|
### Changed
|
|
@@ -4,6 +4,18 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
12
|
+
|
|
13
|
+
## [0.8.26-alpha.4] - 2026-06-05
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Bumped package version for the Atomic 0.8.26-alpha.4 prerelease.
|
|
18
|
+
|
|
7
19
|
## [0.8.26-alpha.3] - 2026-06-05
|
|
8
20
|
|
|
9
21
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
15
|
+
|
|
16
|
+
## [0.8.26-alpha.4] - 2026-06-05
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Bumped package version for the Atomic 0.8.26-alpha.4 prerelease.
|
|
21
|
+
|
|
10
22
|
## [0.8.26-alpha.3] - 2026-06-05
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
|
|
6
6
|
"contributors": [
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
10
|
+
|
|
11
|
+
## [0.8.26-alpha.4] - 2026-06-05
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Bumped package version for the Atomic 0.8.26-alpha.4 prerelease.
|
|
16
|
+
|
|
5
17
|
## [0.8.26-alpha.3] - 2026-06-05
|
|
6
18
|
|
|
7
19
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
12
|
+
|
|
13
|
+
## [0.8.26-alpha.4] - 2026-06-05
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Bumped package version for the Atomic 0.8.26-alpha.4 prerelease.
|
|
18
|
+
|
|
7
19
|
## [0.8.26-alpha.3] - 2026-06-05
|
|
8
20
|
|
|
9
21
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|
|
@@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed the workflow global tool-event hook ignoring unscoped parent-session prompts instead of attributing them to running stages, preventing false `awaiting_input` / "needs attention" states from unrelated `ask_user_question` calls ([#1261](https://github.com/bastani-inc/atomic/issues/1261)).
|
|
14
|
+
|
|
15
|
+
## [0.8.26-alpha.4] - 2026-06-05
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Upgraded builtin workflow fallback model tiers so degraded runs land on stronger models: bumped `github-copilot/claude-opus-4.8` fallbacks from `:medium` to `:xhigh` in `deep-research-codebase` and `ralph`, replaced `claude-sonnet-4-8`/`4.8` fallbacks with `claude-opus-4-8`/`4.8` in the `goal` and `ralph` runner configs, and raised `claude-sonnet-4-6`/`4.6` fallbacks from `:medium` to `:high` in `open-claude-design` ([#1259](https://github.com/bastani-inc/atomic/issues/1259)).
|
|
20
|
+
|
|
9
21
|
## [0.8.26-alpha.3] - 2026-06-05
|
|
10
22
|
|
|
11
23
|
### Changed
|
|
@@ -412,23 +412,23 @@ export default defineWorkflow("deep-research-codebase")
|
|
|
412
412
|
);
|
|
413
413
|
|
|
414
414
|
const plannerModelConfig = {
|
|
415
|
-
model: "openai/gpt-5.5:xhigh",
|
|
415
|
+
model: "openai-codex/gpt-5.5:xhigh",
|
|
416
416
|
fallbackModels: [
|
|
417
|
-
"openai-codex/gpt-5.5:xhigh",
|
|
418
417
|
"github-copilot/gpt-5.5:xhigh",
|
|
419
|
-
"
|
|
420
|
-
"github-copilot/claude-opus-4.8:
|
|
418
|
+
"openai/gpt-5.5:xhigh",
|
|
419
|
+
"github-copilot/claude-opus-4.8:xhigh",
|
|
420
|
+
"anthropic/claude-opus-4-8:xhigh"
|
|
421
421
|
],
|
|
422
422
|
excludedTools: ["ask_user_question"],
|
|
423
423
|
};
|
|
424
424
|
|
|
425
425
|
const explorerModelConfig = {
|
|
426
|
-
model: "openai/gpt-5.4-mini:low",
|
|
426
|
+
model: "openai-codex/gpt-5.4-mini:low",
|
|
427
427
|
fallbackModels: [
|
|
428
|
-
"openai-codex/gpt-5.4-mini:low",
|
|
429
428
|
"github-copilot/gpt-5.4-mini:low",
|
|
430
|
-
"
|
|
429
|
+
"openai/gpt-5.4-mini:low",
|
|
431
430
|
"github-copilot/claude-haiku-4.5:low",
|
|
431
|
+
"anthropic/claude-haiku-4-5:low",
|
|
432
432
|
],
|
|
433
433
|
excludedTools: ["ask_user_question"],
|
|
434
434
|
};
|
|
@@ -1026,23 +1026,23 @@ export default defineWorkflow("goal")
|
|
|
1026
1026
|
const { ledger, ledgerPath, artifactDir } = await createGoalLedger(objective);
|
|
1027
1027
|
|
|
1028
1028
|
const workerModelConfig = {
|
|
1029
|
-
model: "openai/gpt-5.5:medium",
|
|
1029
|
+
model: "openai-codex/gpt-5.5:medium",
|
|
1030
1030
|
fallbackModels: [
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1031
|
+
"github-copilot/gpt-5.5:medium",
|
|
1032
|
+
"openai/gpt-5.5:medium",
|
|
1033
|
+
"github-copilot/claude-opus-4.8:medium",
|
|
1034
|
+
"anthropic/claude-opus-4-8:medium",
|
|
1035
1035
|
],
|
|
1036
1036
|
tools: goalRunnerTools,
|
|
1037
1037
|
};
|
|
1038
1038
|
|
|
1039
1039
|
const reviewerModelConfig = {
|
|
1040
|
-
model: "openai/gpt-5.5:xhigh",
|
|
1040
|
+
model: "openai-codex/gpt-5.5:xhigh",
|
|
1041
1041
|
fallbackModels: [
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1042
|
+
"github-copilot/gpt-5.5:xhigh",
|
|
1043
|
+
"openai/gpt-5.5:xhigh",
|
|
1044
|
+
"github-copilot/claude-opus-4.8:xhigh",
|
|
1045
|
+
"anthropic/claude-opus-4-8:xhigh"
|
|
1046
1046
|
],
|
|
1047
1047
|
tools: [...goalRunnerTools, reviewDecisionTool.name],
|
|
1048
1048
|
customTools: [reviewDecisionTool],
|
|
@@ -226,11 +226,11 @@ export default defineWorkflow("open-claude-design")
|
|
|
226
226
|
const specFileUrl = `file://${specPath}`;
|
|
227
227
|
|
|
228
228
|
const designModelConfig = {
|
|
229
|
-
model: "
|
|
229
|
+
model: "github-copilot/claude-opus-4.8:xhigh",
|
|
230
230
|
fallbackModels: [
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
"anthropic/claude-opus-4-8:xhigh",
|
|
232
|
+
"github-copilot/claude-sonnet-4.6:high",
|
|
233
|
+
"anthropic/claude-sonnet-4-6:high",
|
|
234
234
|
],
|
|
235
235
|
};
|
|
236
236
|
|
|
@@ -615,45 +615,45 @@ async function runRalphWorkflow(
|
|
|
615
615
|
let iterationsCompleted = 0;
|
|
616
616
|
|
|
617
617
|
const plannerModelConfig = {
|
|
618
|
-
model: "openai/gpt-5.5:xhigh",
|
|
618
|
+
model: "openai-codex/gpt-5.5:xhigh",
|
|
619
619
|
fallbackModels: [
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
620
|
+
"github-copilot/gpt-5.5:xhigh",
|
|
621
|
+
"openai/gpt-5.5:xhigh",
|
|
622
|
+
"github-copilot/claude-opus-4.8:xhigh",
|
|
623
|
+
"anthropic/claude-opus-4-8:xhigh",
|
|
624
624
|
],
|
|
625
625
|
excludedTools: ["ask_user_question"],
|
|
626
626
|
};
|
|
627
627
|
|
|
628
628
|
const orchestratorModelConfig = {
|
|
629
|
-
model: "openai/gpt-5.5:medium",
|
|
629
|
+
model: "openai-codex/gpt-5.5:medium",
|
|
630
630
|
fallbackModels: [
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
631
|
+
"github-copilot/gpt-5.5:medium",
|
|
632
|
+
"openai/gpt-5.5:medium",
|
|
633
|
+
"github-copilot/claude-opus-4.8:medium",
|
|
634
|
+
"anthropic/claude-opus-4-8:medium",
|
|
635
635
|
],
|
|
636
636
|
excludedTools: ["ask_user_question"],
|
|
637
637
|
};
|
|
638
638
|
|
|
639
639
|
const simplifierModelConfig = {
|
|
640
|
-
model: "openai/gpt-5.5:medium",
|
|
640
|
+
model: "openai-codex/gpt-5.5:medium",
|
|
641
641
|
fallbackModels: [
|
|
642
|
-
"openai-codex/gpt-5.5:medium",
|
|
643
642
|
"github-copilot/gpt-5.5:medium",
|
|
644
|
-
"
|
|
645
|
-
"github-copilot/claude-
|
|
643
|
+
"openai/gpt-5.5:medium",
|
|
644
|
+
"github-copilot/claude-opus-4.8:medium",
|
|
645
|
+
"anthropic/claude-opus-4-8:medium",
|
|
646
646
|
],
|
|
647
647
|
excludedTools: ["ask_user_question"],
|
|
648
648
|
};
|
|
649
649
|
|
|
650
650
|
const reviewerModelConfig = {
|
|
651
|
-
model: "openai/gpt-5.5:xhigh",
|
|
651
|
+
model: "openai-codex/gpt-5.5:xhigh",
|
|
652
652
|
fallbackModels: [
|
|
653
|
-
"openai-codex/gpt-5.5:xhigh",
|
|
654
653
|
"github-copilot/gpt-5.5:xhigh",
|
|
655
|
-
"
|
|
656
|
-
"github-copilot/claude-opus-4.8:
|
|
654
|
+
"openai/gpt-5.5:xhigh",
|
|
655
|
+
"github-copilot/claude-opus-4.8:xhigh",
|
|
656
|
+
"anthropic/claude-opus-4-8:xhigh"
|
|
657
657
|
],
|
|
658
658
|
excludedTools: ["ask_user_question"],
|
|
659
659
|
customTools: [reviewDecisionTool],
|
|
@@ -160,121 +160,125 @@ export function installToolExecutionHooks(pi: LiveWidgetAPI, storeInstance: Stor
|
|
|
160
160
|
const extensionOn = pi.on;
|
|
161
161
|
if (typeof eventBusOn !== "function" && typeof extensionOn !== "function") return;
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
interface StageScope {
|
|
164
|
+
readonly runId: string;
|
|
165
|
+
readonly stageId: string;
|
|
166
|
+
}
|
|
164
167
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
interface ActiveToolCall extends StageScope {
|
|
169
|
+
readonly callId: string;
|
|
170
|
+
readonly name: string;
|
|
171
|
+
readonly startedAt: number;
|
|
172
|
+
}
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
const terminalRunStatuses = new Set(["completed", "failed", "killed"]);
|
|
175
|
+
const terminalStageStatuses = new Set(["completed", "failed", "skipped"]);
|
|
176
|
+
const activeToolCalls = new Map<string, ActiveToolCall>();
|
|
171
177
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
function activeCallKey(runId: string, stageId: string, callId: string): string {
|
|
179
|
+
return `${runId}\0${stageId}\0${callId}`;
|
|
180
|
+
}
|
|
175
181
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (
|
|
182
|
+
function firstNonEmptyString(...values: readonly unknown[]): string | null {
|
|
183
|
+
for (const value of values) {
|
|
184
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
179
185
|
}
|
|
180
|
-
|
|
181
186
|
return null;
|
|
182
187
|
}
|
|
183
188
|
|
|
184
|
-
function
|
|
185
|
-
|
|
189
|
+
function resolveExplicitStageScope(payload: ToolExecutionStartPayload): StageScope | null {
|
|
190
|
+
const runId = firstNonEmptyString(payload.runId, payload.run_id);
|
|
191
|
+
const stageId = firstNonEmptyString(payload.stageId, payload.stage_id);
|
|
192
|
+
if (runId === null || stageId === null) return null;
|
|
193
|
+
return { runId, stageId };
|
|
186
194
|
}
|
|
187
195
|
|
|
188
|
-
function
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
const
|
|
196
|
+
function hasLiveStageScope(scope: StageScope, snap: StoreSnapshot): boolean {
|
|
197
|
+
const run = snap.runs.find((candidate) => candidate.id === scope.runId);
|
|
198
|
+
if (!run || run.endedAt !== undefined || terminalRunStatuses.has(run.status)) return false;
|
|
199
|
+
const stage = run.stages.find((candidate) => candidate.id === scope.stageId);
|
|
200
|
+
return stage !== undefined && !terminalStageStatuses.has(stage.status);
|
|
201
|
+
}
|
|
192
202
|
|
|
193
|
-
|
|
194
|
-
|
|
203
|
+
function pruneActiveToolCalls(snap: StoreSnapshot): void {
|
|
204
|
+
for (const [key, call] of activeToolCalls) {
|
|
205
|
+
if (!hasLiveStageScope(call, snap)) activeToolCalls.delete(key);
|
|
195
206
|
}
|
|
196
|
-
|
|
197
|
-
const matches = [...activeAskUserQuestionCalls.values()].filter((entry) => {
|
|
198
|
-
if (entry.callId !== callId) return false;
|
|
199
|
-
if (runId !== undefined && entry.runId !== runId) return false;
|
|
200
|
-
if (stageId !== undefined && entry.stageId !== stageId) return false;
|
|
201
|
-
return true;
|
|
202
|
-
});
|
|
203
|
-
return matches.length === 1 ? matches[0] : undefined;
|
|
204
207
|
}
|
|
205
208
|
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
);
|
|
210
|
-
}
|
|
209
|
+
function activeToolCallForPayload(payload: ToolExecutionStartPayload): { key: string; call: ActiveToolCall } | null {
|
|
210
|
+
const scope = resolveExplicitStageScope(payload);
|
|
211
|
+
if (!scope) return null;
|
|
211
212
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
activeAskUserQuestionCalls.set(activeCallKey(ids.runId, ids.stageId, callId), {
|
|
216
|
-
...ids,
|
|
217
|
-
callId,
|
|
218
|
-
});
|
|
219
|
-
storeInstance.recordStageAwaitingInput(ids.runId, ids.stageId, true, payload.ts);
|
|
213
|
+
const key = activeCallKey(scope.runId, scope.stageId, toolCallId(payload));
|
|
214
|
+
const call = activeToolCalls.get(key);
|
|
215
|
+
return call ? { key, call } : null;
|
|
220
216
|
}
|
|
221
217
|
|
|
222
|
-
|
|
223
|
-
const activeCall = findActiveAskCall(payload);
|
|
224
|
-
const resolvedIds = activeCall ?? ids;
|
|
225
|
-
if (resolvedIds === null || resolvedIds === undefined) return;
|
|
226
|
-
|
|
227
|
-
const shouldClear = activeCall !== undefined || isAskUserQuestionToolName(toolName(payload));
|
|
228
|
-
if (!shouldClear) return;
|
|
229
|
-
|
|
230
|
-
activeAskUserQuestionCalls.delete(activeCallKey(resolvedIds.runId, resolvedIds.stageId, toolCallId(payload)));
|
|
231
|
-
if (!stageHasActiveAskCall(resolvedIds.runId, resolvedIds.stageId)) {
|
|
232
|
-
storeInstance.recordStageAwaitingInput(resolvedIds.runId, resolvedIds.stageId, false);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
218
|
+
storeInstance.subscribe(pruneActiveToolCalls);
|
|
235
219
|
|
|
236
220
|
function recordToolStart(payload: unknown): void {
|
|
237
221
|
if (!isToolExecutionPayload(payload)) return;
|
|
238
222
|
|
|
239
|
-
const
|
|
240
|
-
|
|
223
|
+
const snap = storeInstance.snapshot();
|
|
224
|
+
pruneActiveToolCalls(snap);
|
|
225
|
+
|
|
226
|
+
const scope = resolveExplicitStageScope(payload);
|
|
227
|
+
if (!scope || !hasLiveStageScope(scope, snap)) return;
|
|
241
228
|
|
|
242
|
-
|
|
243
|
-
|
|
229
|
+
const callId = toolCallId(payload);
|
|
230
|
+
const key = activeCallKey(scope.runId, scope.stageId, callId);
|
|
231
|
+
if (activeToolCalls.has(key)) return;
|
|
232
|
+
|
|
233
|
+
const name = toolName(payload);
|
|
234
|
+
const startedAt = payload.ts ?? Date.now();
|
|
235
|
+
activeToolCalls.set(key, { ...scope, callId, name, startedAt });
|
|
236
|
+
storeInstance.recordToolStart(scope.runId, scope.stageId, {
|
|
237
|
+
name,
|
|
244
238
|
input: toolInput(payload),
|
|
245
|
-
startedAt
|
|
239
|
+
startedAt,
|
|
246
240
|
});
|
|
247
|
-
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function recordToolUpdate(payload: unknown): void {
|
|
244
|
+
if (!isToolExecutionPayload(payload)) return;
|
|
245
|
+
|
|
246
|
+
pruneActiveToolCalls(storeInstance.snapshot());
|
|
247
|
+
|
|
248
|
+
if (!activeToolCallForPayload(payload)) return;
|
|
249
|
+
// Updates are attach-only until the store has an explicit update API.
|
|
248
250
|
}
|
|
249
251
|
|
|
250
252
|
function recordToolEnd(payload: unknown): void {
|
|
251
253
|
if (!isToolExecutionPayload(payload)) return;
|
|
252
254
|
|
|
253
|
-
|
|
254
|
-
const ids = activeAskCall ?? resolveIds(payload, false);
|
|
255
|
-
if (!ids) return;
|
|
255
|
+
pruneActiveToolCalls(storeInstance.snapshot());
|
|
256
256
|
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
const active = activeToolCallForPayload(payload);
|
|
258
|
+
if (!active) return;
|
|
259
|
+
|
|
260
|
+
storeInstance.recordToolEnd(active.call.runId, active.call.stageId, {
|
|
261
|
+
name: active.call.name,
|
|
259
262
|
input: toolInput(payload),
|
|
260
|
-
startedAt:
|
|
263
|
+
startedAt: active.call.startedAt,
|
|
261
264
|
endedAt: payload.endedAt ?? payload.ended_at ?? Date.now(),
|
|
262
265
|
output: payload.output,
|
|
263
266
|
});
|
|
264
|
-
|
|
267
|
+
activeToolCalls.delete(active.key);
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
const safeStart = safelyHandle(recordToolStart);
|
|
271
|
+
const safeUpdate = safelyHandle(recordToolUpdate);
|
|
268
272
|
const safeEnd = safelyHandle(recordToolEnd);
|
|
269
273
|
|
|
270
274
|
if (typeof eventBusOn === "function") {
|
|
271
275
|
eventBusOn.call(pi.events, "tool_execution_start", safeStart);
|
|
272
|
-
eventBusOn.call(pi.events, "tool_execution_update",
|
|
276
|
+
eventBusOn.call(pi.events, "tool_execution_update", safeUpdate);
|
|
273
277
|
eventBusOn.call(pi.events, "tool_execution_end", safeEnd);
|
|
274
278
|
}
|
|
275
279
|
if (typeof extensionOn === "function") {
|
|
276
280
|
extensionOn.call(pi, "tool_execution_start", safeStart);
|
|
277
|
-
extensionOn.call(pi, "tool_execution_update",
|
|
281
|
+
extensionOn.call(pi, "tool_execution_update", safeUpdate);
|
|
278
282
|
extensionOn.call(pi, "tool_execution_end", safeEnd);
|
|
279
283
|
extensionOn.call(pi, "tool_call", safeStart);
|
|
280
284
|
extensionOn.call(pi, "tool_result", safeEnd);
|
|
@@ -306,7 +310,3 @@ function toolCallId(payload: ToolExecutionStartPayload): string {
|
|
|
306
310
|
function toolInput(payload: ToolExecutionStartPayload): Record<string, unknown> | undefined {
|
|
307
311
|
return payload.input ?? payload.args;
|
|
308
312
|
}
|
|
309
|
-
|
|
310
|
-
function isAskUserQuestionToolName(name: string): boolean {
|
|
311
|
-
return name.toLowerCase().replace(/[^a-z0-9]/g, "") === "askuserquestion";
|
|
312
|
-
}
|