@caupulican/pi-adaptative 0.85.8 → 0.86.2
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 +42 -0
- package/dist/core/agent-paths.d.ts +6 -3
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +10 -3
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session.d.ts +5 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +19 -8
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +11 -5
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +34 -8
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/subagent-prompt.d.ts +3 -3
- package/dist/core/autonomy/subagent-prompt.js +9 -9
- package/dist/core/autonomy/subagent-prompt.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +10 -8
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +23 -13
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bash-execution-controller.d.ts +4 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -1
- package/dist/core/bash-execution-controller.js +11 -4
- package/dist/core/bash-execution-controller.js.map +1 -1
- package/dist/core/bash-executor.d.ts +2 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/capability-contract.d.ts +1 -1
- package/dist/core/capability-contract.d.ts.map +1 -1
- package/dist/core/capability-contract.js +0 -1
- package/dist/core/capability-contract.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts +1 -0
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +3 -2
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +27 -8
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +191 -33
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts +45 -6
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js +110 -13
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +177 -158
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.d.ts +23 -0
- package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -0
- package/dist/core/delegation/worker-authority-resolver.js +128 -0
- package/dist/core/delegation/worker-authority-resolver.js.map +1 -0
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
- package/dist/core/delegation/worker-conversation-store.js +1 -1
- package/dist/core/delegation/worker-conversation-store.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +7 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +260 -87
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +25 -4
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js +90 -1
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts +2 -0
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +22 -12
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js +4 -2
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.d.ts +0 -2
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.js +8 -35
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.js +1 -0
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +6 -1
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +20 -6
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +47 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.js +210 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -0
- package/dist/core/memory/providers/file-store.d.ts +2 -0
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +22 -20
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/models/runtime-process.d.ts.map +1 -1
- package/dist/core/models/runtime-process.js +5 -18
- package/dist/core/models/runtime-process.js.map +1 -1
- package/dist/core/orchestration/bounded-string-array.d.ts +11 -0
- package/dist/core/orchestration/bounded-string-array.d.ts.map +1 -0
- package/dist/core/orchestration/bounded-string-array.js +17 -0
- package/dist/core/orchestration/bounded-string-array.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +16 -0
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +38 -0
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +11 -3
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +0 -1
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/delegation-ledger.d.ts +1 -0
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
- package/dist/core/orchestration/delegation-ledger.js +3 -0
- package/dist/core/orchestration/delegation-ledger.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts +12 -10
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +94 -104
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +4 -1
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
- package/dist/core/orchestration/policy-compiler.js +8 -9
- package/dist/core/orchestration/policy-compiler.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +4 -10
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/task-runtime.d.ts +1 -0
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
- package/dist/core/orchestration/task-runtime.js +58 -3
- package/dist/core/orchestration/task-runtime.js.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js +10 -17
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/risk-classifier.js +3 -3
- package/dist/core/risk-classifier.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +4 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +34 -15
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/secrets/bitwarden-credential-storage.d.ts +51 -0
- package/dist/core/secrets/bitwarden-credential-storage.d.ts.map +1 -0
- package/dist/core/secrets/bitwarden-credential-storage.js +345 -0
- package/dist/core/secrets/bitwarden-credential-storage.js.map +1 -0
- package/dist/core/secrets/credential-exposure-guard.d.ts +8 -4
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +30 -31
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/secrets/credential-manager.d.ts +109 -0
- package/dist/core/secrets/credential-manager.d.ts.map +1 -0
- package/dist/core/secrets/credential-manager.js +384 -0
- package/dist/core/secrets/credential-manager.js.map +1 -0
- package/dist/core/secrets/credential-project.d.ts +4 -0
- package/dist/core/secrets/credential-project.d.ts.map +1 -0
- package/dist/core/secrets/credential-project.js +145 -0
- package/dist/core/secrets/credential-project.js.map +1 -0
- package/dist/core/secrets/secret-dotenv.d.ts +1 -1
- package/dist/core/secrets/secret-dotenv.js +1 -1
- package/dist/core/secrets/secret-dotenv.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +9 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tool-capability-policy.js +2 -2
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +29 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +179 -28
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts +1 -0
- package/dist/core/tools/git-filter.d.ts.map +1 -1
- package/dist/core/tools/git-filter.js +1 -1
- package/dist/core/tools/git-filter.js.map +1 -1
- package/dist/core/tools/profile-writer.js +3 -3
- package/dist/core/tools/profile-writer.js.map +1 -1
- package/dist/core/tools/python.d.ts +2 -0
- package/dist/core/tools/python.d.ts.map +1 -1
- package/dist/core/tools/python.js +17 -12
- package/dist/core/tools/python.js.map +1 -1
- package/dist/core/tools/run-process.d.ts +2 -0
- package/dist/core/tools/run-process.d.ts.map +1 -1
- package/dist/core/tools/run-process.js +7 -3
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/secret-store.d.ts +8 -18
- package/dist/core/tools/secret-store.d.ts.map +1 -1
- package/dist/core/tools/secret-store.js +83 -348
- package/dist/core/tools/secret-store.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +38 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +35 -14
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +26 -3
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/secret-menu-controller.d.ts +21 -0
- package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -0
- package/dist/modes/interactive/secret-menu-controller.js +276 -0
- package/dist/modes/interactive/secret-menu-controller.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +2 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +43 -48
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/zip-extractor.d.ts +8 -0
- package/dist/utils/zip-extractor.d.ts.map +1 -0
- package/dist/utils/zip-extractor.js +275 -0
- package/dist/utils/zip-extractor.js.map +1 -0
- package/docs/harness-architecture.md +34 -22
- package/docs/index.md +1 -1
- package/docs/resources.md +1 -1
- package/docs/settings.md +39 -103
- package/docs/usage.md +7 -5
- package/docs/worker-profiles.md +9 -7
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/core/secrets/secret-vault-format.d.ts +0 -112
- package/dist/core/secrets/secret-vault-format.d.ts.map +0 -1
- package/dist/core/secrets/secret-vault-format.js +0 -396
- package/dist/core/secrets/secret-vault-format.js.map +0 -1
- package/dist/core/secrets/secret-vault.d.ts +0 -72
- package/dist/core/secrets/secret-vault.d.ts.map +0 -1
- package/dist/core/secrets/secret-vault.js +0 -663
- package/dist/core/secrets/secret-vault.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ExtensionUIContext } from "../../core/extensions/types.ts";
|
|
2
|
+
import { type CredentialManager } from "../../core/secrets/credential-manager.ts";
|
|
3
|
+
export interface SecretMenuControllerOptions {
|
|
4
|
+
manager: CredentialManager;
|
|
5
|
+
cwd: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class SecretMenuController {
|
|
8
|
+
private readonly manager;
|
|
9
|
+
private readonly cwd;
|
|
10
|
+
constructor(options: SecretMenuControllerOptions);
|
|
11
|
+
open(ui: ExtensionUIContext): Promise<void>;
|
|
12
|
+
private connect;
|
|
13
|
+
private addOrUpdate;
|
|
14
|
+
private captureUserPassword;
|
|
15
|
+
private captureKey;
|
|
16
|
+
private captureDotenv;
|
|
17
|
+
private activate;
|
|
18
|
+
private bind;
|
|
19
|
+
private remove;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=secret-menu-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-menu-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/secret-menu-controller.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EACN,KAAK,iBAAiB,EAItB,MAAM,0CAA0C,CAAC;AAqBlD,MAAM,WAAW,2BAA2B;IAC3C,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;CACZ;AAsDD,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YAAY,OAAO,EAAE,2BAA2B,EAG/C;IAEK,IAAI,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDhD;YAEa,OAAO;YAkBP,WAAW;YAyCX,mBAAmB;YA4BnB,UAAU;YAqBV,aAAa;YAqBb,QAAQ;YAcR,IAAI;YAcJ,MAAM;CAcpB"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
3
|
+
import { CredentialManagerError, CredentialStorageError, } from "../../core/secrets/credential-manager.js";
|
|
4
|
+
import { formatDotenvVariables, MAX_DOTENV_VALUE_BYTES, parseDotenvDocument, SecretDotenvError, } from "../../core/secrets/secret-dotenv.js";
|
|
5
|
+
import { ExtensionEditorComponent } from "./components/extension-editor.js";
|
|
6
|
+
const ADD_ACTION = "Add or update credentials";
|
|
7
|
+
const ACTIVATE_ACTION = "Activate credentials for this project";
|
|
8
|
+
const BIND_ACTION = "Use an existing profile in this project";
|
|
9
|
+
const REMOVE_ACTION = "Remove a credential profile";
|
|
10
|
+
const RECONNECT_ACTION = "Reconnect Bitwarden";
|
|
11
|
+
const LOCK_ACTION = "Lock Pi credentials";
|
|
12
|
+
const CLOSE_ACTION = "Close";
|
|
13
|
+
const USER_PASSWORD_KIND = "Username and password";
|
|
14
|
+
const KEY_KIND = "API token or private key";
|
|
15
|
+
const DOTENV_KIND = "Environment variables (.env format)";
|
|
16
|
+
function safeErrorMessage(error) {
|
|
17
|
+
if (error instanceof CredentialManagerError ||
|
|
18
|
+
error instanceof CredentialStorageError ||
|
|
19
|
+
error instanceof SecretDotenvError) {
|
|
20
|
+
return error.message;
|
|
21
|
+
}
|
|
22
|
+
return "Credential operation failed safely without exposing private data.";
|
|
23
|
+
}
|
|
24
|
+
async function openPrivateEditor(ui, title, prefill, notice) {
|
|
25
|
+
return ui.custom((tui, _theme, keybindings, done) => new ExtensionEditorComponent(tui, keybindings, title, prefill, (value) => done(value), () => done(undefined), {
|
|
26
|
+
privateContent: true,
|
|
27
|
+
allowExternalEditor: false,
|
|
28
|
+
notice,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
function unquoteDroppedPath(value) {
|
|
32
|
+
if (value.length < 2)
|
|
33
|
+
return value;
|
|
34
|
+
const first = value[0];
|
|
35
|
+
return (first === '"' || first === "'") && value.at(-1) === first ? value.slice(1, -1) : value;
|
|
36
|
+
}
|
|
37
|
+
async function resolvePrivateValue(editorValue) {
|
|
38
|
+
const pathCandidate = unquoteDroppedPath(editorValue.trim());
|
|
39
|
+
if (!isAbsolute(pathCandidate))
|
|
40
|
+
return editorValue;
|
|
41
|
+
const metadata = await stat(pathCandidate).catch(() => undefined);
|
|
42
|
+
if (!metadata?.isFile())
|
|
43
|
+
throw new SecretDotenvError("dropped key file was not found or is not a regular file");
|
|
44
|
+
if (metadata.size > MAX_DOTENV_VALUE_BYTES) {
|
|
45
|
+
throw new SecretDotenvError("dropped key file exceeds the 64 KiB value limit");
|
|
46
|
+
}
|
|
47
|
+
return readFile(pathCandidate, "utf8");
|
|
48
|
+
}
|
|
49
|
+
export class SecretMenuController {
|
|
50
|
+
constructor(options) {
|
|
51
|
+
this.manager = options.manager;
|
|
52
|
+
this.cwd = options.cwd;
|
|
53
|
+
}
|
|
54
|
+
async open(ui) {
|
|
55
|
+
let profiles;
|
|
56
|
+
if (!this.manager.status.connected && this.manager.status.sessionAvailable) {
|
|
57
|
+
try {
|
|
58
|
+
profiles = await this.manager.listForProject(this.cwd);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// A stale BW_SESSION falls through to the one-field owner reconnect flow.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!this.manager.status.connected) {
|
|
65
|
+
if (!(await this.connect(ui)))
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
while (true) {
|
|
69
|
+
try {
|
|
70
|
+
profiles ??= await this.manager.listForProject(this.cwd);
|
|
71
|
+
const actions = [ADD_ACTION];
|
|
72
|
+
if (profiles.some((profile) => profile.boundToCurrentProject))
|
|
73
|
+
actions.push(ACTIVATE_ACTION);
|
|
74
|
+
if (profiles.some((profile) => !profile.boundToCurrentProject))
|
|
75
|
+
actions.push(BIND_ACTION);
|
|
76
|
+
if (profiles.length > 0)
|
|
77
|
+
actions.push(REMOVE_ACTION);
|
|
78
|
+
actions.push(RECONNECT_ACTION, LOCK_ACTION, CLOSE_ACTION);
|
|
79
|
+
const action = await ui.select("Secrets · Bitwarden", actions);
|
|
80
|
+
switch (action) {
|
|
81
|
+
case ADD_ACTION:
|
|
82
|
+
await this.addOrUpdate(ui, profiles);
|
|
83
|
+
profiles = undefined;
|
|
84
|
+
continue;
|
|
85
|
+
case ACTIVATE_ACTION:
|
|
86
|
+
await this.activate(ui, profiles);
|
|
87
|
+
continue;
|
|
88
|
+
case BIND_ACTION:
|
|
89
|
+
await this.bind(ui, profiles);
|
|
90
|
+
profiles = undefined;
|
|
91
|
+
continue;
|
|
92
|
+
case REMOVE_ACTION:
|
|
93
|
+
await this.remove(ui, profiles);
|
|
94
|
+
profiles = undefined;
|
|
95
|
+
continue;
|
|
96
|
+
case RECONNECT_ACTION:
|
|
97
|
+
this.manager.lock();
|
|
98
|
+
if (!(await this.connect(ui)))
|
|
99
|
+
return;
|
|
100
|
+
profiles = undefined;
|
|
101
|
+
continue;
|
|
102
|
+
case LOCK_ACTION:
|
|
103
|
+
this.manager.lock();
|
|
104
|
+
ui.notify("Pi credential access is locked for this session.", "info");
|
|
105
|
+
return;
|
|
106
|
+
case CLOSE_ACTION:
|
|
107
|
+
case undefined:
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
ui.notify(safeErrorMessage(error), "error");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async connect(ui) {
|
|
118
|
+
while (true) {
|
|
119
|
+
let sessionKey = await ui.input("Connect Bitwarden", "Paste BW_SESSION session key", {
|
|
120
|
+
sensitive: true,
|
|
121
|
+
});
|
|
122
|
+
if (sessionKey === undefined)
|
|
123
|
+
return false;
|
|
124
|
+
try {
|
|
125
|
+
await this.manager.connect(sessionKey);
|
|
126
|
+
ui.notify("Bitwarden connected. Pi keeps the session key in memory only.", "info");
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
ui.notify(safeErrorMessage(error), "error");
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
sessionKey = "";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async addOrUpdate(ui, profiles) {
|
|
138
|
+
const profileInput = await ui.input("Credential profile", "Example: deploy-prod");
|
|
139
|
+
if (profileInput === undefined)
|
|
140
|
+
return;
|
|
141
|
+
const profile = profileInput.trim();
|
|
142
|
+
if (!profile) {
|
|
143
|
+
ui.notify("Credential profile name is required.", "error");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (profiles.some((candidate) => candidate.profile === profile)) {
|
|
147
|
+
const approved = await ui.confirm("Update credential profile", `Replace the stored values for ${profile} while preserving its project bindings?`);
|
|
148
|
+
if (!approved)
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const descriptionInput = await ui.input("Description", "Optional non-secret description");
|
|
152
|
+
if (descriptionInput === undefined)
|
|
153
|
+
return;
|
|
154
|
+
const description = descriptionInput.trim() || undefined;
|
|
155
|
+
const kind = await ui.select("Credential shape", [USER_PASSWORD_KIND, KEY_KIND, DOTENV_KIND]);
|
|
156
|
+
if (!kind)
|
|
157
|
+
return;
|
|
158
|
+
let dotenv = "";
|
|
159
|
+
try {
|
|
160
|
+
if (kind === USER_PASSWORD_KIND)
|
|
161
|
+
dotenv = (await this.captureUserPassword(ui)) ?? "";
|
|
162
|
+
else if (kind === KEY_KIND)
|
|
163
|
+
dotenv = (await this.captureKey(ui)) ?? "";
|
|
164
|
+
else
|
|
165
|
+
dotenv = (await this.captureDotenv(ui)) ?? "";
|
|
166
|
+
if (!dotenv)
|
|
167
|
+
return;
|
|
168
|
+
const stored = await this.manager.storeForProject(this.cwd, { profile, description, dotenv });
|
|
169
|
+
ui.notify(`Stored and activated ${stored.profile} (${stored.variableNames.length} variables) in Bitwarden.`, "info");
|
|
170
|
+
if (stored.portable === false) {
|
|
171
|
+
ui.notify("This project has no portable Git remote, so its binding is local to this machine.", "warning");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
ui.notify(safeErrorMessage(error), "error");
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
dotenv = "";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async captureUserPassword(ui) {
|
|
182
|
+
const usernameVariableInput = await ui.input("Username variable", "USERNAME");
|
|
183
|
+
if (usernameVariableInput === undefined)
|
|
184
|
+
return undefined;
|
|
185
|
+
const usernameVariable = usernameVariableInput.trim() || "USERNAME";
|
|
186
|
+
let username = await ui.input("Username", "Type the account username", { sensitive: true });
|
|
187
|
+
if (username === undefined)
|
|
188
|
+
return undefined;
|
|
189
|
+
const passwordVariableInput = await ui.input("Password variable", "PASSWORD");
|
|
190
|
+
if (passwordVariableInput === undefined) {
|
|
191
|
+
username = "";
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
const passwordVariable = passwordVariableInput.trim() || "PASSWORD";
|
|
195
|
+
let password = await ui.input("Password", "Type the account password", { sensitive: true });
|
|
196
|
+
if (password === undefined) {
|
|
197
|
+
username = "";
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
return formatDotenvVariables([
|
|
202
|
+
{ name: usernameVariable, value: username },
|
|
203
|
+
{ name: passwordVariable, value: password },
|
|
204
|
+
]);
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
username = "";
|
|
208
|
+
password = "";
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async captureKey(ui) {
|
|
212
|
+
const variableInput = await ui.input("Key variable", "API_KEY");
|
|
213
|
+
if (variableInput === undefined)
|
|
214
|
+
return undefined;
|
|
215
|
+
const variable = variableInput.trim() || "API_KEY";
|
|
216
|
+
let editorValue = await openPrivateEditor(ui, `Private value · ${variable}`, "", "Paste a token/key, or drag an absolute key-file path here · never sent to the model");
|
|
217
|
+
if (editorValue === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
let value = "";
|
|
220
|
+
try {
|
|
221
|
+
value = await resolvePrivateValue(editorValue);
|
|
222
|
+
return formatDotenvVariables([{ name: variable, value }]);
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
editorValue = "";
|
|
226
|
+
value = "";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async captureDotenv(ui) {
|
|
230
|
+
let draft = "# NAME=value\n";
|
|
231
|
+
while (true) {
|
|
232
|
+
const edited = await openPrivateEditor(ui, "Environment credentials", draft, "Private .env editor · paste one or more NAME=value entries · never sent to the model");
|
|
233
|
+
if (edited === undefined)
|
|
234
|
+
return undefined;
|
|
235
|
+
try {
|
|
236
|
+
const parsed = parseDotenvDocument(edited);
|
|
237
|
+
draft = "";
|
|
238
|
+
return parsed.document;
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
ui.notify(safeErrorMessage(error), "error");
|
|
242
|
+
draft = edited;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async activate(ui, profiles) {
|
|
247
|
+
const bound = profiles.filter((profile) => profile.boundToCurrentProject);
|
|
248
|
+
const profile = await ui.select("Activate credentials", bound.map((candidate) => candidate.profile));
|
|
249
|
+
if (!profile)
|
|
250
|
+
return;
|
|
251
|
+
const activated = await this.manager.activateForProject(this.cwd, profile);
|
|
252
|
+
ui.notify(`Activated ${activated.profile} for ${activated.project} (${activated.variableNames.length} variables).`, "info");
|
|
253
|
+
}
|
|
254
|
+
async bind(ui, profiles) {
|
|
255
|
+
const unbound = profiles.filter((profile) => !profile.boundToCurrentProject);
|
|
256
|
+
const profile = await ui.select("Use profile in this project", unbound.map((candidate) => candidate.profile));
|
|
257
|
+
if (!profile)
|
|
258
|
+
return;
|
|
259
|
+
const bound = await this.manager.bindProfileToProject(this.cwd, profile);
|
|
260
|
+
ui.notify(`Bound ${bound.profile} to ${bound.project}.`, "info");
|
|
261
|
+
if (bound.portable === false) {
|
|
262
|
+
ui.notify("This project has no portable Git remote, so its binding is local to this machine.", "warning");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async remove(ui, profiles) {
|
|
266
|
+
const profile = await ui.select("Remove credential profile", profiles.map((candidate) => candidate.profile));
|
|
267
|
+
if (!profile)
|
|
268
|
+
return;
|
|
269
|
+
const approved = await ui.confirm("Remove credential profile", `Move ${profile} to Bitwarden trash and clear its active environment?`);
|
|
270
|
+
if (!approved)
|
|
271
|
+
return;
|
|
272
|
+
const removed = await this.manager.removeProfile(profile);
|
|
273
|
+
ui.notify(`Removed ${removed.profile} (${removed.variableNames.length} variables).`, "info");
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=secret-menu-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-menu-controller.js","sourceRoot":"","sources":["../../../src/modes/interactive/secret-menu-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile, stat } from \"node:fs/promises\";\nimport { isAbsolute } from \"node:path\";\nimport type { ExtensionUIContext } from \"../../core/extensions/types.ts\";\nimport {\n\ttype CredentialManager,\n\tCredentialManagerError,\n\ttype CredentialProfileSummary,\n\tCredentialStorageError,\n} from \"../../core/secrets/credential-manager.ts\";\nimport {\n\tformatDotenvVariables,\n\tMAX_DOTENV_VALUE_BYTES,\n\tparseDotenvDocument,\n\tSecretDotenvError,\n} from \"../../core/secrets/secret-dotenv.ts\";\nimport { ExtensionEditorComponent } from \"./components/extension-editor.ts\";\n\nconst ADD_ACTION = \"Add or update credentials\";\nconst ACTIVATE_ACTION = \"Activate credentials for this project\";\nconst BIND_ACTION = \"Use an existing profile in this project\";\nconst REMOVE_ACTION = \"Remove a credential profile\";\nconst RECONNECT_ACTION = \"Reconnect Bitwarden\";\nconst LOCK_ACTION = \"Lock Pi credentials\";\nconst CLOSE_ACTION = \"Close\";\n\nconst USER_PASSWORD_KIND = \"Username and password\";\nconst KEY_KIND = \"API token or private key\";\nconst DOTENV_KIND = \"Environment variables (.env format)\";\n\nexport interface SecretMenuControllerOptions {\n\tmanager: CredentialManager;\n\tcwd: string;\n}\n\nfunction safeErrorMessage(error: unknown): string {\n\tif (\n\t\terror instanceof CredentialManagerError ||\n\t\terror instanceof CredentialStorageError ||\n\t\terror instanceof SecretDotenvError\n\t) {\n\t\treturn error.message;\n\t}\n\treturn \"Credential operation failed safely without exposing private data.\";\n}\n\nasync function openPrivateEditor(\n\tui: ExtensionUIContext,\n\ttitle: string,\n\tprefill: string,\n\tnotice: string,\n): Promise<string | undefined> {\n\treturn ui.custom<string | undefined>(\n\t\t(tui, _theme, keybindings, done) =>\n\t\t\tnew ExtensionEditorComponent(\n\t\t\t\ttui,\n\t\t\t\tkeybindings,\n\t\t\t\ttitle,\n\t\t\t\tprefill,\n\t\t\t\t(value) => done(value),\n\t\t\t\t() => done(undefined),\n\t\t\t\t{\n\t\t\t\t\tprivateContent: true,\n\t\t\t\t\tallowExternalEditor: false,\n\t\t\t\t\tnotice,\n\t\t\t\t},\n\t\t\t),\n\t);\n}\n\nfunction unquoteDroppedPath(value: string): string {\n\tif (value.length < 2) return value;\n\tconst first = value[0];\n\treturn (first === '\"' || first === \"'\") && value.at(-1) === first ? value.slice(1, -1) : value;\n}\n\nasync function resolvePrivateValue(editorValue: string): Promise<string> {\n\tconst pathCandidate = unquoteDroppedPath(editorValue.trim());\n\tif (!isAbsolute(pathCandidate)) return editorValue;\n\tconst metadata = await stat(pathCandidate).catch(() => undefined);\n\tif (!metadata?.isFile()) throw new SecretDotenvError(\"dropped key file was not found or is not a regular file\");\n\tif (metadata.size > MAX_DOTENV_VALUE_BYTES) {\n\t\tthrow new SecretDotenvError(\"dropped key file exceeds the 64 KiB value limit\");\n\t}\n\treturn readFile(pathCandidate, \"utf8\");\n}\n\nexport class SecretMenuController {\n\tprivate readonly manager: CredentialManager;\n\tprivate readonly cwd: string;\n\n\tconstructor(options: SecretMenuControllerOptions) {\n\t\tthis.manager = options.manager;\n\t\tthis.cwd = options.cwd;\n\t}\n\n\tasync open(ui: ExtensionUIContext): Promise<void> {\n\t\tlet profiles: CredentialProfileSummary[] | undefined;\n\t\tif (!this.manager.status.connected && this.manager.status.sessionAvailable) {\n\t\t\ttry {\n\t\t\t\tprofiles = await this.manager.listForProject(this.cwd);\n\t\t\t} catch {\n\t\t\t\t// A stale BW_SESSION falls through to the one-field owner reconnect flow.\n\t\t\t}\n\t\t}\n\t\tif (!this.manager.status.connected) {\n\t\t\tif (!(await this.connect(ui))) return;\n\t\t}\n\t\twhile (true) {\n\t\t\ttry {\n\t\t\t\tprofiles ??= await this.manager.listForProject(this.cwd);\n\t\t\t\tconst actions = [ADD_ACTION];\n\t\t\t\tif (profiles.some((profile) => profile.boundToCurrentProject)) actions.push(ACTIVATE_ACTION);\n\t\t\t\tif (profiles.some((profile) => !profile.boundToCurrentProject)) actions.push(BIND_ACTION);\n\t\t\t\tif (profiles.length > 0) actions.push(REMOVE_ACTION);\n\t\t\t\tactions.push(RECONNECT_ACTION, LOCK_ACTION, CLOSE_ACTION);\n\t\t\t\tconst action = await ui.select(\"Secrets · Bitwarden\", actions);\n\t\t\t\tswitch (action) {\n\t\t\t\t\tcase ADD_ACTION:\n\t\t\t\t\t\tawait this.addOrUpdate(ui, profiles);\n\t\t\t\t\t\tprofiles = undefined;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tcase ACTIVATE_ACTION:\n\t\t\t\t\t\tawait this.activate(ui, profiles);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tcase BIND_ACTION:\n\t\t\t\t\t\tawait this.bind(ui, profiles);\n\t\t\t\t\t\tprofiles = undefined;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tcase REMOVE_ACTION:\n\t\t\t\t\t\tawait this.remove(ui, profiles);\n\t\t\t\t\t\tprofiles = undefined;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tcase RECONNECT_ACTION:\n\t\t\t\t\t\tthis.manager.lock();\n\t\t\t\t\t\tif (!(await this.connect(ui))) return;\n\t\t\t\t\t\tprofiles = undefined;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tcase LOCK_ACTION:\n\t\t\t\t\t\tthis.manager.lock();\n\t\t\t\t\t\tui.notify(\"Pi credential access is locked for this session.\", \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\tcase CLOSE_ACTION:\n\t\t\t\t\tcase undefined:\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tui.notify(safeErrorMessage(error), \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async connect(ui: ExtensionUIContext): Promise<boolean> {\n\t\twhile (true) {\n\t\t\tlet sessionKey = await ui.input(\"Connect Bitwarden\", \"Paste BW_SESSION session key\", {\n\t\t\t\tsensitive: true,\n\t\t\t});\n\t\t\tif (sessionKey === undefined) return false;\n\t\t\ttry {\n\t\t\t\tawait this.manager.connect(sessionKey);\n\t\t\t\tui.notify(\"Bitwarden connected. Pi keeps the session key in memory only.\", \"info\");\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tui.notify(safeErrorMessage(error), \"error\");\n\t\t\t} finally {\n\t\t\t\tsessionKey = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async addOrUpdate(ui: ExtensionUIContext, profiles: CredentialProfileSummary[]): Promise<void> {\n\t\tconst profileInput = await ui.input(\"Credential profile\", \"Example: deploy-prod\");\n\t\tif (profileInput === undefined) return;\n\t\tconst profile = profileInput.trim();\n\t\tif (!profile) {\n\t\t\tui.notify(\"Credential profile name is required.\", \"error\");\n\t\t\treturn;\n\t\t}\n\t\tif (profiles.some((candidate) => candidate.profile === profile)) {\n\t\t\tconst approved = await ui.confirm(\n\t\t\t\t\"Update credential profile\",\n\t\t\t\t`Replace the stored values for ${profile} while preserving its project bindings?`,\n\t\t\t);\n\t\t\tif (!approved) return;\n\t\t}\n\t\tconst descriptionInput = await ui.input(\"Description\", \"Optional non-secret description\");\n\t\tif (descriptionInput === undefined) return;\n\t\tconst description = descriptionInput.trim() || undefined;\n\t\tconst kind = await ui.select(\"Credential shape\", [USER_PASSWORD_KIND, KEY_KIND, DOTENV_KIND]);\n\t\tif (!kind) return;\n\t\tlet dotenv = \"\";\n\t\ttry {\n\t\t\tif (kind === USER_PASSWORD_KIND) dotenv = (await this.captureUserPassword(ui)) ?? \"\";\n\t\t\telse if (kind === KEY_KIND) dotenv = (await this.captureKey(ui)) ?? \"\";\n\t\t\telse dotenv = (await this.captureDotenv(ui)) ?? \"\";\n\t\t\tif (!dotenv) return;\n\t\t\tconst stored = await this.manager.storeForProject(this.cwd, { profile, description, dotenv });\n\t\t\tui.notify(\n\t\t\t\t`Stored and activated ${stored.profile} (${stored.variableNames.length} variables) in Bitwarden.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t\tif (stored.portable === false) {\n\t\t\t\tui.notify(\"This project has no portable Git remote, so its binding is local to this machine.\", \"warning\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tui.notify(safeErrorMessage(error), \"error\");\n\t\t} finally {\n\t\t\tdotenv = \"\";\n\t\t}\n\t}\n\n\tprivate async captureUserPassword(ui: ExtensionUIContext): Promise<string | undefined> {\n\t\tconst usernameVariableInput = await ui.input(\"Username variable\", \"USERNAME\");\n\t\tif (usernameVariableInput === undefined) return undefined;\n\t\tconst usernameVariable = usernameVariableInput.trim() || \"USERNAME\";\n\t\tlet username = await ui.input(\"Username\", \"Type the account username\", { sensitive: true });\n\t\tif (username === undefined) return undefined;\n\t\tconst passwordVariableInput = await ui.input(\"Password variable\", \"PASSWORD\");\n\t\tif (passwordVariableInput === undefined) {\n\t\t\tusername = \"\";\n\t\t\treturn undefined;\n\t\t}\n\t\tconst passwordVariable = passwordVariableInput.trim() || \"PASSWORD\";\n\t\tlet password = await ui.input(\"Password\", \"Type the account password\", { sensitive: true });\n\t\tif (password === undefined) {\n\t\t\tusername = \"\";\n\t\t\treturn undefined;\n\t\t}\n\t\ttry {\n\t\t\treturn formatDotenvVariables([\n\t\t\t\t{ name: usernameVariable, value: username },\n\t\t\t\t{ name: passwordVariable, value: password },\n\t\t\t]);\n\t\t} finally {\n\t\t\tusername = \"\";\n\t\t\tpassword = \"\";\n\t\t}\n\t}\n\n\tprivate async captureKey(ui: ExtensionUIContext): Promise<string | undefined> {\n\t\tconst variableInput = await ui.input(\"Key variable\", \"API_KEY\");\n\t\tif (variableInput === undefined) return undefined;\n\t\tconst variable = variableInput.trim() || \"API_KEY\";\n\t\tlet editorValue = await openPrivateEditor(\n\t\t\tui,\n\t\t\t`Private value · ${variable}`,\n\t\t\t\"\",\n\t\t\t\"Paste a token/key, or drag an absolute key-file path here · never sent to the model\",\n\t\t);\n\t\tif (editorValue === undefined) return undefined;\n\t\tlet value = \"\";\n\t\ttry {\n\t\t\tvalue = await resolvePrivateValue(editorValue);\n\t\t\treturn formatDotenvVariables([{ name: variable, value }]);\n\t\t} finally {\n\t\t\teditorValue = \"\";\n\t\t\tvalue = \"\";\n\t\t}\n\t}\n\n\tprivate async captureDotenv(ui: ExtensionUIContext): Promise<string | undefined> {\n\t\tlet draft = \"# NAME=value\\n\";\n\t\twhile (true) {\n\t\t\tconst edited = await openPrivateEditor(\n\t\t\t\tui,\n\t\t\t\t\"Environment credentials\",\n\t\t\t\tdraft,\n\t\t\t\t\"Private .env editor · paste one or more NAME=value entries · never sent to the model\",\n\t\t\t);\n\t\t\tif (edited === undefined) return undefined;\n\t\t\ttry {\n\t\t\t\tconst parsed = parseDotenvDocument(edited);\n\t\t\t\tdraft = \"\";\n\t\t\t\treturn parsed.document;\n\t\t\t} catch (error) {\n\t\t\t\tui.notify(safeErrorMessage(error), \"error\");\n\t\t\t\tdraft = edited;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async activate(ui: ExtensionUIContext, profiles: CredentialProfileSummary[]): Promise<void> {\n\t\tconst bound = profiles.filter((profile) => profile.boundToCurrentProject);\n\t\tconst profile = await ui.select(\n\t\t\t\"Activate credentials\",\n\t\t\tbound.map((candidate) => candidate.profile),\n\t\t);\n\t\tif (!profile) return;\n\t\tconst activated = await this.manager.activateForProject(this.cwd, profile);\n\t\tui.notify(\n\t\t\t`Activated ${activated.profile} for ${activated.project} (${activated.variableNames.length} variables).`,\n\t\t\t\"info\",\n\t\t);\n\t}\n\n\tprivate async bind(ui: ExtensionUIContext, profiles: CredentialProfileSummary[]): Promise<void> {\n\t\tconst unbound = profiles.filter((profile) => !profile.boundToCurrentProject);\n\t\tconst profile = await ui.select(\n\t\t\t\"Use profile in this project\",\n\t\t\tunbound.map((candidate) => candidate.profile),\n\t\t);\n\t\tif (!profile) return;\n\t\tconst bound = await this.manager.bindProfileToProject(this.cwd, profile);\n\t\tui.notify(`Bound ${bound.profile} to ${bound.project}.`, \"info\");\n\t\tif (bound.portable === false) {\n\t\t\tui.notify(\"This project has no portable Git remote, so its binding is local to this machine.\", \"warning\");\n\t\t}\n\t}\n\n\tprivate async remove(ui: ExtensionUIContext, profiles: CredentialProfileSummary[]): Promise<void> {\n\t\tconst profile = await ui.select(\n\t\t\t\"Remove credential profile\",\n\t\t\tprofiles.map((candidate) => candidate.profile),\n\t\t);\n\t\tif (!profile) return;\n\t\tconst approved = await ui.confirm(\n\t\t\t\"Remove credential profile\",\n\t\t\t`Move ${profile} to Bitwarden trash and clear its active environment?`,\n\t\t);\n\t\tif (!approved) return;\n\t\tconst removed = await this.manager.removeProfile(profile);\n\t\tui.notify(`Removed ${removed.profile} (${removed.variableNames.length} variables).`, \"info\");\n\t}\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const BITWARDEN_CLI_VERSION = "2026.7.0";
|
|
1
2
|
export declare const FD_VERSION = "10.4.2";
|
|
2
3
|
export declare const RG_VERSION = "15.2.0";
|
|
3
4
|
export declare const JQ_VERSION = "1.8.2";
|
|
@@ -17,7 +18,7 @@ interface ToolConfig {
|
|
|
17
18
|
getPinnedVersion?: (plat: string, architecture: string) => string | undefined;
|
|
18
19
|
sha256ByAsset?: Readonly<Record<string, string>>;
|
|
19
20
|
}
|
|
20
|
-
declare const TOOLS: Record<"fd" | "jq" | "jscpd" | "rg" | "uv", ToolConfig>;
|
|
21
|
+
declare const TOOLS: Record<"bw" | "fd" | "jq" | "jscpd" | "rg" | "uv", ToolConfig>;
|
|
21
22
|
export type ManagedToolName = keyof typeof TOOLS;
|
|
22
23
|
export type ManagedToolProvisionFailureCode = "offline" | "unsupported_platform" | "installation_failed" | "not_found_after_install" | "unknown_tool";
|
|
23
24
|
export type ManagedToolResolution = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools-manager.d.ts","sourceRoot":"","sources":["../../src/utils/tools-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools-manager.d.ts","sourceRoot":"","sources":["../../src/utils/tools-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,11 +13,13 @@ import { cacheDir as agentCacheDir, cacheFile } from "../core/agent-paths.js";
|
|
|
13
13
|
import { ensureManagedJscpd, JSCPD_VERSION } from "./bundled-jscpd.js";
|
|
14
14
|
import { spawnProcess, waitForChildProcessWithTermination } from "./child-process.js";
|
|
15
15
|
import { getProcessWorkRun } from "./work-directory.js";
|
|
16
|
+
import { extractZipFile } from "./zip-extractor.js";
|
|
16
17
|
const TOOLS_DIR = getBinDir();
|
|
17
18
|
const DOWNLOAD_TIMEOUT_MS = 120_000;
|
|
18
19
|
const COMMAND_PROBE_TIMEOUT_MS = 5_000;
|
|
19
20
|
const ARCHIVE_EXTRACTION_TIMEOUT_MS = 5 * 60_000;
|
|
20
21
|
const FFF_NODE_VERSION = "0.9.6";
|
|
22
|
+
export const BITWARDEN_CLI_VERSION = "2026.7.0";
|
|
21
23
|
export const FD_VERSION = "10.4.2";
|
|
22
24
|
const FD_DARWIN_X64_VERSION = "10.3.0";
|
|
23
25
|
export const RG_VERSION = "15.2.0";
|
|
@@ -34,6 +36,34 @@ function isOfflineModeEnabled() {
|
|
|
34
36
|
return value === "1" || value.toLowerCase() === "true" || value.toLowerCase() === "yes";
|
|
35
37
|
}
|
|
36
38
|
const TOOLS = {
|
|
39
|
+
bw: {
|
|
40
|
+
name: "Bitwarden CLI",
|
|
41
|
+
repo: "bitwarden/clients",
|
|
42
|
+
binaryName: "bw",
|
|
43
|
+
systemBinaryNames: ["bw"],
|
|
44
|
+
tagPrefix: "cli-v",
|
|
45
|
+
pinnedVersion: BITWARDEN_CLI_VERSION,
|
|
46
|
+
getAssetName: (version, plat, architecture) => {
|
|
47
|
+
if (plat === "darwin" && architecture === "arm64")
|
|
48
|
+
return `bw-macos-arm64-${version}.zip`;
|
|
49
|
+
if (plat === "darwin" && architecture === "x64")
|
|
50
|
+
return `bw-macos-${version}.zip`;
|
|
51
|
+
if (plat === "linux" && architecture === "arm64")
|
|
52
|
+
return `bw-linux-arm64-${version}.zip`;
|
|
53
|
+
if (plat === "linux" && architecture === "x64")
|
|
54
|
+
return `bw-linux-${version}.zip`;
|
|
55
|
+
if (plat === "win32" && architecture === "x64")
|
|
56
|
+
return `bw-windows-${version}.zip`;
|
|
57
|
+
return null;
|
|
58
|
+
},
|
|
59
|
+
sha256ByAsset: {
|
|
60
|
+
"bw-linux-2026.7.0.zip": "7a35145e205952f7434d2370da359543145ae0c45ba1af0fe9bdd99d40a00180",
|
|
61
|
+
"bw-linux-arm64-2026.7.0.zip": "e33ed05ca0fada9bd51b8bce76a230369bf0eefd5796a0a8e60699c977327fb5",
|
|
62
|
+
"bw-macos-2026.7.0.zip": "b37836d539798f5adeb8a907619ee8a55b6322549bb68669aa4b3a03d5bc0452",
|
|
63
|
+
"bw-macos-arm64-2026.7.0.zip": "61d5de8a279a9faf3637216f4fb02b506a1e4bb2817d1c64be0bd474466dd85a",
|
|
64
|
+
"bw-windows-2026.7.0.zip": "b0c22438607b789c6452dbd37ffd6be0e8a61e7a5c4e9ac57804d7ae5ed01b5b",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
37
67
|
fd: {
|
|
38
68
|
name: "fd",
|
|
39
69
|
repo: "sharkdp/fd",
|
|
@@ -441,52 +471,13 @@ function extractTarGzArchive(archivePath, extractDir, assetName) {
|
|
|
441
471
|
throw new Error(`Failed to extract ${assetName}: ${failure}`);
|
|
442
472
|
}
|
|
443
473
|
}
|
|
444
|
-
function
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
452
|
-
return "tar.exe";
|
|
453
|
-
}
|
|
454
|
-
function extractZipArchive(archivePath, extractDir, assetName) {
|
|
455
|
-
const failures = [];
|
|
456
|
-
if (platform() === "win32") {
|
|
457
|
-
// Windows ships bsdtar as tar.exe, which supports zip files. Prefer the
|
|
458
|
-
// System32 binary over Git Bash's GNU tar, which does not handle zip archives.
|
|
459
|
-
const tarFailure = runExtractionCommand(getWindowsTarCommand(), ["xf", archivePath, "-C", extractDir]);
|
|
460
|
-
if (!tarFailure)
|
|
461
|
-
return;
|
|
462
|
-
failures.push(tarFailure);
|
|
463
|
-
const script = "& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }";
|
|
464
|
-
const powershellFailure = runExtractionCommand("powershell.exe", [
|
|
465
|
-
"-NoLogo",
|
|
466
|
-
"-NoProfile",
|
|
467
|
-
"-NonInteractive",
|
|
468
|
-
"-ExecutionPolicy",
|
|
469
|
-
"Bypass",
|
|
470
|
-
"-Command",
|
|
471
|
-
script,
|
|
472
|
-
archivePath,
|
|
473
|
-
extractDir,
|
|
474
|
-
]);
|
|
475
|
-
if (!powershellFailure)
|
|
476
|
-
return;
|
|
477
|
-
failures.push(powershellFailure);
|
|
478
|
-
}
|
|
479
|
-
else {
|
|
480
|
-
const unzipFailure = runExtractionCommand("unzip", ["-q", archivePath, "-d", extractDir]);
|
|
481
|
-
if (!unzipFailure)
|
|
482
|
-
return;
|
|
483
|
-
failures.push(unzipFailure);
|
|
484
|
-
const tarFailure = runExtractionCommand("tar", ["xf", archivePath, "-C", extractDir]);
|
|
485
|
-
if (!tarFailure)
|
|
486
|
-
return;
|
|
487
|
-
failures.push(tarFailure);
|
|
488
|
-
}
|
|
489
|
-
throw new Error(`Failed to extract ${assetName}: ${failures.join("; ")}`);
|
|
474
|
+
async function extractZipArchive(archivePath, extractDir, assetName) {
|
|
475
|
+
try {
|
|
476
|
+
await extractZipFile(archivePath, extractDir);
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
throw new Error(`Failed to extract ${assetName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
480
|
+
}
|
|
490
481
|
}
|
|
491
482
|
/** Move a verified upstream standalone executable into Pi's managed bin directory. */
|
|
492
483
|
export function installStandaloneBinaryAsset(downloadedPath, binaryPath, targetPlatform = platform()) {
|
|
@@ -556,7 +547,7 @@ async function downloadTool(tool) {
|
|
|
556
547
|
extractTarGzArchive(archivePath, extractDir, assetName);
|
|
557
548
|
}
|
|
558
549
|
else if (assetName.endsWith(".zip")) {
|
|
559
|
-
extractZipArchive(archivePath, extractDir, assetName);
|
|
550
|
+
await extractZipArchive(archivePath, extractDir, assetName);
|
|
560
551
|
}
|
|
561
552
|
else {
|
|
562
553
|
throw new Error(`Unsupported archive format: ${assetName}`);
|
|
@@ -845,6 +836,8 @@ requires) {
|
|
|
845
836
|
}
|
|
846
837
|
async function installTermuxManagedTool(tool, silent) {
|
|
847
838
|
const packageName = TERMUX_PACKAGES[tool];
|
|
839
|
+
if (!packageName)
|
|
840
|
+
throw new Error(`${TOOLS[tool].name} has no supported Termux package`);
|
|
848
841
|
if (!silent)
|
|
849
842
|
console.log(chalk.dim(`${TOOLS[tool].name} not found. Installing with Termux pkg...`));
|
|
850
843
|
const child = spawnProcess("pkg", ["install", "-y", packageName], {
|
|
@@ -892,7 +885,9 @@ export async function ensureToolWithDiagnostics(tool, silent = false) {
|
|
|
892
885
|
if (platform() === "android") {
|
|
893
886
|
if (tool !== "uv") {
|
|
894
887
|
const packageName = TERMUX_PACKAGES[tool];
|
|
895
|
-
const message =
|
|
888
|
+
const message = packageName
|
|
889
|
+
? `${config.name} not found. Install with: pkg install ${packageName}`
|
|
890
|
+
: `${config.name} is not available as a supported managed tool on Android.`;
|
|
896
891
|
if (!silent)
|
|
897
892
|
console.log(chalk.yellow(message));
|
|
898
893
|
return { status: "unavailable", failureCode: "unsupported_platform", message };
|