@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,327 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Snapshot builder — converts stored SessionEvents into XML resume snapshot
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { StoredEvent } from "../types.js";
|
|
6
|
-
|
|
7
|
-
export interface BuildSnapshotOpts {
|
|
8
|
-
compactCount?: number;
|
|
9
|
-
searchTool?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const MAX_ACTIVE_FILES = 10;
|
|
13
|
-
|
|
14
|
-
function escapeXML(text: string): string {
|
|
15
|
-
return text
|
|
16
|
-
.replace(/&/g, "&")
|
|
17
|
-
.replace(/</g, "<")
|
|
18
|
-
.replace(/>/g, ">")
|
|
19
|
-
.replace(/"/g, """)
|
|
20
|
-
.replace(/'/g, "'");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function buildQueries(items: string[], maxQueries = 4): string[] {
|
|
24
|
-
const unique = [...new Set(items.filter((s) => s.length > 0))];
|
|
25
|
-
const selected = unique.slice(0, maxQueries);
|
|
26
|
-
return selected.map((s) => (s.length > 80 ? s.slice(0, 80) : s));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function toolCall(toolName: string, queries: string[]): string {
|
|
30
|
-
if (queries.length === 0) return "";
|
|
31
|
-
const escaped = queries.map((q) => `"${escapeXML(q)}"`).join(", ");
|
|
32
|
-
return `\n For full details:\n ${escapeXML(toolName)}(\n queries: [${escaped}],\n source: "session-events"\n )`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function buildFilesSection(fileEvents: StoredEvent[], searchTool: string): string {
|
|
36
|
-
if (fileEvents.length === 0) return "";
|
|
37
|
-
const fileMap = new Map<string, { ops: Map<string, number> }>();
|
|
38
|
-
for (const ev of fileEvents) {
|
|
39
|
-
const path = ev.data;
|
|
40
|
-
let entry = fileMap.get(path);
|
|
41
|
-
if (!entry) {
|
|
42
|
-
entry = { ops: new Map() };
|
|
43
|
-
fileMap.set(path, entry);
|
|
44
|
-
}
|
|
45
|
-
let op: string;
|
|
46
|
-
if (ev.type === "file_write") op = "write";
|
|
47
|
-
else if (ev.type === "file_edit") op = "edit";
|
|
48
|
-
else if (ev.type === "file_read") op = "read";
|
|
49
|
-
else op = ev.type;
|
|
50
|
-
entry.ops.set(op, (entry.ops.get(op) ?? 0) + 1);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const entries = Array.from(fileMap.entries());
|
|
54
|
-
const limited = entries.slice(-MAX_ACTIVE_FILES);
|
|
55
|
-
const summaryLines: string[] = [];
|
|
56
|
-
const queryTerms: string[] = [];
|
|
57
|
-
|
|
58
|
-
for (const [path, { ops }] of limited) {
|
|
59
|
-
const opsStr = Array.from(ops.entries()).map(([k, v]) => `${k}×${v}`).join(", ");
|
|
60
|
-
const fileName = path.split("/").pop() ?? path;
|
|
61
|
-
summaryLines.push(` ${escapeXML(fileName)} (${escapeXML(opsStr)})`);
|
|
62
|
-
queryTerms.push(`${fileName} ${Array.from(ops.keys()).join(" ")}`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const queries = buildQueries(queryTerms);
|
|
66
|
-
return [
|
|
67
|
-
` <files count="${fileMap.size}">`,
|
|
68
|
-
...summaryLines,
|
|
69
|
-
toolCall(searchTool, queries),
|
|
70
|
-
` </files>`,
|
|
71
|
-
].join("\n");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function buildErrorsSection(errorEvents: StoredEvent[], searchTool: string): string {
|
|
75
|
-
if (errorEvents.length === 0) return "";
|
|
76
|
-
const summaryLines = errorEvents.map((ev) => ` ${escapeXML(ev.data)}`);
|
|
77
|
-
const queries = buildQueries(errorEvents.map((ev) => ev.data));
|
|
78
|
-
return [
|
|
79
|
-
` <errors count="${errorEvents.length}">`,
|
|
80
|
-
...summaryLines,
|
|
81
|
-
toolCall(searchTool, queries),
|
|
82
|
-
` </errors>`,
|
|
83
|
-
].join("\n");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function buildDecisionsSection(decisionEvents: StoredEvent[], searchTool: string): string {
|
|
87
|
-
if (decisionEvents.length === 0) return "";
|
|
88
|
-
const seen = new Set<string>();
|
|
89
|
-
const summaryLines: string[] = [];
|
|
90
|
-
const queryTerms: string[] = [];
|
|
91
|
-
for (const ev of decisionEvents) {
|
|
92
|
-
if (seen.has(ev.data)) continue;
|
|
93
|
-
seen.add(ev.data);
|
|
94
|
-
summaryLines.push(` ${escapeXML(ev.data)}`);
|
|
95
|
-
queryTerms.push(ev.data);
|
|
96
|
-
}
|
|
97
|
-
if (summaryLines.length === 0) return "";
|
|
98
|
-
const queries = buildQueries(queryTerms);
|
|
99
|
-
return [
|
|
100
|
-
` <decisions count="${summaryLines.length}">`,
|
|
101
|
-
...summaryLines,
|
|
102
|
-
toolCall(searchTool, queries),
|
|
103
|
-
` </decisions>`,
|
|
104
|
-
].join("\n");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function buildRulesSection(ruleEvents: StoredEvent[], searchTool: string): string {
|
|
108
|
-
if (ruleEvents.length === 0) return "";
|
|
109
|
-
const seen = new Set<string>();
|
|
110
|
-
const summaryLines: string[] = [];
|
|
111
|
-
const queryTerms: string[] = [];
|
|
112
|
-
for (const ev of ruleEvents) {
|
|
113
|
-
if (seen.has(ev.data)) continue;
|
|
114
|
-
seen.add(ev.data);
|
|
115
|
-
summaryLines.push(` ${escapeXML(ev.data)}`);
|
|
116
|
-
queryTerms.push(ev.data);
|
|
117
|
-
}
|
|
118
|
-
if (summaryLines.length === 0) return "";
|
|
119
|
-
const queries = buildQueries(queryTerms);
|
|
120
|
-
return [
|
|
121
|
-
` <rules count="${summaryLines.length}">`,
|
|
122
|
-
...summaryLines,
|
|
123
|
-
toolCall(searchTool, queries),
|
|
124
|
-
` </rules>`,
|
|
125
|
-
].join("\n");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function buildGitSection(gitEvents: StoredEvent[], searchTool: string): string {
|
|
129
|
-
if (gitEvents.length === 0) return "";
|
|
130
|
-
const summaryLines = gitEvents.map((ev) => ` ${escapeXML(ev.data)}`);
|
|
131
|
-
const queries = buildQueries(gitEvents.map((ev) => ev.data));
|
|
132
|
-
return [
|
|
133
|
-
` <git count="${gitEvents.length}">`,
|
|
134
|
-
...summaryLines,
|
|
135
|
-
toolCall(searchTool, queries),
|
|
136
|
-
` </git>`,
|
|
137
|
-
].join("\n");
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export function renderTaskState(taskEvents: StoredEvent[]): string {
|
|
141
|
-
if (taskEvents.length === 0) return "";
|
|
142
|
-
const creates: string[] = [];
|
|
143
|
-
const updates: Record<string, string> = {};
|
|
144
|
-
for (const ev of taskEvents) {
|
|
145
|
-
try {
|
|
146
|
-
const parsed = JSON.parse(ev.data) as Record<string, unknown>;
|
|
147
|
-
if (typeof parsed.subject === "string") creates.push(parsed.subject);
|
|
148
|
-
else if (typeof parsed.taskId === "string" && typeof parsed.status === "string") {
|
|
149
|
-
updates[parsed.taskId] = parsed.status;
|
|
150
|
-
}
|
|
151
|
-
} catch { /* not JSON */ }
|
|
152
|
-
}
|
|
153
|
-
if (creates.length === 0) return "";
|
|
154
|
-
const DONE = new Set(["completed", "deleted", "failed"]);
|
|
155
|
-
const sortedIds = Object.keys(updates).sort((a, b) => Number(a) - Number(b));
|
|
156
|
-
const pending: string[] = [];
|
|
157
|
-
for (let i = 0; i < creates.length; i++) {
|
|
158
|
-
const matchedId = sortedIds[i];
|
|
159
|
-
const status = matchedId ? (updates[matchedId] ?? "pending") : "pending";
|
|
160
|
-
if (!DONE.has(status)) pending.push(creates[i]);
|
|
161
|
-
}
|
|
162
|
-
if (pending.length === 0) return "";
|
|
163
|
-
return pending.map((task) => ` [pending] ${escapeXML(task)}`).join("\n");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function buildTaskSection(taskEvents: StoredEvent[], searchTool: string): string {
|
|
167
|
-
const taskContent = renderTaskState(taskEvents);
|
|
168
|
-
if (!taskContent) return "";
|
|
169
|
-
const queryTerms: string[] = [];
|
|
170
|
-
for (const ev of taskEvents) {
|
|
171
|
-
try {
|
|
172
|
-
const parsed = JSON.parse(ev.data) as Record<string, unknown>;
|
|
173
|
-
if (typeof parsed.subject === "string") queryTerms.push(parsed.subject);
|
|
174
|
-
} catch { /* not JSON */ }
|
|
175
|
-
}
|
|
176
|
-
const queries = buildQueries(queryTerms);
|
|
177
|
-
const pendingCount = taskContent.split("\n").length;
|
|
178
|
-
return [
|
|
179
|
-
` <task_state count="${pendingCount}">`,
|
|
180
|
-
taskContent,
|
|
181
|
-
toolCall(searchTool, queries),
|
|
182
|
-
` </task_state>`,
|
|
183
|
-
].join("\n");
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function buildEnvironmentSection(cwdEvents: StoredEvent[], envEvents: StoredEvent[], searchTool: string): string {
|
|
187
|
-
if (cwdEvents.length === 0 && envEvents.length === 0) return "";
|
|
188
|
-
const summaryLines: string[] = [];
|
|
189
|
-
const queryTerms: string[] = [];
|
|
190
|
-
if (cwdEvents.length > 0) {
|
|
191
|
-
summaryLines.push(` cwd: ${escapeXML(cwdEvents[cwdEvents.length - 1].data)}`);
|
|
192
|
-
queryTerms.push("working directory");
|
|
193
|
-
}
|
|
194
|
-
for (const env of envEvents) {
|
|
195
|
-
summaryLines.push(` ${escapeXML(env.data)}`);
|
|
196
|
-
queryTerms.push(env.data);
|
|
197
|
-
}
|
|
198
|
-
const queries = buildQueries(queryTerms);
|
|
199
|
-
return [
|
|
200
|
-
` <environment>`,
|
|
201
|
-
...summaryLines,
|
|
202
|
-
toolCall(searchTool, queries),
|
|
203
|
-
` </environment>`,
|
|
204
|
-
].join("\n");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function buildSubagentsSection(subagentEvents: StoredEvent[], searchTool: string): string {
|
|
208
|
-
if (subagentEvents.length === 0) return "";
|
|
209
|
-
const summaryLines: string[] = [];
|
|
210
|
-
const queryTerms: string[] = [];
|
|
211
|
-
for (const ev of subagentEvents) {
|
|
212
|
-
const status = ev.type === "subagent_completed" ? "completed"
|
|
213
|
-
: ev.type === "subagent_launched" ? "launched"
|
|
214
|
-
: "unknown";
|
|
215
|
-
summaryLines.push(` [${status}] ${escapeXML(ev.data)}`);
|
|
216
|
-
queryTerms.push(`subagent ${ev.data}`);
|
|
217
|
-
}
|
|
218
|
-
const queries = buildQueries(queryTerms);
|
|
219
|
-
return [
|
|
220
|
-
` <subagents count="${subagentEvents.length}">`,
|
|
221
|
-
...summaryLines,
|
|
222
|
-
toolCall(searchTool, queries),
|
|
223
|
-
` </subagents>`,
|
|
224
|
-
].join("\n");
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function buildSkillsSection(skillEvents: StoredEvent[], searchTool: string): string {
|
|
228
|
-
if (skillEvents.length === 0) return "";
|
|
229
|
-
const skillCounts = new Map<string, number>();
|
|
230
|
-
for (const ev of skillEvents) {
|
|
231
|
-
const name = ev.data.split(":")[0].trim();
|
|
232
|
-
skillCounts.set(name, (skillCounts.get(name) ?? 0) + 1);
|
|
233
|
-
}
|
|
234
|
-
const summaryLines: string[] = [];
|
|
235
|
-
const queryTerms: string[] = [];
|
|
236
|
-
for (const [name, count] of skillCounts) {
|
|
237
|
-
summaryLines.push(` ${escapeXML(name)} (${count}×)`);
|
|
238
|
-
queryTerms.push(`skill ${name} invocation`);
|
|
239
|
-
}
|
|
240
|
-
const queries = buildQueries(queryTerms);
|
|
241
|
-
return [
|
|
242
|
-
` <skills count="${skillEvents.length}">`,
|
|
243
|
-
...summaryLines,
|
|
244
|
-
toolCall(searchTool, queries),
|
|
245
|
-
` </skills>`,
|
|
246
|
-
].join("\n");
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function buildIntentSection(intentEvents: StoredEvent[]): string {
|
|
250
|
-
if (intentEvents.length === 0) return "";
|
|
251
|
-
return ` <intent mode="${escapeXML(intentEvents[intentEvents.length - 1].data)}"/>`;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export function buildResumeSnapshot(
|
|
255
|
-
events: StoredEvent[],
|
|
256
|
-
opts?: BuildSnapshotOpts,
|
|
257
|
-
): string {
|
|
258
|
-
const compactCount = opts?.compactCount ?? 1;
|
|
259
|
-
const searchTool = opts?.searchTool ?? "ctx_search";
|
|
260
|
-
|
|
261
|
-
const fileEvents: StoredEvent[] = [];
|
|
262
|
-
const taskEvents: StoredEvent[] = [];
|
|
263
|
-
const ruleEvents: StoredEvent[] = [];
|
|
264
|
-
const decisionEvents: StoredEvent[] = [];
|
|
265
|
-
const cwdEvents: StoredEvent[] = [];
|
|
266
|
-
const errorEvents: StoredEvent[] = [];
|
|
267
|
-
const envEvents: StoredEvent[] = [];
|
|
268
|
-
const gitEvents: StoredEvent[] = [];
|
|
269
|
-
const subagentEvents: StoredEvent[] = [];
|
|
270
|
-
const intentEvents: StoredEvent[] = [];
|
|
271
|
-
const skillEvents: StoredEvent[] = [];
|
|
272
|
-
|
|
273
|
-
for (const ev of events) {
|
|
274
|
-
switch (ev.category) {
|
|
275
|
-
case "file": fileEvents.push(ev); break;
|
|
276
|
-
case "task": taskEvents.push(ev); break;
|
|
277
|
-
case "rule": ruleEvents.push(ev); break;
|
|
278
|
-
case "decision": decisionEvents.push(ev); break;
|
|
279
|
-
case "cwd": cwdEvents.push(ev); break;
|
|
280
|
-
case "error": errorEvents.push(ev); break;
|
|
281
|
-
case "env": envEvents.push(ev); break;
|
|
282
|
-
case "git": gitEvents.push(ev); break;
|
|
283
|
-
case "subagent": subagentEvents.push(ev); break;
|
|
284
|
-
case "intent": intentEvents.push(ev); break;
|
|
285
|
-
case "skill": skillEvents.push(ev); break;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const sections: string[] = [];
|
|
290
|
-
sections.push(` <how_to_search>
|
|
291
|
-
Each section below contains a summary of prior work.
|
|
292
|
-
For FULL DETAILS, run the exact tool call shown under each section.
|
|
293
|
-
Do NOT ask the user to re-explain prior work. Search first.
|
|
294
|
-
Do NOT invent your own queries — use the ones provided.
|
|
295
|
-
</how_to_search>`);
|
|
296
|
-
|
|
297
|
-
const files = buildFilesSection(fileEvents, searchTool);
|
|
298
|
-
if (files) sections.push(files);
|
|
299
|
-
const errors = buildErrorsSection(errorEvents, searchTool);
|
|
300
|
-
if (errors) sections.push(errors);
|
|
301
|
-
const decisions = buildDecisionsSection(decisionEvents, searchTool);
|
|
302
|
-
if (decisions) sections.push(decisions);
|
|
303
|
-
const rules = buildRulesSection(ruleEvents, searchTool);
|
|
304
|
-
if (rules) sections.push(rules);
|
|
305
|
-
const git = buildGitSection(gitEvents, searchTool);
|
|
306
|
-
if (git) sections.push(git);
|
|
307
|
-
const tasks = buildTaskSection(taskEvents, searchTool);
|
|
308
|
-
if (tasks) sections.push(tasks);
|
|
309
|
-
const environment = buildEnvironmentSection(cwdEvents, envEvents, searchTool);
|
|
310
|
-
if (environment) sections.push(environment);
|
|
311
|
-
const subagents = buildSubagentsSection(subagentEvents, searchTool);
|
|
312
|
-
if (subagents) sections.push(subagents);
|
|
313
|
-
const skills = buildSkillsSection(skillEvents, searchTool);
|
|
314
|
-
if (skills) sections.push(skills);
|
|
315
|
-
const intent = buildIntentSection(intentEvents);
|
|
316
|
-
if (intent) sections.push(intent);
|
|
317
|
-
|
|
318
|
-
// Deliberately omit wall-clock time. This snapshot is model-visible on the
|
|
319
|
-
// first post-compaction request and must be reproducible from stored events.
|
|
320
|
-
const header = `<session_resume events="${events.length}" compact_count="${compactCount}">`;
|
|
321
|
-
const footer = `</session_resume>`;
|
|
322
|
-
const body = sections.join("\n\n");
|
|
323
|
-
if (body) {
|
|
324
|
-
return `${header}\n\n${body}\n\n${footer}`;
|
|
325
|
-
}
|
|
326
|
-
return `${header}\n${footer}`;
|
|
327
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ctx_batch_execute tool — atomic batch of commands
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { PolyglotExecutor } from "../executor/executor.js";
|
|
6
|
-
import type { Language, ExecResult } from "../types.js";
|
|
7
|
-
|
|
8
|
-
export interface BatchCommand {
|
|
9
|
-
type: "execute";
|
|
10
|
-
language: Language;
|
|
11
|
-
code: string;
|
|
12
|
-
timeout?: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type BatchItem = BatchCommand;
|
|
16
|
-
|
|
17
|
-
export interface BatchResult {
|
|
18
|
-
results: Array<
|
|
19
|
-
{ type: "execute"; result: ExecResult }
|
|
20
|
-
>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function ctxBatchExecute(
|
|
24
|
-
items: BatchItem[],
|
|
25
|
-
executor = new PolyglotExecutor(),
|
|
26
|
-
): Promise<BatchResult> {
|
|
27
|
-
const results: BatchResult["results"] = [];
|
|
28
|
-
|
|
29
|
-
for (const item of items) {
|
|
30
|
-
if (item.type === "execute") {
|
|
31
|
-
const result = await executor.execute({
|
|
32
|
-
language: item.language,
|
|
33
|
-
code: item.code,
|
|
34
|
-
timeout: item.timeout ?? 30000,
|
|
35
|
-
});
|
|
36
|
-
results.push({ type: "execute", result });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return { results };
|
|
41
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ctx_execute_file tool — process file via FILE_CONTENT variable
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { PolyglotExecutor } from "../executor/executor.js";
|
|
6
|
-
import type { Language, ExecResult } from "../types.js";
|
|
7
|
-
|
|
8
|
-
export interface CtxExecuteFileInput {
|
|
9
|
-
language: Language;
|
|
10
|
-
path: string;
|
|
11
|
-
timeout?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function ctxExecuteFile(
|
|
15
|
-
input: CtxExecuteFileInput,
|
|
16
|
-
executor = new PolyglotExecutor(),
|
|
17
|
-
): Promise<ExecResult> {
|
|
18
|
-
return executor.executeFile({
|
|
19
|
-
language: input.language,
|
|
20
|
-
path: input.path,
|
|
21
|
-
timeout: input.timeout ?? 30000,
|
|
22
|
-
});
|
|
23
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ctx_execute tool — run code in sandbox, only stdout enters context
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { PolyglotExecutor } from "../executor/executor.js";
|
|
6
|
-
import type { Language, ExecResult } from "../types.js";
|
|
7
|
-
|
|
8
|
-
export interface CtxExecuteInput {
|
|
9
|
-
language: Language;
|
|
10
|
-
code: string;
|
|
11
|
-
timeout?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function ctxExecute(
|
|
15
|
-
input: CtxExecuteInput,
|
|
16
|
-
executor = new PolyglotExecutor(),
|
|
17
|
-
): Promise<ExecResult> {
|
|
18
|
-
return executor.execute({
|
|
19
|
-
language: input.language,
|
|
20
|
-
code: input.code,
|
|
21
|
-
timeout: input.timeout ?? 30000,
|
|
22
|
-
});
|
|
23
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ctx_stats tool — context savings dashboard
|
|
3
|
-
*
|
|
4
|
-
* Stats driven by compaction savings (DB-first) with runtime counter fallback.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { SessionDB } from "../session/db.js";
|
|
8
|
-
import type { RuntimeCounters } from "../types.js";
|
|
9
|
-
|
|
10
|
-
export interface CtxStatsResult {
|
|
11
|
-
sessionEvents: number;
|
|
12
|
-
compactions: number;
|
|
13
|
-
tokensSaved: number;
|
|
14
|
-
compressionRatio: string;
|
|
15
|
-
sandboxRuns: number;
|
|
16
|
-
searchQueries: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function ctxStats(
|
|
20
|
-
sessionDB: SessionDB,
|
|
21
|
-
sessionId: string,
|
|
22
|
-
counters?: RuntimeCounters,
|
|
23
|
-
): Promise<CtxStatsResult> {
|
|
24
|
-
const sessionStats = sessionDB.getSessionStats(sessionId);
|
|
25
|
-
|
|
26
|
-
// Compute tokensSaved: prefer in-memory counters (current session),
|
|
27
|
-
// fall back to per-session DB stats, then all-time DB stats.
|
|
28
|
-
let tokensSaved = counters?.totalTokensCompacted ?? 0;
|
|
29
|
-
if (tokensSaved === 0 && sessionStats) {
|
|
30
|
-
const sessionCharsBefore = (sessionStats as any).total_chars_before ?? 0;
|
|
31
|
-
const sessionCharsKept = (sessionStats as any).total_chars_kept ?? 0;
|
|
32
|
-
tokensSaved = Math.round((sessionCharsBefore - sessionCharsKept) / 4);
|
|
33
|
-
}
|
|
34
|
-
if (tokensSaved === 0) {
|
|
35
|
-
const allTime = sessionDB.getAllTimeStats();
|
|
36
|
-
tokensSaved = Math.round((allTime.allCharsBefore - allTime.allCharsKept) / 4);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Compute compactions: prefer in-memory counter (current session),
|
|
40
|
-
// fall back to per-session DB, then all-time DB.
|
|
41
|
-
let compactions = counters?.compactions ?? 0;
|
|
42
|
-
if (compactions === 0) {
|
|
43
|
-
compactions = sessionStats?.compact_count ?? 0;
|
|
44
|
-
}
|
|
45
|
-
if (compactions === 0) {
|
|
46
|
-
const allTime = sessionDB.getAllTimeStats();
|
|
47
|
-
compactions = allTime.allCompactions;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Compression ratio
|
|
51
|
-
let ratio = "N/A";
|
|
52
|
-
if (sessionStats) {
|
|
53
|
-
const before = (sessionStats as any).total_chars_before ?? 0;
|
|
54
|
-
const kept = (sessionStats as any).total_chars_kept ?? 0;
|
|
55
|
-
if (before > 0 && kept > 0) {
|
|
56
|
-
ratio = `${(before / kept).toFixed(1)}:1`;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
sessionEvents: sessionStats?.event_count ?? 0,
|
|
62
|
-
compactions,
|
|
63
|
-
tokensSaved,
|
|
64
|
-
compressionRatio: ratio,
|
|
65
|
-
sandboxRuns: computeSandboxRuns(counters, sessionDB, sessionId),
|
|
66
|
-
searchQueries: computeSearchQueries(counters, sessionDB, sessionId),
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Compute sandbox runs: prefer in-memory counter, fall back to DB. */
|
|
71
|
-
function computeSandboxRuns(counters: RuntimeCounters | undefined, sessionDB: SessionDB, sessionId: string): number {
|
|
72
|
-
let sandboxRuns = counters?.sandboxRuns ?? 0;
|
|
73
|
-
if (sandboxRuns === 0) {
|
|
74
|
-
const sessionStats = sessionDB.getSessionStats(sessionId);
|
|
75
|
-
sandboxRuns = (sessionStats as any)?.sandbox_runs ?? 0;
|
|
76
|
-
}
|
|
77
|
-
if (sandboxRuns === 0) {
|
|
78
|
-
const allTime = sessionDB.getAllTimeStats();
|
|
79
|
-
sandboxRuns = allTime.allSandboxRuns;
|
|
80
|
-
}
|
|
81
|
-
return sandboxRuns;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** Compute search queries: prefer in-memory counter, fall back to DB. */
|
|
85
|
-
function computeSearchQueries(counters: RuntimeCounters | undefined, sessionDB: SessionDB, sessionId: string): number {
|
|
86
|
-
let searchQueries = counters?.searchQueries ?? 0;
|
|
87
|
-
if (searchQueries === 0) {
|
|
88
|
-
const sessionStats = sessionDB.getSessionStats(sessionId);
|
|
89
|
-
searchQueries = (sessionStats as any)?.search_queries ?? 0;
|
|
90
|
-
}
|
|
91
|
-
if (searchQueries === 0) {
|
|
92
|
-
const allTime = sessionDB.getAllTimeStats();
|
|
93
|
-
searchQueries = allTime.allSearchQueries;
|
|
94
|
-
}
|
|
95
|
-
return searchQueries;
|
|
96
|
-
}
|
package/packages/image/README.md
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# @pi-unipi/image
|
|
2
|
-
|
|
3
|
-
Image generation and image recognition tools for the agent.
|
|
4
|
-
|
|
5
|
-
## Tools
|
|
6
|
-
|
|
7
|
-
| Tool | Description |
|
|
8
|
-
|------|-------------|
|
|
9
|
-
| `image_generate` | Generate an image from a text prompt. Returned inline and saved to disk. |
|
|
10
|
-
| `image_recognize` | Analyze an image with a vision model. Accepts a file path, `data:` URL, or base64. Automatically hidden while the session model itself has vision. |
|
|
11
|
-
|
|
12
|
-
## Commands
|
|
13
|
-
|
|
14
|
-
| Command | Description |
|
|
15
|
-
|---------|-------------|
|
|
16
|
-
| `/unipi:settings` | Configure models, output directory and the recognition system prompt |
|
|
17
|
-
|
|
18
|
-
## image_generate
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
image_generate(prompt: "A cutaway diagram of a submarine, technical illustration")
|
|
22
|
-
image_generate(prompt: "...", model: "flux.2-pro")
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Models come from two places, merged into one list:
|
|
26
|
-
|
|
27
|
-
- pi-ai's built-in image catalog — 34 models including FLUX.2, Gemini 3 Pro
|
|
28
|
-
Image, GPT-5 Image, Recraft and Riverflow — served through **OpenRouter**
|
|
29
|
-
([get a key](https://openrouter.ai/keys)).
|
|
30
|
-
- **Any provider registered by another extension.** Third-party providers
|
|
31
|
-
publish no image metadata, so these are detected by name; a real registry
|
|
32
|
-
with 393 models contributed 12 generators (FLUX, Nano Banana, Ideogram,
|
|
33
|
-
Recraft, Seedream, Stable Diffusion) alongside the built-ins.
|
|
34
|
-
|
|
35
|
-
Because that detection is heuristic, the picker has a **custom entry** — press
|
|
36
|
-
`c` in `/unipi:settings` and type any `provider/model-id`. A
|
|
37
|
-
well-formed reference is always accepted, even when the catalog has never
|
|
38
|
-
heard of it, so no model is ever unreachable.
|
|
39
|
-
|
|
40
|
-
The `model` parameter is fuzzy-matched, so `flux`, `recraft` and
|
|
41
|
-
`gemini-3-pro` all work. Omit it to use the model chosen in
|
|
42
|
-
`/unipi:settings`.
|
|
43
|
-
|
|
44
|
-
Images are returned inline **and** written to `~/.unipi/images` by default;
|
|
45
|
-
the saved path is reported back to the agent. A failed write never discards a
|
|
46
|
-
successfully generated image.
|
|
47
|
-
|
|
48
|
-
## image_recognize
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
image_recognize(image: "./screenshot.png")
|
|
52
|
-
image_recognize(image: "./error.png", prompt: "What does the stack trace say?")
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Uses any chat model whose input modality includes `image`. A model that cannot
|
|
56
|
-
accept images is rejected up front with a clear message rather than failing
|
|
57
|
-
inside the provider.
|
|
58
|
-
|
|
59
|
-
Input can be a local file path, a `data:` URL, or raw base64. The media type is
|
|
60
|
-
detected from the file's magic numbers, so a `.jpg` that is really a PNG still
|
|
61
|
-
works. Supported: PNG, JPEG, GIF, WebP. Remote URLs are not fetched.
|
|
62
|
-
|
|
63
|
-
Prefer file paths — inlining base64 into the conversation is far more
|
|
64
|
-
expensive in tokens.
|
|
65
|
-
|
|
66
|
-
**Vision models don't get this tool.** When the session's current model already
|
|
67
|
-
accepts image input, `image_recognize` is dropped from the active tool set —
|
|
68
|
-
the model reads images natively through pi's own tools, so a separate
|
|
69
|
-
recognition round-trip through another model would only duplicate that ability
|
|
70
|
-
and burn context. Switch to a text-only model (via `/model`) and the tool comes
|
|
71
|
-
back automatically.
|
|
72
|
-
|
|
73
|
-
## Configuration
|
|
74
|
-
|
|
75
|
-
`~/.unipi/config/image/config.json`:
|
|
76
|
-
|
|
77
|
-
```json
|
|
78
|
-
{
|
|
79
|
-
"generate": {
|
|
80
|
-
"enabled": true,
|
|
81
|
-
"model": "openrouter/google/gemini-3-pro-image",
|
|
82
|
-
"outputDir": "~/.unipi/images",
|
|
83
|
-
"saveToDisk": true
|
|
84
|
-
},
|
|
85
|
-
"recognize": {
|
|
86
|
-
"enabled": true,
|
|
87
|
-
"model": "",
|
|
88
|
-
"systemPrompt": "You are a precise image analyst…"
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
- `recognize.model` empty means "use the session's current model".
|
|
94
|
-
- The system prompt is fully customizable, and can be overridden per call.
|
|
95
|
-
- Enabling or disabling a tool takes effect next session, since tools are
|
|
96
|
-
registered at startup.
|
|
97
|
-
- Every read falls back to defaults, so a corrupt config never breaks the tools.
|
|
98
|
-
|
|
99
|
-
Set `UNIPI_IMAGE_CONFIG_DIR` to relocate the config directory (used by tests).
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@pi-unipi/image",
|
|
3
|
-
"version": "3.0.0-alpha.2",
|
|
4
|
-
"description": "Image generation and image recognition tools for the Pi coding agent",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "src/index.ts",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"author": "Neuron Mr White",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/Neuron-Mr-White/unipi.git",
|
|
12
|
-
"directory": "packages/image"
|
|
13
|
-
},
|
|
14
|
-
"homepage": "https://github.com/Neuron-Mr-White/unipi#readme",
|
|
15
|
-
"bugs": {
|
|
16
|
-
"url": "https://github.com/Neuron-Mr-White/unipi/issues"
|
|
17
|
-
},
|
|
18
|
-
"keywords": [
|
|
19
|
-
"pi-package",
|
|
20
|
-
"pi-extension",
|
|
21
|
-
"pi-coding-agent",
|
|
22
|
-
"unipi",
|
|
23
|
-
"image",
|
|
24
|
-
"vision",
|
|
25
|
-
"image-generation"
|
|
26
|
-
],
|
|
27
|
-
"files": [
|
|
28
|
-
"index.ts",
|
|
29
|
-
"src/**/*.ts",
|
|
30
|
-
"skills/**/*",
|
|
31
|
-
"README.md"
|
|
32
|
-
],
|
|
33
|
-
"publishConfig": {
|
|
34
|
-
"access": "public"
|
|
35
|
-
},
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.2"
|
|
38
|
-
},
|
|
39
|
-
"peerDependencies": {
|
|
40
|
-
"@earendil-works/pi-ai": "^0.87.1",
|
|
41
|
-
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
42
|
-
"@earendil-works/pi-tui": "^0.87.1",
|
|
43
|
-
"typebox": "^1.1.38"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@types/node": "^25.6.0"
|
|
47
|
-
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"test": "npx tsx --test tests/**/*.test.ts"
|
|
50
|
-
},
|
|
51
|
-
"pi": {
|
|
52
|
-
"extensions": [
|
|
53
|
-
"./src/index.ts"
|
|
54
|
-
],
|
|
55
|
-
"skills": [
|
|
56
|
-
"./skills"
|
|
57
|
-
],
|
|
58
|
-
"prompts": [],
|
|
59
|
-
"themes": []
|
|
60
|
-
}
|
|
61
|
-
}
|