@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
|
@@ -1,22 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import { logger, Snowflake } from "@oh-my-pi/pi-utils";
|
|
1
|
+
import { AudioCapture } from "@oh-my-pi/pi-natives";
|
|
2
|
+
import { logger } from "@oh-my-pi/pi-utils";
|
|
5
3
|
import { settings } from "../config/settings";
|
|
6
4
|
import { type SttStreamHandle, sttClient } from "./asr-client";
|
|
7
5
|
import { downloadSttModel, isSttModelCached } from "./downloader";
|
|
8
6
|
import { resolveSttModelSpec } from "./models";
|
|
9
|
-
import {
|
|
10
|
-
detectRecorder,
|
|
11
|
-
ensureRecorder,
|
|
12
|
-
type RecordingHandle,
|
|
13
|
-
type StreamingRecordingHandle,
|
|
14
|
-
startRecording,
|
|
15
|
-
startStreamingRecording,
|
|
16
|
-
verifyRecordingFile,
|
|
17
|
-
} from "./recorder";
|
|
18
7
|
import { evaluateSubmitTrigger } from "./submit-trigger";
|
|
19
|
-
import { transcribe } from "./transcriber";
|
|
20
8
|
|
|
21
9
|
export type SttState = "idle" | "recording" | "transcribing";
|
|
22
10
|
|
|
@@ -38,26 +26,34 @@ interface Editor {
|
|
|
38
26
|
deleteBeforeCursor(count: number): void;
|
|
39
27
|
}
|
|
40
28
|
|
|
29
|
+
interface CaptureHandle {
|
|
30
|
+
stop(): void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type CaptureFactory = (onAudio: (error: Error | null, samples: Float32Array) => void) => CaptureHandle;
|
|
34
|
+
|
|
35
|
+
/** Coordinates native microphone capture with incremental local transcription. */
|
|
41
36
|
export class STTController {
|
|
42
37
|
#state: SttState = "idle";
|
|
43
38
|
#resolvedModelKey: string | null = null;
|
|
44
39
|
#toggling = false;
|
|
45
40
|
#stopAfterStart = false;
|
|
46
41
|
#disposed = false;
|
|
47
|
-
|
|
48
|
-
// Batch (single-shot) capture.
|
|
49
|
-
#recordingHandle: RecordingHandle | null = null;
|
|
50
|
-
#tempFile: string | null = null;
|
|
51
|
-
#transcriptionAbort: AbortController | null = null;
|
|
42
|
+
readonly #createCapture: CaptureFactory;
|
|
52
43
|
|
|
53
44
|
// Live streaming capture.
|
|
54
45
|
#stream: SttStreamHandle | null = null;
|
|
55
|
-
#streamRecorder:
|
|
46
|
+
#streamRecorder: CaptureHandle | null = null;
|
|
56
47
|
#streamEditor: Editor | null = null;
|
|
57
48
|
#streamCommitted = false;
|
|
58
49
|
#streamAbort: AbortController | null = null;
|
|
59
50
|
#streamUtterance = "";
|
|
60
51
|
|
|
52
|
+
/** Creates a controller; tests may replace the hardware capture boundary. */
|
|
53
|
+
constructor(createCapture: CaptureFactory = onAudio => new AudioCapture(16_000, onAudio)) {
|
|
54
|
+
this.#createCapture = createCapture;
|
|
55
|
+
}
|
|
56
|
+
|
|
61
57
|
get state(): SttState {
|
|
62
58
|
return this.#state;
|
|
63
59
|
}
|
|
@@ -79,7 +75,7 @@ export class STTController {
|
|
|
79
75
|
await this.#start(editor, options);
|
|
80
76
|
break;
|
|
81
77
|
case "recording":
|
|
82
|
-
await this.#stop(
|
|
78
|
+
await this.#stop(options);
|
|
83
79
|
break;
|
|
84
80
|
case "transcribing":
|
|
85
81
|
options.showStatus("Transcription in progress...");
|
|
@@ -87,7 +83,7 @@ export class STTController {
|
|
|
87
83
|
}
|
|
88
84
|
if (this.#stopAfterStart && this.#state === "recording") {
|
|
89
85
|
this.#stopAfterStart = false;
|
|
90
|
-
await this.#stop(
|
|
86
|
+
await this.#stop(options);
|
|
91
87
|
} else if (this.#state !== "recording") {
|
|
92
88
|
this.#stopAfterStart = false;
|
|
93
89
|
}
|
|
@@ -103,19 +99,13 @@ export class STTController {
|
|
|
103
99
|
// (with progress) instead of blocking silently at stop.
|
|
104
100
|
if (this.#resolvedModelKey === modelKey) return true;
|
|
105
101
|
try {
|
|
106
|
-
// Only clear the status line
|
|
107
|
-
// fast path
|
|
108
|
-
// unconditional clear would be a stray write.
|
|
102
|
+
// Only clear the status line when preflight emitted progress; the
|
|
103
|
+
// cached-model fast path emits nothing.
|
|
109
104
|
let wroteStatus = false;
|
|
110
105
|
const status = (msg: string): void => {
|
|
111
106
|
wroteStatus = true;
|
|
112
107
|
options.showStatus(msg);
|
|
113
108
|
};
|
|
114
|
-
// A recorder is required to capture audio; startRecording /
|
|
115
|
-
// startStreamingRecording only *detect* a recorder and throw when none
|
|
116
|
-
// exists, so provision one here. Instant when sox/ffmpeg/arecord is on
|
|
117
|
-
// PATH — only a first-run static-ffmpeg download actually blocks.
|
|
118
|
-
await ensureRecorder(p => status(p.stage + (p.percent != null ? ` (${p.percent}%)` : "")));
|
|
119
109
|
// Loading the multi-hundred-MB speech model into the worker is what made
|
|
120
110
|
// the old "Checking STT dependencies…" step slow. Don't pay it before
|
|
121
111
|
// recording: when the weights are already cached, start now and warm the
|
|
@@ -157,30 +147,15 @@ export class STTController {
|
|
|
157
147
|
|
|
158
148
|
async #start(editor: Editor, options: ToggleOptions): Promise<void> {
|
|
159
149
|
if (!(await this.#ensureDeps(options))) return;
|
|
160
|
-
|
|
161
|
-
// PowerShell mci fallback records to a file, so it stays single-shot.
|
|
162
|
-
if (this.#recorderCanStream()) {
|
|
163
|
-
await this.#startStreaming(editor, options);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
await this.#startBatchRecording(options);
|
|
150
|
+
await this.#startStreaming(editor, options);
|
|
167
151
|
}
|
|
168
152
|
|
|
169
|
-
async #stop(
|
|
170
|
-
|
|
171
|
-
await this.#stopStreaming(options);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
await this.#stopBatch(editor, options);
|
|
153
|
+
async #stop(options: ToggleOptions): Promise<void> {
|
|
154
|
+
await this.#stopStreaming(options);
|
|
175
155
|
}
|
|
176
156
|
|
|
177
157
|
// ── Live streaming ──────────────────────────────────────────────
|
|
178
158
|
|
|
179
|
-
#recorderCanStream(): boolean {
|
|
180
|
-
const recorder = detectRecorder();
|
|
181
|
-
return recorder !== null && recorder.tool !== "powershell";
|
|
182
|
-
}
|
|
183
|
-
|
|
184
159
|
/** Segment text gets a leading space once a prior segment is committed, so
|
|
185
160
|
* phrases join naturally; the first phrase is inserted at the cursor as-is. */
|
|
186
161
|
#prefixed(text: string): string {
|
|
@@ -218,18 +193,38 @@ export class STTController {
|
|
|
218
193
|
},
|
|
219
194
|
});
|
|
220
195
|
this.#stream = stream;
|
|
221
|
-
let recorder:
|
|
196
|
+
let recorder: CaptureHandle;
|
|
222
197
|
try {
|
|
223
|
-
recorder =
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
198
|
+
recorder = this.#createCapture((error, samples) => {
|
|
199
|
+
if (this.#disposed || this.#stream !== stream || this.#state !== "recording") return;
|
|
200
|
+
if (error) {
|
|
201
|
+
logger.error("Native microphone capture failed", { error: error.message });
|
|
202
|
+
const activeRecorder = this.#streamRecorder;
|
|
203
|
+
this.#streamRecorder = null;
|
|
204
|
+
try {
|
|
205
|
+
activeRecorder?.stop();
|
|
206
|
+
} catch (cause) {
|
|
207
|
+
logger.debug("stt: microphone cleanup failed", {
|
|
208
|
+
error: cause instanceof Error ? cause.message : String(cause),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
this.#streamAbort?.abort(error);
|
|
212
|
+
stream.cancel();
|
|
213
|
+
this.#streamEditor?.clearVolatileText();
|
|
214
|
+
options.requestRender?.();
|
|
215
|
+
this.#cleanupStream();
|
|
216
|
+
this.#setState("idle", options);
|
|
217
|
+
options.showWarning(error.message);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
stream.pushAudio(samples);
|
|
227
221
|
});
|
|
228
|
-
}
|
|
229
|
-
if (!recorder) {
|
|
222
|
+
} catch (err) {
|
|
230
223
|
stream.cancel();
|
|
231
224
|
this.#cleanupStream();
|
|
232
|
-
|
|
225
|
+
const msg = err instanceof Error ? err.message : "Failed to start microphone capture";
|
|
226
|
+
options.showWarning(msg);
|
|
227
|
+
logger.error("STT recording failed to start", { error: msg });
|
|
233
228
|
return;
|
|
234
229
|
}
|
|
235
230
|
this.#streamRecorder = recorder;
|
|
@@ -247,7 +242,7 @@ export class STTController {
|
|
|
247
242
|
this.#setState("transcribing", options);
|
|
248
243
|
// Stop the mic first so no further audio is fed, then flush the worker.
|
|
249
244
|
try {
|
|
250
|
-
|
|
245
|
+
recorder?.stop();
|
|
251
246
|
} catch (err) {
|
|
252
247
|
logger.debug("stt: streaming recorder stop failed", {
|
|
253
248
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -306,103 +301,19 @@ export class STTController {
|
|
|
306
301
|
this.#streamUtterance = "";
|
|
307
302
|
}
|
|
308
303
|
|
|
309
|
-
// ── Batch (single-shot) ─────────────────────────────────────────
|
|
310
|
-
|
|
311
|
-
async #startBatchRecording(options: ToggleOptions): Promise<void> {
|
|
312
|
-
const id = Snowflake.next();
|
|
313
|
-
this.#tempFile = path.join(os.tmpdir(), `omp-stt-${id}.wav`);
|
|
314
|
-
try {
|
|
315
|
-
this.#recordingHandle = await startRecording(this.#tempFile);
|
|
316
|
-
this.#setState("recording", options);
|
|
317
|
-
logger.debug("STT recording started", { tempFile: this.#tempFile });
|
|
318
|
-
} catch (err) {
|
|
319
|
-
this.#tempFile = null;
|
|
320
|
-
const msg = err instanceof Error ? err.message : "Failed to start recording";
|
|
321
|
-
options.showWarning(msg);
|
|
322
|
-
logger.error("STT recording failed to start", { error: msg });
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
async #stopBatch(editor: Editor, options: ToggleOptions): Promise<void> {
|
|
327
|
-
const handle = this.#recordingHandle;
|
|
328
|
-
const tempFile = this.#tempFile;
|
|
329
|
-
this.#recordingHandle = null;
|
|
330
|
-
|
|
331
|
-
if (!handle || !tempFile) {
|
|
332
|
-
this.#setState("idle", options);
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
try {
|
|
337
|
-
await handle.stop();
|
|
338
|
-
// Validate the recording produced a usable file
|
|
339
|
-
await verifyRecordingFile(tempFile);
|
|
340
|
-
this.#setState("transcribing", options);
|
|
341
|
-
|
|
342
|
-
const sttSettings = {
|
|
343
|
-
modelName: settings.get("stt.modelName") as string | undefined,
|
|
344
|
-
language: settings.get("stt.language") as string | undefined,
|
|
345
|
-
};
|
|
346
|
-
this.#transcriptionAbort = new AbortController();
|
|
347
|
-
const text = await transcribe(tempFile, { ...sttSettings, signal: this.#transcriptionAbort.signal });
|
|
348
|
-
this.#transcriptionAbort = null;
|
|
349
|
-
if (this.#disposed) return;
|
|
350
|
-
if (text.length > 0) {
|
|
351
|
-
const trigger = settings.get("stt.submitTrigger");
|
|
352
|
-
const { submit, trimTrailing } = evaluateSubmitTrigger(text, trigger);
|
|
353
|
-
const textToInsert = trimTrailing > 0 ? text.slice(0, -trimTrailing) : text;
|
|
354
|
-
if (textToInsert.length > 0) {
|
|
355
|
-
editor.insertText(textToInsert);
|
|
356
|
-
}
|
|
357
|
-
options.showStatus("");
|
|
358
|
-
if (submit) {
|
|
359
|
-
editor.submit();
|
|
360
|
-
}
|
|
361
|
-
} else {
|
|
362
|
-
options.showStatus("No speech detected.");
|
|
363
|
-
}
|
|
364
|
-
if (!this.#disposed) this.#setState("idle", options);
|
|
365
|
-
} catch (err) {
|
|
366
|
-
if (this.#disposed) return;
|
|
367
|
-
if (err instanceof DOMException && err.name === "AbortError") {
|
|
368
|
-
this.#setState("idle", options);
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
const msg = err instanceof Error ? err.message : "Transcription failed";
|
|
372
|
-
options.showWarning(msg);
|
|
373
|
-
logger.error("STT transcription failed", { error: msg });
|
|
374
|
-
this.#setState("idle", options);
|
|
375
|
-
} finally {
|
|
376
|
-
try {
|
|
377
|
-
await fs.rm(tempFile, { force: true });
|
|
378
|
-
} catch {
|
|
379
|
-
// best effort cleanup
|
|
380
|
-
}
|
|
381
|
-
this.#tempFile = null;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
304
|
dispose(): void {
|
|
386
305
|
this.#disposed = true;
|
|
387
|
-
if (this.#transcriptionAbort) {
|
|
388
|
-
this.#transcriptionAbort.abort();
|
|
389
|
-
this.#transcriptionAbort = null;
|
|
390
|
-
}
|
|
391
306
|
if (this.#streamAbort) {
|
|
392
307
|
this.#streamAbort.abort();
|
|
393
308
|
this.#streamAbort = null;
|
|
394
309
|
}
|
|
395
310
|
this.#stream?.cancel();
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
this.#recordingHandle = null;
|
|
401
|
-
}
|
|
402
|
-
if (this.#tempFile) {
|
|
403
|
-
fs.rm(this.#tempFile, { force: true }).catch(() => {});
|
|
404
|
-
this.#tempFile = null;
|
|
311
|
+
try {
|
|
312
|
+
this.#streamRecorder?.stop();
|
|
313
|
+
} catch {
|
|
314
|
+
// best effort cleanup
|
|
405
315
|
}
|
|
316
|
+
this.#cleanupStream();
|
|
406
317
|
this.#state = "idle";
|
|
407
318
|
this.#resolvedModelKey = null;
|
|
408
319
|
}
|
package/src/system-prompt.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as os from "node:os";
|
|
6
|
+
import * as path from "node:path";
|
|
6
7
|
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
7
8
|
import type { ToolExample, TSchema } from "@oh-my-pi/pi-ai";
|
|
8
9
|
import { renderToolInventory } from "@oh-my-pi/pi-ai/dialect";
|
|
@@ -16,6 +17,7 @@ import { expandAtImports } from "./discovery/at-imports";
|
|
|
16
17
|
import { loadSkills, type Skill } from "./extensibility/skills";
|
|
17
18
|
import { hasObsidian } from "./internal-urls/vault-protocol";
|
|
18
19
|
import activeRepoContextTemplate from "./prompts/system/active-repo-context.md" with { type: "text" };
|
|
20
|
+
import computerSafetyPrompt from "./prompts/system/computer-safety.md" with { type: "text" };
|
|
19
21
|
import customSystemPromptTemplate from "./prompts/system/custom-system-prompt.md" with { type: "text" };
|
|
20
22
|
import defaultPersonality from "./prompts/system/personalities/default.md" with { type: "text" };
|
|
21
23
|
import friendlyPersonality from "./prompts/system/personalities/friendly.md" with { type: "text" };
|
|
@@ -466,6 +468,8 @@ export interface BuildSystemPromptOptions {
|
|
|
466
468
|
skillsSettings?: SkillsSettings;
|
|
467
469
|
/** Working directory. Default: getProjectDir() */
|
|
468
470
|
cwd?: string;
|
|
471
|
+
/** Additional workspace directories beyond cwd (multi-root), absolute. Injected into the project prompt. */
|
|
472
|
+
additionalWorkspaceRoots?: string[];
|
|
469
473
|
/** Pre-loaded context files (skips discovery if provided). */
|
|
470
474
|
contextFiles?: Array<{ path: string; content: string; depth?: number }>;
|
|
471
475
|
/** Skills provided directly to system prompt construction. */
|
|
@@ -535,6 +539,7 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
535
539
|
skillsSettings,
|
|
536
540
|
toolNames: providedToolNames,
|
|
537
541
|
cwd,
|
|
542
|
+
additionalWorkspaceRoots = [],
|
|
538
543
|
contextFiles: providedContextFiles,
|
|
539
544
|
skills: providedSkills,
|
|
540
545
|
rules,
|
|
@@ -619,23 +624,42 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
619
624
|
const systemPromptCustomizationPromise: Promise<string | null> = callerControlsCustomPrompt
|
|
620
625
|
? Promise.resolve(null)
|
|
621
626
|
: logger.time("loadSystemPromptFiles", loadSystemPromptFiles, { cwd: resolvedCwd });
|
|
622
|
-
const contextFilesPromise =
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
627
|
+
const contextFilesPromise = (async () => {
|
|
628
|
+
const primary = providedContextFiles
|
|
629
|
+
? providedContextFiles
|
|
630
|
+
: await logger.time("loadProjectContextFiles", loadProjectContextFiles, { cwd: resolvedCwd });
|
|
631
|
+
// Also discover context files (AGENTS.md, rules, etc.) for each additional workspace root.
|
|
632
|
+
const additionalRoots = additionalWorkspaceRoots.filter(d => path.resolve(d) !== path.resolve(resolvedCwd));
|
|
633
|
+
if (additionalRoots.length === 0) return primary;
|
|
634
|
+
const extra = await Promise.all(
|
|
635
|
+
additionalRoots.map(root => loadProjectContextFiles({ cwd: root }).catch(() => [])),
|
|
636
|
+
);
|
|
637
|
+
return dedupeExactContextFiles([...primary, ...extra.flat()]);
|
|
638
|
+
})();
|
|
639
|
+
const additionalRootsForTree = additionalWorkspaceRoots.filter(d => path.resolve(d) !== path.resolve(resolvedCwd));
|
|
640
|
+
const workspaceTreePromise = (async () => {
|
|
641
|
+
const primary =
|
|
642
|
+
providedWorkspaceTree !== undefined
|
|
643
|
+
? await Promise.resolve(providedWorkspaceTree)
|
|
644
|
+
: includeWorkspaceTree
|
|
645
|
+
? await logger.time("buildWorkspaceTree", () =>
|
|
646
|
+
buildWorkspaceTree(resolvedCwd, { timeoutMs: SYSTEM_PROMPT_PREP_TIMEOUT_MS }),
|
|
647
|
+
)
|
|
648
|
+
: { rootPath: resolvedCwd, rendered: "", truncated: false, totalLines: 0, agentsMdFiles: [] };
|
|
649
|
+
if (additionalRootsForTree.length === 0 || !includeWorkspaceTree) return primary;
|
|
650
|
+
const extraTrees = await Promise.all(
|
|
651
|
+
additionalRootsForTree.map(root =>
|
|
652
|
+
buildWorkspaceTree(root, { timeoutMs: SYSTEM_PROMPT_PREP_TIMEOUT_MS }).catch(() => ({
|
|
653
|
+
rootPath: root,
|
|
654
|
+
rendered: "",
|
|
655
|
+
truncated: false,
|
|
656
|
+
totalLines: 0,
|
|
657
|
+
agentsMdFiles: [],
|
|
658
|
+
})),
|
|
659
|
+
),
|
|
660
|
+
);
|
|
661
|
+
return { ...primary, agentsMdFiles: [...primary.agentsMdFiles, ...extraTrees.flatMap(t => t.agentsMdFiles)] };
|
|
662
|
+
})();
|
|
639
663
|
const skillsPromise: Promise<readonly Skill[]> =
|
|
640
664
|
providedSkills !== undefined
|
|
641
665
|
? Promise.resolve(providedSkills)
|
|
@@ -794,6 +818,7 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
794
818
|
date,
|
|
795
819
|
dateTime,
|
|
796
820
|
cwd: promptCwd,
|
|
821
|
+
additionalWorkspaceRoots: additionalWorkspaceRoots.filter(d => path.resolve(d) !== path.resolve(resolvedCwd)),
|
|
797
822
|
model: includeModelInPrompt ? (model ?? "") : "",
|
|
798
823
|
useCodexTaskPrompt: usesCodexTaskPrompt(model),
|
|
799
824
|
personality: personality === "none" ? "" : PERSONALITY_SPECS[personality].trim(),
|
|
@@ -815,6 +840,9 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
815
840
|
};
|
|
816
841
|
const rendered = prompt.render(resolvedCustomPrompt ? customSystemPromptTemplate : systemPromptTemplate, data);
|
|
817
842
|
const systemPrompt = [rendered];
|
|
843
|
+
if (toolNames.includes("computer")) {
|
|
844
|
+
systemPrompt.push(computerSafetyPrompt.trim());
|
|
845
|
+
}
|
|
818
846
|
// Custom prompt templates already render context files and append text; the
|
|
819
847
|
// project footer still carries environment, cwd, workspace, and dir-context.
|
|
820
848
|
const projectPrompt = prompt
|