@gajae-code/coding-agent 0.12.21 → 0.13.0
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 +67 -2
- package/dist/types/cli/args.d.ts +5 -2
- package/dist/types/cli/root-flags.d.ts +246 -0
- package/dist/types/cli.d.ts +11 -19
- package/dist/types/commands/daemon.d.ts +0 -30
- package/dist/types/commands/launch.d.ts +11 -19
- package/dist/types/commands/quick-lane.d.ts +32 -0
- package/dist/types/commands/sdk.d.ts +21 -15
- package/dist/types/config/file-lock-gc.d.ts +2 -0
- package/dist/types/config/model-equivalence.d.ts +20 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -17
- package/dist/types/config/model-profiles.d.ts +10 -0
- package/dist/types/config/model-registry.d.ts +68 -1
- package/dist/types/config/model-resolver.d.ts +15 -4
- package/dist/types/config/models-config-schema.d.ts +7 -2
- package/dist/types/config/provider-selection-policy.d.ts +62 -0
- package/dist/types/config/settings-schema.d.ts +36 -78
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/edit/renderer.d.ts +5 -2
- package/dist/types/edit/streaming.d.ts +13 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -0
- package/dist/types/extensibility/extensions/compact-handler.d.ts +2 -1
- package/dist/types/extensibility/extensions/types.d.ts +3 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +19 -5
- package/dist/types/internal-urls/local-protocol.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +0 -2
- package/dist/types/modes/components/provider-order-context.d.ts +45 -0
- package/dist/types/modes/components/provider-order-editor.d.ts +24 -0
- package/dist/types/modes/components/settings-defs.d.ts +5 -1
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/quick-lane/classify.d.ts +40 -0
- package/dist/types/runtime/stt-settings-setup.d.ts +18 -0
- package/dist/types/sdk/broker/broker.d.ts +56 -2
- package/dist/types/sdk/broker/operation-receipt-ledger.d.ts +25 -0
- package/dist/types/sdk/broker/session-index.d.ts +83 -2
- package/dist/types/sdk/broker/state-version.d.ts +1 -1
- package/dist/types/sdk/bus/notification-service.d.ts +6 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +8 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +26 -0
- package/dist/types/sdk/cli/rows.d.ts +98 -0
- package/dist/types/sdk/cli/session-cli.d.ts +35 -3
- package/dist/types/sdk/elevation/allowlist.d.ts +20 -0
- package/dist/types/sdk/elevation/audit.d.ts +93 -0
- package/dist/types/sdk/elevation/capability.d.ts +3 -0
- package/dist/types/sdk/elevation/digest.d.ts +72 -0
- package/dist/types/sdk/elevation/dispatch-receipt.d.ts +85 -0
- package/dist/types/sdk/elevation/grant-ledger.d.ts +163 -0
- package/dist/types/sdk/elevation/owner.d.ts +48 -0
- package/dist/types/sdk/guides/cache.d.ts +98 -0
- package/dist/types/sdk/guides/catalog.d.ts +156 -0
- package/dist/types/sdk/guides/cli.d.ts +39 -0
- package/dist/types/sdk/guides/manifest.d.ts +66 -0
- package/dist/types/sdk/guides/verify.d.ts +66 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +8 -0
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/query/cursor.d.ts +10 -0
- package/dist/types/sdk/host/query/handlers.d.ts +21 -0
- package/dist/types/sdk/host/session-runtime.d.ts +9 -0
- package/dist/types/sdk/mcp/server.d.ts +2 -2
- package/dist/types/sdk/prompt-status.d.ts +11 -0
- package/dist/types/sdk/session.d.ts +4 -0
- package/dist/types/sdk/transport/index.d.ts +1 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +20 -1
- package/dist/types/session/agent-session.d.ts +32 -18
- package/dist/types/session/blob-store.d.ts +13 -7
- package/dist/types/session/fallback-chain-controller.d.ts +15 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +25 -1
- package/dist/types/session/internal/session-memory-sidecar.d.ts +5 -5
- package/dist/types/session/session-manager.d.ts +139 -10
- package/dist/types/session/session-storage.d.ts +48 -0
- package/dist/types/setup/provider-onboarding.d.ts +7 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +14 -0
- package/dist/types/stt/setup.d.ts +2 -0
- package/dist/types/task/executor.d.ts +10 -2
- package/dist/types/tools/browser/runtime-diagnostics.d.ts +65 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +2 -0
- package/dist/types/tools/browser/tab-worker.d.ts +2 -0
- package/dist/types/tools/browser.d.ts +2 -0
- package/dist/types/tools/image-gen.d.ts +14 -18
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resource-gc.d.ts +2 -0
- package/dist/types/utils/pasted-image-path.d.ts +6 -0
- package/package.json +9 -9
- package/scripts/generate-sdk-operation-inventory.ts +8 -0
- package/scripts/run-test-manifest.ts +61 -21
- package/scripts/verify-gjc-sdk-canonicalization.ts +9 -4
- package/src/cli/args.ts +62 -9
- package/src/cli/completion-cli.ts +1 -0
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/root-flags.ts +100 -0
- package/src/cli/setup-cli.ts +6 -2
- package/src/cli.ts +42 -65
- package/src/commands/acp.ts +1 -1
- package/src/commands/daemon.ts +2 -31
- package/src/commands/gc.ts +1 -1
- package/src/commands/launch.ts +8 -129
- package/src/commands/quick-lane.ts +51 -0
- package/src/commands/sdk.ts +200 -26
- package/src/commands/setup.ts +4 -2
- package/src/config/file-lock-gc.ts +4 -1
- package/src/config/model-equivalence.ts +76 -7
- package/src/config/model-profile-activation.ts +1115 -265
- package/src/config/model-profiles.ts +134 -2
- package/src/config/model-registry.ts +352 -50
- package/src/config/model-resolver.ts +289 -38
- package/src/config/models-config-schema.ts +11 -4
- package/src/config/provider-selection-policy.ts +146 -0
- package/src/config/settings-schema.ts +50 -77
- package/src/config/settings.ts +40 -0
- package/src/coordinator-mcp/server.ts +32 -2
- package/src/edit/renderer.ts +175 -223
- package/src/edit/streaming.ts +108 -1
- package/src/export/html/index.ts +57 -7
- package/src/extensibility/custom-tools/types.ts +2 -0
- package/src/extensibility/extensions/compact-handler.ts +3 -2
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/gjc-runtime/gc-runtime.ts +379 -20
- package/src/gjc-runtime/launch-worktree.ts +5 -1
- package/src/gjc-runtime/team-runtime.ts +59 -2
- package/src/gjc-runtime/tmux-owner-isolation.ts +19 -0
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +16 -1
- package/src/internal-urls/docs-index.generated.ts +17 -13
- package/src/internal-urls/local-protocol.ts +1 -0
- package/src/main.ts +40 -3
- package/src/memories/index.ts +4 -2
- package/src/modes/acp/acp-agent.ts +235 -91
- package/src/modes/components/model-selector.ts +206 -42
- package/src/modes/components/provider-order-context.ts +197 -0
- package/src/modes/components/provider-order-editor.ts +441 -0
- package/src/modes/components/settings-defs.ts +21 -1
- package/src/modes/components/settings-selector.ts +45 -2
- package/src/modes/components/tool-execution.ts +47 -15
- package/src/modes/controllers/command-controller.ts +6 -3
- package/src/modes/controllers/extension-ui-controller.ts +2 -0
- package/src/modes/controllers/input-controller.ts +73 -2
- package/src/modes/controllers/selector-controller.ts +260 -153
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +18 -0
- package/src/prompts/tools/browser.md +1 -0
- package/src/quick-lane/classify.ts +257 -0
- package/src/rlm/index.ts +1 -1
- package/src/runtime/stt-settings-setup.ts +57 -0
- package/src/sdk/acp/adapter.ts +2 -1
- package/src/sdk/broker/broker.ts +780 -12
- package/src/sdk/broker/lifecycle.ts +70 -29
- package/src/sdk/broker/operation-receipt-ledger.ts +144 -0
- package/src/sdk/broker/session-index.ts +463 -48
- package/src/sdk/broker/state-version.ts +13 -9
- package/src/sdk/broker/transport.ts +14 -1
- package/src/sdk/bus/index.ts +34 -13
- package/src/sdk/bus/kind-aware-reconciliation.ts +21 -2
- package/src/sdk/bus/notification-service.ts +47 -1
- package/src/sdk/bus/prompt-reconciliation.ts +22 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
- package/src/sdk/bus/telegram-daemon.ts +54 -3
- package/src/sdk/cli/rows.ts +247 -0
- package/src/sdk/cli/session-cli.ts +930 -79
- package/src/sdk/elevation/allowlist.ts +54 -0
- package/src/sdk/elevation/audit.ts +208 -0
- package/src/sdk/elevation/capability.ts +41 -0
- package/src/sdk/elevation/digest.ts +129 -0
- package/src/sdk/elevation/dispatch-receipt.ts +184 -0
- package/src/sdk/elevation/grant-ledger.ts +1142 -0
- package/src/sdk/elevation/owner.ts +109 -0
- package/src/sdk/guides/cache.ts +363 -0
- package/src/sdk/guides/catalog.ts +554 -0
- package/src/sdk/guides/cli.ts +235 -0
- package/src/sdk/guides/manifest.ts +152 -0
- package/src/sdk/guides/verify.ts +178 -0
- package/src/sdk/host/control/dispatch.ts +49 -1
- package/src/sdk/host/control/index.ts +1 -0
- package/src/sdk/host/control/operations.ts +8 -1
- package/src/sdk/host/query/cursor.ts +47 -3
- package/src/sdk/host/query/handlers.ts +155 -2
- package/src/sdk/host/sdk-surface-parity.test.ts +1 -0
- package/src/sdk/host/session-runtime.test.ts +391 -1
- package/src/sdk/host/session-runtime.ts +308 -73
- package/src/sdk/host/surface-policy.ts +3 -0
- package/src/sdk/host/websocket-transport.ts +7 -1
- package/src/sdk/mcp/server.ts +88 -15
- package/src/sdk/prompt-status.ts +8 -0
- package/src/sdk/protocol/operation-inventory.generated.json +62 -0
- package/src/sdk/protocol/operation-registry.ts +3 -2
- package/src/sdk/session.ts +87 -39
- package/src/sdk/transport/index.ts +1 -0
- package/src/sdk/transport/relay.ts +3 -0
- package/src/sdk/transport/serve-cli.ts +111 -24
- package/src/secrets/obfuscator.ts +92 -12
- package/src/session/agent-session.ts +322 -93
- package/src/session/blob-store.ts +60 -8
- package/src/session/fallback-chain-controller.ts +35 -0
- package/src/session/internal/managed-session-scope.ts +25 -3
- package/src/session/internal/managed-session-storage.ts +574 -73
- package/src/session/internal/session-memory-sidecar.ts +19 -29
- package/src/session/session-manager.ts +2166 -743
- package/src/session/session-storage.ts +715 -48
- package/src/setup/provider-onboarding.ts +19 -3
- package/src/setup/provider-presets.json +3 -1
- package/src/slash-commands/builtin-registry.ts +85 -3
- package/src/stt/downloader.ts +2 -3
- package/src/stt/setup.ts +29 -4
- package/src/task/executor.ts +22 -18
- package/src/task/index.ts +24 -1
- package/src/tools/archive-reader.ts +11 -2
- package/src/tools/browser/runtime-diagnostics.ts +249 -0
- package/src/tools/browser/tab-protocol.ts +4 -0
- package/src/tools/browser/tab-supervisor.ts +5 -0
- package/src/tools/browser/tab-worker.ts +36 -1
- package/src/tools/browser.ts +7 -0
- package/src/tools/image-gen.ts +110 -166
- package/src/tools/index.ts +2 -0
- package/src/tools/read.ts +1 -1
- package/src/tools/resource-gc.ts +6 -1
- package/src/tools/tool-catalog.generated.ts +5 -1
- package/src/utils/pasted-image-path.ts +93 -0
- package/src/web/search/index.ts +3 -3
package/src/commands/sdk.ts
CHANGED
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
writeSessionLifecycleReady,
|
|
25
25
|
} from "../sdk/broker/lifecycle";
|
|
26
26
|
import { processIncarnation } from "../sdk/broker/process-incarnation";
|
|
27
|
+
import { runSdkSessionCli } from "../sdk/cli";
|
|
28
|
+
import { runSdkGuidesCli } from "../sdk/guides/cli";
|
|
27
29
|
import { type CreateLifecycleAgentSessionResult, createLifecycleAgentSession } from "../sdk/lifecycle-session";
|
|
28
30
|
import { listManagedSessionCandidates, resolveManagedSessionScope } from "../sdk/session-directory";
|
|
29
31
|
import {
|
|
@@ -141,25 +143,31 @@ export const SESSION_HOST_FIRST_ATTACH_GRACE_MS = 60 * 60_000;
|
|
|
141
143
|
const SESSION_HOST_ATTACHMENT_POLL_MS = 30_000;
|
|
142
144
|
|
|
143
145
|
/**
|
|
144
|
-
* Resolves once
|
|
145
|
-
* from every client for
|
|
146
|
-
* for
|
|
146
|
+
* Resolves once the host is provably abandoned: either it has been detached
|
|
147
|
+
* from every client for a full idle grace, or nobody has come for it at all
|
|
148
|
+
* for a full first-attach grace.
|
|
147
149
|
*
|
|
148
150
|
* `readAttachedClients` reports the host's own live client/socket subscription
|
|
149
|
-
* count; `undefined` means the SDK endpoint publishes no such evidence
|
|
150
|
-
*
|
|
151
|
-
*
|
|
151
|
+
* count; `undefined` means the SDK endpoint publishes no such evidence — before
|
|
152
|
+
* startup, after teardown, or when every reader itself fails. That ambiguity is
|
|
153
|
+
* never instant detachment: it cannot reap on the poll that first sees it, it
|
|
154
|
+
* can only open a window. Which window depends on what was already observed. A
|
|
155
|
+
* host never seen attached accrues against the first-attach bound. A host that
|
|
156
|
+
* was seen attached and has since lost its evidence is in the *more* suspicious
|
|
157
|
+
* state — a runtime that retracted its registration during teardown looks
|
|
158
|
+
* exactly like this — so it accrues against the detached idle bound, alongside
|
|
159
|
+
* an observed count of zero. Every reachable state therefore carries a finite
|
|
160
|
+
* bound.
|
|
152
161
|
*
|
|
153
162
|
* `readWorkInFlight` reports whether the host is running agent work right now.
|
|
154
|
-
* Work is positive proof
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* after which the window resumes; live work defers the bound, never removes it.
|
|
163
|
+
* Work is positive proof a client did come for this host: a prompt can only
|
|
164
|
+
* arrive over an endpoint a client dialed. Live work therefore restarts both
|
|
165
|
+
* windows, which is what keeps a mid-prompt host alive whether its count reads
|
|
166
|
+
* zero or stops being readable at all. That still bounds a host whose SDK
|
|
167
|
+
* runtime never came up: with no transport it can never receive a prompt, so it
|
|
168
|
+
* never reports work and its window keeps running from process start. And any
|
|
169
|
+
* real turn ends, after which the window resumes; live work defers a bound, it
|
|
170
|
+
* never removes it.
|
|
163
171
|
*/
|
|
164
172
|
export async function watchSessionHostClientAttachment(deps: {
|
|
165
173
|
readAttachedClients: () => number | undefined;
|
|
@@ -182,16 +190,18 @@ export async function watchSessionHostClientAttachment(deps: {
|
|
|
182
190
|
let unattendedSince = now();
|
|
183
191
|
for (;;) {
|
|
184
192
|
const attached = deps.readAttachedClients();
|
|
185
|
-
if (readWorkInFlight())
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (!everAttached && now() - unattendedSince >= firstAttachGraceMs) return;
|
|
191
|
-
} else if (attached > 0) {
|
|
193
|
+
if (readWorkInFlight()) {
|
|
194
|
+
unattendedSince = now();
|
|
195
|
+
detachedSince = null;
|
|
196
|
+
}
|
|
197
|
+
if (attached !== undefined && attached > 0) {
|
|
192
198
|
everAttached = true;
|
|
193
199
|
detachedSince = null;
|
|
194
200
|
} else if (everAttached) {
|
|
201
|
+
// An observed zero and no readable evidence at all are the same
|
|
202
|
+
// absence once a client has been seen: a runtime that retracted its
|
|
203
|
+
// registration stops publishing a count instead of reporting zero.
|
|
204
|
+
// Both accrue against the idle bound rather than running forever.
|
|
195
205
|
detachedSince ??= now();
|
|
196
206
|
if (now() - detachedSince >= idleGraceMs) return;
|
|
197
207
|
} else if (now() - unattendedSince >= firstAttachGraceMs) {
|
|
@@ -697,6 +707,18 @@ export function parseSdkInternalArgv(argv: readonly string[]): SdkInternalArgv {
|
|
|
697
707
|
throw new CliParseError("Invalid internal SDK invocation.");
|
|
698
708
|
}
|
|
699
709
|
|
|
710
|
+
function parsePositiveTimeout(raw: string | undefined, flagName: string): number | undefined {
|
|
711
|
+
if (raw === undefined) return undefined;
|
|
712
|
+
if (!/^[0-9]+$/.test(raw)) {
|
|
713
|
+
throw new CliParseError(`Expected ${flagName} to be a positive safe integer, got "${raw}"`);
|
|
714
|
+
}
|
|
715
|
+
const value = Number(raw);
|
|
716
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
717
|
+
throw new CliParseError(`Expected ${flagName} to be a positive safe integer, got "${raw}"`);
|
|
718
|
+
}
|
|
719
|
+
return value;
|
|
720
|
+
}
|
|
721
|
+
|
|
700
722
|
class SdkServeHelp extends Command {
|
|
701
723
|
static description = "gjc sdk serve --stdio | --socket <path> [--session <id>] [--pending-ceiling <bytes>]";
|
|
702
724
|
static flags = {
|
|
@@ -708,16 +730,168 @@ class SdkServeHelp extends Command {
|
|
|
708
730
|
async run(): Promise<void> {}
|
|
709
731
|
}
|
|
710
732
|
|
|
733
|
+
class SdkSessionHelp extends Command {
|
|
734
|
+
static description =
|
|
735
|
+
"Manage SDK sessions: `gjc sdk session list|inspect|send|status|tail|elevate`, or the explicit raw hatch `gjc sdk session raw control|query|global`. The session CLI is broker-bound, credential-free by default, and elevation approval requires an attended operator.";
|
|
736
|
+
static args = {
|
|
737
|
+
verb: Args.string({
|
|
738
|
+
description: "Session verb",
|
|
739
|
+
required: false,
|
|
740
|
+
options: ["list", "inspect", "send", "status", "tail", "elevate", "raw"],
|
|
741
|
+
}),
|
|
742
|
+
target: Args.string({
|
|
743
|
+
description: "Session id (or the raw kind control|query|global for `raw`)",
|
|
744
|
+
required: false,
|
|
745
|
+
}),
|
|
746
|
+
opRef: Args.string({ description: "Operation reference to report on (status only)", required: false }),
|
|
747
|
+
};
|
|
748
|
+
static flags = {
|
|
749
|
+
"agent-dir": Flags.string({ description: "SDK broker state directory" }),
|
|
750
|
+
json: Flags.boolean({ description: "Emit JSON output (default for SDK session commands)" }),
|
|
751
|
+
repo: Flags.string({
|
|
752
|
+
description: "Workspace directory for saved-session resolution (default: current directory)",
|
|
753
|
+
}),
|
|
754
|
+
op: Flags.string({ description: "Raw control or global operation" }),
|
|
755
|
+
query: Flags.string({ description: "Raw query name" }),
|
|
756
|
+
kind: Flags.string({ description: "Elevation operation kind (control|global)", options: ["control", "global"] }),
|
|
757
|
+
"json-input": Flags.string({ description: "SDK request JSON object" }),
|
|
758
|
+
"json-input-file": Flags.string({ description: "Read SDK request JSON from a 0600 file" }),
|
|
759
|
+
"json-input-stdin": Flags.boolean({ description: "Read SDK request JSON from standard input" }),
|
|
760
|
+
"idempotency-key": Flags.string({ description: "Caller idempotency key required for SDK lifecycle globals" }),
|
|
761
|
+
"elevation-request-id": Flags.string({ description: "Approved elevation grant id for allowlisted raw controls" }),
|
|
762
|
+
confirm: Flags.boolean({ description: "Confirm a destructive SDK control operation" }),
|
|
763
|
+
cursor: Flags.string({
|
|
764
|
+
description:
|
|
765
|
+
"Raw query continuation cursor, or a saved checkpoint token to resume tail from (re-minted per connection)",
|
|
766
|
+
}),
|
|
767
|
+
"show-endpoint-credential": Flags.boolean({ description: "Allow session.get_endpoint secret output" }),
|
|
768
|
+
yes: Flags.boolean({ description: "Confirm endpoint credential output on a TTY" }),
|
|
769
|
+
text: Flags.string({ description: "Prompt text for send (alternative to --json-input)" }),
|
|
770
|
+
"op-ref": Flags.string({ description: "Operation reference for send (defaults to a generated ULID)" }),
|
|
771
|
+
wait: Flags.boolean({
|
|
772
|
+
description: "send --wait: poll turn.prompt_status until terminal or the wait window elapses (never cancels)",
|
|
773
|
+
}),
|
|
774
|
+
"timeout-ms": Flags.string({ description: "Wait window for send --wait, status, and live tail follow" }),
|
|
775
|
+
strict: Flags.boolean({ description: "tail --strict: fail closed (exit 1 retention_gap) on retention gaps" }),
|
|
776
|
+
"until-idle": Flags.boolean({
|
|
777
|
+
description: "tail --until-idle: exit once the observed event stream reaches a terminal turn state",
|
|
778
|
+
}),
|
|
779
|
+
"all-events": Flags.boolean({ description: "tail --all-events: include every event-ring kind" }),
|
|
780
|
+
};
|
|
781
|
+
async run(): Promise<void> {}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
class SdkSessionCommand extends Command {
|
|
785
|
+
static description = SdkSessionHelp.description;
|
|
786
|
+
static args = SdkSessionHelp.args;
|
|
787
|
+
static flags = SdkSessionHelp.flags;
|
|
788
|
+
async run(): Promise<void> {
|
|
789
|
+
const { args, flags } = await this.parse(SdkSessionCommand);
|
|
790
|
+
const verb = args.verb;
|
|
791
|
+
const target = args.target;
|
|
792
|
+
const flagRec = flags as Record<string, unknown>;
|
|
793
|
+
const timeoutMs = parsePositiveTimeout(flagRec["timeout-ms"] as string | undefined, "--timeout-ms");
|
|
794
|
+
await runSdkSessionCli({
|
|
795
|
+
action: verb,
|
|
796
|
+
...(verb === "raw"
|
|
797
|
+
? {
|
|
798
|
+
rawAction: target,
|
|
799
|
+
sessionId: target === "control" || target === "query" ? args.opRef : undefined,
|
|
800
|
+
}
|
|
801
|
+
: { sessionId: verb === "list" ? undefined : target }),
|
|
802
|
+
opRef: verb === "status" ? args.opRef : (flagRec["op-ref"] as string | undefined),
|
|
803
|
+
operation: flagRec.op as string | undefined,
|
|
804
|
+
query: flagRec.query as string | undefined,
|
|
805
|
+
text: flagRec.text as string | undefined,
|
|
806
|
+
jsonInput: flagRec["json-input"] as string | undefined,
|
|
807
|
+
jsonInputFile: flagRec["json-input-file"] as string | undefined,
|
|
808
|
+
jsonInputStdin: Boolean(flagRec["json-input-stdin"]),
|
|
809
|
+
confirm: Boolean(flagRec.confirm),
|
|
810
|
+
idempotencyKey: flagRec["idempotency-key"] as string | undefined,
|
|
811
|
+
elevationRequestId: flagRec["elevation-request-id"] as string | undefined,
|
|
812
|
+
operationKind: flagRec.kind as "control" | "global" | undefined,
|
|
813
|
+
cursor: flagRec.cursor as string | undefined,
|
|
814
|
+
showEndpointCredential: Boolean(flagRec["show-endpoint-credential"]),
|
|
815
|
+
yes: Boolean(flagRec.yes),
|
|
816
|
+
wait: Boolean(flagRec.wait),
|
|
817
|
+
timeoutMs,
|
|
818
|
+
strict: Boolean(flagRec.strict),
|
|
819
|
+
untilIdle: Boolean(flagRec["until-idle"]),
|
|
820
|
+
allEvents: Boolean(flagRec["all-events"]),
|
|
821
|
+
agentDir: flagRec["agent-dir"] as string | undefined,
|
|
822
|
+
repo: flagRec.repo as string | undefined,
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
class SdkGuidesHelp extends Command {
|
|
828
|
+
static description = "Manage verified advisory SDK guides: refresh, list, show, status, or trust.";
|
|
829
|
+
static args = {
|
|
830
|
+
action: Args.string({ required: false, options: ["refresh", "list", "show", "status", "trust"] }),
|
|
831
|
+
guideId: Args.string({ required: false, description: "Guide id for show" }),
|
|
832
|
+
};
|
|
833
|
+
static flags = {
|
|
834
|
+
"agent-dir": Flags.string({ description: "SDK broker state directory" }),
|
|
835
|
+
url: Flags.string({ description: "HTTPS allowlisted manifest URL for refresh" }),
|
|
836
|
+
"timeout-ms": Flags.string({ description: "Bounded refresh timeout in milliseconds" }),
|
|
837
|
+
};
|
|
838
|
+
async run(): Promise<void> {}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
class SdkGuidesCommand extends Command {
|
|
842
|
+
static description = SdkGuidesHelp.description;
|
|
843
|
+
static args = SdkGuidesHelp.args;
|
|
844
|
+
static flags = SdkGuidesHelp.flags;
|
|
845
|
+
async run(): Promise<void> {
|
|
846
|
+
const { args, flags } = await this.parse(SdkGuidesCommand);
|
|
847
|
+
const flagRec = flags as Record<string, unknown>;
|
|
848
|
+
await runSdkGuidesCli({
|
|
849
|
+
action: args.action,
|
|
850
|
+
guideId: args.guideId,
|
|
851
|
+
url: flagRec.url as string | undefined,
|
|
852
|
+
agentDir: flagRec["agent-dir"] as string | undefined,
|
|
853
|
+
timeoutMs: parsePositiveTimeout(flagRec["timeout-ms"] as string | undefined, "--timeout-ms"),
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
711
858
|
export default class Sdk extends Command {
|
|
712
|
-
static description =
|
|
859
|
+
static description =
|
|
860
|
+
"gjc sdk serve --stdio | --socket <path> [--session <id>]; gjc sdk session list|inspect|send|status|tail; gjc sdk guides refresh|list|show|status|trust";
|
|
713
861
|
static hidden = false;
|
|
714
862
|
static delegateHelp = true;
|
|
715
|
-
static args = { action: Args.string({ required: false, options: ["serve"] }) };
|
|
863
|
+
static args = { action: Args.string({ required: false, options: ["serve", "session", "guides"] }) };
|
|
716
864
|
static flags = SdkServeHelp.flags;
|
|
717
865
|
async run(): Promise<void> {
|
|
718
866
|
const action = this.argv[0];
|
|
719
867
|
if (this.argv.includes("--help") || this.argv.includes("-h")) {
|
|
720
|
-
|
|
868
|
+
const helpAction =
|
|
869
|
+
action === "serve"
|
|
870
|
+
? "sdk serve"
|
|
871
|
+
: action === "session"
|
|
872
|
+
? "sdk session"
|
|
873
|
+
: action === "guides"
|
|
874
|
+
? "sdk guides"
|
|
875
|
+
: "sdk";
|
|
876
|
+
const helpCommand =
|
|
877
|
+
action === "serve"
|
|
878
|
+
? SdkServeHelp
|
|
879
|
+
: action === "session"
|
|
880
|
+
? SdkSessionCommand
|
|
881
|
+
: action === "guides"
|
|
882
|
+
? SdkGuidesCommand
|
|
883
|
+
: Sdk;
|
|
884
|
+
renderCommandHelp("gjc", helpAction, helpCommand);
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
if (action === "session") {
|
|
888
|
+
const instance = new SdkSessionCommand(this.argv.slice(1), this.config);
|
|
889
|
+
await instance.run();
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
if (action === "guides") {
|
|
893
|
+
const instance = new SdkGuidesCommand(this.argv.slice(1), this.config);
|
|
894
|
+
await instance.run();
|
|
721
895
|
return;
|
|
722
896
|
}
|
|
723
897
|
if (action === "serve") {
|
|
@@ -725,7 +899,7 @@ export default class Sdk extends Command {
|
|
|
725
899
|
return;
|
|
726
900
|
}
|
|
727
901
|
if (action !== "broker-internal" && action !== "session-host-internal")
|
|
728
|
-
throw new CliParseError("Expected action to be serve.");
|
|
902
|
+
throw new CliParseError("Expected action to be serve, session, or guides.");
|
|
729
903
|
const internal = parseSdkInternalArgv(this.argv);
|
|
730
904
|
if (internal.action === "session-host-internal") {
|
|
731
905
|
await runSessionHost();
|
package/src/commands/setup.ts
CHANGED
|
@@ -50,10 +50,12 @@ export default class Setup extends Command {
|
|
|
50
50
|
"gjc-command": Flags.string({ description: "Command used to start `gjc mcp-serve coordinator`" }),
|
|
51
51
|
target: Flags.string({ description: "Hermes config file target for config-only install" }),
|
|
52
52
|
"profile-dir": Flags.string({ description: "Hermes profile directory for full setup install" }),
|
|
53
|
-
preset: Flags.string({ description: "Provider preset
|
|
53
|
+
preset: Flags.string({ description: "Provider preset id (run setup provider --help to list available presets)" }),
|
|
54
54
|
compat: Flags.string({ description: "Provider compatibility: openai or anthropic" }),
|
|
55
55
|
provider: Flags.string({ description: "Provider id to add to models.yml" }),
|
|
56
|
-
"base-url": Flags.string({
|
|
56
|
+
"base-url": Flags.string({
|
|
57
|
+
description: "Provider API base URL (required for proxy presets: litellm, openai-compatible-proxy)",
|
|
58
|
+
}),
|
|
57
59
|
"api-key-env": Flags.string({ description: "Read provider API key from this environment variable" }),
|
|
58
60
|
model: Flags.string({ description: "Model id to add (repeat or comma-separate)", multiple: true }),
|
|
59
61
|
"models-path": Flags.string({ description: "Override models config path" }),
|
|
@@ -35,6 +35,8 @@ interface WalkState {
|
|
|
35
35
|
export interface FileLocksGcCollectOptions {
|
|
36
36
|
/** Override per-root entry budget (tests). Defaults to {@link FILE_LOCK_GC_MAX_WALK_ENTRIES}. */
|
|
37
37
|
maxWalkEntries?: number;
|
|
38
|
+
/** Override global lock roots for isolated collection tests. */
|
|
39
|
+
roots?: readonly string[];
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
// Global, env-aware GJC lock roots. Per the approved scope this covers the
|
|
@@ -169,7 +171,8 @@ export async function collectFileLocksForGc(
|
|
|
169
171
|
const warnings: GcWarning[] = [];
|
|
170
172
|
const lockDirs = new Set<string>();
|
|
171
173
|
|
|
172
|
-
|
|
174
|
+
const roots = options.roots ?? knownFileLockRoots(ctx);
|
|
175
|
+
for (const root of Array.from(new Set(roots.map(root => path.resolve(root))))) {
|
|
173
176
|
// Fresh budget per root so a huge agent dir cannot starve config/spool.
|
|
174
177
|
const state: WalkState = { entries: 0, truncated: false };
|
|
175
178
|
await walkForLockDirs(root, 0, state, lockDirs, errors, maxWalkEntries);
|
|
@@ -24,6 +24,15 @@ export interface CanonicalModelIndex {
|
|
|
24
24
|
records: CanonicalModelRecord[];
|
|
25
25
|
byId: Map<string, CanonicalModelRecord>;
|
|
26
26
|
bySelector: Map<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* Final-slash-segment lookup aliases: normalized alias key -> normalized
|
|
29
|
+
* variant selectors ("provider/id") of every variant whose model id ends in
|
|
30
|
+
* that segment. Variant-level: an alias never widens to sibling variants in
|
|
31
|
+
* the same canonical record that end in a different segment. Multi-target
|
|
32
|
+
* when distinct variants collide on the same segment. Built without
|
|
33
|
+
* rewriting the canonical or runtime identity of any variant.
|
|
34
|
+
*/
|
|
35
|
+
aliases: Map<string, string[]>;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
interface CanonicalReferenceData {
|
|
@@ -104,6 +113,22 @@ export function formatCanonicalVariantSelector(model: Model<Api>): string {
|
|
|
104
113
|
return `${model.provider}/${model.id}`;
|
|
105
114
|
}
|
|
106
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Normalize a model id into its final-slash-segment alias key (trimmed and
|
|
118
|
+
* lowercased). A bare id without a slash yields the id itself; a multi-level
|
|
119
|
+
* id yields its last path segment. Returns undefined for empty ids.
|
|
120
|
+
*/
|
|
121
|
+
export function getFinalSlashSegmentAliasKey(modelId: string): string | undefined {
|
|
122
|
+
const normalized = modelId.trim();
|
|
123
|
+
if (!normalized) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const slashIndex = normalized.lastIndexOf("/");
|
|
127
|
+
const segment = slashIndex >= 0 ? normalized.slice(slashIndex + 1) : normalized;
|
|
128
|
+
const key = segment.trim().toLowerCase();
|
|
129
|
+
return key || undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
107
132
|
/**
|
|
108
133
|
* Compare equivalent provider variants using the caller's ranking policy.
|
|
109
134
|
*
|
|
@@ -112,11 +137,16 @@ export function formatCanonicalVariantSelector(model: Model<Api>): string {
|
|
|
112
137
|
* source, input plus cache-read cost, and original catalog order. Callers that
|
|
113
138
|
* do not have a canonical index can omit those axes while retaining a stable,
|
|
114
139
|
* total comparison.
|
|
140
|
+
*
|
|
141
|
+
* `providerRankFirst` swaps the first two axes so configured provider rank wins
|
|
142
|
+
* over vision support; canonical/alias resolution uses this order while every
|
|
143
|
+
* existing caller keeps the legacy vision-first order by default.
|
|
115
144
|
*/
|
|
116
145
|
export function compareEquivalentModelVariants(
|
|
117
146
|
left: Model<Api>,
|
|
118
147
|
right: Model<Api>,
|
|
119
148
|
options: {
|
|
149
|
+
providerRankFirst?: boolean;
|
|
120
150
|
providerRank?: ReadonlyMap<string, number>;
|
|
121
151
|
canonicalId?: string;
|
|
122
152
|
leftSourceRank?: number;
|
|
@@ -128,17 +158,32 @@ export function compareEquivalentModelVariants(
|
|
|
128
158
|
): number {
|
|
129
159
|
const leftVisionRank = Number(!left.input.includes("image"));
|
|
130
160
|
const rightVisionRank = Number(!right.input.includes("image"));
|
|
131
|
-
if (leftVisionRank !== rightVisionRank) return leftVisionRank - rightVisionRank;
|
|
132
161
|
|
|
133
|
-
|
|
162
|
+
const compareProviderRank = (): number => {
|
|
163
|
+
if (!options.providerRank) {
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
134
166
|
const leftProviderRank = options.providerRank.get(left.provider.toLowerCase()) ?? Number.MAX_SAFE_INTEGER;
|
|
135
167
|
const rightProviderRank = options.providerRank.get(right.provider.toLowerCase()) ?? Number.MAX_SAFE_INTEGER;
|
|
136
|
-
|
|
168
|
+
return leftProviderRank - rightProviderRank;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
if (options.providerRankFirst) {
|
|
172
|
+
const providerRankDiff = compareProviderRank();
|
|
173
|
+
if (providerRankDiff !== 0) return providerRankDiff;
|
|
174
|
+
if (leftVisionRank !== rightVisionRank) return leftVisionRank - rightVisionRank;
|
|
175
|
+
} else {
|
|
176
|
+
if (leftVisionRank !== rightVisionRank) return leftVisionRank - rightVisionRank;
|
|
177
|
+
const providerRankDiff = compareProviderRank();
|
|
178
|
+
if (providerRankDiff !== 0) return providerRankDiff;
|
|
137
179
|
}
|
|
138
180
|
|
|
139
181
|
if (options.canonicalId) {
|
|
140
|
-
|
|
141
|
-
|
|
182
|
+
// Compare case-insensitively against the normalized exactness key so a
|
|
183
|
+
// mixed-case model id still matches the alias/canonical lookup key.
|
|
184
|
+
const normalizedExactnessKey = options.canonicalId.trim().toLowerCase();
|
|
185
|
+
const leftExactRank = Number(left.id.trim().toLowerCase() !== normalizedExactnessKey);
|
|
186
|
+
const rightExactRank = Number(right.id.trim().toLowerCase() !== normalizedExactnessKey);
|
|
142
187
|
if (leftExactRank !== rightExactRank) return leftExactRank - rightExactRank;
|
|
143
188
|
}
|
|
144
189
|
|
|
@@ -835,6 +880,8 @@ export function buildCanonicalModelIndex(
|
|
|
835
880
|
const compiledEquivalence = compileEquivalenceConfig(equivalence);
|
|
836
881
|
const byId = new Map<string, CanonicalModelRecord>();
|
|
837
882
|
const bySelector = new Map<string, string>();
|
|
883
|
+
const aliases = new Map<string, Set<string>>();
|
|
884
|
+
const ambiguousSelectors = new Set<string>();
|
|
838
885
|
|
|
839
886
|
const compiledWithCache = compiledEquivalence as CompiledEquivalenceConfigWithCache;
|
|
840
887
|
let modelCache = compiledWithCache[kModelResolutionCache];
|
|
@@ -865,7 +912,23 @@ export function buildCanonicalModelIndex(
|
|
|
865
912
|
};
|
|
866
913
|
nextRecord.variants.push(variant);
|
|
867
914
|
byId.set(canonicalKey, nextRecord);
|
|
868
|
-
|
|
915
|
+
const selectorKey = normalizeSelectorKey(selector);
|
|
916
|
+
if (bySelector.has(selectorKey) || ambiguousSelectors.has(selectorKey)) {
|
|
917
|
+
bySelector.delete(selectorKey);
|
|
918
|
+
ambiguousSelectors.add(selectorKey);
|
|
919
|
+
} else {
|
|
920
|
+
bySelector.set(selectorKey, canonical.id);
|
|
921
|
+
}
|
|
922
|
+
const aliasKey = getFinalSlashSegmentAliasKey(model.id);
|
|
923
|
+
if (aliasKey) {
|
|
924
|
+
const aliasSelector = selectorKey;
|
|
925
|
+
let targets = aliases.get(aliasKey);
|
|
926
|
+
if (!targets) {
|
|
927
|
+
targets = new Set<string>();
|
|
928
|
+
aliases.set(aliasKey, targets);
|
|
929
|
+
}
|
|
930
|
+
targets.add(aliasSelector);
|
|
931
|
+
}
|
|
869
932
|
}
|
|
870
933
|
|
|
871
934
|
const records = [...byId.values()].sort(compareCanonicalRecords);
|
|
@@ -873,5 +936,11 @@ export function buildCanonicalModelIndex(
|
|
|
873
936
|
record.variants.sort(compareCanonicalVariants);
|
|
874
937
|
}
|
|
875
938
|
|
|
876
|
-
|
|
939
|
+
const aliasesByKey = new Map<string, string[]>();
|
|
940
|
+
for (const [aliasKey, targets] of aliases) {
|
|
941
|
+
for (const ambiguousSelector of ambiguousSelectors) targets.delete(ambiguousSelector);
|
|
942
|
+
if (targets.size > 0) aliasesByKey.set(aliasKey, [...targets]);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
return { records, byId, bySelector, aliases: aliasesByKey };
|
|
877
946
|
}
|