@pi-unipi/unipi 3.0.0-alpha.2 → 3.0.0-alpha.21
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 +292 -0
- package/README.md +8 -11
- package/docs/prefix-cache-architecture.md +14 -0
- package/package.json +22 -24
- package/packages/ask-user/README.md +55 -107
- package/packages/ask-user/ask-ui.ts +306 -732
- package/packages/ask-user/clipboard.ts +50 -0
- package/packages/ask-user/config.ts +74 -78
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/questions.ts +151 -0
- package/packages/ask-user/skills/ask-user/SKILL.md +59 -133
- package/packages/ask-user/tools.ts +198 -432
- package/packages/autocomplete/package.json +1 -1
- package/packages/autocomplete/src/constants.ts +38 -43
- package/packages/autocomplete/src/sorting.ts +8 -0
- package/packages/background-tasks/package.json +2 -2
- package/packages/background-tasks/src/config.ts +0 -73
- package/packages/background-tasks/src/index.ts +20 -16
- package/packages/background-tasks/src/registry.ts +1 -171
- package/packages/background-tasks/src/types.ts +0 -32
- package/packages/btw/README.md +13 -56
- package/packages/btw/extensions/btw.ts +403 -1796
- package/packages/btw/package.json +5 -2
- package/packages/btw/skills/btw/SKILL.md +7 -143
- package/packages/compactor/README.md +56 -287
- package/packages/compactor/package.json +5 -9
- package/packages/compactor/skills/compactor/SKILL.md +13 -20
- package/packages/compactor/src/card.ts +90 -0
- package/packages/compactor/src/commands/index.ts +73 -130
- package/packages/compactor/src/compaction/compact-args.ts +5 -3
- package/packages/compactor/src/compaction/filter-noise.ts +1 -1
- package/packages/compactor/src/compaction/hooks.ts +487 -311
- package/packages/compactor/src/compaction/source.ts +178 -0
- package/packages/compactor/src/compaction/summarize.ts +586 -52
- package/packages/compactor/src/config/manager.ts +130 -127
- package/packages/compactor/src/config/schema.ts +32 -48
- package/packages/compactor/src/index.ts +40 -431
- package/packages/compactor/src/info-screen.ts +44 -190
- package/packages/compactor/src/session/recall-blocks.ts +1 -1
- package/packages/compactor/src/stats.ts +76 -0
- package/packages/compactor/src/tools/context-budget.ts +17 -34
- package/packages/compactor/src/tools/ctx-doctor.ts +45 -36
- package/packages/compactor/src/tools/register.ts +29 -269
- package/packages/compactor/src/types.ts +47 -186
- package/packages/core/README.md +25 -0
- package/packages/core/child-agent.ts +1 -0
- package/packages/core/command-echo.ts +63 -0
- package/packages/core/compaction-context.ts +41 -0
- package/packages/core/constants.ts +8 -38
- package/packages/core/events.ts +0 -53
- package/packages/core/fusion-status.ts +4 -0
- package/packages/core/global.d.ts +10 -0
- package/packages/core/harness-messages.ts +392 -0
- package/packages/core/index.ts +14 -0
- package/packages/core/kanboard-status.ts +49 -0
- package/packages/core/long-horizon-owner-status.ts +46 -0
- package/packages/core/model-cache.ts +81 -7
- package/packages/core/package.json +6 -3
- package/packages/core/src/attach/detect.ts +163 -0
- package/packages/core/src/child-agent/child-args.ts +31 -0
- package/packages/core/src/child-agent/delivery.ts +41 -0
- package/packages/core/src/child-agent/index.ts +5 -0
- package/packages/core/src/child-agent/readers.ts +203 -0
- package/packages/core/src/child-agent/runtime.ts +584 -0
- package/packages/core/src/evidence.ts +78 -0
- package/packages/core/src/hints/browser.ts +278 -0
- package/packages/core/src/hints/crab-data.ts +19 -0
- package/packages/core/src/hints/index.ts +865 -0
- package/packages/core/src/hints/lines.ts +607 -0
- package/packages/core/src/hints/store.ts +120 -0
- package/packages/core/src/jev/chatter.ts +24 -0
- package/packages/core/src/jev/settings.ts +177 -14
- package/packages/core/src/package-colors.ts +2 -0
- package/packages/core/src/settings/catalog.ts +39 -15
- package/packages/core/src/settings/engine.ts +48 -2
- package/packages/core/src/settings/hub.ts +83 -20
- package/packages/core/src/settings/open.ts +49 -0
- package/packages/core/src/settings/schema.ts +27 -7
- package/packages/core/src/tui/hub-kit.ts +18 -5
- package/packages/core/src/tui/kit.ts +198 -0
- package/packages/core/src/tui/progress.ts +73 -0
- package/packages/core/src/turn/arbiter.ts +290 -0
- package/packages/footer/README.md +4 -6
- package/packages/footer/package.json +3 -3
- package/packages/footer/src/glance-editor.ts +19 -11
- package/packages/footer/src/help.ts +1 -1
- package/packages/footer/src/index.ts +36 -3
- package/packages/footer/src/presets.ts +3 -4
- package/packages/footer/src/rendering/icons.ts +0 -20
- package/packages/footer/src/segments/compactor.ts +52 -142
- package/packages/footer/src/segments/status-ext.ts +0 -1
- package/packages/fusion/README.md +14 -4
- package/packages/fusion/package.json +4 -3
- package/packages/fusion/src/child-args.ts +1 -0
- package/packages/fusion/src/index.ts +161 -8
- package/packages/fusion/src/pi-settings.ts +57 -0
- package/packages/fusion/src/picker.ts +186 -51
- package/packages/fusion/src/preset.ts +56 -2
- package/packages/fusion/src/prompts.ts +1 -1
- package/packages/fusion/src/sidekick-runtime.ts +1 -420
- package/packages/fusion/src/tools.ts +107 -128
- package/packages/fusion/src/transcript.ts +27 -85
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/README.md +18 -30
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/input-shortcuts/src/burst.ts +88 -0
- package/packages/input-shortcuts/src/chord-overlay.ts +20 -70
- package/packages/input-shortcuts/src/cleared-input.ts +97 -0
- package/packages/input-shortcuts/src/index.ts +99 -193
- package/packages/input-shortcuts/src/last-response.ts +40 -0
- package/packages/input-shortcuts/src/registers.ts +8 -23
- package/packages/input-shortcuts/src/types.ts +4 -16
- package/packages/input-shortcuts/src/undo-redo.ts +59 -47
- package/packages/kanboard/README.md +51 -47
- package/packages/kanboard/index.ts +293 -55
- package/packages/kanboard/package.json +8 -8
- package/packages/kanboard/skills/kanboard/SKILL.md +61 -27
- package/packages/kanboard/src/badges.ts +93 -0
- package/packages/kanboard/src/bin.ts +4 -2
- package/packages/kanboard/src/commands.ts +218 -84
- package/packages/kanboard/src/debug.ts +20 -0
- package/packages/kanboard/src/guard.ts +267 -109
- package/packages/kanboard/src/monitor.ts +330 -0
- package/packages/kanboard/src/notice-buffer.ts +74 -0
- package/packages/kanboard/src/progress.ts +27 -0
- package/packages/kanboard/src/reminders.ts +234 -0
- package/packages/kanboard/src/settings.ts +69 -15
- package/packages/kanboard/src/shapes.ts +5 -0
- package/packages/long-horizon/index.ts +190 -13
- package/packages/long-horizon/package.json +3 -3
- package/packages/long-horizon/src/commands.ts +103 -7
- package/packages/long-horizon/src/compaction-brief.ts +35 -0
- package/packages/long-horizon/src/engine/continuation.ts +84 -15
- package/packages/long-horizon/src/engine/goal-state.ts +64 -13
- package/packages/long-horizon/src/engine/nudge-stash.ts +71 -0
- package/packages/long-horizon/src/engine/ralph.ts +3 -2
- package/packages/long-horizon/src/engine/runaway.ts +68 -11
- package/packages/long-horizon/src/engine/verifier.ts +19 -0
- package/packages/long-horizon/src/gate.ts +37 -12
- package/packages/long-horizon/src/judge/resolve.ts +1 -0
- package/packages/long-horizon/src/owner.ts +35 -2
- package/packages/long-horizon/src/progress.ts +87 -0
- package/packages/long-horizon/src/prompts/goal.ts +1 -1
- package/packages/long-horizon/src/runtime.ts +172 -18
- package/packages/long-horizon/src/settings.ts +54 -39
- package/packages/long-horizon/src/tools/goal.ts +6 -0
- package/packages/long-horizon/src/tools/graph.ts +1 -1
- package/packages/long-horizon/src/tools/swarm.ts +3 -3
- package/packages/mcp/package.json +2 -2
- package/packages/memory/commands.ts +7 -2
- package/packages/memory/index.ts +210 -32
- package/packages/memory/package.json +3 -3
- package/packages/memory/save-session.ts +264 -0
- package/packages/memory/settings.ts +17 -0
- package/packages/memory/tools.ts +253 -203
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/README.md +53 -16
- package/packages/skill-registry/index.ts +230 -0
- package/packages/skill-registry/package.json +19 -8
- package/packages/skill-registry/src/editor.ts +206 -0
- package/packages/skill-registry/src/judge.ts +289 -0
- package/packages/skill-registry/src/registry.ts +87 -0
- package/packages/skill-registry/src/settings.ts +259 -0
- package/packages/skill-registry/src/vault.ts +80 -0
- package/packages/subagents/README.md +39 -119
- package/packages/subagents/package.json +6 -13
- package/packages/subagents/skills/subagents/SKILL.md +18 -42
- package/packages/subagents/src/agents.ts +213 -0
- package/packages/subagents/src/cards.ts +182 -0
- package/packages/subagents/src/index.ts +609 -1084
- package/packages/subagents/src/manager.ts +429 -0
- package/packages/subagents/src/profiles.ts +130 -0
- package/packages/subagents/src/transcript.ts +154 -0
- package/packages/subagents/src/ui.ts +389 -0
- package/packages/unipi/bundled.js +39756 -45569
- package/packages/unipi/index.ts +55 -10
- package/packages/updater/package.json +2 -2
- package/packages/utility/README.md +76 -69
- package/packages/utility/package.json +2 -2
- package/packages/utility/skills/image/SKILL.md +37 -0
- package/packages/utility/skills/utility/SKILL.md +17 -60
- package/packages/utility/src/answer/extract.ts +128 -0
- package/packages/utility/src/answer/index.ts +213 -0
- package/packages/utility/src/answer/reply.ts +133 -0
- package/packages/utility/src/answer/web.ts +167 -0
- package/packages/utility/src/attach/index.ts +205 -0
- package/packages/utility/src/commands.ts +38 -142
- package/packages/utility/src/diagnostics/engine.ts +50 -5
- package/packages/utility/src/image/index.ts +33 -0
- package/packages/utility/src/image/models.ts +221 -0
- package/packages/{image/src → utility/src/image}/recognize.ts +2 -2
- package/packages/utility/src/image/settings.ts +178 -0
- package/packages/{image/src/image-source.ts → utility/src/image/source.ts} +1 -1
- package/packages/utility/src/image/tools.ts +168 -0
- package/packages/utility/src/image/transports.ts +186 -0
- package/packages/utility/src/index.ts +68 -389
- package/packages/utility/src/lifecycle/cleanup.ts +116 -311
- package/packages/utility/src/rename/gate.ts +102 -0
- package/packages/utility/src/rename/index.ts +191 -0
- package/packages/utility/src/rename/session.ts +170 -0
- package/packages/utility/src/render/delegated.ts +285 -0
- package/packages/utility/src/render/harness.ts +683 -0
- package/packages/utility/src/render/parse.ts +156 -0
- package/packages/utility/src/render/pi-settings.ts +38 -0
- package/packages/utility/src/render/reply-bg.ts +307 -0
- package/packages/utility/src/render/simple.ts +724 -0
- package/packages/utility/src/render/spacing.ts +235 -0
- package/packages/utility/src/render/styled.ts +251 -0
- package/packages/utility/src/render/tools.ts +353 -0
- package/packages/utility/src/settings.ts +166 -233
- package/packages/utility/src/types.ts +1 -222
- package/packages/watchdog/index.ts +17 -6
- package/packages/watchdog/package.json +3 -3
- package/packages/watchdog/src/config.ts +3 -2
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/README.md +3 -0
- package/packages/workflow/index.ts +0 -2
- package/packages/workflow/package.json +2 -2
- package/packages/workflow/src/permission/decide.ts +6 -4
- package/packages/workflow/src/permission/index.ts +17 -7
- package/packages/workflow/src/permission/settings.ts +39 -4
- package/packages/workflow/src/plan/index.ts +19 -4
- package/packages/background-tasks/extensions/delegate-child.ts +0 -1
- package/packages/background-tasks/src/context-parent-snapshot.ts +0 -142
- package/packages/background-tasks/src/context-token-budget.ts +0 -903
- package/packages/background-tasks/src/context-visible-conversation-v2.ts +0 -551
- package/packages/background-tasks/src/delegate/artifacts.ts +0 -487
- package/packages/background-tasks/src/delegate/budget.ts +0 -415
- package/packages/background-tasks/src/delegate/hook-contract-evidence.json +0 -18
- package/packages/background-tasks/src/delegate/hook-contract.ts +0 -154
- package/packages/background-tasks/src/delegate/launch.ts +0 -484
- package/packages/background-tasks/src/delegate/result-package.ts +0 -459
- package/packages/background-tasks/src/delegate/runner.ts +0 -430
- package/packages/background-tasks/src/delegate/seed.ts +0 -423
- package/packages/background-tasks/src/delegate/types.ts +0 -323
- package/packages/background-tasks/src/delegate-child-extension.ts +0 -978
- package/packages/background-tasks/src/delegate-extension.ts +0 -654
- package/packages/background-tasks/src/fixtures/delegate-context-incident.json +0 -17
- package/packages/compactor/skills/compactor-detail/SKILL.md +0 -116
- package/packages/compactor/skills/compactor-doctor/SKILL.md +0 -71
- package/packages/compactor/skills/compactor-stats/SKILL.md +0 -51
- package/packages/compactor/src/compaction/build-sections.ts +0 -76
- package/packages/compactor/src/compaction/extract/goals.ts +0 -36
- package/packages/compactor/src/compaction/extract/preferences.ts +0 -40
- package/packages/compactor/src/compaction/format.ts +0 -53
- package/packages/compactor/src/compaction/merge.ts +0 -143
- package/packages/compactor/src/config/presets.ts +0 -160
- package/packages/compactor/src/executor/executor.ts +0 -233
- package/packages/compactor/src/executor/runtime.ts +0 -115
- package/packages/compactor/src/security/evaluator.ts +0 -89
- package/packages/compactor/src/security/policy.ts +0 -96
- package/packages/compactor/src/security/scanner.ts +0 -65
- package/packages/compactor/src/session/auto-inject.ts +0 -60
- package/packages/compactor/src/session/db.ts +0 -325
- package/packages/compactor/src/session/extract.ts +0 -144
- package/packages/compactor/src/session/resume-inject.ts +0 -64
- package/packages/compactor/src/session/snapshot.ts +0 -327
- package/packages/compactor/src/tools/ctx-batch-execute.ts +0 -41
- package/packages/compactor/src/tools/ctx-execute-file.ts +0 -23
- package/packages/compactor/src/tools/ctx-execute.ts +0 -23
- package/packages/compactor/src/tools/ctx-stats.ts +0 -96
- package/packages/image/README.md +0 -99
- package/packages/image/package.json +0 -61
- package/packages/image/skills/image/SKILL.md +0 -76
- package/packages/image/src/generate.ts +0 -256
- package/packages/image/src/index.ts +0 -135
- package/packages/image/src/models.ts +0 -519
- package/packages/image/src/openai-images-api.ts +0 -282
- package/packages/image/src/register-providers.ts +0 -209
- package/packages/image/src/settings.ts +0 -173
- package/packages/image/src/tools.ts +0 -326
- package/packages/input-shortcuts/src/clipboard.ts +0 -119
- package/packages/kanboard/src/runner.ts +0 -817
- package/packages/skill-registry/skills/auto/SKILL.md +0 -465
- package/packages/skill-registry/skills/brainstorm/SKILL.md +0 -219
- package/packages/skill-registry/skills/chore-create/SKILL.md +0 -315
- package/packages/skill-registry/skills/chore-execute/SKILL.md +0 -314
- package/packages/skill-registry/skills/consolidate/SKILL.md +0 -142
- package/packages/skill-registry/skills/consultant/SKILL.md +0 -97
- package/packages/skill-registry/skills/debug/SKILL.md +0 -228
- package/packages/skill-registry/skills/document/SKILL.md +0 -120
- package/packages/skill-registry/skills/fix/SKILL.md +0 -212
- package/packages/skill-registry/skills/gather-context/SKILL.md +0 -145
- package/packages/skill-registry/skills/plan/SKILL.md +0 -231
- package/packages/skill-registry/skills/quick-fix/SKILL.md +0 -135
- package/packages/skill-registry/skills/quick-work/SKILL.md +0 -110
- package/packages/skill-registry/skills/research/SKILL.md +0 -251
- package/packages/skill-registry/skills/review-work/SKILL.md +0 -187
- package/packages/skill-registry/skills/scan-issues/SKILL.md +0 -195
- package/packages/skill-registry/skills/work/SKILL.md +0 -218
- package/packages/skill-registry/skills/worktree-create/SKILL.md +0 -69
- package/packages/skill-registry/skills/worktree-list/SKILL.md +0 -78
- package/packages/skill-registry/skills/worktree-merge/SKILL.md +0 -89
- package/packages/subagents/agents/delegate.md +0 -14
- package/packages/subagents/agents/oracle.md +0 -78
- package/packages/subagents/agents/researcher.md +0 -52
- package/packages/subagents/agents/reviewer.md +0 -80
- package/packages/subagents/agents/scout.md +0 -50
- package/packages/subagents/agents/worker.md +0 -59
- package/packages/subagents/prompts/council.md +0 -48
- package/packages/subagents/prompts/gather-context-and-clarify.md +0 -13
- package/packages/subagents/prompts/parallel-cleanup.md +0 -59
- package/packages/subagents/prompts/parallel-research.md +0 -50
- package/packages/subagents/prompts/parallel-review.md +0 -54
- package/packages/subagents/prompts/review-loop.md +0 -43
- package/packages/subagents/skills/council-mode/SKILL.md +0 -230
- package/packages/subagents/skills/subagents/references/constraints-and-recipes.md +0 -259
- package/packages/subagents/skills/subagents/references/execution-controls.md +0 -454
- package/packages/subagents/skills/subagents/references/management-authoring-rpc.md +0 -161
- package/packages/subagents/skills/subagents/references/multi-lane-orchestration.md +0 -39
- package/packages/subagents/skills/subagents/references/prompting-and-roles.md +0 -267
- package/packages/subagents/src/acceptance.ts +0 -331
- package/packages/subagents/src/agent-manager.ts +0 -405
- package/packages/subagents/src/agent-memory.ts +0 -300
- package/packages/subagents/src/agent-overrides.ts +0 -183
- package/packages/subagents/src/agent-runner.ts +0 -271
- package/packages/subagents/src/async-runner.ts +0 -422
- package/packages/subagents/src/authority-policy.ts +0 -47
- package/packages/subagents/src/budgets.ts +0 -285
- package/packages/subagents/src/child-safety.ts +0 -140
- package/packages/subagents/src/config.ts +0 -249
- package/packages/subagents/src/conversation-viewer.ts +0 -281
- package/packages/subagents/src/core-compat.ts +0 -94
- package/packages/subagents/src/custom-agents.ts +0 -343
- package/packages/subagents/src/file-system-retry.ts +0 -50
- package/packages/subagents/src/fleet-data.ts +0 -105
- package/packages/subagents/src/fleet-view.ts +0 -322
- package/packages/subagents/src/foreground-detach.ts +0 -59
- package/packages/subagents/src/fork-context.ts +0 -285
- package/packages/subagents/src/global.d.ts +0 -7
- package/packages/subagents/src/guide.ts +0 -129
- package/packages/subagents/src/mission-state.ts +0 -133
- package/packages/subagents/src/mission-store.ts +0 -436
- package/packages/subagents/src/output-limits.ts +0 -142
- package/packages/subagents/src/parity-types.ts +0 -315
- package/packages/subagents/src/pi-args.ts +0 -167
- package/packages/subagents/src/result-files.ts +0 -232
- package/packages/subagents/src/result-watcher.ts +0 -221
- package/packages/subagents/src/retained-children.ts +0 -176
- package/packages/subagents/src/run-fanout-budget.ts +0 -356
- package/packages/subagents/src/scheduled-runs.ts +0 -349
- package/packages/subagents/src/schemas.ts +0 -263
- package/packages/subagents/src/slash-commands.ts +0 -80
- package/packages/subagents/src/supervisor-channel.ts +0 -249
- package/packages/subagents/src/tool-handler.ts +0 -1144
- package/packages/subagents/src/types.ts +0 -238
- package/packages/subagents/src/widget.ts +0 -457
- package/packages/subagents/src/workflow-script.ts +0 -737
- package/packages/subagents/src/workflow-worker.ts +0 -384
- package/packages/subagents/src/worktree.ts +0 -614
- package/packages/utility/src/analytics/collector.ts +0 -293
- package/packages/utility/src/info-screen.ts +0 -80
- package/packages/utility/src/lifecycle/process.ts +0 -162
- package/packages/utility/src/prefix-cache.ts +0 -263
- package/packages/utility/src/skill-discovery.ts +0 -542
- package/packages/utility/src/tools/env.ts +0 -113
- package/packages/utility/src/tui/name-badge-state.ts +0 -315
- package/packages/utility/src/tui/name-badge.ts +0 -109
- /package/packages/{subagents/src → core/src/child-agent}/pi-spawn.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.21",
|
|
4
4
|
"description": "Shared utilities, event types, and constants for Unipi extension suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
],
|
|
18
18
|
"files": [
|
|
19
19
|
"*.ts",
|
|
20
|
+
"src/**/*.ts",
|
|
20
21
|
"README.md",
|
|
21
|
-
"!*.test.ts"
|
|
22
|
+
"!*.test.ts",
|
|
23
|
+
"!src/**/__tests__/**",
|
|
24
|
+
"!src/**/*.test.ts"
|
|
22
25
|
],
|
|
23
26
|
"publishConfig": {
|
|
24
27
|
"access": "public"
|
|
@@ -41,6 +44,6 @@
|
|
|
41
44
|
"themes": []
|
|
42
45
|
},
|
|
43
46
|
"scripts": {
|
|
44
|
-
"test": "npx tsx --test *.test.ts"
|
|
47
|
+
"test": "npx tsx --test *.test.ts src/*/__tests__/*.test.ts"
|
|
45
48
|
}
|
|
46
49
|
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pi-unipi/core — attachments: path detection and tokens (pure + fs reads)
|
|
3
|
+
*
|
|
4
|
+
* A pasted / dropped / Ctrl+V'd file path in the editor becomes a token:
|
|
5
|
+
* images → [Image #N] (sent as real image content on submit)
|
|
6
|
+
* documents → [File #N] (expanded back to "[File #N: <path>]" on submit)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { basename, extname } from "node:path";
|
|
12
|
+
|
|
13
|
+
export const IMAGE_MIME: Record<string, string> = {
|
|
14
|
+
".png": "image/png",
|
|
15
|
+
".jpg": "image/jpeg",
|
|
16
|
+
".jpeg": "image/jpeg",
|
|
17
|
+
".gif": "image/gif",
|
|
18
|
+
".webp": "image/webp",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const DOC_EXT = new Set([
|
|
22
|
+
".pdf", ".txt", ".md", ".csv", ".tsv", ".json", ".yaml", ".yml", ".xml", ".html", ".log",
|
|
23
|
+
".docx", ".xlsx", ".pptx", ".odt", ".ods", ".rtf", ".zip", ".svg", ".mp3", ".wav", ".mp4", ".mov",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
export type AttachmentKind = "image" | "file";
|
|
27
|
+
|
|
28
|
+
export interface Attachment {
|
|
29
|
+
id: number;
|
|
30
|
+
kind: AttachmentKind;
|
|
31
|
+
path: string;
|
|
32
|
+
name: string;
|
|
33
|
+
bytes: number;
|
|
34
|
+
mimeType?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function tokenFor(a: Pick<Attachment, "kind" | "id">): string {
|
|
38
|
+
return a.kind === "image" ? `[Image #${a.id}]` : `[File #${a.id}]`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function kindOf(path: string): AttachmentKind | undefined {
|
|
42
|
+
const ext = extname(path).toLowerCase();
|
|
43
|
+
if (IMAGE_MIME[ext]) return "image";
|
|
44
|
+
if (DOC_EXT.has(ext)) return "file";
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Candidate path spans: quoted, file:// URIs, and bare absolute or ~ paths (escaped spaces ok). */
|
|
49
|
+
const CANDIDATE = /'(\/[^'\n]+|~\/[^'\n]+)'|"(\/[^"\n]+|~\/[^"\n]+)"|(file:\/\/\/[^\s'"]+)|((?:~|\/)(?:[^\s'"\\]|\\ )+)/g;
|
|
50
|
+
|
|
51
|
+
function normalize(raw: string): string {
|
|
52
|
+
let p = raw;
|
|
53
|
+
if (p.startsWith("file://")) {
|
|
54
|
+
try {
|
|
55
|
+
p = decodeURIComponent(p.slice("file://".length));
|
|
56
|
+
} catch {
|
|
57
|
+
p = p.slice("file://".length);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
p = p.replace(/\\ /g, " ");
|
|
61
|
+
if (p.startsWith("~/")) p = homedir() + p.slice(1);
|
|
62
|
+
return p;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface Found {
|
|
66
|
+
/** Exact text in the editor to replace. */
|
|
67
|
+
raw: string;
|
|
68
|
+
path: string;
|
|
69
|
+
kind: AttachmentKind;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Existing, attachable files mentioned in `text` (first occurrence each). */
|
|
73
|
+
export function findPaths(text: string, exists: (p: string) => boolean = (p) => existsSync(p) && statSync(p).isFile()): Found[] {
|
|
74
|
+
const out: Found[] = [];
|
|
75
|
+
for (const m of text.matchAll(CANDIDATE)) {
|
|
76
|
+
const raw = m[0];
|
|
77
|
+
const path = normalize(m[1] ?? m[2] ?? m[3] ?? m[4] ?? "");
|
|
78
|
+
const kind = kindOf(path);
|
|
79
|
+
if (!kind || out.some((f) => f.path === path)) continue;
|
|
80
|
+
try {
|
|
81
|
+
if (!exists(path)) continue;
|
|
82
|
+
} catch {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
out.push({ raw, path, kind });
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Replace found paths with tokens; returns the new text and new attachments. */
|
|
91
|
+
export function tokenize(
|
|
92
|
+
text: string,
|
|
93
|
+
existing: readonly Attachment[],
|
|
94
|
+
size: (p: string) => number = (p) => statSync(p).size,
|
|
95
|
+
exists?: (p: string) => boolean,
|
|
96
|
+
): { text: string; added: Attachment[] } {
|
|
97
|
+
let next = text;
|
|
98
|
+
let id = existing.reduce((m, a) => Math.max(m, a.id), 0);
|
|
99
|
+
const added: Attachment[] = [];
|
|
100
|
+
for (const f of findPaths(text, exists)) {
|
|
101
|
+
const reuse = [...existing, ...added].find((a) => a.path === f.path);
|
|
102
|
+
const a: Attachment = reuse ?? {
|
|
103
|
+
id: ++id,
|
|
104
|
+
kind: f.kind,
|
|
105
|
+
path: f.path,
|
|
106
|
+
name: basename(f.path),
|
|
107
|
+
bytes: (() => {
|
|
108
|
+
try {
|
|
109
|
+
return size(f.path);
|
|
110
|
+
} catch {
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
})(),
|
|
114
|
+
...(f.kind === "image" ? { mimeType: IMAGE_MIME[extname(f.path).toLowerCase()] } : {}),
|
|
115
|
+
};
|
|
116
|
+
if (!reuse) added.push(a);
|
|
117
|
+
next = next.split(f.raw).join(tokenFor(a));
|
|
118
|
+
}
|
|
119
|
+
return { text: next, added };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Attachments whose token is still in the text. */
|
|
123
|
+
export function stillReferenced(text: string, attachments: readonly Attachment[]): Attachment[] {
|
|
124
|
+
return attachments.filter((a) => text.includes(tokenFor(a)));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface ImagePart {
|
|
128
|
+
type: "image";
|
|
129
|
+
data: string;
|
|
130
|
+
mimeType: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Submit-time expansion: images become image content (in token order), file
|
|
135
|
+
* tokens become "[File #N: <path>]" so the model can read them.
|
|
136
|
+
*/
|
|
137
|
+
export function expandForSubmit(
|
|
138
|
+
text: string,
|
|
139
|
+
attachments: readonly Attachment[],
|
|
140
|
+
read: (p: string) => Buffer = (p) => readFileSync(p),
|
|
141
|
+
): { text: string; images: ImagePart[] } {
|
|
142
|
+
const used = stillReferenced(text, attachments).sort((a, b) => text.indexOf(tokenFor(a)) - text.indexOf(tokenFor(b)));
|
|
143
|
+
const images: ImagePart[] = [];
|
|
144
|
+
let out = text;
|
|
145
|
+
for (const a of used) {
|
|
146
|
+
if (a.kind === "file") {
|
|
147
|
+
out = out.split(tokenFor(a)).join(`[File #${a.id}: ${a.path}]`);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
images.push({ type: "image", data: read(a.path).toString("base64"), mimeType: a.mimeType ?? "image/png" });
|
|
152
|
+
} catch {
|
|
153
|
+
out = out.split(tokenFor(a)).join(`[Image #${a.id}: ${a.path} (unreadable)]`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { text: out, images };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function formatBytes(bytes: number): string {
|
|
160
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
161
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
162
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
163
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension-selection flags the sidekick child must inherit from the lead's
|
|
3
|
+
* argv — otherwise `pi --no-extensions -e <repo>` still lets the child pick
|
|
4
|
+
* up the globally installed suite. Pure: reads a plain argv array.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export function leadExtensionArgs(argv: readonly string[]): string[] {
|
|
8
|
+
const out: string[] = [];
|
|
9
|
+
for (let i = 0; i < argv.length; i++) {
|
|
10
|
+
const arg = argv[i];
|
|
11
|
+
if (arg === "--extension" || arg === "-e") {
|
|
12
|
+
const value = argv[i + 1];
|
|
13
|
+
if (value !== undefined) {
|
|
14
|
+
out.push("--extension", value);
|
|
15
|
+
i++;
|
|
16
|
+
}
|
|
17
|
+
} else if (arg === "--no-extensions" || arg === "-ne") {
|
|
18
|
+
out.push("--no-extensions");
|
|
19
|
+
} else if (arg === "--skill") {
|
|
20
|
+
const value = argv[i + 1];
|
|
21
|
+
if (value !== undefined) {
|
|
22
|
+
out.push("--skill", value);
|
|
23
|
+
i++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// --no-skills is unconditional below: the child never needs skill
|
|
27
|
+
// discovery; the parent's --no-skills is preserved anyway.
|
|
28
|
+
}
|
|
29
|
+
out.push("--no-skills");
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exactly-once completion delivery for handoffs nobody is waiting on.
|
|
3
|
+
*
|
|
4
|
+
* `attach`/`detach` bracket every waiting period. The completion is sent only
|
|
5
|
+
* if the report lands (or has already landed) while no waiter is attached, and
|
|
6
|
+
* only once per handoff id.
|
|
7
|
+
*/
|
|
8
|
+
export function createCompletionDelivery<TReport>(
|
|
9
|
+
send: (report: TReport) => void,
|
|
10
|
+
): {
|
|
11
|
+
attach(id: string): void;
|
|
12
|
+
detach(id: string, done: Promise<TReport>): void;
|
|
13
|
+
consume(id: string): void;
|
|
14
|
+
} {
|
|
15
|
+
const waiting = new Set<string>();
|
|
16
|
+
const armed = new Set<string>();
|
|
17
|
+
const delivered = new Set<string>();
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
attach(id) {
|
|
21
|
+
waiting.add(id);
|
|
22
|
+
},
|
|
23
|
+
detach(id, done) {
|
|
24
|
+
waiting.delete(id);
|
|
25
|
+
// One continuation per handoff, however many times a waiter gives up.
|
|
26
|
+
if (armed.has(id)) return;
|
|
27
|
+
armed.add(id);
|
|
28
|
+
void done
|
|
29
|
+
.then((report) => {
|
|
30
|
+
if (waiting.has(id) || delivered.has(id)) return;
|
|
31
|
+
delivered.add(id);
|
|
32
|
+
send(report);
|
|
33
|
+
})
|
|
34
|
+
.catch(() => undefined);
|
|
35
|
+
},
|
|
36
|
+
consume(id) {
|
|
37
|
+
waiting.delete(id);
|
|
38
|
+
delivered.add(id);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared `read_subagent` registry: owners (fusion sidekick, subagents) register
|
|
3
|
+
* readers keyed by agent_id ownership. The tool itself is registered once by
|
|
4
|
+
* whichever package loads first, and dispatches to the owning reader.
|
|
5
|
+
*
|
|
6
|
+
* Demand: `setReadSubagentDemand(pi, owner, wanted)` — `read_subagent` stays in
|
|
7
|
+
* pi's active tool set iff at least one owner wants it; other tools untouched.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
11
|
+
|
|
12
|
+
export interface SubagentReadParams {
|
|
13
|
+
agent_id?: string;
|
|
14
|
+
block?: boolean;
|
|
15
|
+
timeout?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SubagentReader {
|
|
19
|
+
/** True when `agent_id` belongs to this owner (undefined = can't tell). */
|
|
20
|
+
owns(id: string, ctx?: ExtensionContext): boolean;
|
|
21
|
+
/** The owner's newest handoff/subagent (id + start time) or undefined. */
|
|
22
|
+
latest(ctx?: ExtensionContext): { id: string; startedAt: number } | undefined;
|
|
23
|
+
read(params: SubagentReadParams, signal: AbortSignal | undefined, onUpdate: ((u: unknown) => void) | undefined, ctx: ExtensionContext): Promise<unknown>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RegisteredReader extends SubagentReader {
|
|
27
|
+
owner: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const readers: RegisteredReader[] = [];
|
|
31
|
+
const demand = new Map<string, boolean>();
|
|
32
|
+
|
|
33
|
+
export function registerSubagentReader(owner: string, reader: SubagentReader): RegisteredReader {
|
|
34
|
+
const entry: RegisteredReader = { owner, ...reader };
|
|
35
|
+
const existing = readers.findIndex((r) => r.owner === owner);
|
|
36
|
+
if (existing >= 0) readers[existing] = entry;
|
|
37
|
+
else readers.push(entry);
|
|
38
|
+
return entry;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function subagentReaders(): readonly RegisteredReader[] {
|
|
42
|
+
return readers;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function readerFor(id: string | undefined, ctx?: ExtensionContext): RegisteredReader | undefined {
|
|
46
|
+
if (id !== undefined) return readers.find((r) => r.owns(id, ctx)) ?? readers.find((r) => r.latest(ctx)?.id === id);
|
|
47
|
+
let best: RegisteredReader | undefined;
|
|
48
|
+
let bestAt = -1;
|
|
49
|
+
for (const r of readers) {
|
|
50
|
+
const at = r.latest(ctx)?.startedAt ?? -1;
|
|
51
|
+
if (at > bestAt) { bestAt = at; best = r; }
|
|
52
|
+
}
|
|
53
|
+
return best;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Recompute and apply `read_subagent` presence in pi's active tool set. */
|
|
57
|
+
export function setReadSubagentDemand(pi: Pick<ExtensionAPI, "getActiveTools" | "setActiveTools">, owner: string, wanted: boolean): void {
|
|
58
|
+
demand.set(owner, wanted);
|
|
59
|
+
const want = [...demand.values()].some(Boolean);
|
|
60
|
+
const current = pi.getActiveTools();
|
|
61
|
+
const has = current.includes("read_subagent");
|
|
62
|
+
if (has === want) return;
|
|
63
|
+
pi.setActiveTools(want ? [...current, "read_subagent"] : current.filter((t) => t !== "read_subagent"));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Test hook: clear all registrations (incl. the registered tool flag). */
|
|
67
|
+
export function resetSubagentRegistry(): void {
|
|
68
|
+
readers.length = 0;
|
|
69
|
+
demand.clear();
|
|
70
|
+
toolOwner = undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── The shared read_subagent tool (registered once, dispatches by owner) ────
|
|
74
|
+
|
|
75
|
+
import { Box, Text, type Component } from "@earendil-works/pi-tui";
|
|
76
|
+
import { Type } from "typebox";
|
|
77
|
+
import { badge, leader, spinner, SPINNER_MS, STATE_BADGE, STATE_COLOR, type KitTheme, type RunState } from "../tui/kit.js";
|
|
78
|
+
|
|
79
|
+
const ReadSubagentParams = Type.Object({
|
|
80
|
+
agent_id: Type.Optional(Type.String({ description: "Subagent or sidekick id; omit for the most recent" })),
|
|
81
|
+
block: Type.Optional(Type.Boolean({ description: "Wait for completion (default false)" })),
|
|
82
|
+
timeout: Type.Optional(Type.Number({ description: "Maximum wait in seconds (default 30, max 600)" })),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
let toolOwner: ExtensionAPI | undefined;
|
|
86
|
+
|
|
87
|
+
interface ReadDetails {
|
|
88
|
+
owner?: string;
|
|
89
|
+
title?: string;
|
|
90
|
+
profile?: string;
|
|
91
|
+
status?: string;
|
|
92
|
+
toolCalls?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Shared state for one read_subagent row (call + result renderers). */
|
|
96
|
+
interface ReadState {
|
|
97
|
+
owner?: string;
|
|
98
|
+
title?: string;
|
|
99
|
+
final?: boolean;
|
|
100
|
+
startedAt?: number;
|
|
101
|
+
timer?: ReturnType<typeof setInterval>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface ReadContext {
|
|
105
|
+
state: ReadState;
|
|
106
|
+
invalidate(): void;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const lines = (render: (w: number) => string[]): Component => ({ invalidate() {}, render });
|
|
110
|
+
const secs = (ms: number) => `${String(Math.max(0, Math.floor(ms / 1000)))}s`;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Subagent reads are background work → badge lines:
|
|
114
|
+
* WAIT Map auth flow ······················· ⢎⡱ 12s
|
|
115
|
+
* GOT Map auth flow ······················· completed · 5 tool calls
|
|
116
|
+
* The call line shows while waiting; the result line replaces it.
|
|
117
|
+
*/
|
|
118
|
+
/**
|
|
119
|
+
* Sidekick reads keep pi's tinted tool box (fusion's choice): the tool renders
|
|
120
|
+
* itself (renderShell "self") so subagent reads can go boxless, and this
|
|
121
|
+
* repaints the standard box for everyone else.
|
|
122
|
+
*/
|
|
123
|
+
function toolBox(theme: KitTheme, bg: "toolPendingBg" | "toolSuccessBg" | "toolErrorBg", text: string): Component {
|
|
124
|
+
const paint = (theme as KitTheme & { bg?: (c: string, s: string) => string }).bg;
|
|
125
|
+
// Call as a method: pi's Theme.bg reads this.bgColors, so a detached call crashes the TUI.
|
|
126
|
+
const box = new Box(1, 1, paint ? (s: string) => paint.call(theme, bg, s) : undefined);
|
|
127
|
+
box.addChild(new Text(text, 0, 0));
|
|
128
|
+
return box;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const noContext = (): ReadContext => ({ state: {}, invalidate() {} });
|
|
132
|
+
|
|
133
|
+
function renderReadCall(args: SubagentReadParams, theme: KitTheme, context: ReadContext = noContext()): Component {
|
|
134
|
+
const st = context.state;
|
|
135
|
+
st.owner ??= readerFor(args.agent_id)?.owner;
|
|
136
|
+
st.startedAt ??= Date.now();
|
|
137
|
+
if (st.owner !== "subagents") {
|
|
138
|
+
if (st.final) return lines(() => []);
|
|
139
|
+
return toolBox(theme, "toolPendingBg", `${theme.fg("toolTitle", theme.bold("● read_subagent"))} ${theme.fg("dim", args.block === true ? "· waiting" : "· snapshot")}`);
|
|
140
|
+
}
|
|
141
|
+
if (args.block === true && !st.final && st.timer === undefined) {
|
|
142
|
+
st.timer = setInterval(() => context.invalidate(), SPINNER_MS);
|
|
143
|
+
st.timer.unref?.();
|
|
144
|
+
}
|
|
145
|
+
return lines((w) => {
|
|
146
|
+
if (st.final) return [];
|
|
147
|
+
const who = st.title ?? args.agent_id ?? "latest subagent";
|
|
148
|
+
const right = args.block === true ? `${spinner(theme)} ${theme.fg("dim", secs(Date.now() - (st.startedAt ?? Date.now())))}` : theme.fg("dim", "checking…");
|
|
149
|
+
return [leader(theme, `${badge(theme, "accent", args.block === true ? "WAIT" : "READ")} ${who}`, right, w)];
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function renderReadResult(result: { details?: unknown; isError?: boolean }, opts: { isPartial?: boolean }, theme: KitTheme, context: ReadContext = noContext()): Component {
|
|
154
|
+
const d = result.details as ReadDetails | undefined;
|
|
155
|
+
const st = context.state;
|
|
156
|
+
if (d?.owner) st.owner = d.owner;
|
|
157
|
+
if (d?.title) st.title = d.title;
|
|
158
|
+
if (st.owner === "subagents") {
|
|
159
|
+
if (opts.isPartial) return lines(() => []);
|
|
160
|
+
if (st.timer) clearInterval(st.timer);
|
|
161
|
+
st.timer = undefined;
|
|
162
|
+
st.final = true;
|
|
163
|
+
const status = d?.status ?? (result.isError === true ? "failed" : "completed");
|
|
164
|
+
const state = (status in STATE_COLOR ? status : "failed") as RunState;
|
|
165
|
+
const label = state === "running" ? "READ" : state === "completed" ? "GOT " : STATE_BADGE[state];
|
|
166
|
+
const chip = badge(theme, STATE_COLOR[state], label);
|
|
167
|
+
const bits = [state === "running" ? "still running" : status, d?.toolCalls !== undefined ? `${String(d.toolCalls)} tool call${d.toolCalls === 1 ? "" : "s"}` : ""].filter(Boolean);
|
|
168
|
+
return lines((w) => [leader(theme, `${chip} ${d?.title ?? st.title ?? "subagent"}`, theme.fg("dim", bits.join(" · ")), w)]);
|
|
169
|
+
}
|
|
170
|
+
// Sidekick/fusion reads keep the compact ◆ status line in a tool box; the
|
|
171
|
+
// call box above is dropped once the result box replaces it.
|
|
172
|
+
if (!opts.isPartial) st.final = true;
|
|
173
|
+
const status = d?.status ?? "done";
|
|
174
|
+
const err = result.isError === true;
|
|
175
|
+
return toolBox(theme, opts.isPartial ? "toolPendingBg" : err ? "toolErrorBg" : "toolSuccessBg", `${theme.fg(err ? "error" : "accent", err ? "✗" : "◆")} ${theme.fg("toolTitle", theme.bold(`read_subagent ${status}`))}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Register the shared `read_subagent` tool (idempotent — the first loader
|
|
180
|
+
* wins). Owners must have registered a reader via `registerSubagentReader`.
|
|
181
|
+
*/
|
|
182
|
+
export function ensureReadSubagentTool(pi: ExtensionAPI): void {
|
|
183
|
+
if (toolOwner === pi) return;
|
|
184
|
+
toolOwner = pi;
|
|
185
|
+
pi.registerTool({
|
|
186
|
+
name: "read_subagent",
|
|
187
|
+
label: "Read Subagent",
|
|
188
|
+
description:
|
|
189
|
+
"Read a subagent's or the sidekick's result by agent_id (omit for the most recent). block:true waits for completion up to timeout seconds (default 30, max 600); block:false returns the current status immediately.",
|
|
190
|
+
parameters: ReadSubagentParams,
|
|
191
|
+
renderShell: "self",
|
|
192
|
+
renderCall: (args: SubagentReadParams, theme, context) => renderReadCall(args, theme, context as unknown as ReadContext),
|
|
193
|
+
renderResult: (result, options, theme, context) => renderReadResult(result as never, options, theme, context as unknown as ReadContext),
|
|
194
|
+
async execute(_toolCallId, params: SubagentReadParams, signal, onUpdate, ctx) {
|
|
195
|
+
const reader = readerFor(params.agent_id, ctx);
|
|
196
|
+
if (!reader) {
|
|
197
|
+
return { content: [{ type: "text" as const, text: params.agent_id !== undefined ? `No subagent found for ${params.agent_id}.` : "No subagent has run yet." }], details: {}, isError: true };
|
|
198
|
+
}
|
|
199
|
+
const timeoutSec = Math.min(600, params.timeout ?? 30);
|
|
200
|
+
return (await reader.read({ ...params, timeout: timeoutSec }, signal, onUpdate === undefined ? undefined : (u) => onUpdate(u as never), ctx)) as never;
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
}
|