@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
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* @pi-unipi/kanboard — settings (hub section "Kanboard").
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
+
import { getSettings, globalSettingsPath, projectSettingsPath, registerCommandRunner, registerSettings, setSettings } from "@pi-unipi/core";
|
|
6
7
|
|
|
7
8
|
export type ChainGate = "in_review" | "done";
|
|
8
9
|
|
|
@@ -25,12 +26,20 @@ export interface KanboardSettings {
|
|
|
25
26
|
requireAuth: boolean;
|
|
26
27
|
/** Reuse <home>/token so board links survive daemon restarts. */
|
|
27
28
|
keepToken: boolean;
|
|
28
|
-
/** Tasks one session may queue (0 = unlimited). */
|
|
29
|
-
queueMax: number;
|
|
30
29
|
/** Distinct sessions running tasks per project (min 1). */
|
|
31
30
|
maxSessions: number;
|
|
32
|
-
/** `add` calls allowed per
|
|
31
|
+
/** `add` calls allowed per turn (0 = unlimited). */
|
|
33
32
|
turnAddLimit: number;
|
|
33
|
+
/** Task slots a /unipi:kanboard-do grants (each `start` uses one). */
|
|
34
|
+
doTasks: number;
|
|
35
|
+
/** Board writes a /unipi:kanboard-do grants. */
|
|
36
|
+
doWrites: number;
|
|
37
|
+
/** Whether a blocked-by-confusion task may ask the user (ask) or must
|
|
38
|
+
* assume-and-note (avoid, the default). */
|
|
39
|
+
blocking: "avoid" | "ask";
|
|
40
|
+
/** Progress reminders when the agent works board tasks by hand: `start`
|
|
41
|
+
* before the first edit, `finish` (or block) before the turn ends. */
|
|
42
|
+
reminders: boolean;
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
export const DEFAULT_SETTINGS: KanboardSettings = {
|
|
@@ -43,9 +52,12 @@ export const DEFAULT_SETTINGS: KanboardSettings = {
|
|
|
43
52
|
openBrowser: false,
|
|
44
53
|
requireAuth: false,
|
|
45
54
|
keepToken: false,
|
|
46
|
-
queueMax: 10,
|
|
47
55
|
maxSessions: 2,
|
|
48
56
|
turnAddLimit: 20,
|
|
57
|
+
doTasks: 5,
|
|
58
|
+
doWrites: 10,
|
|
59
|
+
blocking: "avoid",
|
|
60
|
+
reminders: true,
|
|
49
61
|
};
|
|
50
62
|
|
|
51
63
|
export const KANBOARD_NAMESPACE = "kanboard";
|
|
@@ -59,11 +71,11 @@ export function registerKanboardSettings(): void {
|
|
|
59
71
|
registerSettings({
|
|
60
72
|
namespace: KANBOARD_NAMESPACE,
|
|
61
73
|
label: "Kanboard",
|
|
62
|
-
defaults: DEFAULT_SETTINGS as unknown as Record<string, unknown>,
|
|
74
|
+
defaults: { ...DEFAULT_SETTINGS } as unknown as Record<string, unknown>,
|
|
63
75
|
schema: [
|
|
64
76
|
{
|
|
65
77
|
title: "Kanboard",
|
|
66
|
-
description: "
|
|
78
|
+
description: "The session's work board: daemon, -do budgets and skill",
|
|
67
79
|
fields: [
|
|
68
80
|
{
|
|
69
81
|
key: "chainGate",
|
|
@@ -100,12 +112,16 @@ export function registerKanboardSettings(): void {
|
|
|
100
112
|
label: "Keep the access token across restarts",
|
|
101
113
|
description: "Reuse one token so board links stay valid; rotate it below.",
|
|
102
114
|
},
|
|
103
|
-
{ key: "queueMax", type: "number", label: "-do queue limit", min: 0, zeroLabel: "unlimited", description: "Tasks a session may queue for the runner" },
|
|
104
115
|
{ key: "maxSessions", type: "number", label: "Sessions working at once (per project)", min: 1, description: "Distinct sessions holding in_progress tasks" },
|
|
105
|
-
{ key: "turnAddLimit", type: "number", label: "New tasks per turn", min: 0, zeroLabel: "unlimited", description: "`add` calls allowed per
|
|
106
|
-
{
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
{ key: "turnAddLimit", type: "number", label: "New tasks per turn", min: 0, zeroLabel: "unlimited", description: "`add` calls allowed per turn" },
|
|
117
|
+
{
|
|
118
|
+
key: "reminders",
|
|
119
|
+
type: "boolean",
|
|
120
|
+
label: "Progress reminders",
|
|
121
|
+
description: "Remind the agent to `start` a mentioned Todo task before editing (text only, never blocks; off in child sessions)",
|
|
122
|
+
},
|
|
123
|
+
{ key: "doTasks", type: "number", label: "-do task slots", min: 0, zeroLabel: "off", description: "Task slots a /unipi:kanboard-do grants; each `start` uses one" },
|
|
124
|
+
{ key: "doWrites", type: "number", label: "-do write budget", min: 0, zeroLabel: "off", description: "Board writes a /unipi:kanboard-do grants (add, edit, link, order, move, note on tasks you don't hold)" },
|
|
109
125
|
],
|
|
110
126
|
},
|
|
111
127
|
],
|
|
@@ -127,9 +143,18 @@ export function readKanboardSettings(cwd: string = process.cwd()): KanboardSetti
|
|
|
127
143
|
openBrowser: raw.openBrowser === true,
|
|
128
144
|
requireAuth: raw.requireAuth === true,
|
|
129
145
|
keepToken: raw.keepToken === true,
|
|
130
|
-
queueMax: typeof raw.queueMax === "number" && raw.queueMax >= 0 ? raw.queueMax : DEFAULT_SETTINGS.queueMax,
|
|
131
146
|
maxSessions: typeof raw.maxSessions === "number" && raw.maxSessions >= 1 ? raw.maxSessions : DEFAULT_SETTINGS.maxSessions,
|
|
132
147
|
turnAddLimit: typeof raw.turnAddLimit === "number" && raw.turnAddLimit >= 0 ? raw.turnAddLimit : DEFAULT_SETTINGS.turnAddLimit,
|
|
148
|
+
// Migration: getSettings merges defaults, so a stored doCredits hides
|
|
149
|
+
// behind the doWrites default. Look at the stored layer for the legacy key
|
|
150
|
+
// (project first, then global) — the next settings write persists doWrites.
|
|
151
|
+
doTasks: typeof raw.doTasks === "number" && raw.doTasks >= 0 ? raw.doTasks : DEFAULT_SETTINGS.doTasks,
|
|
152
|
+
doWrites:
|
|
153
|
+
typeof raw.doWrites === "number" && raw.doWrites >= 0 && storedDoWritesSet(cwd)
|
|
154
|
+
? raw.doWrites
|
|
155
|
+
: (storedLegacyDoCredits(cwd) ?? DEFAULT_SETTINGS.doWrites),
|
|
156
|
+
blocking: raw.blocking === "ask" ? "ask" : "avoid",
|
|
157
|
+
reminders: raw.reminders !== false,
|
|
133
158
|
};
|
|
134
159
|
}
|
|
135
160
|
|
|
@@ -137,6 +162,35 @@ export function writeKanboardSettings(patch: Partial<KanboardSettings>, cwd: str
|
|
|
137
162
|
setSettings(KANBOARD_NAMESPACE, patch as unknown as Record<string, unknown>, "global", cwd);
|
|
138
163
|
}
|
|
139
164
|
|
|
165
|
+
/** Whether any stored layer carries an explicit doWrites (defaults don't count). */
|
|
166
|
+
function storedDoWritesSet(cwd: string): boolean {
|
|
167
|
+
for (const file of [projectSettingsPath(cwd, KANBOARD_NAMESPACE), globalSettingsPath(KANBOARD_NAMESPACE)]) {
|
|
168
|
+
try {
|
|
169
|
+
if (!existsSync(file)) continue;
|
|
170
|
+
const parsed = JSON.parse(readFileSync(file, "utf-8")) as Record<string, unknown>;
|
|
171
|
+
if (typeof parsed.doWrites === "number") return true;
|
|
172
|
+
} catch {
|
|
173
|
+
// A corrupt file has no legacy value either.
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** The pre-slot doCredits value from the stored layers, if any. */
|
|
180
|
+
function storedLegacyDoCredits(cwd: string): number | undefined {
|
|
181
|
+
for (const file of [projectSettingsPath(cwd, KANBOARD_NAMESPACE), globalSettingsPath(KANBOARD_NAMESPACE)]) {
|
|
182
|
+
try {
|
|
183
|
+
if (!existsSync(file)) continue;
|
|
184
|
+
const parsed = JSON.parse(readFileSync(file, "utf-8")) as Record<string, unknown>;
|
|
185
|
+
const value = parsed.doCredits;
|
|
186
|
+
if (typeof value === "number" && value >= 0) return value;
|
|
187
|
+
} catch {
|
|
188
|
+
// A corrupt file has no legacy value either.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
140
194
|
/** Re-exported so index.ts and tests share one registration path. */
|
|
141
195
|
export function registerKanboardRunners(runners: {
|
|
142
196
|
open: (ctx: unknown) => void | Promise<void>;
|
|
@@ -150,9 +204,9 @@ export function registerKanboardRunners(runners: {
|
|
|
150
204
|
|
|
151
205
|
/**
|
|
152
206
|
* Limits reach the Rust CLI through the environment — refresh the process-wide
|
|
153
|
-
* values so the agent's bash calls and
|
|
207
|
+
* values so the agent's bash calls and spawned CLI calls both see them.
|
|
208
|
+
* (queueMax died with the runner; the binary's queue limit is untouched.)
|
|
154
209
|
*/
|
|
155
210
|
export function applyLimitEnv(settings: KanboardSettings): void {
|
|
156
|
-
process.env.UNIPI_KANBOARD_QUEUE_MAX = String(settings.queueMax);
|
|
157
211
|
process.env.UNIPI_KANBOARD_MAX_SESSIONS = String(settings.maxSessions);
|
|
158
212
|
}
|
|
@@ -32,6 +32,8 @@ export interface KanboardRun {
|
|
|
32
32
|
mode?: string;
|
|
33
33
|
goal?: string | null;
|
|
34
34
|
started?: string;
|
|
35
|
+
/** "system" (runner claim) or "agent" (`start` self-claim). */
|
|
36
|
+
owner?: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export interface KanboardActivity {
|
|
@@ -43,6 +45,8 @@ export interface KanboardActivity {
|
|
|
43
45
|
export interface KanboardTask {
|
|
44
46
|
id: string;
|
|
45
47
|
title: string;
|
|
48
|
+
/** Title derived from the first body line when `title` is empty (Rust `Task::display_title`). */
|
|
49
|
+
displayTitle?: string;
|
|
46
50
|
body?: string;
|
|
47
51
|
status: string;
|
|
48
52
|
priority?: string;
|
|
@@ -113,6 +117,7 @@ export function asTask(command: string, value: unknown): KanboardTask {
|
|
|
113
117
|
...record,
|
|
114
118
|
id: requireString(command, record, "id"),
|
|
115
119
|
title: requireString(command, record, "title"),
|
|
120
|
+
displayTitle: typeof record.displayTitle === "string" ? record.displayTitle : undefined,
|
|
116
121
|
status: requireString(command, record, "status"),
|
|
117
122
|
deps: optionalArray<string>(record.deps) ?? [],
|
|
118
123
|
activity: optionalArray<KanboardActivity>(record.activity) ?? [],
|
|
@@ -10,20 +10,23 @@ import { existsSync, renameSync } from "node:fs";
|
|
|
10
10
|
import { join, resolve } from "node:path";
|
|
11
11
|
import { Text } from "@earendil-works/pi-tui";
|
|
12
12
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
13
|
-
import { emitEvent, getPackageVersion, registerCommandRunner, stateDir, UNIPI_EVENTS, setSharedLongHorizonMode } from "@pi-unipi/core";
|
|
13
|
+
import { appendProgress, emitEvent, getPackageVersion, harnessMetadata, installArbiter, registerCommandRunner, registerCompactionContext, registerNudgeProvider, sendHarnessUserMessage, stateDir, UNIPI_EVENTS, setSharedLongHorizonMode } from "@pi-unipi/core";
|
|
14
|
+
import { longHorizonCompactionBrief } from "./src/compaction-brief.js";
|
|
14
15
|
import { OwnerCoordinator, type OwnerEvent } from "./src/owner.js";
|
|
15
16
|
import { Gate } from "./src/gate.js";
|
|
16
|
-
import { registerLongHorizonCommands } from "./src/commands.js";
|
|
17
|
+
import { registerLongHorizonCommands, stopActiveOwner } from "./src/commands.js";
|
|
17
18
|
import { loadSettings } from "./src/settings.js";
|
|
18
19
|
import { GoalMachine } from "./src/engine/goal-state.js";
|
|
19
20
|
import { GoalToolset } from "./src/tools/goal.js";
|
|
20
21
|
import { GoalContinuation } from "./src/engine/continuation.js";
|
|
22
|
+
import { NudgeStash, nextStashMetaState, ownerEventClearsStash, type StashMetaState } from "./src/engine/nudge-stash.js";
|
|
21
23
|
import { RalphLoop } from "./src/engine/ralph.js";
|
|
22
24
|
import { registerRalphTools } from "./src/tools/ralph.js";
|
|
23
25
|
import { SwarmLedger, registerSwarmTools } from "./src/tools/swarm.js";
|
|
24
26
|
import { GraphLedger, registerGraphTools } from "./src/tools/graph.js";
|
|
25
27
|
import { TodoStore, registerTodoTool } from "./src/tools/todo.js";
|
|
26
28
|
import { wireRuntime } from "./src/runtime.js";
|
|
29
|
+
import { ralphProgressData } from "./src/progress.js";
|
|
27
30
|
|
|
28
31
|
export * from "./src/modes.js";
|
|
29
32
|
export * from "./src/owner.js";
|
|
@@ -56,10 +59,29 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
56
59
|
const version = getPackageVersion("long-horizon");
|
|
57
60
|
const statePath = () => lhStatePath("state.json");
|
|
58
61
|
|
|
62
|
+
// Standalone loads (`-e long-horizon/index.ts`) must install the arbiter
|
|
63
|
+
// themselves; the umbrella installs it before modules mount, and this call
|
|
64
|
+
// is a no-op there (holder flag).
|
|
65
|
+
try {
|
|
66
|
+
installArbiter(pi);
|
|
67
|
+
} catch {
|
|
68
|
+
// Never block module load on the arbiter.
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
// Owner lifecycle → unipi event bus (footer/info-screen consume these).
|
|
72
|
+
// A finished or parked owner invalidates an undelivered nudge (declared
|
|
73
|
+
// before `owner` so the onChange closure can clear it).
|
|
74
|
+
const stash = new NudgeStash();
|
|
75
|
+
// Provenance mirror state lives with the stash (declared BEFORE the owner
|
|
76
|
+
// constructor — its onChange may fire immediately).
|
|
77
|
+
let stashMetaState: StashMetaState<ReturnType<typeof harnessMetadata>> = { meta: undefined, kickoff: false };
|
|
60
78
|
const owner = new OwnerCoordinator({
|
|
61
79
|
statePath,
|
|
62
80
|
onChange: (_snapshot, event: OwnerEvent) => {
|
|
81
|
+
if (ownerEventClearsStash(event)) {
|
|
82
|
+
stash.take();
|
|
83
|
+
stashMetaState = { meta: undefined, kickoff: false };
|
|
84
|
+
}
|
|
63
85
|
emitEvent(pi, UNIPI_EVENTS.LONG_HORIZON_OWNER_CHANGED, {
|
|
64
86
|
event: event.type,
|
|
65
87
|
...("owner" in event && event.owner
|
|
@@ -108,7 +130,9 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
108
130
|
? "active owner"
|
|
109
131
|
: data.source === "judge_abstained_low_confidence"
|
|
110
132
|
? "judge abstained → default"
|
|
111
|
-
: "
|
|
133
|
+
: data.source === "child"
|
|
134
|
+
? "child agent"
|
|
135
|
+
: "default";
|
|
112
136
|
const line = `${t.fg?.("customMessageText", badge) ?? badge} ${t.fg?.("dim", via) ?? via}`;
|
|
113
137
|
return new Text(line, 0, 0);
|
|
114
138
|
},
|
|
@@ -117,6 +141,66 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
117
141
|
// Renderer registration is UI-dependent; skip where unavailable.
|
|
118
142
|
}
|
|
119
143
|
|
|
144
|
+
// ── messaging: nudge stash, not the message queue ──────────────────
|
|
145
|
+
// Continuation/ralph sends land in a one-slot stash; the arbiter delivers
|
|
146
|
+
// it as the single before_settle nudge (priority 100) and takes it.
|
|
147
|
+
// Timer wakes while idle (waiting-backoff) stay direct sends: they are
|
|
148
|
+
// events, and nothing would settle to drain the stash for them.
|
|
149
|
+
// (`stash` is declared above the owner so owner stops can clear it.)
|
|
150
|
+
let runActive = false;
|
|
151
|
+
try {
|
|
152
|
+
pi.on("agent_start", () => {
|
|
153
|
+
runActive = true;
|
|
154
|
+
});
|
|
155
|
+
pi.on("agent_settled", () => {
|
|
156
|
+
runActive = false;
|
|
157
|
+
});
|
|
158
|
+
} catch {
|
|
159
|
+
// Idle tracking must never block load.
|
|
160
|
+
}
|
|
161
|
+
const send: (message: string, kind?: "kickoff", meta?: { source: string; title: string; synopsis?: string; severity?: "warning" }) => void = (
|
|
162
|
+
message,
|
|
163
|
+
kind,
|
|
164
|
+
meta,
|
|
165
|
+
) => {
|
|
166
|
+
const next = nextStashMetaState(stashMetaState, stash.peek() !== null, kind, harnessMetadata(meta ?? { source: "Goal", title: kind === "kickoff" ? "Kickoff" : "Continuation" }, "boundary"));
|
|
167
|
+
stashMetaState = next;
|
|
168
|
+
stash.put(message, kind === "kickoff" ? { kickoff: true } : {});
|
|
169
|
+
};
|
|
170
|
+
const sendNow = (message: string, meta?: { source: string; title: string; synopsis?: string; severity?: "warning" }): void => {
|
|
171
|
+
try {
|
|
172
|
+
const options = runActive ? { deliverAs: "followUp" as const } : undefined;
|
|
173
|
+
sendHarnessUserMessage(
|
|
174
|
+
pi,
|
|
175
|
+
message,
|
|
176
|
+
meta ?? { source: "Goal", title: "Continuation" },
|
|
177
|
+
options,
|
|
178
|
+
);
|
|
179
|
+
} catch {
|
|
180
|
+
// A failed wake must never crash the session.
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
try {
|
|
184
|
+
registerNudgeProvider("long-horizon", 100, () => {
|
|
185
|
+
const text = stash.peek();
|
|
186
|
+
if (text === null) return null;
|
|
187
|
+
return {
|
|
188
|
+
source: "long-horizon",
|
|
189
|
+
priority: 100,
|
|
190
|
+
customType: "unipi:lh-continue",
|
|
191
|
+
content: text,
|
|
192
|
+
display: true,
|
|
193
|
+
...(stashMetaState.meta !== undefined ? { details: { unipiHarness: stashMetaState.meta } } : {}),
|
|
194
|
+
onDelivered: () => {
|
|
195
|
+
stash.take();
|
|
196
|
+
stashMetaState = { meta: undefined, kickoff: false };
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
} catch {
|
|
201
|
+
// Registration must never block load.
|
|
202
|
+
}
|
|
203
|
+
|
|
120
204
|
// Goal engine: machine + tools + continuation + runtime wiring.
|
|
121
205
|
const machine = new GoalMachine({
|
|
122
206
|
statePath: () => lhStatePath("goal.json"),
|
|
@@ -130,18 +214,18 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
130
214
|
toolset,
|
|
131
215
|
owner,
|
|
132
216
|
verifier: { evaluate: async () => { throw new Error("verifier unbound"); } },
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
217
|
+
// Continuation messages ride the arbiter's nudge stash (delivered as the
|
|
218
|
+
// single before_settle nudge); timer wakes use sendNow directly.
|
|
219
|
+
send,
|
|
220
|
+
sendNow,
|
|
136
221
|
});
|
|
137
222
|
// Ralph loop rides the same goal machine + verifier; footer events preserved.
|
|
138
223
|
const ralph = new RalphLoop({
|
|
139
224
|
machine,
|
|
140
225
|
owner,
|
|
141
226
|
ralphDir: () => join(stateDir("long-horizon", "state"), "ralph"),
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
},
|
|
227
|
+
// Iteration prompts ride the arbiter's nudge stash like the goal's.
|
|
228
|
+
send: (message, kind) => send(message, kind, { source: "Ralph", title: "Iteration", synopsis: "Loop iteration prompt" }),
|
|
145
229
|
onEvent: (event) => {
|
|
146
230
|
if (event.type === "loop_start") {
|
|
147
231
|
emitEvent(pi, UNIPI_EVENTS.RALPH_LOOP_START, { name: event.name, iteration: event.iteration, total: event.total });
|
|
@@ -150,6 +234,9 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
150
234
|
} else if (event.type === "loop_end") {
|
|
151
235
|
emitEvent(pi, UNIPI_EVENTS.RALPH_LOOP_END, { name: event.name, reason: event.reason, iterations: event.iterations });
|
|
152
236
|
}
|
|
237
|
+
// User-only progress bar on every loop update.
|
|
238
|
+
const bar = ralphProgressData(ralph);
|
|
239
|
+
if (bar) appendProgress(pi, bar);
|
|
153
240
|
},
|
|
154
241
|
});
|
|
155
242
|
registerRalphTools(pi, ralph);
|
|
@@ -157,7 +244,11 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
157
244
|
registerSwarmTools(pi, { ledger: swarm, owner });
|
|
158
245
|
const graph = new GraphLedger(owner);
|
|
159
246
|
registerGraphTools(pi, { ledger: graph });
|
|
160
|
-
wireRuntime(pi, { machine, toolset, continuation, gate, loadSettings, ralph });
|
|
247
|
+
const runtime = wireRuntime(pi, { machine, toolset, continuation, gate, loadSettings, ralph });
|
|
248
|
+
// Compaction summaries lead with the live goal / ralph state.
|
|
249
|
+
registerCompactionContext("long-horizon", () =>
|
|
250
|
+
longHorizonCompactionBrief(machine.getActive(), ralph.get(), join(stateDir("long-horizon", "state"), "ralph")),
|
|
251
|
+
);
|
|
161
252
|
|
|
162
253
|
// Cross-module entry points: another module (kanboard's runner) can start a
|
|
163
254
|
// goal and read its status without importing this package. Mirrors what the
|
|
@@ -196,9 +287,91 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
196
287
|
if (typeof goalId === "string" && goalId.length > 0 && goal.goalId !== goalId) {
|
|
197
288
|
return { found: false, reason: `the active goal is ${goal.goalId}` };
|
|
198
289
|
}
|
|
199
|
-
return { found: true, goalId: goal.goalId, status: goal.status, objective: goal.objective };
|
|
290
|
+
return { found: true, goalId: goal.goalId, status: goal.status, reason: goal.reason, objective: goal.objective };
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// kanboard runner bridge: pause/resume/stop the goal around task releases
|
|
294
|
+
// and re-claims, so an interrupted task keeps its goal for the next claim.
|
|
295
|
+
registerCommandRunner("unipi:goal-pause", async (_ctx, args) => {
|
|
296
|
+
const goal = machine.get();
|
|
297
|
+
const active = owner.getActive();
|
|
298
|
+
if (!goal || goal.status !== "active" || active?.kind !== "goal") {
|
|
299
|
+
return { ok: false, reason: goal ? `goal is ${goal.status}` : "no goal in this session" };
|
|
300
|
+
}
|
|
301
|
+
const requested = (args as { goalId?: unknown } | undefined)?.goalId;
|
|
302
|
+
if (typeof requested === "string" && requested.length > 0 && requested !== goal.goalId) {
|
|
303
|
+
return { ok: false, reason: `the active goal is ${goal.goalId}` };
|
|
304
|
+
}
|
|
305
|
+
const paused = machine.pause("paused(user_requested)");
|
|
306
|
+
if (!paused) return { ok: false, reason: `goal is ${goal.status}` };
|
|
307
|
+
const parked = owner.suspend("paused(user_requested)");
|
|
308
|
+
if (!parked) {
|
|
309
|
+
// Slot held: the goal stays paused but unowned — resume reactivates it.
|
|
310
|
+
emitEvent(pi, UNIPI_EVENTS.LONG_HORIZON_OWNER_CHANGED, { event: "suspended", kind: "goal" });
|
|
311
|
+
}
|
|
312
|
+
return { ok: true, goalId: paused.goalId, status: paused.status };
|
|
200
313
|
});
|
|
201
|
-
|
|
314
|
+
|
|
315
|
+
registerCommandRunner("unipi:goal-resume", async (_ctx, args) => {
|
|
316
|
+
const goal = machine.get();
|
|
317
|
+
const requested = (args as { goalId?: unknown } | undefined)?.goalId;
|
|
318
|
+
if (!goal) return { ok: false, reason: "no goal in this session" };
|
|
319
|
+
if (goal.status !== "paused") return { ok: false, reason: `goal is ${goal.status}, not paused` };
|
|
320
|
+
if (typeof requested === "string" && requested.length > 0 && requested !== goal.goalId) {
|
|
321
|
+
return { ok: false, reason: `the parked goal is ${goal.goalId}` };
|
|
322
|
+
}
|
|
323
|
+
const resumed = machine.resume();
|
|
324
|
+
if (!resumed) return { ok: false, reason: "goal could not be resumed" };
|
|
325
|
+
if (owner.getParked()) owner.resume();
|
|
326
|
+
gate.setExplicit("goal");
|
|
327
|
+
return { ok: true, goalId: resumed.goalId, status: resumed.status };
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
registerCommandRunner("unipi:goal-stop", async (_ctx, args) => {
|
|
331
|
+
const goal = machine.get();
|
|
332
|
+
const requested = (args as { goalId?: unknown } | undefined)?.goalId;
|
|
333
|
+
if (typeof requested === "string" && requested.length > 0 && goal && requested !== goal.goalId) {
|
|
334
|
+
return { ok: false, reason: `the goal in this session is ${goal.goalId}` };
|
|
335
|
+
}
|
|
336
|
+
const stopped = stopActiveOwner(pi, gate, owner, machine, toolset, "goal");
|
|
337
|
+
return stopped !== undefined
|
|
338
|
+
? { ok: true, goalId: requested || goal?.goalId }
|
|
339
|
+
: { ok: false, reason: goal && goal.status === "complete" ? "goal already stopped" : "no active goal" };
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// kanboard strategy runners: swarm/graph set the explicit mode for the next
|
|
343
|
+
// turn; ralph starts the checklist loop (its own kickoff prompt ships via
|
|
344
|
+
// ralph.start's send — the runner's task prompt lands behind it).
|
|
345
|
+
registerCommandRunner("unipi:lh-explicit", async (_ctx, args) => {
|
|
346
|
+
const mode = String((args as { mode?: unknown } | undefined)?.mode ?? "");
|
|
347
|
+
if (mode !== "swarm" && mode !== "graph" && mode !== "goal" && mode !== "none") {
|
|
348
|
+
return { ok: false, reason: `unknown mode "${mode}"` };
|
|
349
|
+
}
|
|
350
|
+
if (mode !== "none" && owner.getActive() && owner.getActive()?.kind !== mode) {
|
|
351
|
+
return {
|
|
352
|
+
ok: false,
|
|
353
|
+
reason: `the session is owned by a ${owner.getActive()?.kind} owner — finish or suspend it first`,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
gate.setExplicit(mode);
|
|
357
|
+
return { ok: true, mode };
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
registerCommandRunner("unipi:ralph-start", async (_ctx, args) => {
|
|
361
|
+
const a = (args ?? {}) as { name?: unknown; content?: unknown };
|
|
362
|
+
const name = String(a.name ?? "").trim();
|
|
363
|
+
const content = String(a.content ?? "");
|
|
364
|
+
if (!name || !content.trim()) {
|
|
365
|
+
return { ok: false, reason: "name and content are required" };
|
|
366
|
+
}
|
|
367
|
+
return ralph.start(name, content);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
registerLongHorizonCommands(pi, gate, owner, ralph, {
|
|
371
|
+
ralphBar: () => ralphProgressData(ralph),
|
|
372
|
+
estimateGoal: (ctx) => runtime.estimateGoal(ctx),
|
|
373
|
+
goalEstimateOn: () => loadSettings().goalProgress !== "off",
|
|
374
|
+
}, machine, toolset);
|
|
202
375
|
|
|
203
376
|
// Crash recovery: repair, don't resume — reload durable state so the gate
|
|
204
377
|
// reattaches the owner's tool surface; the continuation arms a recovery
|
|
@@ -206,7 +379,10 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
206
379
|
pi.on("session_start", () => {
|
|
207
380
|
const restored = owner.restore();
|
|
208
381
|
machine.restore();
|
|
209
|
-
|
|
382
|
+
// Only a truly drivable goal arms the recovery fragment; a paused goal
|
|
383
|
+
// must come back idle until the user (or the kanboard runner) resumes it.
|
|
384
|
+
const goalStatus = machine.get()?.status;
|
|
385
|
+
if (goalStatus === "active" || goalStatus === "waiting") continuation.armRecovery();
|
|
210
386
|
// Resume (`pi -r`) starts no turn, so before_agent_start never fires. Publish
|
|
211
387
|
// the mode to the shared holder the footer PULLS each render — the active
|
|
212
388
|
// owner's mode if one survived, else the default — so the header restores
|
|
@@ -227,6 +403,7 @@ export default function longHorizon(pi: ExtensionAPI): void {
|
|
|
227
403
|
"unipi:ralph",
|
|
228
404
|
"unipi:swarm",
|
|
229
405
|
"unipi:graph",
|
|
406
|
+
"unipi:regular",
|
|
230
407
|
],
|
|
231
408
|
tools: ["create_goal", "get_goal", "update_goal", "todowrite", "ralph_done", "loop_status", "swarm_report", "swarm_status", "swarm_yield", "update_agent_graph", "graph_output", "view_agent_graph"],
|
|
232
409
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/long-horizon",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.21",
|
|
4
4
|
"description": "Long-horizon execution for Pi — mode-gated /goal /ralph /swarm /graph orchestration with a TypeSafe prompt judge",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"graph"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"test": "tsc --noEmit && npx tsx --test src/__tests__/*.test.ts",
|
|
26
|
+
"test": "tsc --noEmit && UNIPI_FUSION_CHILD= UNIPI_SUBAGENT_CHILD= UNIPI_KANBOARD_CHILD= npx tsx --test src/__tests__/*.test.ts",
|
|
27
27
|
"typecheck": "tsc --noEmit"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
40
|
+
"@pi-unipi/core": "3.0.0-alpha.21"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|