@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
package/packages/unipi/index.ts
CHANGED
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
* mise run unipi
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
13
|
-
import { migrateState, sweepOrphanSessions } from "@pi-unipi/core";
|
|
12
|
+
import type { ExtensionAPI, ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
13
|
+
import { installArbiter, installHarnessProvenance, migrateState, sweepOrphanSessions, withCommandEcho } from "@pi-unipi/core";
|
|
14
|
+
import { withHarnessToolAnnotations } from "@pi-unipi/utility";
|
|
15
|
+
import { readUtilSettings, simpleWrapTool, simpleWrapped, installSimpleGroupEvents } from "@pi-unipi/utility";
|
|
14
16
|
|
|
15
17
|
import workflow from "@pi-unipi/workflow";
|
|
16
18
|
import longHorizon from "@pi-unipi/long-horizon";
|
|
@@ -21,6 +23,7 @@ import backgroundTasks from "@pi-unipi/background-tasks";
|
|
|
21
23
|
import btw from "@pi-unipi/btw/extensions/btw.js";
|
|
22
24
|
import webApi from "@pi-unipi/web-api";
|
|
23
25
|
import utility from "@pi-unipi/utility";
|
|
26
|
+
import skillRegistry from "@pi-unipi/skill-registry";
|
|
24
27
|
import askUser from "@pi-unipi/ask-user";
|
|
25
28
|
import mcp from "@pi-unipi/mcp";
|
|
26
29
|
import notify from "@pi-unipi/notify";
|
|
@@ -30,11 +33,44 @@ import compactor from "@pi-unipi/compactor";
|
|
|
30
33
|
import footer from "@pi-unipi/footer";
|
|
31
34
|
import updater from "@pi-unipi/updater";
|
|
32
35
|
import inputShortcuts from "@pi-unipi/input-shortcuts";
|
|
33
|
-
import image from "@pi-unipi/image";
|
|
34
36
|
import fusion from "@pi-unipi/fusion";
|
|
35
37
|
import watchdog from "@pi-unipi/watchdog";
|
|
36
38
|
|
|
37
39
|
export default function (pi: ExtensionAPI) {
|
|
40
|
+
const api = withCommandEcho(pi);
|
|
41
|
+
// Harness provenance must observe every input/send — install before modules.
|
|
42
|
+
try {
|
|
43
|
+
installHarnessProvenance(api);
|
|
44
|
+
} catch {
|
|
45
|
+
// Provenance is cosmetic; never blocks startup.
|
|
46
|
+
}
|
|
47
|
+
// The turn arbiter must own the single agent_before_settle handler BEFORE
|
|
48
|
+
// any module mounts (idempotent; a no-op in child processes).
|
|
49
|
+
try {
|
|
50
|
+
installArbiter(pi);
|
|
51
|
+
} catch {
|
|
52
|
+
// Never block startup on the arbiter.
|
|
53
|
+
}
|
|
54
|
+
// "simple" render style = mcode transcript: every tool registered by any
|
|
55
|
+
// unipi module is captured here and, after all modules load, re-registered
|
|
56
|
+
// with the collapsed one-liner wrapper (execute/schema untouched; Ctrl+O
|
|
57
|
+
// falls back to the tool's own renderer). best-effort, never blocks load.
|
|
58
|
+
const captured = new Map<string, ToolDefinition<any, any, any>>();
|
|
59
|
+
const rawRegister = api.registerTool.bind(api);
|
|
60
|
+
const registering = new Proxy(api, {
|
|
61
|
+
get(target, prop, receiver) {
|
|
62
|
+
if (prop === "registerTool") {
|
|
63
|
+
return (tool: ToolDefinition<any, any, any>) => {
|
|
64
|
+
// Harness tool-annotation wrapper (idempotent, applied BEFORE the
|
|
65
|
+
// simple-mode wrapper so simpleResult hooks merge).
|
|
66
|
+
const wrapped = withHarnessToolAnnotations(tool);
|
|
67
|
+
captured.set(tool.name, wrapped);
|
|
68
|
+
return rawRegister(wrapped);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return Reflect.get(target, prop, receiver);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
38
74
|
// One-time v3 state relocation into ~/.unipi/{global,workspace}/, then reap
|
|
39
75
|
// any dead-pid session dirs left by crashed sessions. Both are best-effort
|
|
40
76
|
// and version/pid-gated, so they are cheap on every subsequent startup.
|
|
@@ -45,17 +81,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
45
81
|
// Never block startup on housekeeping.
|
|
46
82
|
}
|
|
47
83
|
|
|
48
|
-
const load = (_name: string, extension: (api: ExtensionAPI) => void) => extension(
|
|
84
|
+
const load = (_name: string, extension: (api: ExtensionAPI) => void) => extension(registering);
|
|
49
85
|
|
|
50
86
|
load("workflow", workflow);
|
|
51
87
|
load("long-horizon", longHorizon);
|
|
52
88
|
load("memory", memory);
|
|
53
|
-
// Utility loads BEFORE info-screen: the name badge overlay must be pushed
|
|
54
|
-
// to the BOTTOM of the overlay stack. hideOverlay() pops the topmost entry,
|
|
55
|
-
// and a capturing overlay's done() callback is one-shot — if the badge were
|
|
56
|
-
// stacked above the boot info-screen, the info-screen's auto-close would pop
|
|
57
|
-
// the badge (spending its done()) and strand the dashboard uncloseable.
|
|
58
89
|
load("utility", utility);
|
|
90
|
+
load("skill-registry", skillRegistry);
|
|
59
91
|
load("info-screen", infoScreen);
|
|
60
92
|
load("subagents", subagents);
|
|
61
93
|
load("background-tasks", backgroundTasks);
|
|
@@ -70,7 +102,20 @@ export default function (pi: ExtensionAPI) {
|
|
|
70
102
|
load("footer", footer);
|
|
71
103
|
load("updater", updater);
|
|
72
104
|
load("input-shortcuts", inputShortcuts);
|
|
73
|
-
load("image", image);
|
|
74
105
|
load("fusion", fusion);
|
|
75
106
|
load("watchdog", watchdog);
|
|
107
|
+
|
|
108
|
+
// After all modules registered: apply the mcode-style wrapper. Re-register
|
|
109
|
+
// with the RAW register (not the capturing proxy) to avoid double-capture.
|
|
110
|
+
if (readUtilSettings().render.style === "simple") {
|
|
111
|
+
installSimpleGroupEvents(api);
|
|
112
|
+
for (const def of captured.values()) {
|
|
113
|
+
if (simpleWrapped.has(def)) continue;
|
|
114
|
+
try {
|
|
115
|
+
rawRegister(simpleWrapTool(def));
|
|
116
|
+
} catch {
|
|
117
|
+
// keep the original tool on any failure
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
76
121
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.21",
|
|
4
4
|
"description": "Auto-updater, changelog browser, and readme browser for Unipi — checks npm registry, renders CHANGELOG.md and README.md files in TUI overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.21"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,105 +1,112 @@
|
|
|
1
1
|
# @pi-unipi/utility
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The settings hub, automatic session naming, image tools, pasted-file attachments, `/unipi:answer`, and a few maintenance commands. Also keeps the shared model cache every other module's model picker reads.
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
7
7
|
| Command | Description |
|
|
8
8
|
|---------|-------------|
|
|
9
|
-
| `/unipi:
|
|
10
|
-
| `/unipi:
|
|
11
|
-
| `/unipi:
|
|
12
|
-
| `/unipi:
|
|
13
|
-
| `/unipi:
|
|
14
|
-
| `/unipi:name-badge` | Toggle name badge overlay |
|
|
15
|
-
| `/unipi:settings` | Badge field + "Set/Generate session name" actions (Utility group) |
|
|
16
|
-
| `/unipi:settings` | Hub — badge behavior (Utility group) |
|
|
17
|
-
| `/unipi:prefix-cache` | Show privacy-safe request-prefix transitions and provider cache token counters |
|
|
9
|
+
| `/unipi:settings [search]` | Configure every UniPi module in one panel (global + project scopes); a search term opens it filtered (`/unipi:settings image`). Typing `/settings` lists it before pi's own `/settings` |
|
|
10
|
+
| `/unipi:continue` (`/unipi:retry`) | Take another turn from where the agent stopped, without adding text |
|
|
11
|
+
| `/unipi:cleanup` | Remove stale UniPi temp files and leftovers. Shows what it would remove and asks first; `--dry-run` only lists, `--yes` skips the question |
|
|
12
|
+
| `/unipi:doctor` | Check folders, config, the model cache, the Decision Model key and skill exposure |
|
|
13
|
+
| `/unipi:answer` (`reply`\|`questions`\|`web`) | Answer the agent's last reply without scrolling back and forth |
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
Skill exposure and the skill manager live in `@pi-unipi/skill-registry` (`/unipi:skills`).
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
/unipi:env # Show environment
|
|
23
|
-
/unipi:doctor # Run diagnostics
|
|
24
|
-
/unipi:cleanup # Clean stale files
|
|
25
|
-
/unipi:cleanup --dry-run # Preview what would be cleaned
|
|
26
|
-
/unipi:name-badge # Toggle the session name badge
|
|
27
|
-
/unipi:settings # → Utility → "Generate session name"
|
|
28
|
-
```
|
|
17
|
+
The agent gets the three image tools (below) and nothing else from this package.
|
|
29
18
|
|
|
30
|
-
##
|
|
19
|
+
## Automatic session naming
|
|
31
20
|
|
|
32
|
-
|
|
21
|
+
After each round that finished normally, if you typed the prompt:
|
|
33
22
|
|
|
34
|
-
|
|
23
|
+
1. Greetings, thanks, "ok", "continue" and slash commands are skipped outright.
|
|
24
|
+
2. jev (the Decision Model) answers two short questions: is this a real request with its own subject, and — if the session already has a name — does it move to a different task? Only a confident "yes" renames.
|
|
25
|
+
3. The name is written by a separate throwaway session whose only tool is `rename_session`. It sees the current name and your last few requests, nothing else, and never touches the main session.
|
|
35
26
|
|
|
36
|
-
|
|
27
|
+
A name you set yourself with pi's `/name` is never overwritten. Without a Decision Model key, only an unnamed session gets named, on its first prompt of four words or more.
|
|
37
28
|
|
|
38
|
-
|
|
29
|
+
Inside Herdr, the name is also shown as the pane title and, while the tab still has its default number, the tab label.
|
|
39
30
|
|
|
40
|
-
`/unipi:
|
|
31
|
+
Settings (`/unipi:settings` → Utility → Session name): auto-rename on/off, naming model (defaults to the session model), Herdr sync, and a **Rename now** action.
|
|
41
32
|
|
|
42
|
-
##
|
|
33
|
+
## Answering the last reply
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
|------|-------------|
|
|
46
|
-
| `ctx_env` | Environment inspection for debugging |
|
|
47
|
-
| `set_session_name` | Set the session name for badge display (when badge agent-tool is enabled) |
|
|
35
|
+
`/unipi:answer` opens one of three screens (Settings → Utility → Answer picks the default; `/unipi:answer reply|questions|web` overrides it once, with suggestions as you type):
|
|
48
36
|
|
|
49
|
-
|
|
37
|
+
- **reply** (default) — like `/unipi:btw`, it takes the place of the input area: the agent's last reply in a scrollable view on top, a fixed input box below. ↑↓ scroll the reply while nothing is typed; once you type they move the cursor in your answer, and Alt+↑↓ or PgUp/PgDn scroll instead. Shift+Enter (or Ctrl+J) adds a line, Enter sends it as your next message, Esc goes back to the normal editor with your draft. If the reply asks questions, Tab switches to **questions**.
|
|
38
|
+
- **questions** — pi's editor holding only `Q1. … / A1:` pairs for every question in the reply: each sentence ending in `?`, in full, even when it wraps over several lines (code blocks and URLs are ignored). The cursor starts on the first answer, Tab / Shift+Tab jump between answers, Ctrl+G opens your `$EDITOR`, Enter sends one message that quotes each question above its answer; empty answers are listed as not answered.
|
|
39
|
+
- **web** — a local page with the full reply on the left and one box per question on the right (plus a free-text note), on 127.0.0.1 behind a random URL. Over SSH (detected from `SSH_CONNECTION`/`SSH_TTY`) it doesn't open a browser: it shows the `ssh -L` command, built from this machine's hostname and the port (47321 unless you set one), and the URL to open on your own machine.
|
|
50
40
|
|
|
51
|
-
|
|
41
|
+
When a reply asks questions, a line above the editor says so (`2 questions in the reply — /unipi:answer questions …`) until you send anything. Settings → Utility → Answer → Questions hint turns it off.
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
/unipi:settings # Badge + skills discovery (Utility group)
|
|
55
|
-
```
|
|
43
|
+
## Pasted images and files
|
|
56
44
|
|
|
57
|
-
|
|
45
|
+
Paste a screenshot (Ctrl+V), drag a file into the terminal, or paste a path, and the path in the editor becomes a token: `[Image #1]` for PNG/JPEG/GIF/WebP, `[File #2]` for documents (PDF, text, office files, archives, media). A chip row above the editor lists what's attached, with small previews in terminals that can draw images (Kitty, Ghostty, iTerm2, WezTerm).
|
|
58
46
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
```
|
|
47
|
+
When you send:
|
|
48
|
+
- Images go to the model as real images, in the order their tokens appear.
|
|
49
|
+
- File tokens become `[File #2: /path/to/file]` so the agent can read them.
|
|
50
|
+
- A line under your message in the transcript shows what was attached; the model doesn't see it.
|
|
66
51
|
|
|
67
|
-
|
|
52
|
+
Delete a token to drop its attachment. Only paths that arrive by paste, drop or Ctrl+V are converted; a path you type stays text. Settings → Utility → Attachments turns this or the previews off.
|
|
68
53
|
|
|
69
|
-
|
|
54
|
+
## Image tools
|
|
70
55
|
|
|
71
|
-
|
|
56
|
+
| Tool | What it does |
|
|
57
|
+
|------|--------------|
|
|
58
|
+
| `image_generate` | Text → image |
|
|
59
|
+
| `image_edit` | Image + text → image |
|
|
60
|
+
| `image_recognize` | Image → text with a vision model; only offered while the session model can't see images itself |
|
|
72
61
|
|
|
73
|
-
|
|
74
|
-
- **mode: `all`** — no judging; every skill stays.
|
|
75
|
-
- **mode: `off`** — Unipi's bundled skills are stripped from the catalog (old `discovery: false` behavior).
|
|
62
|
+
Settings → Image has one section per tool. Each model picker only lists models that fit: generation shows models whose output includes images, editing shows models that take an image and output one, recognition shows vision models. The list comes from the shared model cache: pi's registry, OpenRouter's image models (refreshed daily), and a few fal models when a fal key is set.
|
|
76
63
|
|
|
77
|
-
|
|
64
|
+
How a model is called depends on its provider:
|
|
78
65
|
|
|
79
|
-
|
|
66
|
+
| Model | Sent to | Key |
|
|
67
|
+
|-------|---------|-----|
|
|
68
|
+
| `openrouter/…` | OpenRouter (chat with image output) | Settings → Image → Keys, else pi's `/login`, else `OPENROUTER_API_KEY` |
|
|
69
|
+
| `fal/…` | fal.run | Settings → Image → Keys, else `FAL_KEY` / `FAL_API_KEY` |
|
|
70
|
+
| any other pi provider | that provider's endpoint (OpenAI images format) | pi's key for that provider |
|
|
71
|
+
| anything, with a **custom endpoint** set | your base URL, model id sent as typed, format of your choice (OpenAI images, OpenRouter-style, fal) | the endpoint's own key |
|
|
80
72
|
|
|
81
|
-
|
|
82
|
-
{
|
|
83
|
-
"skills": { "mode": "judged", "threshold": 0.3, "maxSkills": 12, "recheck": true }
|
|
84
|
-
}
|
|
85
|
-
```
|
|
73
|
+
Defaults are FLUX.2 [klein] 4B on OpenRouter for both generation and editing, which is cheap and fast. Images are returned inline and saved to `~/.unipi/images/`. When a call fails, the tool reports it as a failure with the missing key or setting spelled out.
|
|
86
74
|
|
|
87
|
-
##
|
|
75
|
+
## Response formatting
|
|
88
76
|
|
|
89
|
-
|
|
90
|
-
|--------|------|-------------|
|
|
91
|
-
| ProcessLifecycle | `lifecycle/process` | Parent PID polling, orphan detection, signal handlers |
|
|
92
|
-
| cleanupStale | `lifecycle/cleanup` | Stale DB/temp/session cleanup with dry-run |
|
|
93
|
-
| AnalyticsCollector | `analytics/collector` | Privacy-respecting event collection with daily rollup |
|
|
94
|
-
| runDiagnostics | `diagnostics/engine` | Cross-module health checks with plugin architecture |
|
|
77
|
+
Settings → Utility → Response formatting → Style changes how pi's built-in `read`, `bash`, `edit` and `write` calls look in the transcript. The model sees exactly the same tools either way; only the drawing changes. It applies after `/reload` (or a restart) — the renderers are registered once when extensions load, so a change made mid-session takes effect on the next reload.
|
|
95
78
|
|
|
96
|
-
|
|
79
|
+
- **simple** — one line per tool, output collapsed:
|
|
80
|
+
```
|
|
81
|
+
▪ Read ./demo/app.py · 5 lines
|
|
82
|
+
▪ Edited ./demo/app.py · +1 -1
|
|
83
|
+
▪ Ran cd demo && ls -la && python3 app.py · 7 output lines
|
|
84
|
+
```
|
|
85
|
+
The live (latest) row shows a ticking timer (`• Running npm test · 12s`) and
|
|
86
|
+
done rows pin the final duration (`· 7 output lines · 3s`). Tools that opt in
|
|
87
|
+
keep their result under the row (`ask_user`'s Q→A) or drive the meta live
|
|
88
|
+
(`run_subagent`'s model · calls · duration · tokens · cost). Sidekick steps
|
|
89
|
+
and other non-pi-tool activity draw with the same verbs/markers.
|
|
90
|
+
- **regular** (default) — pi's own rendering, untouched.
|
|
91
|
+
- **advanced** —
|
|
92
|
+
- Commands are syntax-highlighted. Code embedded in a command is highlighted in its own language: heredoc bodies (`python - <<'PY'`, `cat > x.ts <<EOF`) and `python -c` / `node -e` strings.
|
|
93
|
+
- Output shows its last 10 lines. Whole-output JSON is pretty-printed, test-run summaries (node:test, vitest, cargo, pytest) get a ✓/✗ line, and an exit line shows the code and time.
|
|
94
|
+
- Edits show as a diff with line numbers, syntax colouring by file type, and tinted added/removed lines.
|
|
95
|
+
- Writes and reads are highlighted by file type.
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
Ctrl+O expands anything collapsed in every style. In every style, blank runs
|
|
98
|
+
between transcript blocks are normalized: each block keeps its interior
|
|
99
|
+
spacing, but adjacent blocks are separated by exactly one blank row (pi
|
|
100
|
+
otherwise stacks a block's own padding on top of its leading spacer,
|
|
101
|
+
producing occasional 2–4 blank runs).
|
|
102
|
+
|
|
103
|
+
## Model cache
|
|
104
|
+
|
|
105
|
+
On every session start, utility writes pi's live model list (models with credentials) to `~/.unipi/config/models-cache.json`, with each model's input and output modalities. The settings hub pickers and kanboard read it; `readModelCache()` / `filterModels()` in `@pi-unipi/core` give the same list to any module.
|
|
106
|
+
|
|
107
|
+
## Cleanup safety
|
|
108
|
+
|
|
109
|
+
`/unipi:cleanup` can only remove what its allowlist names: saved tool outputs and `unipi-*` temp files older than 7 days, and the old compactor continuity database. Memory, v2 backups, kanboard boards, config and workspace state are never candidates.
|
|
103
110
|
|
|
104
111
|
## License
|
|
105
112
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/utility",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.21",
|
|
4
4
|
"description": "Utility commands and tools for Pi coding agent — lifecycle, diagnostics, cache, analytics, display, batch execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
39
|
+
"@pi-unipi/core": "3.0.0-alpha.21"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {},
|
|
42
42
|
"peerDependencies": {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: image
|
|
3
|
+
scope: agent
|
|
4
|
+
description: |
|
|
5
|
+
Generate, edit and read images with the image_generate, image_edit and
|
|
6
|
+
image_recognize tools (@pi-unipi/utility). Use when the user asks for a
|
|
7
|
+
picture, icon, illustration, mockup or logo, wants an existing image
|
|
8
|
+
changed, or needs a screenshot/diagram read while the session model
|
|
9
|
+
cannot see images.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Image tools
|
|
13
|
+
|
|
14
|
+
| Tool | Use for |
|
|
15
|
+
|------|---------|
|
|
16
|
+
| `image_generate(prompt, model?)` | A new image from text |
|
|
17
|
+
| `image_edit(prompt, image, model?)` | Change an existing image (`image` = file path, data: URL or base64) |
|
|
18
|
+
| `image_recognize(image, prompt?, model?)` | Read an image with a vision model — only offered while your own model cannot see images |
|
|
19
|
+
|
|
20
|
+
## Prompting
|
|
21
|
+
|
|
22
|
+
- Be concrete: subject, style, composition, lighting, colours, text to render.
|
|
23
|
+
- Say what you want, not what you don't — negation is unreliable.
|
|
24
|
+
- For edits, say what to change AND what to keep; unmentioned details can drift.
|
|
25
|
+
- Images cost money. Generate once, show the result, and only retry when asked.
|
|
26
|
+
|
|
27
|
+
## Models
|
|
28
|
+
|
|
29
|
+
Omit `model` to use the one set in `/unipi:settings` → Image. To override, pass
|
|
30
|
+
`provider/model-id`, e.g. `openrouter/black-forest-labs/flux.2-klein-4b` or
|
|
31
|
+
`fal/fal-ai/flux-2/klein/4b` (edits: `fal/fal-ai/flux-2/klein/4b/edit`).
|
|
32
|
+
|
|
33
|
+
## Results
|
|
34
|
+
|
|
35
|
+
Images come back inline and are saved under `~/.unipi/images/` (path in the
|
|
36
|
+
result). If a call fails, the error says which key or setting is missing —
|
|
37
|
+
tell the user that instead of retrying.
|
|
@@ -2,69 +2,26 @@
|
|
|
2
2
|
name: utility
|
|
3
3
|
scope: agent
|
|
4
4
|
description: |
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
What the @pi-unipi/utility extension does for the user: the /unipi:settings
|
|
6
|
+
hub, /unipi:continue (/unipi:retry), /unipi:cleanup, /unipi:doctor,
|
|
7
|
+
and automatic session naming. It gives the agent no tools.
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# @pi-unipi/utility
|
|
10
|
+
# @pi-unipi/utility
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Commands (user-facing)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
| Command | Purpose |
|
|
15
|
+
|---------|---------|
|
|
16
|
+
| `/unipi:settings` | Configure every UniPi module |
|
|
17
|
+
| `/unipi:continue` / `/unipi:retry` | Take another turn without new text |
|
|
18
|
+
| `/unipi:cleanup` | Remove stale UniPi temp files (previews and asks first; `--dry-run`, `--yes`) |
|
|
19
|
+
| `/unipi:doctor` | Check config, model cache, Decision Model key, skill exposure |
|
|
15
20
|
|
|
16
|
-
##
|
|
21
|
+
## Notes for the agent
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
| `/unipi:cleanup` | Clean stale files, DBs, sessions | When disk space is low or after crashes |
|
|
24
|
-
| `/unipi:env` | Show environment info | For debugging version/path issues |
|
|
25
|
-
| `/unipi:doctor` | Run diagnostics | When something seems broken |
|
|
26
|
-
|
|
27
|
-
### Cleanup Options
|
|
28
|
-
|
|
29
|
-
- `--dry-run` — Report what would be cleaned without removing anything
|
|
30
|
-
- Default max ages: DBs 14 days, temp 7 days, sessions 30 days
|
|
31
|
-
|
|
32
|
-
## Tools
|
|
33
|
-
|
|
34
|
-
| Tool | Purpose |
|
|
35
|
-
|------|---------|
|
|
36
|
-
| `ctx_batch` | Atomic batch execution of commands with rollback |
|
|
37
|
-
| `ctx_env` | Environment inspection |
|
|
38
|
-
|
|
39
|
-
### Batch Execution Pattern
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { BatchBuilder } from "@pi-unipi/utility/tools/batch";
|
|
43
|
-
|
|
44
|
-
const report = await new BatchBuilder()
|
|
45
|
-
.addCommand("search", { query: "foo" })
|
|
46
|
-
.addTool("memory_search", { query: "bar" })
|
|
47
|
-
.withOptions({ failFast: true, commandTimeoutMs: 30000 })
|
|
48
|
-
.execute(myExecutor);
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Modules (for code use)
|
|
52
|
-
|
|
53
|
-
| Module | Import Path | Purpose |
|
|
54
|
-
|--------|-------------|---------|
|
|
55
|
-
| ProcessLifecycle | `@pi-unipi/utility/lifecycle/process` | Parent PID polling, orphan detection, cleanup registry |
|
|
56
|
-
| cleanupStale | `@pi-unipi/utility/lifecycle/cleanup` | Stale file/DB/session cleanup |
|
|
57
|
-
| TTLCache | `@pi-unipi/utility/cache/ttl-cache` | In-memory or SQLite-backed TTL cache |
|
|
58
|
-
| AnalyticsCollector | `@pi-unipi/utility/analytics/collector` | Privacy-respecting event collection |
|
|
59
|
-
| runDiagnostics | `@pi-unipi/utility/diagnostics/engine` | Cross-module health checks |
|
|
60
|
-
| detectCapabilities | `@pi-unipi/utility/display/capabilities` | Terminal feature detection |
|
|
61
|
-
| clampWidth, wrapLines | `@pi-unipi/utility/display/width` | ANSI-aware text formatting |
|
|
62
|
-
| SettingsInspector | `@pi-unipi/utility/tui/settings-inspector` | Reusable settings overlay model |
|
|
63
|
-
|
|
64
|
-
## Integration Notes
|
|
65
|
-
|
|
66
|
-
- Lifecycle manager is a singleton — use `getLifecycle()` to access
|
|
67
|
-
- Analytics collector is a singleton — use `getAnalyticsCollector()`
|
|
68
|
-
- Diagnostics engine supports custom plugins via `registerDiagnosticPlugin()`
|
|
69
|
-
- TTLCache defaults to memory backend; set `persistent: true` for SQLite
|
|
70
|
-
- All modules emit unipi events for cross-module integration
|
|
23
|
+
- There is no tool to rename the session. Naming happens automatically after
|
|
24
|
+
real requests; the user can also use pi's `/name`.
|
|
25
|
+
- Skills not listed in your catalog may still be installed. If the user names
|
|
26
|
+
a skill, read its SKILL.md or ask them to run `/skill:<name>`.
|
|
27
|
+
- When something UniPi-related looks broken, suggest `/unipi:doctor`.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pi-unipi/utility — /unipi:answer: questions in, answers out (pure)
|
|
3
|
+
*
|
|
4
|
+
* Pulls the questions out of the agent's last reply (any line with a "?"
|
|
5
|
+
* outside code blocks, list/heading markers stripped), builds a Q/A template,
|
|
6
|
+
* parses it back, and composes one user message that quotes each question.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const MAX_QUESTIONS = 20;
|
|
10
|
+
|
|
11
|
+
/** Plain text of an assistant message's content. */
|
|
12
|
+
export function messageText(content: unknown): string {
|
|
13
|
+
if (typeof content === "string") return content;
|
|
14
|
+
if (!Array.isArray(content)) return "";
|
|
15
|
+
return content
|
|
16
|
+
.filter((c): c is { type: "text"; text: string } => !!c && typeof c === "object" && (c as { type?: string }).type === "text")
|
|
17
|
+
.map((c) => c.text)
|
|
18
|
+
.join("\n");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function cleanLine(line: string): string {
|
|
22
|
+
return line
|
|
23
|
+
.replace(/^\s*(?:[-*+]|\d+[.)]|#{1,6}|>)\s+/, "")
|
|
24
|
+
.replace(/\*\*|__|`/g, "")
|
|
25
|
+
.replace(/\s+/g, " ")
|
|
26
|
+
.trim();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Questions in a reply. Lines are first joined into paragraphs (a question
|
|
31
|
+
* that wraps over several source lines stays whole), list items and headings
|
|
32
|
+
* each start their own paragraph, code blocks are skipped, and every sentence
|
|
33
|
+
* ending in "?" becomes one question — in full, never truncated.
|
|
34
|
+
*/
|
|
35
|
+
export function extractQuestions(text: string): string[] {
|
|
36
|
+
const paragraphs: string[] = [];
|
|
37
|
+
let current: string[] = [];
|
|
38
|
+
let fenced = false;
|
|
39
|
+
const flush = () => {
|
|
40
|
+
if (current.length) paragraphs.push(current.join(" "));
|
|
41
|
+
current = [];
|
|
42
|
+
};
|
|
43
|
+
for (const raw of text.split("\n")) {
|
|
44
|
+
if (/^\s*(```|~~~)/.test(raw)) {
|
|
45
|
+
flush();
|
|
46
|
+
fenced = !fenced;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (fenced) continue;
|
|
50
|
+
if (!raw.trim()) {
|
|
51
|
+
flush();
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
// A new list item / heading / quote starts a new paragraph.
|
|
55
|
+
if (/^\s*(?:[-*+]|\d+[.)]|#{1,6}|>)\s+/.test(raw)) flush();
|
|
56
|
+
current.push(raw);
|
|
57
|
+
}
|
|
58
|
+
flush();
|
|
59
|
+
|
|
60
|
+
const out: string[] = [];
|
|
61
|
+
for (const para of paragraphs) {
|
|
62
|
+
const clean = cleanLine(para);
|
|
63
|
+
if (!clean.includes("?")) continue;
|
|
64
|
+
// A "?" inside a URL (query string) is not a question: park URLs as tokens.
|
|
65
|
+
const urls: string[] = [];
|
|
66
|
+
const masked = clean.replace(/https?:\/\/\S+/g, (u) => `\u0000${urls.push(u) - 1}\u0000`);
|
|
67
|
+
if (!masked.includes("?")) continue;
|
|
68
|
+
for (const sentence of masked.match(/[^.!?]*(?:[.!](?!\s|$)[^.!?]*)*\?+/g) ?? []) {
|
|
69
|
+
const q = sentence.replace(/\u0000(\d+)\u0000/g, (_m, i: string) => urls[Number(i)] ?? "").trim();
|
|
70
|
+
if (q.length < 4 || out.includes(q)) continue;
|
|
71
|
+
out.push(q);
|
|
72
|
+
if (out.length >= MAX_QUESTIONS) return out;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Q/A pairs, nothing else in the buffer; no questions → an empty buffer. */
|
|
79
|
+
export function buildTemplate(questions: readonly string[]): string {
|
|
80
|
+
if (questions.length === 0) return "";
|
|
81
|
+
return questions.flatMap((q, i) => [`Q${i + 1}. ${q}`, `A${i + 1}: `, ""]).join("\n").trimEnd() + " ";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Answers by question index (0-based); missing/empty → "". */
|
|
85
|
+
export function parseTemplate(text: string, count: number): string[] {
|
|
86
|
+
if (count === 0) return [text.trim()];
|
|
87
|
+
const answers: string[] = Array.from({ length: count }, () => "");
|
|
88
|
+
let current = -1;
|
|
89
|
+
const buf: string[][] = answers.map(() => []);
|
|
90
|
+
for (const line of text.split("\n")) {
|
|
91
|
+
if (/^Q\d+\.\s/.test(line)) {
|
|
92
|
+
current = -1;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const a = line.match(/^A(\d+):\s?(.*)$/);
|
|
96
|
+
if (a) {
|
|
97
|
+
const idx = Number(a[1]) - 1;
|
|
98
|
+
current = idx >= 0 && idx < buf.length ? idx : -1;
|
|
99
|
+
if (current >= 0) buf[current]!.push(a[2]!);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (current >= 0) buf[current]!.push(line);
|
|
103
|
+
}
|
|
104
|
+
return buf.map((lines) => lines.join("\n").trim());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** One user message; undefined when nothing was answered. */
|
|
108
|
+
export function composeAnswers(questions: readonly string[], answers: readonly string[], note = ""): string | undefined {
|
|
109
|
+
const parts: string[] = [];
|
|
110
|
+
const skipped: number[] = [];
|
|
111
|
+
if (questions.length === 0) {
|
|
112
|
+
const text = [answers[0] ?? "", note].map((s) => s.trim()).filter(Boolean).join("\n\n");
|
|
113
|
+
return text || undefined;
|
|
114
|
+
}
|
|
115
|
+
questions.forEach((q, i) => {
|
|
116
|
+
const a = (answers[i] ?? "").trim();
|
|
117
|
+
if (!a) {
|
|
118
|
+
skipped.push(i + 1);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
parts.push(`${i + 1}. > ${q}\n\n${a}`);
|
|
122
|
+
});
|
|
123
|
+
if (parts.length === 0 && !note.trim()) return undefined;
|
|
124
|
+
const lines = [parts.join("\n\n")];
|
|
125
|
+
if (note.trim()) lines.push(note.trim());
|
|
126
|
+
if (skipped.length) lines.push(`(Not answered: ${skipped.map((n) => `#${n}`).join(", ")})`);
|
|
127
|
+
return lines.filter(Boolean).join("\n\n");
|
|
128
|
+
}
|