@gajae-code/coding-agent 0.18.10 → 0.18.12
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 +295 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +1 -0
- package/dist/types/cli/update-cli.d.ts +14 -1
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +5 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/config/autorouting-tier-map.d.ts +30 -0
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +39 -0
- package/dist/types/config/file-lock.d.ts +8 -1
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -6
- package/dist/types/config/model-registry.d.ts +56 -5
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +46 -3
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/modes/patch.d.ts +5 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +10 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/types.d.ts +15 -3
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +2 -2
- package/dist/types/sdk/broker/broker.d.ts +7 -1
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +136 -7
- package/dist/types/sdk/broker/hop.d.ts +36 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +4 -1
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +23 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/session-runtime.d.ts +32 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +58 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +13 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +7 -3
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/bash-allowed-prefixes.d.ts +11 -0
- package/dist/types/tools/descriptors.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +8 -8
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +22 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +27 -19
- package/src/capability/index.ts +2 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +7 -5
- package/src/cli/public-command-errors.ts +4 -0
- package/src/cli/root-flags.ts +2 -2
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +224 -7
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +199 -42
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/message.ts +10 -3
- package/src/config/autorouting-tier-map.ts +30 -0
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +734 -0
- package/src/config/file-lock.ts +216 -56
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +716 -113
- package/src/config/model-registry.ts +1334 -158
- package/src/config/model-resolver.ts +3 -1
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +60 -3
- package/src/config/settings.ts +458 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/crash/sanitize.ts +4 -0
- package/src/customization/import.ts +3 -1
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/debug/crash-diagnostics.ts +2 -1
- package/src/debug/report-bundle.ts +19 -0
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/helpers.ts +1 -2
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +13 -17
- package/src/edit/modes/patch.ts +187 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/export/html/index.ts +46 -6
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +8 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/gjc-runtime/gc-runtime.ts +33 -6
- package/src/gjc-runtime/launch-tmux.ts +7 -2
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/hooks/native-skill-hook.ts +14 -11
- package/src/internal-urls/docs-index.generated.ts +14 -13
- package/src/internal-urls/local-protocol.ts +142 -8
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/migrate/action-planner.ts +57 -0
- package/src/migrate/adapters/claude-code.ts +23 -4
- package/src/migrate/adapters/codex.ts +22 -4
- package/src/migrate/adapters/index.ts +22 -4
- package/src/migrate/adapters/opencode.ts +6 -1
- package/src/migrate/executor.ts +84 -7
- package/src/migrate/report.ts +19 -2
- package/src/migrate/types.ts +14 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/controllers/command-controller.ts +38 -2
- package/src/modes/controllers/plan-mode-controller.ts +17 -7
- package/src/modes/controllers/selector-controller.ts +62 -6
- package/src/modes/interactive-mode.ts +68 -0
- package/src/modes/theme/theme.ts +15 -0
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +32 -0
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +126 -17
- package/src/sdk/broker/broker-exit.ts +8 -5
- package/src/sdk/broker/broker.ts +342 -82
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1143 -265
- package/src/sdk/broker/hop.ts +274 -0
- package/src/sdk/broker/lifecycle-ledger.ts +35 -11
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +62 -12
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/index.ts +52 -21
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
- package/src/sdk/cli/session-cli.ts +21 -6
- package/src/sdk/host/session-runtime.test.ts +118 -23
- package/src/sdk/host/session-runtime.ts +352 -47
- package/src/sdk/lifecycle/service.ts +1 -0
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/protocol/adapter-validation.ts +53 -11
- package/src/sdk/protocol/operation-inventory.generated.json +101 -2
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +114 -61
- package/src/session/agent-session.ts +1043 -81
- package/src/session/internal/managed-session-scope.ts +126 -39
- package/src/session/internal/managed-session-storage.ts +14 -11
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +236 -14
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +491 -32
- package/src/slash-commands/builtin-registry.ts +15 -3
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/task/executor.ts +103 -12
- package/src/task/index.ts +389 -175
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +3 -0
- package/src/tools/bash-allowed-prefixes.ts +153 -5
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash.ts +14 -0
- package/src/tools/debug.ts +7 -6
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +34 -2
- package/src/tools/fetch.ts +3 -2
- package/src/tools/index.ts +2 -0
- package/src/tools/output-meta.ts +23 -2
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +17 -35
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +108 -1
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +31 -3
- package/src/tools/write.ts +35 -3
- package/src/utils/commit-message-generator.ts +9 -2
- package/src/utils/file-mentions.ts +29 -1
- package/src/utils/title-generator.ts +7 -2
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
|
@@ -504,8 +504,12 @@ export interface ReconcileResult {
|
|
|
504
504
|
readonly record?: ActivationRecordV1;
|
|
505
505
|
readonly recordIdentity?: FileIdentity;
|
|
506
506
|
readonly reason?: string;
|
|
507
|
-
/** Present only for a pre-mutation Windows
|
|
507
|
+
/** Present only for a pre-mutation Windows exact-replacement failure. */
|
|
508
508
|
readonly windowsErrorCode?: string;
|
|
509
|
+
readonly detachedPath?: string;
|
|
510
|
+
readonly retainedSuccessorPath?: string;
|
|
511
|
+
readonly retainedPlaceholderPath?: string;
|
|
512
|
+
readonly retainedUnknownPath?: string;
|
|
509
513
|
}
|
|
510
514
|
|
|
511
515
|
/**
|
|
@@ -519,9 +523,11 @@ export interface ReconcileResult {
|
|
|
519
523
|
* records are re-verified and advanced to `verified` once the target
|
|
520
524
|
* digest/identity matches the candidate. `verified` records are read-only
|
|
521
525
|
* re-confirmations. Anything else (target/parent drift, missing staged
|
|
522
|
-
* candidate, an already-occupied backup name
|
|
523
|
-
*
|
|
524
|
-
*
|
|
526
|
+
* candidate, an already-occupied backup name) is reported as `conflict` with
|
|
527
|
+
* the exact reason and never silently promoted. A pre-mutation Windows
|
|
528
|
+
* sharing violation becomes `pending_activation`; an access-denied result is
|
|
529
|
+
* also recorded as pending for safe reuse but remains a `conflict` so the
|
|
530
|
+
* caller reports the publication failure.
|
|
525
531
|
*/
|
|
526
532
|
export async function reconcileActivationRecord(
|
|
527
533
|
targetPath: string,
|
|
@@ -637,11 +643,48 @@ export async function reconcileActivationRecord(
|
|
|
637
643
|
};
|
|
638
644
|
}
|
|
639
645
|
}
|
|
646
|
+
if (
|
|
647
|
+
record.targetIdentity &&
|
|
648
|
+
record.stagingIdentity &&
|
|
649
|
+
result.code === "access_denied" &&
|
|
650
|
+
(process.platform === "win32" || result.windowsErrorCode === "0xC0000022") &&
|
|
651
|
+
!result.detachedPath &&
|
|
652
|
+
!result.retainedSuccessorPath &&
|
|
653
|
+
!result.retainedUnknownPath &&
|
|
654
|
+
!result.retainedPlaceholderPath
|
|
655
|
+
) {
|
|
656
|
+
const unchangedTarget = await snapshotRegularFile(targetPath);
|
|
657
|
+
const unchangedStaging = await snapshotRegularFile(record.stagingPath);
|
|
658
|
+
if (
|
|
659
|
+
unchangedTarget &&
|
|
660
|
+
unchangedStaging &&
|
|
661
|
+
sameFileIdentity(record.targetIdentity, unchangedTarget.identity) &&
|
|
662
|
+
sameFileIdentity(record.stagingIdentity, unchangedStaging.identity)
|
|
663
|
+
) {
|
|
664
|
+
const pending: ActivationRecordV1 = { ...record, phase: "pending_activation" };
|
|
665
|
+
const pendingIdentity = await updateActivationRecordFile(pending, recordIdentity);
|
|
666
|
+
return {
|
|
667
|
+
status: "conflict",
|
|
668
|
+
record: pending,
|
|
669
|
+
recordIdentity: pendingIdentity,
|
|
670
|
+
reason: "access_denied",
|
|
671
|
+
...(result.windowsErrorCode ? { windowsErrorCode: result.windowsErrorCode } : {}),
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
}
|
|
640
675
|
return {
|
|
641
676
|
status: "conflict",
|
|
642
677
|
record,
|
|
643
678
|
reason: result.code ?? "activation_promotion_failed",
|
|
644
679
|
...(result.windowsErrorCode ? { windowsErrorCode: result.windowsErrorCode } : {}),
|
|
680
|
+
...(result.detachedPath !== undefined ? { detachedPath: result.detachedPath } : {}),
|
|
681
|
+
...(result.retainedSuccessorPath !== undefined
|
|
682
|
+
? { retainedSuccessorPath: result.retainedSuccessorPath }
|
|
683
|
+
: {}),
|
|
684
|
+
...(result.retainedPlaceholderPath !== undefined
|
|
685
|
+
? { retainedPlaceholderPath: result.retainedPlaceholderPath }
|
|
686
|
+
: {}),
|
|
687
|
+
...(result.retainedUnknownPath !== undefined ? { retainedUnknownPath: result.retainedUnknownPath } : {}),
|
|
645
688
|
};
|
|
646
689
|
}
|
|
647
690
|
const promoted = await snapshotRegularFile(targetPath);
|
package/src/cli/migrate-cli.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `gjc migrate` — import MCP servers and
|
|
2
|
+
* `gjc migrate` — import MCP servers, skills, and instruction files from other coding agents.
|
|
3
3
|
*/
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import * as path from "node:path";
|
|
@@ -53,8 +53,10 @@ export function resolveSources(from: string[]): MigrateSource[] {
|
|
|
53
53
|
|
|
54
54
|
function resolveDestinations(project: boolean, cwd: string): MigrateDestinations {
|
|
55
55
|
const scope = project ? "project" : "user";
|
|
56
|
-
const
|
|
57
|
-
|
|
56
|
+
const agentDir = project ? getProjectAgentDir(cwd) : getAgentDir();
|
|
57
|
+
const skillsDir = path.join(agentDir, "skills");
|
|
58
|
+
const instructionsPath = path.join(agentDir, "AGENTS.md");
|
|
59
|
+
return { mcpConfigPath: getMCPConfigPath(scope, cwd), skillsDir, instructionsPath };
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
/** Run the migration and return the report (does not set process.exitCode). */
|
|
@@ -66,11 +68,11 @@ export async function runMigrate(args: MigrateCommandArgs): Promise<MigrateRepor
|
|
|
66
68
|
|
|
67
69
|
const results: AdapterResult[] = [];
|
|
68
70
|
for (const source of sources) {
|
|
69
|
-
results.push(await getAdapter(source).collect({ homeDir }));
|
|
71
|
+
results.push(await getAdapter(source).collect({ homeDir, cwd, scope: args.project ? "project" : "user" }));
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
const { actions, warnings } = await planMigration({ results, destinations, force: args.force });
|
|
73
|
-
const finalActions = args.dryRun ? actions : await executeActions(actions);
|
|
75
|
+
const finalActions = args.dryRun ? actions : await executeActions(actions, { project: args.project });
|
|
74
76
|
|
|
75
77
|
return buildReport({
|
|
76
78
|
actions: finalActions,
|
|
@@ -111,6 +111,10 @@ export const PUBLIC_COMMAND_DIAGNOSTICS = {
|
|
|
111
111
|
// of them and never implies that another key would be safe.
|
|
112
112
|
lifecycle_idempotency_conflict:
|
|
113
113
|
"The broker reported an idempotency conflict. Reconcile existing lifecycle state before deciding whether another request is safe.",
|
|
114
|
+
// Refusals of the request payload itself: the broker's own text names the missing field
|
|
115
|
+
// (a required `sessionPath`, for one), and it is never rendered, so the class is named here.
|
|
116
|
+
lifecycle_input_refused:
|
|
117
|
+
"The broker refused the request as invalid input. Correct the request payload and reconcile existing lifecycle state before deciding whether another request is safe.",
|
|
114
118
|
usage_transport_exclusive: "Specify exactly one of --stdio or --socket <path>.",
|
|
115
119
|
usage_duplicate_option: "Each option on this command may occur at most once.",
|
|
116
120
|
usage_unknown_argument: "An unrecognized argument was supplied; re-read the command help for its accepted grammar.",
|
package/src/cli/root-flags.ts
CHANGED
|
@@ -19,11 +19,11 @@ export const ROOT_LAUNCH_FLAGS = {
|
|
|
19
19
|
"api-key": Flags.string({ description: "API key (defaults to env vars)" }),
|
|
20
20
|
credential: Flags.string({
|
|
21
21
|
description:
|
|
22
|
-
"Stored credential selector: email:<addr>, id:<n>, account:<id>, project:<id>, or provider/email:<addr>",
|
|
22
|
+
"Stored credential selector: email:<addr>, id:<n>, account:<id>, project:<id>, org:<id|name>, or provider/email:<addr>",
|
|
23
23
|
}),
|
|
24
24
|
"prefer-credential": Flags.string({
|
|
25
25
|
description:
|
|
26
|
-
"Preferred stored credential with quota fallback: email:<addr>, id:<n>, account:<id>, project:<id>, or provider/id:<n>",
|
|
26
|
+
"Preferred stored credential with quota fallback: email:<addr>, id:<n>, account:<id>, project:<id>, org:<id|name>, or provider/id:<n>",
|
|
27
27
|
}),
|
|
28
28
|
"system-prompt": Flags.string({ description: "System prompt (default: coding assistant prompt)" }),
|
|
29
29
|
"append-system-prompt": Flags.string({ description: "Append text or file contents to the system prompt" }),
|
package/src/cli/stats-cli.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles `gjc stats` subcommand for viewing AI usage statistics.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { APP_NAME, formatDuration, formatNumber, formatPercent } from "@gajae-code/utils";
|
|
7
|
+
import { APP_NAME, formatDuration, formatNumber, formatPercent, sanitizeDisplayLine } from "@gajae-code/utils";
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
import { openPath } from "../utils/open";
|
|
10
10
|
|
|
@@ -168,7 +168,7 @@ async function printStatsSummary(): Promise<void> {
|
|
|
168
168
|
console.log(chalk.bold("\nBy Model:"));
|
|
169
169
|
for (const m of byModel.slice(0, 10)) {
|
|
170
170
|
console.log(
|
|
171
|
-
` ${m.model}: ${formatNumber(m.totalRequests)} reqs, ${formatCost(m.totalCost)}, ${formatPercent(m.cacheRate)} cache`,
|
|
171
|
+
` ${sanitizeDisplayLine(m.model)}: ${formatNumber(m.totalRequests)} reqs, ${formatCost(m.totalCost)}, ${formatPercent(m.cacheRate)} cache`,
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -177,7 +177,7 @@ async function printStatsSummary(): Promise<void> {
|
|
|
177
177
|
console.log(chalk.bold("\nBy Agent Role:"));
|
|
178
178
|
for (const agent of byAgent) {
|
|
179
179
|
console.log(
|
|
180
|
-
` ${agent.agent}: ${formatNumber(agent.totalRequests)} reqs, ${formatNumber(agent.totalInputTokens)} input / ${formatNumber(agent.totalOutputTokens)} output, ${formatPercent(agent.cacheRate)} cache, ${formatCost(agent.totalCost)}`,
|
|
180
|
+
` ${sanitizeDisplayLine(agent.agent)}: ${formatNumber(agent.totalRequests)} reqs, ${formatNumber(agent.totalInputTokens)} input / ${formatNumber(agent.totalOutputTokens)} output, ${formatPercent(agent.cacheRate)} cache, ${formatCost(agent.totalCost)}`,
|
|
181
181
|
);
|
|
182
182
|
}
|
|
183
183
|
}
|
|
@@ -185,7 +185,9 @@ async function printStatsSummary(): Promise<void> {
|
|
|
185
185
|
if (byFolder.length > 0) {
|
|
186
186
|
console.log(chalk.bold("\nBy Folder:"));
|
|
187
187
|
for (const f of byFolder.slice(0, 10)) {
|
|
188
|
-
console.log(
|
|
188
|
+
console.log(
|
|
189
|
+
` ${sanitizeDisplayLine(f.folder)}: ${formatNumber(f.totalRequests)} reqs, ${formatCost(f.totalCost)}`,
|
|
190
|
+
);
|
|
189
191
|
}
|
|
190
192
|
}
|
|
191
193
|
|
|
@@ -201,7 +203,9 @@ async function printStatsSummary(): Promise<void> {
|
|
|
201
203
|
console.log(` Provider-side (prefix intact): ${formatNumber(misses.providerSideMisses)}`);
|
|
202
204
|
console.log(` Model switch: ${formatNumber(misses.modelSwitchMisses)}`);
|
|
203
205
|
for (const cause of misses.byCause) {
|
|
204
|
-
const label =
|
|
206
|
+
const label = sanitizeDisplayLine(
|
|
207
|
+
cause.divergedRole ? `${cause.change} (${cause.divergedRole})` : cause.change,
|
|
208
|
+
);
|
|
205
209
|
console.log(` ${label}: ${formatNumber(cause.misses)}`);
|
|
206
210
|
}
|
|
207
211
|
}
|
package/src/cli/update-cli.ts
CHANGED
|
@@ -11,7 +11,7 @@ import * as fs from "node:fs";
|
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import * as path from "node:path";
|
|
13
13
|
import { exactReplaceRetained, exactUnlink } from "@gajae-code/natives";
|
|
14
|
-
import { $which, APP_NAME, isCompiledBinary, isEnoent, redactCrashSecrets, VERSION } from "@gajae-code/utils";
|
|
14
|
+
import { $which, APP_NAME, isCompiledBinary, isEnoent, logger, redactCrashSecrets, VERSION } from "@gajae-code/utils";
|
|
15
15
|
import { $ } from "bun";
|
|
16
16
|
import chalk from "chalk";
|
|
17
17
|
import { acquireFileLock } from "../config/file-lock";
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
createActivationRecordFile,
|
|
39
39
|
type DirectoryIdentity,
|
|
40
40
|
type FileIdentity,
|
|
41
|
+
type ReconcileResult,
|
|
41
42
|
readActivationRecord,
|
|
42
43
|
reconcileActivationRecord,
|
|
43
44
|
sameDirectoryIdentity,
|
|
@@ -108,6 +109,60 @@ export interface BinaryReplacementOptions {
|
|
|
108
109
|
verifyInstalledVersion: (expectedVersion: string) => Promise<InstalledVersionVerification>;
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
function formatRetainedActivationPaths(
|
|
113
|
+
paths:
|
|
114
|
+
| Pick<
|
|
115
|
+
ReconcileResult,
|
|
116
|
+
"detachedPath" | "retainedSuccessorPath" | "retainedPlaceholderPath" | "retainedUnknownPath"
|
|
117
|
+
>
|
|
118
|
+
| undefined,
|
|
119
|
+
): string {
|
|
120
|
+
if (!paths) return "";
|
|
121
|
+
const entries = [
|
|
122
|
+
paths.detachedPath !== undefined ? `detached=${paths.detachedPath}` : undefined,
|
|
123
|
+
paths.retainedSuccessorPath !== undefined ? `successor=${paths.retainedSuccessorPath}` : undefined,
|
|
124
|
+
paths.retainedPlaceholderPath !== undefined ? `placeholder=${paths.retainedPlaceholderPath}` : undefined,
|
|
125
|
+
paths.retainedUnknownPath !== undefined ? `unknown=${paths.retainedUnknownPath}` : undefined,
|
|
126
|
+
].filter((entry): entry is string => entry !== undefined);
|
|
127
|
+
return entries.length > 0 ? `; retained paths: ${entries.join("|")}` : "";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export class InstallationAccessDeniedError extends Error {
|
|
131
|
+
readonly code = "access_denied";
|
|
132
|
+
|
|
133
|
+
constructor(
|
|
134
|
+
readonly targetPath: string,
|
|
135
|
+
readonly windowsErrorCode?: string,
|
|
136
|
+
readonly stagingCleanupWarning?: string,
|
|
137
|
+
readonly retainedPaths?: Pick<
|
|
138
|
+
ReconcileResult,
|
|
139
|
+
"detachedPath" | "retainedSuccessorPath" | "retainedPlaceholderPath" | "retainedUnknownPath"
|
|
140
|
+
>,
|
|
141
|
+
) {
|
|
142
|
+
super(
|
|
143
|
+
`access_denied during exact replacement of ${targetPath}${windowsErrorCode ? ` (${windowsErrorCode})` : ""}${stagingCleanupWarning ? `; ${stagingCleanupWarning}` : ""}${formatRetainedActivationPaths(retainedPaths)}`,
|
|
144
|
+
);
|
|
145
|
+
this.name = "InstallationAccessDeniedError";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export class ActivationRetryCandidateRepointError extends Error {
|
|
150
|
+
readonly reasonCode: string;
|
|
151
|
+
|
|
152
|
+
constructor(
|
|
153
|
+
readonly candidatePath: string,
|
|
154
|
+
cause: unknown,
|
|
155
|
+
) {
|
|
156
|
+
const reasonCode =
|
|
157
|
+
cause instanceof Error && /^[a-z][a-z0-9_]{0,63}$/.test(cause.message)
|
|
158
|
+
? cause.message
|
|
159
|
+
: "activation_record_repoint_failed";
|
|
160
|
+
super(`${reasonCode}; retained retry candidate: ${candidatePath}`, { cause });
|
|
161
|
+
this.name = "ActivationRetryCandidateRepointError";
|
|
162
|
+
this.reasonCode = reasonCode;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
111
166
|
/**
|
|
112
167
|
* Parse update subcommand arguments.
|
|
113
168
|
* Returns undefined if not an update command.
|
|
@@ -782,6 +837,60 @@ export async function recoverWindowsUpdateJournal(journalPath: string): Promise<
|
|
|
782
837
|
throw new Error("legacy_update_journal_requires_manual_review");
|
|
783
838
|
}
|
|
784
839
|
|
|
840
|
+
async function removeExactStagingFile(filePath: string, identity: FileIdentity): Promise<void> {
|
|
841
|
+
const quarantineName = `.${path.basename(filePath)}.cleanup.${randomUUID()}`;
|
|
842
|
+
const removed = exactUnlink(filePath, toNativeIdentity(identity, quarantineName));
|
|
843
|
+
let pathStillExists = false;
|
|
844
|
+
let snapshotFailure: string | undefined;
|
|
845
|
+
try {
|
|
846
|
+
pathStillExists = (await snapshotRegularFile(filePath)) !== undefined;
|
|
847
|
+
} catch (error) {
|
|
848
|
+
snapshotFailure = error instanceof Error ? error.message : String(error);
|
|
849
|
+
}
|
|
850
|
+
const recoveryPaths = [
|
|
851
|
+
removed.detachedPath ? `detached=${removed.detachedPath}` : undefined,
|
|
852
|
+
removed.retainedPlaceholderPath ? `placeholder=${removed.retainedPlaceholderPath}` : undefined,
|
|
853
|
+
removed.retainedUnknownPath ? `unknown=${removed.retainedUnknownPath}` : undefined,
|
|
854
|
+
removed.retainedSuccessorPath ? `successor=${removed.retainedSuccessorPath}` : undefined,
|
|
855
|
+
].filter((value): value is string => value !== undefined);
|
|
856
|
+
if (
|
|
857
|
+
(!removed.ok && removed.code !== "not_found") ||
|
|
858
|
+
pathStillExists ||
|
|
859
|
+
snapshotFailure !== undefined ||
|
|
860
|
+
recoveryPaths.length > 0
|
|
861
|
+
) {
|
|
862
|
+
const reason =
|
|
863
|
+
removed.code ?? (pathStillExists ? "path_still_exists" : snapshotFailure ? "snapshot_failed" : "unverified");
|
|
864
|
+
const details = [
|
|
865
|
+
`path=${filePath}`,
|
|
866
|
+
...recoveryPaths,
|
|
867
|
+
...(snapshotFailure !== undefined ? [`snapshot=${snapshotFailure}`] : []),
|
|
868
|
+
].join("|");
|
|
869
|
+
throw new Error(`activation_retry_staging_cleanup_failed:${reason}:${details}`);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
async function tryRemoveExactStagingFile(filePath: string, identity: FileIdentity): Promise<string | undefined> {
|
|
874
|
+
try {
|
|
875
|
+
await removeExactStagingFile(filePath, identity);
|
|
876
|
+
return undefined;
|
|
877
|
+
} catch (error) {
|
|
878
|
+
return error instanceof Error ? error.message : String(error);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
async function repointActivationRecordToRetryCandidate(
|
|
883
|
+
record: ActivationRecordV1,
|
|
884
|
+
recordIdentity: FileIdentity,
|
|
885
|
+
candidatePath: string,
|
|
886
|
+
): Promise<FileIdentity> {
|
|
887
|
+
try {
|
|
888
|
+
return await updateActivationRecordFile(record, recordIdentity);
|
|
889
|
+
} catch (error) {
|
|
890
|
+
throw new ActivationRetryCandidateRepointError(candidatePath, error);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
785
894
|
/**
|
|
786
895
|
* Atomically replace the installed binary and roll back if version verification fails.
|
|
787
896
|
*/
|
|
@@ -830,6 +939,7 @@ export async function replaceBinaryForUpdate(options: BinaryReplacementOptions):
|
|
|
830
939
|
}
|
|
831
940
|
let record: ActivationRecordV1;
|
|
832
941
|
let recordIdentity: FileIdentity;
|
|
942
|
+
let redundantStage: { readonly path: string; readonly identity: FileIdentity } | undefined;
|
|
833
943
|
if (existing.status === "valid" && existing.record.phase !== "verified" && existing.record.phase !== "rolled_back") {
|
|
834
944
|
if (
|
|
835
945
|
existing.record.candidate.digest !== (options.candidate?.sha256.toLowerCase() ?? staged?.identity.sha256) ||
|
|
@@ -839,8 +949,43 @@ export async function replaceBinaryForUpdate(options: BinaryReplacementOptions):
|
|
|
839
949
|
existing.record.candidate.channel !== options.candidate.channel))
|
|
840
950
|
)
|
|
841
951
|
throw new Error("activation_transaction_requires_reconciliation");
|
|
842
|
-
|
|
843
|
-
|
|
952
|
+
const currentStagingPath = path.resolve(options.tempPath);
|
|
953
|
+
const recordedStagingPath = path.resolve(existing.record.stagingPath);
|
|
954
|
+
if (currentStagingPath !== recordedStagingPath) {
|
|
955
|
+
const retryCandidate = staged ?? (await snapshotRegularFile(currentStagingPath));
|
|
956
|
+
if (retryCandidate && retryCandidate.identity.sha256 !== existing.record.candidate.digest)
|
|
957
|
+
throw new Error("activation_retry_candidate_digest_mismatch");
|
|
958
|
+
const activationNeedsStagedCandidate =
|
|
959
|
+
existing.record.phase === "staged" || existing.record.phase === "pending_activation";
|
|
960
|
+
const recordedStage = activationNeedsStagedCandidate
|
|
961
|
+
? await snapshotRegularFile(recordedStagingPath)
|
|
962
|
+
: undefined;
|
|
963
|
+
const recordedStageIsValid =
|
|
964
|
+
recordedStage &&
|
|
965
|
+
existing.record.stagingIdentity &&
|
|
966
|
+
sameFileIdentity(existing.record.stagingIdentity, recordedStage.identity) &&
|
|
967
|
+
recordedStage.identity.sha256 === existing.record.candidate.digest;
|
|
968
|
+
if (activationNeedsStagedCandidate && !recordedStageIsValid) {
|
|
969
|
+
if (!retryCandidate) throw new Error("activation_retry_candidate_missing");
|
|
970
|
+
record = {
|
|
971
|
+
...existing.record,
|
|
972
|
+
stagingPath: currentStagingPath,
|
|
973
|
+
stagingIdentity: retryCandidate.identity,
|
|
974
|
+
};
|
|
975
|
+
recordIdentity = await repointActivationRecordToRetryCandidate(
|
|
976
|
+
record,
|
|
977
|
+
existing.identity,
|
|
978
|
+
currentStagingPath,
|
|
979
|
+
);
|
|
980
|
+
} else {
|
|
981
|
+
if (retryCandidate) redundantStage = { path: currentStagingPath, identity: retryCandidate.identity };
|
|
982
|
+
record = existing.record;
|
|
983
|
+
recordIdentity = existing.identity;
|
|
984
|
+
}
|
|
985
|
+
} else {
|
|
986
|
+
record = existing.record;
|
|
987
|
+
recordIdentity = existing.identity;
|
|
988
|
+
}
|
|
844
989
|
} else {
|
|
845
990
|
if (!staged) throw new Error("installation_staging_unavailable");
|
|
846
991
|
record = {
|
|
@@ -873,26 +1018,97 @@ export async function replaceBinaryForUpdate(options: BinaryReplacementOptions):
|
|
|
873
1018
|
allowPromotion: true,
|
|
874
1019
|
expectedRecordIdentity: recordIdentity,
|
|
875
1020
|
});
|
|
876
|
-
if (promoted.
|
|
1021
|
+
if (promoted.reason === "candidate_changed" && redundantStage) {
|
|
1022
|
+
logger.warn("Activation staging path changed during reconciliation; leaving it untouched", {
|
|
1023
|
+
changedStagingPath: record.stagingPath,
|
|
1024
|
+
retryCandidatePath: redundantStage.path,
|
|
1025
|
+
});
|
|
1026
|
+
await repointActivationRecordToRetryCandidate(
|
|
1027
|
+
{
|
|
1028
|
+
...record,
|
|
1029
|
+
phase: "pending_activation",
|
|
1030
|
+
stagingPath: redundantStage.path,
|
|
1031
|
+
stagingIdentity: redundantStage.identity,
|
|
1032
|
+
},
|
|
1033
|
+
recordIdentity,
|
|
1034
|
+
redundantStage.path,
|
|
1035
|
+
);
|
|
1036
|
+
throw new Error("installation_pending_activation");
|
|
1037
|
+
}
|
|
1038
|
+
if (promoted.status === "pending_activation") {
|
|
1039
|
+
if (promoted.reason === "candidate_missing" && redundantStage) {
|
|
1040
|
+
await repointActivationRecordToRetryCandidate(
|
|
1041
|
+
{
|
|
1042
|
+
...record,
|
|
1043
|
+
phase: "pending_activation",
|
|
1044
|
+
stagingPath: redundantStage.path,
|
|
1045
|
+
stagingIdentity: redundantStage.identity,
|
|
1046
|
+
},
|
|
1047
|
+
recordIdentity,
|
|
1048
|
+
redundantStage.path,
|
|
1049
|
+
);
|
|
1050
|
+
} else {
|
|
1051
|
+
const stagingCleanupWarning = redundantStage
|
|
1052
|
+
? await tryRemoveExactStagingFile(redundantStage.path, redundantStage.identity)
|
|
1053
|
+
: undefined;
|
|
1054
|
+
if (stagingCleanupWarning)
|
|
1055
|
+
logger.warn("Update staging cleanup failed while activation is pending", {
|
|
1056
|
+
warning: stagingCleanupWarning,
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
throw new Error("installation_pending_activation");
|
|
1060
|
+
}
|
|
877
1061
|
if (
|
|
878
1062
|
(promoted.status !== "reconciled" &&
|
|
879
1063
|
promoted.status !== "applied_unverified" &&
|
|
880
1064
|
promoted.status !== "verified") ||
|
|
881
1065
|
!promoted.record ||
|
|
882
1066
|
!promoted.recordIdentity
|
|
883
|
-
)
|
|
1067
|
+
) {
|
|
1068
|
+
const stagingCleanupWarning = redundantStage
|
|
1069
|
+
? await tryRemoveExactStagingFile(redundantStage.path, redundantStage.identity)
|
|
1070
|
+
: undefined;
|
|
1071
|
+
if (promoted.reason === "access_denied")
|
|
1072
|
+
throw new InstallationAccessDeniedError(targetPath, promoted.windowsErrorCode, stagingCleanupWarning, {
|
|
1073
|
+
detachedPath: promoted.detachedPath,
|
|
1074
|
+
retainedSuccessorPath: promoted.retainedSuccessorPath,
|
|
1075
|
+
retainedPlaceholderPath: promoted.retainedPlaceholderPath,
|
|
1076
|
+
retainedUnknownPath: promoted.retainedUnknownPath,
|
|
1077
|
+
});
|
|
1078
|
+
if (stagingCleanupWarning)
|
|
1079
|
+
logger.warn("Update staging cleanup failed after activation reconciliation failed", {
|
|
1080
|
+
reason: promoted.reason ?? promoted.status,
|
|
1081
|
+
warning: stagingCleanupWarning,
|
|
1082
|
+
});
|
|
884
1083
|
throw new Error(promoted.reason ?? "installation_publication_unverified");
|
|
1084
|
+
}
|
|
885
1085
|
record = promoted.record;
|
|
886
1086
|
recordIdentity = promoted.recordIdentity;
|
|
1087
|
+
const cleanupWarnings: string[] = [];
|
|
887
1088
|
try {
|
|
888
|
-
|
|
1089
|
+
let verification = await options.verifyInstalledVersion(options.expectedVersion);
|
|
889
1090
|
if (!verification.ok) throw new Error(formatVerificationFailure(verification, options.expectedVersion));
|
|
890
1091
|
const after = await snapshotRegularFile(targetPath);
|
|
891
1092
|
if (!after || !record.targetIdentity || !sameFileIdentity(record.targetIdentity, after.identity))
|
|
892
1093
|
throw new Error("installation_postcheck_identity_changed");
|
|
1094
|
+
if (redundantStage) {
|
|
1095
|
+
const cleanupWarning = await tryRemoveExactStagingFile(redundantStage.path, redundantStage.identity);
|
|
1096
|
+
if (cleanupWarning) {
|
|
1097
|
+
cleanupWarnings.push(cleanupWarning);
|
|
1098
|
+
verification = { ...verification, cleanupWarning };
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
893
1101
|
await updateActivationRecordFile({ ...record, phase: "verified" }, recordIdentity);
|
|
894
1102
|
return verification;
|
|
895
1103
|
} catch (primary) {
|
|
1104
|
+
const rollbackCleanupWarning = redundantStage
|
|
1105
|
+
? await tryRemoveExactStagingFile(redundantStage.path, redundantStage.identity)
|
|
1106
|
+
: undefined;
|
|
1107
|
+
if (rollbackCleanupWarning) cleanupWarnings.push(rollbackCleanupWarning);
|
|
1108
|
+
if (cleanupWarnings.length > 0)
|
|
1109
|
+
logger.warn("Update staging cleanup failed before activation rollback", {
|
|
1110
|
+
warning: cleanupWarnings.join("\n"),
|
|
1111
|
+
});
|
|
896
1112
|
try {
|
|
897
1113
|
const after = await snapshotRegularFile(targetPath);
|
|
898
1114
|
if (!after || !record.targetIdentity || !sameFileIdentity(record.targetIdentity, after.identity))
|
|
@@ -1286,7 +1502,8 @@ async function updateViaBinaryAt(
|
|
|
1286
1502
|
beforeReplace: () => console.log(chalk.dim("Installing update...")),
|
|
1287
1503
|
});
|
|
1288
1504
|
|
|
1289
|
-
if (verification.cleanupWarning)
|
|
1505
|
+
if (verification.cleanupWarning)
|
|
1506
|
+
logger.warn("Update staging cleanup failed", { warning: verification.cleanupWarning });
|
|
1290
1507
|
return verification;
|
|
1291
1508
|
}
|
|
1292
1509
|
|
package/src/cli-ordinary.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* This module owns the effectful bootstrap (startup timing, stderr drainer,
|
|
4
4
|
* bash-shell worker protocol) plus the unchanged ordinary routing order:
|
|
5
5
|
* bash-shell workers -> darwin malloc re-exec -> internal smoke -> tmux owner
|
|
6
|
-
* isolation -> managed-owner supervisor/admission/recovery ->
|
|
7
|
-
* stderr drainer -> public family dispatch -> community app -> doctor worker /
|
|
6
|
+
* isolation -> managed-owner supervisor/admission/recovery -> broker hop ->
|
|
7
|
+
* private sdk stderr drainer -> public family dispatch -> community app -> doctor worker /
|
|
8
8
|
* probe / cli -> full registry. `cli.ts` imports it lazily, only after argv has
|
|
9
9
|
* been proven not to be a `sdk diagnostics` observation. */
|
|
10
10
|
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
BASH_SHELL_SUPERVISOR_ARG,
|
|
17
17
|
BASH_SHELL_WORKER_ARG,
|
|
18
18
|
} from "./exec/bash-shell-worker-protocol";
|
|
19
|
+
import { runBrokerHopFromArgv } from "./sdk/broker/hop";
|
|
19
20
|
import { runSdkStderrDrainerFromArgv } from "./sdk/broker/stderr-drainer";
|
|
20
21
|
|
|
21
22
|
export { commands };
|
|
@@ -128,6 +129,10 @@ export async function runOrdinaryCli(argv: string[]): Promise<void> {
|
|
|
128
129
|
return;
|
|
129
130
|
}
|
|
130
131
|
}
|
|
132
|
+
if (argv.length >= 2 && argv[0] === "internal" && argv[1] === "broker-hop") {
|
|
133
|
+
await runBrokerHopFromArgv(argv.slice(2));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
131
136
|
if (argv[0] === "sdk" && argv[1] === "stderr-drain-internal") {
|
|
132
137
|
// Private lifecycle stderr drainer: must stay ahead of the public sdk family
|
|
133
138
|
// dispatcher, which would otherwise reject the private argv as a usage error.
|
package/src/commands/accounts.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "../cli/accounts-cli";
|
|
9
9
|
|
|
10
10
|
export default class Accounts extends Command {
|
|
11
|
-
static description = "List, check, pin, and remove stored OAuth accounts";
|
|
11
|
+
static description = "List, check, pin, prefer, and remove stored OAuth accounts";
|
|
12
12
|
static strict = true;
|
|
13
13
|
|
|
14
14
|
static args = {
|
|
@@ -22,16 +22,18 @@ export default class Accounts extends Command {
|
|
|
22
22
|
required: false,
|
|
23
23
|
}),
|
|
24
24
|
selector: Args.string({
|
|
25
|
-
description:
|
|
25
|
+
description:
|
|
26
|
+
"Account selector (bare email, id:, email:, or account:); prefer takes several in order, each optionally =<max used percent>",
|
|
26
27
|
required: false,
|
|
28
|
+
multiple: true,
|
|
27
29
|
}),
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
static flags = {
|
|
31
33
|
json: Flags.boolean({ description: "Output safe machine-readable JSON" }),
|
|
32
34
|
persistent: Flags.boolean({ description: "Required for persistent pin changes" }),
|
|
33
|
-
clear: Flags.boolean({ description: "Clear the persistent pin" }),
|
|
34
|
-
account: Flags.string({ description: "Logout one account by row id or
|
|
35
|
+
clear: Flags.boolean({ description: "Clear the persistent pin or preferred accounts" }),
|
|
36
|
+
account: Flags.string({ description: "Logout one account by row id, email, or org:<organization id or name>" }),
|
|
35
37
|
all: Flags.boolean({ description: "Logout every OAuth account for the provider" }),
|
|
36
38
|
};
|
|
37
39
|
|
|
@@ -42,7 +44,10 @@ export default class Accounts extends Command {
|
|
|
42
44
|
"gjc accounts check anthropic --json",
|
|
43
45
|
"gjc accounts pin anthropic me@example.com --persistent",
|
|
44
46
|
"gjc accounts pin anthropic id:42 --persistent",
|
|
47
|
+
"gjc accounts pin anthropic 'org:Acme Team' --persistent",
|
|
45
48
|
"gjc accounts pin anthropic --clear --persistent",
|
|
49
|
+
"gjc accounts prefer anthropic cheap@example.com shared@example.com=75",
|
|
50
|
+
"gjc accounts prefer anthropic --clear",
|
|
46
51
|
"gjc accounts logout anthropic --account me@example.com",
|
|
47
52
|
"gjc accounts logout anthropic --all",
|
|
48
53
|
];
|
|
@@ -57,7 +62,7 @@ export default class Accounts extends Command {
|
|
|
57
62
|
const cmd: AccountsCommandArgs = {
|
|
58
63
|
action,
|
|
59
64
|
provider: args.provider,
|
|
60
|
-
selector: args.selector,
|
|
65
|
+
selectors: Array.isArray(args.selector) ? args.selector : args.selector ? [args.selector] : undefined,
|
|
61
66
|
flags: {
|
|
62
67
|
json: flags.json,
|
|
63
68
|
persistent: flags.persistent,
|
package/src/commands/migrate.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Import MCP servers and
|
|
2
|
+
* Import MCP servers, skills, and instructions from other coding agents into GJC.
|
|
3
3
|
*/
|
|
4
4
|
import { Command, Flags } from "@gajae-code/utils/cli";
|
|
5
5
|
import { type MigrateCommandArgs, runMigrateCommand } from "../cli/migrate-cli";
|
|
6
6
|
|
|
7
7
|
export default class Migrate extends Command {
|
|
8
|
-
static description = "Import MCP servers and skills
|
|
8
|
+
static description = "Import MCP servers and skills, plus Claude Code/Codex instructions";
|
|
9
9
|
|
|
10
10
|
static examples = [
|
|
11
11
|
"gjc migrate --from claude-code",
|
|
@@ -25,7 +25,7 @@ export default class Migrate extends Command {
|
|
|
25
25
|
default: false,
|
|
26
26
|
}),
|
|
27
27
|
force: Flags.boolean({
|
|
28
|
-
description: "Overwrite existing skills
|
|
28
|
+
description: "Overwrite existing skills, MCP servers, or instruction files instead of skipping them",
|
|
29
29
|
default: false,
|
|
30
30
|
}),
|
|
31
31
|
"dry-run": Flags.boolean({ description: "Preview the migration without writing anything", default: false }),
|