@agentclientprotocol/claude-agent-acp 0.90.1-preview.8 → 0.91.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/README.md +14 -5
- package/dist/acp-agent.d.ts +91 -11
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +264 -80
- package/dist/air-extension.d.ts +6 -0
- package/dist/air-extension.d.ts.map +1 -1
- package/dist/air-extension.js +6 -0
- package/dist/gateway-models.d.ts +62 -0
- package/dist/gateway-models.d.ts.map +1 -0
- package/dist/gateway-models.js +180 -0
- package/dist/native-subagents.d.ts +34 -9
- package/dist/native-subagents.d.ts.map +1 -1
- package/dist/native-subagents.js +55 -11
- package/dist/session-index/connection.d.ts +4 -3
- package/dist/session-index/connection.d.ts.map +1 -1
- package/dist/session-index/connection.js +8 -7
- package/dist/session-index/list-subscriptions.d.ts.map +1 -1
- package/dist/session-index/list-subscriptions.js +4 -1
- package/dist/session-index/service.d.ts +10 -0
- package/dist/session-index/service.d.ts.map +1 -1
- package/dist/session-index/service.js +21 -0
- package/dist/session-index/session-index.d.ts +10 -2
- package/dist/session-index/session-index.d.ts.map +1 -1
- package/dist/session-index/session-index.js +21 -5
- package/dist/session-index/session-info.d.ts.map +1 -1
- package/dist/session-index/session-info.js +1 -0
- package/dist/session-index/transcript-scan.d.ts +25 -1
- package/dist/session-index/transcript-scan.d.ts.map +1 -1
- package/dist/session-index/transcript-scan.js +57 -1
- package/dist/session-index/worktrees.d.ts +6 -0
- package/dist/session-index/worktrees.d.ts.map +1 -1
- package/dist/session-index/worktrees.js +12 -0
- package/dist/session-model.d.ts +21 -1
- package/dist/session-model.d.ts.map +1 -1
- package/dist/session-model.js +89 -11
- package/dist/turn-events.d.ts +5 -1
- package/dist/turn-events.d.ts.map +1 -1
- package/dist/v2/prompt.d.ts +2 -1
- package/dist/v2/prompt.d.ts.map +1 -1
- package/dist/v2/prompt.js +2 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/session-index/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAQrD,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAiBzD,OAAO,EAKL,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAG5B,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AACvD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAO7D,MAAM,MAAM,gBAAgB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,oBAAoB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAE/D;AAQD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAMtE;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAM9E;AAED,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1F,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AA0BF,oDAAoD;AACpD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,CAgB3D;AAWD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAU7E;AAED;+CAC+C;AAC/C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CA0B7E;AAQD;;;uEAGuE;AACvE,wBAAsB,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBAgBlF;AA0FD;sEACsE;AACtE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAEjG;6DAC6D;AAC7D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAGnD;AAED;8EAC8E;AAC9E,wBAAgB,SAAS,CAAC,QAAQ,EAAE,OAAO,GAAG,WAAW,CAKxD;AA+CD;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG;IAC3B;;;yCAGqC;IACrC,IAAI,CAAC,EAAE;QACL,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,8DAA8D;QAC9D,MAAM,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;QACjC,mEAAmE;QACnE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF;wDACoD;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;8DAC0D;IAC1D,OAAO,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,uDAAuD;IACvD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,eAAe,GAAG,SAAS,CAAC;IACrE,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,uDAAuD;IACvD,sBAAsB,CAAC,EAAE,IAAI,CAC3B,oBAAoB,EACpB,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,sBAAsB,CACjE,CAAC;IACF,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF,qBAAa,mBAAmB;IAWlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAVjC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,OAAO,CAAC,aAAa,CAAC,CAAoB;IAC1C,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAS;IACzB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;gBAExC,IAAI,EAAE,gBAAgB;IAOnD;qCACiC;IAC3B,IAAI,CACR,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,eAAe,GAAG,SAAS,GACtD,OAAO,CAAC,oBAAoB,CAAC;IA0BhC,wEAAwE;IACxE,OAAO,CAAC,SAAS;IAWjB;;;;;;;;;;;;;;;;;;;OAmBG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAwE9B;;gFAE4E;YAC9D,WAAW;IAuBzB;;;;;;mCAM+B;IACzB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA+C9D;2EACuE;IACvE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAe1D,+CAA+C;IAC/C,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAI7C,iEAAiE;IACjE,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI1C,OAAO,IAAI,IAAI;CAKhB"}
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/session-index/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -276,6 +276,27 @@ function sdkDeleteError(sessionId) {
|
|
|
276
276
|
? `Session ${sessionId} not found in any project directory`
|
|
277
277
|
: `Invalid sessionId: ${sessionId}`);
|
|
278
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* `session/delete` of a client that is neither AIR nor a `sessionIndex` client:
|
|
281
|
+
* the SDK delete of the session's transcript. A session without one succeeds,
|
|
282
|
+
* as ACP asks ("Deleting an already-deleted session, or a session that never
|
|
283
|
+
* existed, SHOULD succeed silently"): an id that is not a session id, a
|
|
284
|
+
* session deleted before, or a session this connection ran but never prompted,
|
|
285
|
+
* since Claude Code writes the transcript at the first prompt. Other failures
|
|
286
|
+
* still fail the request.
|
|
287
|
+
*/
|
|
288
|
+
export async function deleteSessionIfStored(sessionId, deleteSession = sdkDeleteSession) {
|
|
289
|
+
if (!isSessionId(sessionId))
|
|
290
|
+
return;
|
|
291
|
+
try {
|
|
292
|
+
await deleteSession(sessionId);
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
if (isSdkNotFound(error))
|
|
296
|
+
return;
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
279
300
|
/**
|
|
280
301
|
* `session/delete` of an AIR client without `sessionIndex`, which uses delete
|
|
281
302
|
* to mark a session done: archives it instead, so the transcript survives. A
|
|
@@ -52,6 +52,10 @@ export type IndexRow = {
|
|
|
52
52
|
facts: TranscriptFacts;
|
|
53
53
|
mtimeMs: number;
|
|
54
54
|
archived: boolean;
|
|
55
|
+
/** The session runs in a linked git worktree that Claude Code made for
|
|
56
|
+
* it: its transcript says so (`facts.agentWorktree`) and `cwd` lies in
|
|
57
|
+
* a linked worktree. See {@link markAgentWorktrees}. */
|
|
58
|
+
agentWorktree?: true;
|
|
55
59
|
};
|
|
56
60
|
/** A keyset position: the order key and the session id of the last row. */
|
|
57
61
|
export type ListCursor = {
|
|
@@ -171,9 +175,13 @@ export declare class SessionIndex {
|
|
|
171
175
|
* alone gives, read from it at once, and the ids of the sessions it gives
|
|
172
176
|
* no answer for: a transcript of it has nothing cached at its stat, no cwd
|
|
173
177
|
* known, or is continued in another session (whether the successor hides
|
|
174
|
-
* it depends on the successor now). Reads no transcript.
|
|
178
|
+
* it depends on the successor now). Reads no transcript. The rows carry
|
|
179
|
+
* `agentWorktree` ({@link markAgentWorktrees}, which reads git files)
|
|
180
|
+
* unless `mark` is false, for a caller that uses only their ids.
|
|
175
181
|
*/
|
|
176
|
-
cachedRowsOf(paths: readonly string[], candidates: readonly TranscriptCandidate[]
|
|
182
|
+
cachedRowsOf(paths: readonly string[], candidates: readonly TranscriptCandidate[], { mark }?: {
|
|
183
|
+
mark?: boolean;
|
|
184
|
+
}): Promise<{
|
|
177
185
|
rows: IndexRow[];
|
|
178
186
|
unknown: Set<string>;
|
|
179
187
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-index.d.ts","sourceRoot":"","sources":["../../src/session-index/session-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAkBH,OAAO,EAeL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAI9B,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,cAAc,MAAM,CAAC;AAelC;;aAEa;AACb,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAAsC,CAAC;AAE7F,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAEtF;AAED,oDAAoD;AACpD,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAmBF,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB;;4BAEwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"session-index.d.ts","sourceRoot":"","sources":["../../src/session-index/session-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,7 +25,7 @@ import { effectiveTitle, visibleTitle } from "./archive-title.js";
|
|
|
25
25
|
import { canonicalPath, encodeProjectPath, isExactProjectDir, isSessionId, normalizePath, pathAndAncestors, projectDirMatches, projectDirsOf, projectsRoot, sameProjectPath, } from "./project-dirs.js";
|
|
26
26
|
import { continuedInSessionId, hasHistory, isSidechainTranscript, lastTimestamp, readHeadTail, relocatedCwd, scanTranscriptFile, sdkTitles, tailCustomTitle, transcriptAgentName, transcriptProjectCwd, } from "./transcript-scan.js";
|
|
27
27
|
import { DirListings, statFiles } from "./dir-listing.js";
|
|
28
|
-
import { worktreeCounterparts } from "./worktrees.js";
|
|
28
|
+
import { isInLinkedWorktree, worktreeCounterparts } from "./worktrees.js";
|
|
29
29
|
export const DEFAULT_LIST_LIMIT = 50;
|
|
30
30
|
export const MAX_LIST_LIMIT = 200;
|
|
31
31
|
/** Entries of the metadata cache: a few hundred bytes each, so the
|
|
@@ -130,6 +130,19 @@ function toRow({ candidate, metadata }, cwd) {
|
|
|
130
130
|
mtimeMs: candidate.mtimeMs,
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Sets `agentWorktree` on the rows whose transcript says Claude Code made
|
|
135
|
+
* their worktree and whose cwd lies in a linked worktree now. Only those rows
|
|
136
|
+
* are checked; the check is not cached, so a removed worktree shows at once.
|
|
137
|
+
*/
|
|
138
|
+
async function markAgentWorktrees(rows) {
|
|
139
|
+
await Promise.all(rows.map(async (row) => {
|
|
140
|
+
if (row.facts.agentWorktree === true && (await isInLinkedWorktree(row.cwd))) {
|
|
141
|
+
row.agentWorktree = true;
|
|
142
|
+
}
|
|
143
|
+
}));
|
|
144
|
+
return rows;
|
|
145
|
+
}
|
|
133
146
|
function isAfter(row, cursor) {
|
|
134
147
|
return compareRows(row, cursor) > 0;
|
|
135
148
|
}
|
|
@@ -517,9 +530,11 @@ export class SessionIndex {
|
|
|
517
530
|
* alone gives, read from it at once, and the ids of the sessions it gives
|
|
518
531
|
* no answer for: a transcript of it has nothing cached at its stat, no cwd
|
|
519
532
|
* known, or is continued in another session (whether the successor hides
|
|
520
|
-
* it depends on the successor now). Reads no transcript.
|
|
533
|
+
* it depends on the successor now). Reads no transcript. The rows carry
|
|
534
|
+
* `agentWorktree` ({@link markAgentWorktrees}, which reads git files)
|
|
535
|
+
* unless `mark` is false, for a caller that uses only their ids.
|
|
521
536
|
*/
|
|
522
|
-
async cachedRowsOf(paths, candidates) {
|
|
537
|
+
async cachedRowsOf(paths, candidates, { mark = true } = {}) {
|
|
523
538
|
const unknown = new Set();
|
|
524
539
|
const resolved = [];
|
|
525
540
|
for (const candidate of candidates) {
|
|
@@ -552,7 +567,8 @@ export class SessionIndex {
|
|
|
552
567
|
continue;
|
|
553
568
|
newest.set(id, { row: toRow(item, cwd), mtimeMs: item.candidate.mtimeMs });
|
|
554
569
|
}
|
|
555
|
-
|
|
570
|
+
const rows = [...newest.values()].map(({ row }) => row);
|
|
571
|
+
return { rows: mark ? await markAgentWorktrees(rows) : rows, unknown };
|
|
556
572
|
}
|
|
557
573
|
/**
|
|
558
574
|
* Reads `candidates` in order into rows, one per session, sorted. A
|
|
@@ -645,7 +661,7 @@ export class SessionIndex {
|
|
|
645
661
|
await this.learnDirCwds(new Set(pending.map(({ candidate }) => candidate.dirName)), options.unread(read), options.restat ?? false);
|
|
646
662
|
await settlePending();
|
|
647
663
|
}
|
|
648
|
-
return rows();
|
|
664
|
+
return markAgentWorktrees(rows());
|
|
649
665
|
}
|
|
650
666
|
/** Whether the cached metadata of `candidate`, still current, places it
|
|
651
667
|
* at or before `cursor`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-info.d.ts","sourceRoot":"","sources":["../../src/session-index/session-info.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAMnD;kEACkE;AAClE,wBAAgB,aAAa,CAC3B,GAAG,EAAE,QAAQ,EACb,GAAG,EAAE,eAAe,GAAG,SAAS,EAChC,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,GAAG,EAAE,MAAM,GACV,WAAW,
|
|
1
|
+
{"version":3,"file":"session-info.d.ts","sourceRoot":"","sources":["../../src/session-index/session-info.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAMnD;kEACkE;AAClE,wBAAgB,aAAa,CAC3B,GAAG,EAAE,QAAQ,EACb,GAAG,EAAE,eAAe,GAAG,SAAS,EAChC,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,GAAG,EAAE,MAAM,GACV,WAAW,CAiCb;AAED;gCACgC;AAChC,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEzD"}
|
|
@@ -27,6 +27,7 @@ export function sessionInfoOf(row, own, live, now) {
|
|
|
27
27
|
lastPromptAt: iso(facts.lastPromptAt),
|
|
28
28
|
model: facts.model,
|
|
29
29
|
forkedFrom: facts.forkedFrom,
|
|
30
|
+
agentWorktree: row.agentWorktree,
|
|
30
31
|
state: activity?.state,
|
|
31
32
|
lastTurnEndedAt: activity?.lastTurnEndedAt,
|
|
32
33
|
cost: cost === undefined ? undefined : { amount: cost, currency: "USD" },
|
|
@@ -36,6 +36,11 @@ export type TranscriptFacts = {
|
|
|
36
36
|
/** The session this one was forked from: the `forkedFrom.sessionId` that
|
|
37
37
|
* the SDK and CLI fork write on every copied record. */
|
|
38
38
|
forkedFrom?: string;
|
|
39
|
+
/** What the last `worktree-state` record says: true when its
|
|
40
|
+
* `worktreeSession` is set and not `enteredExisting` (Claude Code made the
|
|
41
|
+
* worktree and the session is in it), false when it says otherwise.
|
|
42
|
+
* Undefined when no such record was read. See {@link agentWorktreeOf}. */
|
|
43
|
+
agentWorktree?: boolean;
|
|
39
44
|
/** Whether the head or the tail holds a user or an assistant message. A
|
|
40
45
|
* transcript without one is a metadata-only stub. */
|
|
41
46
|
hasMessages: boolean;
|
|
@@ -50,7 +55,7 @@ export type HeadTail = {
|
|
|
50
55
|
sdkTail?: string;
|
|
51
56
|
};
|
|
52
57
|
/** Facts that an earlier scan may have found before the tail window. */
|
|
53
|
-
declare const INHERITED_FACTS: readonly ["model", "tailCwd", "lastTurnEndedAt"];
|
|
58
|
+
declare const INHERITED_FACTS: readonly ["model", "tailCwd", "lastTurnEndedAt", "agentWorktree"];
|
|
54
59
|
/** What an earlier scan of the same file found, at `size`. */
|
|
55
60
|
export type PreviousScan = {
|
|
56
61
|
size: number;
|
|
@@ -80,6 +85,25 @@ identity?: number): Promise<TranscriptFacts>;
|
|
|
80
85
|
/** The cwd of the last `relocated` record of the tail: where the session
|
|
81
86
|
* was moved, whatever cwd its earlier messages carry. */
|
|
82
87
|
export declare function relocatedCwd(tail: string): string | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Whether the last `worktree-state` record of `text` says the session is in
|
|
90
|
+
* a worktree that Claude Code made for it, as AIR's native Claude provider
|
|
91
|
+
* reads it: a `worktreeSession` that is an object without
|
|
92
|
+
* `enteredExisting: true`. The last line that parses as a `worktree-state`
|
|
93
|
+
* record decides; any other `worktreeSession` (`null`, which the CLI writes
|
|
94
|
+
* when the session leaves the worktree, missing, or no object) means false.
|
|
95
|
+
* Only lines that are not JSON (such as the cut first line of a window) are
|
|
96
|
+
* skipped. Undefined when `text` holds no such record.
|
|
97
|
+
*
|
|
98
|
+
* The CLI writes the record when it enters or leaves a worktree (for
|
|
99
|
+
* `claude --worktree`, at the start of the session, so in the head), and
|
|
100
|
+
* writes it again with the other session metadata at the end of the
|
|
101
|
+
* transcript (on exit and as the transcript grows), so the tail usually
|
|
102
|
+
* holds the latest one. Only the head and the tail are read: a session that
|
|
103
|
+
* entered a worktree midway through a long transcript, with no metadata
|
|
104
|
+
* written after it yet, is not seen until the CLI writes the metadata again.
|
|
105
|
+
*/
|
|
106
|
+
export declare function agentWorktreeOf(text: string): boolean | undefined;
|
|
83
107
|
/** The cwd a transcript belongs to, as the SDK reads it: the last
|
|
84
108
|
* `relocated` record of the tail, else the first cwd of the head. */
|
|
85
109
|
export declare function transcriptProjectCwd({ head, tail }: HeadTail): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcript-scan.d.ts","sourceRoot":"","sources":["../../src/session-index/transcript-scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAcvC,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;AAElD,MAAM,MAAM,eAAe,GAAG;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;0BACsB;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;8EAC0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;qDACiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;kEAC8D;IAC9D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;6DACyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;0DACsD;IACtD,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb;4BACwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb;8CAC0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wEAAwE;AACxE,QAAA,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"transcript-scan.d.ts","sourceRoot":"","sources":["../../src/session-index/transcript-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ const FULL_SEARCH_CACHE_SIZE = 512;
|
|
|
20
20
|
* the same size is not searched again. */
|
|
21
21
|
const fullySearched = new Map();
|
|
22
22
|
/** Facts that an earlier scan may have found before the tail window. */
|
|
23
|
-
const INHERITED_FACTS = ["model", "tailCwd", "lastTurnEndedAt"];
|
|
23
|
+
const INHERITED_FACTS = ["model", "tailCwd", "lastTurnEndedAt", "agentWorktree"];
|
|
24
24
|
/** The last `window` bytes of a file of `size` bytes, without the first,
|
|
25
25
|
* cut line. The whole file when it fits. */
|
|
26
26
|
async function readTail(handle, size, window) {
|
|
@@ -88,6 +88,13 @@ identity) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
// No worktree record in the tail (or before it, by an earlier scan): the
|
|
92
|
+
// one `claude --worktree` writes at the start may still be in the head.
|
|
93
|
+
if (facts.agentWorktree === undefined) {
|
|
94
|
+
const agentWorktree = agentWorktreeOf(read.head);
|
|
95
|
+
if (agentWorktree !== undefined)
|
|
96
|
+
facts.agentWorktree = agentWorktree;
|
|
97
|
+
}
|
|
91
98
|
if (facts.lastPromptAt !== undefined || size <= CHUNK_SIZE) {
|
|
92
99
|
facts.promptSearched = true;
|
|
93
100
|
}
|
|
@@ -135,6 +142,11 @@ identity) {
|
|
|
135
142
|
...wider,
|
|
136
143
|
...(facts.model !== undefined && { model: facts.model }),
|
|
137
144
|
...(facts.tailCwd !== undefined && { tailCwd: facts.tailCwd }),
|
|
145
|
+
// The wider tail holds the narrow one, so a record it has is the
|
|
146
|
+
// latest; else the narrow scan's (inherited or from the head) stands.
|
|
147
|
+
...((wider.agentWorktree ?? facts.agentWorktree) !== undefined && {
|
|
148
|
+
agentWorktree: wider.agentWorktree ?? facts.agentWorktree,
|
|
149
|
+
}),
|
|
138
150
|
// A turn end the wider tail lacks may lie before it: the
|
|
139
151
|
// narrow scan inherited it from an earlier scan of this file.
|
|
140
152
|
lastTurnEndedAt: wider.lastTurnEndedAt ?? facts.lastTurnEndedAt,
|
|
@@ -174,6 +186,45 @@ export function relocatedCwd(tail) {
|
|
|
174
186
|
}
|
|
175
187
|
return undefined;
|
|
176
188
|
}
|
|
189
|
+
const WORKTREE_STATE_MARKER = '"worktree-state"';
|
|
190
|
+
/**
|
|
191
|
+
* Whether the last `worktree-state` record of `text` says the session is in
|
|
192
|
+
* a worktree that Claude Code made for it, as AIR's native Claude provider
|
|
193
|
+
* reads it: a `worktreeSession` that is an object without
|
|
194
|
+
* `enteredExisting: true`. The last line that parses as a `worktree-state`
|
|
195
|
+
* record decides; any other `worktreeSession` (`null`, which the CLI writes
|
|
196
|
+
* when the session leaves the worktree, missing, or no object) means false.
|
|
197
|
+
* Only lines that are not JSON (such as the cut first line of a window) are
|
|
198
|
+
* skipped. Undefined when `text` holds no such record.
|
|
199
|
+
*
|
|
200
|
+
* The CLI writes the record when it enters or leaves a worktree (for
|
|
201
|
+
* `claude --worktree`, at the start of the session, so in the head), and
|
|
202
|
+
* writes it again with the other session metadata at the end of the
|
|
203
|
+
* transcript (on exit and as the transcript grows), so the tail usually
|
|
204
|
+
* holds the latest one. Only the head and the tail are read: a session that
|
|
205
|
+
* entered a worktree midway through a long transcript, with no metadata
|
|
206
|
+
* written after it yet, is not seen until the CLI writes the metadata again.
|
|
207
|
+
*/
|
|
208
|
+
export function agentWorktreeOf(text) {
|
|
209
|
+
if (!text.includes(WORKTREE_STATE_MARKER))
|
|
210
|
+
return undefined;
|
|
211
|
+
const lines = text.split("\n");
|
|
212
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
213
|
+
const line = lines[i];
|
|
214
|
+
if (!line.includes(WORKTREE_STATE_MARKER))
|
|
215
|
+
continue;
|
|
216
|
+
const entry = parseLine(line);
|
|
217
|
+
// Only a line that is no JSON record is skipped: the latest record that
|
|
218
|
+
// parses decides, even when its `worktreeSession` is missing or no object.
|
|
219
|
+
if (entry?.type !== "worktree-state")
|
|
220
|
+
continue;
|
|
221
|
+
const session = entry.worktreeSession;
|
|
222
|
+
if (!session || typeof session !== "object" || Array.isArray(session))
|
|
223
|
+
return false;
|
|
224
|
+
return session.enteredExisting !== true;
|
|
225
|
+
}
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
177
228
|
/** The cwd a transcript belongs to, as the SDK reads it: the last
|
|
178
229
|
* `relocated` record of the tail, else the first cwd of the head. */
|
|
179
230
|
export function transcriptProjectCwd({ head, tail }) {
|
|
@@ -274,6 +325,11 @@ export function scanTranscript({ head, tail }, options = {}) {
|
|
|
274
325
|
const forkedFrom = FORKED_FROM_PATTERN.exec(head)?.[1];
|
|
275
326
|
if (forkedFrom !== undefined)
|
|
276
327
|
facts.forkedFrom = forkedFrom;
|
|
328
|
+
// The tail only: scanTranscriptFile falls back to the head after it
|
|
329
|
+
// inherits what an earlier scan found before the tail.
|
|
330
|
+
const agentWorktree = agentWorktreeOf(tail);
|
|
331
|
+
if (agentWorktree !== undefined)
|
|
332
|
+
facts.agentWorktree = agentWorktree;
|
|
277
333
|
const lines = tail.split("\n");
|
|
278
334
|
let turnEndFound = false;
|
|
279
335
|
let messageFound = false;
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
* worktree root, the worktree roots. Empty outside a repository.
|
|
18
18
|
*/
|
|
19
19
|
export declare function worktreeCounterparts(cwd: string): Promise<string[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Whether `cwd` lies in a linked worktree: its git dir is
|
|
22
|
+
* `<common-dir>/worktrees/<name>`. False in the main worktree, in a
|
|
23
|
+
* submodule and outside a repository.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isInLinkedWorktree(cwd: string): Promise<boolean>;
|
|
20
26
|
/**
|
|
21
27
|
* Every existing worktree of the repository that contains `cwd`: the main
|
|
22
28
|
* worktree and the linked ones. Empty outside a repository.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/session-index/worktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAqFH;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAazE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAaxE"}
|
|
1
|
+
{"version":3,"file":"worktrees.d.ts","sourceRoot":"","sources":["../../src/session-index/worktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAqFH;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAazE;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKtE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAaxE"}
|
|
@@ -110,6 +110,18 @@ export async function worktreeCounterparts(cwd) {
|
|
|
110
110
|
const existing = await Promise.all(candidates.map(async (candidate) => (await statOrUndefined(candidate))?.isDirectory() ? normalizePath(candidate) : undefined));
|
|
111
111
|
return [...new Set(existing.filter((value) => value !== undefined))];
|
|
112
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Whether `cwd` lies in a linked worktree: its git dir is
|
|
115
|
+
* `<common-dir>/worktrees/<name>`. False in the main worktree, in a
|
|
116
|
+
* submodule and outside a repository.
|
|
117
|
+
*/
|
|
118
|
+
export async function isInLinkedWorktree(cwd) {
|
|
119
|
+
const gitDir = await findGitDir(cwd);
|
|
120
|
+
if (!gitDir)
|
|
121
|
+
return false;
|
|
122
|
+
const commonDir = await commonDirOf(gitDir);
|
|
123
|
+
return path.resolve(path.dirname(gitDir)) === path.resolve(commonDir, "worktrees");
|
|
124
|
+
}
|
|
113
125
|
/**
|
|
114
126
|
* Every existing worktree of the repository that contains `cwd`: the main
|
|
115
127
|
* worktree and the linked ones. Empty outside a repository.
|
package/dist/session-model.d.ts
CHANGED
|
@@ -46,6 +46,26 @@ export declare function isDeniedModel(modelId: string, deniedModels: readonly st
|
|
|
46
46
|
* dropped even though the CLI would otherwise leave it unmatched.
|
|
47
47
|
*/
|
|
48
48
|
export declare function applyAvailableModelsAllowlist(sdkModels: ModelInfo[], allowlist: string[], settingsModelOverrides?: Record<string, string>, deniedModels?: readonly string[]): ModelInfo[];
|
|
49
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Keep the SDK models the `providers/set` gateway listed (`listGatewayModels`,
|
|
51
|
+
* `listBedrockModels`). A row matches when its `resolvedModel` (or
|
|
52
|
+
* its `value` when the SDK gives none) names a listed model in any spelling:
|
|
53
|
+
* `claude-sonnet-5[1m]` matches a listed `claude-sonnet-5-20260101`, and
|
|
54
|
+
* `eu.anthropic.claude-sonnet-5` matches a listed `eu.anthropic.claude-sonnet-5-v1:0`.
|
|
55
|
+
*
|
|
56
|
+
* With a Bedrock `regionPrefix`, a row resolved to another cross-region prefix
|
|
57
|
+
* (`us.anthropic.claude-sonnet-5` under `eu`) is dropped even when the same
|
|
58
|
+
* model is listed under `eu`: the CLI would call it in the other region.
|
|
59
|
+
*
|
|
60
|
+
* A row the SDK gives no `resolvedModel` names its model only by an alias, so
|
|
61
|
+
* it is checked as far as the alias allows: `default` is kept, and a family
|
|
62
|
+
* alias such as `opus` is kept when the gateway lists a model of that family.
|
|
63
|
+
*
|
|
64
|
+
* When no row matches by its model (a `default` row kept only for lacking a
|
|
65
|
+
* `resolvedModel` does not count), the gateway serves none of the SDK's
|
|
66
|
+
* models, and nothing is left: the session offers no model.
|
|
67
|
+
*/
|
|
68
|
+
export declare function narrowToGatewayModels(models: ModelInfo[], listedModelIds: readonly string[], regionPrefix?: string): ModelInfo[];
|
|
69
|
+
export declare function getAvailableModels(query: Query, models: ModelInfo[], sdkModels: ModelInfo[], settingsManager: ModelSettingsSource, logger: ModelLogger, isResumedSession: boolean, sessionId: string, resumedModelHint?: string, narrowedByGateway?: boolean): Promise<SessionModelState>;
|
|
50
70
|
export {};
|
|
51
71
|
//# sourceMappingURL=session-model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-model.d.ts","sourceRoot":"","sources":["../src/session-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"session-model.d.ts","sourceRoot":"","sources":["../src/session-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAIjF,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;AACF,KAAK,mBAAmB,GAAG;IAAE,WAAW,IAAI,QAAQ,CAAA;CAAE,CAAC;AAmGvD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CA2ChG;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAyBnF;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,SAAS,EAAE,EACvB,mBAAmB,EAAE,OAAO,GAC3B,mBAAmB,CAsDrB;AAkCD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CASvF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,SAAS,EAAE,EACtB,SAAS,EAAE,MAAM,EAAE,EACnB,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/C,YAAY,GAAE,SAAS,MAAM,EAAO,GACnC,SAAS,EAAE,CA6Db;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EAAE,EACnB,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,YAAY,CAAC,EAAE,MAAM,GACpB,SAAS,EAAE,CAiBb;AAWD,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EAAE,EACtB,eAAe,EAAE,mBAAmB,EACpC,MAAM,EAAE,WAAW,EACnB,gBAAgB,EAAE,OAAO,EACzB,SAAS,EAAE,MAAM,EACjB,gBAAgB,CAAC,EAAE,MAAM,EACzB,iBAAiB,UAAQ,GACxB,OAAO,CAAC,iBAAiB,CAAC,CAoJ5B"}
|
package/dist/session-model.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AIR_RECOMMENDED_CONFIG_VALUE_CAPABILITY, withAirMeta } from "./air-extension.js";
|
|
2
|
+
import { bedrockRegionPrefix } from "./gateway-models.js";
|
|
2
3
|
export const MODEL_CONFIG_ID = "model";
|
|
3
4
|
const MODEL_CONTEXT_HINT_PATTERN = /\[(\d+m)\]$/i;
|
|
4
5
|
const CONTEXT_HINT_SUFFIX_PATTERN = /-(\d+m)$/i;
|
|
@@ -218,9 +219,10 @@ function resolveSettingsModel(models, settingsModel, logger) {
|
|
|
218
219
|
return resolveModelPreference(models, settingsModel);
|
|
219
220
|
}
|
|
220
221
|
const MODEL_FAMILY_ALIASES = new Set(["opus", "sonnet", "haiku", "fable"]);
|
|
221
|
-
/** A model id without the spellings
|
|
222
|
-
* prefixes, dates, version suffixes, `-fast` and context hints.
|
|
223
|
-
|
|
222
|
+
/** A model id without the spellings that name the same model: provider
|
|
223
|
+
* prefixes, dates, version suffixes, `-fast` and context hints. `deniedModels`
|
|
224
|
+
* and gateway listings both match on it. */
|
|
225
|
+
function normalizeModelId(value) {
|
|
224
226
|
let id = stripContextHints(value.trim().toLowerCase());
|
|
225
227
|
const providerPrefix = id.lastIndexOf("anthropic.");
|
|
226
228
|
if (providerPrefix !== -1)
|
|
@@ -239,11 +241,11 @@ function normalizeDeniedModelId(value) {
|
|
|
239
241
|
* the enforcer; this only keeps the picker from offering a refused row.
|
|
240
242
|
*/
|
|
241
243
|
export function isDeniedModel(modelId, deniedModels) {
|
|
242
|
-
const id =
|
|
244
|
+
const id = normalizeModelId(modelId);
|
|
243
245
|
if (!id)
|
|
244
246
|
return false;
|
|
245
247
|
return deniedModels.some((entry) => {
|
|
246
|
-
const denied =
|
|
248
|
+
const denied = normalizeModelId(entry);
|
|
247
249
|
if (!denied)
|
|
248
250
|
return false;
|
|
249
251
|
if (MODEL_FAMILY_ALIASES.has(denied))
|
|
@@ -324,6 +326,46 @@ export function applyAvailableModelsAllowlist(sdkModels, allowlist, settingsMode
|
|
|
324
326
|
}
|
|
325
327
|
return result;
|
|
326
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Keep the SDK models the `providers/set` gateway listed (`listGatewayModels`,
|
|
331
|
+
* `listBedrockModels`). A row matches when its `resolvedModel` (or
|
|
332
|
+
* its `value` when the SDK gives none) names a listed model in any spelling:
|
|
333
|
+
* `claude-sonnet-5[1m]` matches a listed `claude-sonnet-5-20260101`, and
|
|
334
|
+
* `eu.anthropic.claude-sonnet-5` matches a listed `eu.anthropic.claude-sonnet-5-v1:0`.
|
|
335
|
+
*
|
|
336
|
+
* With a Bedrock `regionPrefix`, a row resolved to another cross-region prefix
|
|
337
|
+
* (`us.anthropic.claude-sonnet-5` under `eu`) is dropped even when the same
|
|
338
|
+
* model is listed under `eu`: the CLI would call it in the other region.
|
|
339
|
+
*
|
|
340
|
+
* A row the SDK gives no `resolvedModel` names its model only by an alias, so
|
|
341
|
+
* it is checked as far as the alias allows: `default` is kept, and a family
|
|
342
|
+
* alias such as `opus` is kept when the gateway lists a model of that family.
|
|
343
|
+
*
|
|
344
|
+
* When no row matches by its model (a `default` row kept only for lacking a
|
|
345
|
+
* `resolvedModel` does not count), the gateway serves none of the SDK's
|
|
346
|
+
* models, and nothing is left: the session offers no model.
|
|
347
|
+
*/
|
|
348
|
+
export function narrowToGatewayModels(models, listedModelIds, regionPrefix) {
|
|
349
|
+
const listed = new Set(listedModelIds.map(normalizeModelId).filter(Boolean));
|
|
350
|
+
const narrowed = models.filter((model) => {
|
|
351
|
+
const modelId = model.resolvedModel ?? model.value;
|
|
352
|
+
const prefix = bedrockRegionPrefix(modelId);
|
|
353
|
+
if (regionPrefix !== undefined && prefix !== undefined && prefix !== regionPrefix) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
const id = normalizeModelId(modelId);
|
|
357
|
+
if (listed.has(id))
|
|
358
|
+
return true;
|
|
359
|
+
if (model.resolvedModel !== undefined)
|
|
360
|
+
return false;
|
|
361
|
+
if (model.value === "default")
|
|
362
|
+
return true;
|
|
363
|
+
return MODEL_FAMILY_ALIASES.has(id) && [...listed].some((entry) => entry.includes(`-${id}`));
|
|
364
|
+
});
|
|
365
|
+
return narrowed.some((model) => listed.has(normalizeModelId(model.resolvedModel ?? model.value)))
|
|
366
|
+
? narrowed
|
|
367
|
+
: [];
|
|
368
|
+
}
|
|
327
369
|
/** Whether a rejected `setModel` was vetoed by a user-configured
|
|
328
370
|
* PreModelSwitch hook. The CLI's rejection message is the stable,
|
|
329
371
|
* distinguishable marker ("Model switch blocked by a PreModelSwitch hook:
|
|
@@ -332,7 +374,16 @@ export function applyAvailableModelsAllowlist(sdkModels, allowlist, settingsMode
|
|
|
332
374
|
function isPreModelSwitchHookBlock(error) {
|
|
333
375
|
return error instanceof Error && error.message.includes("blocked by a PreModelSwitch hook");
|
|
334
376
|
}
|
|
335
|
-
export async function getAvailableModels(query, models, sdkModels, settingsManager, logger, isResumedSession, sessionId, resumedModelHint) {
|
|
377
|
+
export async function getAvailableModels(query, models, sdkModels, settingsManager, logger, isResumedSession, sessionId, resumedModelHint, narrowedByGateway = false) {
|
|
378
|
+
// A gateway that lists none of the SDK's models leaves none to offer
|
|
379
|
+
// (`narrowToGatewayModels`). The session stays on the model the SDK runs,
|
|
380
|
+
// and the gateway refuses its requests.
|
|
381
|
+
if (models.length === 0) {
|
|
382
|
+
return {
|
|
383
|
+
availableModels: [],
|
|
384
|
+
currentModelId: (isResumedSession && resumedModelHint) || sdkModels[0]?.value || "default",
|
|
385
|
+
};
|
|
386
|
+
}
|
|
336
387
|
const settings = settingsManager.getSettings();
|
|
337
388
|
let currentModel = models[0];
|
|
338
389
|
let resolvedFromInput;
|
|
@@ -377,8 +428,31 @@ export async function getAvailableModels(query, models, sdkModels, settingsManag
|
|
|
377
428
|
// be re-asserted to keep the reported model truthful.
|
|
378
429
|
// Anything else (fuzzy match, allowlist-synthesized value, alias) gets a
|
|
379
430
|
// setModel call so we don't drift from the user's intended pin.
|
|
431
|
+
// Case (a) does not hold when `narrowToGatewayModels` left the SDK on a
|
|
432
|
+
// model the gateway does not list: the dropped `default` row of a fresh or
|
|
433
|
+
// transcript-less session, or a resumed transcript model outside the list.
|
|
434
|
+
// Such a session switches to models[0].
|
|
380
435
|
const sdkSawSameValue = sdkModels.some((m) => m.value === currentModel.value);
|
|
381
|
-
const
|
|
436
|
+
const sdkDefault = sdkModels.find((m) => m.value === "default");
|
|
437
|
+
const sdkDefaultDropped = sdkDefault !== undefined && !models.some((m) => m.value === "default");
|
|
438
|
+
let switchToListed = false;
|
|
439
|
+
if (resolvedFromInput === undefined) {
|
|
440
|
+
if (!isResumedSession || !resumedModelHint) {
|
|
441
|
+
switchToListed = sdkDefaultDropped;
|
|
442
|
+
}
|
|
443
|
+
else if (narrowedByGateway &&
|
|
444
|
+
(!models.some((m) => m.value === currentModel.value) ||
|
|
445
|
+
// A loose match can map the transcript's model onto a listed row of
|
|
446
|
+
// another version, which the CLI does not resume on.
|
|
447
|
+
(currentModel.resolvedModel !== undefined &&
|
|
448
|
+
normalizeModelId(currentModel.resolvedModel) !== normalizeModelId(resumedModelHint)))) {
|
|
449
|
+
currentModel = models[0];
|
|
450
|
+
switchToListed = true;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// When the switch fails, the SDK stays on the model it ran before it.
|
|
454
|
+
const modelBeforeSwitch = () => switchToListed && sdkDefault !== undefined ? sdkDefault : models[0];
|
|
455
|
+
const skipSetModel = (resolvedFromInput === undefined && !switchToListed) ||
|
|
382
456
|
(!isResumedSession && currentModel.value === resolvedFromInput && sdkSawSameValue);
|
|
383
457
|
if (!skipSetModel) {
|
|
384
458
|
const setModelStartedAt = performance.now();
|
|
@@ -407,14 +481,18 @@ export async function getAvailableModels(query, models, sdkModels, settingsManag
|
|
|
407
481
|
// live model back on this path: getContextUsage isn't serviced on a
|
|
408
482
|
// fresh session until the first prompt turn (issues #886/#880).
|
|
409
483
|
if (!isResumedSession) {
|
|
410
|
-
|
|
484
|
+
// A switch onto a listed model is advisory too: the session stays on
|
|
485
|
+
// the model the SDK runs and reports it.
|
|
486
|
+
if (!switchToListed && !isPreModelSwitchHookBlock(error))
|
|
411
487
|
throw error;
|
|
412
|
-
logger.error(`Model
|
|
413
|
-
currentModel =
|
|
488
|
+
logger.error(`Model switch to "${currentModel.value}" failed or was vetoed by a PreModelSwitch hook; staying on the default model:`, error);
|
|
489
|
+
currentModel = modelBeforeSwitch();
|
|
414
490
|
}
|
|
415
491
|
else {
|
|
416
492
|
logger.error(`Failed to re-assert model "${currentModel.value}" on resume:`, error);
|
|
417
|
-
currentModel = resumedModelHint
|
|
493
|
+
currentModel = resumedModelHint
|
|
494
|
+
? matchResumedModel(models, resumedModelHint)
|
|
495
|
+
: modelBeforeSwitch();
|
|
418
496
|
}
|
|
419
497
|
}
|
|
420
498
|
}
|
package/dist/turn-events.d.ts
CHANGED
|
@@ -53,7 +53,11 @@ export interface TurnEvents {
|
|
|
53
53
|
* the cycle reports nothing more, and the turn reports from there.
|
|
54
54
|
*/
|
|
55
55
|
export interface ForegroundEvents {
|
|
56
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* The work started, or works again after it waited for the user. Not after
|
|
58
|
+
* a wait that a cancel ended: Claude Code's interrupt withdrew the last
|
|
59
|
+
* request, so the work is being stopped, and {@link ended} follows at once.
|
|
60
|
+
*/
|
|
57
61
|
running(): void;
|
|
58
62
|
/**
|
|
59
63
|
* The work waits for the user: a permission request or a question is open in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-events.d.ts","sourceRoot":"","sources":["../src/turn-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gBAAgB;IAC/B
|
|
1
|
+
{"version":3,"file":"turn-events.d.ts","sourceRoot":"","sources":["../src/turn-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,IAAI,IAAI,CAAC;IAChB;;;;OAIG;IACH,YAAY,IAAI,IAAI,CAAC;IACrB,sBAAsB;IACtB,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,SAAS,GAAG,WAAW,CAAC;AAEnG,wBAAwB;AACxB,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC"}
|
package/dist/v2/prompt.d.ts
CHANGED
|
@@ -28,7 +28,8 @@ export declare function v2Prompt(agent: ClaudeAcpAgent, params: v2.PromptRequest
|
|
|
28
28
|
*
|
|
29
29
|
* - Started: `running`. For a prompt's turn, right after its `user_message`.
|
|
30
30
|
* - Waiting on a permission request or a question: `requires_action`, and
|
|
31
|
-
* `running` once none is open
|
|
31
|
+
* `running` once none is open, unless a cancel withdrew the last one: the
|
|
32
|
+
* work is being stopped then, and its `idle` follows.
|
|
32
33
|
* - Ended: `idle` with the stop reason, usage, and `_meta` of the work.
|
|
33
34
|
* - Failed: `idle` with the `error` stop reason and the JSON-RPC error that v1
|
|
34
35
|
* answers the prompt with, so a client can show its message and handle its
|
package/dist/v2/prompt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/v2/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAuC,MAAM,mBAAmB,CAAC;AAE/F;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,EAAE,CAAC,aAAa,EACxB,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,GACvC,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,CAiC5B;AAED
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/v2/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAuC,MAAM,mBAAmB,CAAC;AAE/F;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,EAAE,CAAC,aAAa,EACxB,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,GACvC,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,CAiC5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,GAAG,gBAAgB,CAoBvF;AAgCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,aAAa,GAAG,aAAa,CAEvF"}
|
package/dist/v2/prompt.js
CHANGED
|
@@ -57,7 +57,8 @@ export function v2Prompt(agent, params, send) {
|
|
|
57
57
|
*
|
|
58
58
|
* - Started: `running`. For a prompt's turn, right after its `user_message`.
|
|
59
59
|
* - Waiting on a permission request or a question: `requires_action`, and
|
|
60
|
-
* `running` once none is open
|
|
60
|
+
* `running` once none is open, unless a cancel withdrew the last one: the
|
|
61
|
+
* work is being stopped then, and its `idle` follows.
|
|
61
62
|
* - Ended: `idle` with the stop reason, usage, and `_meta` of the work.
|
|
62
63
|
* - Failed: `idle` with the `error` stop reason and the JSON-RPC error that v1
|
|
63
64
|
* answers the prompt with, so a client can show its message and handle its
|