@gajae-code/coding-agent 0.17.4 → 0.17.6
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 +82 -0
- package/dist/types/config/autorouting-tier-map.d.ts +1031 -3
- package/dist/types/config/file-lock.d.ts +4 -2
- package/dist/types/config/model-registry.d.ts +3 -1
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +11 -2
- package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
- package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
- package/dist/types/harness-control-plane/finalize.d.ts +14 -3
- package/dist/types/main.d.ts +1 -1
- package/dist/types/runtime-mcp/loader.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +13 -6
- package/dist/types/sdk/broker/broker.d.ts +4 -2
- package/dist/types/sdk/broker/ensure.d.ts +3 -0
- package/dist/types/sdk/broker/identity.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +11 -3
- package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
- package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
- package/dist/types/sdk/broker/spawn-authority.d.ts +8 -0
- package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +5 -1
- package/dist/types/sdk/prompt-deadline-flush.d.ts +2 -0
- package/dist/types/sdk/session.d.ts +3 -3
- package/dist/types/session/agent-session.d.ts +7 -2
- package/dist/types/task/types.d.ts +2 -0
- package/dist/types/tools/bash-interactive.d.ts +1 -0
- package/dist/types/tools/fetch.d.ts +10 -1
- package/dist/types/tools/subagent.d.ts +8 -1
- package/package.json +7 -7
- package/src/cli/public-command-registry.ts +8 -2
- package/src/cli/setup-cli.ts +1 -0
- package/src/cli/stats-cli.ts +11 -1
- package/src/config/autorouting-tier-map.ts +529 -3
- package/src/config/file-lock.ts +59 -14
- package/src/config/model-discovery-manager.ts +4 -4
- package/src/config/model-profile-activation.ts +83 -23
- package/src/config/model-registry.ts +72 -12
- package/src/config/model-resolver.ts +6 -1
- package/src/coordinator-mcp/question-state.ts +4 -1
- package/src/coordinator-mcp/server.ts +14 -6
- package/src/exec/bash-executor.ts +3 -0
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
- package/src/gjc-runtime/state-writer.ts +317 -6
- package/src/harness-control-plane/control-endpoint.ts +24 -6
- package/src/harness-control-plane/finalize.ts +312 -25
- package/src/harness-control-plane/owner.ts +323 -89
- package/src/internal-urls/docs-index.generated.ts +6 -4
- package/src/main.ts +69 -19
- package/src/modes/acp/acp-agent.ts +581 -37
- package/src/modes/components/gjc-bundle-settings.ts +21 -1
- package/src/modes/components/tool-status-header.ts +72 -6
- package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
- package/src/runtime-mcp/loader.ts +6 -3
- package/src/runtime-mcp/manager.ts +177 -75
- package/src/sdk/broker/broker.ts +1058 -150
- package/src/sdk/broker/ensure.ts +65 -8
- package/src/sdk/broker/identity.ts +13 -0
- package/src/sdk/broker/lifecycle-ledger.ts +16 -4
- package/src/sdk/broker/managed-task-dag.ts +1927 -0
- package/src/sdk/broker/managed-task-verification.ts +642 -0
- package/src/sdk/broker/spawn-authority.ts +140 -7
- package/src/sdk/broker/startup-failure.ts +80 -1
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +22 -6
- package/src/sdk/bus/telegram-daemon-contract.ts +5 -1
- package/src/sdk/cli/session-cli.ts +18 -0
- package/src/sdk/host/session-runtime.test.ts +46 -0
- package/src/sdk/host/session-runtime.ts +13 -6
- package/src/sdk/lifecycle/service.ts +2 -0
- package/src/sdk/prompt-deadline-flush.ts +26 -4
- package/src/sdk/session.ts +587 -115
- package/src/session/agent-session.ts +60 -14
- package/src/session/internal/managed-session-scope.ts +10 -0
- package/src/session/internal/managed-session-storage.ts +30 -1
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/task/executor.ts +46 -17
- package/src/task/types.ts +2 -0
- package/src/tools/bash-interactive.ts +2 -0
- package/src/tools/bash.ts +20 -0
- package/src/tools/fetch.ts +21 -5
- package/src/tools/subagent-render.ts +24 -1
- package/src/tools/subagent.ts +27 -1
- package/src/utils/mupdf.ts +11 -4
package/src/sdk/broker/ensure.ts
CHANGED
|
@@ -18,13 +18,25 @@ import {
|
|
|
18
18
|
resolveSdkInternalSpawnCommand,
|
|
19
19
|
type SdkInternalSpawnCommand,
|
|
20
20
|
} from "./runtime";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
BrokerStartupError,
|
|
23
|
+
type BrokerStartupFailureMarker,
|
|
24
|
+
brokerStartupFailureCleanupTargetsLock,
|
|
25
|
+
clearBrokerStartupFailureMarker,
|
|
26
|
+
readBrokerStartupFailureMarker,
|
|
27
|
+
} from "./startup-failure";
|
|
22
28
|
|
|
23
29
|
function resolveExpectedBrokerGeneration(): string {
|
|
24
30
|
const v = (packageJson as { version?: unknown }).version;
|
|
25
31
|
return typeof v === "string" && v.length > 0 ? v : "unknown";
|
|
26
32
|
}
|
|
27
33
|
|
|
34
|
+
function brokerStartupFailureReason(marker: BrokerStartupFailureMarker | undefined): string {
|
|
35
|
+
if (!marker) return "Detached SDK broker exited before publishing discovery.";
|
|
36
|
+
if (marker.cleanupCommand && marker.reason.endsWith(": ")) return `${marker.reason}${marker.cleanupCommand}`;
|
|
37
|
+
return marker.reason;
|
|
38
|
+
}
|
|
39
|
+
|
|
28
40
|
export function isBrokerGenerationCompatible(discovery: BrokerDiscovery | null): boolean {
|
|
29
41
|
if (!discovery) return false;
|
|
30
42
|
return discovery.packageGeneration === resolveExpectedBrokerGeneration();
|
|
@@ -69,6 +81,34 @@ const SPAWN_LOCK_WAIT_MS = STALE_BROKER_RETIREMENT_TIMEOUT_MS + DISCOVERY_TIMEOU
|
|
|
69
81
|
const SPAWN_LOCK_RETRY_DELAY_MS = 50;
|
|
70
82
|
const SPAWN_LOCK_TARGET_NAME = "broker.spawn";
|
|
71
83
|
const STARTUP_LOCK_TARGET_NAME = "broker.startup";
|
|
84
|
+
const BROKER_SESSION_ENV_NAMES = new Set([
|
|
85
|
+
"GJC_SESSION_FILE",
|
|
86
|
+
"GJC_SESSION_ID",
|
|
87
|
+
"GJC_SESSION_CWD",
|
|
88
|
+
"GJC_SESSION_PROMPT_ACCEPTED_JSON",
|
|
89
|
+
"GJC_SESSION_WORKTREE_BASELINE_DIRTY",
|
|
90
|
+
"GJC_TMUX_ACTIVE_SESSION",
|
|
91
|
+
"GJC_TMUX_LAUNCHED",
|
|
92
|
+
"TMUX",
|
|
93
|
+
"TMUX_PANE",
|
|
94
|
+
"GJC_LIFECYCLE_REQUEST_ID",
|
|
95
|
+
"GJC_SDK_LIFECYCLE_REQUEST",
|
|
96
|
+
"GJC_STATE_ROOT",
|
|
97
|
+
"GJC_MASTER_CAPABILITY",
|
|
98
|
+
"GJC_MASTER_OWNER_SESSION_ID",
|
|
99
|
+
]);
|
|
100
|
+
const BROKER_SESSION_ENV_PRESERVED_NAMES = new Set([
|
|
101
|
+
"GJC_SESSION_CONTEXT_BUDGET_BYTES",
|
|
102
|
+
"GJC_SESSION_MEMORY_GC_STRATEGY",
|
|
103
|
+
"GJC_SESSION_MEMORY_SECONDARY_ARTIFACT_MODE",
|
|
104
|
+
]);
|
|
105
|
+
const BROKER_SESSION_ENV_PREFIXES = [
|
|
106
|
+
"GJC_SESSION_",
|
|
107
|
+
"GJC_COORDINATOR_SESSION_",
|
|
108
|
+
"GJC_COORDINATOR_SIDECAR_",
|
|
109
|
+
"GJC_TMUX_OWNER_",
|
|
110
|
+
"GJC_MANAGED_OWNER_",
|
|
111
|
+
] as const;
|
|
72
112
|
|
|
73
113
|
export interface BrokerStartupLockTestHooks {
|
|
74
114
|
onAcquired?: () => void;
|
|
@@ -445,11 +485,22 @@ function registerBrokerOwner(
|
|
|
445
485
|
function brokerSpawnEnvironment(command: SdkInternalSpawnCommand, override?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
446
486
|
const environment = { ...(override ?? command.env) };
|
|
447
487
|
delete environment.BUN_OPTIONS;
|
|
448
|
-
//
|
|
449
|
-
//
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
|
|
488
|
+
// Master capability and owner-session markers are matched by the normalized
|
|
489
|
+
// identity-name set below, including differently-cased Windows environment keys.
|
|
490
|
+
// The broker outlives the TUI session that happened to start it. Never let
|
|
491
|
+
// that session's identity or coordinator/tmux ownership markers flow through
|
|
492
|
+
// the broker's process.env into unrelated session hosts. Keep user tmux
|
|
493
|
+
// configuration (for example GJC_TMUX_SESSION, GJC_TMUX_COMMAND, GJC_MOUSE,
|
|
494
|
+
// and GJC_TMUX_PROFILE) intact. Windows environment names are case-insensitive.
|
|
495
|
+
for (const name of Object.keys(environment)) {
|
|
496
|
+
const normalizedName = name.toUpperCase();
|
|
497
|
+
if (BROKER_SESSION_ENV_PRESERVED_NAMES.has(normalizedName)) continue;
|
|
498
|
+
if (
|
|
499
|
+
BROKER_SESSION_ENV_NAMES.has(normalizedName) ||
|
|
500
|
+
BROKER_SESSION_ENV_PREFIXES.some(prefix => normalizedName.startsWith(prefix))
|
|
501
|
+
)
|
|
502
|
+
delete environment[name];
|
|
503
|
+
}
|
|
453
504
|
if (command.kind === "bun-source") {
|
|
454
505
|
delete environment.PI_COMPILED;
|
|
455
506
|
delete environment.GJC_COMPILED;
|
|
@@ -712,7 +763,8 @@ async function ensureBrokerOnce(settings: EnsureBrokerSettings, initiator: Ensur
|
|
|
712
763
|
const startupLockPath = path.join(settings.agentDir, "sdk", STARTUP_LOCK_TARGET_NAME);
|
|
713
764
|
let startupFenceContention =
|
|
714
765
|
exitedBeforeDiscovery &&
|
|
715
|
-
trustedMarker?.reason.startsWith(`Failed to acquire lock for ${startupLockPath} after `) === true
|
|
766
|
+
(trustedMarker?.reason.startsWith(`Failed to acquire lock for ${startupLockPath} after `) === true ||
|
|
767
|
+
brokerStartupFailureCleanupTargetsLock(trustedMarker, `${startupLockPath}.lock`));
|
|
716
768
|
if (!startupFenceContention && exitedBeforeDiscovery && child.exitCode !== 0) {
|
|
717
769
|
try {
|
|
718
770
|
startupFenceContention = (await fs.stat(`${startupLockPath}.lock`)).isDirectory();
|
|
@@ -760,7 +812,7 @@ async function ensureBrokerOnce(settings: EnsureBrokerSettings, initiator: Ensur
|
|
|
760
812
|
? new BrokerStartupError({
|
|
761
813
|
exitCode: child.exitCode,
|
|
762
814
|
signal: child.signalCode,
|
|
763
|
-
reason: trustedMarker
|
|
815
|
+
reason: brokerStartupFailureReason(trustedMarker),
|
|
764
816
|
stderrExcerpt: spawnLogTail.length > 0 ? spawnLogTail : undefined,
|
|
765
817
|
})
|
|
766
818
|
: discoveryError
|
|
@@ -889,3 +941,8 @@ export function registerBrokerOwnerForTest(
|
|
|
889
941
|
): BrokerOwner {
|
|
890
942
|
return registerBrokerOwner(agentDir, child, timing);
|
|
891
943
|
}
|
|
944
|
+
|
|
945
|
+
/** Test hook: exercises the same trusted-marker reason reconstruction used by ensureBroker. */
|
|
946
|
+
export function brokerStartupFailureReasonForTest(marker: BrokerStartupFailureMarker | undefined): string {
|
|
947
|
+
return brokerStartupFailureReason(marker);
|
|
948
|
+
}
|
|
@@ -51,6 +51,19 @@ export async function deriveIdempotencyIdentity(
|
|
|
51
51
|
.digest("hex");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/** Native identity for an idempotency key reserved inside one managed control root. */
|
|
55
|
+
export async function deriveScopedIdempotencyIdentity(
|
|
56
|
+
agentDir: string,
|
|
57
|
+
operation: string,
|
|
58
|
+
callerKey: string,
|
|
59
|
+
scope: string,
|
|
60
|
+
): Promise<string> {
|
|
61
|
+
const key = await getBrokerIdentityKey(agentDir);
|
|
62
|
+
return createHmac("sha256", Buffer.from(key, "hex"))
|
|
63
|
+
.update(JSON.stringify(["managed-spawn-v1", operation, callerKey, scope]))
|
|
64
|
+
.digest("hex");
|
|
65
|
+
}
|
|
66
|
+
|
|
54
67
|
/** Identity format used by lifecycle rows written before target binding. */
|
|
55
68
|
export async function deriveLegacyIdentity(agentDir: string, operation: string, callerKey: string): Promise<string> {
|
|
56
69
|
const key = await getBrokerIdentityKey(agentDir);
|
|
@@ -711,13 +711,25 @@ export class LifecycleLedger {
|
|
|
711
711
|
return [...this.#byIdentity.values()].findLast(entry => entry.operationKey === operationKey);
|
|
712
712
|
}
|
|
713
713
|
/**
|
|
714
|
-
*
|
|
714
|
+
* Live or uncertain legacy rows predate the operation/key index. Their opaque
|
|
715
715
|
* identities cannot establish that a different target is safe, so callers
|
|
716
|
-
* must reject rather than create a second admission.
|
|
716
|
+
* must reject rather than create a second admission. A fresh session.create
|
|
717
|
+
* may ignore completed terminal legacy rows so old successful operations do
|
|
718
|
+
* not block coordinator startup. Other operations retain the legacy fence
|
|
719
|
+
* because target-bound legacy identities cannot prove key uniqueness. For
|
|
720
|
+
* target-bound terminal creates, the opaque legacy identity also cannot reveal
|
|
721
|
+
* the original caller key, so this exception retires that legacy key history;
|
|
722
|
+
* exact key-only legacy creates are still rejected by the earlier lookup.
|
|
717
723
|
*/
|
|
718
|
-
hasLegacyIdentity(
|
|
724
|
+
hasLegacyIdentity(
|
|
725
|
+
excludedIdentities?: ReadonlySet<string>,
|
|
726
|
+
options: { ignoreTerminalRows?: boolean } = {},
|
|
727
|
+
): boolean {
|
|
719
728
|
return [...this.#byIdentity.values()].some(
|
|
720
|
-
entry =>
|
|
729
|
+
entry =>
|
|
730
|
+
entry.operationKey === undefined &&
|
|
731
|
+
!(options.ignoreTerminalRows && terminal(entry.state)) &&
|
|
732
|
+
!excludedIdentities?.has(entry.identity),
|
|
721
733
|
);
|
|
722
734
|
}
|
|
723
735
|
async migrateIdentity(
|