@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
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
* tool_call → TurnActivity accumulation (bash commands, edit/write
|
|
5
5
|
* files, call count)
|
|
6
6
|
* agent_end → extract recent tail + token totals, run continuation
|
|
7
|
-
* settlement,
|
|
8
|
-
*
|
|
9
|
-
* re-resolves, the owner wins, the loop continues)
|
|
7
|
+
* settlement, fill the arbiter's nudge stash (delivered by
|
|
8
|
+
* the single agent_before_settle nudge, long-horizon/index.ts)
|
|
10
9
|
* verifier → modelRegistry.complete on the session model (or the
|
|
11
10
|
* configured verifier model)
|
|
12
11
|
*
|
|
13
|
-
* The loop closes here: agent_end → settle →
|
|
14
|
-
* agent_end … bounded by maxTurns / stall cap / token budget.
|
|
12
|
+
* The loop closes here: agent_end → settle → stash → before_settle nudge →
|
|
13
|
+
* next turn → agent_end … bounded by maxTurns / stall cap / token budget.
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
@@ -24,6 +23,9 @@ import type { RalphLoop } from "./engine/ralph.js";
|
|
|
24
23
|
import type { LongHorizonSettings } from "./settings.js";
|
|
25
24
|
import { loadSettings } from "./settings.js";
|
|
26
25
|
import { RunawayGuard } from "./engine/runaway.js";
|
|
26
|
+
import { appendProgress, registerProgressRenderer, sendHarnessUserMessage, UNIPI_EVENTS } from "@pi-unipi/core";
|
|
27
|
+
import { goalEstimatePrompt, goalProgressData, parseEstimate, type GoalEvidence } from "./progress.js";
|
|
28
|
+
import { TERMINAL_GOAL_STATUSES } from "./engine/goal-state.js";
|
|
27
29
|
|
|
28
30
|
/** Extract command/file signals from a tool call for the activity record. */
|
|
29
31
|
export function classifyToolCall(
|
|
@@ -88,7 +90,9 @@ export function extractTail(
|
|
|
88
90
|
.filter((entry) => entry.text.length > 0);
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
/** Best-effort cumulative token count from assistant usage fields.
|
|
93
|
+
/** Best-effort cumulative token count from assistant usage fields. Accepts
|
|
94
|
+
* both shapes pi providers emit: {input, output, cacheRead, cacheWrite,
|
|
95
|
+
* totalTokens} and {inputTokens, outputTokens}. */
|
|
92
96
|
export function sumUsageTokens(messages: readonly unknown[]): number | undefined {
|
|
93
97
|
let total = 0;
|
|
94
98
|
let seen = false;
|
|
@@ -102,8 +106,16 @@ export function sumUsageTokens(messages: readonly unknown[]): number | undefined
|
|
|
102
106
|
seen = true;
|
|
103
107
|
continue;
|
|
104
108
|
}
|
|
105
|
-
const input = typeof record.
|
|
106
|
-
|
|
109
|
+
const input = typeof record.input === "number"
|
|
110
|
+
? record.input
|
|
111
|
+
: typeof record.inputTokens === "number"
|
|
112
|
+
? record.inputTokens
|
|
113
|
+
: 0;
|
|
114
|
+
const output = typeof record.output === "number"
|
|
115
|
+
? record.output
|
|
116
|
+
: typeof record.outputTokens === "number"
|
|
117
|
+
? record.outputTokens
|
|
118
|
+
: 0;
|
|
107
119
|
if (input + output > 0) {
|
|
108
120
|
total += input + output;
|
|
109
121
|
seen = true;
|
|
@@ -112,6 +124,58 @@ export function sumUsageTokens(messages: readonly unknown[]): number | undefined
|
|
|
112
124
|
return seen ? total : undefined;
|
|
113
125
|
}
|
|
114
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Char-based token estimate (ceil(chars/4)) over a turn's assistant text,
|
|
129
|
+
* thinking, tool-call args, and toolResult text. Used when a provider reports
|
|
130
|
+
* no usable usage so the budget still bounds the loop.
|
|
131
|
+
*/
|
|
132
|
+
export function estimateTokens(messages: readonly unknown[]): number {
|
|
133
|
+
let chars = 0;
|
|
134
|
+
const countText = (value: unknown): void => {
|
|
135
|
+
if (typeof value === "string") chars += value.length;
|
|
136
|
+
};
|
|
137
|
+
for (const message of messages) {
|
|
138
|
+
if (typeof message !== "object" || message === null) continue;
|
|
139
|
+
const record = message as Record<string, unknown>;
|
|
140
|
+
const role = typeof record.role === "string" ? record.role : undefined;
|
|
141
|
+
const content = record.content;
|
|
142
|
+
if (role === "assistant") {
|
|
143
|
+
if (typeof content === "string") {
|
|
144
|
+
chars += content.length;
|
|
145
|
+
} else if (Array.isArray(content)) {
|
|
146
|
+
for (const part of content) {
|
|
147
|
+
if (typeof part !== "object" || part === null) continue;
|
|
148
|
+
const block = part as Record<string, unknown>;
|
|
149
|
+
if (block.type === "text") countText(block.text);
|
|
150
|
+
else if (block.type === "thinking") countText(block.thinking);
|
|
151
|
+
else if (block.type === "toolCall" || block.type === "tool_call" || block.type === "toolUse" || block.type === "tool_use") {
|
|
152
|
+
const args = block.arguments !== undefined ? block.arguments : block.input;
|
|
153
|
+
if (typeof args === "string") {
|
|
154
|
+
chars += args.length;
|
|
155
|
+
} else if (args !== undefined && args !== null) {
|
|
156
|
+
try {
|
|
157
|
+
chars += JSON.stringify(args).length;
|
|
158
|
+
} catch {
|
|
159
|
+
// Unserializable args just don't count.
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} else if (role === "toolResult" || role === "tool_result") {
|
|
166
|
+
if (typeof content === "string") chars += content.length;
|
|
167
|
+
else if (Array.isArray(content)) {
|
|
168
|
+
for (const part of content) {
|
|
169
|
+
if (typeof part === "object" && part !== null && (part as Record<string, unknown>).type === "text") {
|
|
170
|
+
countText((part as Record<string, unknown>).text);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return Math.ceil(chars / 4);
|
|
177
|
+
}
|
|
178
|
+
|
|
115
179
|
export interface RuntimeDeps {
|
|
116
180
|
readonly machine: GoalMachine;
|
|
117
181
|
readonly toolset: GoalToolset;
|
|
@@ -126,8 +190,14 @@ interface EvalContext {
|
|
|
126
190
|
model: ExtensionContext["model"];
|
|
127
191
|
}
|
|
128
192
|
|
|
129
|
-
export
|
|
193
|
+
export interface RuntimeHandle {
|
|
194
|
+
/** Estimate goal progress now and post it (user-only). */
|
|
195
|
+
estimateGoal(ctx?: ExtensionContext): Promise<"ok" | "none" | "failed">;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function wireRuntime(pi: ExtensionAPI, deps: RuntimeDeps): RuntimeHandle {
|
|
130
199
|
const settings = deps.loadSettings ?? loadSettings;
|
|
200
|
+
registerProgressRenderer(pi);
|
|
131
201
|
|
|
132
202
|
// ── per-turn activity accumulator ───────────────────────────────────
|
|
133
203
|
let toolCalls = 0;
|
|
@@ -151,12 +221,31 @@ export function wireRuntime(pi: ExtensionAPI, deps: RuntimeDeps): void {
|
|
|
151
221
|
// ── runaway guard: feed steps, steer once per turn ─────────────────
|
|
152
222
|
const runaway = new RunawayGuard({
|
|
153
223
|
steer: (text) => {
|
|
154
|
-
|
|
224
|
+
sendHarnessUserMessage(
|
|
225
|
+
pi,
|
|
226
|
+
text,
|
|
227
|
+
{ source: "Progress guard", title: "No-progress guard", synopsis: "Repeated work detected", severity: "warning" },
|
|
228
|
+
{ deliverAs: "steer" },
|
|
229
|
+
);
|
|
155
230
|
},
|
|
156
231
|
});
|
|
232
|
+
// pi's tool_execution_end carries no input — capture args per call at
|
|
233
|
+
// execution start and join them at the end, so "identical arguments" keys
|
|
234
|
+
// on real arguments instead of collapsing to one hash for the whole tool.
|
|
235
|
+
const argsByCallId = new Map<string, unknown>();
|
|
236
|
+
pi.on("tool_execution_start", (event) => {
|
|
237
|
+
try {
|
|
238
|
+
const startEvent = event as { toolCallId?: string; args?: unknown };
|
|
239
|
+
if (typeof startEvent.toolCallId === "string") {
|
|
240
|
+
argsByCallId.set(startEvent.toolCallId, startEvent.args);
|
|
241
|
+
}
|
|
242
|
+
} catch {
|
|
243
|
+
// Detector instrumentation must never abort a turn.
|
|
244
|
+
}
|
|
245
|
+
});
|
|
157
246
|
pi.on("tool_execution_end", (event) => {
|
|
158
247
|
try {
|
|
159
|
-
const toolEvent = event as { toolName?: string; result?: unknown; isError?: boolean };
|
|
248
|
+
const toolEvent = event as { toolCallId?: string; toolName?: string; result?: unknown; isError?: boolean; input?: unknown };
|
|
160
249
|
if (typeof toolEvent.toolName !== "string") return;
|
|
161
250
|
const resultText =
|
|
162
251
|
typeof toolEvent.result === "string"
|
|
@@ -168,9 +257,12 @@ export function wireRuntime(pi: ExtensionAPI, deps: RuntimeDeps): void {
|
|
|
168
257
|
return String(toolEvent.result ?? "");
|
|
169
258
|
}
|
|
170
259
|
})();
|
|
260
|
+
const callId = typeof toolEvent.toolCallId === "string" ? toolEvent.toolCallId : undefined;
|
|
261
|
+
const input = callId !== undefined ? argsByCallId.get(callId) : undefined;
|
|
262
|
+
if (callId !== undefined) argsByCallId.delete(callId);
|
|
171
263
|
runaway.feed({
|
|
172
264
|
tool: toolEvent.toolName,
|
|
173
|
-
input: (event as { input?: unknown }).input,
|
|
265
|
+
input: input ?? (event as { input?: unknown }).input,
|
|
174
266
|
resultText: resultText.slice(0, 400),
|
|
175
267
|
isError: toolEvent.isError === true,
|
|
176
268
|
});
|
|
@@ -202,21 +294,75 @@ export function wireRuntime(pi: ExtensionAPI, deps: RuntimeDeps): void {
|
|
|
202
294
|
const tokens = sumUsageTokens(messages);
|
|
203
295
|
// Only update when this turn actually reported usage — a usage-less turn
|
|
204
296
|
// keeps the last known counter (and never erases an injected one).
|
|
205
|
-
if (tokens !== undefined)
|
|
297
|
+
if (tokens !== undefined) {
|
|
298
|
+
deps.continuation.setTokenCounter(() => tokens);
|
|
299
|
+
deps.continuation.setTokensEstimated(false);
|
|
300
|
+
} else if (messages.length > 0) {
|
|
301
|
+
// Messages exist but carry no usable usage: estimate from their sizes so
|
|
302
|
+
// the budget still bounds the loop (flagged as estimated everywhere).
|
|
303
|
+
const estimated = estimateTokens(messages);
|
|
304
|
+
deps.continuation.setTokenCounter(() => estimated);
|
|
305
|
+
deps.continuation.setTokensEstimated(true);
|
|
306
|
+
}
|
|
307
|
+
deps.continuation.setNotify((text, level) => {
|
|
308
|
+
try {
|
|
309
|
+
(ctx as { ui?: { notify?: (t: string, l?: string) => void } }).ui?.notify?.(text, level ?? "warning");
|
|
310
|
+
} catch {
|
|
311
|
+
// Notification must never break settlement.
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
if (deps.machine.get()) lastEvidence = activity;
|
|
206
315
|
await deps.continuation.onTurnEnd(activity);
|
|
316
|
+
// Per-loop goal progress: fire-and-forget, never delays the next turn.
|
|
317
|
+
if (settings().goalProgress === "loop") void estimateGoal(ctx, true);
|
|
207
318
|
} catch {
|
|
208
319
|
// Settlement failures must never surface as turn aborts.
|
|
209
320
|
}
|
|
210
321
|
});
|
|
211
322
|
|
|
212
|
-
// ──
|
|
213
|
-
|
|
214
|
-
|
|
323
|
+
// ── goal progress estimate (one-off side call, never in context) ─────
|
|
324
|
+
let lastEvidence: GoalEvidence | undefined;
|
|
325
|
+
let lastPercent: number | undefined;
|
|
326
|
+
let lastGoalKey: string | undefined;
|
|
327
|
+
let estimating = false;
|
|
328
|
+
|
|
329
|
+
async function estimateGoal(ctx?: ExtensionContext, fromLoop = false): Promise<"ok" | "none" | "failed"> {
|
|
330
|
+
try {
|
|
331
|
+
const goal = deps.machine.get();
|
|
332
|
+
if (!goal || deps.ralph?.get()?.status === "active") return "none"; // ralph has its own bar
|
|
333
|
+
const key = `${goal.goalId}:${goal.status}`;
|
|
334
|
+
const terminal = TERMINAL_GOAL_STATUSES.has(goal.status);
|
|
335
|
+
// A loop posts once per goal turn; a finished goal posts its last bar once.
|
|
336
|
+
if (fromLoop && (goal.status === "paused" || (terminal && key === lastGoalKey))) return "none";
|
|
337
|
+
if (goal.goalId !== lastGoalKey?.split(":")[0]) lastPercent = undefined;
|
|
338
|
+
lastGoalKey = key;
|
|
339
|
+
if (goal.status === "complete") {
|
|
340
|
+
appendProgress(pi, goalProgressData(goal, 100, "Objective met."));
|
|
341
|
+
return "ok";
|
|
342
|
+
}
|
|
343
|
+
if (estimating) return "ok";
|
|
344
|
+
estimating = true;
|
|
345
|
+
const s = settings();
|
|
346
|
+
const text = await complete(s.progressModel || s.verifierModel, goalEstimatePrompt(goal, lastEvidence, lastPercent), undefined, ctx);
|
|
347
|
+
const est = parseEstimate(text);
|
|
348
|
+
if (!est) return "failed";
|
|
349
|
+
lastPercent = est.percent;
|
|
350
|
+
appendProgress(pi, goalProgressData(deps.machine.get() ?? goal, est.percent, est.summary));
|
|
351
|
+
return "ok";
|
|
352
|
+
} catch {
|
|
353
|
+
return "failed";
|
|
354
|
+
} finally {
|
|
355
|
+
estimating = false;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ── one-shot completions (verifier, progress) → modelRegistry.complete ─
|
|
360
|
+
async function complete(configured: string, prompt: string, signal?: AbortSignal, ctx?: ExtensionContext): Promise<string> {
|
|
361
|
+
const context = ctx ? { registry: ctx.modelRegistry, model: ctx.model } : evalContext;
|
|
215
362
|
if (!context?.model || !context.registry) {
|
|
216
363
|
throw new Error("verifier: no model context available yet");
|
|
217
364
|
}
|
|
218
365
|
let model = context.model;
|
|
219
|
-
const configured = settings().verifierModel;
|
|
220
366
|
if (configured) {
|
|
221
367
|
const slash = configured.indexOf("/");
|
|
222
368
|
if (slash > 0) {
|
|
@@ -243,7 +389,8 @@ export function wireRuntime(pi: ExtensionAPI, deps: RuntimeDeps): void {
|
|
|
243
389
|
: "";
|
|
244
390
|
if (!text) throw new Error("verifier: empty completion");
|
|
245
391
|
return text;
|
|
246
|
-
}
|
|
392
|
+
}
|
|
393
|
+
const evaluate: VerifierEvaluate = (prompt, signal) => complete(settings().verifierModel, prompt, signal);
|
|
247
394
|
deps.continuation.setEvaluate(evaluate);
|
|
248
395
|
if (deps.ralph) deps.ralph.setEvaluate(evaluate);
|
|
249
396
|
|
|
@@ -251,4 +398,11 @@ export function wireRuntime(pi: ExtensionAPI, deps: RuntimeDeps): void {
|
|
|
251
398
|
pi.on("session_compact", () => {
|
|
252
399
|
deps.continuation.armRecovery();
|
|
253
400
|
});
|
|
401
|
+
// Boundary compactions (compactor's percentage trigger) don't fire
|
|
402
|
+
// session_compact; the compactor announces them on the event bus.
|
|
403
|
+
pi.events?.on?.(UNIPI_EVENTS.COMPACTOR_COMPACTED, () => {
|
|
404
|
+
deps.continuation.armRecovery();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
return { estimateGoal: (ctx) => estimateGoal(ctx) };
|
|
254
408
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { dirname, join } from "node:path";
|
|
14
14
|
import { homedir } from "node:os";
|
|
15
|
-
import { getSettings, registerSettings, setSettings } from "@pi-unipi/core";
|
|
15
|
+
import { decisionModelSection, DEFAULT_DECISION_OVERRIDE, getSettings, registerSettings, resolveDecisionModel, setSettings } from "@pi-unipi/core";
|
|
16
16
|
import type { LhMode } from "./modes.js";
|
|
17
17
|
|
|
18
18
|
export interface JudgeSettings {
|
|
@@ -52,6 +52,14 @@ export interface LongHorizonSettings {
|
|
|
52
52
|
defaultMode: LhMode;
|
|
53
53
|
/** Model used for goal-completion verification (empty = session model). */
|
|
54
54
|
verifierModel: string;
|
|
55
|
+
/**
|
|
56
|
+
* User-only goal progress estimate (a one-off model call, never in context):
|
|
57
|
+
* "loop" = after every goal turn and on /unipi:goal status; "status" = only
|
|
58
|
+
* on status; "off" = never.
|
|
59
|
+
*/
|
|
60
|
+
goalProgress: "loop" | "status" | "off";
|
|
61
|
+
/** Model for the estimate (empty = verifier model, else session model). */
|
|
62
|
+
progressModel: string;
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
export const DEFAULT_SETTINGS: LongHorizonSettings = {
|
|
@@ -62,12 +70,14 @@ export const DEFAULT_SETTINGS: LongHorizonSettings = {
|
|
|
62
70
|
// openrouter/custom ride the decisions endpoint → the hosted jev id.
|
|
63
71
|
model: "typesafe/jev-1.13",
|
|
64
72
|
baseUrl: "",
|
|
65
|
-
threshold: 0.
|
|
73
|
+
threshold: 0.8,
|
|
66
74
|
timeoutMs: 0,
|
|
67
75
|
apiKey: "",
|
|
68
76
|
},
|
|
69
|
-
defaultMode: "
|
|
77
|
+
defaultMode: "none",
|
|
70
78
|
verifierModel: "",
|
|
79
|
+
goalProgress: "loop",
|
|
80
|
+
progressModel: "",
|
|
71
81
|
};
|
|
72
82
|
|
|
73
83
|
const settingsPath = (): string => join(homedir(), ".pi", "agent", "settings.json");
|
|
@@ -134,6 +144,8 @@ function mergeSettings(stored: unknown): LongHorizonSettings {
|
|
|
134
144
|
? (stored.defaultMode as LhMode)
|
|
135
145
|
: DEFAULT_SETTINGS.defaultMode,
|
|
136
146
|
verifierModel: typeof stored.verifierModel === "string" ? stored.verifierModel : "",
|
|
147
|
+
goalProgress: stored.goalProgress === "status" || stored.goalProgress === "off" ? stored.goalProgress : "loop",
|
|
148
|
+
progressModel: typeof stored.progressModel === "string" ? stored.progressModel : "",
|
|
137
149
|
};
|
|
138
150
|
}
|
|
139
151
|
|
|
@@ -145,50 +157,18 @@ let cache: LongHorizonSettings | null = null;
|
|
|
145
157
|
registerSettings({
|
|
146
158
|
namespace: "long-horizon",
|
|
147
159
|
label: "Long-Horizon",
|
|
148
|
-
defaults: DEFAULT_SETTINGS as unknown as Record<string, unknown>,
|
|
160
|
+
defaults: { ...DEFAULT_SETTINGS, decisionModel: DEFAULT_DECISION_OVERRIDE } as unknown as Record<string, unknown>,
|
|
149
161
|
projectOverrides: true,
|
|
150
162
|
schema: [
|
|
151
163
|
{
|
|
152
164
|
title: "Judge",
|
|
153
|
-
description: "Prompt → mode routing
|
|
165
|
+
description: "Prompt → mode routing with the Decision Model (shared settings: /unipi:settings → Decision Model)",
|
|
154
166
|
fields: [
|
|
155
167
|
{ key: "judge.enabled", type: "boolean", label: "Judge enabled", description: "Route new prompts automatically; off = always defaultMode" },
|
|
156
|
-
{
|
|
157
|
-
key: "judge.provider",
|
|
158
|
-
type: "enum",
|
|
159
|
-
label: "Provider",
|
|
160
|
-
options: [
|
|
161
|
-
{ value: "typesafe", label: "typesafe (native systemone)" },
|
|
162
|
-
{ value: "openrouter", label: "openrouter (decisions endpoint)" },
|
|
163
|
-
{ value: "custom", label: "custom (Base URL + API key)" },
|
|
164
|
-
],
|
|
165
|
-
description: "typesafe = native systemone · openrouter = decisions/chat · custom = your own gateway",
|
|
166
|
-
},
|
|
167
|
-
{ key: "judge.baseUrl", type: "string", label: "Base URL", description: "required when provider=custom · oino proxy = https://router.oino.dev/v1", emptyLabel: "provider default" },
|
|
168
|
-
{ key: "judge.apiKey", type: "secret", label: "API key", description: "Stored key wins over env (works in tmux/ssh-c/systemd)", emptyLabel: "env / bridge fallback" },
|
|
169
|
-
{
|
|
170
|
-
key: "judge.model",
|
|
171
|
-
type: "model",
|
|
172
|
-
label: "Decision model",
|
|
173
|
-
description: "decision (classifier) model — jev; custom… for others",
|
|
174
|
-
providerKey: "judge.provider",
|
|
175
|
-
presetsByProvider: {
|
|
176
|
-
typesafe: ["jev-latest"],
|
|
177
|
-
openrouter: ["typesafe/jev-1.13"],
|
|
178
|
-
custom: ["typesafe/jev-1.13"],
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
168
|
{ key: "judge.threshold", type: "number", label: "Confidence threshold", description: "Below this the judge abstains (0-1)", min: 0.01, max: 1 },
|
|
182
169
|
],
|
|
183
170
|
},
|
|
184
|
-
{
|
|
185
|
-
title: "Judge — Advanced",
|
|
186
|
-
advanced: true,
|
|
187
|
-
description: "Rarely needed — zero means the provider default",
|
|
188
|
-
fields: [
|
|
189
|
-
{ key: "judge.timeoutMs", type: "number", label: "Timeout ms", min: 0, zeroLabel: "auto (1s native / 6s chat)" },
|
|
190
|
-
],
|
|
191
|
-
},
|
|
171
|
+
decisionModelSection({ title: "Judge — Decision model" }),
|
|
192
172
|
{
|
|
193
173
|
title: "Modes",
|
|
194
174
|
fields: [
|
|
@@ -202,6 +182,24 @@ registerSettings({
|
|
|
202
182
|
{ key: "verifierModel", type: "model", label: "Verifier model", description: "Goal completion verification", emptyLabel: "inherit (session model)", capability: "text", emptyOption: "inherit (session model)" },
|
|
203
183
|
],
|
|
204
184
|
},
|
|
185
|
+
{
|
|
186
|
+
title: "Progress",
|
|
187
|
+
description: "Progress bars shown only to you — never sent to the model",
|
|
188
|
+
fields: [
|
|
189
|
+
{
|
|
190
|
+
key: "goalProgress",
|
|
191
|
+
type: "enum",
|
|
192
|
+
label: "Goal progress estimate",
|
|
193
|
+
options: [
|
|
194
|
+
{ value: "loop", label: "every loop + /goal status" },
|
|
195
|
+
{ value: "status", label: "only on /goal status" },
|
|
196
|
+
{ value: "off", label: "off" },
|
|
197
|
+
],
|
|
198
|
+
description: "A one-off side call estimates % done and summarizes the work so far",
|
|
199
|
+
},
|
|
200
|
+
{ key: "progressModel", type: "model", label: "Estimate model", description: "Cheaper is fine; runs once per goal turn", emptyLabel: "inherit (verifier → session model)", capability: "text", emptyOption: "inherit (verifier → session model)" },
|
|
201
|
+
],
|
|
202
|
+
},
|
|
205
203
|
],
|
|
206
204
|
});
|
|
207
205
|
|
|
@@ -209,10 +207,27 @@ export function loadSettings(force = false): LongHorizonSettings {
|
|
|
209
207
|
if (cache && !force) return cache;
|
|
210
208
|
const raw = getSettings("long-horizon", process.cwd());
|
|
211
209
|
// The engine stores validated shapes; re-validate defensively anyway.
|
|
212
|
-
cache = mergeSettings(raw);
|
|
210
|
+
cache = withDecisionModel(mergeSettings(raw), process.cwd());
|
|
213
211
|
return cache;
|
|
214
212
|
}
|
|
215
213
|
|
|
214
|
+
/**
|
|
215
|
+
* The judge's transport (provider/model/baseUrl/key/timeout) is the Decision
|
|
216
|
+
* Model — shared, or this module's custom override. `enabled` and
|
|
217
|
+
* `threshold` stay long-horizon's own.
|
|
218
|
+
*/
|
|
219
|
+
function withDecisionModel(settings: LongHorizonSettings, cwd: string): LongHorizonSettings {
|
|
220
|
+
try {
|
|
221
|
+
const dm = resolveDecisionModel(cwd, "long-horizon");
|
|
222
|
+
return {
|
|
223
|
+
...settings,
|
|
224
|
+
judge: { ...settings.judge, provider: dm.provider, model: dm.model, baseUrl: dm.baseUrl, apiKey: dm.apiKey, timeoutMs: dm.timeoutMs ?? 0 },
|
|
225
|
+
};
|
|
226
|
+
} catch {
|
|
227
|
+
return settings;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
216
231
|
export function saveSettings(update: Partial<LongHorizonSettings>): LongHorizonSettings {
|
|
217
232
|
const current = mergeSettings(getSettings("long-horizon", process.cwd()));
|
|
218
233
|
const next = mergeSettings({ ...current, ...update, judge: { ...current.judge, ...(update.judge ?? {}) } });
|
|
@@ -59,6 +59,11 @@ export class GoalToolset {
|
|
|
59
59
|
return this.pending;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/** Drop any pending proposal unverified (user stop/clear); get_goal stops advertising it. */
|
|
63
|
+
discardProposal(): void {
|
|
64
|
+
this.pending = null;
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
register(pi: ExtensionAPI): void {
|
|
63
68
|
// ── create_goal ───────────────────────────────────────────────────
|
|
64
69
|
pi.registerTool({
|
|
@@ -219,6 +224,7 @@ export class GoalToolset {
|
|
|
219
224
|
stall_cap: goal.stallCap,
|
|
220
225
|
token_budget: goal.tokenBudget,
|
|
221
226
|
tokens_used: goal.tokensBaselinePending ? null : goal.tokensNow - goal.tokensAtStart,
|
|
227
|
+
tokens_estimated: goal.tokensEstimated === true,
|
|
222
228
|
expected_goal_id: goal.goalId,
|
|
223
229
|
expected_updated_at: goal.updatedAt,
|
|
224
230
|
updated_at: goal.updatedAt,
|
|
@@ -51,7 +51,7 @@ export const GRAPH_ORCHESTRATION_PROMPT = `<long-horizon-graph>
|
|
|
51
51
|
Graph Mode is active. You are the supervisor of a dependent work graph.
|
|
52
52
|
|
|
53
53
|
- Declare the graph first with update_agent_graph: items with explicit dependsOn (an item's inputs are the COMMITTED results of its dependencies). Cycles are refused.
|
|
54
|
-
- Dispatch every currently-ready item with
|
|
54
|
+
- Dispatch every currently-ready item with run_subagent (is_background:true for parallel items). Do not dispatch an item before its dependencies complete.
|
|
55
55
|
- After dispatching a wave, call swarm_yield. Do not poll; background notifications wake you.
|
|
56
56
|
- On wake, record outcomes with graph_output. Recording a completion hands you the next ready items together with their input frontiers (the dependency summaries) — pass those inputs into the child instructions instead of restating conclusions.
|
|
57
57
|
- A failed item can be re-dispatched after its failure is recorded; downstream items stay blocked until it completes or is aborted.
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Swarm — Maka's fan-out prescription over unipi's delegation tools.
|
|
3
3
|
*
|
|
4
4
|
* The ledger is the durable schedule: declared items with reported outcomes.
|
|
5
|
-
* The MODEL dispatches via
|
|
5
|
+
* The MODEL dispatches via run_subagent (full surface in swarm
|
|
6
6
|
* mode); swarm_report records outcomes idempotently; swarm_status projects
|
|
7
7
|
* running | needs_attention | settled; swarm_yield ends the supervisor turn
|
|
8
8
|
* (wakes arrive via background-task notifications — user-first by design).
|
|
9
9
|
*
|
|
10
|
-
* v1 seam honesty:
|
|
10
|
+
* v1 seam honesty: run_subagent dispatch is opaque to extensions, so
|
|
11
11
|
* claim-before-dispatch is enforced by the orchestration prompt (one dispatch
|
|
12
12
|
* per item) plus report idempotency (duplicate terminal reports refused
|
|
13
13
|
* unless the item was failed and is being replaced). Harness-level claims
|
|
@@ -45,7 +45,7 @@ Swarm Mode is active. Treat parallel delegation as the preferred execution strat
|
|
|
45
45
|
|
|
46
46
|
- Before acting, decide whether parallel delegation would materially improve speed, quality, coverage, or independent verification. If the work cannot be usefully divided into at least two meaningful independent items, continue directly.
|
|
47
47
|
- Make every item bounded and self-contained: explicit scope, expected output, constraints. Avoid overlapping writes; prefer read-only investigation.
|
|
48
|
-
- Dispatch each item exactly once with
|
|
48
|
+
- Dispatch each item exactly once with run_subagent (is_background:true for parallel items). Do not re-dispatch an item unless you reported it failed and are replacing it.
|
|
49
49
|
- After dispatching all items, call swarm_yield. Do not poll, sleep, watch task logs, or wait synchronously; background-task notifications will wake you when work settles.
|
|
50
50
|
- On wake, call swarm_status for compact statuses. Read full results only for completed items you will synthesize or failed items you must diagnose.
|
|
51
51
|
- Record every outcome with swarm_report. Replace failed work by re-dispatching a corrected item and reporting it under the same id.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/mcp",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.21",
|
|
4
4
|
"description": "MCP server management extension for Pi coding agent — browse, add, configure, and use MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test": "npx tsx --test tests/**/*.test.ts"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
33
|
+
"@pi-unipi/core": "3.0.0-alpha.21"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
12
|
import * as path from "node:path";
|
|
13
13
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
14
|
+
import { sendHarnessUserMessage } from "@pi-unipi/core";
|
|
14
15
|
import type { SessionBackend } from "./session.js";
|
|
15
16
|
import { MEMORY_TOOLS } from "./tools.js";
|
|
16
17
|
import { readMemoryConfig } from "./settings.js";
|
|
@@ -226,8 +227,10 @@ export function registerMemoryCommands(
|
|
|
226
227
|
return;
|
|
227
228
|
}
|
|
228
229
|
ctx.ui.notify("Analyzing text for memories... Use memory_store tool to save.", "info");
|
|
229
|
-
|
|
230
|
+
sendHarnessUserMessage(
|
|
231
|
+
pi,
|
|
230
232
|
`Analyze the following text and extract any memory-worthy items (user preferences, project decisions, code patterns, conversation summaries). For each item found, use the memory_store tool to save it.\n\nText to analyze:\n${args}`,
|
|
233
|
+
{ source: "Memory", title: "Extract memories", synopsis: "Generated from /unipi:memory-process" },
|
|
231
234
|
{ deliverAs: "followUp" },
|
|
232
235
|
);
|
|
233
236
|
},
|
|
@@ -237,7 +240,8 @@ export function registerMemoryCommands(
|
|
|
237
240
|
description: "Consolidate current session into memory",
|
|
238
241
|
handler: async (_args, ctx) => {
|
|
239
242
|
ctx.ui.notify("Consolidating session into memory... Use memory_store tool to save insights.", "info");
|
|
240
|
-
|
|
243
|
+
sendHarnessUserMessage(
|
|
244
|
+
pi,
|
|
241
245
|
`Review the current session and identify any memory-worthy items:
|
|
242
246
|
- User preferences discovered
|
|
243
247
|
- Project decisions made
|
|
@@ -245,6 +249,7 @@ export function registerMemoryCommands(
|
|
|
245
249
|
- Important context to remember
|
|
246
250
|
|
|
247
251
|
For each item, use the memory_store tool to save it with an appropriate title and type.`,
|
|
252
|
+
{ source: "Memory", title: "Consolidate session", synopsis: "Generated from /unipi:memory-consolidate" },
|
|
248
253
|
{ deliverAs: "followUp" },
|
|
249
254
|
);
|
|
250
255
|
},
|