@gajae-code/coding-agent 0.12.4 → 0.12.5
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 +4 -0
- package/dist/types/async/job-manager.d.ts +9 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -2
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +5 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +3 -22
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/task/executor.d.ts +1 -1
- package/dist/types/task/index.d.ts +2 -1
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +16 -0
- package/dist/types/task/worktree.d.ts +13 -6
- package/dist/types/tools/subagent.d.ts +2 -0
- package/dist/types/utils/git.d.ts +1 -0
- package/package.json +8 -8
- package/src/async/job-manager.ts +13 -5
- package/src/internal-urls/docs-index.generated.ts +1 -1
- package/src/sdk/broker/lifecycle.ts +13 -18
- package/src/sdk/bus/chat-daemon-control.ts +6 -4
- package/src/sdk/bus/telegram-daemon-contract.ts +5 -3
- package/src/sdk/session.ts +1 -0
- package/src/session/internal/managed-session-scope.ts +107 -158
- package/src/session/internal/managed-session-storage.ts +57 -445
- package/src/session/session-manager.ts +12 -7
- package/src/session/session-storage.ts +44 -29
- package/src/task/executor.ts +5 -2
- package/src/task/index.ts +232 -64
- package/src/task/receipt.ts +22 -2
- package/src/task/render.ts +12 -1
- package/src/task/types.ts +18 -0
- package/src/task/worktree.ts +122 -43
- package/src/tools/subagent-render.ts +5 -2
- package/src/tools/subagent.ts +8 -0
- package/src/utils/git.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.12.5] - 2026-07-30
|
|
6
|
+
|
|
5
7
|
## [0.12.4] - 2026-07-30
|
|
6
8
|
|
|
7
9
|
## [0.12.3] - 2026-07-30
|
|
@@ -30,6 +32,7 @@
|
|
|
30
32
|
- `gjc --worktree` / `gjc -w` launch no longer crashes with a raw uncaught `EEXIST` when the worktree bucket directory (`<repo>.gajae-code-worktrees`) is a broken symbolic link to unmounted or offloaded cold storage. The launch distinguishes dangling links and non-directory entries from valid directory symlinks or Windows junctions, reclassifies mkdir races, avoids disclosing raw link targets or unsafe shell commands, and never deletes or replaces an obstructing entry.
|
|
31
33
|
- POSIX parent identity reproof/fsync is now centralized before every promotable artifact-phase result, preventing a crash-window where a rename is lost after durable retirement is recorded (#3489).
|
|
32
34
|
- Artifact retirement, planned paths, retained authority, and transcript retry in both managed reconciliation and deletion now bind to the newest published `pendingEvidence` attempt, preventing stranded detached transcripts at paths absent from the newest receipt after a crash (#3489).
|
|
35
|
+
- Provider retry classification prefers the typed `stream_first_event_timeout` transport fact when present, falling back to error-message regex for message-only callers (#3496).
|
|
33
36
|
- Detached task receipts for in-memory parent sessions no longer advertise dead `agent://` output URIs. TaskTool allocates a session-lifetime durable artifact root under the process temp directory, persists child outputs there, authorizes parent and same-session descendants for scoped resolution, and omits the URI entirely when durable allocation fails (#3471).
|
|
34
37
|
- Managed-session replacement and cleanup now bind Windows destination mutation to exact native identity, keep lock acquisition/release retryable without reviving lost ownership, and report retained artifact payloads as `cleanup_pending` until only the verified root remains.
|
|
35
38
|
- Resuming a session no longer crashes with an unhandled rejection when another session transition is already running. The session picker dispatches resume through a void-returning callback, and `handleResumeSession` had no re-entrancy guard, so a second selection (or a resume issued while compaction, handoff, or a fork was in flight) reached `switchSession` and the `{ code: "busy" }` transition error rejected a promise nobody awaited. Resume now ignores an overlapping request with a status message, reports a busy transition as status, and still propagates every other failure. The progress lease is released on all paths.
|
|
@@ -53,6 +56,7 @@
|
|
|
53
56
|
### Added
|
|
54
57
|
|
|
55
58
|
- User-created Telegram forum topics can now start a GJC session by selecting the home folder, choosing a verified recent work folder, or entering an explicit folder path. The selected topic is adopted by the new session without creating or deleting a separate Telegram topic.
|
|
59
|
+
- The interactive terminal’s responsive IRC/todo work-lane contract now covers exact narrow/wide geometry, requested versus effective IRC visibility, direct-root pin ordering, todo lane bounds, remapped IRC toggles, and live composer shortcut hints.
|
|
56
60
|
|
|
57
61
|
### Fixed
|
|
58
62
|
|
|
@@ -134,6 +134,8 @@ export interface SubagentRecord {
|
|
|
134
134
|
effectiveModel?: string;
|
|
135
135
|
/** True when the requested model lacked credentials and the subagent fell back to the parent model. */
|
|
136
136
|
modelFellBack?: boolean;
|
|
137
|
+
/** True when the effective subagent provider is in fast mode. */
|
|
138
|
+
fastMode?: boolean;
|
|
137
139
|
}
|
|
138
140
|
/** Lightweight, manager-owned resume payload. The async layer treats `data` as opaque. */
|
|
139
141
|
export interface ResumeDescriptor {
|
|
@@ -251,11 +253,17 @@ export declare class AsyncJobManager {
|
|
|
251
253
|
};
|
|
252
254
|
/** Register or replace the canonical record for a subagent. */
|
|
253
255
|
registerSubagentRecord(record: SubagentRecord): void;
|
|
254
|
-
/**
|
|
256
|
+
/**
|
|
257
|
+
* Patch model/runtime metadata onto an existing subagent record (best-effort; no-op if
|
|
258
|
+
* unknown). Every field is optional and omitting one preserves its current value, so a
|
|
259
|
+
* narrow patch like `{ fastMode: true }` cannot erase model identity recorded earlier.
|
|
260
|
+
* A field therefore cannot be cleared back to `undefined` through this method.
|
|
261
|
+
*/
|
|
255
262
|
updateSubagentModel(subagentId: string, model: {
|
|
256
263
|
requestedModel?: string;
|
|
257
264
|
effectiveModel?: string;
|
|
258
265
|
modelFellBack?: boolean;
|
|
266
|
+
fastMode?: boolean;
|
|
259
267
|
}): void;
|
|
260
268
|
getSubagentRecord(subagentId: string, filter?: AsyncJobFilter): SubagentRecord | undefined;
|
|
261
269
|
getSubagentRecords(filter?: AsyncJobFilter): SubagentRecord[];
|
|
@@ -19,8 +19,10 @@ export type ChatDaemonAction = "stop" | "reload";
|
|
|
19
19
|
* chat daemons after notification configuration parsing changes. Generation 15
|
|
20
20
|
* applies the current notification configuration directly when starting chat
|
|
21
21
|
* daemon transports. Generation 16 applies Telegram sound-policy configuration
|
|
22
|
-
* through shared notification parsing. Generation 17
|
|
23
|
-
* replacement to exact native filesystem authority
|
|
22
|
+
* through shared notification parsing. Generation 17 bound managed-session
|
|
23
|
+
* replacement to exact native filesystem authority; generation 18 retires that
|
|
24
|
+
* binding (revert of #3489, which stalled POSIX artifact cleanup) while keeping
|
|
25
|
+
* the lifecycle contract moving strictly forward.
|
|
24
26
|
*/
|
|
25
27
|
export declare const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>>;
|
|
26
28
|
export declare function chatDaemonGeneration(kind: ChatDaemonKind): number;
|
|
@@ -44,10 +44,12 @@ export declare const NOTIFICATION_PROTOCOL_VERSION = 3;
|
|
|
44
44
|
* 33 adds action-bound multi-select state rendering and replay-safe option
|
|
45
45
|
* snapshots. Generation 34 converts non-photo image formats (including WebP)
|
|
46
46
|
* into Telegram-compatible photo uploads when possible. Generation 35 adds
|
|
47
|
-
* user-created topic adoption (forum-topic folder picker). Generation 36
|
|
48
|
-
* managed-session replacement to exact native filesystem authority
|
|
47
|
+
* user-created topic adoption (forum-topic folder picker). Generation 36 bound
|
|
48
|
+
* managed-session replacement to exact native filesystem authority; generation
|
|
49
|
+
* 37 retires that binding (revert of #3489, which stalled POSIX artifact
|
|
50
|
+
* cleanup) while keeping the lifecycle contract moving strictly forward.
|
|
49
51
|
*/
|
|
50
|
-
export declare const DAEMON_GENERATION =
|
|
52
|
+
export declare const DAEMON_GENERATION = 37;
|
|
51
53
|
/**
|
|
52
54
|
* Serving-compatibility boundary for daemon lifecycle requests. Epoch 1 covers
|
|
53
55
|
* all builds published before this field existed; epoch 2 covered generation 29;
|
|
@@ -7,7 +7,6 @@ export declare const MANAGED_ARTIFACT_MAX_TOTAL_BYTES: number;
|
|
|
7
7
|
export declare const MANAGED_ARTIFACT_COPY_BATCH_SIZE = 256;
|
|
8
8
|
export declare class ManagedPublishError extends Error {
|
|
9
9
|
readonly classification: "destination_conflict" | "atomic_unavailable" | "invalid_request" | "durability_not_provable" | "identity_mismatch" | "io_error" | "durability_failed";
|
|
10
|
-
readonly code: ManagedPublishError["classification"];
|
|
11
10
|
readonly diagnostic: string;
|
|
12
11
|
constructor(classification: ManagedPublishError["classification"], outcome: NativePublishOutcome);
|
|
13
12
|
}
|
|
@@ -21,12 +20,6 @@ export interface ManagedStorageLock {
|
|
|
21
20
|
assertOwned(): void;
|
|
22
21
|
release(): Promise<void>;
|
|
23
22
|
}
|
|
24
|
-
export interface ManagedStorageLockSync {
|
|
25
|
-
path: string;
|
|
26
|
-
attemptId: string;
|
|
27
|
-
assertOwned(): void;
|
|
28
|
-
release(): void;
|
|
29
|
-
}
|
|
30
23
|
export interface ManagedFileSnapshot {
|
|
31
24
|
bytes: Buffer;
|
|
32
25
|
identity: {
|
|
@@ -38,13 +31,6 @@ export interface ManagedFileSnapshot {
|
|
|
38
31
|
sha256: string;
|
|
39
32
|
};
|
|
40
33
|
}
|
|
41
|
-
export declare const MANAGED_SESSION_SECURITY_CODES: readonly ["acl_denied", "acl_io_error", "acl_present", "acl_malformed", "acl_unknown", "acl_unavailable", "acl_apply_failed", "acl_verify_failed", "not_found", "not_directory", "network_unsupported", "reparse_point", "identity_unavailable", "identity_mismatch", "owner_mismatch", "mode_mismatch", "io_error"];
|
|
42
|
-
export type ManagedSessionSecurityCode = (typeof MANAGED_SESSION_SECURITY_CODES)[number];
|
|
43
|
-
export declare class ManagedSessionSecurityError extends Error {
|
|
44
|
-
readonly code: ManagedSessionSecurityCode;
|
|
45
|
-
constructor(code: ManagedSessionSecurityCode);
|
|
46
|
-
}
|
|
47
|
-
export declare function managedSessionSecurityCode(error: unknown): ManagedSessionSecurityCode | undefined;
|
|
48
34
|
export declare function validateNativeSecurityResult(value: unknown, operation: "apply" | "verify", kind: "directory" | "file"): NativeOwnerOnlySecurityResult;
|
|
49
35
|
/** Captured configured-root authority for managed paths only. */
|
|
50
36
|
export interface ManagedDirectoryRoot {
|
|
@@ -119,18 +105,13 @@ export declare function captureManagedFileNoFollow(pathname: string): ManagedFil
|
|
|
119
105
|
/** Atomically publishes bytes without replacing an existing destination. */
|
|
120
106
|
export declare function publishManagedFileNoReplace(destination: string, bytes: Uint8Array, assertOwned?: () => void, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): Promise<void>;
|
|
121
107
|
export declare function publishManagedFileNoReplaceSync(destination: string, bytes: Uint8Array, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): void;
|
|
122
|
-
/**
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* an unconditional pathname rename.
|
|
126
|
-
*/
|
|
127
|
-
export declare function replaceManagedFileExactSync(destination: string, bytes: Uint8Array, expected: Pick<ManagedFileSnapshot, "identity">, root: ManagedDirectoryRoot): void;
|
|
108
|
+
/** Replace one managed regular file while retaining the secured staging fd through publication. */
|
|
109
|
+
export declare function replaceManagedFileSync(destination: string, bytes: Uint8Array, root: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): void;
|
|
110
|
+
export declare function replaceManagedFile(destination: string, bytes: Uint8Array, root: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): Promise<void>;
|
|
128
111
|
/** Copy the exact bytes captured from one no-follow source descriptor. */
|
|
129
112
|
export declare function copyManagedFileNoReplace(source: string, destination: string, snapshot?: ManagedFileSnapshot, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): Promise<void>;
|
|
130
113
|
/** Acquire a lease lock with bounded wait, heartbeats, conservative stale reclaim, and fencing. */
|
|
131
114
|
export declare function acquireManagedLock(locksDirectory: string, name: string, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): Promise<ManagedStorageLock>;
|
|
132
|
-
/** Acquire a synchronous lease lock for a short cross-process critical section. */
|
|
133
|
-
export declare function acquireManagedLockSync(locksDirectory: string, name: string, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): ManagedStorageLockSync;
|
|
134
115
|
export interface ManagedArtifactTreeLimits {
|
|
135
116
|
maxFiles?: number;
|
|
136
117
|
maxTotalBytes?: number;
|
|
@@ -986,7 +986,7 @@ export declare class SessionManager {
|
|
|
986
986
|
* @param sessionDir Optional session directory for /new or /branch. If omitted, derives from file's parent.
|
|
987
987
|
*/
|
|
988
988
|
static open(filePath: string, destinationInput?: SessionDestinationInput, storage?: SessionStorage, migrationPolicy?: SessionDirectoryMigrationPolicy): Promise<SessionManager>;
|
|
989
|
-
static openNestedManaged(filePath: string, destination: SessionDestination, store: ManagedSessionDescendantStore, storage?: SessionStorage): Promise<SessionManager>;
|
|
989
|
+
static openNestedManaged(filePath: string, destination: SessionDestination, store: ManagedSessionDescendantStore, storage?: SessionStorage, cwdOverride?: string): Promise<SessionManager>;
|
|
990
990
|
/**
|
|
991
991
|
* List default-managed sessions for the resume picker without recovery or other
|
|
992
992
|
* maintenance writes. This is the only picker inventory that includes legacy
|
|
@@ -107,7 +107,7 @@ export interface ExecutorOptions {
|
|
|
107
107
|
export declare class ManagedTaskPersistence {
|
|
108
108
|
#private;
|
|
109
109
|
constructor(artifacts: ArtifactManager, taskId: string);
|
|
110
|
-
openSession(): Promise<SessionManager>;
|
|
110
|
+
openSession(cwd: string): Promise<SessionManager>;
|
|
111
111
|
publishOutput(rawOutput: string, metadata: Uint8Array): Promise<void>;
|
|
112
112
|
}
|
|
113
113
|
export declare function createManagedTaskPersistence(artifacts: ArtifactManager, taskId: string): ManagedTaskPersistence;
|
|
@@ -5,8 +5,9 @@ import { type SubagentRunOutcome } from "../async";
|
|
|
5
5
|
import type { Theme } from "../modes/theme/theme";
|
|
6
6
|
import { type SingleResult, type TaskToolDetails, type TaskToolSchemaInstance } from "./types";
|
|
7
7
|
import "../tools/review";
|
|
8
|
+
import { type TaskResultReceipt } from "./receipt";
|
|
8
9
|
import { renderResult, renderCall as renderTaskCall } from "./render";
|
|
9
|
-
export declare function subagentRunOutcomeFromSingleResult(finalText: string, singleResult: Pick<SingleResult, "aborted" | "exitCode" | "paused" | "setupFailure"> | undefined): string | SubagentRunOutcome;
|
|
10
|
+
export declare function subagentRunOutcomeFromSingleResult(finalText: string, singleResult: (Pick<SingleResult, "aborted" | "exitCode" | "paused" | "setupFailure"> & Partial<Pick<TaskResultReceipt, "status">>) | undefined): string | SubagentRunOutcome;
|
|
10
11
|
export { loadBundledAgents as BUNDLED_AGENTS } from "./agents";
|
|
11
12
|
export { discoverCommands, expandCommand, getCommand } from "./commands";
|
|
12
13
|
export { discoverAgents, getAgent } from "./discovery";
|
|
@@ -495,6 +495,18 @@ export interface SetupFailureSummary {
|
|
|
495
495
|
}
|
|
496
496
|
/** Create a bounded diagnostic that preserves a setup failure's cause without exposing credentials or local paths. */
|
|
497
497
|
export declare function createSetupFailureSummary(error: unknown): SetupFailureSummary;
|
|
498
|
+
export interface TaskRecoveryArtifactRef {
|
|
499
|
+
uri: string;
|
|
500
|
+
sizeBytes: number;
|
|
501
|
+
sha256: string;
|
|
502
|
+
/** Recovery artifacts remain readable for the parent session lifetime. */
|
|
503
|
+
durability: "session";
|
|
504
|
+
}
|
|
505
|
+
export interface TaskPersistenceResult {
|
|
506
|
+
outcome: "applied" | "no_changes" | "recovery_available";
|
|
507
|
+
ownerWorktreeApplied: boolean;
|
|
508
|
+
recoveryRef?: TaskRecoveryArtifactRef;
|
|
509
|
+
}
|
|
498
510
|
/** Result from a single agent execution */
|
|
499
511
|
export interface SingleResult {
|
|
500
512
|
index: number;
|
|
@@ -540,6 +552,10 @@ export interface SingleResult {
|
|
|
540
552
|
nestedPatches?: NestedRepoPatch[];
|
|
541
553
|
/** Whether isolated execution produced a non-empty root or nested patch. */
|
|
542
554
|
producedChanges?: boolean;
|
|
555
|
+
/** Receipt-safe owner-worktree persistence result for isolated execution. */
|
|
556
|
+
persistence?: TaskPersistenceResult;
|
|
557
|
+
/** Identity-bound patch artifact captured before isolation cleanup. */
|
|
558
|
+
recoveryRef?: TaskRecoveryArtifactRef;
|
|
543
559
|
/** Data extracted by registered subprocess tool handlers (keyed by tool name) */
|
|
544
560
|
extractedToolData?: Record<string, unknown[]>;
|
|
545
561
|
/** Full wrapper-owned review evidence, kept separate from caller completion data. */
|
|
@@ -22,6 +22,8 @@ export interface WorktreeBaseline {
|
|
|
22
22
|
export declare function getRepoRoot(cwd: string): Promise<string>;
|
|
23
23
|
export declare function getGitNoIndexNullPath(): string;
|
|
24
24
|
export declare function captureBaseline(repoRoot: string): Promise<WorktreeBaseline>;
|
|
25
|
+
/** Confirm that applying patches to the captured owner baseline exactly matches the current owner worktree. */
|
|
26
|
+
export declare function verifyRootPatchesApplied(repoRoot: string, baseline: WorktreeBaseline, patches: readonly string[]): Promise<boolean>;
|
|
25
27
|
export interface NestedRepoPatch {
|
|
26
28
|
relativePath: string;
|
|
27
29
|
patch: string;
|
|
@@ -29,14 +31,19 @@ export interface NestedRepoPatch {
|
|
|
29
31
|
export interface DeltaPatchResult {
|
|
30
32
|
rootPatch: string;
|
|
31
33
|
nestedPatches: NestedRepoPatch[];
|
|
34
|
+
captureErrors?: string[];
|
|
32
35
|
}
|
|
36
|
+
export interface RecoveryPatchBundle {
|
|
37
|
+
version: 1;
|
|
38
|
+
rootPatch: string;
|
|
39
|
+
nestedPatches: NestedRepoPatch[];
|
|
40
|
+
captureErrors?: string[];
|
|
41
|
+
}
|
|
42
|
+
export declare function serializeRecoveryPatchBundle(delta: DeltaPatchResult): string;
|
|
43
|
+
export declare function verifyNestedPatchesApplied(repoRoot: string, baseline: WorktreeBaseline, patches: readonly NestedRepoPatch[]): Promise<boolean>;
|
|
33
44
|
export declare function captureDeltaPatch(isolationDir: string, baseline: WorktreeBaseline): Promise<DeltaPatchResult>;
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
* @param commitMessage Optional async function to generate a commit message from the combined diff.
|
|
37
|
-
* If omitted or returns null, falls back to a generic message.
|
|
38
|
-
*/
|
|
39
|
-
export declare function applyNestedPatches(repoRoot: string, patches: NestedRepoPatch[], commitMessage?: (diff: string) => Promise<string | null>): Promise<void>;
|
|
45
|
+
/** Preflight every nested delta, then roll back earlier repositories if a later apply fails. */
|
|
46
|
+
export declare function applyNestedPatches(repoRoot: string, patches: NestedRepoPatch[]): Promise<void>;
|
|
40
47
|
/**
|
|
41
48
|
* User-facing isolation mode names exposed by the `task.isolation.mode`
|
|
42
49
|
* setting. Mapped to a backend-kind hint via {@link parseIsolationMode};
|
|
@@ -57,6 +57,8 @@ export interface SubagentSnapshot {
|
|
|
57
57
|
requestedModel?: string;
|
|
58
58
|
/** True when the requested model lacked credentials and fell back to the parent model. */
|
|
59
59
|
modelFellBack?: boolean;
|
|
60
|
+
/** True when the effective subagent provider is in fast mode. */
|
|
61
|
+
fastMode?: boolean;
|
|
60
62
|
}
|
|
61
63
|
export type SubagentAwaitOutcome = "completed" | "timed_out" | "interrupted";
|
|
62
64
|
export interface SubagentToolDetails {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/coding-agent",
|
|
4
|
-
"version": "0.12.
|
|
4
|
+
"version": "0.12.5",
|
|
5
5
|
"description": "Gajae Code CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
54
54
|
"@babel/parser": "^7.29.3",
|
|
55
55
|
"@mozilla/readability": "^0.6.0",
|
|
56
|
-
"@gajae-code/stats": "0.12.
|
|
57
|
-
"@gajae-code/agent-core": "0.12.
|
|
58
|
-
"@gajae-code/ai": "0.12.
|
|
59
|
-
"@gajae-code/bridge-client": "0.12.
|
|
60
|
-
"@gajae-code/natives": "0.12.
|
|
61
|
-
"@gajae-code/tui": "0.12.
|
|
62
|
-
"@gajae-code/utils": "0.12.
|
|
56
|
+
"@gajae-code/stats": "0.12.5",
|
|
57
|
+
"@gajae-code/agent-core": "0.12.5",
|
|
58
|
+
"@gajae-code/ai": "0.12.5",
|
|
59
|
+
"@gajae-code/bridge-client": "0.12.5",
|
|
60
|
+
"@gajae-code/natives": "0.12.5",
|
|
61
|
+
"@gajae-code/tui": "0.12.5",
|
|
62
|
+
"@gajae-code/utils": "0.12.5",
|
|
63
63
|
"@puppeteer/browsers": "^2.13.0",
|
|
64
64
|
"@types/turndown": "5.0.6",
|
|
65
65
|
"@xterm/headless": "^6.0.0",
|
package/src/async/job-manager.ts
CHANGED
|
@@ -164,6 +164,8 @@ export interface SubagentRecord {
|
|
|
164
164
|
effectiveModel?: string;
|
|
165
165
|
/** True when the requested model lacked credentials and the subagent fell back to the parent model. */
|
|
166
166
|
modelFellBack?: boolean;
|
|
167
|
+
/** True when the effective subagent provider is in fast mode. */
|
|
168
|
+
fastMode?: boolean;
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
/** Lightweight, manager-owned resume payload. The async layer treats `data` as opaque. */
|
|
@@ -702,16 +704,22 @@ export class AsyncJobManager {
|
|
|
702
704
|
this.#notifyChange();
|
|
703
705
|
}
|
|
704
706
|
|
|
705
|
-
/**
|
|
707
|
+
/**
|
|
708
|
+
* Patch model/runtime metadata onto an existing subagent record (best-effort; no-op if
|
|
709
|
+
* unknown). Every field is optional and omitting one preserves its current value, so a
|
|
710
|
+
* narrow patch like `{ fastMode: true }` cannot erase model identity recorded earlier.
|
|
711
|
+
* A field therefore cannot be cleared back to `undefined` through this method.
|
|
712
|
+
*/
|
|
706
713
|
updateSubagentModel(
|
|
707
714
|
subagentId: string,
|
|
708
|
-
model: { requestedModel?: string; effectiveModel?: string; modelFellBack?: boolean },
|
|
715
|
+
model: { requestedModel?: string; effectiveModel?: string; modelFellBack?: boolean; fastMode?: boolean },
|
|
709
716
|
): void {
|
|
710
717
|
const record = this.#subagentRecords.get(subagentId);
|
|
711
718
|
if (!record) return;
|
|
712
|
-
record.requestedModel = model.requestedModel;
|
|
713
|
-
record.effectiveModel = model.effectiveModel;
|
|
714
|
-
record.modelFellBack = model.modelFellBack;
|
|
719
|
+
record.requestedModel = model.requestedModel ?? record.requestedModel;
|
|
720
|
+
record.effectiveModel = model.effectiveModel ?? record.effectiveModel;
|
|
721
|
+
record.modelFellBack = model.modelFellBack ?? record.modelFellBack;
|
|
722
|
+
record.fastMode = model.fastMode ?? record.fastMode;
|
|
715
723
|
}
|
|
716
724
|
|
|
717
725
|
#recordFromResumeDescriptor(subagentId: string, filter?: AsyncJobFilter): SubagentRecord | undefined {
|