@gajae-code/coding-agent 0.11.6 → 0.11.8
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 +92 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-activation.d.ts +4 -3
- package/dist/types/config/model-profile-contract.d.ts +38 -0
- package/dist/types/config/settings-schema.d.ts +70 -7
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/gjc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +20 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/main.d.ts +32 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +2 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
- package/dist/types/modes/interactive-mode.d.ts +7 -2
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +4 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/manager.d.ts +1 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +26 -1
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +105 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +18 -3
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +189 -4
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +1 -1
- package/dist/types/sdk/host/query/handlers.d.ts +9 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/startup-capability.d.ts +3 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +30 -5
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +32 -9
- package/dist/types/session/internal/managed-session-storage.d.ts +27 -10
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/session-manager.d.ts +25 -4
- package/dist/types/session/session-storage.d.ts +18 -0
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +94 -0
- package/dist/types/tools/ask.d.ts +454 -174
- package/dist/types/tools/fetch.d.ts +5 -8
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -8
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-sdk-operation-inventory.ts +4 -0
- package/scripts/run-test-manifest.ts +4 -4
- package/src/capability/index.ts +50 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +2 -92
- package/src/cli/notify-cli.ts +5 -38
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +52 -9
- package/src/commands/daemon.ts +22 -5
- package/src/commands/sdk.ts +44 -11
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-activation.ts +7 -18
- package/src/config/model-profile-contract.ts +161 -0
- package/src/config/model-profiles.ts +18 -0
- package/src/config/model-registry.ts +11 -1
- package/src/config/settings-schema.ts +73 -7
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +2 -2
- package/src/defaults/gjc/skills/ralplan/SKILL.md +3 -1
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +42 -1
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/py/executor.ts +30 -11
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +2 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/gjc-runtime/launch-tmux.ts +1 -1
- package/src/gjc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/gjc-runtime/ralplan-runtime.ts +75 -3
- package/src/gjc-runtime/repository-binding.ts +267 -0
- package/src/gjc-runtime/session-state-sidecar.ts +25 -9
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -1
- package/src/gjc-runtime/tmux-sessions.ts +45 -6
- package/src/gjc-runtime/ultragoal-guard.ts +93 -15
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +103 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +456 -31
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +23 -0
- package/src/internal-urls/docs-index.generated.ts +12 -10
- package/src/internal-urls/local-protocol.ts +64 -21
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +111 -37
- package/src/modes/DESIGN.md +5 -0
- package/src/modes/acp/acp-agent.ts +50 -16
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/model-selector.ts +73 -11
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/tool-status-header.ts +25 -4
- package/src/modes/components/welcome.ts +22 -18
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +97 -54
- package/src/modes/controllers/event-controller.ts +10 -0
- package/src/modes/controllers/input-controller.ts +38 -2
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +149 -63
- package/src/modes/interactive-mode.ts +57 -34
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +4 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +5 -3
- package/src/prompts/agents/architect.md +0 -1
- package/src/prompts/agents/critic.md +0 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -4
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/json-rpc.ts +23 -9
- package/src/runtime-mcp/manager.ts +51 -53
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/lifecycle.ts +185 -36
- package/src/sdk/bus/chat-daemon-control.ts +19 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +9 -1
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/index.ts +244 -70
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +68 -20
- package/src/sdk/bus/prompt-reconciliation.ts +239 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/telegram-daemon-contract.ts +18 -3
- package/src/sdk/bus/telegram-daemon-control.ts +147 -35
- package/src/sdk/bus/telegram-daemon.ts +2463 -450
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +1 -1
- package/src/sdk/host/control/operations.ts +1 -1
- package/src/sdk/host/host.ts +2 -6
- package/src/sdk/host/query/handlers.ts +70 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +58 -0
- package/src/sdk/protocol/operation-registry.ts +18 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +31 -5
- package/src/sdk/startup-capability.ts +9 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +292 -154
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/internal/managed-session-scope.ts +1163 -137
- package/src/session/internal/managed-session-storage.ts +397 -234
- package/src/session/internal/native-publish-outcome.ts +266 -0
- package/src/session/session-manager.ts +620 -403
- package/src/session/session-storage.ts +128 -11
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +30 -1
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/gjc-command.ts +2 -2
- package/src/task/index.ts +121 -15
- package/src/task/receipt.ts +3 -0
- package/src/task/types.ts +34 -3
- package/src/tools/ask.ts +199 -89
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +13 -131
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +4 -0
- package/src/tools/read.ts +2 -0
- package/src/tools/render-utils.ts +7 -1
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Handles /mcp subcommands for managing MCP servers.
|
|
5
5
|
*/
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
+
import { resolveMCPOAuthResourceOrigin, resolveMCPOAuthTokenEndpoint } from "@gajae-code/ai";
|
|
7
8
|
import { Spacer, Text } from "@gajae-code/tui";
|
|
8
9
|
import { getMCPConfigPath, getProjectDir } from "@gajae-code/utils";
|
|
9
10
|
import type { SourceMeta } from "../../capability/types";
|
|
@@ -61,6 +62,7 @@ function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string)
|
|
|
61
62
|
*/
|
|
62
63
|
interface OAuthFlowResult {
|
|
63
64
|
credentialId: string;
|
|
65
|
+
tokenEndpoint: string;
|
|
64
66
|
clientId?: string;
|
|
65
67
|
clientSecret?: string;
|
|
66
68
|
}
|
|
@@ -423,6 +425,7 @@ export class MCPCommandController {
|
|
|
423
425
|
try {
|
|
424
426
|
const oauthClientSecret = finalConfig.oauth?.clientSecret ?? "";
|
|
425
427
|
const oauthResult = await this.#handleOAuthFlow(
|
|
428
|
+
finalConfig.url,
|
|
426
429
|
oauth.authorizationUrl,
|
|
427
430
|
oauth.tokenUrl,
|
|
428
431
|
oauth.clientId ?? finalConfig.oauth?.clientId ?? "",
|
|
@@ -439,7 +442,7 @@ export class MCPCommandController {
|
|
|
439
442
|
auth: {
|
|
440
443
|
type: "oauth",
|
|
441
444
|
credentialId: oauthResult.credentialId,
|
|
442
|
-
tokenUrl:
|
|
445
|
+
tokenUrl: oauthResult.tokenEndpoint,
|
|
443
446
|
clientId: persistedClientId,
|
|
444
447
|
clientSecret: persistedClientSecret,
|
|
445
448
|
},
|
|
@@ -480,8 +483,15 @@ export class MCPCommandController {
|
|
|
480
483
|
done();
|
|
481
484
|
this.#handleWizardCancel();
|
|
482
485
|
},
|
|
483
|
-
async (
|
|
484
|
-
|
|
486
|
+
async (
|
|
487
|
+
endpointUrl: string,
|
|
488
|
+
authUrl: string,
|
|
489
|
+
tokenUrl: string,
|
|
490
|
+
clientId: string,
|
|
491
|
+
clientSecret: string,
|
|
492
|
+
scopes: string,
|
|
493
|
+
) => {
|
|
494
|
+
return await this.#handleOAuthFlow(endpointUrl, authUrl, tokenUrl, clientId, clientSecret, scopes);
|
|
485
495
|
},
|
|
486
496
|
async (config: MCPServerConfig) => {
|
|
487
497
|
return await this.#handleTestConnection(config);
|
|
@@ -503,6 +513,7 @@ export class MCPCommandController {
|
|
|
503
513
|
* Handle OAuth authentication flow for MCP server
|
|
504
514
|
*/
|
|
505
515
|
async #handleOAuthFlow(
|
|
516
|
+
endpointUrl: string,
|
|
506
517
|
authUrl: string,
|
|
507
518
|
tokenUrl: string,
|
|
508
519
|
clientId: string,
|
|
@@ -514,11 +525,13 @@ export class MCPCommandController {
|
|
|
514
525
|
): Promise<OAuthFlowResult> {
|
|
515
526
|
const authStorage = this.ctx.session.modelRegistry.authStorage;
|
|
516
527
|
let parsedAuthUrl: URL;
|
|
528
|
+
const resourceOrigin = resolveMCPOAuthResourceOrigin(endpointUrl);
|
|
529
|
+
const tokenEndpoint = resolveMCPOAuthTokenEndpoint(tokenUrl);
|
|
530
|
+
if (!resourceOrigin || !tokenEndpoint) throw new Error("Invalid MCP OAuth configuration.");
|
|
517
531
|
|
|
518
532
|
// Validate OAuth URLs
|
|
519
533
|
try {
|
|
520
534
|
parsedAuthUrl = new URL(authUrl);
|
|
521
|
-
new URL(tokenUrl);
|
|
522
535
|
} catch (_error) {
|
|
523
536
|
throw new Error(
|
|
524
537
|
`Invalid OAuth URLs. Please check:\n Authorization URL: ${authUrl}\n Token URL: ${tokenUrl}`,
|
|
@@ -533,7 +546,7 @@ export class MCPCommandController {
|
|
|
533
546
|
const flow = new MCPOAuthFlow(
|
|
534
547
|
{
|
|
535
548
|
authorizationUrl: authUrl,
|
|
536
|
-
tokenUrl:
|
|
549
|
+
tokenUrl: tokenEndpoint,
|
|
537
550
|
clientId: resolvedClientId,
|
|
538
551
|
clientSecret: resolvedClientSecret,
|
|
539
552
|
scopes: scopes || undefined,
|
|
@@ -618,6 +631,10 @@ export class MCPCommandController {
|
|
|
618
631
|
const oauthCredential: OAuthCredential = {
|
|
619
632
|
type: "oauth",
|
|
620
633
|
...credentials,
|
|
634
|
+
mcpBinding: {
|
|
635
|
+
resourceOrigin,
|
|
636
|
+
tokenEndpoint,
|
|
637
|
+
},
|
|
621
638
|
};
|
|
622
639
|
|
|
623
640
|
// Store under a synthetic provider name
|
|
@@ -625,6 +642,7 @@ export class MCPCommandController {
|
|
|
625
642
|
|
|
626
643
|
return {
|
|
627
644
|
credentialId,
|
|
645
|
+
tokenEndpoint,
|
|
628
646
|
clientId: flow.resolvedClientId,
|
|
629
647
|
clientSecret: flow.registeredClientSecret,
|
|
630
648
|
};
|
|
@@ -1328,6 +1346,10 @@ export class MCPCommandController {
|
|
|
1328
1346
|
this.ctx.showError(`Server "${name}" is disabled. Run /mcp enable ${name} first.`);
|
|
1329
1347
|
return;
|
|
1330
1348
|
}
|
|
1349
|
+
if (found.config.type !== "http" && found.config.type !== "sse") {
|
|
1350
|
+
this.ctx.showError(`Server "${name}" does not use a remote MCP transport.`);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1331
1353
|
|
|
1332
1354
|
const currentAuth = (found.config as MCPServerConfig & { auth?: MCPAuthConfig }).auth;
|
|
1333
1355
|
if (currentAuth?.type === "oauth") {
|
|
@@ -1341,6 +1363,7 @@ export class MCPCommandController {
|
|
|
1341
1363
|
this.#showMessage(["", theme.fg("muted", `Reauthorizing "${name}"...`), ""].join("\n"));
|
|
1342
1364
|
|
|
1343
1365
|
const oauthResult = await this.#handleOAuthFlow(
|
|
1366
|
+
found.config.url,
|
|
1344
1367
|
oauth.authorizationUrl,
|
|
1345
1368
|
oauth.tokenUrl,
|
|
1346
1369
|
oauth.clientId ?? found.config.oauth?.clientId ?? "",
|
|
@@ -1359,7 +1382,7 @@ export class MCPCommandController {
|
|
|
1359
1382
|
auth: {
|
|
1360
1383
|
type: "oauth",
|
|
1361
1384
|
credentialId: oauthResult.credentialId,
|
|
1362
|
-
tokenUrl:
|
|
1385
|
+
tokenUrl: oauthResult.tokenEndpoint,
|
|
1363
1386
|
clientId: persistedClientId,
|
|
1364
1387
|
clientSecret: persistedClientSecret,
|
|
1365
1388
|
},
|
|
@@ -5,7 +5,7 @@ import type { OAuthProvider } from "@gajae-code/ai/utils/oauth/types";
|
|
|
5
5
|
import type { Component, OverlayHandle, SlashCommand } from "@gajae-code/tui";
|
|
6
6
|
import { Input, isPetMode, Loader, Spacer, Text } from "@gajae-code/tui";
|
|
7
7
|
import { getAgentDbPath, getProjectDir, logger, VERSION } from "@gajae-code/utils";
|
|
8
|
-
import {
|
|
8
|
+
import type { AppKeybinding } from "../../config/keybindings";
|
|
9
9
|
import {
|
|
10
10
|
activateModelProfile,
|
|
11
11
|
type MaterializeModelProfileForDeletionResult,
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
import type { NotificationSessionStatus } from "../../sdk/bus/session-control";
|
|
65
65
|
import {
|
|
66
66
|
ensureTelegramDaemonRunningDetailed,
|
|
67
|
-
|
|
67
|
+
resolveTelegramSetupPreflight,
|
|
68
68
|
unregisterNotificationRoot,
|
|
69
69
|
} from "../../sdk/bus/telegram-daemon";
|
|
70
70
|
import { TelegramDaemonController } from "../../sdk/bus/telegram-daemon-control";
|
|
@@ -101,8 +101,10 @@ import {
|
|
|
101
101
|
} from "../../setup/model-onboarding-guidance";
|
|
102
102
|
import { addApiCompatibleProvider, formatProviderSetupResult } from "../../setup/provider-onboarding";
|
|
103
103
|
import {
|
|
104
|
+
IMAGE_PROVIDER_DEFAULTS,
|
|
104
105
|
isConfigurableSearchProviderId,
|
|
105
106
|
isSearchProviderPreference,
|
|
107
|
+
setConfiguredImageModel,
|
|
106
108
|
setPreferredImageProvider,
|
|
107
109
|
setPreferredSearchProvider,
|
|
108
110
|
setSearchFallbackProviders,
|
|
@@ -190,6 +192,7 @@ export function buildStatusLineSettings(settingsInstance: Settings): StatusLineS
|
|
|
190
192
|
rightSegments: settingsInstance.get("statusLine.rightSegments"),
|
|
191
193
|
separator: settingsInstance.get("statusLine.separator"),
|
|
192
194
|
showHookStatus: settingsInstance.get("statusLine.showHookStatus"),
|
|
195
|
+
showActionHints: settingsInstance.get("statusLine.showActionHints"),
|
|
193
196
|
sessionAccent: settingsInstance.get("statusLine.sessionAccent"),
|
|
194
197
|
maxRows: settingsInstance.get("statusLine.maxRows"),
|
|
195
198
|
segmentOptions: settingsInstance.get("statusLine.segmentOptions"),
|
|
@@ -223,6 +226,7 @@ export interface NotificationsEditorOperationDependencies {
|
|
|
223
226
|
sanitizeDiagnostic: typeof sanitizeDiagnostic;
|
|
224
227
|
ensureTelegramDaemonRunningDetailed: typeof ensureTelegramDaemonRunningDetailed;
|
|
225
228
|
runTelegramSetup: typeof runTelegramSetup;
|
|
229
|
+
resolveTelegramSetupPreflight: typeof resolveTelegramSetupPreflight;
|
|
226
230
|
proposedTelegramIdentity: typeof proposedTelegramIdentity;
|
|
227
231
|
reconcileCommittedTelegramConfiguration: typeof reconcileCommittedTelegramConfiguration;
|
|
228
232
|
saveTelegramInactive: typeof saveTelegramInactive;
|
|
@@ -247,6 +251,7 @@ const notificationEditorOperationDependencies: NotificationsEditorOperationDepen
|
|
|
247
251
|
sanitizeDiagnostic,
|
|
248
252
|
ensureTelegramDaemonRunningDetailed,
|
|
249
253
|
runTelegramSetup,
|
|
254
|
+
resolveTelegramSetupPreflight,
|
|
250
255
|
proposedTelegramIdentity,
|
|
251
256
|
reconcileCommittedTelegramConfiguration,
|
|
252
257
|
saveTelegramInactive,
|
|
@@ -303,33 +308,8 @@ export function createNotificationsEditorOperations(
|
|
|
303
308
|
cwd: ctx.sessionManager.getCwd(),
|
|
304
309
|
sessionId: ctx.sessionManager.getSessionId(),
|
|
305
310
|
});
|
|
306
|
-
const telegramSetupPreflight = async (): Promise<TelegramSetupPreflight> =>
|
|
307
|
-
|
|
308
|
-
try {
|
|
309
|
-
const state = await readDaemonState(ctx.settings);
|
|
310
|
-
const validPid = Number.isSafeInteger(state?.pid) && (state?.pid ?? 0) > 0;
|
|
311
|
-
if (!state || !validPid) return { storedChatId };
|
|
312
|
-
let live = false;
|
|
313
|
-
try {
|
|
314
|
-
process.kill(state.pid, 0);
|
|
315
|
-
live = true;
|
|
316
|
-
} catch (error) {
|
|
317
|
-
live = (error as NodeJS.ErrnoException).code === "EPERM";
|
|
318
|
-
}
|
|
319
|
-
return live
|
|
320
|
-
? {
|
|
321
|
-
storedChatId,
|
|
322
|
-
daemon: {
|
|
323
|
-
live,
|
|
324
|
-
tokenFingerprint: typeof state.tokenFingerprint === "string" ? state.tokenFingerprint : undefined,
|
|
325
|
-
chatId: typeof state.chatId === "string" && state.chatId.trim() ? state.chatId.trim() : undefined,
|
|
326
|
-
},
|
|
327
|
-
}
|
|
328
|
-
: { storedChatId };
|
|
329
|
-
} catch {
|
|
330
|
-
return { storedChatId };
|
|
331
|
-
}
|
|
332
|
-
};
|
|
311
|
+
const telegramSetupPreflight = async (): Promise<TelegramSetupPreflight> =>
|
|
312
|
+
await services.resolveTelegramSetupPreflight(ctx.settings);
|
|
333
313
|
|
|
334
314
|
return {
|
|
335
315
|
loadState: async () => {
|
|
@@ -835,7 +815,7 @@ export class SelectorController {
|
|
|
835
815
|
id: `action:${action.id}`,
|
|
836
816
|
label: action.label,
|
|
837
817
|
description: action.id,
|
|
838
|
-
keybinding:
|
|
818
|
+
keybinding: this.ctx.keybindings.getDisplayString(action.id as AppKeybinding) || undefined,
|
|
839
819
|
searchText: action.id,
|
|
840
820
|
handler: action.handler,
|
|
841
821
|
})),
|
|
@@ -1103,6 +1083,75 @@ export class SelectorController {
|
|
|
1103
1083
|
}
|
|
1104
1084
|
}
|
|
1105
1085
|
|
|
1086
|
+
async #handleImageGenerationConfig(): Promise<void> {
|
|
1087
|
+
const provider = await this.ctx.showHookInput(
|
|
1088
|
+
"Image Generation provider (auto, openai, gemini, openrouter, antigravity, alibaba, custom)",
|
|
1089
|
+
"auto",
|
|
1090
|
+
);
|
|
1091
|
+
if (provider === undefined) return;
|
|
1092
|
+
const normalized = provider.trim().toLowerCase();
|
|
1093
|
+
const validProviders = ["auto", "openai", "gemini", "openrouter", "antigravity", "alibaba", "custom"];
|
|
1094
|
+
if (!validProviders.includes(normalized)) {
|
|
1095
|
+
this.ctx.showStatus(`Invalid image provider: ${normalized}. Valid: ${validProviders.join(", ")}`);
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
let model: string | undefined;
|
|
1099
|
+
if (normalized !== "auto" && normalized !== "custom") {
|
|
1100
|
+
const defaultModel = IMAGE_PROVIDER_DEFAULTS[normalized];
|
|
1101
|
+
model = await this.ctx.showHookInput(`Image model for ${normalized} (default: ${defaultModel})`, defaultModel);
|
|
1102
|
+
if (model === undefined) return;
|
|
1103
|
+
model = model.trim() || defaultModel;
|
|
1104
|
+
}
|
|
1105
|
+
let customUrl: string | undefined;
|
|
1106
|
+
let customKey: string | undefined;
|
|
1107
|
+
if (normalized === "custom") {
|
|
1108
|
+
customUrl = await this.ctx.showHookInput("Custom image endpoint base URL");
|
|
1109
|
+
if (!customUrl?.trim()) {
|
|
1110
|
+
this.ctx.showStatus("Custom image endpoint requires a base URL");
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
model = await this.ctx.showHookInput("Custom image model", IMAGE_PROVIDER_DEFAULTS.openai);
|
|
1114
|
+
if (model === undefined) return;
|
|
1115
|
+
model = model.trim() || IMAGE_PROVIDER_DEFAULTS.openai;
|
|
1116
|
+
customKey = await this.ctx.showHookInput("Custom image endpoint API key");
|
|
1117
|
+
}
|
|
1118
|
+
const scope = await this.ctx.showHookInput(
|
|
1119
|
+
"Scope: 'session' (this session only) or 'default' (persist)",
|
|
1120
|
+
"session",
|
|
1121
|
+
);
|
|
1122
|
+
if (scope === undefined) return;
|
|
1123
|
+
const persistDefault = scope.trim().toLowerCase() === "default";
|
|
1124
|
+
|
|
1125
|
+
const imageProvider = normalized as
|
|
1126
|
+
| "auto"
|
|
1127
|
+
| "openai"
|
|
1128
|
+
| "gemini"
|
|
1129
|
+
| "openrouter"
|
|
1130
|
+
| "antigravity"
|
|
1131
|
+
| "alibaba"
|
|
1132
|
+
| "custom";
|
|
1133
|
+
setPreferredImageProvider(imageProvider === "custom" ? "auto" : imageProvider);
|
|
1134
|
+
setConfiguredImageModel({
|
|
1135
|
+
provider: imageProvider,
|
|
1136
|
+
model: model ?? null,
|
|
1137
|
+
customUrl: customUrl?.trim(),
|
|
1138
|
+
customKey: customKey?.trim(),
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1141
|
+
if (persistDefault) {
|
|
1142
|
+
this.ctx.settings.set("providers.image", imageProvider);
|
|
1143
|
+
if (model) this.ctx.settings.set("providers.imageModel", model);
|
|
1144
|
+
if (customUrl?.trim()) this.ctx.settings.set("providers.imageCustomUrl", customUrl.trim());
|
|
1145
|
+
if (customKey?.trim()) this.ctx.settings.set("providers.imageCustomKey", customKey.trim());
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
const displayModel =
|
|
1149
|
+
model ?? (normalized !== "auto" && normalized !== "custom" ? IMAGE_PROVIDER_DEFAULTS[normalized] : undefined);
|
|
1150
|
+
const label = normalized === "auto" ? "Auto" : `${normalized}${displayModel ? ` (${displayModel})` : ""}`;
|
|
1151
|
+
this.ctx.showStatus(`Image Generation: ${label}${persistDefault ? " (default)" : " (session)"}`);
|
|
1152
|
+
this.ctx.ui.requestRender();
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1106
1155
|
showCustomProviderWizard(): void {
|
|
1107
1156
|
this.showSelector(done => {
|
|
1108
1157
|
let wizard: CustomProviderWizardComponent;
|
|
@@ -1516,6 +1565,7 @@ export class SelectorController {
|
|
|
1516
1565
|
case "statusLine.separator":
|
|
1517
1566
|
case "statusLineShowHooks":
|
|
1518
1567
|
case "statusLine.showHookStatus":
|
|
1568
|
+
case "statusLine.showActionHints":
|
|
1519
1569
|
case "statusLine.sessionAccent":
|
|
1520
1570
|
case "statusLine.maxRows":
|
|
1521
1571
|
case "statusLine.leftSegments":
|
|
@@ -1563,16 +1613,35 @@ export class SelectorController {
|
|
|
1563
1613
|
}
|
|
1564
1614
|
break;
|
|
1565
1615
|
case "providers.image":
|
|
1616
|
+
case "providers.imageModel":
|
|
1617
|
+
case "providers.imageCustomUrl":
|
|
1618
|
+
case "providers.imageCustomKey":
|
|
1619
|
+
case "providers.imageCustomKeyEnv": {
|
|
1620
|
+
const imgProvider = this.ctx.settings.get("providers.image");
|
|
1621
|
+
const imgModel = this.ctx.settings.get("providers.imageModel");
|
|
1622
|
+
const imgCustomUrl = this.ctx.settings.get("providers.imageCustomUrl");
|
|
1623
|
+
const imgCustomKey = this.ctx.settings.get("providers.imageCustomKey");
|
|
1624
|
+
const imgCustomKeyEnv = this.ctx.settings.get("providers.imageCustomKeyEnv");
|
|
1566
1625
|
if (
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1626
|
+
imgProvider === "auto" ||
|
|
1627
|
+
imgProvider === "openai" ||
|
|
1628
|
+
imgProvider === "gemini" ||
|
|
1629
|
+
imgProvider === "openrouter" ||
|
|
1630
|
+
imgProvider === "antigravity" ||
|
|
1631
|
+
imgProvider === "alibaba" ||
|
|
1632
|
+
imgProvider === "custom"
|
|
1572
1633
|
) {
|
|
1573
|
-
setPreferredImageProvider(
|
|
1634
|
+
setPreferredImageProvider(imgProvider === "custom" ? "auto" : imgProvider);
|
|
1635
|
+
setConfiguredImageModel({
|
|
1636
|
+
provider: imgProvider,
|
|
1637
|
+
model: imgModel ?? null,
|
|
1638
|
+
customUrl: imgCustomUrl,
|
|
1639
|
+
customKey: imgCustomKey,
|
|
1640
|
+
customKeyEnv: imgCustomKeyEnv,
|
|
1641
|
+
});
|
|
1574
1642
|
}
|
|
1575
1643
|
break;
|
|
1644
|
+
}
|
|
1576
1645
|
|
|
1577
1646
|
// MCP update injection - live subscribe/unsubscribe
|
|
1578
1647
|
case "mcp.notifications":
|
|
@@ -1610,6 +1679,14 @@ export class SelectorController {
|
|
|
1610
1679
|
showModelSelector(options?: { temporaryOnly?: boolean }): void {
|
|
1611
1680
|
this.showSelector(done => {
|
|
1612
1681
|
let modelSelector: ModelSelectorComponent;
|
|
1682
|
+
const refreshRoleAssignments = () => {
|
|
1683
|
+
modelSelector.refreshRoleAssignments({
|
|
1684
|
+
currentModel: this.ctx.session.model,
|
|
1685
|
+
currentThinkingLevel: this.ctx.session.thinkingLevel,
|
|
1686
|
+
activeModelProfile:
|
|
1687
|
+
this.ctx.session.getActiveModelProfile?.() ?? this.ctx.settings.get("modelProfile.default"),
|
|
1688
|
+
});
|
|
1689
|
+
};
|
|
1613
1690
|
modelSelector = new ModelSelectorComponent(
|
|
1614
1691
|
this.ctx.ui,
|
|
1615
1692
|
this.ctx.session.model,
|
|
@@ -1617,6 +1694,8 @@ export class SelectorController {
|
|
|
1617
1694
|
this.ctx.session.modelRegistry,
|
|
1618
1695
|
this.ctx.session.scopedModels,
|
|
1619
1696
|
async selection => {
|
|
1697
|
+
const isTrackedSingleAssignment =
|
|
1698
|
+
selection.kind === "assignment" && selection.role !== null && selection.roles === undefined;
|
|
1620
1699
|
try {
|
|
1621
1700
|
if (selection.kind === "createProfile") {
|
|
1622
1701
|
done();
|
|
@@ -1631,6 +1710,11 @@ export class SelectorController {
|
|
|
1631
1710
|
await this.#deleteCustomModelPreset(selection.profileName, modelSelector);
|
|
1632
1711
|
return;
|
|
1633
1712
|
}
|
|
1713
|
+
if (selection.kind === "imageGeneration") {
|
|
1714
|
+
done();
|
|
1715
|
+
await this.#handleImageGenerationConfig();
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1634
1718
|
if (selection.kind === "profile") {
|
|
1635
1719
|
await this.#applyModelProfile(selection.profileName, selection.setDefault);
|
|
1636
1720
|
done();
|
|
@@ -1652,7 +1736,7 @@ export class SelectorController {
|
|
|
1652
1736
|
this.ctx.showStatus(`Temporary model: ${selectedSelector ?? model.id}`);
|
|
1653
1737
|
done();
|
|
1654
1738
|
this.ctx.ui.requestRender();
|
|
1655
|
-
} else if (selection.roles) {
|
|
1739
|
+
} else if (selection.roles !== undefined) {
|
|
1656
1740
|
const targetRoles: readonly GjcModelAssignmentTargetId[] = selection.roles;
|
|
1657
1741
|
const includesDefault = targetRoles.includes("default");
|
|
1658
1742
|
const includesRoleAgent = targetRoles.some(targetRole => targetRole !== "default");
|
|
@@ -1730,25 +1814,23 @@ export class SelectorController {
|
|
|
1730
1814
|
selectedSelector ?? `${model.provider}/${model.id}`,
|
|
1731
1815
|
thinkingLevel,
|
|
1732
1816
|
);
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1817
|
+
if (
|
|
1818
|
+
!materializeActiveModelProfileAssignment({
|
|
1819
|
+
session: this.ctx.session,
|
|
1820
|
+
settings: this.ctx.settings,
|
|
1821
|
+
role,
|
|
1822
|
+
selector: value,
|
|
1823
|
+
})
|
|
1824
|
+
) {
|
|
1825
|
+
this.ctx.settings.setModelRole(role, value);
|
|
1826
|
+
}
|
|
1739
1827
|
if (thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit) {
|
|
1740
1828
|
this.ctx.session.setThinkingLevel(thinkingLevel);
|
|
1741
1829
|
}
|
|
1742
|
-
|
|
1743
|
-
currentModel: this.ctx.session.model,
|
|
1744
|
-
currentThinkingLevel: this.ctx.session.thinkingLevel,
|
|
1745
|
-
activeModelProfile:
|
|
1746
|
-
this.ctx.session.getActiveModelProfile?.() ?? this.ctx.settings.get("modelProfile.default"),
|
|
1747
|
-
});
|
|
1830
|
+
refreshRoleAssignments();
|
|
1748
1831
|
this.ctx.statusLine.invalidate();
|
|
1749
1832
|
this.ctx.updateEditorBorderColor();
|
|
1750
1833
|
this.ctx.showStatus(`Default model: ${selectedSelector ?? model.id}`);
|
|
1751
|
-
done();
|
|
1752
1834
|
this.ctx.ui.requestRender();
|
|
1753
1835
|
} else {
|
|
1754
1836
|
const apiKey = await this.ctx.session.modelRegistry.getApiKey(model, this.ctx.session.sessionId);
|
|
@@ -1771,22 +1853,21 @@ export class SelectorController {
|
|
|
1771
1853
|
this.ctx.settings.setAgentModelOverride(role, value);
|
|
1772
1854
|
}
|
|
1773
1855
|
}
|
|
1774
|
-
|
|
1775
|
-
currentModel: this.ctx.session.model,
|
|
1776
|
-
currentThinkingLevel: this.ctx.session.thinkingLevel,
|
|
1777
|
-
activeModelProfile:
|
|
1778
|
-
this.ctx.session.getActiveModelProfile?.() ?? this.ctx.settings.get("modelProfile.default"),
|
|
1779
|
-
});
|
|
1856
|
+
refreshRoleAssignments();
|
|
1780
1857
|
this.ctx.settings.getStorage()?.recordModelUsage(`${model.provider}/${model.id}`);
|
|
1781
1858
|
this.ctx.statusLine.invalidate();
|
|
1782
1859
|
this.ctx.updateEditorBorderColor();
|
|
1783
1860
|
await this.ctx.notifyConfigChanged?.();
|
|
1784
1861
|
this.ctx.showStatus(`${role} agent model: ${value}`);
|
|
1785
|
-
done();
|
|
1786
1862
|
this.ctx.ui.requestRender();
|
|
1787
1863
|
}
|
|
1788
1864
|
} catch (error) {
|
|
1789
1865
|
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
1866
|
+
if (isTrackedSingleAssignment) {
|
|
1867
|
+
refreshRoleAssignments();
|
|
1868
|
+
this.ctx.ui.requestRender();
|
|
1869
|
+
throw error;
|
|
1870
|
+
}
|
|
1790
1871
|
}
|
|
1791
1872
|
},
|
|
1792
1873
|
() => {
|
|
@@ -2057,10 +2138,7 @@ export class SelectorController {
|
|
|
2057
2138
|
}
|
|
2058
2139
|
|
|
2059
2140
|
async showSessionSelector(): Promise<void> {
|
|
2060
|
-
const sessions = await
|
|
2061
|
-
this.ctx.sessionManager.getCwd(),
|
|
2062
|
-
this.ctx.sessionManager.getSessionDir(),
|
|
2063
|
-
);
|
|
2141
|
+
const sessions = await this.ctx.sessionManager.listForResumePickerReadOnly();
|
|
2064
2142
|
this.showSelector(done => {
|
|
2065
2143
|
const selector = new SessionSelectorComponent(
|
|
2066
2144
|
sessions,
|
|
@@ -2156,8 +2234,16 @@ export class SelectorController {
|
|
|
2156
2234
|
this.#clearTransientSessionUi();
|
|
2157
2235
|
const migrationPolicy =
|
|
2158
2236
|
this.ctx.settings?.get("session.directoryMigration") === "disabled" ? "disabled" : "copy-retain";
|
|
2159
|
-
|
|
2160
|
-
|
|
2237
|
+
let writableSessionPath = sessionPath;
|
|
2238
|
+
if (this.ctx.sessionManager.isManagedDestination()) {
|
|
2239
|
+
const inspection = await SessionManager.inspectSessionTailReadOnly(sessionPath);
|
|
2240
|
+
if (inspection.kind === "error") throw new Error(`Could not inspect selected session: ${inspection.reason}`);
|
|
2241
|
+
writableSessionPath = await this.ctx.sessionManager.prepareManagedCandidateForStrictAdoption(
|
|
2242
|
+
sessionPath,
|
|
2243
|
+
migrationPolicy,
|
|
2244
|
+
inspection.identity,
|
|
2245
|
+
);
|
|
2246
|
+
}
|
|
2161
2247
|
// Switch session via AgentSession (emits hook and tool session events)
|
|
2162
2248
|
if (!(await this.ctx.session.switchSession(writableSessionPath))) return;
|
|
2163
2249
|
const switchingToDifferentSession = previousSessionId !== this.ctx.sessionManager.getSessionId();
|