@gajae-code/coding-agent 0.15.6 → 0.16.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 +59 -0
- package/dist/types/cli/args.d.ts +2 -0
- package/dist/types/cli/root-flags.d.ts +14 -0
- package/dist/types/cli/update-cli.d.ts +13 -0
- package/dist/types/cli.d.ts +7 -0
- package/dist/types/commands/launch.d.ts +10 -0
- package/dist/types/config/autorouting-tier-map.d.ts +24 -0
- package/dist/types/config/file-lock.d.ts +5 -0
- package/dist/types/config/model-registry.d.ts +6 -0
- package/dist/types/config/settings-schema.d.ts +10 -1
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/coordinator-mcp/projection-scan.d.ts +8 -0
- package/dist/types/crash/record-loader.d.ts +15 -0
- package/dist/types/gjc-runtime/launch-worktree-reservation.d.ts +21 -0
- package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +2 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +66 -1
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +1 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +27 -0
- package/dist/types/master-mode/context.d.ts +21 -0
- package/dist/types/master-mode/first-request.d.ts +34 -0
- package/dist/types/master-mode/snapshot.d.ts +32 -0
- package/dist/types/modes/components/frictionless-onboarding-selector.d.ts +10 -0
- package/dist/types/modes/components/oauth-selector.d.ts +1 -0
- package/dist/types/modes/components/status-line/model-name.d.ts +18 -0
- package/dist/types/modes/components/status-line/priority-row.d.ts +34 -0
- package/dist/types/modes/components/status-line/segments.d.ts +10 -0
- package/dist/types/modes/print-mode.d.ts +17 -0
- package/dist/types/modes/ui-language.d.ts +7 -1
- package/dist/types/sdk/broker/broker.d.ts +77 -1
- package/dist/types/sdk/broker/endpoint-authority.d.ts +24 -0
- package/dist/types/sdk/broker/index.d.ts +3 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +26 -0
- package/dist/types/sdk/broker/master-capability.d.ts +10 -0
- package/dist/types/sdk/broker/session-index.d.ts +40 -11
- package/dist/types/sdk/broker/session-scope.d.ts +72 -0
- package/dist/types/sdk/broker/spawn-authority.d.ts +201 -0
- package/dist/types/sdk/broker/spawn-substrate.d.ts +30 -0
- package/dist/types/sdk/broker/state-version.d.ts +4 -1
- package/dist/types/sdk/broker/worktree-occupancy.d.ts +28 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -0
- package/dist/types/sdk/bus/index.d.ts +6 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/master-cli.d.ts +63 -0
- package/dist/types/sdk/cli/rows.d.ts +4 -3
- package/dist/types/sdk/cli/session-cli.d.ts +18 -2
- package/dist/types/sdk/client/client.d.ts +3 -2
- package/dist/types/sdk/host/control/dispatch.d.ts +10 -0
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +2 -0
- package/dist/types/sdk/host/control/runtime-gate.d.ts +21 -7
- package/dist/types/sdk/host/host.d.ts +10 -0
- package/dist/types/sdk/host/session-runtime.d.ts +52 -0
- package/dist/types/sdk/lifecycle/broker-client.d.ts +6 -0
- package/dist/types/sdk/lifecycle/service.d.ts +15 -3
- package/dist/types/sdk/lifecycle-session.d.ts +2 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/session.d.ts +16 -0
- package/dist/types/sdk/startup-capability.d.ts +2 -1
- package/dist/types/session/agent-session.d.ts +5 -0
- package/dist/types/session/credential-store-errors.d.ts +1 -0
- package/dist/types/session/session-manager.d.ts +65 -0
- package/dist/types/session/yield-queue.d.ts +5 -4
- package/dist/types/setup/frictionless-onboarding.d.ts +1 -0
- package/dist/types/tools/bash.d.ts +4 -0
- package/dist/types/tools/gh.d.ts +8 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +6 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +35 -1
- package/src/cli/accounts-cli.ts +9 -5
- package/src/cli/args.ts +17 -0
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/root-flags.ts +5 -0
- package/src/cli/update-cli.ts +77 -11
- package/src/commands/launch.ts +86 -18
- package/src/commands/sdk.ts +113 -21
- package/src/config/autorouting-tier-map.ts +12 -0
- package/src/config/file-lock.ts +158 -83
- package/src/config/model-preset-registry.ts +1 -5
- package/src/config/model-profiles.ts +5 -5
- package/src/config/model-registry.ts +23 -0
- package/src/config/model-resolver.ts +5 -0
- package/src/config/settings-schema.ts +8 -1
- package/src/config/settings.ts +5 -0
- package/src/coordinator-mcp/projection-scan.ts +21 -0
- package/src/coordinator-mcp/question-state.ts +9 -11
- package/src/coordinator-mcp/server.ts +94 -20
- package/src/crash/index-store.ts +2 -0
- package/src/crash/record-loader.ts +10 -0
- package/src/gjc-runtime/launch-worktree-reservation.ts +242 -0
- package/src/gjc-runtime/managed-owner-supervisor.ts +63 -51
- package/src/gjc-runtime/session-state-lock.ts +79 -6
- package/src/gjc-runtime/session-state-sidecar.ts +929 -23
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +4 -7
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -2
- package/src/gjc-runtime/tmux-sessions.ts +252 -13
- package/src/hooks/skill-state.ts +6 -0
- package/src/internal-urls/docs-index.generated.ts +7 -7
- package/src/internal-urls/issue-pr-protocol.ts +4 -2
- package/src/main.ts +57 -2
- package/src/master-mode/context.ts +50 -0
- package/src/master-mode/first-request.ts +65 -0
- package/src/master-mode/snapshot.ts +205 -0
- package/src/modes/acp/acp-agent.ts +605 -156
- package/src/modes/components/footer.ts +4 -2
- package/src/modes/components/frictionless-onboarding-selector.ts +48 -2
- package/src/modes/components/oauth-selector.ts +6 -1
- package/src/modes/components/settings-selector.ts +1 -0
- package/src/modes/components/status-line/model-name.ts +53 -0
- package/src/modes/components/status-line/priority-row.ts +107 -0
- package/src/modes/components/status-line/segments.ts +23 -9
- package/src/modes/components/tool-status-header.ts +151 -15
- package/src/modes/controllers/input-controller.ts +28 -0
- package/src/modes/controllers/selector-controller.ts +191 -96
- package/src/modes/print-mode.ts +64 -0
- package/src/modes/ui-language.ts +49 -2
- package/src/prompts/system/master-mode.md +28 -0
- package/src/sdk/broker/broker.ts +1636 -26
- package/src/sdk/broker/endpoint-authority.ts +86 -0
- package/src/sdk/broker/ensure.ts +5 -0
- package/src/sdk/broker/index.ts +3 -0
- package/src/sdk/broker/lifecycle.ts +186 -41
- package/src/sdk/broker/master-capability.ts +232 -0
- package/src/sdk/broker/session-index.ts +121 -17
- package/src/sdk/broker/session-scope.ts +272 -0
- package/src/sdk/broker/spawn-authority.ts +1031 -0
- package/src/sdk/broker/spawn-substrate.ts +548 -0
- package/src/sdk/broker/state-version.ts +26 -14
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/broker/worktree-occupancy.ts +90 -0
- package/src/sdk/bus/chat-daemon-control.ts +5 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +35 -4
- package/src/sdk/bus/index.ts +51 -4
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/master-cli.ts +259 -0
- package/src/sdk/cli/rows.ts +11 -8
- package/src/sdk/cli/session-cli.ts +264 -5
- package/src/sdk/client/client.ts +14 -8
- package/src/sdk/host/control/dispatch.ts +99 -38
- package/src/sdk/host/control/index.ts +2 -0
- package/src/sdk/host/control/operations.ts +2 -0
- package/src/sdk/host/control/runtime-gate.ts +203 -11
- package/src/sdk/host/host.ts +27 -2
- package/src/sdk/host/session-runtime.test.ts +210 -6
- package/src/sdk/host/session-runtime.ts +291 -49
- package/src/sdk/lifecycle/broker-client.ts +28 -0
- package/src/sdk/lifecycle/service.ts +279 -20
- package/src/sdk/lifecycle-session.ts +10 -2
- package/src/sdk/protocol/operation-inventory.generated.json +51 -0
- package/src/sdk/protocol/operation-registry.ts +13 -3
- package/src/sdk/router/session-router.ts +67 -59
- package/src/sdk/session.ts +357 -155
- package/src/sdk/startup-capability.ts +1 -0
- package/src/session/agent-session.ts +640 -103
- package/src/session/blob-store.ts +15 -5
- package/src/session/credential-store-errors.ts +2 -0
- package/src/session/internal/managed-session-storage.ts +153 -78
- package/src/session/session-manager.ts +337 -24
- package/src/session/yield-queue.ts +24 -10
- package/src/setup/frictionless-onboarding.ts +2 -0
- package/src/telemetry/events.ts +1138 -12
- package/src/tools/bash.ts +256 -42
- package/src/tools/gh.ts +104 -48
- package/src/tools/github-cache.ts +2 -2
- package/src/tools/index.ts +4 -0
|
@@ -3,9 +3,11 @@ import * as fs from "node:fs/promises";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { logger, resolveEquivalentPath } from "@gajae-code/utils";
|
|
5
5
|
import {
|
|
6
|
+
canonicalSessionCwd,
|
|
6
7
|
SessionIndex as DefaultSessionIndex,
|
|
7
8
|
type IndexedSession,
|
|
8
9
|
isSessionAuthorityEligible,
|
|
10
|
+
resolveSessionLocator,
|
|
9
11
|
type SessionIndex,
|
|
10
12
|
} from "../broker/session-index";
|
|
11
13
|
import { cancellableSleep, lifecycleRequestTimeoutMs } from "../broker/startup-budget";
|
|
@@ -258,6 +260,8 @@ export type SessionRouterProviderDeps = Pick<
|
|
|
258
260
|
|
|
259
261
|
export interface SessionRouterOptions {
|
|
260
262
|
agentDir: string;
|
|
263
|
+
/** Limits attachment to exact ids selected by a Broker-scoped operation. */
|
|
264
|
+
sessionIds?: readonly string[];
|
|
261
265
|
deps?: SessionRouterDeps;
|
|
262
266
|
/** Runtime-specific identity validation; Router supplies a conservative fallback. */
|
|
263
267
|
correlateFrame?: SessionRouterFrameCorrelator;
|
|
@@ -446,6 +450,10 @@ async function lstatEndpoint(file: string): Promise<SessionEndpointIdentity | un
|
|
|
446
450
|
};
|
|
447
451
|
}
|
|
448
452
|
|
|
453
|
+
function warningAffectsSession(warning: string, sessionId: string): boolean {
|
|
454
|
+
return !warning.startsWith("Session ") || warning.includes(`Session ${sessionId} `);
|
|
455
|
+
}
|
|
456
|
+
|
|
449
457
|
function sameEndpointIdentity(expected: SessionEndpointIdentity, current: SessionEndpointIdentity): boolean {
|
|
450
458
|
return (
|
|
451
459
|
expected.mtimeMs === current.mtimeMs &&
|
|
@@ -565,6 +573,7 @@ type AdoptedSession = {
|
|
|
565
573
|
*/
|
|
566
574
|
export class SessionRouter {
|
|
567
575
|
readonly #agentDir: string;
|
|
576
|
+
readonly #sessionIds: ReadonlySet<string> | undefined;
|
|
568
577
|
readonly #deps: SessionRouterDeps;
|
|
569
578
|
readonly #correlateFrame: SessionRouterFrameCorrelator;
|
|
570
579
|
readonly #index: SessionIndex;
|
|
@@ -603,6 +612,7 @@ export class SessionRouter {
|
|
|
603
612
|
|
|
604
613
|
constructor(options: SessionRouterOptions) {
|
|
605
614
|
this.#agentDir = options.agentDir;
|
|
615
|
+
this.#sessionIds = options.sessionIds === undefined ? undefined : new Set(options.sessionIds);
|
|
606
616
|
this.#deps = options.deps ?? {};
|
|
607
617
|
this.#correlateFrame = options.correlateFrame ?? fallbackCorrelation;
|
|
608
618
|
this.#index = this.#deps.createIndex?.(options.agentDir) ?? new DefaultSessionIndex(options.agentDir);
|
|
@@ -753,11 +763,11 @@ export class SessionRouter {
|
|
|
753
763
|
"pre_send",
|
|
754
764
|
"Broker lifecycle result omitted an exact session endpoint authority.",
|
|
755
765
|
);
|
|
756
|
-
const
|
|
757
|
-
const stateRoot = path.join(
|
|
766
|
+
const cwd = await canonicalSessionCwd(fallback.cwd);
|
|
767
|
+
const stateRoot = path.join(cwd, ".gjc", "state");
|
|
758
768
|
const indexed: IndexedSession = {
|
|
759
769
|
sessionId,
|
|
760
|
-
locator:
|
|
770
|
+
locator: await resolveSessionLocator(cwd, stateRoot),
|
|
761
771
|
endpointGeneration,
|
|
762
772
|
pid,
|
|
763
773
|
endpointMtimeMs,
|
|
@@ -780,8 +790,9 @@ export class SessionRouter {
|
|
|
780
790
|
if (!attached || !current || !capability)
|
|
781
791
|
throw new SessionRouterError("pre_send", "Broker session endpoint could not be attached.");
|
|
782
792
|
const listing = this.#index.listSessions();
|
|
783
|
-
const indexedCurrent =
|
|
784
|
-
|
|
793
|
+
const indexedCurrent = listing.warnings.some(warning => warningAffectsSession(warning, sessionId))
|
|
794
|
+
? undefined
|
|
795
|
+
: listing.sessions.find(item => item.sessionId === sessionId);
|
|
785
796
|
if (indexedCurrent && sameIndexedAuthority(indexed, indexedCurrent))
|
|
786
797
|
await this.#serialReconcile(this.#runEpoch, true, true);
|
|
787
798
|
return capability;
|
|
@@ -953,7 +964,7 @@ export class SessionRouter {
|
|
|
953
964
|
try {
|
|
954
965
|
await this.#index.refresh();
|
|
955
966
|
const listing = this.#index.listSessions();
|
|
956
|
-
if (listing.warnings.
|
|
967
|
+
if (listing.warnings.some(warning => warningAffectsSession(warning, sessionId))) return undefined;
|
|
957
968
|
indexed = listing.sessions.find(candidate => candidate.sessionId === sessionId);
|
|
958
969
|
} catch {
|
|
959
970
|
return undefined;
|
|
@@ -1025,7 +1036,7 @@ export class SessionRouter {
|
|
|
1025
1036
|
await this.#index.open();
|
|
1026
1037
|
await this.#index.refresh();
|
|
1027
1038
|
const listing = this.#index.listSessions();
|
|
1028
|
-
if (listing.warnings.
|
|
1039
|
+
if (listing.warnings.some(warning => warningAffectsSession(warning, sessionId)))
|
|
1029
1040
|
throw new SessionActivationError(
|
|
1030
1041
|
"session_not_live",
|
|
1031
1042
|
"Session activation requires an intact session index.",
|
|
@@ -1203,50 +1214,51 @@ export class SessionRouter {
|
|
|
1203
1214
|
return;
|
|
1204
1215
|
}
|
|
1205
1216
|
const indexed = this.#index.listSessions();
|
|
1206
|
-
const live =
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1217
|
+
const live = indexed.sessions.filter(
|
|
1218
|
+
session =>
|
|
1219
|
+
!indexed.warnings.some(warning => warningAffectsSession(warning, session.sessionId)) &&
|
|
1220
|
+
session.live &&
|
|
1221
|
+
isSessionAuthorityEligible(session) &&
|
|
1222
|
+
!session.terminalUncertain &&
|
|
1223
|
+
(this.#sessionIds === undefined || this.#sessionIds.has(session.sessionId)),
|
|
1224
|
+
);
|
|
1212
1225
|
const liveIds = new Set(live.map(session => session.sessionId));
|
|
1213
1226
|
const attachedIds = new Set<string>();
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
this.#adopted.delete(sessionId);
|
|
1244
|
-
attachedIds.add(sessionId);
|
|
1245
|
-
}
|
|
1246
|
-
} catch {
|
|
1227
|
+
for (const [sessionId, adopted] of [...this.#adopted]) {
|
|
1228
|
+
if (indexed.warnings.some(warning => warningAffectsSession(warning, sessionId))) continue;
|
|
1229
|
+
const attached = this.#sessions.get(sessionId);
|
|
1230
|
+
const indexedSession = indexed.sessions.find(session => session.sessionId === sessionId);
|
|
1231
|
+
if (!attached || attached.capability !== adopted.attachment) {
|
|
1232
|
+
this.#adopted.delete(sessionId);
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1235
|
+
const exactIndex =
|
|
1236
|
+
indexedSession?.live === true &&
|
|
1237
|
+
isSessionAuthorityEligible(indexedSession) &&
|
|
1238
|
+
!indexedSession.terminalUncertain &&
|
|
1239
|
+
indexedSession.endpointGeneration === adopted.generation &&
|
|
1240
|
+
indexedSession.pid === adopted.pid &&
|
|
1241
|
+
indexedSession.endpointMtimeMs === adopted.endpointMtimeMs;
|
|
1242
|
+
const endpoint = exactIndex ? await this.#readEndpoint(indexedSession).catch(() => null) : null;
|
|
1243
|
+
if (
|
|
1244
|
+
!exactIndex ||
|
|
1245
|
+
!endpoint ||
|
|
1246
|
+
endpoint.pid !== adopted.pid ||
|
|
1247
|
+
endpoint.url !== attached.endpoint.url ||
|
|
1248
|
+
endpoint.token !== attached.endpoint.token
|
|
1249
|
+
) {
|
|
1250
|
+
this.#adopted.delete(sessionId);
|
|
1251
|
+
await this.#retireAttachment(attached);
|
|
1252
|
+
continue;
|
|
1253
|
+
}
|
|
1254
|
+
try {
|
|
1255
|
+
if (await this.#publishAttachment(attached, true)) {
|
|
1247
1256
|
this.#adopted.delete(sessionId);
|
|
1248
|
-
|
|
1257
|
+
attachedIds.add(sessionId);
|
|
1249
1258
|
}
|
|
1259
|
+
} catch {
|
|
1260
|
+
this.#adopted.delete(sessionId);
|
|
1261
|
+
await this.#retireAttachment(attached);
|
|
1250
1262
|
}
|
|
1251
1263
|
}
|
|
1252
1264
|
let nextAttachment = 0;
|
|
@@ -1361,15 +1373,11 @@ export class SessionRouter {
|
|
|
1361
1373
|
indexed: IndexedSession,
|
|
1362
1374
|
): Promise<{ endpoint: SdkSessionEndpoint; identity: SessionEndpointIdentity } | null> {
|
|
1363
1375
|
if (!isSessionAuthorityEligible(indexed)) return null;
|
|
1364
|
-
const
|
|
1365
|
-
const defaultStateRoot = path.join(
|
|
1366
|
-
//
|
|
1367
|
-
//
|
|
1368
|
-
//
|
|
1369
|
-
// The scope test therefore compares path identity, not spelling: a lexical
|
|
1370
|
-
// match fails for every symlinked cwd (macOS /var -> /private/var,
|
|
1371
|
-
// /home/jun/desk -> /data/Lina-Desk), the adopted attachment is retired on
|
|
1372
|
-
// reconcile, and session/new surfaces "lost exact Router authority".
|
|
1376
|
+
const cwd = indexed.locator.cwd;
|
|
1377
|
+
const defaultStateRoot = path.join(cwd, ".gjc", "state");
|
|
1378
|
+
// Locator cwd is already canonical. `stateRoot` remains the host-provided
|
|
1379
|
+
// authority path, so this comparison resolves equivalent paths only for the
|
|
1380
|
+
// state-root identity boundary; cwd never retains lexical symlink spellings.
|
|
1373
1381
|
const indexedStateRoot = resolveEquivalentPath(indexed.locator.stateRoot);
|
|
1374
1382
|
const scope =
|
|
1375
1383
|
indexedStateRoot === resolveEquivalentPath(defaultStateRoot)
|
|
@@ -1378,9 +1386,9 @@ export class SessionRouter {
|
|
|
1378
1386
|
? "chat"
|
|
1379
1387
|
: undefined;
|
|
1380
1388
|
if (!scope || indexed.endpointMtimeMs === undefined || !Number.isFinite(indexed.endpointMtimeMs)) return null;
|
|
1381
|
-
const endpointPath = path.join(endpointDirectory(
|
|
1389
|
+
const endpointPath = path.join(endpointDirectory(cwd, scope), `${indexed.sessionId}.json`);
|
|
1382
1390
|
const endpointIdentity = await lstatEndpoint(endpointPath);
|
|
1383
|
-
const endpoint = await readSdkSessionEndpoint(
|
|
1391
|
+
const endpoint = await readSdkSessionEndpoint(cwd, indexed.sessionId, scope);
|
|
1384
1392
|
if (!endpoint || endpoint.stale || endpoint.pid !== indexed.pid) return null;
|
|
1385
1393
|
if (!endpointIdentity || endpointIdentity.mtimeMs !== indexed.endpointMtimeMs) return null;
|
|
1386
1394
|
// Identity is proven INSIDE this authority read (#4730 review): sampling it
|
|
@@ -1413,7 +1421,7 @@ export class SessionRouter {
|
|
|
1413
1421
|
return null;
|
|
1414
1422
|
await this.#index.refresh();
|
|
1415
1423
|
const listing = this.#index.listSessions();
|
|
1416
|
-
if (listing.warnings.
|
|
1424
|
+
if (listing.warnings.some(warning => warningAffectsSession(warning, indexed.sessionId))) return null;
|
|
1417
1425
|
const current = listing.sessions.find(session => session.sessionId === indexed.sessionId);
|
|
1418
1426
|
if (!current || !sameIndexedAuthority(indexed, current)) return null;
|
|
1419
1427
|
return { endpoint, identity: provenIdentity };
|