@pi-unipi/unipi 3.0.0-alpha.2 → 3.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +292 -0
- package/README.md +8 -11
- package/docs/prefix-cache-architecture.md +14 -0
- package/package.json +22 -24
- package/packages/ask-user/README.md +55 -107
- package/packages/ask-user/ask-ui.ts +306 -732
- package/packages/ask-user/clipboard.ts +50 -0
- package/packages/ask-user/config.ts +74 -78
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/questions.ts +151 -0
- package/packages/ask-user/skills/ask-user/SKILL.md +59 -133
- package/packages/ask-user/tools.ts +198 -432
- package/packages/autocomplete/package.json +1 -1
- package/packages/autocomplete/src/constants.ts +38 -43
- package/packages/autocomplete/src/sorting.ts +8 -0
- package/packages/background-tasks/package.json +2 -2
- package/packages/background-tasks/src/config.ts +0 -73
- package/packages/background-tasks/src/index.ts +20 -16
- package/packages/background-tasks/src/registry.ts +1 -171
- package/packages/background-tasks/src/types.ts +0 -32
- package/packages/btw/README.md +13 -56
- package/packages/btw/extensions/btw.ts +403 -1796
- package/packages/btw/package.json +5 -2
- package/packages/btw/skills/btw/SKILL.md +7 -143
- package/packages/compactor/README.md +56 -287
- package/packages/compactor/package.json +5 -9
- package/packages/compactor/skills/compactor/SKILL.md +13 -20
- package/packages/compactor/src/card.ts +90 -0
- package/packages/compactor/src/commands/index.ts +73 -130
- package/packages/compactor/src/compaction/compact-args.ts +5 -3
- package/packages/compactor/src/compaction/filter-noise.ts +1 -1
- package/packages/compactor/src/compaction/hooks.ts +487 -311
- package/packages/compactor/src/compaction/source.ts +178 -0
- package/packages/compactor/src/compaction/summarize.ts +586 -52
- package/packages/compactor/src/config/manager.ts +130 -127
- package/packages/compactor/src/config/schema.ts +32 -48
- package/packages/compactor/src/index.ts +40 -431
- package/packages/compactor/src/info-screen.ts +44 -190
- package/packages/compactor/src/session/recall-blocks.ts +1 -1
- package/packages/compactor/src/stats.ts +76 -0
- package/packages/compactor/src/tools/context-budget.ts +17 -34
- package/packages/compactor/src/tools/ctx-doctor.ts +45 -36
- package/packages/compactor/src/tools/register.ts +29 -269
- package/packages/compactor/src/types.ts +47 -186
- package/packages/core/README.md +25 -0
- package/packages/core/child-agent.ts +1 -0
- package/packages/core/command-echo.ts +63 -0
- package/packages/core/compaction-context.ts +41 -0
- package/packages/core/constants.ts +8 -38
- package/packages/core/events.ts +0 -53
- package/packages/core/fusion-status.ts +4 -0
- package/packages/core/global.d.ts +10 -0
- package/packages/core/harness-messages.ts +392 -0
- package/packages/core/index.ts +14 -0
- package/packages/core/kanboard-status.ts +49 -0
- package/packages/core/long-horizon-owner-status.ts +46 -0
- package/packages/core/model-cache.ts +81 -7
- package/packages/core/package.json +6 -3
- package/packages/core/src/attach/detect.ts +163 -0
- package/packages/core/src/child-agent/child-args.ts +31 -0
- package/packages/core/src/child-agent/delivery.ts +41 -0
- package/packages/core/src/child-agent/index.ts +5 -0
- package/packages/core/src/child-agent/readers.ts +203 -0
- package/packages/core/src/child-agent/runtime.ts +584 -0
- package/packages/core/src/evidence.ts +78 -0
- package/packages/core/src/hints/browser.ts +278 -0
- package/packages/core/src/hints/crab-data.ts +19 -0
- package/packages/core/src/hints/index.ts +865 -0
- package/packages/core/src/hints/lines.ts +607 -0
- package/packages/core/src/hints/store.ts +120 -0
- package/packages/core/src/jev/chatter.ts +24 -0
- package/packages/core/src/jev/settings.ts +177 -14
- package/packages/core/src/package-colors.ts +2 -0
- package/packages/core/src/settings/catalog.ts +39 -15
- package/packages/core/src/settings/engine.ts +48 -2
- package/packages/core/src/settings/hub.ts +83 -20
- package/packages/core/src/settings/open.ts +49 -0
- package/packages/core/src/settings/schema.ts +27 -7
- package/packages/core/src/tui/hub-kit.ts +18 -5
- package/packages/core/src/tui/kit.ts +198 -0
- package/packages/core/src/tui/progress.ts +73 -0
- package/packages/core/src/turn/arbiter.ts +290 -0
- package/packages/footer/README.md +4 -6
- package/packages/footer/package.json +3 -3
- package/packages/footer/src/glance-editor.ts +19 -11
- package/packages/footer/src/help.ts +1 -1
- package/packages/footer/src/index.ts +36 -3
- package/packages/footer/src/presets.ts +3 -4
- package/packages/footer/src/rendering/icons.ts +0 -20
- package/packages/footer/src/segments/compactor.ts +52 -142
- package/packages/footer/src/segments/status-ext.ts +0 -1
- package/packages/fusion/README.md +14 -4
- package/packages/fusion/package.json +4 -3
- package/packages/fusion/src/child-args.ts +1 -0
- package/packages/fusion/src/index.ts +161 -8
- package/packages/fusion/src/pi-settings.ts +57 -0
- package/packages/fusion/src/picker.ts +186 -51
- package/packages/fusion/src/preset.ts +56 -2
- package/packages/fusion/src/prompts.ts +1 -1
- package/packages/fusion/src/sidekick-runtime.ts +1 -420
- package/packages/fusion/src/tools.ts +107 -128
- package/packages/fusion/src/transcript.ts +27 -85
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/README.md +18 -30
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/input-shortcuts/src/burst.ts +88 -0
- package/packages/input-shortcuts/src/chord-overlay.ts +20 -70
- package/packages/input-shortcuts/src/cleared-input.ts +97 -0
- package/packages/input-shortcuts/src/index.ts +99 -193
- package/packages/input-shortcuts/src/last-response.ts +40 -0
- package/packages/input-shortcuts/src/registers.ts +8 -23
- package/packages/input-shortcuts/src/types.ts +4 -16
- package/packages/input-shortcuts/src/undo-redo.ts +59 -47
- package/packages/kanboard/README.md +51 -47
- package/packages/kanboard/index.ts +293 -55
- package/packages/kanboard/package.json +8 -8
- package/packages/kanboard/skills/kanboard/SKILL.md +61 -27
- package/packages/kanboard/src/badges.ts +93 -0
- package/packages/kanboard/src/bin.ts +4 -2
- package/packages/kanboard/src/commands.ts +218 -84
- package/packages/kanboard/src/debug.ts +20 -0
- package/packages/kanboard/src/guard.ts +267 -109
- package/packages/kanboard/src/monitor.ts +330 -0
- package/packages/kanboard/src/notice-buffer.ts +74 -0
- package/packages/kanboard/src/progress.ts +27 -0
- package/packages/kanboard/src/reminders.ts +234 -0
- package/packages/kanboard/src/settings.ts +69 -15
- package/packages/kanboard/src/shapes.ts +5 -0
- package/packages/long-horizon/index.ts +190 -13
- package/packages/long-horizon/package.json +3 -3
- package/packages/long-horizon/src/commands.ts +103 -7
- package/packages/long-horizon/src/compaction-brief.ts +35 -0
- package/packages/long-horizon/src/engine/continuation.ts +84 -15
- package/packages/long-horizon/src/engine/goal-state.ts +64 -13
- package/packages/long-horizon/src/engine/nudge-stash.ts +71 -0
- package/packages/long-horizon/src/engine/ralph.ts +3 -2
- package/packages/long-horizon/src/engine/runaway.ts +68 -11
- package/packages/long-horizon/src/engine/verifier.ts +19 -0
- package/packages/long-horizon/src/gate.ts +37 -12
- package/packages/long-horizon/src/judge/resolve.ts +1 -0
- package/packages/long-horizon/src/owner.ts +35 -2
- package/packages/long-horizon/src/progress.ts +87 -0
- package/packages/long-horizon/src/prompts/goal.ts +1 -1
- package/packages/long-horizon/src/runtime.ts +172 -18
- package/packages/long-horizon/src/settings.ts +54 -39
- package/packages/long-horizon/src/tools/goal.ts +6 -0
- package/packages/long-horizon/src/tools/graph.ts +1 -1
- package/packages/long-horizon/src/tools/swarm.ts +3 -3
- package/packages/mcp/package.json +2 -2
- package/packages/memory/commands.ts +7 -2
- package/packages/memory/index.ts +210 -32
- package/packages/memory/package.json +3 -3
- package/packages/memory/save-session.ts +264 -0
- package/packages/memory/settings.ts +17 -0
- package/packages/memory/tools.ts +253 -203
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/README.md +53 -16
- package/packages/skill-registry/index.ts +230 -0
- package/packages/skill-registry/package.json +19 -8
- package/packages/skill-registry/src/editor.ts +206 -0
- package/packages/skill-registry/src/judge.ts +289 -0
- package/packages/skill-registry/src/registry.ts +87 -0
- package/packages/skill-registry/src/settings.ts +259 -0
- package/packages/skill-registry/src/vault.ts +80 -0
- package/packages/subagents/README.md +39 -119
- package/packages/subagents/package.json +6 -13
- package/packages/subagents/skills/subagents/SKILL.md +18 -42
- package/packages/subagents/src/agents.ts +213 -0
- package/packages/subagents/src/cards.ts +182 -0
- package/packages/subagents/src/index.ts +609 -1084
- package/packages/subagents/src/manager.ts +429 -0
- package/packages/subagents/src/profiles.ts +130 -0
- package/packages/subagents/src/transcript.ts +154 -0
- package/packages/subagents/src/ui.ts +389 -0
- package/packages/unipi/bundled.js +39756 -45569
- package/packages/unipi/index.ts +55 -10
- package/packages/updater/package.json +2 -2
- package/packages/utility/README.md +76 -69
- package/packages/utility/package.json +2 -2
- package/packages/utility/skills/image/SKILL.md +37 -0
- package/packages/utility/skills/utility/SKILL.md +17 -60
- package/packages/utility/src/answer/extract.ts +128 -0
- package/packages/utility/src/answer/index.ts +213 -0
- package/packages/utility/src/answer/reply.ts +133 -0
- package/packages/utility/src/answer/web.ts +167 -0
- package/packages/utility/src/attach/index.ts +205 -0
- package/packages/utility/src/commands.ts +38 -142
- package/packages/utility/src/diagnostics/engine.ts +50 -5
- package/packages/utility/src/image/index.ts +33 -0
- package/packages/utility/src/image/models.ts +221 -0
- package/packages/{image/src → utility/src/image}/recognize.ts +2 -2
- package/packages/utility/src/image/settings.ts +178 -0
- package/packages/{image/src/image-source.ts → utility/src/image/source.ts} +1 -1
- package/packages/utility/src/image/tools.ts +168 -0
- package/packages/utility/src/image/transports.ts +186 -0
- package/packages/utility/src/index.ts +68 -389
- package/packages/utility/src/lifecycle/cleanup.ts +116 -311
- package/packages/utility/src/rename/gate.ts +102 -0
- package/packages/utility/src/rename/index.ts +191 -0
- package/packages/utility/src/rename/session.ts +170 -0
- package/packages/utility/src/render/delegated.ts +285 -0
- package/packages/utility/src/render/harness.ts +683 -0
- package/packages/utility/src/render/parse.ts +156 -0
- package/packages/utility/src/render/pi-settings.ts +38 -0
- package/packages/utility/src/render/reply-bg.ts +307 -0
- package/packages/utility/src/render/simple.ts +724 -0
- package/packages/utility/src/render/spacing.ts +235 -0
- package/packages/utility/src/render/styled.ts +251 -0
- package/packages/utility/src/render/tools.ts +353 -0
- package/packages/utility/src/settings.ts +166 -233
- package/packages/utility/src/types.ts +1 -222
- package/packages/watchdog/index.ts +17 -6
- package/packages/watchdog/package.json +3 -3
- package/packages/watchdog/src/config.ts +3 -2
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/README.md +3 -0
- package/packages/workflow/index.ts +0 -2
- package/packages/workflow/package.json +2 -2
- package/packages/workflow/src/permission/decide.ts +6 -4
- package/packages/workflow/src/permission/index.ts +17 -7
- package/packages/workflow/src/permission/settings.ts +39 -4
- package/packages/workflow/src/plan/index.ts +19 -4
- package/packages/background-tasks/extensions/delegate-child.ts +0 -1
- package/packages/background-tasks/src/context-parent-snapshot.ts +0 -142
- package/packages/background-tasks/src/context-token-budget.ts +0 -903
- package/packages/background-tasks/src/context-visible-conversation-v2.ts +0 -551
- package/packages/background-tasks/src/delegate/artifacts.ts +0 -487
- package/packages/background-tasks/src/delegate/budget.ts +0 -415
- package/packages/background-tasks/src/delegate/hook-contract-evidence.json +0 -18
- package/packages/background-tasks/src/delegate/hook-contract.ts +0 -154
- package/packages/background-tasks/src/delegate/launch.ts +0 -484
- package/packages/background-tasks/src/delegate/result-package.ts +0 -459
- package/packages/background-tasks/src/delegate/runner.ts +0 -430
- package/packages/background-tasks/src/delegate/seed.ts +0 -423
- package/packages/background-tasks/src/delegate/types.ts +0 -323
- package/packages/background-tasks/src/delegate-child-extension.ts +0 -978
- package/packages/background-tasks/src/delegate-extension.ts +0 -654
- package/packages/background-tasks/src/fixtures/delegate-context-incident.json +0 -17
- package/packages/compactor/skills/compactor-detail/SKILL.md +0 -116
- package/packages/compactor/skills/compactor-doctor/SKILL.md +0 -71
- package/packages/compactor/skills/compactor-stats/SKILL.md +0 -51
- package/packages/compactor/src/compaction/build-sections.ts +0 -76
- package/packages/compactor/src/compaction/extract/goals.ts +0 -36
- package/packages/compactor/src/compaction/extract/preferences.ts +0 -40
- package/packages/compactor/src/compaction/format.ts +0 -53
- package/packages/compactor/src/compaction/merge.ts +0 -143
- package/packages/compactor/src/config/presets.ts +0 -160
- package/packages/compactor/src/executor/executor.ts +0 -233
- package/packages/compactor/src/executor/runtime.ts +0 -115
- package/packages/compactor/src/security/evaluator.ts +0 -89
- package/packages/compactor/src/security/policy.ts +0 -96
- package/packages/compactor/src/security/scanner.ts +0 -65
- package/packages/compactor/src/session/auto-inject.ts +0 -60
- package/packages/compactor/src/session/db.ts +0 -325
- package/packages/compactor/src/session/extract.ts +0 -144
- package/packages/compactor/src/session/resume-inject.ts +0 -64
- package/packages/compactor/src/session/snapshot.ts +0 -327
- package/packages/compactor/src/tools/ctx-batch-execute.ts +0 -41
- package/packages/compactor/src/tools/ctx-execute-file.ts +0 -23
- package/packages/compactor/src/tools/ctx-execute.ts +0 -23
- package/packages/compactor/src/tools/ctx-stats.ts +0 -96
- package/packages/image/README.md +0 -99
- package/packages/image/package.json +0 -61
- package/packages/image/skills/image/SKILL.md +0 -76
- package/packages/image/src/generate.ts +0 -256
- package/packages/image/src/index.ts +0 -135
- package/packages/image/src/models.ts +0 -519
- package/packages/image/src/openai-images-api.ts +0 -282
- package/packages/image/src/register-providers.ts +0 -209
- package/packages/image/src/settings.ts +0 -173
- package/packages/image/src/tools.ts +0 -326
- package/packages/input-shortcuts/src/clipboard.ts +0 -119
- package/packages/kanboard/src/runner.ts +0 -817
- package/packages/skill-registry/skills/auto/SKILL.md +0 -465
- package/packages/skill-registry/skills/brainstorm/SKILL.md +0 -219
- package/packages/skill-registry/skills/chore-create/SKILL.md +0 -315
- package/packages/skill-registry/skills/chore-execute/SKILL.md +0 -314
- package/packages/skill-registry/skills/consolidate/SKILL.md +0 -142
- package/packages/skill-registry/skills/consultant/SKILL.md +0 -97
- package/packages/skill-registry/skills/debug/SKILL.md +0 -228
- package/packages/skill-registry/skills/document/SKILL.md +0 -120
- package/packages/skill-registry/skills/fix/SKILL.md +0 -212
- package/packages/skill-registry/skills/gather-context/SKILL.md +0 -145
- package/packages/skill-registry/skills/plan/SKILL.md +0 -231
- package/packages/skill-registry/skills/quick-fix/SKILL.md +0 -135
- package/packages/skill-registry/skills/quick-work/SKILL.md +0 -110
- package/packages/skill-registry/skills/research/SKILL.md +0 -251
- package/packages/skill-registry/skills/review-work/SKILL.md +0 -187
- package/packages/skill-registry/skills/scan-issues/SKILL.md +0 -195
- package/packages/skill-registry/skills/work/SKILL.md +0 -218
- package/packages/skill-registry/skills/worktree-create/SKILL.md +0 -69
- package/packages/skill-registry/skills/worktree-list/SKILL.md +0 -78
- package/packages/skill-registry/skills/worktree-merge/SKILL.md +0 -89
- package/packages/subagents/agents/delegate.md +0 -14
- package/packages/subagents/agents/oracle.md +0 -78
- package/packages/subagents/agents/researcher.md +0 -52
- package/packages/subagents/agents/reviewer.md +0 -80
- package/packages/subagents/agents/scout.md +0 -50
- package/packages/subagents/agents/worker.md +0 -59
- package/packages/subagents/prompts/council.md +0 -48
- package/packages/subagents/prompts/gather-context-and-clarify.md +0 -13
- package/packages/subagents/prompts/parallel-cleanup.md +0 -59
- package/packages/subagents/prompts/parallel-research.md +0 -50
- package/packages/subagents/prompts/parallel-review.md +0 -54
- package/packages/subagents/prompts/review-loop.md +0 -43
- package/packages/subagents/skills/council-mode/SKILL.md +0 -230
- package/packages/subagents/skills/subagents/references/constraints-and-recipes.md +0 -259
- package/packages/subagents/skills/subagents/references/execution-controls.md +0 -454
- package/packages/subagents/skills/subagents/references/management-authoring-rpc.md +0 -161
- package/packages/subagents/skills/subagents/references/multi-lane-orchestration.md +0 -39
- package/packages/subagents/skills/subagents/references/prompting-and-roles.md +0 -267
- package/packages/subagents/src/acceptance.ts +0 -331
- package/packages/subagents/src/agent-manager.ts +0 -405
- package/packages/subagents/src/agent-memory.ts +0 -300
- package/packages/subagents/src/agent-overrides.ts +0 -183
- package/packages/subagents/src/agent-runner.ts +0 -271
- package/packages/subagents/src/async-runner.ts +0 -422
- package/packages/subagents/src/authority-policy.ts +0 -47
- package/packages/subagents/src/budgets.ts +0 -285
- package/packages/subagents/src/child-safety.ts +0 -140
- package/packages/subagents/src/config.ts +0 -249
- package/packages/subagents/src/conversation-viewer.ts +0 -281
- package/packages/subagents/src/core-compat.ts +0 -94
- package/packages/subagents/src/custom-agents.ts +0 -343
- package/packages/subagents/src/file-system-retry.ts +0 -50
- package/packages/subagents/src/fleet-data.ts +0 -105
- package/packages/subagents/src/fleet-view.ts +0 -322
- package/packages/subagents/src/foreground-detach.ts +0 -59
- package/packages/subagents/src/fork-context.ts +0 -285
- package/packages/subagents/src/global.d.ts +0 -7
- package/packages/subagents/src/guide.ts +0 -129
- package/packages/subagents/src/mission-state.ts +0 -133
- package/packages/subagents/src/mission-store.ts +0 -436
- package/packages/subagents/src/output-limits.ts +0 -142
- package/packages/subagents/src/parity-types.ts +0 -315
- package/packages/subagents/src/pi-args.ts +0 -167
- package/packages/subagents/src/result-files.ts +0 -232
- package/packages/subagents/src/result-watcher.ts +0 -221
- package/packages/subagents/src/retained-children.ts +0 -176
- package/packages/subagents/src/run-fanout-budget.ts +0 -356
- package/packages/subagents/src/scheduled-runs.ts +0 -349
- package/packages/subagents/src/schemas.ts +0 -263
- package/packages/subagents/src/slash-commands.ts +0 -80
- package/packages/subagents/src/supervisor-channel.ts +0 -249
- package/packages/subagents/src/tool-handler.ts +0 -1144
- package/packages/subagents/src/types.ts +0 -238
- package/packages/subagents/src/widget.ts +0 -457
- package/packages/subagents/src/workflow-script.ts +0 -737
- package/packages/subagents/src/workflow-worker.ts +0 -384
- package/packages/subagents/src/worktree.ts +0 -614
- package/packages/utility/src/analytics/collector.ts +0 -293
- package/packages/utility/src/info-screen.ts +0 -80
- package/packages/utility/src/lifecycle/process.ts +0 -162
- package/packages/utility/src/prefix-cache.ts +0 -263
- package/packages/utility/src/skill-discovery.ts +0 -542
- package/packages/utility/src/tools/env.ts +0 -113
- package/packages/utility/src/tui/name-badge-state.ts +0 -315
- package/packages/utility/src/tui/name-badge.ts +0 -109
- /package/packages/{subagents/src → core/src/child-agent}/pi-spawn.ts +0 -0
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @pi-unipi/image — Agent tool registration
|
|
3
|
-
*
|
|
4
|
-
* Registers `image_generate` and `image_recognize`. Each tool is registered
|
|
5
|
-
* only when enabled in config, so a user who wants just one does not have the
|
|
6
|
-
* other consuming context in the system prompt.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { Type } from "typebox";
|
|
10
|
-
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
11
|
-
import { IMAGE_TOOLS } from "@pi-unipi/core";
|
|
12
|
-
|
|
13
|
-
import { generateImage } from "./generate.js";
|
|
14
|
-
import { loadImage } from "./image-source.js";
|
|
15
|
-
import { registerRegistryImageProviders } from "./register-providers.js";
|
|
16
|
-
import {
|
|
17
|
-
findProviderBaseUrl,
|
|
18
|
-
formatModelRef,
|
|
19
|
-
listAllImageGenModels,
|
|
20
|
-
resolveImageGenModel,
|
|
21
|
-
resolveVisionModel,
|
|
22
|
-
type ChatModelRegistry,
|
|
23
|
-
type VisionModel,
|
|
24
|
-
} from "./models.js";
|
|
25
|
-
import { recognizeImage } from "./recognize.js";
|
|
26
|
-
import { getOutputDir, loadConfig } from "./settings.js";
|
|
27
|
-
|
|
28
|
-
/** Error shape shared by both tools. */
|
|
29
|
-
function errorResult(message: string) {
|
|
30
|
-
return {
|
|
31
|
-
content: [{ type: "text" as const, text: message }],
|
|
32
|
-
isError: true,
|
|
33
|
-
details: {},
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function messageOf(error: unknown): string {
|
|
38
|
-
return error instanceof Error ? error.message : String(error);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Read the chat model registry off the extension context. */
|
|
42
|
-
function getRegistry(ctx: ExtensionContext): ChatModelRegistry | undefined {
|
|
43
|
-
return (ctx as unknown as { modelRegistry?: ChatModelRegistry }).modelRegistry;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Resolve an API key for a provider through pi's auth storage. */
|
|
47
|
-
async function resolveApiKey(
|
|
48
|
-
registry: ChatModelRegistry | undefined,
|
|
49
|
-
provider: string,
|
|
50
|
-
): Promise<string | undefined> {
|
|
51
|
-
try {
|
|
52
|
-
const key = await registry?.getApiKeyForProvider?.(provider);
|
|
53
|
-
if (key) return key;
|
|
54
|
-
} catch {
|
|
55
|
-
// Fall through to the environment.
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const envName = `${provider.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_API_KEY`;
|
|
59
|
-
return process.env[envName] || undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Look up the full pi-ai model object for a vision model. */
|
|
63
|
-
function findChatModel(
|
|
64
|
-
registry: ChatModelRegistry,
|
|
65
|
-
model: VisionModel,
|
|
66
|
-
): { baseUrl?: string; api?: string } | undefined {
|
|
67
|
-
try {
|
|
68
|
-
return registry.find(model.provider, model.id) as
|
|
69
|
-
| { baseUrl?: string; api?: string }
|
|
70
|
-
| undefined;
|
|
71
|
-
} catch {
|
|
72
|
-
return undefined;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function registerImageTools(pi: ExtensionAPI): void {
|
|
77
|
-
const config = loadConfig();
|
|
78
|
-
|
|
79
|
-
if (config.generate.enabled) registerGenerateTool(pi);
|
|
80
|
-
if (config.recognize.enabled) registerRecognizeTool(pi);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function registerGenerateTool(pi: ExtensionAPI): void {
|
|
84
|
-
pi.registerTool({
|
|
85
|
-
name: IMAGE_TOOLS.GENERATE,
|
|
86
|
-
label: "Generate Image",
|
|
87
|
-
description:
|
|
88
|
-
"Generate an image from a text prompt, or edit an existing image by " +
|
|
89
|
-
"passing `image`. The result is returned inline and, when enabled, saved to disk.",
|
|
90
|
-
promptSnippet: "Generate an image from a text prompt.",
|
|
91
|
-
promptGuidelines: [
|
|
92
|
-
"Use image_generate to create images from a text description.",
|
|
93
|
-
"Write a detailed prompt — subject, style, composition and lighting all help.",
|
|
94
|
-
"Pass `image` to edit an existing image instead of generating a new one.",
|
|
95
|
-
"Editing regenerates the whole image, so unmentioned details may change.",
|
|
96
|
-
"Describe what you DO want; negation is unreliable in image models.",
|
|
97
|
-
"Omit model to use the one configured in /unipi:settings.",
|
|
98
|
-
"Generated images cost money per call; do not regenerate without being asked.",
|
|
99
|
-
],
|
|
100
|
-
parameters: Type.Object({
|
|
101
|
-
prompt: Type.String({
|
|
102
|
-
description: "Description of the image to generate. Be specific.",
|
|
103
|
-
}),
|
|
104
|
-
image: Type.Optional(
|
|
105
|
-
Type.String({
|
|
106
|
-
description:
|
|
107
|
-
"Source image to edit: a local file path, data: URL, or base64 data. " +
|
|
108
|
-
"When set, the model edits this image instead of generating from scratch.",
|
|
109
|
-
}),
|
|
110
|
-
),
|
|
111
|
-
model: Type.Optional(
|
|
112
|
-
Type.String({
|
|
113
|
-
description:
|
|
114
|
-
'Image model override, e.g. "flux.2-pro" or ' +
|
|
115
|
-
'"openrouter/google/gemini-3-pro-image". Omit to use the configured default.',
|
|
116
|
-
}),
|
|
117
|
-
),
|
|
118
|
-
}),
|
|
119
|
-
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
120
|
-
try {
|
|
121
|
-
const config = loadConfig();
|
|
122
|
-
const registry = getRegistry(ctx);
|
|
123
|
-
// Bridge pi's own providers into pi-ai's images collection so the user
|
|
124
|
-
// is not forced onto OpenRouter. Idempotent and best-effort.
|
|
125
|
-
await registerRegistryImageProviders(registry);
|
|
126
|
-
// Include image models contributed by registered providers, so the
|
|
127
|
-
// tool can resolve anything the settings picker offers.
|
|
128
|
-
const models = await listAllImageGenModels(registry);
|
|
129
|
-
|
|
130
|
-
const requested = params.model?.trim() || config.generate.model;
|
|
131
|
-
const maybeResolved = resolveImageGenModel(requested, models);
|
|
132
|
-
if (typeof maybeResolved === "string") return errorResult(maybeResolved);
|
|
133
|
-
|
|
134
|
-
// A model may arrive without an endpoint — notably a user-typed
|
|
135
|
-
// "provider/model-id", accepted at face value. Fill it in from the
|
|
136
|
-
// registry so the adapter knows where to POST.
|
|
137
|
-
const registryBaseUrl = maybeResolved.baseUrl
|
|
138
|
-
? undefined
|
|
139
|
-
: findProviderBaseUrl(registry, maybeResolved.provider);
|
|
140
|
-
const resolved = registryBaseUrl
|
|
141
|
-
? { ...maybeResolved, baseUrl: registryBaseUrl }
|
|
142
|
-
: maybeResolved;
|
|
143
|
-
|
|
144
|
-
// pi-ai resolves image auth from its own credential store; only fall
|
|
145
|
-
// back to pi's chat-provider key when that comes up empty.
|
|
146
|
-
const fallbackKey = await resolveApiKey(registry, resolved.provider);
|
|
147
|
-
|
|
148
|
-
// An input image switches the request into edit mode.
|
|
149
|
-
const sourceImage = params.image?.trim()
|
|
150
|
-
? loadImage(params.image, ctx.cwd ?? process.cwd())
|
|
151
|
-
: undefined;
|
|
152
|
-
|
|
153
|
-
const result = await generateImage({
|
|
154
|
-
prompt: params.prompt,
|
|
155
|
-
model: resolved,
|
|
156
|
-
...(fallbackKey ? { apiKey: fallbackKey } : {}),
|
|
157
|
-
...(sourceImage ? { inputImage: sourceImage } : {}),
|
|
158
|
-
signal,
|
|
159
|
-
outputDir: config.generate.saveToDisk ? getOutputDir(config) : undefined,
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const saved = result.images
|
|
163
|
-
.map((image) => image.path)
|
|
164
|
-
.filter((path): path is string => Boolean(path));
|
|
165
|
-
|
|
166
|
-
const summary = [
|
|
167
|
-
`${sourceImage ? "Edited" : "Generated"} ${result.images.length} ` +
|
|
168
|
-
`image${result.images.length === 1 ? "" : "s"} with ${formatModelRef(resolved)}.`,
|
|
169
|
-
saved.length > 0 ? `Saved to:\n${saved.map((p) => ` ${p}`).join("\n")}` : "",
|
|
170
|
-
config.generate.saveToDisk && saved.length === 0
|
|
171
|
-
? "Could not write to the output directory — returning the image inline only."
|
|
172
|
-
: "",
|
|
173
|
-
result.text,
|
|
174
|
-
]
|
|
175
|
-
.filter(Boolean)
|
|
176
|
-
.join("\n");
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
content: [
|
|
180
|
-
{ type: "text" as const, text: summary },
|
|
181
|
-
...result.images.map((image) => ({
|
|
182
|
-
type: "image" as const,
|
|
183
|
-
data: image.data,
|
|
184
|
-
mimeType: image.mimeType,
|
|
185
|
-
})),
|
|
186
|
-
],
|
|
187
|
-
details: {
|
|
188
|
-
model: formatModelRef(resolved),
|
|
189
|
-
count: result.images.length,
|
|
190
|
-
paths: saved,
|
|
191
|
-
},
|
|
192
|
-
};
|
|
193
|
-
} catch (error) {
|
|
194
|
-
return errorResult(`Image generation failed: ${messageOf(error)}`);
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function registerRecognizeTool(pi: ExtensionAPI): void {
|
|
201
|
-
pi.registerTool({
|
|
202
|
-
name: IMAGE_TOOLS.RECOGNIZE,
|
|
203
|
-
label: "Recognize Image",
|
|
204
|
-
description:
|
|
205
|
-
"Analyze an image and answer questions about it using a vision model. " +
|
|
206
|
-
"Accepts a local file path, a data: URL, or base64 image data.",
|
|
207
|
-
promptSnippet: "Analyze an image and answer questions about it.",
|
|
208
|
-
promptGuidelines: [
|
|
209
|
-
"Use image_recognize to read screenshots, diagrams, mockups and photos.",
|
|
210
|
-
"Pass a local file path whenever possible — it is cheaper than inlining base64.",
|
|
211
|
-
"Ask a specific question in `prompt` to focus the analysis.",
|
|
212
|
-
"Remote URLs are not fetched; download the image first.",
|
|
213
|
-
],
|
|
214
|
-
parameters: Type.Object({
|
|
215
|
-
image: Type.String({
|
|
216
|
-
description:
|
|
217
|
-
"Local file path, data: URL, or base64 image data. " +
|
|
218
|
-
"Supported types: PNG, JPEG, GIF, WebP.",
|
|
219
|
-
}),
|
|
220
|
-
prompt: Type.Optional(
|
|
221
|
-
Type.String({
|
|
222
|
-
description:
|
|
223
|
-
"What to ask about the image. Defaults to a general description.",
|
|
224
|
-
}),
|
|
225
|
-
),
|
|
226
|
-
model: Type.Optional(
|
|
227
|
-
Type.String({
|
|
228
|
-
description:
|
|
229
|
-
"Vision model override. Must accept image input. " +
|
|
230
|
-
"Omit to use the configured default or the current session model.",
|
|
231
|
-
}),
|
|
232
|
-
),
|
|
233
|
-
systemPrompt: Type.Optional(
|
|
234
|
-
Type.String({
|
|
235
|
-
description:
|
|
236
|
-
"Override the configured system prompt for this call only.",
|
|
237
|
-
}),
|
|
238
|
-
),
|
|
239
|
-
}),
|
|
240
|
-
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
241
|
-
try {
|
|
242
|
-
const config = loadConfig();
|
|
243
|
-
|
|
244
|
-
const registry = getRegistry(ctx);
|
|
245
|
-
if (!registry) {
|
|
246
|
-
return errorResult(
|
|
247
|
-
"Model registry unavailable — image_recognize needs an active session.",
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Precedence: per-call override, configured model, session model.
|
|
252
|
-
const requested =
|
|
253
|
-
params.model?.trim() ||
|
|
254
|
-
config.recognize.model.trim() ||
|
|
255
|
-
currentSessionModel(ctx);
|
|
256
|
-
|
|
257
|
-
if (!requested) {
|
|
258
|
-
return errorResult(
|
|
259
|
-
"No vision model configured.\n" +
|
|
260
|
-
"→ Choose one with /unipi:settings, or pass `model`.",
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const resolved = resolveVisionModel(requested, registry);
|
|
265
|
-
if (typeof resolved === "string") return errorResult(resolved);
|
|
266
|
-
|
|
267
|
-
const image = loadImage(params.image, ctx.cwd ?? process.cwd());
|
|
268
|
-
|
|
269
|
-
const chatModel = findChatModel(registry, resolved);
|
|
270
|
-
const baseUrl = chatModel?.baseUrl;
|
|
271
|
-
if (!baseUrl) {
|
|
272
|
-
return errorResult(
|
|
273
|
-
`Could not determine the API endpoint for ${formatModelRef(resolved)}.`,
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const apiKey = await resolveApiKey(registry, resolved.provider);
|
|
278
|
-
if (!apiKey) {
|
|
279
|
-
return errorResult(
|
|
280
|
-
`No API key for provider "${resolved.provider}".\n` +
|
|
281
|
-
"→ Sign in with /login, or set the provider's API key environment variable.",
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const result = await recognizeImage({
|
|
286
|
-
image,
|
|
287
|
-
prompt: params.prompt?.trim() || "Describe this image in detail.",
|
|
288
|
-
systemPrompt: params.systemPrompt?.trim() || config.recognize.systemPrompt,
|
|
289
|
-
apiKey,
|
|
290
|
-
baseUrl,
|
|
291
|
-
api: chatModel?.api ?? "openai-completions",
|
|
292
|
-
modelId: resolved.id,
|
|
293
|
-
signal,
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
const origin = image.path ? ` (${image.path})` : "";
|
|
297
|
-
|
|
298
|
-
return {
|
|
299
|
-
content: [
|
|
300
|
-
{
|
|
301
|
-
type: "text" as const,
|
|
302
|
-
text: `${result.text}\n\n— analyzed with ${formatModelRef(resolved)}${origin}`,
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
details: {
|
|
306
|
-
model: formatModelRef(resolved),
|
|
307
|
-
mimeType: image.mimeType,
|
|
308
|
-
source: image.source,
|
|
309
|
-
...(image.path ? { path: image.path } : {}),
|
|
310
|
-
},
|
|
311
|
-
};
|
|
312
|
-
} catch (error) {
|
|
313
|
-
return errorResult(`Image recognition failed: ${messageOf(error)}`);
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/** The session's current model as "provider/id", when discoverable. */
|
|
320
|
-
function currentSessionModel(ctx: ExtensionContext): string {
|
|
321
|
-
const model = (ctx as unknown as { model?: { provider?: string; id?: string } }).model;
|
|
322
|
-
if (model?.provider && model?.id) {
|
|
323
|
-
return formatModelRef({ provider: model.provider, id: model.id });
|
|
324
|
-
}
|
|
325
|
-
return "";
|
|
326
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-platform clipboard read/write using child_process.
|
|
3
|
-
* Detection order: xclip → xsel → pbcopy/pbpaste → clip/powershell.
|
|
4
|
-
* Caches detected command on first use.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { execSync } from "node:child_process";
|
|
8
|
-
|
|
9
|
-
export interface ClipboardResult {
|
|
10
|
-
ok: boolean;
|
|
11
|
-
text?: string;
|
|
12
|
-
reason?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type ClipboardTool = "xclip" | "xsel" | "pbcopy" | "clip" | "powershell" | null;
|
|
16
|
-
|
|
17
|
-
let cachedTool: ClipboardTool | undefined; // undefined = not yet detected
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Detect available clipboard command. Caches result.
|
|
21
|
-
*/
|
|
22
|
-
export function detectClipboard(): ClipboardTool {
|
|
23
|
-
if (cachedTool !== undefined) return cachedTool;
|
|
24
|
-
|
|
25
|
-
const tools: Array<{ name: ClipboardTool; test: string }> = [
|
|
26
|
-
{ name: "xclip", test: "xclip -selection clipboard -o" },
|
|
27
|
-
{ name: "xsel", test: "xsel --clipboard --output" },
|
|
28
|
-
{ name: "pbcopy", test: "pbpaste" },
|
|
29
|
-
{ name: "clip", test: "echo test | clip" },
|
|
30
|
-
{ name: "powershell", test: "powershell -command Get-Clipboard" },
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
for (const tool of tools) {
|
|
34
|
-
try {
|
|
35
|
-
execSync(tool.test, { stdio: "ignore", timeout: 2000 });
|
|
36
|
-
cachedTool = tool.name;
|
|
37
|
-
return cachedTool;
|
|
38
|
-
} catch {
|
|
39
|
-
// Try next tool
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
cachedTool = null;
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Copy text to system clipboard.
|
|
49
|
-
*/
|
|
50
|
-
export function copyToClipboard(text: string): ClipboardResult {
|
|
51
|
-
const tool = detectClipboard();
|
|
52
|
-
if (!tool) return { ok: false, reason: "clipboard unavailable" };
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
switch (tool) {
|
|
56
|
-
case "xclip":
|
|
57
|
-
execSync("xclip -selection clipboard", { input: text, timeout: 2000 });
|
|
58
|
-
break;
|
|
59
|
-
case "xsel":
|
|
60
|
-
execSync("xsel --clipboard --input", { input: text, timeout: 2000 });
|
|
61
|
-
break;
|
|
62
|
-
case "pbcopy":
|
|
63
|
-
execSync("pbcopy", { input: text, timeout: 2000 });
|
|
64
|
-
break;
|
|
65
|
-
case "clip":
|
|
66
|
-
execSync("clip", { input: text, timeout: 2000 });
|
|
67
|
-
break;
|
|
68
|
-
case "powershell":
|
|
69
|
-
execSync(`powershell -command "Set-Clipboard -Value '${text.replace(/'/g, "''")}'"`, { timeout: 2000 });
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
return { ok: true };
|
|
73
|
-
} catch {
|
|
74
|
-
return { ok: false, reason: "clipboard write failed" };
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Read text from system clipboard.
|
|
80
|
-
*/
|
|
81
|
-
export function pasteFromClipboard(): ClipboardResult {
|
|
82
|
-
const tool = detectClipboard();
|
|
83
|
-
if (!tool) return { ok: false, reason: "clipboard unavailable" };
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
let text: string;
|
|
87
|
-
switch (tool) {
|
|
88
|
-
case "xclip":
|
|
89
|
-
text = execSync("xclip -selection clipboard -o", { encoding: "utf-8", timeout: 2000 }).trimEnd();
|
|
90
|
-
break;
|
|
91
|
-
case "xsel":
|
|
92
|
-
text = execSync("xsel --clipboard --output", { encoding: "utf-8", timeout: 2000 }).trimEnd();
|
|
93
|
-
break;
|
|
94
|
-
case "pbcopy":
|
|
95
|
-
// pbcopy is write-only; use pbpaste for reading
|
|
96
|
-
text = execSync("pbpaste", { encoding: "utf-8", timeout: 2000 }).trimEnd();
|
|
97
|
-
break;
|
|
98
|
-
case "clip":
|
|
99
|
-
// clip is write-only on Windows; use powershell for reading
|
|
100
|
-
text = execSync("powershell -command Get-Clipboard", { encoding: "utf-8", timeout: 2000 }).trimEnd();
|
|
101
|
-
break;
|
|
102
|
-
case "powershell":
|
|
103
|
-
text = execSync("powershell -command Get-Clipboard", { encoding: "utf-8", timeout: 2000 }).trimEnd();
|
|
104
|
-
break;
|
|
105
|
-
default:
|
|
106
|
-
return { ok: false, reason: "clipboard unavailable" };
|
|
107
|
-
}
|
|
108
|
-
return { ok: true, text };
|
|
109
|
-
} catch {
|
|
110
|
-
return { ok: false, reason: "clipboard read failed" };
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Reset cached tool detection (for testing).
|
|
116
|
-
*/
|
|
117
|
-
export function resetClipboardCache(): void {
|
|
118
|
-
cachedTool = undefined;
|
|
119
|
-
}
|