@dotobokuri/fleet-console 1.59.0 → 1.60.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/AGENTS.md +1 -1
- package/dist/cli.mjs +12 -2
- package/dist/client/assets/{_baseUniq-CKkDoWU8.js → _baseUniq-CA3I-KTP.js} +1 -1
- package/dist/client/assets/{arc-CcRdX8oF.js → arc-DOkIWugv.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-gaFzE1W7.js → architectureDiagram-Q4EWVU46--Z_t3Gn9.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-Bzybih30.js → blockDiagram-DXYQGD6D-CrRA5qvl.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-Dz8bwV9j.js → c4Diagram-AHTNJAMY-DKvbMOAM.js} +1 -1
- package/dist/client/assets/channel-Bjfd2afp.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-DmgZtGyV.js → chunk-4BX2VUAB-D6wc2KrB.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-DX1WxV3U.js → chunk-4TB4RGXK-B4QvYh7f.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-Bk4b3T9u.js → chunk-55IACEB6-B0VZPoad.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-BzGadfvT.js → chunk-EDXVE4YY-BdHIgvVh.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-44f7YyvW.js → chunk-FMBD7UC4-BAYTd_pU.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-CyUAky9W.js → chunk-OYMX7WX6-DkZ-neug.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-C11OUntR.js → chunk-QZHKN3VN-B5h7E8GE.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-DVTmWawU.js → chunk-YZCP3GAM-COMJ2EwJ.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-DgpHvFOU.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-DgpHvFOU.js +1 -0
- package/dist/client/assets/clone-sFXqwEZz.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-CEatGsZv.js → cose-bilkent-S5V4N54A-JvC7pCqe.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-DlrgN02H.js → dagre-KV5264BT-jZdVPQcJ.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-BZ3hRO5t.js → diagram-5BDNPKRD-B6-u7AU2.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-B-izS46x.js → diagram-G4DWMVQ6-CV5G3KNM.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-Cw-wnJGs.js → diagram-MMDJMWI5-ZLrEkNww.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-BoWnyd4_.js → diagram-TYMM5635-D1tv2JX9.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-BUmyXZbP.js → erDiagram-SMLLAGMA-Bta0Mt3t.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-COS3kjS0.js → flowDiagram-DWJPFMVM-C282oRLT.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-BTr1fdio.js → ganttDiagram-T4ZO3ILL-D9P4CVIW.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-BkGkaosN.js → gitGraphDiagram-UUTBAWPF-DLQnTjJ2.js} +1 -1
- package/dist/client/assets/{graph-DmbgK-mH.js → graph-Cd8Q-8WG.js} +1 -1
- package/dist/client/assets/index-B3gusU1E.js +465 -0
- package/dist/client/assets/index-_PHObHQ-.css +1 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-B8zI6k1l.js → infoDiagram-42DDH7IO-ClhLpons.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-cIcEzrcK.js → ishikawaDiagram-UXIWVN3A-BDeZ2vOG.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-DhuabHCk.js → journeyDiagram-VCZTEJTY-DbJhbFKN.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-uHTkqxhX.js → kanban-definition-6JOO6SKY-CYKcE2fE.js} +1 -1
- package/dist/client/assets/{layout-Cfgk_duA.js → layout-CuAgTRkn.js} +1 -1
- package/dist/client/assets/{linear-BKvV0sr5.js → linear-3EL9MakS.js} +1 -1
- package/dist/client/assets/{mermaid.core-DozmrCuG.js → mermaid.core-7qKaxHEA.js} +4 -4
- package/dist/client/assets/{min-ke46otlW.js → min-4mJsdKjT.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-d7xzxhzf.js → mindmap-definition-QFDTVHPH-B-Zve2OH.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-C4S9Jy5A.js → pieDiagram-DEJITSTG-DlsdbAii.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-CoQnj3kv.js → quadrantDiagram-34T5L4WZ-Cb4h0xwt.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-CdopMDtg.js → requirementDiagram-MS252O5E-CZNGYqJt.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-DdR4zdh4.js → sankeyDiagram-XADWPNL6-DeVSGR6W.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-NeYZWVQm.js → sequenceDiagram-FGHM5R23-Te7TkLIe.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-D0CQGKV_.js → stateDiagram-FHFEXIEX-Be-0oYyv.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BnQ2lBhr.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-Bz2b3nfQ.js → timeline-definition-GMOUNBTQ-DQyUgC-K.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-CVO2Ja80.js → vennDiagram-DHZGUBPP-BrArIWI8.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-Ba_GKs5u.js → wardley-RL74JXVD-6-sWm8kk.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-yP3xvrPy.js → wardleyDiagram-NUSXRM2D-C4MvFXGS.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-BLSs6w4C.js → xychartDiagram-5P7HB3ND-CGrtjhmr.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/fleet-plugins/file-explorer/routes.mjs +132 -13
- package/dist/fleet-plugins/ledger/routes.mjs +223 -16
- package/dist/fleet-plugins/quota/routes.mjs +33 -2
- package/dist/fleet-plugins/scuttlebutt/routes.mjs +5 -5
- package/dist/fleet-plugins/terminal/routes.mjs +411 -61
- package/dist/fleet.mjs +274 -43
- package/package.json +1 -1
- package/dist/client/assets/channel-CAhLkt5l.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-BSvLoE2t.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-BSvLoE2t.js +0 -1
- package/dist/client/assets/clone-o26VS_sk.js +0 -1
- package/dist/client/assets/index-C-3spb_b.js +0 -465
- package/dist/client/assets/index-FU1PGEfG.css +0 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-hM1GV37r.js +0 -1
|
@@ -20195,6 +20195,10 @@ var CLAUDE_COMPAT_CONTEXT_WINDOW = 1e6;
|
|
|
20195
20195
|
var CLAUDE_DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
20196
20196
|
var CLAUDE_COMPACT_RESERVE = 32e3;
|
|
20197
20197
|
var PROVIDER_COMPACT_RESERVE = 16e3;
|
|
20198
|
+
var COMPACT_CEILING_EARLY_PERCENT = 88;
|
|
20199
|
+
var COMPACT_CEILING_LATE_PERCENT = 97;
|
|
20200
|
+
var COMPACT_CEILING_CUSTOM_MIN = 70;
|
|
20201
|
+
var COMPACT_CEILING_CUSTOM_MAX = 99;
|
|
20198
20202
|
var DEFAULT_MAX_JSON_BYTES = 16 * 1024 * 1024;
|
|
20199
20203
|
var DEFAULT_MAX_SSE_FRAME_BYTES = 1024 * 1024;
|
|
20200
20204
|
var MAX_SSE_SEPARATOR_BYTES = 4;
|
|
@@ -20212,20 +20216,41 @@ function hasClaudeOneMillionMarker(modelId) {
|
|
|
20212
20216
|
function stripClaudeOneMillionMarker(modelId) {
|
|
20213
20217
|
return modelId.replace(/\[1m\]$/i, "");
|
|
20214
20218
|
}
|
|
20215
|
-
function projectClaudeContextInputTokens(inputTokens, advertisedContextWindow, upstreamContextWindow = advertisedContextWindow) {
|
|
20219
|
+
function projectClaudeContextInputTokens(inputTokens, advertisedContextWindow, upstreamContextWindow = advertisedContextWindow, compactCeiling) {
|
|
20216
20220
|
if (!Number.isFinite(inputTokens) || inputTokens < 0) return inputTokens;
|
|
20217
20221
|
const advertisedWindow = positiveContextWindow(advertisedContextWindow);
|
|
20218
20222
|
if (advertisedWindow === void 0) return inputTokens;
|
|
20219
20223
|
const projectionWindow = positiveContextWindow(upstreamContextWindow) ?? advertisedWindow;
|
|
20220
20224
|
const coordinate = advertisedWindow >= CLAUDE_COMPAT_CONTEXT_WINDOW ? CLAUDE_COMPAT_CONTEXT_WINDOW : CLAUDE_DEFAULT_CONTEXT_WINDOW;
|
|
20221
20225
|
const claudeCompactThreshold = coordinate - CLAUDE_COMPACT_RESERVE;
|
|
20222
|
-
const providerCompactThreshold = projectionWindow
|
|
20226
|
+
const providerCompactThreshold = compactThresholdTokens(projectionWindow, compactCeiling);
|
|
20223
20227
|
if (providerCompactThreshold <= 0) return Math.min(coordinate, inputTokens);
|
|
20224
20228
|
return Math.min(
|
|
20225
20229
|
coordinate,
|
|
20226
20230
|
Math.ceil(inputTokens * claudeCompactThreshold / providerCompactThreshold)
|
|
20227
20231
|
);
|
|
20228
20232
|
}
|
|
20233
|
+
function compactThresholdTokens(window, compactCeiling) {
|
|
20234
|
+
if (!Number.isFinite(window) || window <= 0) return window;
|
|
20235
|
+
const percent2 = compactCeilingPercent(compactCeiling);
|
|
20236
|
+
if (percent2 === void 0) return window - PROVIDER_COMPACT_RESERVE;
|
|
20237
|
+
return Math.floor(window * percent2 / 100);
|
|
20238
|
+
}
|
|
20239
|
+
function compactCeilingPercent(compactCeiling) {
|
|
20240
|
+
if (compactCeiling === "early") return COMPACT_CEILING_EARLY_PERCENT;
|
|
20241
|
+
if (compactCeiling === "late") return COMPACT_CEILING_LATE_PERCENT;
|
|
20242
|
+
if (typeof compactCeiling === "number" && Number.isInteger(compactCeiling) && compactCeiling >= COMPACT_CEILING_CUSTOM_MIN && compactCeiling <= COMPACT_CEILING_CUSTOM_MAX) {
|
|
20243
|
+
return compactCeiling;
|
|
20244
|
+
}
|
|
20245
|
+
return void 0;
|
|
20246
|
+
}
|
|
20247
|
+
function normalizeCompactCeiling(value) {
|
|
20248
|
+
if (value === "early" || value === "late") return value;
|
|
20249
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= COMPACT_CEILING_CUSTOM_MIN && value <= COMPACT_CEILING_CUSTOM_MAX) {
|
|
20250
|
+
return value;
|
|
20251
|
+
}
|
|
20252
|
+
return void 0;
|
|
20253
|
+
}
|
|
20229
20254
|
async function* projectAnthropicResponseUsage(chunks, options) {
|
|
20230
20255
|
const contextWindow = positiveContextWindow(options.contextWindow);
|
|
20231
20256
|
const responseModel = typeof options.responseModel === "string" && options.responseModel.length > 0 ? options.responseModel : void 0;
|
|
@@ -20239,7 +20264,8 @@ async function* projectAnthropicResponseUsage(chunks, options) {
|
|
|
20239
20264
|
chunks,
|
|
20240
20265
|
contextWindow,
|
|
20241
20266
|
responseModel,
|
|
20242
|
-
positiveLimit(options.maxSseFrameBytes, DEFAULT_MAX_SSE_FRAME_BYTES)
|
|
20267
|
+
positiveLimit(options.maxSseFrameBytes, DEFAULT_MAX_SSE_FRAME_BYTES),
|
|
20268
|
+
options.compactCeiling
|
|
20243
20269
|
);
|
|
20244
20270
|
return;
|
|
20245
20271
|
}
|
|
@@ -20248,13 +20274,14 @@ async function* projectAnthropicResponseUsage(chunks, options) {
|
|
|
20248
20274
|
chunks,
|
|
20249
20275
|
contextWindow,
|
|
20250
20276
|
responseModel,
|
|
20251
|
-
positiveLimit(options.maxJsonBytes, DEFAULT_MAX_JSON_BYTES)
|
|
20277
|
+
positiveLimit(options.maxJsonBytes, DEFAULT_MAX_JSON_BYTES),
|
|
20278
|
+
options.compactCeiling
|
|
20252
20279
|
);
|
|
20253
20280
|
return;
|
|
20254
20281
|
}
|
|
20255
20282
|
yield* chunks;
|
|
20256
20283
|
}
|
|
20257
|
-
async function* projectJsonUsage(chunks, contextWindow, responseModel, maxBytes) {
|
|
20284
|
+
async function* projectJsonUsage(chunks, contextWindow, responseModel, maxBytes, compactCeiling) {
|
|
20258
20285
|
const buffered = [];
|
|
20259
20286
|
let bufferedBytes = 0;
|
|
20260
20287
|
let passthrough = false;
|
|
@@ -20274,10 +20301,10 @@ async function* projectJsonUsage(chunks, contextWindow, responseModel, maxBytes)
|
|
|
20274
20301
|
}
|
|
20275
20302
|
if (passthrough || bufferedBytes === 0) return;
|
|
20276
20303
|
const original = concatChunks(buffered, bufferedBytes);
|
|
20277
|
-
const projected = projectJsonBytes(original, contextWindow, responseModel);
|
|
20304
|
+
const projected = projectJsonBytes(original, contextWindow, responseModel, compactCeiling);
|
|
20278
20305
|
yield projected ?? original;
|
|
20279
20306
|
}
|
|
20280
|
-
async function* projectSseUsage(chunks, contextWindow, responseModel, maxFrameBytes) {
|
|
20307
|
+
async function* projectSseUsage(chunks, contextWindow, responseModel, maxFrameBytes, compactCeiling) {
|
|
20281
20308
|
let buffered = new Uint8Array(0);
|
|
20282
20309
|
let oversizedFrame = false;
|
|
20283
20310
|
for await (const chunk of chunks) {
|
|
@@ -20304,7 +20331,7 @@ async function* projectSseUsage(chunks, contextWindow, responseModel, maxFrameBy
|
|
|
20304
20331
|
const frame = buffered.slice(0, separator.index);
|
|
20305
20332
|
const separatorBytes = buffered.slice(separator.index, separator.index + separator.length);
|
|
20306
20333
|
const originalFrame = buffered.slice(0, separator.index + separator.length);
|
|
20307
|
-
const projectedFrame = frame.byteLength > maxFrameBytes ? void 0 : projectSseFrame(frame, contextWindow, responseModel);
|
|
20334
|
+
const projectedFrame = frame.byteLength > maxFrameBytes ? void 0 : projectSseFrame(frame, contextWindow, responseModel, compactCeiling);
|
|
20308
20335
|
yield projectedFrame === void 0 ? originalFrame : concatBytes(projectedFrame, separatorBytes);
|
|
20309
20336
|
buffered = buffered.slice(separator.index + separator.length);
|
|
20310
20337
|
}
|
|
@@ -20318,17 +20345,17 @@ async function* projectSseUsage(chunks, contextWindow, responseModel, maxFrameBy
|
|
|
20318
20345
|
}
|
|
20319
20346
|
if (buffered.byteLength > 0) yield buffered;
|
|
20320
20347
|
}
|
|
20321
|
-
function projectJsonBytes(bytes, contextWindow, responseModel) {
|
|
20348
|
+
function projectJsonBytes(bytes, contextWindow, responseModel, compactCeiling) {
|
|
20322
20349
|
let parsed;
|
|
20323
20350
|
try {
|
|
20324
20351
|
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
20325
20352
|
} catch {
|
|
20326
20353
|
return void 0;
|
|
20327
20354
|
}
|
|
20328
|
-
const projected = projectAnthropicUsageEnvelope(parsed, contextWindow, responseModel);
|
|
20355
|
+
const projected = projectAnthropicUsageEnvelope(parsed, contextWindow, responseModel, compactCeiling);
|
|
20329
20356
|
return projected.changed ? new TextEncoder().encode(JSON.stringify(projected.value)) : void 0;
|
|
20330
20357
|
}
|
|
20331
|
-
function projectSseFrame(frame, contextWindow, responseModel) {
|
|
20358
|
+
function projectSseFrame(frame, contextWindow, responseModel, compactCeiling) {
|
|
20332
20359
|
let text2;
|
|
20333
20360
|
try {
|
|
20334
20361
|
text2 = new TextDecoder("utf-8", { fatal: true }).decode(frame);
|
|
@@ -20354,7 +20381,7 @@ function projectSseFrame(frame, contextWindow, responseModel) {
|
|
|
20354
20381
|
} catch {
|
|
20355
20382
|
return void 0;
|
|
20356
20383
|
}
|
|
20357
|
-
const projected = projectAnthropicUsageEnvelope(parsed, contextWindow, responseModel);
|
|
20384
|
+
const projected = projectAnthropicUsageEnvelope(parsed, contextWindow, responseModel, compactCeiling);
|
|
20358
20385
|
if (!projected.changed) return void 0;
|
|
20359
20386
|
const firstDataIndex = dataIndexes[0];
|
|
20360
20387
|
const dataIndexSet = new Set(dataIndexes);
|
|
@@ -20368,19 +20395,19 @@ function projectSseFrame(frame, contextWindow, responseModel) {
|
|
|
20368
20395
|
}
|
|
20369
20396
|
return new TextEncoder().encode(outputLines.join(newline));
|
|
20370
20397
|
}
|
|
20371
|
-
function projectAnthropicUsageEnvelope(value, contextWindow, responseModel) {
|
|
20398
|
+
function projectAnthropicUsageEnvelope(value, contextWindow, responseModel, compactCeiling) {
|
|
20372
20399
|
if (!isRecord2(value)) return { changed: false, value };
|
|
20373
20400
|
let projectedValue = value;
|
|
20374
20401
|
let changed = false;
|
|
20375
20402
|
if (contextWindow !== void 0) {
|
|
20376
|
-
const topLevelUsage = projectUsageProperty(projectedValue, "usage", contextWindow);
|
|
20403
|
+
const topLevelUsage = projectUsageProperty(projectedValue, "usage", contextWindow, compactCeiling);
|
|
20377
20404
|
if (topLevelUsage.changed) {
|
|
20378
20405
|
projectedValue = topLevelUsage.value;
|
|
20379
20406
|
changed = true;
|
|
20380
20407
|
}
|
|
20381
20408
|
const message = projectedValue.message;
|
|
20382
20409
|
if (isRecord2(message)) {
|
|
20383
|
-
const messageUsage = projectUsageProperty(message, "usage", contextWindow);
|
|
20410
|
+
const messageUsage = projectUsageProperty(message, "usage", contextWindow, compactCeiling);
|
|
20384
20411
|
if (messageUsage.changed) {
|
|
20385
20412
|
projectedValue = { ...projectedValue, message: messageUsage.value };
|
|
20386
20413
|
changed = true;
|
|
@@ -20400,7 +20427,7 @@ function projectAnthropicUsageEnvelope(value, contextWindow, responseModel) {
|
|
|
20400
20427
|
}
|
|
20401
20428
|
return { changed, value: projectedValue };
|
|
20402
20429
|
}
|
|
20403
|
-
function projectUsageProperty(container, property, contextWindow) {
|
|
20430
|
+
function projectUsageProperty(container, property, contextWindow, compactCeiling) {
|
|
20404
20431
|
const usage4 = container[property];
|
|
20405
20432
|
if (!isRecord2(usage4)) return { changed: false, value: container };
|
|
20406
20433
|
const coordinates = ANTHROPIC_INPUT_USAGE_FIELDS.map((field) => {
|
|
@@ -20409,7 +20436,7 @@ function projectUsageProperty(container, property, contextWindow) {
|
|
|
20409
20436
|
}).filter((entry) => entry !== void 0);
|
|
20410
20437
|
if (coordinates.length === 0) return { changed: false, value: container };
|
|
20411
20438
|
const total = coordinates.reduce((sum, entry) => sum + entry.tokens, 0);
|
|
20412
|
-
const projectedTotal = projectClaudeContextInputTokens(total, contextWindow);
|
|
20439
|
+
const projectedTotal = projectClaudeContextInputTokens(total, contextWindow, contextWindow, compactCeiling);
|
|
20413
20440
|
if (projectedTotal === total) return { changed: false, value: container };
|
|
20414
20441
|
const projectedUsage = { ...usage4 };
|
|
20415
20442
|
const remainderField = coordinates.some((entry) => entry.field === "input_tokens") ? "input_tokens" : coordinates[0].field;
|
|
@@ -22073,12 +22100,13 @@ function stringMetadata(metadata) {
|
|
|
22073
22100
|
);
|
|
22074
22101
|
return entries.length === 0 ? void 0 : Object.fromEntries(entries);
|
|
22075
22102
|
}
|
|
22076
|
-
function toAnthropicCacheAwareUsage(rawInputTokens, cachedInputTokens, cacheWriteInputTokens, outputTokens, advertisedContextWindow, upstreamContextWindow) {
|
|
22103
|
+
function toAnthropicCacheAwareUsage(rawInputTokens, cachedInputTokens, cacheWriteInputTokens, outputTokens, advertisedContextWindow, upstreamContextWindow, compactCeiling) {
|
|
22077
22104
|
const safeInputTokens = Number.isFinite(rawInputTokens) && rawInputTokens > 0 ? rawInputTokens : 0;
|
|
22078
22105
|
const projectedTotal = projectClaudeContextInputTokens(
|
|
22079
22106
|
safeInputTokens,
|
|
22080
22107
|
advertisedContextWindow,
|
|
22081
|
-
upstreamContextWindow
|
|
22108
|
+
upstreamContextWindow,
|
|
22109
|
+
compactCeiling
|
|
22082
22110
|
);
|
|
22083
22111
|
if (safeInputTokens === 0) {
|
|
22084
22112
|
return {
|
|
@@ -22128,7 +22156,8 @@ function anthropicUsageFromCanonical(usage4, advertisedContextWindow, options =
|
|
|
22128
22156
|
usage4?.cache_write_input_tokens,
|
|
22129
22157
|
options.forceOutputZero ? 0 : usage4?.output_tokens ?? 0,
|
|
22130
22158
|
advertisedContextWindow,
|
|
22131
|
-
usage4?.context_window
|
|
22159
|
+
usage4?.context_window,
|
|
22160
|
+
options.compactCeiling
|
|
22132
22161
|
);
|
|
22133
22162
|
}
|
|
22134
22163
|
async function collectAnthropicMessage(events, fallbackModel, options = {}) {
|
|
@@ -22231,7 +22260,8 @@ async function collectAnthropicMessage(events, fallbackModel, options = {}) {
|
|
|
22231
22260
|
cacheWriteInputTokens,
|
|
22232
22261
|
outputTokens,
|
|
22233
22262
|
options.contextWindow,
|
|
22234
|
-
upstreamContextWindow
|
|
22263
|
+
upstreamContextWindow,
|
|
22264
|
+
options.compactCeiling
|
|
22235
22265
|
)
|
|
22236
22266
|
};
|
|
22237
22267
|
}
|
|
@@ -22309,7 +22339,8 @@ data: ${JSON.stringify(data)}
|
|
|
22309
22339
|
stop_reason: null,
|
|
22310
22340
|
stop_sequence: null,
|
|
22311
22341
|
usage: anthropicUsageFromCanonical(event.response.usage, options.contextWindow, {
|
|
22312
|
-
forceOutputZero: true
|
|
22342
|
+
forceOutputZero: true,
|
|
22343
|
+
compactCeiling: options.compactCeiling
|
|
22313
22344
|
})
|
|
22314
22345
|
}
|
|
22315
22346
|
});
|
|
@@ -22475,7 +22506,9 @@ data: ${JSON.stringify(data)}
|
|
|
22475
22506
|
// Claude Code updates context occupancy from the terminal cumulative
|
|
22476
22507
|
// usage frame. Sending output-only leaves Responses-backed models at
|
|
22477
22508
|
// zero input usage even though Kimi's native Anthropic stream works.
|
|
22478
|
-
usage: anthropicUsageFromCanonical(event.response.usage, options.contextWindow
|
|
22509
|
+
usage: anthropicUsageFromCanonical(event.response.usage, options.contextWindow, {
|
|
22510
|
+
compactCeiling: options.compactCeiling
|
|
22511
|
+
})
|
|
22479
22512
|
});
|
|
22480
22513
|
yield encode3("message_stop", { type: "message_stop" });
|
|
22481
22514
|
messageStopped = true;
|
|
@@ -22720,6 +22753,20 @@ function nextEventBoundary(buffer) {
|
|
|
22720
22753
|
const match = /\r\n\r\n|\n\n|\r\r/.exec(buffer);
|
|
22721
22754
|
return match === null ? void 0 : { index: match.index, length: match[0].length };
|
|
22722
22755
|
}
|
|
22756
|
+
function nextEventBoundaryBytes(buffer) {
|
|
22757
|
+
for (let index = 0; index < buffer.byteLength; index += 1) {
|
|
22758
|
+
const first = buffer[index];
|
|
22759
|
+
if (first === 10) {
|
|
22760
|
+
if (buffer[index + 1] === 10) return { index, length: 2 };
|
|
22761
|
+
continue;
|
|
22762
|
+
}
|
|
22763
|
+
if (first !== 13) continue;
|
|
22764
|
+
if (buffer[index + 1] === 13) return { index, length: 2 };
|
|
22765
|
+
if (buffer[index + 1] !== 10) continue;
|
|
22766
|
+
if (buffer[index + 2] === 13 && buffer[index + 3] === 10) return { index, length: 4 };
|
|
22767
|
+
}
|
|
22768
|
+
return void 0;
|
|
22769
|
+
}
|
|
22723
22770
|
function parseSseFrameFields(frame) {
|
|
22724
22771
|
let eventName;
|
|
22725
22772
|
const data = [];
|
|
@@ -22863,6 +22910,104 @@ async function* logCanonicalEvents(events, event) {
|
|
|
22863
22910
|
yield item;
|
|
22864
22911
|
}
|
|
22865
22912
|
}
|
|
22913
|
+
function logRawWireEvent(label, eventName, data) {
|
|
22914
|
+
if (!wireLogEnabled()) return;
|
|
22915
|
+
wireLog(label, {
|
|
22916
|
+
...eventName === void 0 ? {} : { event: eventName },
|
|
22917
|
+
data
|
|
22918
|
+
});
|
|
22919
|
+
}
|
|
22920
|
+
var RAW_EVENT_MAX_FRAME_BYTES = 1024 * 1024;
|
|
22921
|
+
var RAW_EVENT_MAX_JSON_BYTES = 16 * 1024 * 1024;
|
|
22922
|
+
async function* logRawPassthroughBody(chunks, options) {
|
|
22923
|
+
if (!wireLogEnabled()) {
|
|
22924
|
+
yield* chunks;
|
|
22925
|
+
return;
|
|
22926
|
+
}
|
|
22927
|
+
const mediaType = options.contentType?.split(";", 1)[0]?.trim().toLowerCase();
|
|
22928
|
+
if (mediaType === "text/event-stream") {
|
|
22929
|
+
yield* tapPassthroughSse(chunks, options.label);
|
|
22930
|
+
return;
|
|
22931
|
+
}
|
|
22932
|
+
if (mediaType === "application/json" || mediaType?.endsWith("+json")) {
|
|
22933
|
+
yield* tapPassthroughJson(chunks, options.label);
|
|
22934
|
+
return;
|
|
22935
|
+
}
|
|
22936
|
+
yield* chunks;
|
|
22937
|
+
}
|
|
22938
|
+
async function* tapPassthroughSse(chunks, label) {
|
|
22939
|
+
let pending = new Uint8Array(0);
|
|
22940
|
+
let oversizedFrame = false;
|
|
22941
|
+
for await (const chunk of chunks) {
|
|
22942
|
+
pending = concatBytes2(pending, chunk);
|
|
22943
|
+
let boundary = nextEventBoundaryBytes(pending);
|
|
22944
|
+
while (boundary !== void 0) {
|
|
22945
|
+
const frame = pending.slice(0, boundary.index);
|
|
22946
|
+
pending = pending.slice(boundary.index + boundary.length);
|
|
22947
|
+
if (!oversizedFrame && frame.byteLength <= RAW_EVENT_MAX_FRAME_BYTES) {
|
|
22948
|
+
tapPassthroughFrameBytes(label, frame);
|
|
22949
|
+
}
|
|
22950
|
+
oversizedFrame = false;
|
|
22951
|
+
boundary = nextEventBoundaryBytes(pending);
|
|
22952
|
+
}
|
|
22953
|
+
if (pending.byteLength > RAW_EVENT_MAX_FRAME_BYTES) {
|
|
22954
|
+
pending = pending.slice(Math.max(0, pending.byteLength - 3));
|
|
22955
|
+
oversizedFrame = true;
|
|
22956
|
+
}
|
|
22957
|
+
yield chunk;
|
|
22958
|
+
}
|
|
22959
|
+
if (!oversizedFrame && pending.byteLength > 0) {
|
|
22960
|
+
tapPassthroughFrameBytes(label, pending);
|
|
22961
|
+
}
|
|
22962
|
+
}
|
|
22963
|
+
function tapPassthroughFrameBytes(label, frameBytes) {
|
|
22964
|
+
let frame;
|
|
22965
|
+
try {
|
|
22966
|
+
frame = new TextDecoder("utf-8", { fatal: true }).decode(frameBytes);
|
|
22967
|
+
} catch {
|
|
22968
|
+
return;
|
|
22969
|
+
}
|
|
22970
|
+
const { event: eventName, data } = parseSseFrameFields(frame);
|
|
22971
|
+
if (data.length === 0 || data === "[DONE]") return;
|
|
22972
|
+
let parsed;
|
|
22973
|
+
try {
|
|
22974
|
+
parsed = JSON.parse(data);
|
|
22975
|
+
} catch {
|
|
22976
|
+
return;
|
|
22977
|
+
}
|
|
22978
|
+
logRawWireEvent(label, eventName, parsed);
|
|
22979
|
+
}
|
|
22980
|
+
async function* tapPassthroughJson(chunks, label) {
|
|
22981
|
+
let pending = new Uint8Array(0);
|
|
22982
|
+
let oversized = false;
|
|
22983
|
+
for await (const chunk of chunks) {
|
|
22984
|
+
if (!oversized) {
|
|
22985
|
+
if (pending.byteLength + chunk.byteLength > RAW_EVENT_MAX_JSON_BYTES) {
|
|
22986
|
+
oversized = true;
|
|
22987
|
+
pending = new Uint8Array(0);
|
|
22988
|
+
} else {
|
|
22989
|
+
pending = concatBytes2(pending, chunk);
|
|
22990
|
+
}
|
|
22991
|
+
}
|
|
22992
|
+
yield chunk;
|
|
22993
|
+
}
|
|
22994
|
+
if (oversized || pending.byteLength === 0) return;
|
|
22995
|
+
let parsed;
|
|
22996
|
+
try {
|
|
22997
|
+
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(pending));
|
|
22998
|
+
} catch {
|
|
22999
|
+
return;
|
|
23000
|
+
}
|
|
23001
|
+
logRawWireEvent(label, void 0, parsed);
|
|
23002
|
+
}
|
|
23003
|
+
function concatBytes2(left, right) {
|
|
23004
|
+
if (left.byteLength === 0) return right;
|
|
23005
|
+
if (right.byteLength === 0) return left;
|
|
23006
|
+
const combined = new Uint8Array(left.byteLength + right.byteLength);
|
|
23007
|
+
combined.set(left, 0);
|
|
23008
|
+
combined.set(right, left.byteLength);
|
|
23009
|
+
return combined;
|
|
23010
|
+
}
|
|
22866
23011
|
var OPENAI_RESPONSES_URL = "https://api.openai.com/v1/responses";
|
|
22867
23012
|
var CHATGPT_CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
22868
23013
|
var DEFAULT_MAX_UPSTREAM_BODY_BYTES = 64 * 1024 * 1024;
|
|
@@ -23293,6 +23438,7 @@ function parseEventFrame(frame) {
|
|
|
23293
23438
|
`OpenAI SSE contained invalid JSON: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
23294
23439
|
);
|
|
23295
23440
|
}
|
|
23441
|
+
logRawWireEvent("openai.wire.event", eventName, parsed);
|
|
23296
23442
|
if (isRecord3(parsed) && typeof parsed.type !== "string" && eventName !== void 0) {
|
|
23297
23443
|
parsed = { ...parsed, type: eventName };
|
|
23298
23444
|
}
|
|
@@ -23790,12 +23936,14 @@ var AnthropicMessagesGateway = class {
|
|
|
23790
23936
|
}),
|
|
23791
23937
|
body: withSseKeepAlive(encodeAnthropicSse(events, {
|
|
23792
23938
|
contextWindow: options.contextWindow,
|
|
23939
|
+
compactCeiling: options.compactCeiling,
|
|
23793
23940
|
model: request.model
|
|
23794
23941
|
}))
|
|
23795
23942
|
};
|
|
23796
23943
|
}
|
|
23797
23944
|
const message = await collectAnthropicMessage(events, request.model, {
|
|
23798
23945
|
contextWindow: options.contextWindow,
|
|
23946
|
+
compactCeiling: options.compactCeiling,
|
|
23799
23947
|
model: request.model
|
|
23800
23948
|
});
|
|
23801
23949
|
return {
|
|
@@ -24521,6 +24669,7 @@ function parseEventFrame2(frame) {
|
|
|
24521
24669
|
`Grok CLI SSE contained invalid JSON: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
24522
24670
|
);
|
|
24523
24671
|
}
|
|
24672
|
+
logRawWireEvent("xai-responses.wire.event", eventName, parsed);
|
|
24524
24673
|
if (isRecord5(parsed) && typeof parsed.type !== "string" && eventName !== void 0) {
|
|
24525
24674
|
parsed = { ...parsed, type: eventName };
|
|
24526
24675
|
}
|
|
@@ -28524,6 +28673,7 @@ ${argumentsText}`;
|
|
|
28524
28673
|
continue;
|
|
28525
28674
|
}
|
|
28526
28675
|
const decodedFrame = decodeCursorServerMessage(frame.payload);
|
|
28676
|
+
logRawWireEvent("cursor.wire.event", void 0, decodedFrame);
|
|
28527
28677
|
if (!isCursorHeartbeatFrame(decodedFrame)) noteSemanticProgress();
|
|
28528
28678
|
handleFrame(decodedFrame);
|
|
28529
28679
|
}
|
|
@@ -29146,12 +29296,14 @@ function normalizeAiGatewaySettings(value) {
|
|
|
29146
29296
|
}];
|
|
29147
29297
|
}) : [];
|
|
29148
29298
|
const providerPriority = sanitizeProviderPriority(value.providerPriority);
|
|
29299
|
+
const compactCeiling = normalizeCompactCeiling(value.compactCeiling);
|
|
29149
29300
|
return {
|
|
29150
29301
|
version: 1,
|
|
29151
29302
|
...models.length > 0 ? { models } : {},
|
|
29152
29303
|
...value.cursorDiagnosticsEnabled === true ? { cursorDiagnosticsEnabled: true } : {},
|
|
29153
29304
|
...typeof value.wireLogEnabled === "boolean" ? { wireLogEnabled: value.wireLogEnabled } : {},
|
|
29154
|
-
...providerPriority ? { providerPriority: [...providerPriority] } : {}
|
|
29305
|
+
...providerPriority ? { providerPriority: [...providerPriority] } : {},
|
|
29306
|
+
...compactCeiling !== void 0 ? { compactCeiling } : {}
|
|
29155
29307
|
};
|
|
29156
29308
|
}
|
|
29157
29309
|
function sanitizeProviderPriority(value) {
|
|
@@ -29757,17 +29909,19 @@ async function* translateChatCompletionsStream(body, options, toolSchemas) {
|
|
|
29757
29909
|
while (boundary !== void 0) {
|
|
29758
29910
|
const frame = buffer.slice(0, boundary.index);
|
|
29759
29911
|
buffer = buffer.slice(boundary.index + boundary.length);
|
|
29760
|
-
const
|
|
29761
|
-
if (
|
|
29762
|
-
|
|
29912
|
+
const frameData = chatFrameData(frame);
|
|
29913
|
+
if (frameData !== void 0) {
|
|
29914
|
+
logRawWireEvent("openai-chat.wire.event", frameData.event, frameData.data);
|
|
29915
|
+
yield* consumeChunk(frameData.data);
|
|
29763
29916
|
}
|
|
29764
29917
|
boundary = nextEventBoundary(buffer);
|
|
29765
29918
|
}
|
|
29766
29919
|
}
|
|
29767
29920
|
if (buffer.trim().length > 0) {
|
|
29768
|
-
const
|
|
29769
|
-
if (
|
|
29770
|
-
|
|
29921
|
+
const frameData = chatFrameData(buffer);
|
|
29922
|
+
if (frameData !== void 0) {
|
|
29923
|
+
logRawWireEvent("openai-chat.wire.event", frameData.event, frameData.data);
|
|
29924
|
+
yield* consumeChunk(frameData.data);
|
|
29771
29925
|
}
|
|
29772
29926
|
}
|
|
29773
29927
|
yield* finish();
|
|
@@ -29777,12 +29931,15 @@ async function* translateChatCompletionsStream(body, options, toolSchemas) {
|
|
|
29777
29931
|
}
|
|
29778
29932
|
}
|
|
29779
29933
|
function chatFrameData(frame) {
|
|
29780
|
-
const { data } = parseSseFrameFields(frame);
|
|
29934
|
+
const { event: eventName, data } = parseSseFrameFields(frame);
|
|
29781
29935
|
if (data.length === 0 || data === "[DONE]") {
|
|
29782
29936
|
return void 0;
|
|
29783
29937
|
}
|
|
29784
29938
|
try {
|
|
29785
|
-
return
|
|
29939
|
+
return {
|
|
29940
|
+
...eventName === void 0 ? {} : { event: eventName },
|
|
29941
|
+
data: JSON.parse(data)
|
|
29942
|
+
};
|
|
29786
29943
|
} catch (error51) {
|
|
29787
29944
|
throw new UpstreamProtocolError(
|
|
29788
29945
|
`Chat Completions SSE contained invalid JSON: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
@@ -29980,6 +30137,7 @@ function parseEventFrame3(frame) {
|
|
|
29980
30137
|
`OpenCode Go SSE contained invalid JSON: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
29981
30138
|
);
|
|
29982
30139
|
}
|
|
30140
|
+
logRawWireEvent("opencode-go-responses.wire.event", eventName, parsed);
|
|
29983
30141
|
if (isRecord11(parsed) && typeof parsed.type !== "string" && eventName !== void 0) {
|
|
29984
30142
|
parsed = { ...parsed, type: eventName };
|
|
29985
30143
|
}
|
|
@@ -30426,9 +30584,14 @@ async function proxyAnthropicMessages(res, body, options) {
|
|
|
30426
30584
|
}
|
|
30427
30585
|
const rawBody = readResponseBody(upstream.body);
|
|
30428
30586
|
const contentType = upstream.headers.get("content-type");
|
|
30429
|
-
const
|
|
30587
|
+
const observedBody = options.wireEventLabel === void 0 ? rawBody : logRawPassthroughBody(rawBody, {
|
|
30588
|
+
label: options.wireEventLabel,
|
|
30589
|
+
contentType
|
|
30590
|
+
});
|
|
30591
|
+
const projectedBody = options.contextWindow === void 0 && options.responseModel === void 0 ? observedBody : projectAnthropicResponseUsage(observedBody, {
|
|
30430
30592
|
contentType,
|
|
30431
30593
|
contextWindow: options.contextWindow,
|
|
30594
|
+
compactCeiling: options.compactCeiling,
|
|
30432
30595
|
responseModel: options.responseModel
|
|
30433
30596
|
});
|
|
30434
30597
|
const responseBody = options.keepAlive === true && contentType?.split(";", 1)[0]?.trim().toLowerCase() === "text/event-stream" ? withSseKeepAlive(projectedBody) : projectedBody;
|
|
@@ -30479,17 +30642,19 @@ function isOpencodeAnthropicPassthrough(model) {
|
|
|
30479
30642
|
function createOpencodeGateway(wire) {
|
|
30480
30643
|
return new AnthropicMessagesGateway(createOpencodeGoAdapter(wire));
|
|
30481
30644
|
}
|
|
30482
|
-
async function proxyToOpencode(requestHeaders, res, body, model, contextWindow, apiKey, fetchImpl, signal) {
|
|
30645
|
+
async function proxyToOpencode(requestHeaders, res, body, model, contextWindow, compactCeiling, apiKey, fetchImpl, signal) {
|
|
30483
30646
|
const headers = opencodeAnthropicHeaders(requestHeaders, apiKey);
|
|
30484
30647
|
const responseModel = typeof body.model === "string" ? body.model : void 0;
|
|
30485
30648
|
await proxyAnthropicMessages(res, opencodeRequestBody(body, model), {
|
|
30486
30649
|
contextWindow,
|
|
30650
|
+
compactCeiling,
|
|
30487
30651
|
responseModel,
|
|
30488
30652
|
keepAlive: true,
|
|
30489
30653
|
fetchImpl,
|
|
30490
30654
|
headers,
|
|
30491
30655
|
signal,
|
|
30492
|
-
url: OPENCODE_GO_MESSAGES_URL
|
|
30656
|
+
url: OPENCODE_GO_MESSAGES_URL,
|
|
30657
|
+
wireEventLabel: "opencode-go-anthropic.wire.event"
|
|
30493
30658
|
});
|
|
30494
30659
|
}
|
|
30495
30660
|
var AI_GATEWAY_ROUTE_SEGMENT = "ai-gateway";
|
|
@@ -30542,6 +30707,13 @@ function createAiGatewayRouter(deps) {
|
|
|
30542
30707
|
return false;
|
|
30543
30708
|
}
|
|
30544
30709
|
};
|
|
30710
|
+
const compactCeiling = () => {
|
|
30711
|
+
try {
|
|
30712
|
+
return gatewaySettings()?.compactCeiling;
|
|
30713
|
+
} catch {
|
|
30714
|
+
return void 0;
|
|
30715
|
+
}
|
|
30716
|
+
};
|
|
30545
30717
|
const handle = async ({ req, res, pathname }) => {
|
|
30546
30718
|
if (pathname.endsWith("/api/hello")) {
|
|
30547
30719
|
res.writeHead(200, { "content-type": "application/json" });
|
|
@@ -30661,6 +30833,7 @@ function createAiGatewayRouter(deps) {
|
|
|
30661
30833
|
return true;
|
|
30662
30834
|
}
|
|
30663
30835
|
const claudeContextWindow = target2.contextWindow;
|
|
30836
|
+
const ceiling = compactCeiling();
|
|
30664
30837
|
if (target2.provider === "kimi") {
|
|
30665
30838
|
await proxyToKimi(
|
|
30666
30839
|
req.headers,
|
|
@@ -30668,6 +30841,7 @@ function createAiGatewayRouter(deps) {
|
|
|
30668
30841
|
body,
|
|
30669
30842
|
upstreamModelId(target2),
|
|
30670
30843
|
claudeContextWindow,
|
|
30844
|
+
ceiling,
|
|
30671
30845
|
credential,
|
|
30672
30846
|
fetchImpl,
|
|
30673
30847
|
controller.signal
|
|
@@ -30681,6 +30855,7 @@ function createAiGatewayRouter(deps) {
|
|
|
30681
30855
|
body,
|
|
30682
30856
|
upstreamModelId(target2),
|
|
30683
30857
|
claudeContextWindow,
|
|
30858
|
+
ceiling,
|
|
30684
30859
|
credential,
|
|
30685
30860
|
fetchImpl,
|
|
30686
30861
|
controller.signal
|
|
@@ -30693,6 +30868,7 @@ function createAiGatewayRouter(deps) {
|
|
|
30693
30868
|
const upstream = await gateway.stream(body, {
|
|
30694
30869
|
apiKey: credential,
|
|
30695
30870
|
...claudeContextWindow ? { contextWindow: claudeContextWindow } : {},
|
|
30871
|
+
...ceiling === void 0 ? {} : { compactCeiling: ceiling },
|
|
30696
30872
|
...modelContextWindow === void 0 ? {} : { modelContextWindow },
|
|
30697
30873
|
...diagnosticsEnabled === void 0 ? {} : { diagnosticsEnabled },
|
|
30698
30874
|
signal: controller.signal,
|
|
@@ -30736,20 +30912,23 @@ async function proxyToAnthropic(requestHeaders, res, body, fetchImpl, signal) {
|
|
|
30736
30912
|
fetchImpl,
|
|
30737
30913
|
headers,
|
|
30738
30914
|
signal,
|
|
30739
|
-
url: ANTHROPIC_MESSAGES_URL
|
|
30915
|
+
url: ANTHROPIC_MESSAGES_URL,
|
|
30916
|
+
wireEventLabel: "anthropic.wire.event"
|
|
30740
30917
|
});
|
|
30741
30918
|
}
|
|
30742
|
-
async function proxyToKimi(requestHeaders, res, body, model, contextWindow, apiKey, fetchImpl, signal) {
|
|
30919
|
+
async function proxyToKimi(requestHeaders, res, body, model, contextWindow, compactCeiling, apiKey, fetchImpl, signal) {
|
|
30743
30920
|
const headers = kimiAnthropicHeaders(requestHeaders, apiKey);
|
|
30744
30921
|
const responseModel = typeof body.model === "string" ? body.model : void 0;
|
|
30745
30922
|
await proxyAnthropicMessages(res, kimiRequestBody(body, model), {
|
|
30746
30923
|
contextWindow,
|
|
30924
|
+
compactCeiling,
|
|
30747
30925
|
responseModel,
|
|
30748
30926
|
keepAlive: true,
|
|
30749
30927
|
fetchImpl,
|
|
30750
30928
|
headers,
|
|
30751
30929
|
signal,
|
|
30752
|
-
url: KIMI_MESSAGES_URL
|
|
30930
|
+
url: KIMI_MESSAGES_URL,
|
|
30931
|
+
wireEventLabel: "kimi-anthropic.wire.event"
|
|
30753
30932
|
});
|
|
30754
30933
|
}
|
|
30755
30934
|
function createGatewayFor(model, chatgptAccountId, originator) {
|
|
@@ -30844,6 +31023,7 @@ function createAiGatewaySettingsStore(deps = {}) {
|
|
|
30844
31023
|
// 우선순위는 이 update 계약이 나르지 않는 별도 표면의 설정이다. 이월하지 않으면
|
|
30845
31024
|
// 무관한 모델 노출 저장 한 번이 사용자의 소진 순서를 지운다.
|
|
30846
31025
|
...current.providerPriority ? { providerPriority: current.providerPriority } : {},
|
|
31026
|
+
...current.compactCeiling !== void 0 ? { compactCeiling: current.compactCeiling } : {},
|
|
30847
31027
|
...value ?? {}
|
|
30848
31028
|
})),
|
|
30849
31029
|
writeCursorDiagnosticsEnabled: (enabled) => update((current) => normalizeAiGatewaySettings({
|
|
@@ -30859,6 +31039,16 @@ function createAiGatewaySettingsStore(deps = {}) {
|
|
|
30859
31039
|
const withoutWireLog = { ...next };
|
|
30860
31040
|
delete withoutWireLog.wireLogEnabled;
|
|
30861
31041
|
return withoutWireLog;
|
|
31042
|
+
}),
|
|
31043
|
+
writeCompactCeiling: (ceiling) => update((current) => {
|
|
31044
|
+
const next = normalizeAiGatewaySettings({
|
|
31045
|
+
...current,
|
|
31046
|
+
...ceiling === void 0 ? {} : { compactCeiling: ceiling }
|
|
31047
|
+
});
|
|
31048
|
+
if (ceiling !== void 0) return next;
|
|
31049
|
+
const withoutCeiling = { ...next };
|
|
31050
|
+
delete withoutCeiling.compactCeiling;
|
|
31051
|
+
return withoutCeiling;
|
|
30862
31052
|
})
|
|
30863
31053
|
};
|
|
30864
31054
|
}
|
|
@@ -30887,7 +31077,7 @@ function readLegacySettings(legacyPath) {
|
|
|
30887
31077
|
return hasStoredValue(settings2) ? { kind: "adopt", settings: settings2 } : { kind: "nothing" };
|
|
30888
31078
|
}
|
|
30889
31079
|
function hasStoredValue(settings2) {
|
|
30890
|
-
return (settings2.models?.length ?? 0) > 0 || settings2.cursorDiagnosticsEnabled !== void 0 || settings2.wireLogEnabled !== void 0;
|
|
31080
|
+
return (settings2.models?.length ?? 0) > 0 || settings2.cursorDiagnosticsEnabled !== void 0 || settings2.wireLogEnabled !== void 0 || settings2.providerPriority !== void 0 || settings2.compactCeiling !== void 0;
|
|
30891
31081
|
}
|
|
30892
31082
|
|
|
30893
31083
|
// ../../packages/fleet-admiral/src/ai-gateway/auth.ts
|
|
@@ -44830,7 +45020,13 @@ function buildAgentCliLaunchKinds(metadata, operationType, gatewaySelection) {
|
|
|
44830
45020
|
id: cli.id,
|
|
44831
45021
|
type: operationType,
|
|
44832
45022
|
title: cli.label,
|
|
44833
|
-
...disabledReason ? { disabled: true, disabledReason } : cli.id === "claude-gateway" ? {
|
|
45023
|
+
...disabledReason ? { disabled: true, disabledReason } : cli.id === "claude-gateway" ? {
|
|
45024
|
+
variants: buildClaudeGatewayLaunchVariants(gatewaySelection),
|
|
45025
|
+
// 채팅으로 태어나는 길은 SDK 인수 계약 위에 서므로 Claude Gateway 종류에서만 열린다
|
|
45026
|
+
// (전환 경로의 `chat_unsupported`와 같은 판정). 다른 종류는 선언하지 않으므로
|
|
45027
|
+
// 컴포저의 시작 뷰 선택 자체가 서지 않는다.
|
|
45028
|
+
launchViews: ["terminal", "chat"]
|
|
45029
|
+
} : {}
|
|
44834
45030
|
};
|
|
44835
45031
|
});
|
|
44836
45032
|
}
|
|
@@ -46497,6 +46693,25 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
46497
46693
|
clearTerminalSessionBackgroundPending(session);
|
|
46498
46694
|
return toTerminalSessionInfo(session);
|
|
46499
46695
|
}
|
|
46696
|
+
function setTerminalSessionChatActive(sessionId, active) {
|
|
46697
|
+
const session = terminalSessionsById.get(sessionId);
|
|
46698
|
+
if (!session) return null;
|
|
46699
|
+
if (session.chatActive === true === active) return null;
|
|
46700
|
+
if (active) session.chatActive = true;
|
|
46701
|
+
else {
|
|
46702
|
+
delete session.chatActive;
|
|
46703
|
+
delete session.chatWorking;
|
|
46704
|
+
}
|
|
46705
|
+
return toTerminalSessionInfo(session);
|
|
46706
|
+
}
|
|
46707
|
+
function setTerminalSessionChatWorking(sessionId, working) {
|
|
46708
|
+
const session = terminalSessionsById.get(sessionId);
|
|
46709
|
+
if (!session || session.chatActive !== true) return null;
|
|
46710
|
+
if (session.chatWorking === true === working) return toTerminalSessionInfo(session);
|
|
46711
|
+
if (working) session.chatWorking = true;
|
|
46712
|
+
else delete session.chatWorking;
|
|
46713
|
+
return toTerminalSessionInfo(session);
|
|
46714
|
+
}
|
|
46500
46715
|
function renameTerminalSession(sessionId, rawLabel) {
|
|
46501
46716
|
const session = terminalSessionsById.get(sessionId);
|
|
46502
46717
|
if (!session) return null;
|
|
@@ -46609,6 +46824,8 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
46609
46824
|
setTerminalSessionBackgroundPending,
|
|
46610
46825
|
getTerminalSessionSettledAgentIds,
|
|
46611
46826
|
setTerminalSessionModelActivity,
|
|
46827
|
+
setTerminalSessionChatActive,
|
|
46828
|
+
setTerminalSessionChatWorking,
|
|
46612
46829
|
transitionTerminalSessionToDormant,
|
|
46613
46830
|
removeTerminalSession,
|
|
46614
46831
|
registerTerminalRuntimeSession,
|
|
@@ -46632,6 +46849,8 @@ function toTerminalSessionInfo(state) {
|
|
|
46632
46849
|
...state.modelActivity ? { modelActivity: state.modelActivity } : {},
|
|
46633
46850
|
...state.attentionPending === true ? { attentionPending: true } : {},
|
|
46634
46851
|
...state.backgroundPending === true ? { backgroundPending: true } : {},
|
|
46852
|
+
...state.chatActive === true ? { chatActive: true } : {},
|
|
46853
|
+
...state.chatWorking === true ? { chatWorking: true } : {},
|
|
46635
46854
|
createdAt: state.createdAt,
|
|
46636
46855
|
theaterId: state.theaterId,
|
|
46637
46856
|
registrationId: state.registrationId,
|
|
@@ -46892,7 +47111,10 @@ var AgentChatSession = class {
|
|
|
46892
47111
|
createSdk;
|
|
46893
47112
|
sdk = null;
|
|
46894
47113
|
sdkFlight = null;
|
|
46895
|
-
/**
|
|
47114
|
+
/**
|
|
47115
|
+
* resume 좌표는 트랜스크립트 파일명이 말하는 세션 id다 — 캡처 id는 드리프트할 수 있다.
|
|
47116
|
+
* `fresh`는 아직 세션이 없으므로 null로 출발하고, 첫 SDK 메시지의 session_id가 이 자리를 채운다.
|
|
47117
|
+
*/
|
|
46896
47118
|
latestSessionId;
|
|
46897
47119
|
journal = [];
|
|
46898
47120
|
seq = 0;
|
|
@@ -46904,16 +47126,18 @@ var AgentChatSession = class {
|
|
|
46904
47126
|
this.operationId = operationId;
|
|
46905
47127
|
this.seed = seed;
|
|
46906
47128
|
this.createSdk = createSdk;
|
|
46907
|
-
this.latestSessionId = path19__default.basename(seed.transcriptPath, ".jsonl");
|
|
47129
|
+
this.latestSessionId = seed.origin.kind === "resume" ? path19__default.basename(seed.origin.transcriptPath, ".jsonl") : null;
|
|
46908
47130
|
}
|
|
46909
47131
|
get busy() {
|
|
46910
47132
|
return this.pendingTurns > 0;
|
|
46911
47133
|
}
|
|
46912
47134
|
async replayTranscript() {
|
|
47135
|
+
if (this.seed.origin.kind === "fresh") return;
|
|
47136
|
+
const transcriptPath = this.seed.origin.transcriptPath;
|
|
46913
47137
|
this.push({ kind: "replay-start" });
|
|
46914
47138
|
let turns = 0;
|
|
46915
47139
|
try {
|
|
46916
|
-
const raw = await promises.readFile(
|
|
47140
|
+
const raw = await promises.readFile(transcriptPath, "utf8");
|
|
46917
47141
|
for (const line of raw.split("\n")) {
|
|
46918
47142
|
if (line.trim().length === 0) continue;
|
|
46919
47143
|
for (const event of chatEventsFromTranscriptLine(line, { cwd: this.seed.cwd })) {
|
|
@@ -46938,6 +47162,13 @@ var AgentChatSession = class {
|
|
|
46938
47162
|
* 턴을 직렬화해 실행한다. 반환은 큐 등록 시점이다 — 진행·실패는 저널 이벤트로 전달된다.
|
|
46939
47163
|
* 실패한 턴은 반드시 run.close()로 슬롯을 반납한다(스파이크에서 실증한 함정).
|
|
46940
47164
|
*/
|
|
47165
|
+
/**
|
|
47166
|
+
* 활동축이 이 세션의 턴을 받을 수 있는지 미리 확인한다. 큐에 넣은 뒤에는 HTTP 응답이 이미
|
|
47167
|
+
* 떠났으므로, 거절은 요청 경계에서만 시끄러울 수 있다.
|
|
47168
|
+
*/
|
|
47169
|
+
canReportActivity() {
|
|
47170
|
+
return this.seed.canReportActivity();
|
|
47171
|
+
}
|
|
46941
47172
|
send(text2) {
|
|
46942
47173
|
if (this.disposed) return;
|
|
46943
47174
|
this.pendingTurns += 1;
|
|
@@ -46995,18 +47226,24 @@ var AgentChatSession = class {
|
|
|
46995
47226
|
/**
|
|
46996
47227
|
* 원 트랜스크립트를 격리 config dir의 같은 projects/<인코딩된 cwd>/ 아래로 복사한다.
|
|
46997
47228
|
* 인코딩 규칙을 재구현하지 않는다 — 원 경로의 부모 디렉터리 이름이 곧 그 인코딩이다.
|
|
47229
|
+
* 채팅으로 태어난 세션에는 복사할 원본이 없다 — SDK가 자기 dir 안에 스스로 만든다.
|
|
46998
47230
|
*/
|
|
46999
47231
|
async copyTranscriptIntoConfigDir(configDir) {
|
|
47000
|
-
|
|
47232
|
+
if (this.seed.origin.kind === "fresh") return;
|
|
47233
|
+
const projectDirName = path19__default.basename(path19__default.dirname(this.seed.origin.transcriptPath));
|
|
47001
47234
|
const dest = path19__default.join(configDir, "projects", projectDirName, `${this.latestSessionId}.jsonl`);
|
|
47002
47235
|
await promises.mkdir(path19__default.dirname(dest), { recursive: true, mode: 448 });
|
|
47003
|
-
await promises.copyFile(this.seed.transcriptPath, dest);
|
|
47236
|
+
await promises.copyFile(this.seed.origin.transcriptPath, dest);
|
|
47004
47237
|
}
|
|
47005
47238
|
async runTurn(text2) {
|
|
47006
47239
|
if (this.disposed) return;
|
|
47007
47240
|
this.push({ kind: "dispatch", text: text2, at: Date.now() });
|
|
47008
47241
|
this.push({ kind: "turn-start", at: Date.now() });
|
|
47009
|
-
this.
|
|
47242
|
+
if (!this.seed.reportActivity(true)) {
|
|
47243
|
+
this.push({ kind: "error", code: "chat_activity_unavailable" });
|
|
47244
|
+
this.push({ kind: "turn-end", ok: false });
|
|
47245
|
+
return;
|
|
47246
|
+
}
|
|
47010
47247
|
let sawResult = false;
|
|
47011
47248
|
try {
|
|
47012
47249
|
const sdk = await this.ensureSdk();
|
|
@@ -47015,7 +47252,9 @@ var AgentChatSession = class {
|
|
|
47015
47252
|
model: this.seed.model,
|
|
47016
47253
|
...this.seed.effort ? { effort: this.seed.effort } : {},
|
|
47017
47254
|
cwd: this.seed.cwd,
|
|
47018
|
-
resume
|
|
47255
|
+
// 채팅으로 태어난 세션의 첫 턴에는 이어붙일 좌표가 없다 — resume 없이 시작하고,
|
|
47256
|
+
// SDK가 돌려주는 session_id가 그 자리를 채운다(그다음 턴부터는 resume이 선다).
|
|
47257
|
+
...this.latestSessionId ? { resume: this.latestSessionId } : {},
|
|
47019
47258
|
permissionMode: "bypassPermissions",
|
|
47020
47259
|
// 스트리밍 감각의 근거 — 글자 단위 text_delta를 받으려면 부분 메시지가 필요하다.
|
|
47021
47260
|
includePartialMessages: true
|
|
@@ -47040,7 +47279,7 @@ var AgentChatSession = class {
|
|
|
47040
47279
|
this.push({ kind: "error", code: "chat_turn_failed" });
|
|
47041
47280
|
if (!sawResult) this.push({ kind: "turn-end", ok: false });
|
|
47042
47281
|
} finally {
|
|
47043
|
-
this.
|
|
47282
|
+
this.seed.reportActivity(false);
|
|
47044
47283
|
}
|
|
47045
47284
|
}
|
|
47046
47285
|
/**
|
|
@@ -47049,15 +47288,19 @@ var AgentChatSession = class {
|
|
|
47049
47288
|
*/
|
|
47050
47289
|
async writeBackTranscript() {
|
|
47051
47290
|
const sdk = this.sdk;
|
|
47052
|
-
if (!sdk) return;
|
|
47053
|
-
const
|
|
47054
|
-
const
|
|
47291
|
+
if (!sdk || !this.latestSessionId) return;
|
|
47292
|
+
const sessionId = this.latestSessionId;
|
|
47293
|
+
const projectDirName = await this.resolveProjectDirName(sdk.configDir);
|
|
47294
|
+
if (!projectDirName) return;
|
|
47295
|
+
const source = path19__default.join(sdk.configDir, "projects", projectDirName, `${sessionId}.jsonl`);
|
|
47055
47296
|
const sourceStat = await promises.stat(source).catch(() => null);
|
|
47056
47297
|
if (!sourceStat?.isFile()) return;
|
|
47057
|
-
const
|
|
47298
|
+
const destDir = this.seed.origin.kind === "resume" ? path19__default.dirname(this.seed.origin.transcriptPath) : path19__default.join(this.seed.origin.transcriptRoot, projectDirName);
|
|
47299
|
+
const dest = path19__default.join(destDir, `${sessionId}.jsonl`);
|
|
47058
47300
|
const destStat = await promises.stat(dest).catch(() => null);
|
|
47059
47301
|
if (destStat?.isFile() && destStat.size > sourceStat.size) return;
|
|
47060
47302
|
try {
|
|
47303
|
+
if (this.seed.origin.kind === "fresh") await promises.mkdir(destDir, { recursive: true, mode: 448 });
|
|
47061
47304
|
await promises.copyFile(source, dest);
|
|
47062
47305
|
} catch {
|
|
47063
47306
|
this.push({ kind: "error", code: "chat_writeback_failed" });
|
|
@@ -47065,12 +47308,25 @@ var AgentChatSession = class {
|
|
|
47065
47308
|
}
|
|
47066
47309
|
this.seed.onProviderSessionUpdate({
|
|
47067
47310
|
provider: "claude",
|
|
47068
|
-
sessionId
|
|
47311
|
+
sessionId,
|
|
47069
47312
|
transcriptPath: dest,
|
|
47070
47313
|
source: "chat-mode",
|
|
47071
47314
|
capturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
47072
47315
|
});
|
|
47073
47316
|
}
|
|
47317
|
+
/**
|
|
47318
|
+
* 이 세션의 트랜스크립트가 앉은 projects 디렉터리 이름. resume은 원 경로가 이미 말해 주고,
|
|
47319
|
+
* fresh는 SDK가 자기 dir 안에 만든 이름을 읽는다 — cwd 인코딩 규칙을 재구현하지 않기 위해서다.
|
|
47320
|
+
* 격리 dir은 이 세션 전용이라 그 아래 projects 항목은 하나뿐이며, 여럿이면 무엇이 우리 것인지
|
|
47321
|
+
* 말할 수 없으므로 되쓰지 않는다(잘못된 뿌리에 남의 세션을 심는 것보다 낫다).
|
|
47322
|
+
*/
|
|
47323
|
+
async resolveProjectDirName(configDir) {
|
|
47324
|
+
if (this.seed.origin.kind === "resume") return path19__default.basename(path19__default.dirname(this.seed.origin.transcriptPath));
|
|
47325
|
+
const entries = await promises.readdir(path19__default.join(configDir, "projects"), { withFileTypes: true }).catch(() => null);
|
|
47326
|
+
if (!entries) return null;
|
|
47327
|
+
const dirs = entries.filter((entry) => entry.isDirectory());
|
|
47328
|
+
return dirs.length === 1 ? dirs[0]?.name ?? null : null;
|
|
47329
|
+
}
|
|
47074
47330
|
};
|
|
47075
47331
|
var AgentChatRegistry = class {
|
|
47076
47332
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -47300,6 +47556,15 @@ function registerTerminalSettingsRoutes(ctx, deps) {
|
|
|
47300
47556
|
));
|
|
47301
47557
|
return true;
|
|
47302
47558
|
}
|
|
47559
|
+
if ("compactCeiling" in update) {
|
|
47560
|
+
const stored = deps.aiGatewayStore.writeCompactCeiling(update.compactCeiling);
|
|
47561
|
+
ctx.host.http.writeJson(res, 200, toTerminalSettingsState(
|
|
47562
|
+
deps.globalOptionsService.load(),
|
|
47563
|
+
stored,
|
|
47564
|
+
deps.wireLogRuntime.enabled()
|
|
47565
|
+
));
|
|
47566
|
+
return true;
|
|
47567
|
+
}
|
|
47303
47568
|
const updated = deps.globalOptionsService.update((current) => ({ ...current, ...update }));
|
|
47304
47569
|
ctx.host.http.writeJson(res, 200, toTerminalSettingsState(
|
|
47305
47570
|
updated,
|
|
@@ -47326,7 +47591,8 @@ function toTerminalSettingsState(data, aiGateway, wireLogEnabled2) {
|
|
|
47326
47591
|
} : null,
|
|
47327
47592
|
aiGatewayCatalog: buildAiGatewayCatalog(),
|
|
47328
47593
|
cursorDiagnosticsEnabled: aiGateway.cursorDiagnosticsEnabled === true,
|
|
47329
|
-
wireLogEnabled: wireLogEnabled2
|
|
47594
|
+
wireLogEnabled: wireLogEnabled2,
|
|
47595
|
+
compactCeiling: aiGateway.compactCeiling ?? null
|
|
47330
47596
|
};
|
|
47331
47597
|
}
|
|
47332
47598
|
function resolveAgentIdleDormantMinutes(data) {
|
|
@@ -47353,6 +47619,11 @@ function parseTerminalSettingsBody(value) {
|
|
|
47353
47619
|
if (keys[0] === "wireLogEnabled") {
|
|
47354
47620
|
return typeof body.wireLogEnabled === "boolean" ? { wireLogEnabled: body.wireLogEnabled } : null;
|
|
47355
47621
|
}
|
|
47622
|
+
if (keys[0] === "compactCeiling") {
|
|
47623
|
+
if (body.compactCeiling === null) return { compactCeiling: void 0 };
|
|
47624
|
+
const ceiling = normalizeCompactCeiling(body.compactCeiling);
|
|
47625
|
+
return ceiling === void 0 ? null : { compactCeiling: ceiling };
|
|
47626
|
+
}
|
|
47356
47627
|
return null;
|
|
47357
47628
|
}
|
|
47358
47629
|
function isAgentIdleDormantMinutes(value) {
|
|
@@ -47407,7 +47678,13 @@ var OPERATION_DELETED_EVENT_CHANNEL = "operation:deleted";
|
|
|
47407
47678
|
var OPERATION_PURGED_EVENT_CHANNEL = "operation:purged";
|
|
47408
47679
|
var TERMINAL_PLUGIN_ID = "terminal";
|
|
47409
47680
|
var CHAT_MODE_PAYLOAD_KEY = "chatMode";
|
|
47681
|
+
var CHAT_BORN_PAYLOAD_KEY = "chatBorn";
|
|
47410
47682
|
var CHAT_SUPPORTED_CLI_ID = "claude-gateway";
|
|
47683
|
+
function resolveClaudeProjectsRoot() {
|
|
47684
|
+
const configured = process4.env.CLAUDE_CONFIG_DIR;
|
|
47685
|
+
const configDir = configured && configured.length > 0 ? configured : path19__default.join(os3__default.homedir(), ".claude");
|
|
47686
|
+
return path19__default.join(configDir, "projects");
|
|
47687
|
+
}
|
|
47411
47688
|
async function registerAgentRoutes(ctx, terminalRuntime, deps) {
|
|
47412
47689
|
const api = await createAgentApi(ctx, terminalRuntime, deps);
|
|
47413
47690
|
terminalRuntime.registerLaunchResolver(AGENT_OPERATION_TYPE, api.launch);
|
|
@@ -47713,6 +47990,15 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
47713
47990
|
const prompt = typeof body?.prompt === "string" ? sanitizeLaunchPrompt(body.prompt) : void 0;
|
|
47714
47991
|
const attachmentIds = readAttachmentIds(body?.attachmentIds, res);
|
|
47715
47992
|
if (attachmentIds === false) return true;
|
|
47993
|
+
if (body?.viewMode !== void 0 && body.viewMode !== "terminal" && body.viewMode !== "chat") {
|
|
47994
|
+
ctx.host.http.writeJson(res, 400, { error: "invalid_view_mode" });
|
|
47995
|
+
return true;
|
|
47996
|
+
}
|
|
47997
|
+
const chatBorn = body?.viewMode === "chat";
|
|
47998
|
+
if (chatBorn && cliId !== CHAT_SUPPORTED_CLI_ID) {
|
|
47999
|
+
ctx.host.http.writeJson(res, 409, { error: "chat_unsupported" });
|
|
48000
|
+
return true;
|
|
48001
|
+
}
|
|
47716
48002
|
const cwd = ctx.host.paths.resolveTheaterPath(theaterId);
|
|
47717
48003
|
if (!cwd) {
|
|
47718
48004
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
@@ -47732,7 +48018,8 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
47732
48018
|
await createSession(cwd, theaterId, cliId, res, {
|
|
47733
48019
|
...launchOptions,
|
|
47734
48020
|
...composedPrompt ? { prompt: composedPrompt } : {},
|
|
47735
|
-
...attachmentIds.length > 0 ? { attachmentIds } : {}
|
|
48021
|
+
...attachmentIds.length > 0 ? { attachmentIds } : {},
|
|
48022
|
+
...chatBorn ? { chatBorn: true } : {}
|
|
47736
48023
|
});
|
|
47737
48024
|
} catch (error51) {
|
|
47738
48025
|
if (attachmentIds.length > 0) launchAttachments.unreserve(attachmentIds);
|
|
@@ -47805,6 +48092,37 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
47805
48092
|
}
|
|
47806
48093
|
return methodNotAllowed2(res);
|
|
47807
48094
|
}
|
|
48095
|
+
async function startChatBornSession(sessionId, res, launchOptions) {
|
|
48096
|
+
const rollback = (status, error51) => {
|
|
48097
|
+
if (launchOptions.attachmentIds && launchOptions.attachmentIds.length > 0) {
|
|
48098
|
+
launchAttachments.unreserve(launchOptions.attachmentIds);
|
|
48099
|
+
}
|
|
48100
|
+
ctx.host.operations.delete(sessionId);
|
|
48101
|
+
observability.removeTerminalSession(sessionId);
|
|
48102
|
+
ctx.host.http.writeJson(res, status, { error: error51 });
|
|
48103
|
+
};
|
|
48104
|
+
const node = ctx.host.operations.get(sessionId);
|
|
48105
|
+
if (!node) return rollback(500, "session_not_found");
|
|
48106
|
+
observability.updateTerminalSessionStatus(sessionId, "dormant");
|
|
48107
|
+
const activated = observability.setTerminalSessionChatActive(sessionId, true);
|
|
48108
|
+
if (activated) observability.notifySessionUpdated(activated);
|
|
48109
|
+
const seed = await resolveChatSeed(node);
|
|
48110
|
+
if (!seed.ok) return rollback(seed.status, seed.error);
|
|
48111
|
+
let chat;
|
|
48112
|
+
try {
|
|
48113
|
+
chat = await chatRegistry.ensure(sessionId, () => seed.seed);
|
|
48114
|
+
} catch {
|
|
48115
|
+
return rollback(503, "chat_unavailable");
|
|
48116
|
+
}
|
|
48117
|
+
if (launchOptions.prompt) chat.send(launchOptions.prompt);
|
|
48118
|
+
if (launchOptions.attachmentIds && launchOptions.attachmentIds.length > 0) {
|
|
48119
|
+
launchAttachments.bind(sessionId, launchOptions.attachmentIds);
|
|
48120
|
+
if (!ctx.host.operations.get(sessionId)) launchAttachments.releaseSession(sessionId);
|
|
48121
|
+
}
|
|
48122
|
+
const created = observability.getTerminalSessionInfo(sessionId);
|
|
48123
|
+
if (created) observability.notifySessionUpdated(created);
|
|
48124
|
+
ctx.host.http.writeJson(res, 200, created ?? { sessionId });
|
|
48125
|
+
}
|
|
47808
48126
|
async function createSession(cwd, theaterId, cliId, res, launchOptions = {}) {
|
|
47809
48127
|
const meta3 = (await buildAgentCliLaunchMetadata()).find((entry) => entry.id === cliId);
|
|
47810
48128
|
if (!meta3 || !meta3.available || !meta3.signedIn) {
|
|
@@ -47832,10 +48150,17 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
47832
48150
|
// Claude Code의 resume가 launch 좌표를 자체 복원한다고 가정하지 않는다 — 정규화된
|
|
47833
48151
|
// 최초 선택을 Operation에 남겨 dormant·Console 재시작 뒤에도 같은 인자로 재개한다.
|
|
47834
48152
|
...launchOptions.model ? { launchModel: launchOptions.model } : {},
|
|
47835
|
-
...launchOptions.effort ? { launchEffort: launchOptions.effort } : {}
|
|
48153
|
+
...launchOptions.effort ? { launchEffort: launchOptions.effort } : {},
|
|
48154
|
+
// 채팅으로 태어난 Operation은 두 마커를 함께 진다. chatMode가 뷰를 가르고, chatBorn이
|
|
48155
|
+
// "transcript 부재는 상실이 아니라 아직 첫 턴 전"이라는 뜻을 durable하게 남긴다.
|
|
48156
|
+
...launchOptions.chatBorn ? { [CHAT_MODE_PAYLOAD_KEY]: true, [CHAT_BORN_PAYLOAD_KEY]: true } : {}
|
|
47836
48157
|
},
|
|
47837
48158
|
createdAt: session.createdAt
|
|
47838
48159
|
});
|
|
48160
|
+
if (launchOptions.chatBorn) {
|
|
48161
|
+
await startChatBornSession(sessionId, res, launchOptions);
|
|
48162
|
+
return;
|
|
48163
|
+
}
|
|
47839
48164
|
try {
|
|
47840
48165
|
await terminalRuntime.attach({
|
|
47841
48166
|
cwd,
|
|
@@ -47911,6 +48236,8 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
47911
48236
|
const cleared = { ...ctx.host.operations.get(sessionId)?.payload ?? node.payload };
|
|
47912
48237
|
delete cleared[CHAT_MODE_PAYLOAD_KEY];
|
|
47913
48238
|
ctx.host.operations.patch(sessionId, { payload: cleared });
|
|
48239
|
+
const releasedOnResume = observability.setTerminalSessionChatActive(sessionId, false);
|
|
48240
|
+
if (releasedOnResume) observability.notifySessionUpdated(releasedOnResume);
|
|
47914
48241
|
resumeNode = ctx.host.operations.get(sessionId) ?? node;
|
|
47915
48242
|
if (!fresh) resumeProviderSession = readProviderSession(resumeNode.payload) ?? providerSession;
|
|
47916
48243
|
}
|
|
@@ -48038,6 +48365,11 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
48038
48365
|
}
|
|
48039
48366
|
try {
|
|
48040
48367
|
const chat = await chatRegistry.ensure(sessionId, () => seed.seed);
|
|
48368
|
+
if (!chat.canReportActivity()) {
|
|
48369
|
+
settleAttachments(false);
|
|
48370
|
+
ctx.host.http.writeJson(res, 503, { error: "chat_activity_unavailable" });
|
|
48371
|
+
return true;
|
|
48372
|
+
}
|
|
48041
48373
|
chat.send(composeLaunchPromptWithAttachments(text2.trim(), attachmentPaths));
|
|
48042
48374
|
} catch {
|
|
48043
48375
|
settleAttachments(false);
|
|
@@ -48115,6 +48447,8 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
48115
48447
|
const cleared = { ...ctx.host.operations.get(sessionId)?.payload ?? node.payload };
|
|
48116
48448
|
delete cleared[CHAT_MODE_PAYLOAD_KEY];
|
|
48117
48449
|
ctx.host.operations.patch(sessionId, { payload: cleared });
|
|
48450
|
+
const released = observability.setTerminalSessionChatActive(sessionId, false);
|
|
48451
|
+
if (released) observability.notifySessionUpdated(released);
|
|
48118
48452
|
ctx.host.http.writeJson(res, 200, { ok: true });
|
|
48119
48453
|
return true;
|
|
48120
48454
|
}
|
|
@@ -48140,6 +48474,8 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
48140
48474
|
}
|
|
48141
48475
|
}
|
|
48142
48476
|
ctx.host.operations.patch(sessionId, { payload: { ...node.payload, [CHAT_MODE_PAYLOAD_KEY]: true } });
|
|
48477
|
+
const activated = observability.setTerminalSessionChatActive(sessionId, true);
|
|
48478
|
+
if (activated) observability.notifySessionUpdated(activated);
|
|
48143
48479
|
if (live) {
|
|
48144
48480
|
terminalRuntime.invalidateTicketsForSession(sessionId);
|
|
48145
48481
|
terminalRuntime.terminate(sessionId);
|
|
@@ -48215,9 +48551,11 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
48215
48551
|
return { ok: false, status: 409, error: "chat_unsupported" };
|
|
48216
48552
|
}
|
|
48217
48553
|
const providerSession = readProviderSession(node.payload);
|
|
48218
|
-
|
|
48219
|
-
const
|
|
48220
|
-
|
|
48554
|
+
const transcriptPath = providerSession?.transcriptPath ? await resolveTranscriptPath(providerSession.transcriptPath, node.ts.createdAt) : null;
|
|
48555
|
+
const chatBorn = node.payload[CHAT_BORN_PAYLOAD_KEY] === true;
|
|
48556
|
+
const neverStarted = chatBorn && !providerSession;
|
|
48557
|
+
if (!transcriptPath && !neverStarted) return { ok: false, status: 409, error: "chat_transcript_missing" };
|
|
48558
|
+
const sessionOrigin = transcriptPath ? { kind: "resume", transcriptPath } : { kind: "fresh", transcriptRoot: resolveClaudeProjectsRoot() };
|
|
48221
48559
|
const origin = ctx.host.server.origin();
|
|
48222
48560
|
if (!origin) return { ok: false, status: 503, error: "chat_gateway_unavailable" };
|
|
48223
48561
|
const cwd = readPayloadString(node.payload, "cwd") || ctx.host.paths.resolveTheaterPath(node.theaterId);
|
|
@@ -48231,11 +48569,18 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
48231
48569
|
model,
|
|
48232
48570
|
...effort ? { effort } : {},
|
|
48233
48571
|
cwd,
|
|
48234
|
-
|
|
48572
|
+
origin: sessionOrigin,
|
|
48235
48573
|
onProviderSessionUpdate: (updated) => {
|
|
48236
48574
|
const operation = ctx.host.operations.get(node.id);
|
|
48237
48575
|
if (operation) ctx.host.operations.patch(node.id, { payload: { ...operation.payload, providerSession: updated } });
|
|
48238
48576
|
observability.updateTerminalSessionProviderSession(node.id, updated);
|
|
48577
|
+
},
|
|
48578
|
+
canReportActivity: () => observability.getTerminalSessionInfo(node.id)?.chatActive === true,
|
|
48579
|
+
reportActivity: (working) => {
|
|
48580
|
+
const updated = observability.setTerminalSessionChatWorking(node.id, working);
|
|
48581
|
+
if (!updated) return false;
|
|
48582
|
+
observability.notifySessionUpdated(updated);
|
|
48583
|
+
return true;
|
|
48239
48584
|
}
|
|
48240
48585
|
}
|
|
48241
48586
|
};
|
|
@@ -48492,8 +48837,13 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
48492
48837
|
for (const operation of ctx.host.operations.list()) {
|
|
48493
48838
|
if (operation.pluginId !== ctx.pluginId || operation.type !== AGENT_OPERATION_TYPE) continue;
|
|
48494
48839
|
const providerSession = readProviderSession(operation.payload);
|
|
48495
|
-
|
|
48840
|
+
const chatBorn = operation.payload[CHAT_BORN_PAYLOAD_KEY] === true;
|
|
48841
|
+
if (!providerSession && !chatBorn || observability.getTerminalSessionInfo(operation.id)) continue;
|
|
48496
48842
|
const dormant = injectOperation(operation);
|
|
48843
|
+
if (operation.payload[CHAT_MODE_PAYLOAD_KEY] === true) {
|
|
48844
|
+
const adopted = observability.setTerminalSessionChatActive(operation.id, true);
|
|
48845
|
+
if (adopted) observability.notifySessionUpdated(adopted);
|
|
48846
|
+
}
|
|
48497
48847
|
const cwd = readPayloadString(operation.payload, "cwd") || (ctx.host.paths.resolveTheaterPath(operation.theaterId) ?? "");
|
|
48498
48848
|
ctx.host.operations.patch(operation.id, { payload: toOperationPayload(operation.payload, cwd, dormant, providerSession, observability.getDurableOperation(operation.id)?.providerTitle) });
|
|
48499
48849
|
}
|