@opengsd/gsd-pi 1.0.2-dev.5961fbf → 1.0.2-dev.5f7864c
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 +63 -12
- package/dist/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +2 -0
- package/dist/resource-loader.js +18 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -15
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +1 -1
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -1
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +13 -13
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +57 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +64 -28
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -15
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +1 -1
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +56 -4
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/shared/package-manager-detection.ts +39 -0
- /package/dist/web/standalone/.next/static/{spUYLkQXoHJyxYOMH9VQy → IjxvcC7sl_MHNKXsUZrAy}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{spUYLkQXoHJyxYOMH9VQy → IjxvcC7sl_MHNKXsUZrAy}/_ssgManifest.js +0 -0
|
@@ -22,6 +22,7 @@ import { gsdHome } from "./gsd-home.js";
|
|
|
22
22
|
// ─── Provider Registry ─────────────────────────────────────────────────────────
|
|
23
23
|
|
|
24
24
|
export type ProviderCategory = "llm" | "tool" | "search" | "remote";
|
|
25
|
+
export type ProviderAuthMode = "apiKey" | "browserOAuth" | "externalCli" | "cloudIdentity" | "none";
|
|
25
26
|
|
|
26
27
|
export interface ProviderInfo {
|
|
27
28
|
id: string;
|
|
@@ -29,24 +30,24 @@ export interface ProviderInfo {
|
|
|
29
30
|
category: ProviderCategory;
|
|
30
31
|
envVar?: string;
|
|
31
32
|
prefixes?: string[];
|
|
32
|
-
|
|
33
|
+
authMode?: ProviderAuthMode;
|
|
33
34
|
dashboardUrl?: string;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export const PROVIDER_REGISTRY: ProviderInfo[] = [
|
|
37
38
|
// LLM Providers
|
|
38
|
-
{ id: "anthropic", label: "Anthropic (Claude)", category: "llm", envVar: "ANTHROPIC_API_KEY", prefixes: ["sk-ant-"],
|
|
39
|
+
{ id: "anthropic", label: "Anthropic (Claude)", category: "llm", envVar: "ANTHROPIC_API_KEY", prefixes: ["sk-ant-"], authMode: "apiKey", dashboardUrl: "console.anthropic.com" },
|
|
39
40
|
// Claude Code CLI: routes through the local `claude` binary — no API key,
|
|
40
41
|
// authentication is handled by the CLI's own OAuth flow.
|
|
41
42
|
// Referenced by doctor-providers.ts, auto-model-selection.ts, and others;
|
|
42
43
|
// must be in the canonical registry so all consumers see the same catalog.
|
|
43
44
|
// See: https://github.com/open-gsd/gsd-pi/issues/4541
|
|
44
|
-
{ id: "claude-code", label: "Claude Code CLI", category: "llm",
|
|
45
|
+
{ id: "claude-code", label: "Claude Code CLI", category: "llm", authMode: "externalCli" },
|
|
45
46
|
{ id: "openai", label: "OpenAI", category: "llm", envVar: "OPENAI_API_KEY", prefixes: ["sk-"], dashboardUrl: "platform.openai.com/api-keys" },
|
|
46
|
-
{ id: "github-copilot", label: "GitHub Copilot", category: "llm", envVar: "GITHUB_TOKEN",
|
|
47
|
-
{ id: "openai-codex", label: "ChatGPT Plus/Pro (Codex)",category: "llm",
|
|
48
|
-
{ id: "google-gemini-cli",label: "Google Gemini CLI", category: "llm",
|
|
49
|
-
{ id: "google-antigravity",label: "Antigravity", category: "llm",
|
|
47
|
+
{ id: "github-copilot", label: "GitHub Copilot", category: "llm", envVar: "GITHUB_TOKEN", authMode: "browserOAuth" },
|
|
48
|
+
{ id: "openai-codex", label: "ChatGPT Plus/Pro (Codex)",category: "llm", authMode: "browserOAuth" },
|
|
49
|
+
{ id: "google-gemini-cli",label: "Google Gemini CLI", category: "llm", authMode: "externalCli" },
|
|
50
|
+
{ id: "google-antigravity",label: "Antigravity", category: "llm", authMode: "externalCli" },
|
|
50
51
|
{ id: "google", label: "Google (Gemini)", category: "llm", envVar: "GEMINI_API_KEY", dashboardUrl: "aistudio.google.com/apikey" },
|
|
51
52
|
{ id: "groq", label: "Groq", category: "llm", envVar: "GROQ_API_KEY", dashboardUrl: "console.groq.com" },
|
|
52
53
|
{ id: "xai", label: "xAI (Grok)", category: "llm", envVar: "XAI_API_KEY", dashboardUrl: "console.x.ai" },
|
|
@@ -77,6 +78,21 @@ export const PROVIDER_REGISTRY: ProviderInfo[] = [
|
|
|
77
78
|
|
|
78
79
|
// ─── Utilities ──────────────────────────────────────────────────────────────────
|
|
79
80
|
|
|
81
|
+
export function getProviderAuthMode(provider: ProviderInfo): ProviderAuthMode {
|
|
82
|
+
return provider.authMode ?? "apiKey";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function supportsBrowserOAuth(provider: ProviderInfo): boolean {
|
|
86
|
+
return getProviderAuthMode(provider) === "browserOAuth";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function supportsStoredApiKey(provider: ProviderInfo): boolean {
|
|
90
|
+
const mode = getProviderAuthMode(provider);
|
|
91
|
+
if (mode === "externalCli" || mode === "cloudIdentity" || mode === "none") return false;
|
|
92
|
+
if (mode === "browserOAuth") return Boolean(provider.envVar || provider.prefixes?.length);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
80
96
|
/**
|
|
81
97
|
* Mask an API key for display: show first 4 + last 4 chars.
|
|
82
98
|
* Keys shorter than 12 chars show only first 2 + last 2.
|
|
@@ -104,10 +120,13 @@ export function formatDuration(ms: number): string {
|
|
|
104
120
|
/**
|
|
105
121
|
* Describe a credential's type and status.
|
|
106
122
|
*/
|
|
107
|
-
export function describeCredential(cred: AuthCredential): string {
|
|
123
|
+
export function describeCredential(cred: AuthCredential, provider?: ProviderInfo): string {
|
|
108
124
|
if (cred.type === "api_key") {
|
|
109
125
|
const apiCred = cred as ApiKeyCredential;
|
|
110
126
|
if (!apiCred.key) return "empty key";
|
|
127
|
+
if (apiCred.key === "cli" && provider && getProviderAuthMode(provider) === "externalCli") {
|
|
128
|
+
return "external CLI";
|
|
129
|
+
}
|
|
111
130
|
return `API key (${maskKey(apiCred.key)})`;
|
|
112
131
|
}
|
|
113
132
|
if (cred.type === "oauth") {
|
|
@@ -171,7 +190,7 @@ export function getAllKeyStatuses(auth: AuthStorage): KeyStatus[] {
|
|
|
171
190
|
const desc =
|
|
172
191
|
creds.length > 1
|
|
173
192
|
? `${creds.length} keys (round-robin)`
|
|
174
|
-
: describeCredential(firstCred);
|
|
193
|
+
: describeCredential(firstCred, provider);
|
|
175
194
|
return {
|
|
176
195
|
provider,
|
|
177
196
|
configured: true,
|
|
@@ -289,9 +308,28 @@ export async function handleAddKey(
|
|
|
289
308
|
provider = PROVIDER_REGISTRY[idx];
|
|
290
309
|
}
|
|
291
310
|
|
|
292
|
-
|
|
293
|
-
if (
|
|
294
|
-
|
|
311
|
+
const authMode = getProviderAuthMode(provider);
|
|
312
|
+
if (authMode === "externalCli") {
|
|
313
|
+
ctx.ui.notify(
|
|
314
|
+
`${provider.label} is authenticated by its own local CLI. ` +
|
|
315
|
+
`Sign in with that CLI first, then run /login to activate it in GSD.`,
|
|
316
|
+
"info",
|
|
317
|
+
);
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (authMode === "cloudIdentity") {
|
|
322
|
+
ctx.ui.notify(
|
|
323
|
+
`${provider.label} uses cloud identity credentials. Configure the provider's cloud CLI or environment, then restart GSD.`,
|
|
324
|
+
"info",
|
|
325
|
+
);
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (supportsBrowserOAuth(provider)) {
|
|
330
|
+
const methods = supportsStoredApiKey(provider)
|
|
331
|
+
? ["API token/key", "Browser login (OAuth)"]
|
|
332
|
+
: ["Browser login (OAuth)"];
|
|
295
333
|
const method = await ctx.ui.select(
|
|
296
334
|
`${provider.label} — how do you want to authenticate?`,
|
|
297
335
|
methods,
|
|
@@ -308,6 +346,11 @@ export async function handleAddKey(
|
|
|
308
346
|
}
|
|
309
347
|
}
|
|
310
348
|
|
|
349
|
+
if (!supportsStoredApiKey(provider)) {
|
|
350
|
+
ctx.ui.notify(`${provider.label} does not accept a GSD-stored API key. Use /login.`, "info");
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
|
|
311
354
|
// API key input
|
|
312
355
|
const input = await ctx.ui.input(
|
|
313
356
|
`API key for ${provider.label}:`,
|
|
@@ -387,7 +430,7 @@ export async function handleRemoveKey(
|
|
|
387
430
|
|
|
388
431
|
// Multi-key handling
|
|
389
432
|
if (creds.length > 1) {
|
|
390
|
-
const options = creds.map((c, i) => `[${i + 1}] ${describeCredential(c)}`);
|
|
433
|
+
const options = creds.map((c, i) => `[${i + 1}] ${describeCredential(c, provider)}`);
|
|
391
434
|
options.push("Remove all");
|
|
392
435
|
|
|
393
436
|
const choice = await ctx.ui.select(
|
|
@@ -411,7 +454,7 @@ export async function handleRemoveKey(
|
|
|
411
454
|
} else {
|
|
412
455
|
const confirmed = await ctx.ui.confirm(
|
|
413
456
|
"Remove key?",
|
|
414
|
-
`Remove ${describeCredential(creds[0])} for ${provider.label}?`,
|
|
457
|
+
`Remove ${describeCredential(creds[0], provider)} for ${provider.label}?`,
|
|
415
458
|
);
|
|
416
459
|
if (!confirmed) return false;
|
|
417
460
|
auth.remove(provider.id);
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
16
16
|
import {
|
|
17
17
|
padRightVisible,
|
|
18
|
-
|
|
18
|
+
renderDialogFrame,
|
|
19
19
|
renderKeyHints,
|
|
20
20
|
rightAlign,
|
|
21
21
|
wrapVisibleText,
|
|
@@ -200,13 +200,20 @@ export class GSDNotificationOverlay {
|
|
|
200
200
|
availableRows,
|
|
201
201
|
Math.max(1, Math.floor((terminalRows * OVERLAY_MAX_HEIGHT_PERCENT) / 100)),
|
|
202
202
|
);
|
|
203
|
-
const maxVisibleRows = Math.max(5, overlayRows -
|
|
203
|
+
const maxVisibleRows = Math.max(5, overlayRows - 4);
|
|
204
204
|
const visibleContentRows = Math.min(content.length, maxVisibleRows);
|
|
205
205
|
const maxScroll = Math.max(0, content.length - visibleContentRows);
|
|
206
206
|
this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
|
|
207
207
|
const visibleContent = content.slice(this.scrollOffset, this.scrollOffset + visibleContentRows);
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
const footer = renderKeyHints(
|
|
209
|
+
this.theme,
|
|
210
|
+
["↑/↓ scroll", "f filter", "c clear", `Esc/${formattedShortcutPair("notifications")} close`],
|
|
211
|
+
Math.max(1, width - 4),
|
|
212
|
+
);
|
|
213
|
+
const lines = renderDialogFrame(this.theme, "Notifications", visibleContent, width, {
|
|
214
|
+
footer,
|
|
215
|
+
scroll: { offset: this.scrollOffset, visibleRows: visibleContentRows, totalRows: content.length },
|
|
216
|
+
});
|
|
210
217
|
|
|
211
218
|
this.cachedWidth = width;
|
|
212
219
|
this.cachedLines = lines;
|
|
@@ -256,8 +263,6 @@ export class GSDNotificationOverlay {
|
|
|
256
263
|
const blank = () => row("");
|
|
257
264
|
const hr = () => row(th.fg("dim", "─".repeat(contentWidth)));
|
|
258
265
|
|
|
259
|
-
// Header
|
|
260
|
-
const title = th.fg("accent", th.bold("Notifications"));
|
|
261
266
|
const filterLabel = this.filter === "all"
|
|
262
267
|
? th.fg("dim", "all")
|
|
263
268
|
: th.fg(
|
|
@@ -269,15 +274,11 @@ export class GSDNotificationOverlay {
|
|
|
269
274
|
);
|
|
270
275
|
const count = `${this.filteredEntries.length} entries`;
|
|
271
276
|
lines.push(row(rightAlign(
|
|
272
|
-
`${
|
|
277
|
+
`${th.fg("dim", "filter:")} ${filterLabel}`,
|
|
273
278
|
th.fg("dim", count),
|
|
274
279
|
contentWidth,
|
|
275
280
|
)));
|
|
276
281
|
lines.push(hr());
|
|
277
|
-
|
|
278
|
-
// Controls
|
|
279
|
-
const closeShortcut = formattedShortcutPair("notifications");
|
|
280
|
-
lines.push(row(renderKeyHints(th, ["↑/↓ scroll", "f filter", "c clear", `Esc/${closeShortcut} close`], contentWidth)));
|
|
281
282
|
lines.push(blank());
|
|
282
283
|
|
|
283
284
|
// Entries
|
|
@@ -13,6 +13,7 @@ import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
|
13
13
|
import { resolveGsdPathContract } from "./paths.js";
|
|
14
14
|
import {
|
|
15
15
|
renderBar,
|
|
16
|
+
renderDialogFrame,
|
|
16
17
|
renderKeyHints,
|
|
17
18
|
renderProgressBar,
|
|
18
19
|
safeLine,
|
|
@@ -378,19 +379,18 @@ export class ParallelMonitorOverlay {
|
|
|
378
379
|
const t = this.theme;
|
|
379
380
|
const lines: string[] = [];
|
|
380
381
|
const w = Math.max(1, width);
|
|
382
|
+
const contentWidth = Math.max(1, w - 4);
|
|
381
383
|
|
|
382
|
-
// Header
|
|
383
384
|
const totalCost = this.workers.reduce((s, wk) => s + wk.cost, 0);
|
|
384
385
|
const aliveCount = this.workers.filter((wk) => wk.alive).length;
|
|
385
386
|
const now = new Date().toLocaleTimeString();
|
|
386
387
|
|
|
387
|
-
lines.push(t.bold(t.fg("accent", " GSD Parallel Monitor ")));
|
|
388
388
|
lines.push(
|
|
389
389
|
t.fg("muted", ` ${now} │ ${aliveCount}/${this.workers.length} alive │ Total: `) +
|
|
390
390
|
t.bold(`$${totalCost.toFixed(2)}`) +
|
|
391
391
|
t.fg("muted", " │ 5s refresh"),
|
|
392
392
|
);
|
|
393
|
-
lines.push(renderBar(t,
|
|
393
|
+
lines.push(renderBar(t, contentWidth));
|
|
394
394
|
|
|
395
395
|
if (this.workers.length === 0) {
|
|
396
396
|
lines.push("");
|
|
@@ -444,7 +444,7 @@ export class ParallelMonitorOverlay {
|
|
|
444
444
|
lines.push(` ${t.fg("muted", "slices")} ${chips.join(" ")}`);
|
|
445
445
|
|
|
446
446
|
// Task progress bar
|
|
447
|
-
const barWidth = Math.max(6, Math.min(25,
|
|
447
|
+
const barWidth = Math.max(6, Math.min(25, contentWidth - 32));
|
|
448
448
|
const bar = renderProgressBar(t, wk.doneTasks, wk.totalTasks, barWidth, {
|
|
449
449
|
filledChar: "█",
|
|
450
450
|
emptyChar: "░",
|
|
@@ -466,7 +466,7 @@ export class ParallelMonitorOverlay {
|
|
|
466
466
|
|
|
467
467
|
// Event feed
|
|
468
468
|
lines.push("");
|
|
469
|
-
lines.push(renderBar(t,
|
|
469
|
+
lines.push(renderBar(t, contentWidth));
|
|
470
470
|
lines.push(` ${t.bold("Recent Events")}`);
|
|
471
471
|
|
|
472
472
|
if (this.events.length === 0) {
|
|
@@ -478,7 +478,6 @@ export class ParallelMonitorOverlay {
|
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
-
// Footer
|
|
482
481
|
lines.push("");
|
|
483
482
|
const allDone = this.workers.length > 0 && this.workers.every((wk) => !wk.alive);
|
|
484
483
|
if (allDone) {
|
|
@@ -491,17 +490,22 @@ export class ParallelMonitorOverlay {
|
|
|
491
490
|
}
|
|
492
491
|
lines.push(` ${t.bold("Total: $" + this.workers.reduce((s, wk) => s + wk.cost, 0).toFixed(2))}`);
|
|
493
492
|
}
|
|
494
|
-
lines.push(renderKeyHints(t, [`ESC/q/${formattedShortcutPair("parallel")} close`, "↑↓ scroll"], w));
|
|
495
493
|
|
|
496
494
|
// Apply scroll — use terminal rows as height estimate
|
|
497
495
|
const termHeight = process.stdout.rows || 40;
|
|
498
|
-
const
|
|
496
|
+
const maxBodyRows = Math.max(1, Math.min(lines.length, termHeight - 12));
|
|
497
|
+
const maxScroll = Math.max(0, lines.length - maxBodyRows);
|
|
499
498
|
this.scrollOffset = Math.min(Math.max(this.scrollOffset, 0), maxScroll);
|
|
500
499
|
const visible = lines
|
|
501
|
-
.slice(this.scrollOffset, this.scrollOffset +
|
|
502
|
-
.map((line) => safeLine(line,
|
|
503
|
-
|
|
500
|
+
.slice(this.scrollOffset, this.scrollOffset + maxBodyRows)
|
|
501
|
+
.map((line) => safeLine(line, contentWidth));
|
|
502
|
+
const footer = renderKeyHints(t, [`ESC/q/${formattedShortcutPair("parallel")} close`, "↑↓ scroll"], contentWidth);
|
|
503
|
+
|
|
504
|
+
this.cachedLines = renderDialogFrame(t, "GSD Parallel Monitor", visible, w, {
|
|
505
|
+
footer,
|
|
506
|
+
scroll: { offset: this.scrollOffset, visibleRows: maxBodyRows, totalRows: lines.length },
|
|
507
|
+
});
|
|
504
508
|
this.cachedWidth = width;
|
|
505
|
-
return
|
|
509
|
+
return this.cachedLines;
|
|
506
510
|
}
|
|
507
511
|
}
|
|
@@ -22,6 +22,7 @@ import { join, dirname } from "node:path";
|
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
23
|
import { logWarning } from "./workflow-logger.js";
|
|
24
24
|
import { gsdHome } from "./gsd-home.js";
|
|
25
|
+
import { chooseVisionAskVariant } from "./vision-ask.js";
|
|
25
26
|
|
|
26
27
|
type ExistsFn = (path: string) => boolean;
|
|
27
28
|
|
|
@@ -184,6 +185,7 @@ export function loadPrompt(name: string, vars: Record<string, string> = {}): str
|
|
|
184
185
|
planTemplatePath: join(getTemplatesDir(), "plan.md"),
|
|
185
186
|
taskPlanTemplatePath: join(getTemplatesDir(), "task-plan.md"),
|
|
186
187
|
taskSummaryTemplatePath: join(getTemplatesDir(), "task-summary.md"),
|
|
188
|
+
visionAsk: chooseVisionAskVariant(),
|
|
187
189
|
skillActivation: "If a `GSD Skill Preferences` block is present in system context, use it and the `<available_skills>` catalog in your system prompt to decide which skills to load and follow for this unit, without relaxing required verification or artifact rules.",
|
|
188
190
|
...vars,
|
|
189
191
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{{preamble}}
|
|
2
2
|
|
|
3
|
-
Ask
|
|
3
|
+
Ask exactly this once: "{{visionAsk}}" Then use the user's reply as vision input.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The opener is intentionally variable so GSD feels alive across project starts. Keep it natural, easy to answer, and assistant/developer shaped: plain language, light guidance, no corporate wording, no roleplay.
|
|
6
|
+
|
|
7
|
+
**Special handling:** If the **user's** message is status, branch state, clarification, or any other non-project-description, treat it as vision input and proceed instead of repeating the opener. Do **not** treat the system preamble above (e.g. "New milestone M00X.") as vision input — wait for the user.
|
|
6
8
|
|
|
7
9
|
## Reflection Step
|
|
8
10
|
|
|
@@ -4,6 +4,8 @@ Discuss milestone {{milestoneId}} ("{{milestoneTitle}}"). Identify real gray are
|
|
|
4
4
|
|
|
5
5
|
**Structured questions available: {{structuredQuestionsAvailable}}**
|
|
6
6
|
|
|
7
|
+
**Conversation opener:** For the first user-facing question round, if you need a broad starting question, use: "{{visionAsk}}" Pair it with investigation-shaped follow-ups. Keep the tone natural and easy to answer, like an assistant/developer helping the user shape the next piece of work.
|
|
8
|
+
|
|
7
9
|
{{inlinedTemplates}}
|
|
8
10
|
|
|
9
11
|
---
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
12
12
|
import { type Theme } from "@gsd/pi-coding-agent";
|
|
13
13
|
import { Key, matchesKey, truncateToWidth, type TUI } from "@gsd/pi-tui";
|
|
14
|
-
import { makeUI } from "../shared/tui.js";
|
|
15
14
|
import { GLYPH } from "../shared/mod.js";
|
|
16
15
|
import { validateQueueOrder, type DependencyValidation } from "./queue-order.js";
|
|
16
|
+
import { renderDialogFrame, renderKeyHints } from "./tui/render-kit.js";
|
|
17
17
|
|
|
18
18
|
export interface ReorderItem {
|
|
19
19
|
id: string;
|
|
@@ -45,6 +45,7 @@ export async function showQueueReorder(
|
|
|
45
45
|
let grabbed = false;
|
|
46
46
|
let scrollOffset = 0;
|
|
47
47
|
let cachedLines: string[] | undefined;
|
|
48
|
+
let cachedWidth: number | undefined;
|
|
48
49
|
let validation: DependencyValidation;
|
|
49
50
|
|
|
50
51
|
// Mutable deps map — tracks removals during this session
|
|
@@ -66,6 +67,7 @@ export async function showQueueReorder(
|
|
|
66
67
|
|
|
67
68
|
function refresh() {
|
|
68
69
|
cachedLines = undefined;
|
|
70
|
+
cachedWidth = undefined;
|
|
69
71
|
tui.requestRender();
|
|
70
72
|
}
|
|
71
73
|
|
|
@@ -151,17 +153,15 @@ export async function showQueueReorder(
|
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
function render(width: number): string[] {
|
|
154
|
-
if (cachedLines) return cachedLines;
|
|
156
|
+
if (cachedLines && cachedWidth === width) return cachedLines;
|
|
155
157
|
|
|
156
|
-
const
|
|
158
|
+
const contentWidth = Math.max(1, width - 4);
|
|
157
159
|
const lines: string[] = [];
|
|
158
160
|
const queueRows: string[] = [];
|
|
159
|
-
const
|
|
160
|
-
const add = (s: string) => truncateToWidth(s, width);
|
|
161
|
+
const add = (s: string) => truncateToWidth(s, contentWidth);
|
|
161
162
|
let cursorQueueRow = 0;
|
|
162
163
|
|
|
163
|
-
const headerText = grabbed ? "
|
|
164
|
-
push(ui.bar(), ui.blank(), ui.header(headerText), ui.blank());
|
|
164
|
+
const headerText = grabbed ? "Queue Reorder - Moving Item" : "Queue Reorder";
|
|
165
165
|
|
|
166
166
|
// Completed milestones (dimmed)
|
|
167
167
|
if (completed.length > 0) {
|
|
@@ -170,7 +170,7 @@ export async function showQueueReorder(
|
|
|
170
170
|
const label = m.title && m.title !== m.id ? `${m.id} ${m.title}` : m.id;
|
|
171
171
|
lines.push(add(` ${theme.fg("dim", `${GLYPH.statusDone} ${label}`)}`));
|
|
172
172
|
}
|
|
173
|
-
push(
|
|
173
|
+
lines.push("");
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
// Pending milestones
|
|
@@ -223,7 +223,7 @@ export async function showQueueReorder(
|
|
|
223
223
|
// Removed deps feedback
|
|
224
224
|
const trailingLines: string[] = [];
|
|
225
225
|
if (removedDeps.length > 0) {
|
|
226
|
-
trailingLines.push(
|
|
226
|
+
trailingLines.push("");
|
|
227
227
|
for (const r of removedDeps) {
|
|
228
228
|
trailingLines.push(add(` ${theme.fg("success", `${GLYPH.statusDone} Removed: ${r.milestone} depends_on ${r.dep}`)}`));
|
|
229
229
|
}
|
|
@@ -232,12 +232,10 @@ export async function showQueueReorder(
|
|
|
232
232
|
// Circular warning
|
|
233
233
|
const circ = validation.violations.find(v => v.type === 'circular');
|
|
234
234
|
if (circ) {
|
|
235
|
-
trailingLines.push(
|
|
235
|
+
trailingLines.push("");
|
|
236
236
|
trailingLines.push(add(` ${theme.fg("error", `${GLYPH.statusWarning} ${circ.message}`)}`));
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
trailingLines.push(...ui.blank());
|
|
240
|
-
|
|
241
239
|
// Hints — context-sensitive based on grab state
|
|
242
240
|
const hints: string[] = [];
|
|
243
241
|
if (grabbed) {
|
|
@@ -256,10 +254,9 @@ export async function showQueueReorder(
|
|
|
256
254
|
}
|
|
257
255
|
hints.push("esc");
|
|
258
256
|
|
|
259
|
-
trailingLines.push(...ui.hints(hints), ...ui.bar());
|
|
260
|
-
|
|
261
257
|
const maxOverlayRows = Math.max(10, process.stdout.rows ? Math.floor(process.stdout.rows * 0.8) : 24);
|
|
262
|
-
const
|
|
258
|
+
const frameRows = 4;
|
|
259
|
+
const availableQueueRows = Math.max(1, maxOverlayRows - frameRows - lines.length - trailingLines.length);
|
|
263
260
|
const maxScroll = Math.max(0, queueRows.length - availableQueueRows);
|
|
264
261
|
if (cursorQueueRow < scrollOffset) {
|
|
265
262
|
scrollOffset = cursorQueueRow;
|
|
@@ -268,13 +265,25 @@ export async function showQueueReorder(
|
|
|
268
265
|
}
|
|
269
266
|
scrollOffset = Math.min(Math.max(scrollOffset, 0), maxScroll);
|
|
270
267
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
const queueStartRow = lines.length;
|
|
269
|
+
const visibleQueueRows = queueRows.slice(scrollOffset, scrollOffset + availableQueueRows);
|
|
270
|
+
lines.push(...visibleQueueRows, ...trailingLines);
|
|
271
|
+
|
|
272
|
+
cachedLines = renderDialogFrame(theme, headerText, lines, width, {
|
|
273
|
+
footer: renderKeyHints(theme, hints, contentWidth),
|
|
274
|
+
scroll: {
|
|
275
|
+
offset: scrollOffset,
|
|
276
|
+
visibleRows: availableQueueRows,
|
|
277
|
+
totalRows: queueRows.length,
|
|
278
|
+
trackOffset: queueStartRow,
|
|
279
|
+
trackRows: visibleQueueRows.length,
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
cachedWidth = width;
|
|
283
|
+
return cachedLines;
|
|
275
284
|
}
|
|
276
285
|
|
|
277
|
-
return { render, invalidate: () => { cachedLines = undefined; }, handleInput };
|
|
286
|
+
return { render, invalidate: () => { cachedLines = undefined; cachedWidth = undefined; }, handleInput };
|
|
278
287
|
}, {
|
|
279
288
|
overlay: true,
|
|
280
289
|
overlayOptions: { width: "70%", minWidth: 50, maxHeight: "80%", anchor: "center" },
|