@oh-my-pi/pi-coding-agent 17.0.9 → 17.1.1
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 +78 -0
- package/README.md +1 -1
- package/dist/cli.js +4685 -4614
- package/dist/types/async/job-manager.d.ts +37 -1
- package/dist/types/cli/args.d.ts +2 -0
- package/dist/types/cli/bench-cli.d.ts +41 -0
- package/dist/types/commands/bench.d.ts +15 -3
- package/dist/types/commands/launch.d.ts +4 -0
- package/dist/types/config/model-registry.d.ts +3 -1
- package/dist/types/config/models-config-schema.d.ts +18 -6
- package/dist/types/config/models-config.d.ts +14 -5
- package/dist/types/config/provider-globals.d.ts +2 -2
- package/dist/types/config/service-tier.d.ts +5 -1
- package/dist/types/config/settings-schema.d.ts +374 -47
- package/dist/types/config/settings.d.ts +7 -0
- package/dist/types/dap/client.d.ts +20 -0
- package/dist/types/exec/bash-executor.d.ts +38 -0
- package/dist/types/exec/direnv.d.ts +33 -0
- package/dist/types/export/html/args.d.ts +15 -0
- package/dist/types/export/html/index.d.ts +11 -26
- package/dist/types/export/html/web-palette.d.ts +55 -116
- package/dist/types/extensibility/extensions/loader.d.ts +3 -0
- package/dist/types/extensibility/extensions/types.d.ts +17 -2
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +3 -0
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +13 -0
- package/dist/types/live/attestation.d.ts +2 -0
- package/dist/types/live/controller.d.ts +48 -0
- package/dist/types/live/protocol.d.ts +85 -0
- package/dist/types/live/protocol.test.d.ts +1 -0
- package/dist/types/live/transport.d.ts +35 -0
- package/dist/types/live/visualizer.d.ts +30 -0
- package/dist/types/lsp/client.d.ts +16 -1
- package/dist/types/mcp/config-writer.test.d.ts +1 -0
- package/dist/types/mcp/oauth-discovery.d.ts +2 -0
- package/dist/types/mcp/smithery-auth.d.ts +1 -1
- package/dist/types/mcp/smithery-auth.test.d.ts +1 -0
- package/dist/types/memory-backend/tool-names.d.ts +2 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -0
- package/dist/types/modes/components/custom-message.d.ts +1 -1
- package/dist/types/modes/components/login-dialog.d.ts +2 -2
- package/dist/types/modes/components/message-frame.d.ts +8 -4
- package/dist/types/modes/components/plan-review-overlay.d.ts +26 -0
- package/dist/types/modes/components/session-account-selector.d.ts +11 -0
- package/dist/types/modes/components/settings-defs.d.ts +7 -1
- package/dist/types/modes/components/status-line/component.jj-cache.test.d.ts +1 -0
- package/dist/types/modes/components/tool-execution.d.ts +9 -1
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/event-controller.d.ts +6 -1
- package/dist/types/modes/controllers/live-command-controller.d.ts +14 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +6 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +4 -1
- package/dist/types/modes/utils/context-usage.d.ts +12 -2
- package/dist/types/plan-mode/plan-files.d.ts +10 -0
- package/dist/types/registry/agent-lifecycle.d.ts +21 -9
- package/dist/types/registry/agent-registry.d.ts +11 -4
- package/dist/types/sdk.d.ts +15 -1
- package/dist/types/secrets/index.d.ts +15 -2
- package/dist/types/secrets/obfuscator.d.ts +113 -15
- package/dist/types/session/acp-permission-gate.d.ts +19 -0
- package/dist/types/session/agent-session-events.d.ts +84 -0
- package/dist/types/session/agent-session-types.d.ts +321 -0
- package/dist/types/session/agent-session.d.ts +135 -753
- package/dist/types/session/async-job-delivery.d.ts +28 -0
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/bash-runner.d.ts +75 -0
- package/dist/types/session/blob-store.d.ts +11 -1
- package/dist/types/session/blob-store.test.d.ts +1 -0
- package/dist/types/session/checkpoint-entries.d.ts +28 -0
- package/dist/types/session/eval-runner.d.ts +51 -0
- package/dist/types/session/irc-bridge.d.ts +46 -0
- package/dist/types/session/messages.d.ts +24 -0
- package/dist/types/session/model-controls.d.ts +180 -0
- package/dist/types/session/prewalk.d.ts +46 -0
- package/dist/types/session/queued-messages.d.ts +22 -0
- package/dist/types/session/redis-session-storage.d.ts +1 -0
- package/dist/types/session/retry-fallback-chains.d.ts +74 -0
- package/dist/types/session/role-models.d.ts +15 -0
- package/dist/types/session/session-advisors.d.ts +228 -0
- package/dist/types/session/session-entries.d.ts +8 -0
- package/dist/types/session/session-handoff.d.ts +70 -0
- package/dist/types/session/session-history-format.d.ts +6 -1
- package/dist/types/session/session-maintenance.d.ts +246 -0
- package/dist/types/session/session-manager.d.ts +41 -0
- package/dist/types/session/session-memory.d.ts +56 -0
- package/dist/types/session/session-provider-boundary.d.ts +62 -0
- package/dist/types/session/session-stats.d.ts +48 -0
- package/dist/types/session/session-tools.d.ts +158 -0
- package/dist/types/session/session-workspace.d.ts +32 -0
- package/dist/types/session/stream-guards.d.ts +44 -0
- package/dist/types/session/streaming-output.d.ts +8 -0
- package/dist/types/session/todo-tracker.d.ts +56 -0
- package/dist/types/session/ttsr-coordinator.d.ts +51 -0
- package/dist/types/session/turn-recovery.d.ts +225 -0
- package/dist/types/slash-commands/helpers/session-pin.d.ts +9 -0
- package/dist/types/stt/index.d.ts +0 -2
- package/dist/types/stt/stt-controller.d.ts +7 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +4 -1
- package/dist/types/task/output-manager.d.ts +3 -1
- package/dist/types/tiny/title-client.d.ts +10 -0
- package/dist/types/tools/approval.d.ts +1 -0
- package/dist/types/tools/browser/launch.d.ts +5 -0
- package/dist/types/tools/builtin-names.d.ts +1 -1
- package/dist/types/tools/computer/protocol.d.ts +43 -0
- package/dist/types/tools/computer/supervisor.d.ts +32 -0
- package/dist/types/tools/computer/worker-entry.d.ts +1 -0
- package/dist/types/tools/computer/worker.d.ts +15 -0
- package/dist/types/tools/computer-renderer.d.ts +22 -0
- package/dist/types/tools/computer.d.ts +71 -0
- package/dist/types/tools/context.d.ts +2 -0
- package/dist/types/tools/default-renderer.d.ts +21 -0
- package/dist/types/tools/image-gen.d.ts +4 -4
- package/dist/types/tools/image-providers.d.ts +38 -0
- package/dist/types/tools/index.d.ts +7 -0
- package/dist/types/tools/path-utils.d.ts +8 -0
- package/dist/types/tools/todo.d.ts +10 -4
- package/dist/types/tools/xdev.d.ts +5 -1
- package/dist/types/tts/streaming-player.d.ts +10 -29
- package/dist/types/tts/vocalizer.d.ts +5 -0
- package/dist/types/utils/jj.d.ts +29 -0
- package/dist/types/utils/lang-from-path.d.ts +1 -0
- package/dist/types/utils/title-generator.d.ts +30 -0
- package/dist/types/utils/tools-manager.d.ts +1 -2
- package/dist/types/vibe/runtime.d.ts +36 -8
- package/dist/types/web/search/index.d.ts +1 -1
- package/dist/types/web/search/provider.d.ts +15 -5
- package/dist/types/web/search/types.d.ts +94 -0
- package/package.json +12 -12
- package/scripts/generate-share-viewer.ts +4 -6
- package/src/advisor/__tests__/advisor.test.ts +643 -0
- package/src/advisor/runtime.ts +144 -43
- package/src/async/job-manager.ts +90 -2
- package/src/cli/args.ts +3 -0
- package/src/cli/auth-gateway-cli.ts +18 -3
- package/src/cli/bench-cli.ts +395 -29
- package/src/cli/flag-tables.ts +3 -0
- package/src/cli/gc-cli.ts +2 -2
- package/src/cli/setup-cli.ts +2 -14
- package/src/cli/usage-cli.ts +10 -1
- package/src/cli.ts +8 -0
- package/src/collab/host.ts +3 -2
- package/src/commands/bench.ts +18 -4
- package/src/commands/launch.ts +4 -0
- package/src/config/model-registry.ts +16 -2
- package/src/config/models-config-schema.ts +15 -4
- package/src/config/provider-globals.ts +9 -9
- package/src/config/service-tier.ts +26 -1
- package/src/config/settings-schema.ts +270 -51
- package/src/config/settings.ts +81 -2
- package/src/dap/client.ts +37 -4
- package/src/edit/index.ts +49 -12
- package/src/eval/executor-base.ts +1 -0
- package/src/eval/js/executor.ts +2 -0
- package/src/eval/py/executor.ts +103 -33
- package/src/exec/bash-executor.ts +90 -6
- package/src/exec/direnv.ts +145 -0
- package/src/export/html/args.ts +20 -0
- package/src/export/html/index.ts +45 -47
- package/src/export/html/template.css +19 -1
- package/src/export/html/template.html +6 -0
- package/src/export/html/template.js +21 -0
- package/src/export/html/tool-views.generated.js +31 -31
- package/src/export/html/web-palette.ts +116 -132
- package/src/export/share.ts +249 -49
- package/src/extensibility/extensions/loader.ts +29 -1
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +33 -2
- package/src/extensibility/extensions/wrapper.ts +68 -12
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +7 -1
- package/src/extensibility/plugins/legacy-pi-compat.ts +19 -1
- package/src/hindsight/state.ts +64 -6
- package/src/internal-urls/local-protocol.ts +2 -1
- package/src/internal-urls/memory-protocol.ts +2 -2
- package/src/internal-urls/skill-protocol.ts +2 -2
- package/src/internal-urls/ssh-protocol.ts +2 -1
- package/src/internal-urls/vault-protocol.ts +2 -1
- package/src/live/attestation.ts +91 -0
- package/src/live/controller.ts +517 -0
- package/src/live/prompts/agent-final-message.md +3 -0
- package/src/live/prompts/live-instructions.md +23 -0
- package/src/live/protocol.test.ts +140 -0
- package/src/live/protocol.ts +233 -0
- package/src/live/transport.ts +422 -0
- package/src/live/visualizer.ts +214 -0
- package/src/lsp/client.ts +29 -9
- package/src/lsp/index.ts +19 -4
- package/src/main.ts +8 -1
- package/src/mcp/config-writer.test.ts +43 -0
- package/src/mcp/config-writer.ts +109 -82
- package/src/mcp/oauth-discovery.ts +10 -2
- package/src/mcp/smithery-auth.test.ts +29 -0
- package/src/mcp/smithery-auth.ts +3 -2
- package/src/memories/index.ts +40 -20
- package/src/memory-backend/tool-names.ts +2 -0
- package/src/mnemopi/backend.ts +24 -7
- package/src/modes/acp/acp-agent.ts +56 -10
- package/src/modes/acp/acp-event-mapper.ts +8 -1
- package/src/modes/components/agent-hub.ts +1 -1
- package/src/modes/components/assistant-message.ts +7 -2
- package/src/modes/components/custom-message.ts +4 -1
- package/src/modes/components/login-dialog.ts +14 -4
- package/src/modes/components/message-frame.ts +14 -8
- package/src/modes/components/plan-review-overlay.ts +350 -35
- package/src/modes/components/session-account-selector.ts +62 -0
- package/src/modes/components/settings-defs.ts +23 -1
- package/src/modes/components/settings-selector.ts +169 -1
- package/src/modes/components/status-line/component.jj-cache.test.ts +229 -0
- package/src/modes/components/status-line/component.ts +123 -2
- package/src/modes/components/tool-execution.ts +28 -112
- package/src/modes/controllers/command-controller.ts +56 -15
- package/src/modes/controllers/event-controller.ts +111 -16
- package/src/modes/controllers/extension-ui-controller.test.ts +1 -0
- package/src/modes/controllers/extension-ui-controller.ts +20 -4
- package/src/modes/controllers/input-controller.ts +47 -39
- package/src/modes/controllers/live-command-controller.ts +255 -0
- package/src/modes/controllers/mcp-command-controller.ts +10 -1
- package/src/modes/controllers/omfg-controller.ts +44 -40
- package/src/modes/controllers/selector-controller.ts +80 -10
- package/src/modes/controllers/session-focus-controller.ts +6 -1
- package/src/modes/interactive-mode.ts +176 -38
- package/src/modes/runtime-init.ts +2 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +17 -9
- package/src/modes/theme/theme.ts +1 -1
- package/src/modes/types.ts +4 -1
- package/src/modes/utils/context-usage.ts +23 -7
- package/src/modes/utils/ui-helpers.ts +10 -5
- package/src/plan-mode/plan-files.ts +40 -0
- package/src/prompts/bench/cache-prefix-chunk.md +1 -0
- package/src/prompts/bench/cache-prefix.md +3 -0
- package/src/prompts/bench/cache-suffix.md +1 -0
- package/src/prompts/system/computer-safety.md +14 -0
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/project-prompt.md +8 -1
- package/src/prompts/system/subagent-async-pending.md +6 -0
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/workflow-notice.md +48 -40
- package/src/prompts/system/xdev-mount-notice.md +4 -0
- package/src/prompts/tools/computer.md +26 -0
- package/src/prompts/tools/todo.md +3 -1
- package/src/registry/agent-lifecycle.ts +116 -46
- package/src/registry/agent-registry.ts +35 -8
- package/src/registry/persisted-agents.ts +26 -2
- package/src/sdk.ts +215 -136
- package/src/secrets/index.ts +127 -4
- package/src/secrets/obfuscator.ts +2328 -105
- package/src/session/acp-permission-gate.ts +165 -0
- package/src/session/agent-session-error-log.test.ts +1 -1
- package/src/session/agent-session-events.ts +66 -0
- package/src/session/agent-session-types.ts +343 -0
- package/src/session/agent-session.ts +1940 -12218
- package/src/session/artifacts.ts +6 -5
- package/src/session/async-job-delivery.ts +74 -0
- package/src/session/auth-storage.ts +1 -0
- package/src/session/bash-runner.ts +326 -0
- package/src/session/blob-store.test.ts +56 -0
- package/src/session/blob-store.ts +18 -2
- package/src/session/checkpoint-entries.ts +81 -0
- package/src/session/eval-runner.ts +217 -0
- package/src/session/indexed-session-storage.ts +9 -2
- package/src/session/irc-bridge.ts +203 -0
- package/src/session/messages.ts +266 -1
- package/src/session/model-controls.ts +714 -0
- package/src/session/prewalk.ts +252 -0
- package/src/session/queued-messages.ts +93 -0
- package/src/session/redis-session-storage.ts +51 -11
- package/src/session/retry-fallback-chains.ts +455 -0
- package/src/session/role-models.ts +85 -0
- package/src/session/session-advisors.ts +1679 -0
- package/src/session/session-context.ts +6 -3
- package/src/session/session-entries.ts +8 -0
- package/src/session/session-handoff.ts +308 -0
- package/src/session/session-history-format.ts +20 -9
- package/src/session/session-loader.ts +0 -46
- package/src/session/session-maintenance.ts +2983 -0
- package/src/session/session-manager.ts +390 -30
- package/src/session/session-memory.ts +222 -0
- package/src/session/session-provider-boundary.ts +307 -0
- package/src/session/session-stats.ts +293 -0
- package/src/session/session-tools.ts +980 -0
- package/src/session/session-workspace.ts +53 -0
- package/src/session/stream-guards.ts +417 -0
- package/src/session/streaming-output.ts +52 -5
- package/src/session/todo-tracker.ts +380 -0
- package/src/session/ttsr-coordinator.ts +496 -0
- package/src/session/turn-recovery.ts +1629 -0
- package/src/slash-commands/builtin-registry.ts +257 -20
- package/src/slash-commands/helpers/session-pin.ts +44 -0
- package/src/slash-commands/helpers/usage-report.ts +22 -3
- package/src/stt/downloader.ts +0 -2
- package/src/stt/index.ts +0 -2
- package/src/stt/stt-controller.ts +57 -146
- package/src/system-prompt.ts +45 -17
- package/src/task/executor.ts +285 -70
- package/src/task/index.ts +98 -105
- package/src/task/output-manager.ts +25 -3
- package/src/task/persisted-revive.ts +4 -3
- package/src/task/structured-subagent.ts +1 -0
- package/src/tiny/title-client.ts +22 -0
- package/src/tools/approval.ts +55 -10
- package/src/tools/bash-interactive.ts +116 -86
- package/src/tools/bash-skill-urls.ts +28 -2
- package/src/tools/bash.ts +339 -123
- package/src/tools/browser/launch.ts +9 -1
- package/src/tools/browser/tab-supervisor.ts +8 -5
- package/src/tools/browser.ts +94 -47
- package/src/tools/builtin-names.ts +1 -0
- package/src/tools/computer/protocol.ts +28 -0
- package/src/tools/computer/supervisor.ts +258 -0
- package/src/tools/computer/worker-entry.ts +25 -0
- package/src/tools/computer/worker.ts +135 -0
- package/src/tools/computer-renderer.ts +108 -0
- package/src/tools/computer.ts +433 -0
- package/src/tools/context.ts +2 -0
- package/src/tools/default-renderer.ts +139 -0
- package/src/tools/essential-tools.ts +1 -0
- package/src/tools/image-gen.ts +20 -28
- package/src/tools/image-providers.ts +50 -0
- package/src/tools/index.ts +14 -0
- package/src/tools/path-utils.ts +49 -2
- package/src/tools/read.ts +156 -88
- package/src/tools/renderers.ts +9 -1
- package/src/tools/todo.ts +101 -11
- package/src/tools/vibe.ts +1 -2
- package/src/tools/write.ts +51 -1
- package/src/tools/xdev.ts +121 -29
- package/src/tts/streaming-player.ts +82 -283
- package/src/tts/vocalizer.ts +18 -1
- package/src/utils/clipboard.ts +1 -30
- package/src/utils/jj.ts +125 -4
- package/src/utils/lang-from-path.ts +7 -0
- package/src/utils/mac-file-urls.applescript +37 -0
- package/src/utils/title-generator.ts +137 -1
- package/src/utils/tool-choice.ts +14 -0
- package/src/utils/tools-manager.ts +1 -19
- package/src/vibe/runtime.ts +852 -72
- package/src/web/search/index.ts +3 -6
- package/src/web/search/provider.ts +31 -16
- package/src/web/search/providers/xai.ts +7 -1
- package/src/web/search/types.ts +3 -0
- package/dist/types/stt/recorder.d.ts +0 -30
- package/dist/types/stt/transcriber.d.ts +0 -14
- package/dist/types/stt/wav.d.ts +0 -29
- package/dist/types/tts/player.d.ts +0 -32
- package/src/stt/recorder.ts +0 -551
- package/src/stt/transcriber.ts +0 -60
- package/src/stt/wav.ts +0 -173
- package/src/tts/player.ts +0 -137
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
resolveActiveProjectRegistryPath,
|
|
17
17
|
resolveOrDefaultProjectRegistryPath,
|
|
18
18
|
} from "../discovery/helpers.js";
|
|
19
|
+
import { parseExportArgs } from "../export/html/args";
|
|
19
20
|
import { shareSession } from "../export/share";
|
|
20
21
|
import { PluginManager } from "../extensibility/plugins";
|
|
21
22
|
import {
|
|
@@ -32,6 +33,7 @@ import { theme } from "../modes/theme/theme";
|
|
|
32
33
|
import type { InteractiveModeContext } from "../modes/types";
|
|
33
34
|
import { extractLastCodeBlock, extractLastCommand } from "../modes/utils/copy-targets";
|
|
34
35
|
import type { AgentSession, FreshSessionResult } from "../session/agent-session";
|
|
36
|
+
import type { SessionOAuthAccountList } from "../session/agent-session-types";
|
|
35
37
|
import { COMPACT_MODES, parseCompactArgs } from "../session/compact-modes";
|
|
36
38
|
import { resolveResumableSession } from "../session/session-listing";
|
|
37
39
|
import { formatShakeSummary, type ShakeMode } from "../session/shake-types";
|
|
@@ -51,6 +53,7 @@ import { createMarketplaceManager } from "./helpers/marketplace-manager";
|
|
|
51
53
|
import { handleMcpAcp } from "./helpers/mcp";
|
|
52
54
|
import { commandConsumed, errorMessage, parseSlashCommand, parseSubcommand, usage } from "./helpers/parse";
|
|
53
55
|
import { describeRedeemOutcome, type ResetUsageAccount, toResetUsageAccounts } from "./helpers/reset-usage";
|
|
56
|
+
import { matchSessionPinAccounts, toSessionPinAccounts } from "./helpers/session-pin";
|
|
54
57
|
import { handleSshAcp } from "./helpers/ssh";
|
|
55
58
|
import { launchStatsDashboard, parseStatsDashboardArgs } from "./helpers/stats-dashboard";
|
|
56
59
|
import { handleTodoAcp } from "./helpers/todo";
|
|
@@ -87,6 +90,26 @@ function formatFastModeStatus(session: AgentSession): string {
|
|
|
87
90
|
return session.isFastModeEnabled() ? "on" : "off";
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
/** `/computer status` label for the session-effective `computer.enabled` value. */
|
|
94
|
+
function formatComputerUseStatus(session: AgentSession): string {
|
|
95
|
+
return session.settings.get("computer.enabled") ? "on" : "off";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Apply a session-scoped computer-use toggle: flip the active tool slate first
|
|
100
|
+
* (so a failed enable never leaves a stale settings override), then record the
|
|
101
|
+
* runtime override — never `settings.set`, which would persist to settings.json.
|
|
102
|
+
* Returns the operator feedback line.
|
|
103
|
+
*/
|
|
104
|
+
async function applyComputerUseToggle(session: AgentSession, enable: boolean): Promise<string> {
|
|
105
|
+
const applied = await session.setComputerToolEnabled(enable);
|
|
106
|
+
if (enable && !applied) {
|
|
107
|
+
return "Computer use is unavailable in this session.";
|
|
108
|
+
}
|
|
109
|
+
session.settings.override("computer.enabled", enable);
|
|
110
|
+
return `Computer use ${enable ? "enabled" : "disabled"} for this session.`;
|
|
111
|
+
}
|
|
112
|
+
|
|
90
113
|
const AUTOCOMPLETE_DETAIL_LIMIT = 48;
|
|
91
114
|
|
|
92
115
|
function shortDetail(value: string, limit = AUTOCOMPLETE_DETAIL_LIMIT): string {
|
|
@@ -195,6 +218,74 @@ async function handleUsageResetCommand(
|
|
|
195
218
|
await output(describeRedeemOutcome(outcome, target.label));
|
|
196
219
|
}
|
|
197
220
|
|
|
221
|
+
async function handleSessionPinCommand(
|
|
222
|
+
arg: string,
|
|
223
|
+
session: AgentSession,
|
|
224
|
+
output: SlashCommandRuntime["output"],
|
|
225
|
+
): Promise<void> {
|
|
226
|
+
if (session.isStreaming) {
|
|
227
|
+
await output("Cannot pin an account while the session is streaming.");
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
let accountList: SessionOAuthAccountList | undefined;
|
|
231
|
+
try {
|
|
232
|
+
accountList = await session.listCurrentProviderOAuthAccounts();
|
|
233
|
+
} catch (error) {
|
|
234
|
+
await output(`Could not load provider accounts: ${errorMessage(error)}`);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (!accountList) {
|
|
238
|
+
await output("Select a model before pinning a provider account.");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const provider = getOAuthProviders().find(candidate => candidate.id === accountList.provider);
|
|
242
|
+
const providerName = provider?.name ?? accountList.provider;
|
|
243
|
+
const accounts = toSessionPinAccounts(accountList.accounts);
|
|
244
|
+
if (accounts.length === 0) {
|
|
245
|
+
const source = session.modelRegistry.authStorage.describeCredentialSource(
|
|
246
|
+
accountList.provider,
|
|
247
|
+
session.sessionId,
|
|
248
|
+
);
|
|
249
|
+
await output(
|
|
250
|
+
source
|
|
251
|
+
? `No stored OAuth accounts for ${providerName}. Current auth comes from ${source}.`
|
|
252
|
+
: `No stored OAuth accounts for ${providerName}. Use /login to add one.`,
|
|
253
|
+
);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const selector = arg.trim();
|
|
258
|
+
if (!selector) {
|
|
259
|
+
const lines = [`OAuth accounts for ${providerName}:`];
|
|
260
|
+
for (const account of accounts) {
|
|
261
|
+
lines.push(`${account.position + 1}. ${account.label}${account.active ? " (active)" : ""}`);
|
|
262
|
+
}
|
|
263
|
+
lines.push("", "Pin one with `/session pin <number|email|account id>`.");
|
|
264
|
+
await output(lines.join("\n"));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const matches = matchSessionPinAccounts(accounts, selector);
|
|
269
|
+
if (matches.length === 0) {
|
|
270
|
+
await output(`No ${providerName} account matches "${selector}".`);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (matches.length > 1) {
|
|
274
|
+
await output(
|
|
275
|
+
`"${selector}" matches multiple ${providerName} accounts: ${matches
|
|
276
|
+
.map(account => `${account.position + 1}. ${account.label}`)
|
|
277
|
+
.join(", ")}. Use the account number.`,
|
|
278
|
+
);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const account = matches[0];
|
|
282
|
+
if (!account || !session.pinCurrentProviderOAuthAccount(account.credentialId)) {
|
|
283
|
+
await output(`${account?.label ?? selector} is no longer available to pin.`);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
await output(`Pinned ${account.label} to this session for ${providerName}.`);
|
|
287
|
+
}
|
|
288
|
+
|
|
198
289
|
/** Parse the `/shake` subcommand into a {@link ShakeMode}; empty defaults to elide. */
|
|
199
290
|
function parseShakeMode(args: string): ShakeMode | { error: string } {
|
|
200
291
|
const verb = args.trim().toLowerCase();
|
|
@@ -203,6 +294,14 @@ function parseShakeMode(args: string): ShakeMode | { error: string } {
|
|
|
203
294
|
return { error: `Unknown /shake mode "${verb}". Use elide or images.` };
|
|
204
295
|
}
|
|
205
296
|
|
|
297
|
+
/** Format the session's workspace directories (cwd + additional) for display. */
|
|
298
|
+
function formatWorkspaceDirectories(runtime: SlashCommandRuntime, note?: string): string {
|
|
299
|
+
const cwd = runtime.sessionManager.getCwd();
|
|
300
|
+
const additional = runtime.sessionManager.getAdditionalDirectories();
|
|
301
|
+
const lines = ["Workspace directories:", ` ${cwd} (working directory)`, ...additional.map(d => ` ${d}`)];
|
|
302
|
+
return note ? `${note}\n${lines.join("\n")}` : lines.join("\n");
|
|
303
|
+
}
|
|
304
|
+
|
|
206
305
|
const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
207
306
|
{
|
|
208
307
|
name: "settings",
|
|
@@ -463,6 +562,49 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
463
562
|
runtime.ctx.editor.setText("");
|
|
464
563
|
},
|
|
465
564
|
},
|
|
565
|
+
{
|
|
566
|
+
name: "computer",
|
|
567
|
+
description: "Toggle the native computer-use tool for this session",
|
|
568
|
+
acpDescription: "Toggle computer use",
|
|
569
|
+
acpInputHint: "[on|off|status]",
|
|
570
|
+
subcommands: [
|
|
571
|
+
{ name: "on", description: "Enable computer use for this session" },
|
|
572
|
+
{ name: "off", description: "Disable computer use for this session" },
|
|
573
|
+
{ name: "status", description: "Show computer use status" },
|
|
574
|
+
],
|
|
575
|
+
allowArgs: true,
|
|
576
|
+
getTuiAutocompleteDescription: runtime => `Computer: ${formatComputerUseStatus(runtime.ctx.session)}`,
|
|
577
|
+
handle: async (command, runtime) => {
|
|
578
|
+
const arg = command.args.trim().toLowerCase();
|
|
579
|
+
if (arg === "status") {
|
|
580
|
+
await runtime.output(`Computer use is ${formatComputerUseStatus(runtime.session)}.`);
|
|
581
|
+
return commandConsumed();
|
|
582
|
+
}
|
|
583
|
+
if (!arg || arg === "toggle" || arg === "on" || arg === "off") {
|
|
584
|
+
const enable = arg === "off" ? false : arg === "on" || !runtime.session.settings.get("computer.enabled");
|
|
585
|
+
await runtime.output(await applyComputerUseToggle(runtime.session, enable));
|
|
586
|
+
return commandConsumed();
|
|
587
|
+
}
|
|
588
|
+
return usage("Usage: /computer [on|off|status]", runtime);
|
|
589
|
+
},
|
|
590
|
+
handleTui: async (command, runtime) => {
|
|
591
|
+
const arg = command.args.trim().toLowerCase();
|
|
592
|
+
if (arg === "status") {
|
|
593
|
+
runtime.ctx.showStatus(`Computer use is ${formatComputerUseStatus(runtime.ctx.session)}.`);
|
|
594
|
+
runtime.ctx.editor.setText("");
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
if (!arg || arg === "toggle" || arg === "on" || arg === "off") {
|
|
598
|
+
const enable =
|
|
599
|
+
arg === "off" ? false : arg === "on" || !runtime.ctx.session.settings.get("computer.enabled");
|
|
600
|
+
runtime.ctx.showStatus(await applyComputerUseToggle(runtime.ctx.session, enable));
|
|
601
|
+
runtime.ctx.editor.setText("");
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
runtime.ctx.showStatus("Usage: /computer [on|off|status]");
|
|
605
|
+
runtime.ctx.editor.setText("");
|
|
606
|
+
},
|
|
607
|
+
},
|
|
466
608
|
{
|
|
467
609
|
name: "prewalk",
|
|
468
610
|
description: "Switch to a fast/cheap model at the next action (works even without --prewalk)",
|
|
@@ -606,19 +748,15 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
606
748
|
{
|
|
607
749
|
name: "export",
|
|
608
750
|
description: "Export session to HTML file",
|
|
609
|
-
inlineHint: "[path]",
|
|
751
|
+
inlineHint: "[--themes] [path]",
|
|
610
752
|
allowArgs: true,
|
|
611
753
|
handle: async (command, runtime) => {
|
|
612
|
-
const arg = command.args.trim();
|
|
613
|
-
// Match the interactive `/export` behavior: clipboard aliases are not a
|
|
614
|
-
// valid export target. Without this, the literal value (`copy`,
|
|
615
|
-
// `--copy`, `clipboard`) is passed to `exportToHtml` and becomes the
|
|
616
|
-
// output filename.
|
|
617
|
-
if (arg === "--copy" || arg === "clipboard" || arg === "copy") {
|
|
618
|
-
return usage("Use /dump to copy the session to clipboard.", runtime);
|
|
619
|
-
}
|
|
620
754
|
try {
|
|
621
|
-
const
|
|
755
|
+
const { outputPath, useUserThemes } = parseExportArgs(command.args);
|
|
756
|
+
if (outputPath === "--copy" || outputPath === "clipboard" || outputPath === "copy") {
|
|
757
|
+
return usage("Use /dump to copy the session to clipboard.", runtime);
|
|
758
|
+
}
|
|
759
|
+
const filePath = await runtime.session.exportToHtml(outputPath, useUserThemes);
|
|
622
760
|
await runtime.output(`Session exported to: ${filePath}`);
|
|
623
761
|
return commandConsumed();
|
|
624
762
|
} catch (err) {
|
|
@@ -976,15 +1114,21 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
976
1114
|
{
|
|
977
1115
|
name: "session",
|
|
978
1116
|
description: "Session management commands",
|
|
979
|
-
acpDescription: "Show session
|
|
980
|
-
acpInputHint: "info|delete",
|
|
1117
|
+
acpDescription: "Show or configure the current session",
|
|
1118
|
+
acpInputHint: "[info|delete|pin [account]]",
|
|
981
1119
|
subcommands: [
|
|
982
1120
|
{ name: "info", description: "Show session info and stats" },
|
|
983
1121
|
{ name: "delete", description: "Delete current session and return to selector" },
|
|
1122
|
+
{
|
|
1123
|
+
name: "pin",
|
|
1124
|
+
description: "Pin the current provider to a stored OAuth account",
|
|
1125
|
+
usage: "[account]",
|
|
1126
|
+
},
|
|
984
1127
|
],
|
|
985
1128
|
allowArgs: true,
|
|
986
1129
|
handle: async (command, runtime) => {
|
|
987
|
-
|
|
1130
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
1131
|
+
if (!verb || (verb === "info" && !rest)) {
|
|
988
1132
|
await runtime.output(
|
|
989
1133
|
[
|
|
990
1134
|
`Session: ${runtime.session.sessionId}`,
|
|
@@ -994,7 +1138,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
994
1138
|
);
|
|
995
1139
|
return commandConsumed();
|
|
996
1140
|
}
|
|
997
|
-
if (
|
|
1141
|
+
if (verb === "delete" && !rest) {
|
|
998
1142
|
if (runtime.session.isStreaming) return usage("Cannot delete the session while streaming.", runtime);
|
|
999
1143
|
const sessionFile = runtime.sessionManager.getSessionFile();
|
|
1000
1144
|
if (!sessionFile) return usage("No session file to delete (in-memory session).", runtime);
|
|
@@ -1013,17 +1157,34 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
1013
1157
|
);
|
|
1014
1158
|
return commandConsumed();
|
|
1015
1159
|
}
|
|
1016
|
-
|
|
1160
|
+
if (verb === "pin") {
|
|
1161
|
+
await handleSessionPinCommand(rest, runtime.session, runtime.output);
|
|
1162
|
+
return commandConsumed();
|
|
1163
|
+
}
|
|
1164
|
+
return usage("Usage: /session [info|delete|pin [account]]", runtime);
|
|
1017
1165
|
},
|
|
1018
1166
|
handleTui: async (command, runtime) => {
|
|
1019
|
-
const
|
|
1020
|
-
if (
|
|
1167
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
1168
|
+
if (verb === "delete" && !rest) {
|
|
1021
1169
|
runtime.ctx.editor.setText("");
|
|
1022
1170
|
await runtime.ctx.handleSessionDeleteCommand();
|
|
1023
1171
|
return;
|
|
1024
1172
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1173
|
+
if (verb === "pin") {
|
|
1174
|
+
if (rest) {
|
|
1175
|
+
await handleSessionPinCommand(rest, runtime.ctx.session, text => runtime.ctx.showStatus(text));
|
|
1176
|
+
refreshStatusLine(runtime.ctx);
|
|
1177
|
+
} else {
|
|
1178
|
+
await runtime.ctx.showSessionPinSelector();
|
|
1179
|
+
}
|
|
1180
|
+
runtime.ctx.editor.setText("");
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
if (!verb || (verb === "info" && !rest)) {
|
|
1184
|
+
await runtime.ctx.handleSessionCommand();
|
|
1185
|
+
} else {
|
|
1186
|
+
runtime.ctx.showStatus("Usage: /session [info|delete|pin [account]]");
|
|
1187
|
+
}
|
|
1027
1188
|
runtime.ctx.editor.setText("");
|
|
1028
1189
|
},
|
|
1029
1190
|
},
|
|
@@ -1712,7 +1873,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
1712
1873
|
return usage(`Failed to save pending settings: ${errorMessage(err)}`, runtime);
|
|
1713
1874
|
}
|
|
1714
1875
|
try {
|
|
1715
|
-
await runtime.
|
|
1876
|
+
await runtime.session.moveSession(resolvedPath);
|
|
1716
1877
|
} catch (err) {
|
|
1717
1878
|
return usage(`Move failed: ${errorMessage(err)}`, runtime);
|
|
1718
1879
|
}
|
|
@@ -1733,6 +1894,74 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
1733
1894
|
await runtime.ctx.handleMoveCommand(command.args || undefined);
|
|
1734
1895
|
},
|
|
1735
1896
|
},
|
|
1897
|
+
{
|
|
1898
|
+
name: "add-dir",
|
|
1899
|
+
description: "Add a workspace directory to this session (multi-root)",
|
|
1900
|
+
acpDescription: "Add a workspace directory to this session",
|
|
1901
|
+
inlineHint: "<path>",
|
|
1902
|
+
allowArgs: true,
|
|
1903
|
+
handle: async (command, runtime) => {
|
|
1904
|
+
if (runtime.session.isStreaming) return usage("Cannot add a directory while streaming.", runtime);
|
|
1905
|
+
if (!command.args) return usage(formatWorkspaceDirectories(runtime, "Usage: /add-dir <path>"), runtime);
|
|
1906
|
+
const resolved = resolveToCwd(command.args, runtime.cwd);
|
|
1907
|
+
try {
|
|
1908
|
+
const stat = await fs.stat(resolved);
|
|
1909
|
+
if (!stat.isDirectory()) return usage(`Not a directory: ${resolved}`, runtime);
|
|
1910
|
+
} catch {
|
|
1911
|
+
return usage(`Directory does not exist: ${resolved}`, runtime);
|
|
1912
|
+
}
|
|
1913
|
+
let added: string | null;
|
|
1914
|
+
try {
|
|
1915
|
+
added = await runtime.sessionManager.addWorkspaceDirectory(resolved);
|
|
1916
|
+
} catch (err) {
|
|
1917
|
+
return usage(errorMessage(err), runtime);
|
|
1918
|
+
}
|
|
1919
|
+
if (added === null) {
|
|
1920
|
+
await runtime.output(`Already in the workspace: ${resolved}`);
|
|
1921
|
+
return commandConsumed();
|
|
1922
|
+
}
|
|
1923
|
+
await runtime.session.refreshBaseSystemPrompt();
|
|
1924
|
+
await runtime.output(formatWorkspaceDirectories(runtime, `Added ${added}.`));
|
|
1925
|
+
return commandConsumed();
|
|
1926
|
+
},
|
|
1927
|
+
},
|
|
1928
|
+
{
|
|
1929
|
+
name: "remove-dir",
|
|
1930
|
+
description: "Remove a workspace directory from this session",
|
|
1931
|
+
acpDescription: "Remove a workspace directory from this session",
|
|
1932
|
+
inlineHint: "<path>",
|
|
1933
|
+
allowArgs: true,
|
|
1934
|
+
handle: async (command, runtime) => {
|
|
1935
|
+
if (runtime.session.isStreaming) return usage("Cannot remove a directory while streaming.", runtime);
|
|
1936
|
+
if (!command.args) return usage("Usage: /remove-dir <path>", runtime);
|
|
1937
|
+
const resolved = resolveToCwd(command.args, runtime.cwd);
|
|
1938
|
+
if (resolved === path.resolve(runtime.cwd)) {
|
|
1939
|
+
return usage("Cannot remove the working directory; use /move to change it.", runtime);
|
|
1940
|
+
}
|
|
1941
|
+
let removed: string | null;
|
|
1942
|
+
try {
|
|
1943
|
+
removed = await runtime.sessionManager.removeWorkspaceDirectory(resolved);
|
|
1944
|
+
} catch (err) {
|
|
1945
|
+
return usage(errorMessage(err), runtime);
|
|
1946
|
+
}
|
|
1947
|
+
if (removed === null) {
|
|
1948
|
+
await runtime.output(`Not a workspace directory: ${resolved}`);
|
|
1949
|
+
return commandConsumed();
|
|
1950
|
+
}
|
|
1951
|
+
await runtime.session.refreshBaseSystemPrompt();
|
|
1952
|
+
await runtime.output(formatWorkspaceDirectories(runtime, `Removed ${removed}.`));
|
|
1953
|
+
return commandConsumed();
|
|
1954
|
+
},
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
name: "dirs",
|
|
1958
|
+
description: "List this session's workspace directories",
|
|
1959
|
+
acpDescription: "List this session's workspace directories",
|
|
1960
|
+
handle: async (_command, runtime) => {
|
|
1961
|
+
await runtime.output(formatWorkspaceDirectories(runtime));
|
|
1962
|
+
return commandConsumed();
|
|
1963
|
+
},
|
|
1964
|
+
},
|
|
1736
1965
|
{
|
|
1737
1966
|
name: "exit",
|
|
1738
1967
|
description: "Exit the application",
|
|
@@ -2317,6 +2546,14 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
2317
2546
|
if (prompt) return { prompt };
|
|
2318
2547
|
},
|
|
2319
2548
|
},
|
|
2549
|
+
{
|
|
2550
|
+
name: "live",
|
|
2551
|
+
description: "Start Codex-backed realtime voice mode",
|
|
2552
|
+
handleTui: async (_command, runtime) => {
|
|
2553
|
+
runtime.ctx.editor.setText("");
|
|
2554
|
+
await runtime.ctx.handleLiveCommand();
|
|
2555
|
+
},
|
|
2556
|
+
},
|
|
2320
2557
|
{
|
|
2321
2558
|
name: "pause",
|
|
2322
2559
|
description: "Freeze all agents (main, subagents, advisor) until resumed",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { OAuthAccountSummary } from "../../session/auth-storage";
|
|
2
|
+
import { formatActiveAccountLabel } from "./active-oauth-account";
|
|
3
|
+
|
|
4
|
+
/** Stored OAuth account rendered and matched by `/session pin`. */
|
|
5
|
+
export interface SessionPinAccount extends OAuthAccountSummary {
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Add stable user-facing labels to provider account summaries. */
|
|
10
|
+
export function toSessionPinAccounts(accounts: readonly OAuthAccountSummary[]): SessionPinAccount[] {
|
|
11
|
+
return accounts.map(account => {
|
|
12
|
+
const enterpriseUrl = account.enterpriseUrl?.trim();
|
|
13
|
+
return {
|
|
14
|
+
...account,
|
|
15
|
+
label: (formatActiveAccountLabel(account) ?? enterpriseUrl) || `OAuth credential #${account.credentialId}`,
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Match a `/session pin` selector by 1-based position or exact account identity. */
|
|
21
|
+
export function matchSessionPinAccounts(accounts: readonly SessionPinAccount[], selector: string): SessionPinAccount[] {
|
|
22
|
+
const wanted = selector.trim().toLowerCase();
|
|
23
|
+
if (!wanted) return [];
|
|
24
|
+
if (wanted === "active") return accounts.filter(account => account.active);
|
|
25
|
+
|
|
26
|
+
if (/^\d+$/.test(wanted)) {
|
|
27
|
+
const position = Number(wanted) - 1;
|
|
28
|
+
const positioned = accounts.find(account => account.position === position);
|
|
29
|
+
if (positioned) return [positioned];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return accounts.filter(account =>
|
|
33
|
+
[
|
|
34
|
+
account.label,
|
|
35
|
+
account.email,
|
|
36
|
+
account.accountId,
|
|
37
|
+
account.projectId,
|
|
38
|
+
account.enterpriseUrl,
|
|
39
|
+
account.orgId,
|
|
40
|
+
account.orgName,
|
|
41
|
+
`OAuth credential #${account.credentialId}`,
|
|
42
|
+
].some(value => value?.trim().toLowerCase() === wanted),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -12,6 +12,14 @@ function formatProviderName(provider: string): string {
|
|
|
12
12
|
.join(" ");
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
function formatWindowSuffix(label: string, windowLabel: string | undefined): string {
|
|
16
|
+
if (!windowLabel) return "";
|
|
17
|
+
const normalizedLabel = label.toLowerCase();
|
|
18
|
+
const normalizedWindow = windowLabel.toLowerCase();
|
|
19
|
+
if (normalizedWindow === "quota window" || normalizedLabel.includes(normalizedWindow)) return "";
|
|
20
|
+
return ` — ${windowLabel}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
function formatUsageAmount(limit: UsageLimit): string {
|
|
16
24
|
const amount = limit.amount;
|
|
17
25
|
const used = amount.used ?? (amount.usedFraction !== undefined ? amount.usedFraction * 100 : undefined);
|
|
@@ -55,6 +63,7 @@ function renderUsageReports(
|
|
|
55
63
|
reports: UsageReport[],
|
|
56
64
|
nowMs: number,
|
|
57
65
|
resolveActiveAccount?: (provider: string) => OAuthAccountIdentity | undefined,
|
|
66
|
+
usageModelSelectors: readonly string[] = [],
|
|
58
67
|
): string {
|
|
59
68
|
const latestFetchedAt = Math.max(...reports.map(report => report.fetchedAt ?? 0));
|
|
60
69
|
const lines = [`Usage${latestFetchedAt ? ` (${formatDuration(nowMs - latestFetchedAt)} ago)` : ""}`];
|
|
@@ -69,6 +78,11 @@ function renderUsageReports(
|
|
|
69
78
|
left.localeCompare(right),
|
|
70
79
|
)) {
|
|
71
80
|
lines.push("", formatProviderName(provider));
|
|
81
|
+
const reportingModels = usageModelSelectors.filter(selector => selector.startsWith(`${provider}/`));
|
|
82
|
+
if (reportingModels.length > 0) {
|
|
83
|
+
lines.push(" Models with usage data");
|
|
84
|
+
for (const selector of reportingModels) lines.push(` ${sanitizeText(selector)}`);
|
|
85
|
+
}
|
|
72
86
|
const activeAccount = resolveActiveAccount?.(provider);
|
|
73
87
|
// Provider-wide disclaimers render once per provider, not per limit.
|
|
74
88
|
const providerNotes = [...new Set(providerReports.flatMap(report => report.notes ?? []))];
|
|
@@ -118,7 +132,7 @@ function renderUsageReports(
|
|
|
118
132
|
limit.scope.tier && !limit.label.toLowerCase().includes(limit.scope.tier.toLowerCase())
|
|
119
133
|
? ` (${limit.scope.tier})`
|
|
120
134
|
: "";
|
|
121
|
-
lines.push(`- ${limit.label}${tier}${
|
|
135
|
+
lines.push(`- ${limit.label}${tier}${formatWindowSuffix(limit.label, window)}`);
|
|
122
136
|
lines.push(
|
|
123
137
|
` ${formatUsageReportAccount(report, limit, index)}: ${formatUsageAmount(limit)}${inUse ? " ← in use by this session" : ""}`,
|
|
124
138
|
);
|
|
@@ -146,6 +160,7 @@ function renderUsageReports(
|
|
|
146
160
|
export async function buildUsageReportText(runtime: SlashCommandRuntime): Promise<string> {
|
|
147
161
|
const provider = runtime.session as SlashCommandRuntime["session"] & {
|
|
148
162
|
fetchUsageReports?: () => Promise<UsageReport[] | null>;
|
|
163
|
+
getUsageReportingModelSelectors?: (reports: readonly UsageReport[]) => string[];
|
|
149
164
|
};
|
|
150
165
|
if (provider.fetchUsageReports) {
|
|
151
166
|
const reports = await provider.fetchUsageReports();
|
|
@@ -157,8 +172,12 @@ export async function buildUsageReportText(runtime: SlashCommandRuntime): Promis
|
|
|
157
172
|
runtime.session.sessionId,
|
|
158
173
|
)
|
|
159
174
|
: undefined;
|
|
160
|
-
|
|
161
|
-
|
|
175
|
+
const usageModelSelectors = provider.getUsageReportingModelSelectors?.(reports) ?? [];
|
|
176
|
+
return renderUsageReports(
|
|
177
|
+
reports,
|
|
178
|
+
Date.now(),
|
|
179
|
+
providerId => (providerId === currentProvider ? activeAccount : undefined),
|
|
180
|
+
usageModelSelectors,
|
|
162
181
|
);
|
|
163
182
|
}
|
|
164
183
|
}
|
package/src/stt/downloader.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { getTinyModelsCacheDir } from "@oh-my-pi/pi-utils";
|
|
|
4
4
|
import { sttClient } from "./asr-client";
|
|
5
5
|
import type { SttProgressStatus } from "./asr-protocol";
|
|
6
6
|
import { resolveSttModelSpec } from "./models";
|
|
7
|
-
import { ensureRecorder } from "./recorder";
|
|
8
7
|
|
|
9
8
|
export interface DownloadProgress {
|
|
10
9
|
stage: string;
|
|
@@ -129,7 +128,6 @@ export async function downloadSttModel(
|
|
|
129
128
|
// ── Public API ─────────────────────────────────────────────────────
|
|
130
129
|
|
|
131
130
|
export async function ensureSTTDependencies(options?: EnsureOptions): Promise<void> {
|
|
132
|
-
await ensureRecorder(progress => options?.onProgress?.(progress), options?.signal);
|
|
133
131
|
await downloadSttModel(
|
|
134
132
|
resolveSttModelSpec(options?.modelName).key,
|
|
135
133
|
progress => {
|