pi-crew 0.9.36 → 0.9.37
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 +19 -0
- package/dist/build-meta.json +50 -12
- package/dist/index.mjs +303 -7
- package/dist/index.mjs.map +4 -4
- package/package.json +1 -1
- package/src/extension/register.ts +6 -0
- package/src/extension/registration/subagent-tools.ts +18 -1
- package/src/extension/team-tool/context.ts +60 -4
- package/src/extension/team-tool/handle-settings.ts +1 -1
- package/src/runtime/progress-tracker.ts +140 -0
- package/src/ui/settings-overlay.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.37] — cold context + subagent streaming (2026-07-14)
|
|
4
|
+
|
|
5
|
+
Two performance improvements targeting perceived subagent slowness:
|
|
6
|
+
|
|
7
|
+
### Phase 1: Cold Context (inheritContext default → true)
|
|
8
|
+
|
|
9
|
+
- **`inheritContext` default changed from `false` → `true`** — subagents now receive parent conversation context by default, eliminating redundant re-exploration of files the main session already processed. Configurable via `runtime.inheritContext`.
|
|
10
|
+
- **`buildParentContext()` token budget** — 12K char budget with most-recent-first retention prevents token bloat on large parent sessions.
|
|
11
|
+
- **Noisy content filtering** — skips file dumps (code blocks, `ls` output, import lists >1K chars) and truncates long assistant messages to 200 chars. Compaction summaries kept in full.
|
|
12
|
+
- **Tests**: `test/unit/build-parent-context.test.ts` (10 cases).
|
|
13
|
+
|
|
14
|
+
### Phase 2: Subagent Streaming (child-process → widget)
|
|
15
|
+
|
|
16
|
+
- **`ProgressTracker.handleWorkerEvent()`** — bridges child-process JSON events (from `onJsonEvent`) into `crewEventBus`, enabling real-time widget display of tool calls, assistant text, and token usage for BOTH runtimes (previously only live-session had streaming).
|
|
17
|
+
- **`register.ts` onJsonEvent** — now forwards events to `globalProgressTracker` (was only feeding `overflowTracker`).
|
|
18
|
+
- **`subagent-tools.ts` inline progress** — enriched with real-time worker progress: ⚡ current tool, 📊 tokens, 💬 partial assistant text.
|
|
19
|
+
- **Throttled to 500ms per worker** to prevent widget flooding.
|
|
20
|
+
- **Tests**: `test/unit/progress-tracker-worker.test.ts` (8 cases).
|
|
21
|
+
|
|
3
22
|
## [0.9.36] — security audit round 1 (2026-07-14)
|
|
4
23
|
|
|
5
24
|
Three security hardening fixes from the first formal security audit pass (run via `team_20260714045239_bb49d72211b966a2` + verified via `team_20260714062932_638dbb0310cc9f77`, 12/12 targeted tests pass, typecheck clean):
|
package/dist/build-meta.json
CHANGED
|
@@ -8410,7 +8410,7 @@
|
|
|
8410
8410
|
"format": "esm"
|
|
8411
8411
|
},
|
|
8412
8412
|
"src/extension/team-tool/context.ts": {
|
|
8413
|
-
"bytes":
|
|
8413
|
+
"bytes": 5581,
|
|
8414
8414
|
"imports": [
|
|
8415
8415
|
{
|
|
8416
8416
|
"path": "src/extension/tool-result.ts",
|
|
@@ -8577,7 +8577,7 @@
|
|
|
8577
8577
|
"format": "esm"
|
|
8578
8578
|
},
|
|
8579
8579
|
"src/extension/team-tool/handle-settings.ts": {
|
|
8580
|
-
"bytes":
|
|
8580
|
+
"bytes": 17989,
|
|
8581
8581
|
"imports": [
|
|
8582
8582
|
{
|
|
8583
8583
|
"path": "src/config/config.ts",
|
|
@@ -16950,7 +16950,7 @@
|
|
|
16950
16950
|
"format": "esm"
|
|
16951
16951
|
},
|
|
16952
16952
|
"src/ui/settings-overlay.ts": {
|
|
16953
|
-
"bytes":
|
|
16953
|
+
"bytes": 31025,
|
|
16954
16954
|
"imports": [
|
|
16955
16955
|
{
|
|
16956
16956
|
"path": "src/utils/visual.ts",
|
|
@@ -17720,8 +17720,30 @@
|
|
|
17720
17720
|
],
|
|
17721
17721
|
"format": "esm"
|
|
17722
17722
|
},
|
|
17723
|
+
"src/observability/event-bus.ts": {
|
|
17724
|
+
"bytes": 2219,
|
|
17725
|
+
"imports": [
|
|
17726
|
+
{
|
|
17727
|
+
"path": "src/utils/internal-error.ts",
|
|
17728
|
+
"kind": "import-statement",
|
|
17729
|
+
"original": "../utils/internal-error.ts"
|
|
17730
|
+
}
|
|
17731
|
+
],
|
|
17732
|
+
"format": "esm"
|
|
17733
|
+
},
|
|
17734
|
+
"src/runtime/progress-tracker.ts": {
|
|
17735
|
+
"bytes": 7543,
|
|
17736
|
+
"imports": [
|
|
17737
|
+
{
|
|
17738
|
+
"path": "src/observability/event-bus.ts",
|
|
17739
|
+
"kind": "import-statement",
|
|
17740
|
+
"original": "../observability/event-bus.ts"
|
|
17741
|
+
}
|
|
17742
|
+
],
|
|
17743
|
+
"format": "esm"
|
|
17744
|
+
},
|
|
17723
17745
|
"src/extension/registration/subagent-tools.ts": {
|
|
17724
|
-
"bytes":
|
|
17746
|
+
"bytes": 18292,
|
|
17725
17747
|
"imports": [
|
|
17726
17748
|
{
|
|
17727
17749
|
"path": "node_modules/@sinclair/typebox/build/esm/index.mjs",
|
|
@@ -17753,6 +17775,11 @@
|
|
|
17753
17775
|
"kind": "import-statement",
|
|
17754
17776
|
"original": "../../runtime/crew-agent-records.ts"
|
|
17755
17777
|
},
|
|
17778
|
+
{
|
|
17779
|
+
"path": "src/runtime/progress-tracker.ts",
|
|
17780
|
+
"kind": "import-statement",
|
|
17781
|
+
"original": "../../runtime/progress-tracker.ts"
|
|
17782
|
+
},
|
|
17756
17783
|
{
|
|
17757
17784
|
"path": "src/runtime/role-permission.ts",
|
|
17758
17785
|
"kind": "import-statement",
|
|
@@ -17993,7 +18020,7 @@
|
|
|
17993
18020
|
"format": "esm"
|
|
17994
18021
|
},
|
|
17995
18022
|
"src/extension/register.ts": {
|
|
17996
|
-
"bytes":
|
|
18023
|
+
"bytes": 68402,
|
|
17997
18024
|
"imports": [
|
|
17998
18025
|
{
|
|
17999
18026
|
"path": "node:fs",
|
|
@@ -18315,6 +18342,11 @@
|
|
|
18315
18342
|
"kind": "import-statement",
|
|
18316
18343
|
"original": "../i18n.ts"
|
|
18317
18344
|
},
|
|
18345
|
+
{
|
|
18346
|
+
"path": "src/runtime/progress-tracker.ts",
|
|
18347
|
+
"kind": "import-statement",
|
|
18348
|
+
"original": "../runtime/progress-tracker.ts"
|
|
18349
|
+
},
|
|
18318
18350
|
{
|
|
18319
18351
|
"path": "src/runtime/session-resources.ts",
|
|
18320
18352
|
"kind": "import-statement",
|
|
@@ -18415,7 +18447,7 @@
|
|
|
18415
18447
|
"imports": [],
|
|
18416
18448
|
"exports": [],
|
|
18417
18449
|
"inputs": {},
|
|
18418
|
-
"bytes":
|
|
18450
|
+
"bytes": 6717985
|
|
18419
18451
|
},
|
|
18420
18452
|
"dist/index.mjs": {
|
|
18421
18453
|
"imports": [
|
|
@@ -20931,7 +20963,7 @@
|
|
|
20931
20963
|
"bytesInOutput": 1541
|
|
20932
20964
|
},
|
|
20933
20965
|
"src/extension/team-tool/context.ts": {
|
|
20934
|
-
"bytesInOutput":
|
|
20966
|
+
"bytesInOutput": 3237
|
|
20935
20967
|
},
|
|
20936
20968
|
"src/extension/team-tool/intent-policy.ts": {
|
|
20937
20969
|
"bytesInOutput": 1245
|
|
@@ -20952,7 +20984,7 @@
|
|
|
20952
20984
|
"bytesInOutput": 1876
|
|
20953
20985
|
},
|
|
20954
20986
|
"src/extension/team-tool/handle-settings.ts": {
|
|
20955
|
-
"bytesInOutput":
|
|
20987
|
+
"bytesInOutput": 16051
|
|
20956
20988
|
},
|
|
20957
20989
|
"src/workflows/validate-workflow.ts": {
|
|
20958
20990
|
"bytesInOutput": 1927
|
|
@@ -21960,7 +21992,7 @@
|
|
|
21960
21992
|
"bytesInOutput": 15659
|
|
21961
21993
|
},
|
|
21962
21994
|
"src/ui/settings-overlay.ts": {
|
|
21963
|
-
"bytesInOutput":
|
|
21995
|
+
"bytesInOutput": 30588
|
|
21964
21996
|
},
|
|
21965
21997
|
"src/extension/registration/commands.ts": {
|
|
21966
21998
|
"bytesInOutput": 40488
|
|
@@ -22020,7 +22052,7 @@
|
|
|
22020
22052
|
"bytesInOutput": 3150
|
|
22021
22053
|
},
|
|
22022
22054
|
"src/extension/register.ts": {
|
|
22023
|
-
"bytesInOutput":
|
|
22055
|
+
"bytesInOutput": 45685
|
|
22024
22056
|
},
|
|
22025
22057
|
"src/runtime/batch-barrier.ts": {
|
|
22026
22058
|
"bytesInOutput": 3060
|
|
@@ -22104,11 +22136,17 @@
|
|
|
22104
22136
|
"bytesInOutput": 647
|
|
22105
22137
|
},
|
|
22106
22138
|
"src/extension/registration/subagent-tools.ts": {
|
|
22107
|
-
"bytesInOutput":
|
|
22139
|
+
"bytesInOutput": 16197
|
|
22108
22140
|
},
|
|
22109
22141
|
"src/i18n.ts": {
|
|
22110
22142
|
"bytesInOutput": 6837
|
|
22111
22143
|
},
|
|
22144
|
+
"src/observability/event-bus.ts": {
|
|
22145
|
+
"bytesInOutput": 1170
|
|
22146
|
+
},
|
|
22147
|
+
"src/runtime/progress-tracker.ts": {
|
|
22148
|
+
"bytesInOutput": 6660
|
|
22149
|
+
},
|
|
22112
22150
|
"src/extension/session-summary.ts": {
|
|
22113
22151
|
"bytesInOutput": 512
|
|
22114
22152
|
},
|
|
@@ -22125,7 +22163,7 @@
|
|
|
22125
22163
|
"bytesInOutput": 81
|
|
22126
22164
|
}
|
|
22127
22165
|
},
|
|
22128
|
-
"bytes":
|
|
22166
|
+
"bytes": 3182689
|
|
22129
22167
|
}
|
|
22130
22168
|
}
|
|
22131
22169
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -24757,6 +24757,7 @@ var init_workflow_serializer = __esm({
|
|
|
24757
24757
|
// src/extension/team-tool/context.ts
|
|
24758
24758
|
var context_exports = {};
|
|
24759
24759
|
__export(context_exports, {
|
|
24760
|
+
MAX_PARENT_CONTEXT_CHARS: () => MAX_PARENT_CONTEXT_CHARS,
|
|
24760
24761
|
buildParentContext: () => buildParentContext,
|
|
24761
24762
|
configRecord: () => configRecord,
|
|
24762
24763
|
formatScoped: () => formatScoped,
|
|
@@ -24780,6 +24781,10 @@ function extractTextContent(content) {
|
|
|
24780
24781
|
(part) => part && typeof part === "object" && !Array.isArray(part) && typeof part.text === "string" ? part.text : ""
|
|
24781
24782
|
).filter(Boolean).join("\n");
|
|
24782
24783
|
}
|
|
24784
|
+
function isNoisyContent(text) {
|
|
24785
|
+
if (text.length < NOISY_THRESHOLD) return false;
|
|
24786
|
+
return NOISY_PREFIXES.some((prefix) => text.startsWith(prefix));
|
|
24787
|
+
}
|
|
24783
24788
|
function buildParentContext(ctx) {
|
|
24784
24789
|
const branch = ctx.sessionManager?.getBranch?.();
|
|
24785
24790
|
if (!Array.isArray(branch) || branch.length === 0) return void 0;
|
|
@@ -24787,28 +24792,50 @@ function buildParentContext(ctx) {
|
|
|
24787
24792
|
for (const entry of branch.slice(-20)) {
|
|
24788
24793
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
24789
24794
|
const record = entry;
|
|
24790
|
-
if (record.type === "compaction" && typeof record.summary === "string")
|
|
24795
|
+
if (record.type === "compaction" && typeof record.summary === "string") {
|
|
24796
|
+
parts.push(`[Summary]: ${record.summary}`);
|
|
24797
|
+
continue;
|
|
24798
|
+
}
|
|
24791
24799
|
const message = record.message && typeof record.message === "object" && !Array.isArray(record.message) ? record.message : void 0;
|
|
24792
24800
|
if (!message || message.role !== "user" && message.role !== "assistant") continue;
|
|
24793
|
-
|
|
24794
|
-
if (text)
|
|
24801
|
+
let text = extractTextContent(message.content).trim();
|
|
24802
|
+
if (!text) continue;
|
|
24803
|
+
if (isNoisyContent(text)) continue;
|
|
24804
|
+
if (message.role === "assistant" && text.length > MAX_ASSISTANT_MSG_CHARS) {
|
|
24805
|
+
text = `${text.slice(0, TRUNCATED_ASSISTANT_CHARS)}\u2026`;
|
|
24806
|
+
}
|
|
24807
|
+
parts.push(`[${message.role === "user" ? "User" : "Assistant"}]: ${text}`);
|
|
24795
24808
|
}
|
|
24796
24809
|
if (!parts.length) return void 0;
|
|
24810
|
+
let totalChars = 0;
|
|
24811
|
+
const budgeted = [];
|
|
24812
|
+
for (const part of [...parts].reverse()) {
|
|
24813
|
+
if (totalChars + part.length > MAX_PARENT_CONTEXT_CHARS) break;
|
|
24814
|
+
budgeted.unshift(part);
|
|
24815
|
+
totalChars += part.length;
|
|
24816
|
+
}
|
|
24817
|
+
if (!budgeted.length) return void 0;
|
|
24797
24818
|
return [
|
|
24798
24819
|
`# Parent Conversation Context`,
|
|
24799
24820
|
"The following context was inherited from the parent Pi session. Treat it as reference-only.",
|
|
24800
24821
|
"",
|
|
24801
|
-
|
|
24822
|
+
budgeted.join("\n\n")
|
|
24802
24823
|
].join("\n");
|
|
24803
24824
|
}
|
|
24804
24825
|
function configRecord(config) {
|
|
24805
24826
|
if (!config || typeof config !== "object" || Array.isArray(config)) return {};
|
|
24806
24827
|
return config;
|
|
24807
24828
|
}
|
|
24829
|
+
var MAX_PARENT_CONTEXT_CHARS, MAX_ASSISTANT_MSG_CHARS, TRUNCATED_ASSISTANT_CHARS, NOISY_THRESHOLD, NOISY_PREFIXES;
|
|
24808
24830
|
var init_context = __esm({
|
|
24809
24831
|
"src/extension/team-tool/context.ts"() {
|
|
24810
24832
|
"use strict";
|
|
24811
24833
|
init_tool_result();
|
|
24834
|
+
MAX_PARENT_CONTEXT_CHARS = 12e3;
|
|
24835
|
+
MAX_ASSISTANT_MSG_CHARS = 500;
|
|
24836
|
+
TRUNCATED_ASSISTANT_CHARS = 200;
|
|
24837
|
+
NOISY_THRESHOLD = 1e3;
|
|
24838
|
+
NOISY_PREFIXES = ["```", "total ", "drwx", "-rw", "import ", "export "];
|
|
24812
24839
|
}
|
|
24813
24840
|
});
|
|
24814
24841
|
|
|
@@ -26191,7 +26218,7 @@ var init_handle_settings = __esm({
|
|
|
26191
26218
|
"runtime.mode": "auto",
|
|
26192
26219
|
"runtime.maxTurns": 1e4,
|
|
26193
26220
|
"runtime.graceTurns": 5,
|
|
26194
|
-
"runtime.inheritContext":
|
|
26221
|
+
"runtime.inheritContext": true,
|
|
26195
26222
|
"runtime.promptMode": "replace",
|
|
26196
26223
|
"runtime.completionMutationGuard": "warn",
|
|
26197
26224
|
"runtime.isolationPolicy": void 0,
|
|
@@ -75794,7 +75821,7 @@ var init_settings_overlay = __esm({
|
|
|
75794
75821
|
"runtime.mode": "auto",
|
|
75795
75822
|
"runtime.maxTurns": 1e4,
|
|
75796
75823
|
"runtime.graceTurns": 5,
|
|
75797
|
-
"runtime.inheritContext":
|
|
75824
|
+
"runtime.inheritContext": true,
|
|
75798
75825
|
"runtime.promptMode": "replace",
|
|
75799
75826
|
"runtime.completionMutationGuard": "warn",
|
|
75800
75827
|
"runtime.isolationPolicy": void 0,
|
|
@@ -84091,6 +84118,259 @@ function initI18n(pi) {
|
|
|
84091
84118
|
|
|
84092
84119
|
// src/extension/registration/subagent-tools.ts
|
|
84093
84120
|
init_crew_agent_records();
|
|
84121
|
+
|
|
84122
|
+
// src/observability/event-bus.ts
|
|
84123
|
+
init_internal_error();
|
|
84124
|
+
var EventBus = class _EventBus {
|
|
84125
|
+
listeners = /* @__PURE__ */ new Map();
|
|
84126
|
+
static _instance;
|
|
84127
|
+
static getInstance() {
|
|
84128
|
+
if (!_EventBus._instance) {
|
|
84129
|
+
_EventBus._instance = new _EventBus();
|
|
84130
|
+
}
|
|
84131
|
+
return _EventBus._instance;
|
|
84132
|
+
}
|
|
84133
|
+
/**
|
|
84134
|
+
* Dispose of the EventBus instance and clear all listeners.
|
|
84135
|
+
* Resets the singleton so a new instance can be created.
|
|
84136
|
+
*/
|
|
84137
|
+
dispose() {
|
|
84138
|
+
this.listeners.clear();
|
|
84139
|
+
_EventBus._instance = void 0;
|
|
84140
|
+
}
|
|
84141
|
+
emit(event) {
|
|
84142
|
+
const listeners2 = this.listeners.get(event.type);
|
|
84143
|
+
if (listeners2) {
|
|
84144
|
+
for (const listener of listeners2) {
|
|
84145
|
+
try {
|
|
84146
|
+
listener(event);
|
|
84147
|
+
} catch (e) {
|
|
84148
|
+
logInternalError("event-bus.listener", e, `type=${event.type} runId=${event.runId}`);
|
|
84149
|
+
}
|
|
84150
|
+
}
|
|
84151
|
+
}
|
|
84152
|
+
}
|
|
84153
|
+
on(type, listener) {
|
|
84154
|
+
if (!this.listeners.has(type)) {
|
|
84155
|
+
this.listeners.set(type, /* @__PURE__ */ new Set());
|
|
84156
|
+
}
|
|
84157
|
+
this.listeners.get(type).add(listener);
|
|
84158
|
+
return () => {
|
|
84159
|
+
this.listeners.get(type)?.delete(listener);
|
|
84160
|
+
};
|
|
84161
|
+
}
|
|
84162
|
+
off(type, listener) {
|
|
84163
|
+
this.listeners.get(type)?.delete(listener);
|
|
84164
|
+
}
|
|
84165
|
+
};
|
|
84166
|
+
var crewEventBus = EventBus.getInstance();
|
|
84167
|
+
|
|
84168
|
+
// src/runtime/progress-tracker.ts
|
|
84169
|
+
var ProgressTracker = class _ProgressTracker {
|
|
84170
|
+
sessions = /* @__PURE__ */ new Map();
|
|
84171
|
+
track(session, agentId, runId) {
|
|
84172
|
+
if (this.sessions.has(agentId)) {
|
|
84173
|
+
return this.sessions.get(agentId).progress;
|
|
84174
|
+
}
|
|
84175
|
+
const progress = {
|
|
84176
|
+
toolCalls: 0,
|
|
84177
|
+
currentTool: null,
|
|
84178
|
+
toolStartTime: null,
|
|
84179
|
+
errors: [],
|
|
84180
|
+
turns: 0,
|
|
84181
|
+
tokens: { input: 0, output: 0 },
|
|
84182
|
+
status: "running"
|
|
84183
|
+
};
|
|
84184
|
+
const unsubscribe = session.subscribe((event) => {
|
|
84185
|
+
this.handleEvent(event, progress, agentId, runId);
|
|
84186
|
+
});
|
|
84187
|
+
this.sessions.set(agentId, { unsubscribe, progress });
|
|
84188
|
+
return progress;
|
|
84189
|
+
}
|
|
84190
|
+
handleEvent(event, progress, agentId, runId) {
|
|
84191
|
+
switch (event.type) {
|
|
84192
|
+
case "tool_execution_start":
|
|
84193
|
+
progress.toolCalls++;
|
|
84194
|
+
progress.currentTool = event.toolName;
|
|
84195
|
+
progress.toolStartTime = Date.now();
|
|
84196
|
+
crewEventBus.emit({
|
|
84197
|
+
type: "agent:progress",
|
|
84198
|
+
runId,
|
|
84199
|
+
agentId,
|
|
84200
|
+
payload: { ...progress },
|
|
84201
|
+
timestamp: Date.now()
|
|
84202
|
+
});
|
|
84203
|
+
break;
|
|
84204
|
+
case "tool_execution_end":
|
|
84205
|
+
progress.currentTool = null;
|
|
84206
|
+
progress.toolStartTime = null;
|
|
84207
|
+
if (event.isError) {
|
|
84208
|
+
progress.errors.push(String(event.result ?? "Unknown error"));
|
|
84209
|
+
crewEventBus.emit({
|
|
84210
|
+
type: "agent:error",
|
|
84211
|
+
runId,
|
|
84212
|
+
agentId,
|
|
84213
|
+
payload: String(event.result ?? "Unknown error"),
|
|
84214
|
+
timestamp: Date.now()
|
|
84215
|
+
});
|
|
84216
|
+
}
|
|
84217
|
+
crewEventBus.emit({
|
|
84218
|
+
type: "agent:progress",
|
|
84219
|
+
runId,
|
|
84220
|
+
agentId,
|
|
84221
|
+
payload: { ...progress },
|
|
84222
|
+
timestamp: Date.now()
|
|
84223
|
+
});
|
|
84224
|
+
break;
|
|
84225
|
+
case "turn_start":
|
|
84226
|
+
progress.turns++;
|
|
84227
|
+
break;
|
|
84228
|
+
case "agent_end":
|
|
84229
|
+
progress.status = "completed";
|
|
84230
|
+
crewEventBus.emit({
|
|
84231
|
+
type: "agent:complete",
|
|
84232
|
+
runId,
|
|
84233
|
+
agentId,
|
|
84234
|
+
payload: { ...progress },
|
|
84235
|
+
timestamp: Date.now()
|
|
84236
|
+
});
|
|
84237
|
+
break;
|
|
84238
|
+
case "agent_start":
|
|
84239
|
+
progress.status = "running";
|
|
84240
|
+
break;
|
|
84241
|
+
}
|
|
84242
|
+
}
|
|
84243
|
+
untrack(agentId) {
|
|
84244
|
+
const tracked = this.sessions.get(agentId);
|
|
84245
|
+
if (tracked) {
|
|
84246
|
+
tracked.unsubscribe();
|
|
84247
|
+
this.sessions.delete(agentId);
|
|
84248
|
+
}
|
|
84249
|
+
}
|
|
84250
|
+
getProgress(agentId) {
|
|
84251
|
+
return this.sessions.get(agentId)?.progress;
|
|
84252
|
+
}
|
|
84253
|
+
// ── Child-process worker event bridge ──────────────────────────────────
|
|
84254
|
+
//
|
|
84255
|
+
// For child-process runtime, events arrive as raw JSON from the child pi
|
|
84256
|
+
// process's stdout (via onJsonEvent). These methods bridge those events into
|
|
84257
|
+
// the same crewEventBus stream that live-session uses, so the widget shows
|
|
84258
|
+
// real-time tool calls and assistant text for BOTH runtimes.
|
|
84259
|
+
workerProgress = /* @__PURE__ */ new Map();
|
|
84260
|
+
/** Throttle: don't emit more than 1 progress event per 500ms per worker. */
|
|
84261
|
+
lastEmitTs = /* @__PURE__ */ new Map();
|
|
84262
|
+
static EMIT_THROTTLE_MS = 500;
|
|
84263
|
+
/**
|
|
84264
|
+
* Handle a raw child-process JSON event (from onJsonEvent callback).
|
|
84265
|
+
* Processes tool_execution_start/end, agent_start/end, and assistant text.
|
|
84266
|
+
*/
|
|
84267
|
+
handleWorkerEvent(taskId, runId, event) {
|
|
84268
|
+
let progress = this.workerProgress.get(taskId);
|
|
84269
|
+
if (!progress) {
|
|
84270
|
+
progress = {
|
|
84271
|
+
toolCalls: 0,
|
|
84272
|
+
currentTool: null,
|
|
84273
|
+
toolStartTime: null,
|
|
84274
|
+
errors: [],
|
|
84275
|
+
turns: 0,
|
|
84276
|
+
tokens: { input: 0, output: 0 },
|
|
84277
|
+
status: "running"
|
|
84278
|
+
};
|
|
84279
|
+
this.workerProgress.set(taskId, progress);
|
|
84280
|
+
}
|
|
84281
|
+
const eventType = typeof event.type === "string" ? event.type : void 0;
|
|
84282
|
+
switch (eventType) {
|
|
84283
|
+
case "tool_execution_start": {
|
|
84284
|
+
progress.toolCalls++;
|
|
84285
|
+
progress.currentTool = typeof event.toolName === "string" ? event.toolName : "unknown";
|
|
84286
|
+
progress.toolStartTime = Date.now();
|
|
84287
|
+
this.emitThrottled(taskId, runId, progress);
|
|
84288
|
+
break;
|
|
84289
|
+
}
|
|
84290
|
+
case "tool_execution_end": {
|
|
84291
|
+
progress.currentTool = null;
|
|
84292
|
+
progress.toolStartTime = null;
|
|
84293
|
+
if (event.isError) {
|
|
84294
|
+
progress.errors.push(String(event.result ?? "Unknown error"));
|
|
84295
|
+
crewEventBus.emit({
|
|
84296
|
+
type: "agent:error",
|
|
84297
|
+
runId,
|
|
84298
|
+
agentId: taskId,
|
|
84299
|
+
payload: String(event.result ?? "Unknown error"),
|
|
84300
|
+
timestamp: Date.now()
|
|
84301
|
+
});
|
|
84302
|
+
}
|
|
84303
|
+
this.emitThrottled(taskId, runId, progress);
|
|
84304
|
+
break;
|
|
84305
|
+
}
|
|
84306
|
+
case "turn_start":
|
|
84307
|
+
case "turn_end":
|
|
84308
|
+
progress.turns++;
|
|
84309
|
+
break;
|
|
84310
|
+
case "agent_start":
|
|
84311
|
+
progress.status = "running";
|
|
84312
|
+
break;
|
|
84313
|
+
case "agent_end":
|
|
84314
|
+
case "agent_settled":
|
|
84315
|
+
progress.status = "completed";
|
|
84316
|
+
this.emitThrottled(taskId, runId, progress);
|
|
84317
|
+
break;
|
|
84318
|
+
case "message":
|
|
84319
|
+
case "message_end": {
|
|
84320
|
+
const message = event.message;
|
|
84321
|
+
if (message?.role === "assistant") {
|
|
84322
|
+
const text = extractWorkerText(message.content);
|
|
84323
|
+
if (text) {
|
|
84324
|
+
progress.partialText = text.slice(-2e3);
|
|
84325
|
+
this.emitThrottled(taskId, runId, progress);
|
|
84326
|
+
}
|
|
84327
|
+
}
|
|
84328
|
+
if (eventType === "message_end" && event.usage && typeof event.usage === "object") {
|
|
84329
|
+
const usage = event.usage;
|
|
84330
|
+
if (typeof usage.input === "number") progress.tokens.input += usage.input;
|
|
84331
|
+
if (typeof usage.output === "number") progress.tokens.output += usage.output;
|
|
84332
|
+
}
|
|
84333
|
+
break;
|
|
84334
|
+
}
|
|
84335
|
+
}
|
|
84336
|
+
}
|
|
84337
|
+
/** Get the accumulated progress for a child-process worker task. */
|
|
84338
|
+
getWorkerProgress(taskId) {
|
|
84339
|
+
return this.workerProgress.get(taskId);
|
|
84340
|
+
}
|
|
84341
|
+
/** Remove a worker from tracking after completion. */
|
|
84342
|
+
untrackWorker(taskId) {
|
|
84343
|
+
this.workerProgress.delete(taskId);
|
|
84344
|
+
this.lastEmitTs.delete(taskId);
|
|
84345
|
+
}
|
|
84346
|
+
/**
|
|
84347
|
+
* Emit a progress event to crewEventBus, throttled to avoid flooding
|
|
84348
|
+
* the widget with re-renders (max 1 event per EMIT_THROTTLE_MS per worker).
|
|
84349
|
+
*/
|
|
84350
|
+
emitThrottled(taskId, runId, progress) {
|
|
84351
|
+
const now = Date.now();
|
|
84352
|
+
const last = this.lastEmitTs.get(taskId) ?? 0;
|
|
84353
|
+
if (now - last < _ProgressTracker.EMIT_THROTTLE_MS) return;
|
|
84354
|
+
this.lastEmitTs.set(taskId, now);
|
|
84355
|
+
crewEventBus.emit({
|
|
84356
|
+
type: "agent:progress",
|
|
84357
|
+
runId,
|
|
84358
|
+
agentId: taskId,
|
|
84359
|
+
payload: { ...progress },
|
|
84360
|
+
timestamp: now
|
|
84361
|
+
});
|
|
84362
|
+
}
|
|
84363
|
+
};
|
|
84364
|
+
var globalProgressTracker = new ProgressTracker();
|
|
84365
|
+
function extractWorkerText(content) {
|
|
84366
|
+
if (typeof content === "string") return content;
|
|
84367
|
+
if (!Array.isArray(content)) return "";
|
|
84368
|
+
return content.map(
|
|
84369
|
+
(part) => part && typeof part === "object" && !Array.isArray(part) && typeof part.text === "string" ? part.text : ""
|
|
84370
|
+
).filter(Boolean).join("\n");
|
|
84371
|
+
}
|
|
84372
|
+
|
|
84373
|
+
// src/extension/registration/subagent-tools.ts
|
|
84094
84374
|
init_role_permission();
|
|
84095
84375
|
init_state_store();
|
|
84096
84376
|
init_manager();
|
|
@@ -84458,7 +84738,20 @@ function startAgentToolProgress(cwd, agentRecordId, onUpdate, manager) {
|
|
|
84458
84738
|
agents,
|
|
84459
84739
|
error: record.error
|
|
84460
84740
|
});
|
|
84461
|
-
|
|
84741
|
+
let progressLine = text;
|
|
84742
|
+
if (tasks && tasks.length > 0) {
|
|
84743
|
+
const wp = globalProgressTracker.getWorkerProgress(tasks[0].id);
|
|
84744
|
+
if (wp) {
|
|
84745
|
+
const toolLine = wp.currentTool ? `
|
|
84746
|
+
\u26A1 tool: ${wp.currentTool}` : "";
|
|
84747
|
+
const tokenLine = wp.tokens.input + wp.tokens.output > 0 ? `
|
|
84748
|
+
\u{1F4CA} tokens: ${(wp.tokens.input / 1e3).toFixed(1)}K in, ${(wp.tokens.output / 1e3).toFixed(1)}K out` : "";
|
|
84749
|
+
const textLine = wp.partialText ? `
|
|
84750
|
+
\u{1F4AC} ${wp.partialText.slice(-150).replace(/\n/g, " ")}` : "";
|
|
84751
|
+
progressLine = `${text}${toolLine}${tokenLine}${textLine}`;
|
|
84752
|
+
}
|
|
84753
|
+
}
|
|
84754
|
+
onUpdate({ content: [{ type: "text", text: progressLine }] });
|
|
84462
84755
|
} catch (error) {
|
|
84463
84756
|
logInternalError("subagent-tools.progress", error, `agentId=${agentRecordId}`);
|
|
84464
84757
|
}
|
|
@@ -85590,6 +85883,9 @@ Subagent may need manual intervention.`
|
|
|
85590
85883
|
const record = event;
|
|
85591
85884
|
const eventType = typeof record.type === "string" ? record.type : void 0;
|
|
85592
85885
|
if (eventType) lifecycleState.overflowTracker?.feedEvent(taskId, runId, eventType);
|
|
85886
|
+
if (record && typeof record === "object") {
|
|
85887
|
+
globalProgressTracker.handleWorkerEvent(taskId, runId, record);
|
|
85888
|
+
}
|
|
85593
85889
|
}
|
|
85594
85890
|
});
|
|
85595
85891
|
registerSubagentTools(pi, subagentManager, {
|