pi-ui-extend 0.1.6 → 0.1.9
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/README.md +34 -0
- package/bin/pix.mjs +4 -4
- package/dist/app/app.js +38 -38
- package/dist/app/{cli.d.ts → cli/cli.d.ts} +1 -1
- package/dist/app/{cli.js → cli/cli.js} +1 -1
- package/dist/app/{install.js → cli/install.js} +2 -2
- package/dist/app/{command-controller.d.ts → commands/command-controller.d.ts} +1 -1
- package/dist/app/{command-host.d.ts → commands/command-host.d.ts} +3 -3
- package/dist/app/{command-model-actions.d.ts → commands/command-model-actions.d.ts} +1 -1
- package/dist/app/{command-model-actions.js → commands/command-model-actions.js} +2 -2
- package/dist/app/{command-navigation-actions.d.ts → commands/command-navigation-actions.d.ts} +1 -1
- package/dist/app/{command-navigation-actions.js → commands/command-navigation-actions.js} +5 -5
- package/dist/app/{command-registry.d.ts → commands/command-registry.d.ts} +1 -1
- package/dist/app/{command-runtime.js → commands/command-runtime.js} +1 -1
- package/dist/app/{command-session-actions.js → commands/command-session-actions.js} +3 -3
- package/dist/app/{shell-controller.d.ts → commands/shell-controller.d.ts} +1 -1
- package/dist/app/{shell-controller.js → commands/shell-controller.js} +1 -1
- package/dist/app/{slash-commands.d.ts → commands/slash-commands.d.ts} +2 -2
- package/dist/app/{slash-commands.js → commands/slash-commands.js} +1 -1
- package/dist/app/{extension-actions-controller.d.ts → extensions/extension-actions-controller.d.ts} +1 -1
- package/dist/app/{extension-actions-controller.js → extensions/extension-actions-controller.js} +1 -1
- package/dist/app/{extension-ui-controller.d.ts → extensions/extension-ui-controller.d.ts} +3 -3
- package/dist/app/{extension-ui-controller.js → extensions/extension-ui-controller.js} +4 -3
- package/dist/app/{input-action-controller.d.ts → input/input-action-controller.d.ts} +7 -7
- package/dist/app/{input-action-controller.js → input/input-action-controller.js} +3 -3
- package/dist/app/{input-controller.d.ts → input/input-controller.d.ts} +3 -3
- package/dist/app/{input-controller.js → input/input-controller.js} +1 -1
- package/dist/app/{input-paste-handler.d.ts → input/input-paste-handler.d.ts} +1 -1
- package/dist/app/{input-paste-handler.js → input/input-paste-handler.js} +3 -3
- package/dist/app/{native-modifiers.js → input/native-modifiers.js} +2 -2
- package/dist/app/{prompt-enhancer-controller.d.ts → input/prompt-enhancer-controller.d.ts} +5 -5
- package/dist/app/{prompt-enhancer-controller.js → input/prompt-enhancer-controller.js} +3 -3
- package/dist/app/{voice-controller.d.ts → input/voice-controller.d.ts} +1 -1
- package/dist/app/{voice-controller.js → input/voice-controller.js} +2 -2
- package/dist/app/{model-ref.d.ts → model/model-ref.d.ts} +1 -1
- package/dist/app/{model-ref.js → model/model-ref.js} +1 -1
- package/dist/app/{model-usage-controller.js → model/model-usage-controller.js} +1 -1
- package/dist/app/{model-usage-status.d.ts → model/model-usage-status.d.ts} +1 -1
- package/dist/app/{model-usage-status.js → model/model-usage-status.js} +1 -1
- package/dist/app/{menu-items-controller.d.ts → popup/menu-items-controller.d.ts} +4 -4
- package/dist/app/{menu-items-controller.js → popup/menu-items-controller.js} +5 -5
- package/dist/app/{popup-action-controller.d.ts → popup/popup-action-controller.d.ts} +4 -4
- package/dist/app/{popup-action-controller.js → popup/popup-action-controller.js} +2 -2
- package/dist/app/{popup-menu-controller.d.ts → popup/popup-menu-controller.d.ts} +4 -4
- package/dist/app/{popup-menu-controller.js → popup/popup-menu-controller.js} +7 -7
- package/dist/app/{conversation-entry-renderer.d.ts → rendering/conversation-entry-renderer.d.ts} +3 -3
- package/dist/app/{conversation-entry-renderer.js → rendering/conversation-entry-renderer.js} +3 -3
- package/dist/app/{conversation-shell-renderer.d.ts → rendering/conversation-shell-renderer.d.ts} +1 -1
- package/dist/app/{conversation-shell-renderer.js → rendering/conversation-shell-renderer.js} +1 -1
- package/dist/app/{conversation-tool-renderer.d.ts → rendering/conversation-tool-renderer.d.ts} +3 -3
- package/dist/app/{conversation-tool-renderer.js → rendering/conversation-tool-renderer.js} +7 -7
- package/dist/app/{conversation-viewport.d.ts → rendering/conversation-viewport.d.ts} +3 -3
- package/dist/app/{dcp-stats.js → rendering/dcp-stats.js} +1 -1
- package/dist/app/{editor-layout-renderer.d.ts → rendering/editor-layout-renderer.d.ts} +3 -3
- package/dist/app/{editor-layout-renderer.js → rendering/editor-layout-renderer.js} +2 -2
- package/dist/app/{editor-panels.d.ts → rendering/editor-panels.d.ts} +2 -2
- package/dist/app/{editor-panels.js → rendering/editor-panels.js} +4 -4
- package/dist/app/{message-content.d.ts → rendering/message-content.d.ts} +1 -1
- package/dist/app/{message-content.js → rendering/message-content.js} +1 -1
- package/dist/app/{render-controller.d.ts → rendering/render-controller.d.ts} +6 -6
- package/dist/app/{render-controller.js → rendering/render-controller.js} +5 -5
- package/dist/app/{render-text.d.ts → rendering/render-text.d.ts} +2 -2
- package/dist/app/{render-text.js → rendering/render-text.js} +3 -3
- package/dist/app/{status-line-renderer.d.ts → rendering/status-line-renderer.d.ts} +4 -4
- package/dist/app/{status-line-renderer.js → rendering/status-line-renderer.js} +4 -4
- package/dist/app/{tab-line-renderer.d.ts → rendering/tab-line-renderer.d.ts} +3 -3
- package/dist/app/{tab-line-renderer.js → rendering/tab-line-renderer.js} +2 -2
- package/dist/app/{toast-controller.d.ts → rendering/toast-controller.d.ts} +1 -1
- package/dist/app/{toast-controller.js → rendering/toast-controller.js} +2 -2
- package/dist/app/{toast-renderer.d.ts → rendering/toast-renderer.d.ts} +3 -3
- package/dist/app/{toast-renderer.js → rendering/toast-renderer.js} +3 -3
- package/dist/app/{tool-block-renderer.d.ts → rendering/tool-block-renderer.d.ts} +5 -5
- package/dist/app/{tool-block-renderer.js → rendering/tool-block-renderer.js} +2 -2
- package/dist/app/runtime.js +1 -1
- package/dist/app/{blink-controller.js → screen/blink-controller.js} +1 -1
- package/dist/app/{image-click-targets.d.ts → screen/image-click-targets.d.ts} +2 -2
- package/dist/app/{image-opener.d.ts → screen/image-opener.d.ts} +1 -1
- package/dist/app/{mouse-controller.d.ts → screen/mouse-controller.d.ts} +13 -9
- package/dist/app/{mouse-controller.js → screen/mouse-controller.js} +56 -28
- package/dist/app/{screen-selection.d.ts → screen/screen-selection.d.ts} +1 -1
- package/dist/app/{screen-styler.d.ts → screen/screen-styler.d.ts} +2 -2
- package/dist/app/{screen-styler.js → screen/screen-styler.js} +4 -4
- package/dist/app/{scroll-controller.d.ts → screen/scroll-controller.d.ts} +3 -3
- package/dist/app/{scroll-controller.js → screen/scroll-controller.js} +1 -1
- package/dist/app/{status-controller.d.ts → screen/status-controller.d.ts} +2 -2
- package/dist/app/{status-controller.js → screen/status-controller.js} +1 -1
- package/dist/app/{queued-message-controller.d.ts → session/queued-message-controller.d.ts} +2 -2
- package/dist/app/{queued-message-controller.js → session/queued-message-controller.js} +2 -2
- package/dist/app/{request-history.js → session/request-history.js} +2 -2
- package/dist/app/{session-event-controller.d.ts → session/session-event-controller.d.ts} +3 -3
- package/dist/app/{session-event-controller.js → session/session-event-controller.js} +3 -3
- package/dist/app/{session-history.d.ts → session/session-history.d.ts} +1 -1
- package/dist/app/{session-history.js → session/session-history.js} +3 -3
- package/dist/app/{session-lifecycle-controller.d.ts → session/session-lifecycle-controller.d.ts} +2 -2
- package/dist/app/{session-lifecycle-controller.js → session/session-lifecycle-controller.js} +7 -7
- package/dist/app/{session-search.d.ts → session/session-search.d.ts} +1 -1
- package/dist/app/{session-search.js → session/session-search.js} +3 -3
- package/dist/app/{tabs-controller.d.ts → session/tabs-controller.d.ts} +2 -2
- package/dist/app/{tabs-controller.js → session/tabs-controller.js} +4 -4
- package/dist/app/{subagents-files.d.ts → subagents/subagents-files.d.ts} +1 -1
- package/dist/app/{subagents-files.js → subagents/subagents-files.js} +1 -1
- package/dist/app/{subagents-model.d.ts → subagents/subagents-model.d.ts} +1 -1
- package/dist/app/{subagents-model.js → subagents/subagents-model.js} +4 -4
- package/dist/app/{subagents-widget-controller.d.ts → subagents/subagents-widget-controller.d.ts} +1 -1
- package/dist/app/{subagents-widget-controller.js → subagents/subagents-widget-controller.js} +2 -2
- package/dist/app/{terminal-bell-sound-controller.js → terminal/terminal-bell-sound-controller.js} +1 -1
- package/dist/app/{terminal-controller.js → terminal/terminal-controller.js} +2 -2
- package/dist/app/{todo-model.d.ts → todo/todo-model.d.ts} +1 -1
- package/dist/app/{todo-model.js → todo/todo-model.js} +3 -3
- package/dist/app/{todo-widget-controller.d.ts → todo/todo-widget-controller.d.ts} +1 -1
- package/dist/app/{todo-widget-controller.js → todo/todo-widget-controller.js} +2 -2
- package/dist/app/types.d.ts +2 -2
- package/dist/app/{workspace-actions-controller.d.ts → workspace/workspace-actions-controller.d.ts} +1 -1
- package/dist/app/{workspace-actions-controller.js → workspace/workspace-actions-controller.js} +3 -3
- package/dist/main.js +2 -2
- package/external/pi-tools-suite/README.md +82 -50
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +4 -0
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +6 -2
- package/external/pi-tools-suite/src/dcp/prompts.ts +4 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +272 -2
- package/external/pi-tools-suite/src/index.ts +1 -1
- package/external/pi-tools-suite/src/lsp/_shared/config.ts +38 -13
- package/external/pi-tools-suite/src/lsp/_shared/paths.ts +11 -1
- package/external/pi-tools-suite/src/lsp/async.ts +6 -1
- package/external/pi-tools-suite/src/lsp/child-process.ts +16 -2
- package/external/pi-tools-suite/src/lsp/client.ts +183 -4
- package/external/pi-tools-suite/src/lsp/manager.ts +44 -5
- package/external/pi-tools-suite/src/lsp/markdown-diagnostics.ts +157 -0
- package/external/pi-tools-suite/src/opencode-import/commands.ts +86 -0
- package/external/pi-tools-suite/src/opencode-import/importer.ts +208 -0
- package/external/pi-tools-suite/src/opencode-import/index.ts +25 -0
- package/package.json +1 -1
- package/external/pi-tools-suite/src/terminal-bell/index.ts +0 -339
- /package/dist/app/{install.d.ts → cli/install.d.ts} +0 -0
- /package/dist/app/{startup-checks.d.ts → cli/startup-checks.d.ts} +0 -0
- /package/dist/app/{startup-checks.js → cli/startup-checks.js} +0 -0
- /package/dist/app/{startup-info.d.ts → cli/startup-info.d.ts} +0 -0
- /package/dist/app/{startup-info.js → cli/startup-info.js} +0 -0
- /package/dist/app/{update.d.ts → cli/update.d.ts} +0 -0
- /package/dist/app/{update.js → cli/update.js} +0 -0
- /package/dist/app/{command-controller.js → commands/command-controller.js} +0 -0
- /package/dist/app/{command-host.js → commands/command-host.js} +0 -0
- /package/dist/app/{command-registry.js → commands/command-registry.js} +0 -0
- /package/dist/app/{command-runtime.d.ts → commands/command-runtime.d.ts} +0 -0
- /package/dist/app/{command-session-actions.d.ts → commands/command-session-actions.d.ts} +0 -0
- /package/dist/app/{shell-command.d.ts → commands/shell-command.d.ts} +0 -0
- /package/dist/app/{shell-command.js → commands/shell-command.js} +0 -0
- /package/dist/app/{extension-event-bus.d.ts → extensions/extension-event-bus.d.ts} +0 -0
- /package/dist/app/{extension-event-bus.js → extensions/extension-event-bus.js} +0 -0
- /package/dist/app/{native-modifiers.d.ts → input/native-modifiers.d.ts} +0 -0
- /package/dist/app/{terminal-edit-shortcuts.d.ts → input/terminal-edit-shortcuts.d.ts} +0 -0
- /package/dist/app/{terminal-edit-shortcuts.js → input/terminal-edit-shortcuts.js} +0 -0
- /package/dist/app/{model-usage-controller.d.ts → model/model-usage-controller.d.ts} +0 -0
- /package/dist/app/{conversation-viewport.js → rendering/conversation-viewport.js} +0 -0
- /package/dist/app/{dcp-stats.d.ts → rendering/dcp-stats.d.ts} +0 -0
- /package/dist/app/{blink-controller.d.ts → screen/blink-controller.d.ts} +0 -0
- /package/dist/app/{clipboard.d.ts → screen/clipboard.d.ts} +0 -0
- /package/dist/app/{clipboard.js → screen/clipboard.js} +0 -0
- /package/dist/app/{file-link-opener.d.ts → screen/file-link-opener.d.ts} +0 -0
- /package/dist/app/{file-link-opener.js → screen/file-link-opener.js} +0 -0
- /package/dist/app/{file-links.d.ts → screen/file-links.d.ts} +0 -0
- /package/dist/app/{file-links.js → screen/file-links.js} +0 -0
- /package/dist/app/{image-click-targets.js → screen/image-click-targets.js} +0 -0
- /package/dist/app/{image-opener.js → screen/image-opener.js} +0 -0
- /package/dist/app/{screen-selection.js → screen/screen-selection.js} +0 -0
- /package/dist/app/{request-history.d.ts → session/request-history.d.ts} +0 -0
- /package/dist/app/{nerd-font-controller.d.ts → terminal/nerd-font-controller.d.ts} +0 -0
- /package/dist/app/{nerd-font-controller.js → terminal/nerd-font-controller.js} +0 -0
- /package/dist/app/{terminal-bell-sound-controller.d.ts → terminal/terminal-bell-sound-controller.d.ts} +0 -0
- /package/dist/app/{terminal-controller.d.ts → terminal/terminal-controller.d.ts} +0 -0
- /package/dist/app/{terminal-output-buffer.d.ts → terminal/terminal-output-buffer.d.ts} +0 -0
- /package/dist/app/{terminal-output-buffer.js → terminal/terminal-output-buffer.js} +0 -0
- /package/dist/app/{workspace-undo.d.ts → workspace/workspace-undo.d.ts} +0 -0
- /package/dist/app/{workspace-undo.js → workspace/workspace-undo.js} +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { getPiAuthPath, importOpencodeAntigravityAccount, readJsonFile, writeJsonFileSecure } from "../antigravity-auth/auth-store";
|
|
5
|
+
|
|
6
|
+
export type OpencodeAuthCredential = {
|
|
7
|
+
type?: string;
|
|
8
|
+
access?: string;
|
|
9
|
+
refresh?: string;
|
|
10
|
+
expires?: number;
|
|
11
|
+
key?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type PiAuthCredential = OpencodeAuthCredential;
|
|
16
|
+
export type PiAuthData = Record<string, PiAuthCredential | undefined>;
|
|
17
|
+
export type OpencodeAuthData = Record<string, OpencodeAuthCredential | undefined>;
|
|
18
|
+
|
|
19
|
+
export type OpencodeProviderImportStatus = "imported" | "already-imported" | "auth-exists-use-force" | "source-missing" | "target-set-from-other-source" | "invalid-source";
|
|
20
|
+
|
|
21
|
+
export type OpencodeProviderImportResult = {
|
|
22
|
+
label: string;
|
|
23
|
+
sourceProvider: string;
|
|
24
|
+
targetProvider: string;
|
|
25
|
+
status: OpencodeProviderImportStatus;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type OpencodeImportResult = {
|
|
29
|
+
sourcePath: string;
|
|
30
|
+
antigravitySourcePath?: string;
|
|
31
|
+
authPath: string;
|
|
32
|
+
providers: OpencodeProviderImportResult[];
|
|
33
|
+
antigravity?: {
|
|
34
|
+
imported: boolean;
|
|
35
|
+
reason?: string;
|
|
36
|
+
email?: string;
|
|
37
|
+
accountIndex?: number;
|
|
38
|
+
accountCount?: number;
|
|
39
|
+
overwroteExisting?: boolean;
|
|
40
|
+
};
|
|
41
|
+
wroteAuth: boolean;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type OpencodeImportOptions = {
|
|
45
|
+
sourcePath?: string;
|
|
46
|
+
authPath?: string;
|
|
47
|
+
antigravitySourcePath?: string;
|
|
48
|
+
overwrite?: boolean;
|
|
49
|
+
skipAuthJson?: boolean;
|
|
50
|
+
skipAntigravity?: boolean;
|
|
51
|
+
antigravityAccountIndex?: number;
|
|
52
|
+
antigravityEmail?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type Mapping = {
|
|
56
|
+
label: string;
|
|
57
|
+
sourceProvider: string;
|
|
58
|
+
targetProvider: string;
|
|
59
|
+
transform: (credential: OpencodeAuthCredential) => PiAuthCredential | undefined;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const AUTH_JSON_MAPPINGS: Mapping[] = [
|
|
63
|
+
{
|
|
64
|
+
label: "OpenAI Codex",
|
|
65
|
+
sourceProvider: "openai",
|
|
66
|
+
targetProvider: "openai-codex",
|
|
67
|
+
transform: transformOAuthCredential,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
label: "GitHub Copilot",
|
|
71
|
+
sourceProvider: "github-copilot",
|
|
72
|
+
targetProvider: "github-copilot",
|
|
73
|
+
transform: transformOAuthCredential,
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
label: "Z.ai",
|
|
77
|
+
sourceProvider: "zai-coding-plan",
|
|
78
|
+
targetProvider: "zai",
|
|
79
|
+
transform: transformApiKeyCredential,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
label: "Zhipu/Z.ai",
|
|
83
|
+
sourceProvider: "zhipuai-coding-plan",
|
|
84
|
+
targetProvider: "zai",
|
|
85
|
+
transform: transformApiKeyCredential,
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
export function getDefaultOpencodeAuthPath(): string {
|
|
90
|
+
const dataDir = process.env.OPENCODE_DATA_DIR ?? join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "opencode");
|
|
91
|
+
return join(dataDir, "auth.json");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function transformOAuthCredential(credential: OpencodeAuthCredential): PiAuthCredential | undefined {
|
|
95
|
+
if (!credential.access && !credential.refresh) return undefined;
|
|
96
|
+
return { ...credential, type: "oauth" };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function transformApiKeyCredential(credential: OpencodeAuthCredential): PiAuthCredential | undefined {
|
|
100
|
+
if (!credential.key) return undefined;
|
|
101
|
+
return { ...credential, type: "api_key", key: credential.key };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function sameCredential(a: PiAuthCredential | undefined, b: PiAuthCredential | undefined): boolean {
|
|
105
|
+
return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function providerResult(mapping: Mapping, status: OpencodeProviderImportStatus): OpencodeProviderImportResult {
|
|
109
|
+
return {
|
|
110
|
+
label: mapping.label,
|
|
111
|
+
sourceProvider: mapping.sourceProvider,
|
|
112
|
+
targetProvider: mapping.targetProvider,
|
|
113
|
+
status,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function pathExists(path: string): Promise<boolean> {
|
|
118
|
+
try {
|
|
119
|
+
await fs.access(path);
|
|
120
|
+
return true;
|
|
121
|
+
} catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function importOpencodeAccounts(options: OpencodeImportOptions = {}): Promise<OpencodeImportResult> {
|
|
127
|
+
const sourcePath = options.sourcePath ?? getDefaultOpencodeAuthPath();
|
|
128
|
+
const authPath = options.authPath ?? getPiAuthPath();
|
|
129
|
+
const result: OpencodeImportResult = {
|
|
130
|
+
sourcePath,
|
|
131
|
+
authPath,
|
|
132
|
+
providers: [],
|
|
133
|
+
wroteAuth: false,
|
|
134
|
+
};
|
|
135
|
+
if (options.antigravitySourcePath) result.antigravitySourcePath = options.antigravitySourcePath;
|
|
136
|
+
|
|
137
|
+
let piAuth = await readJsonFile<PiAuthData>(authPath, {});
|
|
138
|
+
const changedTargets = new Set<string>();
|
|
139
|
+
|
|
140
|
+
if (!options.skipAuthJson) {
|
|
141
|
+
const sourceExists = await pathExists(sourcePath);
|
|
142
|
+
const opencodeAuth = sourceExists ? await readJsonFile<OpencodeAuthData>(sourcePath, {}) : {};
|
|
143
|
+
|
|
144
|
+
for (const mapping of AUTH_JSON_MAPPINGS) {
|
|
145
|
+
const sourceCredential = opencodeAuth[mapping.sourceProvider];
|
|
146
|
+
if (!sourceCredential) {
|
|
147
|
+
result.providers.push(providerResult(mapping, "source-missing"));
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (changedTargets.has(mapping.targetProvider)) {
|
|
152
|
+
result.providers.push(providerResult(mapping, "target-set-from-other-source"));
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const nextCredential = mapping.transform(sourceCredential);
|
|
157
|
+
if (!nextCredential) {
|
|
158
|
+
result.providers.push(providerResult(mapping, "invalid-source"));
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const existingCredential = piAuth[mapping.targetProvider];
|
|
163
|
+
if (sameCredential(existingCredential, nextCredential)) {
|
|
164
|
+
result.providers.push(providerResult(mapping, "already-imported"));
|
|
165
|
+
changedTargets.add(mapping.targetProvider);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (existingCredential && !options.overwrite) {
|
|
170
|
+
result.providers.push(providerResult(mapping, "auth-exists-use-force"));
|
|
171
|
+
changedTargets.add(mapping.targetProvider);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
piAuth = { ...piAuth, [mapping.targetProvider]: nextCredential };
|
|
176
|
+
changedTargets.add(mapping.targetProvider);
|
|
177
|
+
result.providers.push(providerResult(mapping, "imported"));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (result.providers.some((provider) => provider.status === "imported")) {
|
|
181
|
+
await writeJsonFileSecure(authPath, piAuth);
|
|
182
|
+
result.wroteAuth = true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!options.skipAntigravity) {
|
|
187
|
+
const antigravity = await importOpencodeAntigravityAccount({
|
|
188
|
+
sourcePath: options.antigravitySourcePath,
|
|
189
|
+
authPath,
|
|
190
|
+
overwrite: options.overwrite,
|
|
191
|
+
accountIndex: options.antigravityAccountIndex,
|
|
192
|
+
email: options.antigravityEmail,
|
|
193
|
+
});
|
|
194
|
+
const antigravityResult: NonNullable<OpencodeImportResult["antigravity"]> = {
|
|
195
|
+
imported: antigravity.imported,
|
|
196
|
+
};
|
|
197
|
+
if (antigravity.reason) antigravityResult.reason = antigravity.reason;
|
|
198
|
+
if (antigravity.email) antigravityResult.email = antigravity.email;
|
|
199
|
+
if (typeof antigravity.accountIndex === "number") antigravityResult.accountIndex = antigravity.accountIndex;
|
|
200
|
+
if (typeof antigravity.accountCount === "number") antigravityResult.accountCount = antigravity.accountCount;
|
|
201
|
+
if (typeof antigravity.overwroteExisting === "boolean") antigravityResult.overwroteExisting = antigravity.overwroteExisting;
|
|
202
|
+
result.antigravity = antigravityResult;
|
|
203
|
+
result.antigravitySourcePath = antigravity.sourcePath;
|
|
204
|
+
result.wroteAuth ||= antigravity.imported;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { formatOpencodeImportResult, notificationLevel, parseOpencodeImportCommandArgs } from "./commands";
|
|
3
|
+
import { importOpencodeAccounts } from "./importer";
|
|
4
|
+
|
|
5
|
+
export { formatOpencodeImportResult, notificationLevel, parseOpencodeImportCommandArgs } from "./commands";
|
|
6
|
+
export { getDefaultOpencodeAuthPath, importOpencodeAccounts } from "./importer";
|
|
7
|
+
export type { OpencodeImportOptions, OpencodeImportResult } from "./importer";
|
|
8
|
+
|
|
9
|
+
export default function opencodeImport(pi: ExtensionAPI): void {
|
|
10
|
+
pi.registerCommand("opencode-import", {
|
|
11
|
+
description: "Import opencode auth.json credentials and Antigravity accounts into Pi/Pix auth.json",
|
|
12
|
+
handler: async (args: string, ctx: any) => {
|
|
13
|
+
try {
|
|
14
|
+
const result = await importOpencodeAccounts(parseOpencodeImportCommandArgs(args));
|
|
15
|
+
const message = formatOpencodeImportResult(result);
|
|
16
|
+
if (ctx.ui?.notify) ctx.ui.notify(message, notificationLevel(result));
|
|
17
|
+
else console.log(message);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20
|
+
if (ctx.ui?.notify) ctx.ui.notify(message, "error");
|
|
21
|
+
else console.error(message);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
-
import { homedir } from "node:os";
|
|
5
|
-
import { delimiter, isAbsolute, join } from "node:path";
|
|
6
|
-
import { parse as parseJsonc } from "jsonc-parser";
|
|
7
|
-
|
|
8
|
-
const BELL = "\x07";
|
|
9
|
-
const DEFAULT_IDLE_DELAY_MS = 250;
|
|
10
|
-
const IDLE_RETRY_DELAY_MS = 100;
|
|
11
|
-
const MAX_IDLE_RETRIES = 40;
|
|
12
|
-
const SUBAGENTS_LIVE_COUNT_EVENT = "pi-tools-suite:async-subagents:live-count";
|
|
13
|
-
const DEFAULT_NOTIFICATION_TITLE = "Pi";
|
|
14
|
-
const DEFAULT_NOTIFICATION_MESSAGE = "Session stopped";
|
|
15
|
-
const DEFAULT_ASK_USER_NOTIFICATION_MESSAGE = "Waiting for your answer";
|
|
16
|
-
const DEFAULT_MAC_SOUND = "Glass";
|
|
17
|
-
const TERMINAL_BELL_CONFIG_KEY = "terminalBell";
|
|
18
|
-
const SOUND_CONFIG_KEY = "sound";
|
|
19
|
-
|
|
20
|
-
const TERM_PROGRAM_BUNDLE_IDS: Record<string, string> = {
|
|
21
|
-
Apple_Terminal: "com.apple.Terminal",
|
|
22
|
-
iTerm: "com.googlecode.iterm2",
|
|
23
|
-
"iTerm.app": "com.googlecode.iterm2",
|
|
24
|
-
WezTerm: "com.github.wez.wezterm",
|
|
25
|
-
WarpTerminal: "dev.warp.Warp-Stable",
|
|
26
|
-
ghostty: "com.mitchellh.ghostty",
|
|
27
|
-
Ghostty: "com.mitchellh.ghostty",
|
|
28
|
-
kitty: "net.kovidgoyal.kitty",
|
|
29
|
-
Alacritty: "org.alacritty",
|
|
30
|
-
vscode: "com.microsoft.VSCode",
|
|
31
|
-
"vscode-insiders": "com.microsoft.VSCodeInsiders",
|
|
32
|
-
zed: "dev.zed.Zed",
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
type Timer = ReturnType<typeof setTimeout>;
|
|
36
|
-
|
|
37
|
-
type SubagentsLiveCountEvent = {
|
|
38
|
-
count?: unknown;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
function parseDelayMs(value: string | undefined): number {
|
|
42
|
-
if (value === undefined || value.trim() === "") return DEFAULT_IDLE_DELAY_MS;
|
|
43
|
-
const parsed = Number(value);
|
|
44
|
-
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_IDLE_DELAY_MS;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function isTruthyEnv(value: string | undefined): boolean {
|
|
48
|
-
if (value === undefined) return false;
|
|
49
|
-
return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function extensionDisabled(): boolean {
|
|
53
|
-
return isTruthyEnv(process.env.HEADLESS) || isTruthyEnv(process.env.PI_TERMINAL_BELL_DISABLED);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function getPiToolsSuiteUserConfigPath(homeDir = homedir()): string {
|
|
57
|
-
return join(homeDir, ".config", "pi", "pi-tools-suite.jsonc");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
61
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function readTerminalBellSoundConfig(configPath = getPiToolsSuiteUserConfigPath()): boolean | undefined {
|
|
65
|
-
if (!existsSync(configPath)) return undefined;
|
|
66
|
-
try {
|
|
67
|
-
const parsed = parseJsonc(readFileSync(configPath, "utf-8")) as unknown;
|
|
68
|
-
if (!isRecord(parsed)) return undefined;
|
|
69
|
-
const terminalBell = parsed[TERMINAL_BELL_CONFIG_KEY];
|
|
70
|
-
if (!isRecord(terminalBell)) return undefined;
|
|
71
|
-
const sound = terminalBell[SOUND_CONFIG_KEY];
|
|
72
|
-
return typeof sound === "boolean" ? sound : undefined;
|
|
73
|
-
} catch {
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function terminalBellSoundEnabled(ctx: Pick<ExtensionContext, "hasUI">, configPath = getPiToolsSuiteUserConfigPath()): boolean {
|
|
79
|
-
if (process.env.PI_TERMINAL_BELL_SOUND === "0") return false;
|
|
80
|
-
if (process.env.PI_TERMINAL_BELL_SOUND === "1") return true;
|
|
81
|
-
const configured = readTerminalBellSoundConfig(configPath);
|
|
82
|
-
if (configured !== undefined) return configured;
|
|
83
|
-
return ctx.hasUI === true;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function terminalBellNotificationsEnabled(ctx: Pick<ExtensionContext, "hasUI">, configPath = getPiToolsSuiteUserConfigPath()): boolean {
|
|
87
|
-
if (!terminalBellSoundEnabled(ctx, configPath)) return false;
|
|
88
|
-
if (process.env.PI_TERMINAL_BELL_NOTIFY === "0") return false;
|
|
89
|
-
if (process.env.PI_TERMINAL_BELL_NOTIFY === "1") return true;
|
|
90
|
-
return ctx.hasUI === true;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function canRingTerminal(ctx: Pick<ExtensionContext, "hasUI">, configPath = getPiToolsSuiteUserConfigPath()): boolean {
|
|
94
|
-
if (!terminalBellSoundEnabled(ctx, configPath)) return false;
|
|
95
|
-
if (process.env.PI_TERMINAL_BELL === "0") return false;
|
|
96
|
-
if (process.env.PI_TERMINAL_BELL_FORCE === "1") return true;
|
|
97
|
-
return Boolean(process.stdout.isTTY || process.stderr.isTTY);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function writeBell(): void {
|
|
101
|
-
const stream = process.stdout.isTTY || !process.stderr.isTTY ? process.stdout : process.stderr;
|
|
102
|
-
stream.write(BELL);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function appleScriptString(value: string): string {
|
|
106
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function shellSingleQuote(value: string): string {
|
|
110
|
-
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function spawnDetached(command: string, args: string[]): void {
|
|
114
|
-
try {
|
|
115
|
-
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
116
|
-
child.on("error", () => {});
|
|
117
|
-
child.unref();
|
|
118
|
-
} catch {
|
|
119
|
-
// Best-effort user attention signal. Missing notification backends should not
|
|
120
|
-
// affect the agent loop or suppress the terminal bell.
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function findExecutable(command: string): string | undefined {
|
|
125
|
-
if (command.includes("/")) return existsSync(command) ? command : undefined;
|
|
126
|
-
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
127
|
-
if (!dir) continue;
|
|
128
|
-
const candidate = join(dir, command);
|
|
129
|
-
if (existsSync(candidate)) return candidate;
|
|
130
|
-
}
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function resolveMacSoundPath(sound: string): string {
|
|
135
|
-
if (isAbsolute(sound)) return sound;
|
|
136
|
-
const fileName = sound.endsWith(".aiff") ? sound : `${sound}.aiff`;
|
|
137
|
-
return `/System/Library/Sounds/${fileName}`;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function detectMacActivationBundleId(): string | undefined {
|
|
141
|
-
const explicit = process.env.PI_TERMINAL_BELL_NOTIFY_ACTIVATE;
|
|
142
|
-
if (explicit === "0" || explicit === "false") return undefined;
|
|
143
|
-
if (explicit && explicit.trim() !== "") return explicit.trim();
|
|
144
|
-
|
|
145
|
-
// GUI apps that launch shells on macOS commonly export their own bundle id.
|
|
146
|
-
// This catches Terminal.app, iTerm2, Zed's terminal, VS Code terminals, etc.
|
|
147
|
-
const inheritedBundleId = process.env.__CFBundleIdentifier;
|
|
148
|
-
if (inheritedBundleId && inheritedBundleId.trim() !== "") return inheritedBundleId.trim();
|
|
149
|
-
|
|
150
|
-
const termProgram = process.env.TERM_PROGRAM;
|
|
151
|
-
if (!termProgram) return undefined;
|
|
152
|
-
return TERM_PROGRAM_BUNDLE_IDS[termProgram];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function playAttentionSound(ctx: ExtensionContext): void {
|
|
156
|
-
if (!terminalBellSoundEnabled(ctx)) return;
|
|
157
|
-
if (process.platform !== "darwin") return;
|
|
158
|
-
const sound = process.env.PI_TERMINAL_BELL_SOUND && process.env.PI_TERMINAL_BELL_SOUND !== "1"
|
|
159
|
-
? process.env.PI_TERMINAL_BELL_SOUND
|
|
160
|
-
: DEFAULT_MAC_SOUND;
|
|
161
|
-
const soundPath = resolveMacSoundPath(sound);
|
|
162
|
-
if (!existsSync(soundPath)) return;
|
|
163
|
-
spawnDetached("/usr/bin/afplay", [soundPath]);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function notifySessionStopped(
|
|
167
|
-
ctx: ExtensionContext,
|
|
168
|
-
macActivationBundleId: string | undefined,
|
|
169
|
-
message = process.env.PI_TERMINAL_BELL_NOTIFY_MESSAGE ?? DEFAULT_NOTIFICATION_MESSAGE,
|
|
170
|
-
): void {
|
|
171
|
-
if (!terminalBellNotificationsEnabled(ctx)) return;
|
|
172
|
-
const title = process.env.PI_TERMINAL_BELL_NOTIFY_TITLE ?? DEFAULT_NOTIFICATION_TITLE;
|
|
173
|
-
|
|
174
|
-
if (process.platform === "darwin") {
|
|
175
|
-
const terminalNotifier = findExecutable(process.env.PI_TERMINAL_BELL_NOTIFIER ?? "terminal-notifier");
|
|
176
|
-
if (terminalNotifier) {
|
|
177
|
-
const args = ["-title", title, "-message", message];
|
|
178
|
-
const activate = macActivationBundleId;
|
|
179
|
-
if (activate) {
|
|
180
|
-
args.push("-activate", activate);
|
|
181
|
-
args.push("-execute", `/usr/bin/open -b ${shellSingleQuote(activate)}`);
|
|
182
|
-
|
|
183
|
-
// Do not pass -sender by default. On recent macOS versions it can make the
|
|
184
|
-
// notification look like it came from the target app, but then clicking the
|
|
185
|
-
// “Show” button may be handled as that app's own notification instead of
|
|
186
|
-
// terminal-notifier's -activate/-execute action.
|
|
187
|
-
if (process.env.PI_TERMINAL_BELL_NOTIFY_SENDER === "1") {
|
|
188
|
-
args.push("-sender", activate);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
spawnDetached(terminalNotifier, args);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Bare osascript notifications are sent by Script Editor/osascript on macOS;
|
|
196
|
-
// clicking them can open Script Editor's file picker. Keep that backend opt-in
|
|
197
|
-
// and prefer terminal-notifier for clickable system notifications.
|
|
198
|
-
if (process.env.PI_TERMINAL_BELL_NOTIFY_OSASCRIPT !== "1") return;
|
|
199
|
-
spawnDetached("/usr/bin/osascript", [
|
|
200
|
-
"-e",
|
|
201
|
-
`display notification ${appleScriptString(message)} with title ${appleScriptString(title)}`,
|
|
202
|
-
]);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (process.platform === "linux") {
|
|
207
|
-
spawnDetached("notify-send", [title, message]);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const ASK_USER_TOOL_NAMES = new Set(["ask_user", "ask_user_question", "question"]);
|
|
212
|
-
|
|
213
|
-
function isAskUserToolName(toolName: string): boolean {
|
|
214
|
-
return ASK_USER_TOOL_NAMES.has(toolName);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function isSubagentsWaitTool(toolName: string, args: unknown): boolean {
|
|
218
|
-
if (toolName === "async_subagents_wait") return true;
|
|
219
|
-
if (toolName !== "subagents") return false;
|
|
220
|
-
if (!args || typeof args !== "object") return false;
|
|
221
|
-
const action = (args as { action?: unknown }).action;
|
|
222
|
-
return typeof action === "string" && action.trim().toLowerCase() === "wait";
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function normalizeLiveCount(event: SubagentsLiveCountEvent): number | undefined {
|
|
226
|
-
if (typeof event.count !== "number" || !Number.isFinite(event.count)) return undefined;
|
|
227
|
-
return Math.max(0, Math.floor(event.count));
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export default function terminalBell(pi: ExtensionAPI) {
|
|
231
|
-
if (extensionDisabled()) return;
|
|
232
|
-
|
|
233
|
-
let timer: Timer | undefined;
|
|
234
|
-
let lastCtx: ExtensionContext | undefined;
|
|
235
|
-
let deferredUntilSubagentsFinish = false;
|
|
236
|
-
let liveSubagentCount = 0;
|
|
237
|
-
const activeSubagentWaitToolCallIds = new Set<string>();
|
|
238
|
-
const notifiedAskUserToolCallIds = new Set<string>();
|
|
239
|
-
const idleDelayMs = parseDelayMs(process.env.PI_TERMINAL_BELL_DELAY_MS);
|
|
240
|
-
const macActivationBundleId = process.platform === "darwin" ? detectMacActivationBundleId() : undefined;
|
|
241
|
-
|
|
242
|
-
function clearTimer(): void {
|
|
243
|
-
if (!timer) return;
|
|
244
|
-
clearTimeout(timer);
|
|
245
|
-
timer = undefined;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function hasSubagentWork(): boolean {
|
|
249
|
-
return liveSubagentCount > 0 || activeSubagentWaitToolCallIds.size > 0;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
function notifyAttention(ctx: ExtensionContext, message?: string): void {
|
|
253
|
-
if (canRingTerminal(ctx)) writeBell();
|
|
254
|
-
playAttentionSound(ctx);
|
|
255
|
-
notifySessionStopped(ctx, macActivationBundleId, message);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function attemptBell(ctx: ExtensionContext, attempt: number): void {
|
|
259
|
-
timer = undefined;
|
|
260
|
-
|
|
261
|
-
if (!ctx.isIdle()) {
|
|
262
|
-
if (attempt < MAX_IDLE_RETRIES) scheduleBell(ctx, IDLE_RETRY_DELAY_MS, attempt + 1);
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (ctx.hasPendingMessages()) return;
|
|
267
|
-
|
|
268
|
-
if (hasSubagentWork()) {
|
|
269
|
-
deferredUntilSubagentsFinish = true;
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
deferredUntilSubagentsFinish = false;
|
|
274
|
-
notifyAttention(ctx);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function scheduleBell(ctx: ExtensionContext, delayMs = idleDelayMs, attempt = 0): void {
|
|
278
|
-
lastCtx = ctx;
|
|
279
|
-
clearTimer();
|
|
280
|
-
timer = setTimeout(() => attemptBell(ctx, attempt), delayMs);
|
|
281
|
-
timer.unref?.();
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function notifyAskUserWaiting(toolCallId: string, ctx: ExtensionContext): void {
|
|
285
|
-
if (notifiedAskUserToolCallIds.has(toolCallId)) return;
|
|
286
|
-
notifiedAskUserToolCallIds.add(toolCallId);
|
|
287
|
-
notifyAttention(ctx, process.env.PI_TERMINAL_BELL_ASK_USER_NOTIFY_MESSAGE ?? DEFAULT_ASK_USER_NOTIFICATION_MESSAGE);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
pi.events.on(SUBAGENTS_LIVE_COUNT_EVENT, (data: unknown) => {
|
|
291
|
-
const event = data && typeof data === "object" ? data as SubagentsLiveCountEvent : {};
|
|
292
|
-
const count = normalizeLiveCount(event);
|
|
293
|
-
if (count === undefined) return;
|
|
294
|
-
liveSubagentCount = count;
|
|
295
|
-
if (count === 0 && deferredUntilSubagentsFinish && lastCtx) {
|
|
296
|
-
scheduleBell(lastCtx);
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
pi.on("agent_start", async () => {
|
|
301
|
-
clearTimer();
|
|
302
|
-
deferredUntilSubagentsFinish = false;
|
|
303
|
-
activeSubagentWaitToolCallIds.clear();
|
|
304
|
-
notifiedAskUserToolCallIds.clear();
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
pi.on("tool_execution_start", async (event, ctx) => {
|
|
308
|
-
if (isSubagentsWaitTool(event.toolName, event.args)) {
|
|
309
|
-
activeSubagentWaitToolCallIds.add(event.toolCallId);
|
|
310
|
-
}
|
|
311
|
-
if (isAskUserToolName(event.toolName)) {
|
|
312
|
-
notifyAskUserWaiting(event.toolCallId, ctx);
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
pi.on("tool_call", async (event, ctx) => {
|
|
317
|
-
if (isAskUserToolName(event.toolName)) {
|
|
318
|
-
notifyAskUserWaiting(event.toolCallId, ctx);
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
pi.on("tool_execution_end", async (event) => {
|
|
323
|
-
activeSubagentWaitToolCallIds.delete(event.toolCallId);
|
|
324
|
-
notifiedAskUserToolCallIds.delete(event.toolCallId);
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
pi.on("agent_end", async (_event, ctx) => {
|
|
328
|
-
scheduleBell(ctx);
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
pi.on("session_shutdown", async () => {
|
|
332
|
-
clearTimer();
|
|
333
|
-
lastCtx = undefined;
|
|
334
|
-
deferredUntilSubagentsFinish = false;
|
|
335
|
-
liveSubagentCount = 0;
|
|
336
|
-
activeSubagentWaitToolCallIds.clear();
|
|
337
|
-
notifiedAskUserToolCallIds.clear();
|
|
338
|
-
});
|
|
339
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|