@gajae-code/coding-agent 0.18.6 → 0.18.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 +318 -1
- package/dist/types/async/job-manager.d.ts +1 -1
- package/dist/types/capability/mcp.d.ts +2 -0
- package/dist/types/capability/skill.d.ts +2 -0
- package/dist/types/capability/types.d.ts +6 -0
- package/dist/types/cli/public-command-errors.d.ts +3 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/config/autorouting-tier-map.d.ts +348 -9
- package/dist/types/config/file-lock.d.ts +1 -0
- package/dist/types/config/model-bindings-applier.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -3
- package/dist/types/config/model-registry.d.ts +4 -9
- package/dist/types/config/settings.d.ts +4 -0
- package/dist/types/config/skill-settings-defaults.d.ts +2 -0
- package/dist/types/cursor-delete-path.d.ts +1 -0
- package/dist/types/cursor-mcp-name.d.ts +8 -0
- package/dist/types/customization/inventory.d.ts +2 -0
- package/dist/types/debug/report-bundle-parent.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
- package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
- package/dist/types/discovery/helpers.d.ts +8 -3
- package/dist/types/export/html/css-color.d.ts +2 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/types.d.ts +7 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
- package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
- package/dist/types/extensibility/skill-management.d.ts +3 -1
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
- package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
- package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +11 -1
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
- package/dist/types/internal-urls/skill-path.d.ts +1 -0
- package/dist/types/lsp/workspace-path.d.ts +1 -0
- package/dist/types/modes/acp/acp-agent.d.ts +7 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
- package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
- package/dist/types/modes/controllers/input-controller.d.ts +9 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
- package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
- package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
- package/dist/types/progress/collect-project-progress.d.ts +38 -0
- package/dist/types/progress/progress-contract.d.ts +154 -0
- package/dist/types/progress/progress-snapshot.d.ts +11 -0
- package/dist/types/progress/project-progress.d.ts +141 -0
- package/dist/types/progress/render-progress.d.ts +28 -0
- package/dist/types/runtime-mcp/elicitation.d.ts +12 -0
- package/dist/types/runtime-mcp/oauth-public-url.d.ts +1 -0
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
- package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
- package/dist/types/runtime-mcp/types.d.ts +6 -0
- package/dist/types/sdk/acp/adapter.d.ts +1 -1
- package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
- package/dist/types/sdk/broker/broker.d.ts +18 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +9 -0
- package/dist/types/sdk/broker/session-index.d.ts +12 -6
- package/dist/types/sdk/broker/task-artifact-owner-validation.d.ts +55 -0
- package/dist/types/sdk/bus/index.d.ts +12 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +3 -2
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +6 -0
- package/dist/types/sdk/host/query/handlers.d.ts +3 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +9 -0
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +8 -0
- package/dist/types/session/agent-session.d.ts +38 -9
- package/dist/types/session/artifacts.d.ts +2 -2
- package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +36 -1
- package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
- package/dist/types/session/internal/task-artifact-owner-access.d.ts +19 -0
- package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +11 -0
- package/dist/types/session/session-manager.d.ts +31 -5
- package/dist/types/session/session-retirement.d.ts +71 -0
- package/dist/types/session/session-storage.d.ts +62 -48
- package/dist/types/session/session-transcript-header.d.ts +2 -0
- package/dist/types/session/task-artifact-owner-codec.d.ts +109 -0
- package/dist/types/session/task-artifact-owner-retirement.d.ts +7 -0
- package/dist/types/session/task-artifact-owner.d.ts +10 -0
- package/dist/types/setup/credential-auto-import.d.ts +1 -1
- package/dist/types/setup/credential-import.d.ts +6 -4
- package/dist/types/skill-state/active-state.d.ts +38 -0
- package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/tools/bash-skill-urls.d.ts +1 -1
- package/dist/types/tools/index.d.ts +3 -0
- package/dist/types/tools/python.d.ts +9 -1
- package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
- package/dist/types/tools/restricted-cwd.d.ts +1 -0
- package/dist/types/tools/todo-write.d.ts +6 -0
- package/dist/types/utils/tools-checksum.d.ts +7 -0
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +21 -0
- package/scripts/resident-memory-bench.ts +174 -20
- package/scripts/verify-managed-empty-stop.ts +28 -0
- package/src/async/job-manager.ts +228 -122
- package/src/capability/index.ts +18 -0
- package/src/capability/mcp.ts +2 -0
- package/src/capability/skill.ts +2 -0
- package/src/capability/types.ts +6 -0
- package/src/cli/auth-broker-cli.ts +1 -1
- package/src/cli/config-cli.ts +8 -18
- package/src/cli/customize-doctor.ts +15 -2
- package/src/cli/public-command-errors.ts +21 -1
- package/src/cli/setup-cli.ts +4 -4
- package/src/cli/skills-cli.ts +5 -0
- package/src/cli-main.ts +7 -8
- package/src/commands/deep-interview.ts +47 -8
- package/src/commands/sdk.ts +140 -29
- package/src/config/autorouting-tier-map.ts +117 -7
- package/src/config/file-lock.ts +307 -68
- package/src/config/mcp-schema.json +4 -0
- package/src/config/model-bindings-applier.ts +20 -0
- package/src/config/model-profile-activation.ts +240 -46
- package/src/config/model-registry.ts +47 -153
- package/src/config/settings.ts +44 -4
- package/src/config/skill-settings-defaults.ts +7 -0
- package/src/coordinator-mcp/policy.ts +3 -2
- package/src/cursor-delete-path.ts +10 -0
- package/src/cursor-mcp-name.ts +15 -0
- package/src/cursor.ts +13 -2
- package/src/customization/inventory.ts +3 -0
- package/src/debug/report-bundle-parent.ts +22 -0
- package/src/debug/report-bundle.ts +3 -0
- package/src/debug/system-info.ts +13 -1
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
- package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
- package/src/defaults/gjc-defaults.test.ts +18 -1
- package/src/defaults/gjc-defaults.ts +3 -0
- package/src/defaults/gjc-skills.generated.ts +58 -36
- package/src/discovery/agents.ts +6 -1
- package/src/discovery/builtin.ts +10 -0
- package/src/discovery/helpers.ts +168 -23
- package/src/discovery/mcp-json.ts +6 -0
- package/src/discovery/ssh.ts +9 -4
- package/src/discovery/substitute-plugin-root.ts +3 -1
- package/src/edit/file-read-cache.ts +1 -1
- package/src/eval/py/executor.ts +380 -120
- package/src/export/html/css-color.ts +9 -0
- package/src/export/html/index.ts +5 -4
- package/src/export/html/template.generated.ts +1 -1
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +7 -0
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +73 -8
- package/src/extensibility/plugins/manager.ts +3 -2
- package/src/extensibility/plugins/marketplace/cache.ts +15 -0
- package/src/extensibility/plugins/marketplace/manager.ts +11 -3
- package/src/extensibility/plugins/plugin-link-path.ts +12 -0
- package/src/extensibility/runtime-skill-discovery.ts +20 -2
- package/src/extensibility/skill-management.ts +6 -2
- package/src/extensibility/skills.ts +6 -1
- package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
- package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
- package/src/gjc-runtime/deep-interview-stage.ts +98 -21
- package/src/gjc-runtime/gc-runtime.ts +206 -8
- package/src/gjc-runtime/launch-worktree.ts +14 -4
- package/src/gjc-runtime/ralplan-runtime.ts +447 -52
- package/src/gjc-runtime/state-argv.ts +2 -0
- package/src/gjc-runtime/state-migrations.ts +91 -29
- package/src/gjc-runtime/state-runtime.ts +3716 -135
- package/src/gjc-runtime/state-writer.ts +83 -8
- package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
- package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
- package/src/gjc-runtime/workflow-manifest.ts +54 -21
- package/src/harness-control-plane/operate.ts +12 -4
- package/src/harness-control-plane/owner.ts +5 -1
- package/src/hashline/parser.ts +48 -9
- package/src/hashline/recovery.ts +13 -4
- package/src/hindsight/config.ts +9 -3
- package/src/internal-urls/docs-index.generated.ts +19 -18
- package/src/internal-urls/skill-path.ts +19 -0
- package/src/internal-urls/skill-protocol.ts +2 -0
- package/src/lsp/edits.ts +6 -0
- package/src/lsp/workspace-path.ts +51 -0
- package/src/main.ts +195 -31
- package/src/modes/acp/acp-agent.ts +163 -7
- package/src/modes/components/custom-editor.ts +14 -0
- package/src/modes/components/customization/customization-dashboard.ts +12 -0
- package/src/modes/components/extensions/extension-dashboard.ts +2 -2
- package/src/modes/components/extensions/state-manager.ts +15 -5
- package/src/modes/components/model-selector.ts +1 -4
- package/src/modes/components/provider-onboarding-selector.ts +1 -1
- package/src/modes/components/status-line/segments.ts +4 -0
- package/src/modes/controllers/event-controller.ts +11 -4
- package/src/modes/controllers/input-controller.ts +74 -29
- package/src/modes/controllers/runtime-mcp-command-controller.ts +8 -3
- package/src/modes/controllers/selector-controller.ts +28 -15
- package/src/modes/interactive-mode.ts +4 -0
- package/src/modes/runtime-init.ts +4 -0
- package/src/modes/utils/abort-message.ts +3 -1
- package/src/modes/utils/interrupt-ownership.ts +12 -0
- package/src/modes/utils/keybinding-matchers.ts +4 -0
- package/src/modes/utils/macos-option-forwarding.ts +80 -0
- package/src/progress/collect-project-progress.ts +153 -0
- package/src/progress/progress-contract.ts +172 -0
- package/src/progress/progress-snapshot.ts +140 -0
- package/src/progress/project-progress.ts +446 -0
- package/src/progress/render-progress.ts +209 -0
- package/src/prompts/system/master-mode.md +1 -0
- package/src/prompts/tools/skill-discovery.md +1 -1
- package/src/runtime-mcp/client.ts +13 -4
- package/src/runtime-mcp/config-writer.ts +10 -6
- package/src/runtime-mcp/config.ts +1 -0
- package/src/runtime-mcp/elicitation.ts +142 -0
- package/src/runtime-mcp/oauth-flow.ts +5 -0
- package/src/runtime-mcp/oauth-public-url.ts +8 -0
- package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
- package/src/runtime-mcp/smithery-registry.ts +22 -3
- package/src/runtime-mcp/transports/http.ts +2 -2
- package/src/runtime-mcp/types.ts +6 -0
- package/src/sdk/acp/adapter.ts +93 -8
- package/src/sdk/broker/broker-exit.ts +52 -23
- package/src/sdk/broker/broker.ts +83 -7
- package/src/sdk/broker/ensure.ts +2 -0
- package/src/sdk/broker/lifecycle.ts +820 -73
- package/src/sdk/broker/session-index.ts +191 -81
- package/src/sdk/broker/task-artifact-owner-validation.ts +259 -0
- package/src/sdk/bus/chat-daemon-cli.ts +38 -1
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +3 -0
- package/src/sdk/bus/index.ts +241 -46
- package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
- package/src/sdk/bus/telegram-daemon.ts +4 -2
- package/src/sdk/cli/session-cli.ts +17 -3
- package/src/sdk/client/client.ts +28 -8
- package/src/sdk/host/host.ts +6 -0
- package/src/sdk/host/query/handlers.ts +9 -1
- package/src/sdk/host/session-runtime.test.ts +2805 -411
- package/src/sdk/host/session-runtime.ts +428 -111
- package/src/sdk/host/surface-policy.ts +1 -0
- package/src/sdk/index.ts +8 -0
- package/src/sdk/lifecycle-session.ts +3 -1
- package/src/sdk/mcp/server.ts +15 -3
- package/src/sdk/prompt-deadline-manager.ts +15 -0
- package/src/sdk/protocol/operation-inventory.generated.json +146 -0
- package/src/sdk/protocol/operation-registry.ts +9 -2
- package/src/sdk/router/session-router.ts +94 -14
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +81 -38
- package/src/session/agent-session.ts +674 -224
- package/src/session/artifacts.ts +174 -70
- package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
- package/src/session/internal/managed-session-scope.ts +3457 -462
- package/src/session/internal/managed-session-storage.ts +482 -61
- package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
- package/src/session/internal/task-artifact-owner-access.ts +245 -0
- package/src/session/internal/task-artifact-owner-transcript.ts +614 -0
- package/src/session/session-manager.ts +939 -133
- package/src/session/session-retirement.ts +714 -0
- package/src/session/session-storage.ts +418 -174
- package/src/session/session-transcript-header.ts +17 -0
- package/src/session/task-artifact-owner-codec.ts +641 -0
- package/src/session/task-artifact-owner-retirement.ts +477 -0
- package/src/session/task-artifact-owner.ts +289 -0
- package/src/setup/credential-auto-import.ts +12 -3
- package/src/setup/credential-import.ts +176 -5
- package/src/setup/paseo/announce.ts +6 -1
- package/src/skill-state/active-state.ts +132 -2
- package/src/slash-commands/builtin-registry.ts +39 -9
- package/src/slash-commands/helpers/progress-report.ts +23 -0
- package/src/stt/setup.ts +3 -5
- package/src/task/commands.ts +3 -1
- package/src/task/executor.ts +4 -0
- package/src/task/index.ts +6 -0
- package/src/tools/ask.ts +205 -6
- package/src/tools/ast-edit.ts +4 -0
- package/src/tools/bash-allowed-prefixes.ts +15 -0
- package/src/tools/bash-skill-urls.ts +56 -3
- package/src/tools/bash.ts +48 -79
- package/src/tools/descriptors.ts +5 -1
- package/src/tools/eval.ts +56 -36
- package/src/tools/image-gen.ts +1 -1
- package/src/tools/index.ts +3 -0
- package/src/tools/python.ts +187 -66
- package/src/tools/recipe/index.ts +9 -0
- package/src/tools/recipe/recipe-guard.ts +19 -0
- package/src/tools/restricted-cwd.ts +10 -0
- package/src/tools/skill-discovery.ts +5 -0
- package/src/tools/skill.ts +28 -1
- package/src/tools/todo-write.ts +10 -1
- package/src/tools/tool-catalog.generated.ts +1 -1
- package/src/tools/write.ts +1 -0
- package/src/utils/tools-checksum.ts +34 -0
- package/src/utils/tools-manager.ts +24 -6
- package/src/web/search/providers/codex.ts +3 -2
|
@@ -38,6 +38,8 @@ import {
|
|
|
38
38
|
} from "@agentclientprotocol/sdk";
|
|
39
39
|
import { getAgentDir, logger, resolveEquivalentPath } from "@gajae-code/utils";
|
|
40
40
|
import packageJson from "../../../package.json" with { type: "json" };
|
|
41
|
+
import { PROJECT_PROGRESS_SNAPSHOT_SCHEMA, type ProjectProgressSnapshot } from "../../progress/progress-contract";
|
|
42
|
+
import { PROGRESS_COMMAND_ACP_DESCRIPTION, renderProgressSnapshot } from "../../progress/render-progress";
|
|
41
43
|
import {
|
|
42
44
|
ACP_SESSION_RECONNECT,
|
|
43
45
|
type AcpProviderRegistration,
|
|
@@ -258,6 +260,8 @@ type PendingAttachment = { epoch: number; task: Promise<void> };
|
|
|
258
260
|
|
|
259
261
|
type PromptAdmissionSettlement = { kind: "cancelled" } | { kind: "rejected"; error: AcpSdkAdapterError };
|
|
260
262
|
type PromptAdmissionReservation = {
|
|
263
|
+
/** Held by a model-free builtin (`/progress`) answered locally; no host turn exists to abort. */
|
|
264
|
+
localCommand?: true;
|
|
261
265
|
cancelled?: boolean;
|
|
262
266
|
settlement?: PromptAdmissionSettlement;
|
|
263
267
|
wake: () => void;
|
|
@@ -526,9 +530,12 @@ function pageItems(value: unknown): unknown[] {
|
|
|
526
530
|
return Array.isArray(page?.items) ? page.items : [];
|
|
527
531
|
}
|
|
528
532
|
|
|
533
|
+
/** Builtin `/progress`: answered locally from the read-only `session.progress` SDK query, never a model turn. */
|
|
534
|
+
const ACP_PROGRESS_COMMAND: AvailableCommand = { name: "progress", description: PROGRESS_COMMAND_ACP_DESCRIPTION };
|
|
535
|
+
|
|
529
536
|
/** Build the ACP command palette from the shared builtins and live SDK skill state. */
|
|
530
537
|
export function acpAvailableCommandsFromSkills(query: unknown): AvailableCommand[] {
|
|
531
|
-
const commands = new Map<string, AvailableCommand>();
|
|
538
|
+
const commands = new Map<string, AvailableCommand>([[ACP_PROGRESS_COMMAND.name, ACP_PROGRESS_COMMAND]]);
|
|
532
539
|
for (const item of pageItems(query)) {
|
|
533
540
|
const skill = object(item);
|
|
534
541
|
if (typeof skill?.name !== "string" || !skill.name) continue;
|
|
@@ -1426,6 +1433,21 @@ const THINKING_CONFIG_OPTIONS = ["off", "minimal", "low", "medium", "high", "xhi
|
|
|
1426
1433
|
name: value,
|
|
1427
1434
|
}));
|
|
1428
1435
|
|
|
1436
|
+
function thinkingConfigOptions(query: unknown, currentModel: string | undefined): { value: string; name: string }[] {
|
|
1437
|
+
if (!currentModel) return THINKING_CONFIG_OPTIONS;
|
|
1438
|
+
const separator = currentModel.indexOf("/");
|
|
1439
|
+
if (separator <= 0 || separator === currentModel.length - 1) return THINKING_CONFIG_OPTIONS;
|
|
1440
|
+
const provider = currentModel.slice(0, separator);
|
|
1441
|
+
const id = currentModel.slice(separator + 1);
|
|
1442
|
+
const model = pageItems(query)
|
|
1443
|
+
.map(item => object(item))
|
|
1444
|
+
.find(item => item?.provider === provider && item.id === id);
|
|
1445
|
+
const validLevels = object(model?.thinking)?.validLevels;
|
|
1446
|
+
if (!Array.isArray(validLevels) || validLevels.length === 0) return THINKING_CONFIG_OPTIONS;
|
|
1447
|
+
const levels = validLevels.filter((value): value is string => typeof value === "string");
|
|
1448
|
+
return levels.length === 0 ? THINKING_CONFIG_OPTIONS : levels.map(value => ({ value, name: value }));
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1429
1451
|
/** Maps live canonical SDK config and the selected model catalog into the ACP 1.2.1 session state surface. */
|
|
1430
1452
|
export function acpSessionStateFromConfig(
|
|
1431
1453
|
query: unknown,
|
|
@@ -1436,6 +1458,7 @@ export function acpSessionStateFromConfig(
|
|
|
1436
1458
|
const values = configValues(query);
|
|
1437
1459
|
const useModelPresets = modelPreset !== undefined;
|
|
1438
1460
|
const currentModeId = values.get(MODE_CONFIG_ID) === ACP_PLAN_MODE_ID ? ACP_PLAN_MODE_ID : ACP_DEFAULT_MODE_ID;
|
|
1461
|
+
const thinkingOptions = thinkingConfigOptions(modelCatalogQuery, values.get(MODEL_CONFIG_ID));
|
|
1439
1462
|
return {
|
|
1440
1463
|
configOptions: [
|
|
1441
1464
|
{
|
|
@@ -1461,7 +1484,7 @@ export function acpSessionStateFromConfig(
|
|
|
1461
1484
|
? modelPresetConfigOptions(modelCatalogQuery, value)
|
|
1462
1485
|
: modelConfigOptions(modelCatalogQuery, value, activeProviders)
|
|
1463
1486
|
: option.id === THINKING_CONFIG_ID
|
|
1464
|
-
?
|
|
1487
|
+
? thinkingOptions
|
|
1465
1488
|
: [...option.options];
|
|
1466
1489
|
return [
|
|
1467
1490
|
{
|
|
@@ -1492,6 +1515,22 @@ export function acpSkillInvocation(blocks: PromptRequest["prompt"]): { name: str
|
|
|
1492
1515
|
return { name: match[1], args: match[2]?.trim() ?? "" };
|
|
1493
1516
|
}
|
|
1494
1517
|
|
|
1518
|
+
/**
|
|
1519
|
+
* Recognize the builtin `/progress` command only when it is the complete, single text
|
|
1520
|
+
* prompt. Like the TUI (`allowArgs: false`), `/progress <args>` is not the command.
|
|
1521
|
+
*/
|
|
1522
|
+
export function isAcpProgressCommand(blocks: PromptRequest["prompt"]): boolean {
|
|
1523
|
+
return blocks.length === 1 && blocks[0]?.type === "text" && blocks[0].text.trim() === "/progress";
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
/** Render the `session.progress` query result as the plain-text `/progress` view. */
|
|
1527
|
+
export function acpProgressReportText(query: unknown): string {
|
|
1528
|
+
const snapshot = object(pageItems(query)[0]);
|
|
1529
|
+
if (snapshot?.schema !== PROJECT_PROGRESS_SNAPSHOT_SCHEMA)
|
|
1530
|
+
throw new AcpSdkAdapterError("unavailable", "SDK session.progress response omitted the progress snapshot.");
|
|
1531
|
+
return renderProgressSnapshot(snapshot as unknown as ProjectProgressSnapshot).join("\n");
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1495
1534
|
/** Convert every ACP prompt block the agent advertises without silently discarding context. */
|
|
1496
1535
|
export function acpPromptPayload(blocks: PromptRequest["prompt"]): {
|
|
1497
1536
|
text: string;
|
|
@@ -1798,11 +1837,13 @@ export class AcpAgent implements Agent {
|
|
|
1798
1837
|
if (adapter) adapter.acceptFrame(acpFrame);
|
|
1799
1838
|
else this.#pendingRouterFrames.get(attachment.sessionId)?.push(acpFrame);
|
|
1800
1839
|
},
|
|
1801
|
-
onSessionRemoved: attachment => {
|
|
1840
|
+
onSessionRemoved: (attachment, removalReason) => {
|
|
1802
1841
|
const adapter =
|
|
1803
1842
|
this.#sessions.get(attachment.sessionId)?.adapter ??
|
|
1804
1843
|
this.#pendingRouterAdapters.get(attachment.sessionId);
|
|
1805
1844
|
adapter?.revokeAttachment(attachment);
|
|
1845
|
+
if (adapter && removalReason !== "replaced_same_generation")
|
|
1846
|
+
this.#settlePromptAfterHostClose(attachment.sessionId, removalReason ?? "host_exit");
|
|
1806
1847
|
},
|
|
1807
1848
|
},
|
|
1808
1849
|
});
|
|
@@ -2158,7 +2199,22 @@ export class AcpAgent implements Agent {
|
|
|
2158
2199
|
}
|
|
2159
2200
|
break;
|
|
2160
2201
|
case THINKING_CONFIG_ID:
|
|
2161
|
-
|
|
2202
|
+
{
|
|
2203
|
+
const before = await this.#sessionState(params.sessionId);
|
|
2204
|
+
const thinkingOption = before.configOptions?.find(option => option.id === THINKING_CONFIG_ID);
|
|
2205
|
+
if (
|
|
2206
|
+
thinkingOption?.type !== "select" ||
|
|
2207
|
+
!thinkingOption.options.some(option => "value" in option && option.value === params.value)
|
|
2208
|
+
)
|
|
2209
|
+
throw new Error(`Unsupported thinking level: ${params.value}`);
|
|
2210
|
+
await this.#adapter(params.sessionId).control("thinking.set", { level: params.value });
|
|
2211
|
+
const after = await this.#sessionState(params.sessionId);
|
|
2212
|
+
const currentValue = after.configOptions?.find(option => option.id === THINKING_CONFIG_ID)?.currentValue;
|
|
2213
|
+
if (currentValue !== params.value)
|
|
2214
|
+
throw new Error(
|
|
2215
|
+
`Thinking level was not applied: requested ${params.value}, current ${currentValue ?? "unknown"}`,
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2162
2218
|
break;
|
|
2163
2219
|
default: {
|
|
2164
2220
|
const operation = ACP_CONFIG_CONTROL_OPERATIONS[params.configId];
|
|
@@ -2365,6 +2421,38 @@ export class AcpAgent implements Agent {
|
|
|
2365
2421
|
}
|
|
2366
2422
|
}
|
|
2367
2423
|
|
|
2424
|
+
/**
|
|
2425
|
+
* Read-only builtin `/progress`: answered from the session.progress query instead of a
|
|
2426
|
+
* model turn. It owns prompt admission (`pendingPromptAdmission`) from the query until its
|
|
2427
|
+
* response is published, so a concurrent prompt is refused as `conflict` exactly as it is
|
|
2428
|
+
* while a model turn is active. `cancel` and session teardown settle that reservation
|
|
2429
|
+
* through the existing admission paths; this command observes it and stops publishing.
|
|
2430
|
+
*/
|
|
2431
|
+
async #runProgressCommand(sessionId: string, record: SessionRecord): Promise<PromptResponse> {
|
|
2432
|
+
const { promise: woken, resolve: wake } = Promise.withResolvers<void>();
|
|
2433
|
+
const reservation: PromptAdmissionReservation = { localCommand: true, wake, woken };
|
|
2434
|
+
// Replaces a follow-up reservation this prompt already consumed; `#submitPrompt` only
|
|
2435
|
+
// clears the reservation it installed, so ownership stays with this command.
|
|
2436
|
+
record.pendingPromptAdmission = reservation;
|
|
2437
|
+
try {
|
|
2438
|
+
const query = record.adapter.query("session.progress");
|
|
2439
|
+
void query.catch(() => undefined);
|
|
2440
|
+
const result = await Promise.race([query.then(value => ({ value })), woken.then(() => undefined)]);
|
|
2441
|
+
const settlement = reservation.settlement;
|
|
2442
|
+
if (settlement?.kind === "rejected") throw settlement.error;
|
|
2443
|
+
if (settlement?.kind === "cancelled" || reservation.cancelled || !result) return { stopReason: "cancelled" };
|
|
2444
|
+
const text = acpProgressReportText(result.value);
|
|
2445
|
+
await this.#publishSessionUpdate(
|
|
2446
|
+
sessionId,
|
|
2447
|
+
{ sessionId, update: { sessionUpdate: "agent_message_chunk", content: { type: "text", text } } },
|
|
2448
|
+
record.adapter,
|
|
2449
|
+
);
|
|
2450
|
+
return { stopReason: "end_turn" };
|
|
2451
|
+
} finally {
|
|
2452
|
+
if (record.pendingPromptAdmission === reservation) record.pendingPromptAdmission = undefined;
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2368
2456
|
async #waitForPromptSettlement(
|
|
2369
2457
|
waiter: PromptWaiter,
|
|
2370
2458
|
admissionReservation: PromptAdmissionReservation,
|
|
@@ -2449,6 +2537,7 @@ export class AcpAgent implements Agent {
|
|
|
2449
2537
|
);
|
|
2450
2538
|
return { stopReason: "end_turn" };
|
|
2451
2539
|
}
|
|
2540
|
+
if (isAcpProgressCommand(params.prompt)) return await this.#runProgressCommand(params.sessionId, record);
|
|
2452
2541
|
// The SDK transport hard-caps a single request frame at 256 KiB and answers an
|
|
2453
2542
|
// oversize frame by closing the socket (CloseCode::Size, crates/gjc-sdk/src/server.rs),
|
|
2454
2543
|
// which surfaces to the client as an opaque `connection_closed` mid-turn. Reject
|
|
@@ -2936,6 +3025,7 @@ export class AcpAgent implements Agent {
|
|
|
2936
3025
|
// Record the client's intent before awaiting the SDK so a prompt that rejects
|
|
2937
3026
|
// mid-cancel (e.g. preflight `busy`) can still settle as `cancelled`.
|
|
2938
3027
|
record.cancelRequested = true;
|
|
3028
|
+
const localCommand = !record.activePrompt && record.pendingPromptAdmission?.localCommand === true;
|
|
2939
3029
|
this.#settlePendingPromptAdmission(record, { kind: "cancelled" });
|
|
2940
3030
|
// C04 terminal abort: an external client cancel stops the current turn
|
|
2941
3031
|
// (`scope:"turn"`, the default, matching the SDK `turn.abort` default and
|
|
@@ -2943,6 +3033,12 @@ export class AcpAgent implements Agent {
|
|
|
2943
3033
|
// subagents and background tasks stopped opts in with
|
|
2944
3034
|
// `_meta.gjc.abortScope: "owned"` (or `GJC_ACP_ABORT_SCOPE=owned`).
|
|
2945
3035
|
const scope = resolveAcpAbortScope(params._meta, process.env);
|
|
3036
|
+
// The current turn is a model-free builtin answered locally: settling its reservation
|
|
3037
|
+
// above cancels it, and the host has no turn to abort.
|
|
3038
|
+
if (localCommand && scope === "turn") {
|
|
3039
|
+
record.cancelRequested = false;
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
2946
3042
|
const waiter = record.activePrompt;
|
|
2947
3043
|
const waiterWasUnacknowledged = waiter !== undefined && !waiter.acknowledged;
|
|
2948
3044
|
const waiterWasBeforeActivity = waiter !== undefined && !waiter.observedTurnActivity;
|
|
@@ -3018,9 +3114,11 @@ export class AcpAgent implements Agent {
|
|
|
3018
3114
|
// publication is advisory and must never gate the settlement above.
|
|
3019
3115
|
void this.#publishPromptPhaseIdle(params.sessionId, record.adapter);
|
|
3020
3116
|
} else {
|
|
3117
|
+
if (waiter && record.activePrompt === waiter && waiter.terminal && !waiter.settled)
|
|
3118
|
+
this.#settlePrompt(params.sessionId, record, waiter);
|
|
3021
3119
|
// The acknowledgement proves the run was aborted, not that its terminal was
|
|
3022
3120
|
// published. Arm the bounded settlement so the turn cannot outlive the cancel.
|
|
3023
|
-
this.#scheduleCancelSettlement(params.sessionId, record);
|
|
3121
|
+
else this.#scheduleCancelSettlement(params.sessionId, record);
|
|
3024
3122
|
}
|
|
3025
3123
|
waiter?.cancelAttemptResolve?.(true);
|
|
3026
3124
|
} catch (error) {
|
|
@@ -3036,6 +3134,9 @@ export class AcpAgent implements Agent {
|
|
|
3036
3134
|
!waiter.settled
|
|
3037
3135
|
) {
|
|
3038
3136
|
if (waiter.terminalReserved) {
|
|
3137
|
+
await record.frameTail;
|
|
3138
|
+
if (record.activePrompt === waiter && waiter.terminal && !waiter.settled)
|
|
3139
|
+
this.#settlePrompt(params.sessionId, record, waiter);
|
|
3039
3140
|
waiter.cancelAttemptResolve?.(true);
|
|
3040
3141
|
return;
|
|
3041
3142
|
}
|
|
@@ -3091,6 +3192,9 @@ export class AcpAgent implements Agent {
|
|
|
3091
3192
|
waiter.cancelAttempt = undefined;
|
|
3092
3193
|
waiter.cancelAttemptResolve = undefined;
|
|
3093
3194
|
}
|
|
3195
|
+
const cancelWaveSettled = !waiter || waiter.cancelAcknowledged || (waiter.pendingCancelAttempts ?? 0) <= 1;
|
|
3196
|
+
if (cancelWaveSettled && waiter && record.activePrompt === waiter && waiter.terminal && !waiter.settled)
|
|
3197
|
+
this.#settlePrompt(params.sessionId, record, waiter);
|
|
3094
3198
|
throw cancellationError;
|
|
3095
3199
|
} finally {
|
|
3096
3200
|
if (waiter) {
|
|
@@ -4459,6 +4563,37 @@ export class AcpAgent implements Agent {
|
|
|
4459
4563
|
return undefined;
|
|
4460
4564
|
}
|
|
4461
4565
|
|
|
4566
|
+
/** Settles the active prompt when the host explicitly reports that its session closed. */
|
|
4567
|
+
#settlePromptAfterHostClose(id: string, reason: string): void {
|
|
4568
|
+
const record = this.#sessions.get(id);
|
|
4569
|
+
if (!record) return;
|
|
4570
|
+
const waiter = record.activePrompt;
|
|
4571
|
+
if (!waiter || waiter.settled || waiter.terminalReserved) return;
|
|
4572
|
+
if (record.cancelRequested && waiter.cancelAcknowledged) {
|
|
4573
|
+
void this.#settleCancelledPrompt(id, record, waiter);
|
|
4574
|
+
return;
|
|
4575
|
+
}
|
|
4576
|
+
// An accepted mutation without its acknowledgement remains uncertain. Keep the
|
|
4577
|
+
// existing reconciliation path so a host exit never turns an ambiguous prompt
|
|
4578
|
+
// into a retryable failure.
|
|
4579
|
+
if (waiter.dispatched && !waiter.acknowledged) {
|
|
4580
|
+
this.#startUncertainPromptRecovery(id, record, waiter);
|
|
4581
|
+
return;
|
|
4582
|
+
}
|
|
4583
|
+
record.busy = record.backgroundBusy;
|
|
4584
|
+
void this.#rejectPrompt(
|
|
4585
|
+
record,
|
|
4586
|
+
id,
|
|
4587
|
+
waiter,
|
|
4588
|
+
new AcpPromptAbandonedError(
|
|
4589
|
+
"prompt_abandoned",
|
|
4590
|
+
`ACP prompt was abandoned because the SDK session host closed (${reason}). The turn was settled so the ` +
|
|
4591
|
+
`client stops waiting; a new prompt requires a valid or re-established session attachment.`,
|
|
4592
|
+
waiter.planSnapshot,
|
|
4593
|
+
),
|
|
4594
|
+
);
|
|
4595
|
+
}
|
|
4596
|
+
|
|
4462
4597
|
/**
|
|
4463
4598
|
* Settles the ACP prompt only. The agent's own work is left alone: this reports that the
|
|
4464
4599
|
* turn can no longer be observed, it does not cancel or tear down the session.
|
|
@@ -4532,6 +4667,14 @@ export class AcpAgent implements Agent {
|
|
|
4532
4667
|
else logger.warn(`ACP session ${id} dropped an event from a foreign session identity.`);
|
|
4533
4668
|
return;
|
|
4534
4669
|
}
|
|
4670
|
+
if (ingressEvent?.type === "session_closed" || ingressEvent?.type === "session_terminated") {
|
|
4671
|
+
const reason =
|
|
4672
|
+
typeof ingressEvent.reason === "string" && ingressEvent.reason.length > 0
|
|
4673
|
+
? ingressEvent.reason
|
|
4674
|
+
: ingressEvent.type;
|
|
4675
|
+
this.#settlePromptAfterHostClose(id, reason);
|
|
4676
|
+
return;
|
|
4677
|
+
}
|
|
4535
4678
|
if (frame.type !== "hello" && frame.type !== "server_hello" && typeof frame.connectionId === "string")
|
|
4536
4679
|
record.connectionId = frame.connectionId;
|
|
4537
4680
|
// Ingress ordering is recorded before queued work begins.
|
|
@@ -4813,7 +4956,18 @@ export class AcpAgent implements Agent {
|
|
|
4813
4956
|
// Failure diagnostics are useful but advisory. Settle before any mapped
|
|
4814
4957
|
// session update can await a backpressured client transport; otherwise an
|
|
4815
4958
|
// already-decided failure can still lose to the inactivity watchdog.
|
|
4816
|
-
|
|
4959
|
+
// A terminal that races an in-flight cancel must not settle the public prompt before
|
|
4960
|
+
// the cancel request proves its outcome. Otherwise a follow-up prompt can be admitted
|
|
4961
|
+
// between the stale terminal settlement and the abort acknowledgement, leaving the
|
|
4962
|
+
// cancelled background request reported as `end_turn`.
|
|
4963
|
+
const cancelSettlementPending =
|
|
4964
|
+
activePrompt.cancelAttempt !== undefined &&
|
|
4965
|
+
!activePrompt.cancelAcknowledged &&
|
|
4966
|
+
record.statusRecovery !== activePrompt &&
|
|
4967
|
+
!this.#ownsUncertainAbort(record, activePrompt);
|
|
4968
|
+
if (!cancelSettlementPending) {
|
|
4969
|
+
this.#settlePrompt(id, record, activePrompt);
|
|
4970
|
+
}
|
|
4817
4971
|
}
|
|
4818
4972
|
if (!isTerminal && derivedCorrelation === undefined) return;
|
|
4819
4973
|
if (!isTerminal && hasCorrelation(correlation)) {
|
|
@@ -5202,7 +5356,9 @@ export class AcpAgent implements Agent {
|
|
|
5202
5356
|
const { outcome } = waiter.terminal;
|
|
5203
5357
|
this.#rememberSettledPromptCorrelation(id, record, waiter.correlation);
|
|
5204
5358
|
if (outcome.kind === "stopped") {
|
|
5205
|
-
|
|
5359
|
+
// Once the SDK has acknowledged a client cancel, the cancellation owns the
|
|
5360
|
+
// turn even if a stale terminal frame races in with another stopped reason.
|
|
5361
|
+
waiter.resolve({ stopReason: waiter.cancelAcknowledged ? "cancelled" : outcome.reason });
|
|
5206
5362
|
return;
|
|
5207
5363
|
}
|
|
5208
5364
|
// `phase` is the host's own claim, and a host that omits it leaves `terminalOutcome`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Editor, type KeyId, matchesKey, parseKittySequence } from "@gajae-code/tui";
|
|
2
2
|
import { BracketedPasteHandler } from "@gajae-code/tui/bracketed-paste";
|
|
3
3
|
import { type AppKeybinding, KEYBINDINGS } from "../../config/keybindings";
|
|
4
|
+
import { macosOptionChordForComposedText } from "../utils/macos-option-forwarding";
|
|
4
5
|
|
|
5
6
|
type ConfigurableEditorAction = Extract<
|
|
6
7
|
AppKeybinding,
|
|
@@ -116,6 +117,12 @@ export class CustomEditor extends Editor {
|
|
|
116
117
|
onQueue?: () => void;
|
|
117
118
|
/** Called when Caps Lock is pressed. */
|
|
118
119
|
onCapsLock?: () => void;
|
|
120
|
+
/**
|
|
121
|
+
* Called when typed text is what macOS composes for a bound Option chord
|
|
122
|
+
* (for example `œ` for a bound `alt+q`), meaning the terminal sent Option as
|
|
123
|
+
* text. The text is still inserted; the callback only explains the miss.
|
|
124
|
+
*/
|
|
125
|
+
onUnforwardedOptionChord?: (key: KeyId, text: string) => void;
|
|
119
126
|
/** Called when PageUp/PageDown should scroll the transcript viewport instead of prompt history. */
|
|
120
127
|
onViewportPageScroll?: (direction: -1 | 1) => void;
|
|
121
128
|
/** Called before regular composer input should return the transcript viewport to the live bottom. */
|
|
@@ -473,6 +480,13 @@ export class CustomEditor extends Editor {
|
|
|
473
480
|
}
|
|
474
481
|
}
|
|
475
482
|
|
|
483
|
+
if (this.onUnforwardedOptionChord) {
|
|
484
|
+
const optionKey = macosOptionChordForComposedText(data);
|
|
485
|
+
if (optionKey && (this.hasActionKey(optionKey) || this.#customKeyHandlers.has(optionKey))) {
|
|
486
|
+
this.onUnforwardedOptionChord(optionKey, data);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
476
490
|
// Pass to parent for normal handling.
|
|
477
491
|
super.handleInput(data);
|
|
478
492
|
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { Container, matchesKey, type SelectItem, SelectList, Text } from "@gajae-code/tui";
|
|
22
22
|
import { sanitizeText } from "@gajae-code/utils";
|
|
23
|
+
import { resolveGlobalUserSkillLinkTrust } from "../../../config/skill-settings-defaults";
|
|
23
24
|
import { type CustomizationInventory, loadCustomizationInventory } from "../../../customization/inventory";
|
|
24
25
|
import {
|
|
25
26
|
removeHookFile,
|
|
@@ -47,6 +48,7 @@ import { ImportWizard } from "./import-wizard";
|
|
|
47
48
|
/** Minimal settings slice the dashboard reads and writes. */
|
|
48
49
|
export interface CustomizationSettingsSlice {
|
|
49
50
|
get(key: string): unknown;
|
|
51
|
+
getGlobal?(key: string): unknown;
|
|
50
52
|
set?(key: string, value: unknown): void;
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -150,6 +152,16 @@ export class CustomizationDashboard extends Container {
|
|
|
150
152
|
cwd: this.#cwd,
|
|
151
153
|
home: this.#homeDir,
|
|
152
154
|
policy: this.#skillPolicy(),
|
|
155
|
+
allowExternalUserSkillSymlinks: resolveGlobalUserSkillLinkTrust({
|
|
156
|
+
trustUserSkills:
|
|
157
|
+
typeof this.#settings?.getGlobal === "function"
|
|
158
|
+
? (this.#settings.getGlobal("skills.trustUserSkills") as boolean | undefined)
|
|
159
|
+
: undefined,
|
|
160
|
+
enablePiUser:
|
|
161
|
+
typeof this.#settings?.getGlobal === "function"
|
|
162
|
+
? (this.#settings.getGlobal("skills.enablePiUser") as boolean | undefined)
|
|
163
|
+
: undefined,
|
|
164
|
+
}),
|
|
153
165
|
disabledExtensions: this.#getStringArray("disabledExtensions"),
|
|
154
166
|
});
|
|
155
167
|
}
|
|
@@ -59,7 +59,7 @@ export class ExtensionDashboard extends Container {
|
|
|
59
59
|
async #init(): Promise<void> {
|
|
60
60
|
const sm = this.settings ?? (await Settings.init());
|
|
61
61
|
const disabledIds = sm ? ((sm.get("disabledExtensions") as string[]) ?? []) : [];
|
|
62
|
-
this.#state = await createInitialState(this.cwd, disabledIds);
|
|
62
|
+
this.#state = await createInitialState(this.cwd, disabledIds, sm);
|
|
63
63
|
|
|
64
64
|
// Calculate max visible items based on terminal height
|
|
65
65
|
// Reserve ~10 lines for header, tabs, help text, borders
|
|
@@ -193,7 +193,7 @@ export class ExtensionDashboard extends Container {
|
|
|
193
193
|
|
|
194
194
|
const sm = this.settings ?? Settings.instance;
|
|
195
195
|
const disabledIds = sm ? ((sm.get("disabledExtensions") as string[]) ?? []) : [];
|
|
196
|
-
const nextState = await refreshState(this.#state, this.cwd, disabledIds);
|
|
196
|
+
const nextState = await refreshState(this.#state, this.cwd, disabledIds, sm);
|
|
197
197
|
if (refreshToken !== this.#refreshToken) return;
|
|
198
198
|
this.#state = nextState;
|
|
199
199
|
|
|
@@ -14,6 +14,7 @@ import type { Skill } from "../../../capability/skill";
|
|
|
14
14
|
import type { SlashCommand } from "../../../capability/slash-command";
|
|
15
15
|
import type { CustomTool } from "../../../capability/tool";
|
|
16
16
|
import type { SourceMeta } from "../../../capability/types";
|
|
17
|
+
import type { Settings } from "../../../config/settings";
|
|
17
18
|
import {
|
|
18
19
|
disableProvider,
|
|
19
20
|
enableProvider,
|
|
@@ -43,7 +44,11 @@ export interface ExtensionSettingsManager {
|
|
|
43
44
|
/**
|
|
44
45
|
* Load all extensions from all capabilities.
|
|
45
46
|
*/
|
|
46
|
-
export async function loadAllExtensions(
|
|
47
|
+
export async function loadAllExtensions(
|
|
48
|
+
cwd?: string,
|
|
49
|
+
disabledIds?: string[],
|
|
50
|
+
settings?: Settings,
|
|
51
|
+
): Promise<Extension[]> {
|
|
47
52
|
const extensions: Extension[] = [];
|
|
48
53
|
const disabledExtensions = new Set<string>(disabledIds ?? []);
|
|
49
54
|
|
|
@@ -97,7 +102,7 @@ export async function loadAllExtensions(cwd?: string, disabledIds?: string[]): P
|
|
|
97
102
|
}
|
|
98
103
|
}
|
|
99
104
|
|
|
100
|
-
const loadOpts = cwd ? { cwd, includeDisabled: true } : { includeDisabled: true };
|
|
105
|
+
const loadOpts = cwd ? { cwd, includeDisabled: true, settings } : { includeDisabled: true, settings };
|
|
101
106
|
|
|
102
107
|
// Load skills
|
|
103
108
|
try {
|
|
@@ -553,8 +558,12 @@ export function applyDisabledExtensionsToState(state: DashboardState, disabledId
|
|
|
553
558
|
/**
|
|
554
559
|
* Create initial dashboard state.
|
|
555
560
|
*/
|
|
556
|
-
export async function createInitialState(
|
|
557
|
-
|
|
561
|
+
export async function createInitialState(
|
|
562
|
+
cwd?: string,
|
|
563
|
+
disabledIds?: string[],
|
|
564
|
+
settings?: Settings,
|
|
565
|
+
): Promise<DashboardState> {
|
|
566
|
+
const extensions = await loadAllExtensions(cwd, disabledIds, settings);
|
|
558
567
|
const tabs = buildProviderTabs(extensions);
|
|
559
568
|
const tabFiltered = extensions; // "all" tab by default
|
|
560
569
|
const searchFiltered = tabFiltered;
|
|
@@ -592,8 +601,9 @@ export async function refreshState(
|
|
|
592
601
|
state: DashboardState,
|
|
593
602
|
cwd?: string,
|
|
594
603
|
disabledIds?: string[],
|
|
604
|
+
settings?: Settings,
|
|
595
605
|
): Promise<DashboardState> {
|
|
596
|
-
const extensions = await loadAllExtensions(cwd, disabledIds);
|
|
606
|
+
const extensions = await loadAllExtensions(cwd, disabledIds, settings);
|
|
597
607
|
const tabs = buildProviderTabs(extensions);
|
|
598
608
|
|
|
599
609
|
// Get current provider from tabs
|
|
@@ -1369,10 +1369,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
1369
1369
|
}
|
|
1370
1370
|
|
|
1371
1371
|
#getProfileAvailableModels(): Model[] {
|
|
1372
|
-
|
|
1373
|
-
return typeof getAvailableForProfileActivation === "function"
|
|
1374
|
-
? getAvailableForProfileActivation.call(this.#modelRegistry)
|
|
1375
|
-
: this.#modelRegistry.getAvailable();
|
|
1372
|
+
return this.#modelRegistry.getAvailable();
|
|
1376
1373
|
}
|
|
1377
1374
|
|
|
1378
1375
|
#createProfileResolutionRegistry(availableModels: readonly Model[]) {
|
|
@@ -30,7 +30,7 @@ const PROVIDER_ONBOARDING_OPTIONS: ProviderOnboardingOption[] = [
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
label: "Import existing credentials",
|
|
33
|
-
description: "Detect and import Claude Code / Codex CLI logins already on this machine.",
|
|
33
|
+
description: "Detect and import Claude Code / Codex CLI / Kiro CLI logins already on this machine.",
|
|
34
34
|
action: "import-credentials",
|
|
35
35
|
},
|
|
36
36
|
];
|
|
@@ -109,6 +109,10 @@ const modelSegment: StatusLineSegment = {
|
|
|
109
109
|
const modelName = shortenModelId(state.model?.id ?? state.model?.name);
|
|
110
110
|
|
|
111
111
|
let content = withIcon(theme.icon.model, modelName);
|
|
112
|
+
const unavailableProfile = ctx.session.getUnavailableModelProfile?.();
|
|
113
|
+
if (unavailableProfile) {
|
|
114
|
+
content = `${theme.fg("warning", `profile unavailable: ${sanitizeStatusText(unavailableProfile)}`)} ${content}`;
|
|
115
|
+
}
|
|
112
116
|
|
|
113
117
|
if (ctx.session.isFastModeActive() && theme.icon.fast) {
|
|
114
118
|
content += ` ${theme.icon.fast}`;
|
|
@@ -60,6 +60,8 @@ export const __eventControllerPerfCounters = {
|
|
|
60
60
|
const COMPLETION_NOTIFY_COMMAND_TIMEOUT_MS = 10_000;
|
|
61
61
|
const TEXTLESS_LENGTH_WARNING =
|
|
62
62
|
'Response ended with stopReason "length" before producing visible text or a tool call. Check the model\'s output and context token limits (maxTokens in models.yml) or lower the reasoning level (/reasoning), then retry.';
|
|
63
|
+
const TEXTLESS_INCOMPLETE_WARNING =
|
|
64
|
+
"Response ended before producing visible text or a tool call. See the provider diagnostic for the reason.";
|
|
63
65
|
|
|
64
66
|
function isTextlessLengthStop(message: AssistantMessage | undefined): boolean {
|
|
65
67
|
return (
|
|
@@ -1090,7 +1092,7 @@ export class EventController {
|
|
|
1090
1092
|
event.stopReason !== "maintenance" &&
|
|
1091
1093
|
isTextlessLengthStop(lastAssistant)
|
|
1092
1094
|
) {
|
|
1093
|
-
this.ctx.showWarning(TEXTLESS_LENGTH_WARNING);
|
|
1095
|
+
this.ctx.showWarning(lastAssistant?.errorMessage ? TEXTLESS_INCOMPLETE_WARNING : TEXTLESS_LENGTH_WARNING);
|
|
1094
1096
|
}
|
|
1095
1097
|
this.sendCompletionNotification();
|
|
1096
1098
|
this.ctx.promptSuggestion?.onAgentEnd();
|
|
@@ -1372,15 +1374,20 @@ export class EventController {
|
|
|
1372
1374
|
|
|
1373
1375
|
const sessionName = this.ctx.sessionManager.getSessionName();
|
|
1374
1376
|
const textlessLengthStop = isTextlessLengthStop(last);
|
|
1377
|
+
const incompleteTitle = last?.errorMessage ? "Response incomplete" : "Output limit reached";
|
|
1375
1378
|
const title = textlessLengthStop
|
|
1376
1379
|
? sessionName
|
|
1377
|
-
? `${sessionName}:
|
|
1378
|
-
:
|
|
1380
|
+
? `${sessionName}: ${incompleteTitle}`
|
|
1381
|
+
: incompleteTitle
|
|
1379
1382
|
: sessionName
|
|
1380
1383
|
? `${sessionName}: Complete`
|
|
1381
1384
|
: "Complete";
|
|
1382
1385
|
const summary = summaryFromMessage(last, 1000);
|
|
1383
|
-
const body = textlessLengthStop
|
|
1386
|
+
const body = textlessLengthStop
|
|
1387
|
+
? last?.errorMessage
|
|
1388
|
+
? TEXTLESS_INCOMPLETE_WARNING
|
|
1389
|
+
: TEXTLESS_LENGTH_WARNING
|
|
1390
|
+
: (summary ?? "Complete");
|
|
1384
1391
|
const sessionManager = this.ctx.sessionManager as { getCwd?: () => string; getSessionId?: () => string };
|
|
1385
1392
|
const payload: CompletionNotifyPayload = {
|
|
1386
1393
|
type: "agent-turn-complete",
|