@cmmd-center/forge 0.10.6 → 0.10.8
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/dist/bin.cjs +1235 -764
- package/dist/bin.mjs +1235 -762
- package/dist/client/assets/{CanvasPanel-Dr4I7MnM.js → CanvasPanel-ECmvVI7T.js} +2 -2
- package/dist/client/assets/{CompositeItem-Cj6_oAlz.js → CompositeItem-8hzrVacr.js} +2 -2
- package/dist/client/assets/{DiffPanel-njtnlFro.js → DiffPanel-BmZCQ7ie.js} +3 -3
- package/dist/client/assets/{DiffPanel.logic-BiWRNb4k.js → DiffPanel.logic-EQgKCWRo.js} +2 -2
- package/dist/client/assets/DiffPanelShell-CpaWJE6J.js +2531 -0
- package/dist/client/assets/{DiffWorkerPoolProvider-DWrja16U.js → DiffWorkerPoolProvider-CU7zWBfP.js} +8 -8
- package/dist/client/assets/{PullRequestCodePanel-CAaq9dk8.js → PullRequestCodePanel-FhNDL-Wv.js} +3 -3
- package/dist/client/assets/{Virtualizer-BXpiamky.js → Virtualizer-BLq-Dt-i.js} +2 -2
- package/dist/client/assets/{canvasStateStore-DncdOQ4J.js → canvasStateStore-3EN8RaUf.js} +2 -2
- package/dist/client/assets/{cmmdAuthRedirect-DWiMDVzN.js → cmmdAuthRedirect-DwPtzhq9.js} +2 -2
- package/dist/client/assets/index-BYEPqKu0.js +151 -0
- package/dist/client/assets/index-D22UpSjv.css +1 -0
- package/dist/client/assets/{src-CtyKlVph.js → src-DZBONdiY.js} +2 -2
- package/dist/client/assets/{toggle-pTm2fPLg.js → toggle-mQ7UG7Dd.js} +2 -2
- package/dist/client/assets/{useTriggerFocusGuards-B4Ejoaox.js → useTriggerFocusGuards-BUEnX8xa.js} +2 -2
- package/dist/client/index.html +11 -11
- package/dist/forge-build.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/DiffPanelShell-AKUK0L-g.js +0 -2531
- package/dist/client/assets/index-DBIIL0ML.js +0 -151
- package/dist/client/assets/index-T36rURmx.css +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -16520,7 +16520,7 @@ function makeNetServiceShape(createServer = Net.createServer) {
|
|
|
16520
16520
|
}
|
|
16521
16521
|
//#endregion
|
|
16522
16522
|
//#region ../../packages/shared/src/releaseInfo.generated.ts
|
|
16523
|
-
const FORGE_RELEASE_VERSION = "0.10.
|
|
16523
|
+
const FORGE_RELEASE_VERSION = "0.10.5";
|
|
16524
16524
|
//#endregion
|
|
16525
16525
|
//#region ../../packages/shared/src/hostProcess.ts
|
|
16526
16526
|
/**
|
|
@@ -24231,6 +24231,7 @@ const UsageBucket = Struct({
|
|
|
24231
24231
|
costSource: UsageCostSource,
|
|
24232
24232
|
records: NonNegativeInt,
|
|
24233
24233
|
unpricedRecords: NonNegativeInt,
|
|
24234
|
+
unreportedRecords: optional$4(NonNegativeInt),
|
|
24234
24235
|
sessions: NonNegativeInt,
|
|
24235
24236
|
runtimeId: optional$4(TrimmedNonEmptyString),
|
|
24236
24237
|
origin: optional$4(UsageBucketOrigin),
|
|
@@ -65120,7 +65121,7 @@ function normalizeNumberish(value) {
|
|
|
65120
65121
|
}
|
|
65121
65122
|
//#endregion
|
|
65122
65123
|
//#region package.json
|
|
65123
|
-
var version$1 = "0.10.
|
|
65124
|
+
var version$1 = "0.10.8";
|
|
65124
65125
|
//#endregion
|
|
65125
65126
|
//#region src/sentry.ts
|
|
65126
65127
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -70026,6 +70027,14 @@ function invalidateCachedCmmdWorkIntakeForIdentity(identityKey) {
|
|
|
70026
70027
|
*
|
|
70027
70028
|
* Bespoke routes (MCP/PAT transport, hybrid fallback, multipart) stay in
|
|
70028
70029
|
* http.ts and are NOT migrated here.
|
|
70030
|
+
*
|
|
70031
|
+
* A second, narrower entry point — `registerProxyHandler` / `ProxyHandlerRoute`
|
|
70032
|
+
* — covers routes whose middle (request parsing, the actual gateway call,
|
|
70033
|
+
* success shaping) cannot be expressed by the five `ProxyRoute` fields above,
|
|
70034
|
+
* while still sharing the same prologue: session auth, the CMMD-connection
|
|
70035
|
+
* gate, and the same `buildProxyErrorResponse` error mapping plus
|
|
70036
|
+
* `clearUnrecoverableCmmdAuthForSession` on an auth failure. See the type doc
|
|
70037
|
+
* below for the exact contract.
|
|
70029
70038
|
*/
|
|
70030
70039
|
/** Substitutes ":paramName" tokens in a path template from a params record. */
|
|
70031
70040
|
function substitutePath(template, params) {
|
|
@@ -70075,6 +70084,29 @@ function buildProxyErrorResponse(error) {
|
|
|
70075
70084
|
}
|
|
70076
70085
|
return jsonUnsafe({ error: "CMMD REST request failed." }, { status: 502 });
|
|
70077
70086
|
}
|
|
70087
|
+
/**
|
|
70088
|
+
* Clears every unrecoverable CMMD credential tied to this session, logging a
|
|
70089
|
+
* warning rather than failing the request if the clear itself errors — a
|
|
70090
|
+
* session that already has no usable credential must still get its 401,
|
|
70091
|
+
* not a 500 from a failed best-effort cleanup.
|
|
70092
|
+
*/
|
|
70093
|
+
function clearCmmdAuthAfterFailure(sessionId) {
|
|
70094
|
+
return clearUnrecoverableCmmdAuthForSession(sessionId).pipe(catch_((error) => logWarning$1("Failed to clear unrecoverable CMMD auth after CMMD auth failure.", {
|
|
70095
|
+
cause: error,
|
|
70096
|
+
sessionId
|
|
70097
|
+
})));
|
|
70098
|
+
}
|
|
70099
|
+
/**
|
|
70100
|
+
* The single "no usable CMMD credential" response: clears whatever
|
|
70101
|
+
* unrecoverable auth state this session is holding, then returns the
|
|
70102
|
+
* canonical `CMMD_AUTH_REQUIRED` body. Every prologue path that decides the
|
|
70103
|
+
* session has no way to reach CMMD — a missing PAT, a JWT that fails to
|
|
70104
|
+
* resolve, a bespoke gate elsewhere in http.ts — emits this same response so
|
|
70105
|
+
* the Shell only ever has one `CMMD_AUTH_REQUIRED` body to branch on.
|
|
70106
|
+
*/
|
|
70107
|
+
function respondCmmdConnectionRequired(sessionId) {
|
|
70108
|
+
return clearCmmdAuthAfterFailure(sessionId).pipe(as$3(buildProxyErrorResponse(new CmmdProxyAuthenticationRequiredError("CMMD connection required. Reconnect CMMD to continue."))));
|
|
70109
|
+
}
|
|
70078
70110
|
async function dispatchToProxy(method, jwt, cmmdPath, rawBody, orgId, searchParams) {
|
|
70079
70111
|
return cmmdGateway.request({
|
|
70080
70112
|
method,
|
|
@@ -70105,12 +70137,27 @@ function buildProxySearchParams(input) {
|
|
|
70105
70137
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
70106
70138
|
}
|
|
70107
70139
|
const _registeredRoutes = [];
|
|
70108
|
-
|
|
70109
|
-
|
|
70110
|
-
*
|
|
70111
|
-
|
|
70112
|
-
|
|
70113
|
-
|
|
70140
|
+
const _registeredLayers = [];
|
|
70141
|
+
/**
|
|
70142
|
+
* Layers produced by every registerProxyRoute call so far, in registration
|
|
70143
|
+
* order. Callers that want only the routes registered by their own module
|
|
70144
|
+
* should snapshot `.length` before their own registerProxyRoute calls run and
|
|
70145
|
+
* slice from that index — see command/http.ts's `cmmdProxyRouteLayers`.
|
|
70146
|
+
*
|
|
70147
|
+
* Typed via `ReturnType<typeof buildProxyRouteLayer>` (not `HttpRouter.add`
|
|
70148
|
+
* directly, and not `registerProxyRoute` itself — that would be circular
|
|
70149
|
+
* since registerProxyRoute pushes onto this same array): `buildProxyRouteLayer`
|
|
70150
|
+
* takes a concrete, non-generic `ProxyRoute` argument and never references
|
|
70151
|
+
* this array, so its return type is fully resolved independently. Referencing
|
|
70152
|
+
* the generic `HttpRouter.add` on its own instead collapses its unresolved E/R
|
|
70153
|
+
* type parameters to `unknown`, which then leaks into makeRoutesLayer's
|
|
70154
|
+
* requirements channel everywhere this array is spread.
|
|
70155
|
+
*/
|
|
70156
|
+
function registeredProxyRouteLayers() {
|
|
70157
|
+
return Object.freeze([..._registeredLayers]);
|
|
70158
|
+
}
|
|
70159
|
+
/** Builds the Effect HttpRouter layer for one route, with no registry side effects. */
|
|
70160
|
+
function buildProxyRouteLayer(route) {
|
|
70114
70161
|
const handler = gen(function* () {
|
|
70115
70162
|
const req = yield* HttpServerRequest;
|
|
70116
70163
|
const session = yield* (yield* ServerAuth).authenticateHttpRequest(req);
|
|
@@ -70133,23 +70180,14 @@ function registerProxyRoute(route) {
|
|
|
70133
70180
|
forceRefresh
|
|
70134
70181
|
});
|
|
70135
70182
|
const jwt = yield* resolveJwt();
|
|
70136
|
-
if (!jwt)
|
|
70137
|
-
yield* clearUnrecoverableCmmdAuthForSession(session.sessionId).pipe(catch_((error) => logWarning$1("Failed to clear unrecoverable CMMD auth after missing JWT.", {
|
|
70138
|
-
cause: error,
|
|
70139
|
-
sessionId: session.sessionId
|
|
70140
|
-
})));
|
|
70141
|
-
return buildProxyErrorResponse(new CmmdProxyAuthenticationRequiredError("CMMD connection required. Reconnect CMMD to continue."));
|
|
70142
|
-
}
|
|
70183
|
+
if (!jwt) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
70143
70184
|
let outcome = yield* promise(() => runProxy(() => dispatchToProxy(route.method, jwt, cmmdPath, rawBody, orgId, searchParams)));
|
|
70144
70185
|
if (!outcome.ok && outcome.error instanceof CmmdProxyAuthError) {
|
|
70145
70186
|
const refreshedJwt = yield* resolveJwt(true);
|
|
70146
70187
|
if (refreshedJwt && refreshedJwt !== jwt) outcome = yield* promise(() => runProxy(() => dispatchToProxy(route.method, refreshedJwt, cmmdPath, rawBody, orgId, searchParams)));
|
|
70147
70188
|
}
|
|
70148
70189
|
if (!outcome.ok) {
|
|
70149
|
-
if (outcome.error instanceof CmmdProxyAuthError || outcome.error instanceof CmmdProxyAuthenticationRequiredError) yield*
|
|
70150
|
-
cause: error,
|
|
70151
|
-
sessionId: session.sessionId
|
|
70152
|
-
})));
|
|
70190
|
+
if (outcome.error instanceof CmmdProxyAuthError || outcome.error instanceof CmmdProxyAuthenticationRequiredError) yield* clearCmmdAuthAfterFailure(session.sessionId);
|
|
70153
70191
|
return buildProxyErrorResponse(outcome.error);
|
|
70154
70192
|
}
|
|
70155
70193
|
const payload = route.responseShape === "passthrough" ? outcome.value : unwrapEnvelope$1(outcome.value);
|
|
@@ -70159,6 +70197,59 @@ function registerProxyRoute(route) {
|
|
|
70159
70197
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error)));
|
|
70160
70198
|
return add$1(route.method, route.forgePath, handler);
|
|
70161
70199
|
}
|
|
70200
|
+
/**
|
|
70201
|
+
* Generates an Effect HttpRouter layer for the given route and records it in
|
|
70202
|
+
* the registry (for auditing / tests, and so command/http.ts's
|
|
70203
|
+
* `cmmdProxyRouteLayers` can pick it up). The returned layer registers one
|
|
70204
|
+
* handler at forgePath.
|
|
70205
|
+
*/
|
|
70206
|
+
function registerProxyRoute(route) {
|
|
70207
|
+
_registeredRoutes.push(route);
|
|
70208
|
+
const layer = buildProxyRouteLayer(route);
|
|
70209
|
+
_registeredLayers.push(layer);
|
|
70210
|
+
return layer;
|
|
70211
|
+
}
|
|
70212
|
+
/**
|
|
70213
|
+
* Builds the bare handler Effect for one handler route (no `HttpRouter.add`
|
|
70214
|
+
* wrapping, no registry side effects) — exposed on its own so tests can
|
|
70215
|
+
* exercise it the same way they exercise every other bespoke handler in
|
|
70216
|
+
* http.ts: providing `HttpServerRequest` / `ServerAuth` directly and running
|
|
70217
|
+
* the Effect, without standing up a router.
|
|
70218
|
+
*/
|
|
70219
|
+
function buildProxyHandlerEffect(route) {
|
|
70220
|
+
return gen(function* () {
|
|
70221
|
+
const req = yield* HttpServerRequest;
|
|
70222
|
+
const session = yield* (yield* ServerAuth).authenticateHttpRequest(req);
|
|
70223
|
+
if (!readCommandAccessTokenForSession(session.sessionId)) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
70224
|
+
const parsed = yield* route.parse(req);
|
|
70225
|
+
if (!parsed.ok) return jsonUnsafe(parsed.body, { status: parsed.status });
|
|
70226
|
+
const result$4 = yield* route.run(parsed.value, { session }).pipe(result);
|
|
70227
|
+
if (isFailure$1(result$4)) {
|
|
70228
|
+
const error = result$4.failure;
|
|
70229
|
+
if (error instanceof CmmdProxyAuthError || error instanceof CmmdProxyAuthenticationRequiredError) yield* clearCmmdAuthAfterFailure(session.sessionId);
|
|
70230
|
+
return buildProxyErrorResponse(error);
|
|
70231
|
+
}
|
|
70232
|
+
return jsonUnsafe(result$4.success.body, { status: result$4.success.status });
|
|
70233
|
+
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error)));
|
|
70234
|
+
}
|
|
70235
|
+
const _registeredHandlerRoutes = [];
|
|
70236
|
+
/**
|
|
70237
|
+
* Builds the handler Effect for one route, mounts it via `HttpRouter.add` and
|
|
70238
|
+
* records that layer in the same registry `registerProxyRoute` uses (so
|
|
70239
|
+
* command/http.ts's `cmmdProxyRouteLayers` picks it up without a separate
|
|
70240
|
+
* mount list) — then returns the bare handler Effect rather than the layer,
|
|
70241
|
+
* so the caller can keep a single `__xHandlerForTests`-style export that
|
|
70242
|
+
* doubles as both the thing under test and the thing that gets mounted.
|
|
70243
|
+
*/
|
|
70244
|
+
function registerProxyHandler(route) {
|
|
70245
|
+
_registeredHandlerRoutes.push({
|
|
70246
|
+
method: route.method,
|
|
70247
|
+
forgePath: route.forgePath
|
|
70248
|
+
});
|
|
70249
|
+
const handler = buildProxyHandlerEffect(route);
|
|
70250
|
+
_registeredLayers.push(add$1(route.method, route.forgePath, handler));
|
|
70251
|
+
return handler;
|
|
70252
|
+
}
|
|
70162
70253
|
//#endregion
|
|
70163
70254
|
//#region src/connect/credentialRefresh.ts
|
|
70164
70255
|
async function refreshConnectCredential(deps) {
|
|
@@ -92271,6 +92362,172 @@ function classifyRuntimeReplicationHttpFailure(failure) {
|
|
|
92271
92362
|
};
|
|
92272
92363
|
}
|
|
92273
92364
|
//#endregion
|
|
92365
|
+
//#region src/runtimeReplication/runtimeLane.ts
|
|
92366
|
+
/**
|
|
92367
|
+
* Read a grant-lane response the way the gateway reads an owner-lane one: a
|
|
92368
|
+
* non-2xx becomes a `CmmdProxyRequestError` carrying the status and CMMD's
|
|
92369
|
+
* error code, so a caller can classify either lane's failure with one rule.
|
|
92370
|
+
*/
|
|
92371
|
+
async function parseRuntimeLaneResponse(response) {
|
|
92372
|
+
const text = await response.text();
|
|
92373
|
+
let body = null;
|
|
92374
|
+
if (text) try {
|
|
92375
|
+
body = JSON.parse(text);
|
|
92376
|
+
} catch {
|
|
92377
|
+
body = null;
|
|
92378
|
+
}
|
|
92379
|
+
if (!response.ok) {
|
|
92380
|
+
const code = readRuntimeReplicationErrorCode(body);
|
|
92381
|
+
throw new CmmdProxyRequestError(`CMMD runtime replication failed (${response.status})`, response.status, null, code ? { code } : null);
|
|
92382
|
+
}
|
|
92383
|
+
if (body === null) throw new Error("CMMD runtime replication returned an empty or invalid JSON response.");
|
|
92384
|
+
return body;
|
|
92385
|
+
}
|
|
92386
|
+
/**
|
|
92387
|
+
* One request on whichever lane the runtime holds. The caller has already
|
|
92388
|
+
* built the path for `lane.kind`; this only decides the transport and the
|
|
92389
|
+
* credential header, and normalises failures to the gateway's error classes.
|
|
92390
|
+
*/
|
|
92391
|
+
async function requestOnRuntimeLane(lane, request, transport = {}) {
|
|
92392
|
+
if (lane.kind === "owner-session") return (transport.gateway ?? cmmdGateway).request({
|
|
92393
|
+
method: request.method,
|
|
92394
|
+
jwt: lane.jwt,
|
|
92395
|
+
path: request.path,
|
|
92396
|
+
...request.body === void 0 ? {} : { body: request.body }
|
|
92397
|
+
});
|
|
92398
|
+
return parseRuntimeLaneResponse(await (transport.fetchImpl ?? fetch)(new URL(request.path, `${lane.controlPlaneUrl}/`), {
|
|
92399
|
+
method: request.method,
|
|
92400
|
+
headers: {
|
|
92401
|
+
authorization: `Bearer ${lane.grantToken}`,
|
|
92402
|
+
accept: "application/json",
|
|
92403
|
+
...request.body === void 0 ? {} : { "content-type": "application/json" }
|
|
92404
|
+
},
|
|
92405
|
+
...request.body === void 0 ? {} : { body: JSON.stringify(request.body) },
|
|
92406
|
+
...request.signal === void 0 ? {} : { signal: request.signal }
|
|
92407
|
+
}));
|
|
92408
|
+
}
|
|
92409
|
+
function mapRuntimeReplicationClientError(error, operation) {
|
|
92410
|
+
if (error instanceof CmmdProxyAuthError) return new RuntimeReplicationClientError({
|
|
92411
|
+
kind: "auth",
|
|
92412
|
+
code: "CMMD_AUTH_REQUIRED",
|
|
92413
|
+
detail: error.message
|
|
92414
|
+
});
|
|
92415
|
+
if (error instanceof CmmdProxyAuthenticationRequiredError) return new RuntimeReplicationClientError({
|
|
92416
|
+
kind: "auth",
|
|
92417
|
+
code: "CMMD_AUTH_REQUIRED",
|
|
92418
|
+
detail: error.message
|
|
92419
|
+
});
|
|
92420
|
+
if (error instanceof CmmdProxyPermissionError) return new RuntimeReplicationClientError({
|
|
92421
|
+
kind: "permanent",
|
|
92422
|
+
code: "CMMD_PERMISSION_DENIED",
|
|
92423
|
+
detail: error.message
|
|
92424
|
+
});
|
|
92425
|
+
if (error instanceof CmmdProxyRequestError) return new RuntimeReplicationClientError(classifyRuntimeReplicationHttpFailure({
|
|
92426
|
+
status: error.status,
|
|
92427
|
+
body: error.body,
|
|
92428
|
+
detail: error.detail ?? error.message,
|
|
92429
|
+
...operation ? { operation } : {}
|
|
92430
|
+
}));
|
|
92431
|
+
return new RuntimeReplicationClientError({
|
|
92432
|
+
kind: "retryable",
|
|
92433
|
+
code: "CMMD_UNAVAILABLE",
|
|
92434
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
92435
|
+
});
|
|
92436
|
+
}
|
|
92437
|
+
//#endregion
|
|
92438
|
+
//#region src/runtimeReplication/lifecycleIntentClient.ts
|
|
92439
|
+
/**
|
|
92440
|
+
* The runtime half of a lifecycle intent: a settle or un-settle a person asked
|
|
92441
|
+
* for while this runtime was offline, held by CMMD until the runtime lists it,
|
|
92442
|
+
* applies it through its own orchestration, and acknowledges it.
|
|
92443
|
+
*
|
|
92444
|
+
* Both lanes carry the same envelope (pinned equal in the contracts package),
|
|
92445
|
+
* so one client serves the desktop's owner-session lane and the cloud
|
|
92446
|
+
* runtime's grant lane; only the path family differs.
|
|
92447
|
+
*/
|
|
92448
|
+
const LIFECYCLE_INTENT_TIMEOUT = "10 seconds";
|
|
92449
|
+
const LifecycleIntentListEnvelope = Struct({ data: Struct({ intents: ArraySchema(Struct({
|
|
92450
|
+
runtimeId: String$1,
|
|
92451
|
+
threadId: String$1,
|
|
92452
|
+
action: Literals(["settle", "unsettle"]),
|
|
92453
|
+
requestedAt: String$1
|
|
92454
|
+
})) }) });
|
|
92455
|
+
const LifecycleIntentAcknowledgementEnvelope = Struct({ data: Struct({ acknowledged: Number$1 }) });
|
|
92456
|
+
const decodeListEnvelope = decodeUnknownSync(LifecycleIntentListEnvelope);
|
|
92457
|
+
const decodeAcknowledgementEnvelope = decodeUnknownSync(LifecycleIntentAcknowledgementEnvelope);
|
|
92458
|
+
function decodeLifecycleIntentListResponse(response) {
|
|
92459
|
+
return decodeListEnvelope(response).data;
|
|
92460
|
+
}
|
|
92461
|
+
function decodeLifecycleIntentAcknowledgementResponse(response) {
|
|
92462
|
+
return decodeAcknowledgementEnvelope(response).data;
|
|
92463
|
+
}
|
|
92464
|
+
/**
|
|
92465
|
+
* Ids arrive from runtime rows, not constrained to path-safe characters, so
|
|
92466
|
+
* they are encoded the way every other runtime-lane path builder encodes them.
|
|
92467
|
+
*/
|
|
92468
|
+
function lifecycleIntentPath(lane, operation) {
|
|
92469
|
+
const base = `/api/forge/context/${lane.kind === "grant" ? "runtime-replication" : "devices"}/runtimes/${encodeURIComponent(lane.runtimeId)}/thread-lifecycle-intents`;
|
|
92470
|
+
return operation === "ack" ? `${base}/ack` : base;
|
|
92471
|
+
}
|
|
92472
|
+
function timedOut(operation) {
|
|
92473
|
+
return new RuntimeReplicationClientError({
|
|
92474
|
+
kind: "retryable",
|
|
92475
|
+
code: "CMMD_TIMEOUT",
|
|
92476
|
+
detail: `CMMD lifecycle intent ${operation} timed out.`
|
|
92477
|
+
});
|
|
92478
|
+
}
|
|
92479
|
+
function decodeOrFail(response, decode, label) {
|
|
92480
|
+
return try_({
|
|
92481
|
+
try: () => decode(response),
|
|
92482
|
+
catch: (cause) => new RuntimeReplicationClientError({
|
|
92483
|
+
kind: "permanent",
|
|
92484
|
+
code: "CMMD_PROTOCOL_INVALID_RESPONSE",
|
|
92485
|
+
detail: `CMMD returned an invalid lifecycle intent ${label}: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
92486
|
+
})
|
|
92487
|
+
});
|
|
92488
|
+
}
|
|
92489
|
+
/**
|
|
92490
|
+
* Every pending intent for this runtime, or an empty list.
|
|
92491
|
+
*
|
|
92492
|
+
* 404 is an ordinary answer, not a failure: a CMMD that predates the route
|
|
92493
|
+
* has nothing pending for anyone, and a runtime it has not registered yet has
|
|
92494
|
+
* nothing pending either. Every other non-2xx is a typed error -- a signed-out
|
|
92495
|
+
* owner (auth) is the caller's to skip, an outage is the next tick's to retry.
|
|
92496
|
+
*/
|
|
92497
|
+
function listPendingLifecycleIntents(lane, transport) {
|
|
92498
|
+
return tryPromise({
|
|
92499
|
+
try: (signal) => requestOnRuntimeLane(lane, {
|
|
92500
|
+
method: "GET",
|
|
92501
|
+
path: lifecycleIntentPath(lane, "list"),
|
|
92502
|
+
signal
|
|
92503
|
+
}, transport),
|
|
92504
|
+
catch: (cause) => cause instanceof CmmdProxyRequestError && cause.status === 404 ? null : mapRuntimeReplicationClientError(cause)
|
|
92505
|
+
}).pipe(catch_((cause) => cause === null ? succeed(null) : fail(cause)), flatMap((response) => response === null ? succeed([]) : decodeOrFail(response, decodeLifecycleIntentListResponse, "list").pipe(map$3((list) => list.intents))), timeoutOrElse({
|
|
92506
|
+
duration: LIFECYCLE_INTENT_TIMEOUT,
|
|
92507
|
+
orElse: () => fail(timedOut("list"))
|
|
92508
|
+
}));
|
|
92509
|
+
}
|
|
92510
|
+
/**
|
|
92511
|
+
* Tell CMMD which intents were applied (or deliberately skipped), by thread
|
|
92512
|
+
* and requested time. CMMD drops only an intent whose requested time matches,
|
|
92513
|
+
* so a newer request recorded while this one was being applied survives.
|
|
92514
|
+
*/
|
|
92515
|
+
function acknowledgeLifecycleIntents(lane, intents, transport) {
|
|
92516
|
+
const body = { intents };
|
|
92517
|
+
return tryPromise({
|
|
92518
|
+
try: (signal) => requestOnRuntimeLane(lane, {
|
|
92519
|
+
method: "POST",
|
|
92520
|
+
path: lifecycleIntentPath(lane, "ack"),
|
|
92521
|
+
body,
|
|
92522
|
+
signal
|
|
92523
|
+
}, transport),
|
|
92524
|
+
catch: mapRuntimeReplicationClientError
|
|
92525
|
+
}).pipe(flatMap((response) => decodeOrFail(response, decodeLifecycleIntentAcknowledgementResponse, "acknowledgement")), timeoutOrElse({
|
|
92526
|
+
duration: LIFECYCLE_INTENT_TIMEOUT,
|
|
92527
|
+
orElse: () => fail(timedOut("ack"))
|
|
92528
|
+
}));
|
|
92529
|
+
}
|
|
92530
|
+
//#endregion
|
|
92274
92531
|
//#region src/runtimeReplication/runtimeReplicationGrantPolicy.ts
|
|
92275
92532
|
/**
|
|
92276
92533
|
* Chooses which CMMD grant a replication send should use: the in-memory
|
|
@@ -92366,26 +92623,11 @@ function runtimeReplicationDevicePath(input) {
|
|
|
92366
92623
|
const threadId = input.streamKey.slice(7);
|
|
92367
92624
|
return `${devicePath}/threads/${encodeURIComponent(threadId)}/events`;
|
|
92368
92625
|
}
|
|
92369
|
-
async function parseRuntimeReplicationResponse(response) {
|
|
92370
|
-
const text = await response.text();
|
|
92371
|
-
let body = null;
|
|
92372
|
-
if (text) try {
|
|
92373
|
-
body = JSON.parse(text);
|
|
92374
|
-
} catch {
|
|
92375
|
-
body = null;
|
|
92376
|
-
}
|
|
92377
|
-
if (!response.ok) {
|
|
92378
|
-
const code = readRuntimeReplicationErrorCode(body);
|
|
92379
|
-
throw new CmmdProxyRequestError(`CMMD runtime replication failed (${response.status})`, response.status, null, code ? { code } : null);
|
|
92380
|
-
}
|
|
92381
|
-
if (body === null) throw new Error("CMMD runtime replication returned an empty or invalid JSON response.");
|
|
92382
|
-
return body;
|
|
92383
|
-
}
|
|
92384
92626
|
async function requestRuntimeReplicationWithGrant(input, fetchImpl = fetch) {
|
|
92385
92627
|
const abortController = new AbortController();
|
|
92386
92628
|
const timeout = setTimeout(() => abortController.abort(), RUNTIME_REPLICATION_TIMEOUT_MS);
|
|
92387
92629
|
try {
|
|
92388
|
-
return await
|
|
92630
|
+
return await parseRuntimeLaneResponse(await fetchImpl(new URL(runtimeReplicationGrantPath(input), `${input.controlPlaneUrl}/`), {
|
|
92389
92631
|
method: input.operation === "inventory" ? "PUT" : "POST",
|
|
92390
92632
|
headers: {
|
|
92391
92633
|
authorization: `Bearer ${input.grantToken}`,
|
|
@@ -92398,34 +92640,6 @@ async function requestRuntimeReplicationWithGrant(input, fetchImpl = fetch) {
|
|
|
92398
92640
|
clearTimeout(timeout);
|
|
92399
92641
|
}
|
|
92400
92642
|
}
|
|
92401
|
-
function mapRuntimeReplicationClientError(error, operation) {
|
|
92402
|
-
if (error instanceof CmmdProxyAuthError) return new RuntimeReplicationClientError({
|
|
92403
|
-
kind: "auth",
|
|
92404
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
92405
|
-
detail: error.message
|
|
92406
|
-
});
|
|
92407
|
-
if (error instanceof CmmdProxyAuthenticationRequiredError) return new RuntimeReplicationClientError({
|
|
92408
|
-
kind: "auth",
|
|
92409
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
92410
|
-
detail: error.message
|
|
92411
|
-
});
|
|
92412
|
-
if (error instanceof CmmdProxyPermissionError) return new RuntimeReplicationClientError({
|
|
92413
|
-
kind: "permanent",
|
|
92414
|
-
code: "CMMD_PERMISSION_DENIED",
|
|
92415
|
-
detail: error.message
|
|
92416
|
-
});
|
|
92417
|
-
if (error instanceof CmmdProxyRequestError) return new RuntimeReplicationClientError(classifyRuntimeReplicationHttpFailure({
|
|
92418
|
-
status: error.status,
|
|
92419
|
-
body: error.body,
|
|
92420
|
-
detail: error.detail ?? error.message,
|
|
92421
|
-
...operation ? { operation } : {}
|
|
92422
|
-
}));
|
|
92423
|
-
return new RuntimeReplicationClientError({
|
|
92424
|
-
kind: "retryable",
|
|
92425
|
-
code: "CMMD_UNAVAILABLE",
|
|
92426
|
-
detail: error instanceof Error ? error.message : String(error)
|
|
92427
|
-
});
|
|
92428
|
-
}
|
|
92429
92643
|
function decodeRuntimeThreadAcknowledgementResponse(response) {
|
|
92430
92644
|
return decodeThreadAcknowledgement(response).data.acknowledgement;
|
|
92431
92645
|
}
|
|
@@ -92501,9 +92715,12 @@ function replicateWithOwnerSession(sql, input) {
|
|
|
92501
92715
|
const jwt = owner.jwt;
|
|
92502
92716
|
const path = runtimeReplicationDevicePath(input);
|
|
92503
92717
|
const response = yield* tryPromise({
|
|
92504
|
-
try: () =>
|
|
92718
|
+
try: () => requestOnRuntimeLane({
|
|
92719
|
+
kind: "owner-session",
|
|
92720
|
+
runtimeId: input.runtimeId,
|
|
92721
|
+
jwt
|
|
92722
|
+
}, {
|
|
92505
92723
|
method: input.operation === "inventory" ? "PUT" : "POST",
|
|
92506
|
-
jwt,
|
|
92507
92724
|
path,
|
|
92508
92725
|
body: input.payload
|
|
92509
92726
|
}),
|
|
@@ -92514,11 +92731,63 @@ function replicateWithOwnerSession(sql, input) {
|
|
|
92514
92731
|
return yield* decodeAcknowledgementOrFail(response, decodeRuntimeThreadAcknowledgementResponse, "transcript");
|
|
92515
92732
|
});
|
|
92516
92733
|
}
|
|
92734
|
+
/**
|
|
92735
|
+
* The lane this runtime holds right now, resolved per call because both
|
|
92736
|
+
* credentials rotate: the cloud grant is re-read from the control authority,
|
|
92737
|
+
* and the owner session is whichever sign-in is newest on this desktop.
|
|
92738
|
+
*/
|
|
92739
|
+
function resolveRuntimeLane(config, sql, input) {
|
|
92740
|
+
return gen(function* () {
|
|
92741
|
+
if (config.forgeCmmdRuntimeMode === true) {
|
|
92742
|
+
const cloudGrant = resolveCloudRuntimeReplicationGrant(config);
|
|
92743
|
+
if (!cloudGrant) return yield* new RuntimeReplicationClientError({
|
|
92744
|
+
kind: "auth",
|
|
92745
|
+
code: "CMMD_RUNTIME_GRANT_REQUIRED",
|
|
92746
|
+
detail: "Cloud runtime replication requires a canonical runtime ID, CMMD URL, and scoped runtime grant."
|
|
92747
|
+
});
|
|
92748
|
+
if (input.runtimeId !== cloudGrant.runtimeId) return yield* new RuntimeReplicationClientError({
|
|
92749
|
+
kind: "permanent",
|
|
92750
|
+
code: "CMMD_RUNTIME_ID_MISMATCH",
|
|
92751
|
+
detail: "The requested runtime does not match this cloud runtime identity."
|
|
92752
|
+
});
|
|
92753
|
+
return {
|
|
92754
|
+
kind: "grant",
|
|
92755
|
+
controlPlaneUrl: cloudGrant.controlPlaneUrl,
|
|
92756
|
+
runtimeId: cloudGrant.runtimeId,
|
|
92757
|
+
grantToken: cloudGrant.grantToken
|
|
92758
|
+
};
|
|
92759
|
+
}
|
|
92760
|
+
const owner = yield* resolveCmmdOwnerSessionCredential(sql, { logPrefix: input.logPrefix });
|
|
92761
|
+
if (owner.kind === "no-session") return yield* new RuntimeReplicationClientError({
|
|
92762
|
+
kind: "auth",
|
|
92763
|
+
code: "CMMD_AUTH_REQUIRED",
|
|
92764
|
+
detail: "CMMD sign-in is required for runtime replication."
|
|
92765
|
+
});
|
|
92766
|
+
if (owner.kind === "no-credential") return yield* new RuntimeReplicationClientError({
|
|
92767
|
+
kind: "auth",
|
|
92768
|
+
code: "CMMD_AUTH_REQUIRED",
|
|
92769
|
+
detail: "CMMD REST credentials are unavailable for runtime replication."
|
|
92770
|
+
});
|
|
92771
|
+
return {
|
|
92772
|
+
kind: "owner-session",
|
|
92773
|
+
runtimeId: input.runtimeId,
|
|
92774
|
+
jwt: owner.jwt
|
|
92775
|
+
};
|
|
92776
|
+
});
|
|
92777
|
+
}
|
|
92517
92778
|
const RuntimeReplicationClientLive = effect(RuntimeReplicationClient, gen(function* () {
|
|
92518
92779
|
const sql = yield* SqlClient;
|
|
92519
92780
|
const config = yield* ServerConfig;
|
|
92520
92781
|
const send = (input) => config.forgeCmmdRuntimeMode === true ? replicateWithRuntimeGrant(config, input) : replicateWithOwnerSession(sql, input);
|
|
92521
|
-
|
|
92782
|
+
const lane = (runtimeId) => resolveRuntimeLane(config, sql, {
|
|
92783
|
+
runtimeId,
|
|
92784
|
+
logPrefix: "lifecycle-intents"
|
|
92785
|
+
});
|
|
92786
|
+
return RuntimeReplicationClient.of({
|
|
92787
|
+
send,
|
|
92788
|
+
listPendingLifecycleIntents: ({ runtimeId }) => lane(runtimeId).pipe(flatMap((l) => listPendingLifecycleIntents(l))),
|
|
92789
|
+
acknowledgeLifecycleIntents: ({ runtimeId, intents }) => lane(runtimeId).pipe(flatMap((l) => acknowledgeLifecycleIntents(l, intents)))
|
|
92790
|
+
});
|
|
92522
92791
|
}));
|
|
92523
92792
|
//#endregion
|
|
92524
92793
|
//#region src/runtimeReplication/Services/RuntimeReplicationOutbox.ts
|
|
@@ -92836,6 +93105,14 @@ function stableReplicaDigest(...values) {
|
|
|
92836
93105
|
function replicaHydrationCommandId(runtimeId, generationId, threadId) {
|
|
92837
93106
|
return CommandId.make("runtime-replica-hydration:" + stableReplicaDigest(runtimeId, generationId, threadId));
|
|
92838
93107
|
}
|
|
93108
|
+
/**
|
|
93109
|
+
* One id per (runtime, thread, requested time): a restart between dispatch and
|
|
93110
|
+
* acknowledgement re-lists the same intent, and the engine's command receipts
|
|
93111
|
+
* turn the second dispatch into a no-op instead of a second settle.
|
|
93112
|
+
*/
|
|
93113
|
+
function lifecycleIntentCommandId(runtimeId, threadId, requestedAt) {
|
|
93114
|
+
return CommandId.make("lifecycle-intent:" + stableReplicaDigest(runtimeId, threadId, requestedAt));
|
|
93115
|
+
}
|
|
92839
93116
|
//#endregion
|
|
92840
93117
|
//#region src/runtimeReplication/protocol.ts
|
|
92841
93118
|
const EMPTY_RUNTIME_THREAD_HEAD_HASH = "sha256:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU";
|
|
@@ -93785,6 +94062,21 @@ function totalTokens(totals) {
|
|
|
93785
94062
|
return totals.uncachedInputTokens + totals.cachedInputTokens + totals.cacheCreationTokens + totals.outputTokens;
|
|
93786
94063
|
}
|
|
93787
94064
|
/**
|
|
94065
|
+
* What a transcript record's own on-disk facts say it is a row of.
|
|
94066
|
+
*
|
|
94067
|
+
* Reuses exactly the facts `usageDrivers.ts`'s `isForgeAgent` reads to route a
|
|
94068
|
+
* record to the Forge agents lane, minus the "is this one of this
|
|
94069
|
+
* environment's own threads" gate: a Claude sidechain or a Codex subagent
|
|
94070
|
+
* rollout is a Subagent row regardless of which thread (if any) it hangs
|
|
94071
|
+
* under, so a subagent driven from outside Forge is still `subagent`, not a
|
|
94072
|
+
* plain Recorded-turn-shaped `turn`. Exported so the scan cache can recompute
|
|
94073
|
+
* the same value on decode instead of storing it as a redundant column.
|
|
94074
|
+
*/
|
|
94075
|
+
function transcriptRecordKind(provider, sidechain, rootSessionId) {
|
|
94076
|
+
if (provider === "claude") return sidechain === true ? "subagent" : "turn";
|
|
94077
|
+
return rootSessionId !== void 0 ? "subagent" : "turn";
|
|
94078
|
+
}
|
|
94079
|
+
/**
|
|
93788
94080
|
* Cheap substring gate applied before `JSON.parse`.
|
|
93789
94081
|
*
|
|
93790
94082
|
* Transcripts are mostly tool output; only a minority of lines carry usage. On
|
|
@@ -93853,6 +94145,7 @@ function parseClaudeLine(line, diagnostics) {
|
|
|
93853
94145
|
const dedupeKey = claudeDedupeKey(stringAt(messageRecord, "id"), stringAt(record, "requestId"));
|
|
93854
94146
|
const cost = record["costUSD"];
|
|
93855
94147
|
const launcher = stringAt(record, "entrypoint");
|
|
94148
|
+
const sidechain = record["isSidechain"] === true;
|
|
93856
94149
|
return {
|
|
93857
94150
|
provider: "claude",
|
|
93858
94151
|
timestampMs,
|
|
@@ -93861,8 +94154,9 @@ function parseClaudeLine(line, diagnostics) {
|
|
|
93861
94154
|
totals: claudeTokenBuckets(usageRecord) ?? EMPTY_TOTALS,
|
|
93862
94155
|
reportedCostUsd: typeof cost === "number" && Number.isFinite(cost) ? cost : null,
|
|
93863
94156
|
dedupeKey,
|
|
94157
|
+
kind: transcriptRecordKind("claude", sidechain, void 0),
|
|
93864
94158
|
...launcher === null ? {} : { launcher },
|
|
93865
|
-
...
|
|
94159
|
+
...sidechain ? { sidechain: true } : {}
|
|
93866
94160
|
};
|
|
93867
94161
|
}
|
|
93868
94162
|
function initialCodexScanState() {
|
|
@@ -93979,6 +94273,7 @@ function parseCodexTokenCount(record, payloadRecord, state) {
|
|
|
93979
94273
|
totals,
|
|
93980
94274
|
reportedCostUsd: null,
|
|
93981
94275
|
dedupeKey: null,
|
|
94276
|
+
kind: transcriptRecordKind("codex", void 0, state.rootSessionId),
|
|
93982
94277
|
...codexSessionFields(state)
|
|
93983
94278
|
};
|
|
93984
94279
|
}
|
|
@@ -94247,7 +94542,8 @@ var UsageAggregator = class {
|
|
|
94247
94542
|
origin,
|
|
94248
94543
|
sync,
|
|
94249
94544
|
runtimeId,
|
|
94250
|
-
driver
|
|
94545
|
+
driver,
|
|
94546
|
+
record.kind
|
|
94251
94547
|
].join("\0");
|
|
94252
94548
|
const existing = this.#buckets.get(key);
|
|
94253
94549
|
if (existing !== void 0) return existing;
|
|
@@ -94285,7 +94581,7 @@ var UsageAggregator = class {
|
|
|
94285
94581
|
finish() {
|
|
94286
94582
|
const buckets = [];
|
|
94287
94583
|
for (const [key, bucket] of this.#buckets) {
|
|
94288
|
-
const [day = "", hourStart = "", provider = "", model = "", origin = "", sync = "", runtimeId = "", driver = ""] = key.split("\0");
|
|
94584
|
+
const [day = "", hourStart = "", provider = "", model = "", origin = "", sync = "", runtimeId = "", driver = "", kind = ""] = key.split("\0");
|
|
94289
94585
|
buckets.push({
|
|
94290
94586
|
day,
|
|
94291
94587
|
...hourStart === "" ? {} : { hourStart },
|
|
@@ -94301,10 +94597,15 @@ var UsageAggregator = class {
|
|
|
94301
94597
|
origin,
|
|
94302
94598
|
...sync === "" ? {} : { sync },
|
|
94303
94599
|
...runtimeId === "" ? {} : { runtimeId },
|
|
94304
|
-
...driver === "" ? {} : { driver }
|
|
94600
|
+
...driver === "" ? {} : { driver },
|
|
94601
|
+
kind
|
|
94305
94602
|
});
|
|
94306
94603
|
}
|
|
94307
|
-
buckets.sort((a, b) =>
|
|
94604
|
+
buckets.sort((a, b) => {
|
|
94605
|
+
const left = bucketSortKey(a);
|
|
94606
|
+
const right = bucketSortKey(b);
|
|
94607
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
94608
|
+
});
|
|
94308
94609
|
return {
|
|
94309
94610
|
buckets,
|
|
94310
94611
|
duplicatesDropped: this.#duplicatesDropped,
|
|
@@ -94322,7 +94623,8 @@ function bucketSortKey(bucket) {
|
|
|
94322
94623
|
bucket.origin ?? "",
|
|
94323
94624
|
bucket.sync ?? "",
|
|
94324
94625
|
bucket.runtimeId ?? "",
|
|
94325
|
-
bucket.driver ?? ""
|
|
94626
|
+
bucket.driver ?? "",
|
|
94627
|
+
bucket.kind ?? ""
|
|
94326
94628
|
].join("\0");
|
|
94327
94629
|
}
|
|
94328
94630
|
/**
|
|
@@ -95311,6 +95613,7 @@ function syncOf(sequence, options, threadId, events) {
|
|
|
95311
95613
|
return sequence <= cursor.acknowledgedSequence ? "acknowledged" : "pending";
|
|
95312
95614
|
}
|
|
95313
95615
|
function recordOf(event, provider, sync, threadId, runtimeId) {
|
|
95616
|
+
const kind = event.usageKind ?? "turn";
|
|
95314
95617
|
return {
|
|
95315
95618
|
provider,
|
|
95316
95619
|
timestampMs: Date.parse(event.occurredAt),
|
|
@@ -95319,6 +95622,7 @@ function recordOf(event, provider, sync, threadId, runtimeId) {
|
|
|
95319
95622
|
totals: event.usage ?? EMPTY_TOTALS,
|
|
95320
95623
|
reportedCostUsd: null,
|
|
95321
95624
|
dedupeKey: `recorded:${threadId}:${event.turnId}:${event.usageKind ?? "turn"}:${event.subagentId ?? ""}:${event.model}`,
|
|
95625
|
+
kind,
|
|
95322
95626
|
origin: "recorded",
|
|
95323
95627
|
...sync === void 0 ? {} : { sync },
|
|
95324
95628
|
...runtimeId === void 0 ? {} : { runtimeId },
|
|
@@ -96039,6 +96343,22 @@ async function readTranscriptRecords(filePath, provider) {
|
|
|
96039
96343
|
//#endregion
|
|
96040
96344
|
//#region src/usage/usageScanCache.ts
|
|
96041
96345
|
/**
|
|
96346
|
+
* Durable per-file scan cache.
|
|
96347
|
+
*
|
|
96348
|
+
* Transcripts are append-only and a file that has not changed can never yield
|
|
96349
|
+
* different usage, so parsed records are keyed by `(size, mtime)` and reused.
|
|
96350
|
+
* Without this every server restart re-parses the whole window: seconds for a
|
|
96351
|
+
* 30-day scan, against milliseconds to reload this cache.
|
|
96352
|
+
*
|
|
96353
|
+
* Caching *per file* rather than per day is deliberate. It is timezone
|
|
96354
|
+
* independent, so changing the reporting zone does not invalidate anything, and
|
|
96355
|
+
* it keeps cross-file de-duplication exact: cached entries are de-duplicated
|
|
96356
|
+
* within their own file only, and the aggregator still applies the global
|
|
96357
|
+
* dedupe pass over the small surviving key set.
|
|
96358
|
+
*
|
|
96359
|
+
* @module usageScanCache
|
|
96360
|
+
*/
|
|
96361
|
+
/**
|
|
96042
96362
|
* Bumped whenever cached records could differ from what a fresh parse produces.
|
|
96043
96363
|
*
|
|
96044
96364
|
* Version 1 was written before `parseCodexLine` suppressed the parent history a
|
|
@@ -96184,6 +96504,7 @@ function decodeRecord(row, provider, tables) {
|
|
|
96184
96504
|
},
|
|
96185
96505
|
reportedCostUsd: finiteNumber(reportedCostUsd),
|
|
96186
96506
|
dedupeKey: typeof dedupeKey === "string" ? dedupeKey : null,
|
|
96507
|
+
kind: transcriptRecordKind(provider, session.sidechain, session.rootSessionId),
|
|
96187
96508
|
...session
|
|
96188
96509
|
};
|
|
96189
96510
|
}
|
|
@@ -99151,144 +99472,6 @@ function claudeWriteToken(env = process.env) {
|
|
|
99151
99472
|
return accessor.read(env);
|
|
99152
99473
|
}
|
|
99153
99474
|
//#endregion
|
|
99154
|
-
//#region src/usage/providerRateLimits.ts
|
|
99155
|
-
/**
|
|
99156
|
-
* In-process cache of the latest Claude 5h/7d rate-limit telemetry, decoded
|
|
99157
|
-
* from the genuine Claude Agent SDK's own `rate_limit_event` messages
|
|
99158
|
-
* (see ClaudeAdapter.ts). This is intentionally NOT a CMMD call site: CMMD
|
|
99159
|
-
* must never replay a personal Claude OAuth token against api.anthropic.com
|
|
99160
|
-
* from its own backend (see CMMD's personal-claude-delivery.ts) - the only
|
|
99161
|
-
* legitimate source for this data is the real in-VM SDK session reporting it
|
|
99162
|
-
* as a side effect of a real turn.
|
|
99163
|
-
*
|
|
99164
|
-
* Snapshots are fenced by the exact non-secret credential-generation hash.
|
|
99165
|
-
* A Forge process can outlive an account reconnect, so a process-wide singleton
|
|
99166
|
-
* without that fence can leak account A's windows into account B's session.
|
|
99167
|
-
* The request-scoped route that reads this
|
|
99168
|
-
* cache (apps/server/src/command/http.ts) is what actually forwards it to
|
|
99169
|
-
* CMMD, using the request's own authenticated session - a background event
|
|
99170
|
-
* pipeline has no such session to reuse safely.
|
|
99171
|
-
*/
|
|
99172
|
-
/**
|
|
99173
|
-
* The SDK only ever reports ONE window per event. Only `five_hour` and
|
|
99174
|
-
* `seven_day` map to the two windows the Usage page shows; the
|
|
99175
|
-
* per-model/overage variants (seven_day_opus, overage, ...) are ignored here
|
|
99176
|
-
* on purpose rather than silently overwriting the plain 7-day figure.
|
|
99177
|
-
*/
|
|
99178
|
-
function mapClaudeRateLimitInfo(info) {
|
|
99179
|
-
if (typeof info.utilization !== "number" || typeof info.resetsAt !== "number" || !info.status) return null;
|
|
99180
|
-
const kind = info.rateLimitType === "five_hour" ? "fiveHour" : info.rateLimitType === "seven_day" ? "sevenDay" : null;
|
|
99181
|
-
if (!kind) return null;
|
|
99182
|
-
return {
|
|
99183
|
-
kind,
|
|
99184
|
-
window: {
|
|
99185
|
-
usedPercent: Math.round(info.utilization * 100),
|
|
99186
|
-
resetsAt: (/* @__PURE__ */ new Date(info.resetsAt * 1e3)).toISOString(),
|
|
99187
|
-
status: info.status
|
|
99188
|
-
}
|
|
99189
|
-
};
|
|
99190
|
-
}
|
|
99191
|
-
const SEVEN_DAY_MODEL_PREFIX = "seven_day_";
|
|
99192
|
-
const SEVEN_DAY_OVERAGE_SUFFIX = "overage_included";
|
|
99193
|
-
function capitalizeModelSuffix(suffix) {
|
|
99194
|
-
return suffix.length === 0 ? suffix : suffix.charAt(0).toUpperCase() + suffix.slice(1);
|
|
99195
|
-
}
|
|
99196
|
-
/**
|
|
99197
|
-
* Maps a per-model weekly SDKRateLimitInfo (`seven_day_<model>`, e.g.
|
|
99198
|
-
* `seven_day_opus`) into a `ProviderUsageModelWindow`. `seven_day_overage_included`
|
|
99199
|
-
* is not a per-model window (it reports overage-inclusive quota, not a
|
|
99200
|
-
* specific model) and stays ignored here, same as plain `overage`.
|
|
99201
|
-
*/
|
|
99202
|
-
function mapClaudeModelRateLimitInfo(info) {
|
|
99203
|
-
if (typeof info.utilization !== "number" || typeof info.resetsAt !== "number" || !info.status) return null;
|
|
99204
|
-
if (!info.rateLimitType?.startsWith(SEVEN_DAY_MODEL_PREFIX)) return null;
|
|
99205
|
-
const suffix = info.rateLimitType.slice(10);
|
|
99206
|
-
if (suffix.length === 0 || suffix === SEVEN_DAY_OVERAGE_SUFFIX) return null;
|
|
99207
|
-
return {
|
|
99208
|
-
model: capitalizeModelSuffix(suffix),
|
|
99209
|
-
window: {
|
|
99210
|
-
usedPercent: Math.round(info.utilization * 100),
|
|
99211
|
-
resetsAt: (/* @__PURE__ */ new Date(info.resetsAt * 1e3)).toISOString(),
|
|
99212
|
-
status: info.status
|
|
99213
|
-
}
|
|
99214
|
-
};
|
|
99215
|
-
}
|
|
99216
|
-
const cachedSnapshots = /* @__PURE__ */ new Map();
|
|
99217
|
-
let localClaudeGenerationHash = null;
|
|
99218
|
-
function setLocalClaudeUsageGeneration(generationId) {
|
|
99219
|
-
localClaudeGenerationHash = createHash("sha256").update(generationId).digest("hex");
|
|
99220
|
-
}
|
|
99221
|
-
function currentClaudeUsageGenerationHash() {
|
|
99222
|
-
const value = process.env.FORGE_PERSONAL_CLAUDE_GENERATION_HASH?.trim() ?? "";
|
|
99223
|
-
return /^[a-f0-9]{64}$/.test(value) ? value : localClaudeGenerationHash;
|
|
99224
|
-
}
|
|
99225
|
-
function cacheKeyFor(generationHash, providerAccountId) {
|
|
99226
|
-
return providerAccountId ? `${providerAccountId}:${generationHash}` : generationHash;
|
|
99227
|
-
}
|
|
99228
|
-
/**
|
|
99229
|
-
* `observedAt` here is a placeholder, not an observation — it becomes
|
|
99230
|
-
* meaningful only once a standard (five_hour/seven_day) window actually
|
|
99231
|
-
* lands via `withStandardWindow`, which recomputes it from the retained
|
|
99232
|
-
* windows' own observation times. A per-model-only cache (no standard window
|
|
99233
|
-
* yet) still carries this placeholder, so callers should treat `observedAt`
|
|
99234
|
-
* as trustworthy only once `fiveHour` or `sevenDay` is non-null.
|
|
99235
|
-
*/
|
|
99236
|
-
function emptyCachedSnapshot(observedAt) {
|
|
99237
|
-
return {
|
|
99238
|
-
fiveHour: null,
|
|
99239
|
-
sevenDay: null,
|
|
99240
|
-
modelWindowsByModel: {},
|
|
99241
|
-
observedAt,
|
|
99242
|
-
fiveHourObservedAt: null,
|
|
99243
|
-
sevenDayObservedAt: null
|
|
99244
|
-
};
|
|
99245
|
-
}
|
|
99246
|
-
/** Oldest observation among the retained standard windows, so one fresh event cannot mask stale data. */
|
|
99247
|
-
function oldestObservedAt(fiveHourObservedAt, sevenDayObservedAt) {
|
|
99248
|
-
return [fiveHourObservedAt, sevenDayObservedAt].filter((value) => value !== null).toSorted()[0];
|
|
99249
|
-
}
|
|
99250
|
-
function withStandardWindow(previous, mapped, observedAt) {
|
|
99251
|
-
const isFiveHour = mapped.kind === "fiveHour";
|
|
99252
|
-
const fiveHourObservedAt = isFiveHour ? observedAt : previous.fiveHourObservedAt;
|
|
99253
|
-
const sevenDayObservedAt = isFiveHour ? previous.sevenDayObservedAt : observedAt;
|
|
99254
|
-
return {
|
|
99255
|
-
...previous,
|
|
99256
|
-
fiveHour: isFiveHour ? mapped.window : previous.fiveHour,
|
|
99257
|
-
sevenDay: isFiveHour ? previous.sevenDay : mapped.window,
|
|
99258
|
-
fiveHourObservedAt,
|
|
99259
|
-
sevenDayObservedAt,
|
|
99260
|
-
observedAt: oldestObservedAt(fiveHourObservedAt, sevenDayObservedAt)
|
|
99261
|
-
};
|
|
99262
|
-
}
|
|
99263
|
-
function withModelWindow(previous, mapped) {
|
|
99264
|
-
return {
|
|
99265
|
-
...previous,
|
|
99266
|
-
modelWindowsByModel: {
|
|
99267
|
-
...previous.modelWindowsByModel,
|
|
99268
|
-
[mapped.model]: mapped.window
|
|
99269
|
-
}
|
|
99270
|
-
};
|
|
99271
|
-
}
|
|
99272
|
-
/**
|
|
99273
|
-
* Merges a single-window update into the cached snapshot without clobbering
|
|
99274
|
-
* the other windows. A per-model weekly report (`seven_day_<model>`) merges
|
|
99275
|
-
* into `modelWindowsByModel` keyed by model, leaving every other model and
|
|
99276
|
-
* the plain five_hour/seven_day windows untouched.
|
|
99277
|
-
*/
|
|
99278
|
-
function recordClaudeRateLimitTelemetry(info, generationHash = currentClaudeUsageGenerationHash(), providerAccountId) {
|
|
99279
|
-
if (generationHash === null) return;
|
|
99280
|
-
const cacheKey = cacheKeyFor(generationHash, providerAccountId);
|
|
99281
|
-
const observedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
99282
|
-
const previous = cachedSnapshots.get(cacheKey) ?? emptyCachedSnapshot(observedAt);
|
|
99283
|
-
const standard = mapClaudeRateLimitInfo(info);
|
|
99284
|
-
if (standard) {
|
|
99285
|
-
cachedSnapshots.set(cacheKey, withStandardWindow(previous, standard, observedAt));
|
|
99286
|
-
return;
|
|
99287
|
-
}
|
|
99288
|
-
const model = mapClaudeModelRateLimitInfo(info);
|
|
99289
|
-
if (model) cachedSnapshots.set(cacheKey, withModelWindow(previous, model));
|
|
99290
|
-
}
|
|
99291
|
-
//#endregion
|
|
99292
99475
|
//#region src/providerAuth/ClaudeDeviceAuth.ts
|
|
99293
99476
|
const AUTHORIZE_URL_PATTERN = /https:\/\/[^\s]*\/oauth\/authorize\?[^\s]+/u;
|
|
99294
99477
|
const ANSI_ESCAPE_PATTERN$1 = new RegExp(String.raw`\x1B\[[0-?]*[ -/]*[@-~]`, "gu");
|
|
@@ -99803,7 +99986,6 @@ async function finalizeClaudeCredentialSync(input) {
|
|
|
99803
99986
|
const providerAccountId = extractClaudeProviderAccountId(input.response);
|
|
99804
99987
|
const credentialGenerationId = extractClaudeCredentialGenerationId(input.response);
|
|
99805
99988
|
if (providerAccountId === null || credentialGenerationId === null) return null;
|
|
99806
|
-
if (input.auth.path === USER_CLAUDE_CREDENTIAL_PATH) setLocalClaudeUsageGeneration(credentialGenerationId);
|
|
99807
99989
|
return publishClaudeUsageAfterSync({
|
|
99808
99990
|
auth: input.auth,
|
|
99809
99991
|
providerAccountId,
|
|
@@ -146893,137 +147075,6 @@ const LocalAutomationRepositoryLive = effect(LocalAutomationRepository, gen(func
|
|
|
146893
147075
|
*/
|
|
146894
147076
|
var CodexAdapter = class extends Service$1()("forge/provider/Services/CodexAdapter") {};
|
|
146895
147077
|
//#endregion
|
|
146896
|
-
//#region ../../packages/shared/src/model.ts
|
|
146897
|
-
/** Check whether a capabilities object includes a given effort value. */
|
|
146898
|
-
function hasEffortLevel(caps, value) {
|
|
146899
|
-
return caps.reasoningEffortLevels.some((l) => l.value === value);
|
|
146900
|
-
}
|
|
146901
|
-
/** Return the default effort value for a capabilities object, or null if none. */
|
|
146902
|
-
function getDefaultEffort(caps) {
|
|
146903
|
-
return caps.reasoningEffortLevels.find((l) => l.isDefault)?.value ?? null;
|
|
146904
|
-
}
|
|
146905
|
-
/**
|
|
146906
|
-
* Resolve a raw effort option against capabilities.
|
|
146907
|
-
*
|
|
146908
|
-
* Returns the effective effort value — the explicit value if supported and not
|
|
146909
|
-
* prompt-injected, otherwise the model's default. Returns `undefined` only
|
|
146910
|
-
* when the model has no effort levels at all.
|
|
146911
|
-
*
|
|
146912
|
-
* Prompt-injected efforts (e.g. "ultrathink") are excluded because they are
|
|
146913
|
-
* applied via prompt text, not the effort API parameter.
|
|
146914
|
-
*/
|
|
146915
|
-
function resolveEffort(caps, raw) {
|
|
146916
|
-
const defaultValue = getDefaultEffort(caps);
|
|
146917
|
-
const trimmed = typeof raw === "string" ? raw.trim() : null;
|
|
146918
|
-
if (trimmed && !caps.promptInjectedEffortLevels.includes(trimmed) && hasEffortLevel(caps, trimmed)) return trimmed;
|
|
146919
|
-
return defaultValue ?? void 0;
|
|
146920
|
-
}
|
|
146921
|
-
/** Check whether a capabilities object includes a given context window value. */
|
|
146922
|
-
function hasContextWindowOption(caps, value) {
|
|
146923
|
-
return caps.contextWindowOptions.some((o) => o.value === value);
|
|
146924
|
-
}
|
|
146925
|
-
/** Return the default context window value, or `null` if none is defined. */
|
|
146926
|
-
function getDefaultContextWindow(caps) {
|
|
146927
|
-
return caps.contextWindowOptions.find((o) => o.isDefault)?.value ?? null;
|
|
146928
|
-
}
|
|
146929
|
-
/**
|
|
146930
|
-
* Resolve a raw `contextWindow` option against capabilities.
|
|
146931
|
-
*
|
|
146932
|
-
* Returns the effective context window value — the explicit value if supported,
|
|
146933
|
-
* otherwise the model's default. Returns `undefined` only when the model has
|
|
146934
|
-
* no context window options at all.
|
|
146935
|
-
*
|
|
146936
|
-
* Unlike effort levels (where the API has matching defaults), the context
|
|
146937
|
-
* window requires an explicit API suffix (e.g. `[1m]`), so we always preserve
|
|
146938
|
-
* the resolved value to avoid ambiguity between "user chose the default" and
|
|
146939
|
-
* "not specified".
|
|
146940
|
-
*/
|
|
146941
|
-
function resolveContextWindow(caps, raw) {
|
|
146942
|
-
const defaultValue = getDefaultContextWindow(caps);
|
|
146943
|
-
if (!raw) return defaultValue ?? void 0;
|
|
146944
|
-
return hasContextWindowOption(caps, raw) ? raw : defaultValue ?? void 0;
|
|
146945
|
-
}
|
|
146946
|
-
function normalizeCodexModelOptionsWithCapabilities(caps, modelOptions) {
|
|
146947
|
-
const reasoningEffort = resolveEffort(caps, modelOptions?.reasoningEffort);
|
|
146948
|
-
const fastMode = caps.supportsFastMode ? modelOptions?.fastMode : void 0;
|
|
146949
|
-
const nextOptions = {
|
|
146950
|
-
...reasoningEffort ? { reasoningEffort } : {},
|
|
146951
|
-
...fastMode !== void 0 ? { fastMode } : {}
|
|
146952
|
-
};
|
|
146953
|
-
return Object.keys(nextOptions).length > 0 ? nextOptions : void 0;
|
|
146954
|
-
}
|
|
146955
|
-
function normalizeClaudeModelOptionsWithCapabilities(caps, modelOptions) {
|
|
146956
|
-
const effort = resolveEffort(caps, modelOptions?.effort);
|
|
146957
|
-
const thinking = caps.supportsThinkingToggle ? modelOptions?.thinking : void 0;
|
|
146958
|
-
const fastMode = caps.supportsFastMode ? modelOptions?.fastMode : void 0;
|
|
146959
|
-
const contextWindow = resolveContextWindow(caps, modelOptions?.contextWindow);
|
|
146960
|
-
const nextOptions = {
|
|
146961
|
-
...thinking !== void 0 ? { thinking } : {},
|
|
146962
|
-
...effort ? { effort } : {},
|
|
146963
|
-
...fastMode !== void 0 ? { fastMode } : {},
|
|
146964
|
-
...contextWindow !== void 0 ? { contextWindow } : {}
|
|
146965
|
-
};
|
|
146966
|
-
return Object.keys(nextOptions).length > 0 ? nextOptions : void 0;
|
|
146967
|
-
}
|
|
146968
|
-
function normalizeModelSlug(model, provider = "codex") {
|
|
146969
|
-
if (typeof model !== "string") return null;
|
|
146970
|
-
const trimmed = model.trim();
|
|
146971
|
-
if (!trimmed) return null;
|
|
146972
|
-
const aliases = MODEL_SLUG_ALIASES_BY_PROVIDER[provider];
|
|
146973
|
-
const aliased = Object.prototype.hasOwnProperty.call(aliases, trimmed) ? aliases[trimmed] : void 0;
|
|
146974
|
-
return typeof aliased === "string" ? aliased : trimmed;
|
|
146975
|
-
}
|
|
146976
|
-
/** Trim a string, returning null for empty/missing values. */
|
|
146977
|
-
function trimOrNull(value) {
|
|
146978
|
-
if (typeof value !== "string") return null;
|
|
146979
|
-
return value.trim() || null;
|
|
146980
|
-
}
|
|
146981
|
-
/**
|
|
146982
|
-
* Resolve the actual API model identifier from a model selection.
|
|
146983
|
-
*
|
|
146984
|
-
* Provider-aware: each provider can map `contextWindow` (or other options)
|
|
146985
|
-
* to whatever the API requires — a model-id suffix, a separate parameter, etc.
|
|
146986
|
-
* The canonical slug stored in the selection stays unchanged so the
|
|
146987
|
-
* capabilities system keeps working.
|
|
146988
|
-
*
|
|
146989
|
-
* Expects `contextWindow` to already be resolved (via `resolveContextWindow`)
|
|
146990
|
-
* to the effective value, not stripped to `undefined` for defaults.
|
|
146991
|
-
*/
|
|
146992
|
-
function resolveApiModelId(modelSelection) {
|
|
146993
|
-
switch (modelSelection.provider) {
|
|
146994
|
-
case "claudeAgent": switch (modelSelection.options?.contextWindow) {
|
|
146995
|
-
case "1m": return `${modelSelection.model}[1m]`;
|
|
146996
|
-
default: return modelSelection.model;
|
|
146997
|
-
}
|
|
146998
|
-
default: return modelSelection.model;
|
|
146999
|
-
}
|
|
147000
|
-
}
|
|
147001
|
-
function applyClaudePromptEffortPrefix(text, effort) {
|
|
147002
|
-
const trimmed = text.trim();
|
|
147003
|
-
if (!trimmed) return trimmed;
|
|
147004
|
-
if (effort !== "ultrathink") return trimmed;
|
|
147005
|
-
if (trimmed.startsWith("Ultrathink:")) return trimmed;
|
|
147006
|
-
return `Ultrathink:\n${trimmed}`;
|
|
147007
|
-
}
|
|
147008
|
-
function getRawProviderOptionSelectionValue(selections, id) {
|
|
147009
|
-
return selections?.find((candidate) => candidate.id === id)?.value;
|
|
147010
|
-
}
|
|
147011
|
-
function getProviderOptionSelectionValue(selections, id) {
|
|
147012
|
-
return getRawProviderOptionSelectionValue(selections, id);
|
|
147013
|
-
}
|
|
147014
|
-
function getProviderOptionStringSelectionValue(selections, id) {
|
|
147015
|
-
const value = getProviderOptionSelectionValue(selections, id);
|
|
147016
|
-
return typeof value === "string" ? value : void 0;
|
|
147017
|
-
}
|
|
147018
|
-
function flatProviderOptions(selection) {
|
|
147019
|
-
if (!selection) return void 0;
|
|
147020
|
-
if (selection.provider !== "cursor" && selection.provider !== "opencode") return void 0;
|
|
147021
|
-
return selection.options;
|
|
147022
|
-
}
|
|
147023
|
-
function getModelSelectionStringOptionValue(selection, id) {
|
|
147024
|
-
return getProviderOptionStringSelectionValue(flatProviderOptions(selection), id);
|
|
147025
|
-
}
|
|
147026
|
-
//#endregion
|
|
147027
147078
|
//#region src/provider/codexCliVersion.ts
|
|
147028
147079
|
const CODEX_VERSION_PATTERN = /\bv?(\d+\.\d+(?:\.\d+)?(?:-[0-9A-Za-z.-]+)?)\b/;
|
|
147029
147080
|
const MINIMUM_CODEX_CLI_VERSION = "0.37.0";
|
|
@@ -147678,6 +147729,213 @@ async function probeCodexDiscovery(input) {
|
|
|
147678
147729
|
});
|
|
147679
147730
|
}
|
|
147680
147731
|
//#endregion
|
|
147732
|
+
//#region ../../packages/shared/src/model.ts
|
|
147733
|
+
/** Check whether a capabilities object includes a given effort value. */
|
|
147734
|
+
function hasEffortLevel(caps, value) {
|
|
147735
|
+
return caps.reasoningEffortLevels.some((l) => l.value === value);
|
|
147736
|
+
}
|
|
147737
|
+
/** Return the default effort value for a capabilities object, or null if none. */
|
|
147738
|
+
function getDefaultEffort(caps) {
|
|
147739
|
+
return caps.reasoningEffortLevels.find((l) => l.isDefault)?.value ?? null;
|
|
147740
|
+
}
|
|
147741
|
+
/**
|
|
147742
|
+
* Resolve a raw effort option against capabilities.
|
|
147743
|
+
*
|
|
147744
|
+
* Returns the effective effort value — the explicit value if supported and not
|
|
147745
|
+
* prompt-injected, otherwise the model's default. Returns `undefined` only
|
|
147746
|
+
* when the model has no effort levels at all.
|
|
147747
|
+
*
|
|
147748
|
+
* Prompt-injected efforts (e.g. "ultrathink") are excluded because they are
|
|
147749
|
+
* applied via prompt text, not the effort API parameter.
|
|
147750
|
+
*/
|
|
147751
|
+
function resolveEffort(caps, raw) {
|
|
147752
|
+
const defaultValue = getDefaultEffort(caps);
|
|
147753
|
+
const trimmed = typeof raw === "string" ? raw.trim() : null;
|
|
147754
|
+
if (trimmed && !caps.promptInjectedEffortLevels.includes(trimmed) && hasEffortLevel(caps, trimmed)) return trimmed;
|
|
147755
|
+
return defaultValue ?? void 0;
|
|
147756
|
+
}
|
|
147757
|
+
/** Check whether a capabilities object includes a given context window value. */
|
|
147758
|
+
function hasContextWindowOption(caps, value) {
|
|
147759
|
+
return caps.contextWindowOptions.some((o) => o.value === value);
|
|
147760
|
+
}
|
|
147761
|
+
/** Return the default context window value, or `null` if none is defined. */
|
|
147762
|
+
function getDefaultContextWindow(caps) {
|
|
147763
|
+
return caps.contextWindowOptions.find((o) => o.isDefault)?.value ?? null;
|
|
147764
|
+
}
|
|
147765
|
+
/**
|
|
147766
|
+
* Resolve a raw `contextWindow` option against capabilities.
|
|
147767
|
+
*
|
|
147768
|
+
* Returns the effective context window value — the explicit value if supported,
|
|
147769
|
+
* otherwise the model's default. Returns `undefined` only when the model has
|
|
147770
|
+
* no context window options at all.
|
|
147771
|
+
*
|
|
147772
|
+
* Unlike effort levels (where the API has matching defaults), the context
|
|
147773
|
+
* window requires an explicit API suffix (e.g. `[1m]`), so we always preserve
|
|
147774
|
+
* the resolved value to avoid ambiguity between "user chose the default" and
|
|
147775
|
+
* "not specified".
|
|
147776
|
+
*/
|
|
147777
|
+
function resolveContextWindow(caps, raw) {
|
|
147778
|
+
const defaultValue = getDefaultContextWindow(caps);
|
|
147779
|
+
if (!raw) return defaultValue ?? void 0;
|
|
147780
|
+
return hasContextWindowOption(caps, raw) ? raw : defaultValue ?? void 0;
|
|
147781
|
+
}
|
|
147782
|
+
function normalizeCodexModelOptionsWithCapabilities(caps, modelOptions) {
|
|
147783
|
+
const reasoningEffort = resolveEffort(caps, modelOptions?.reasoningEffort);
|
|
147784
|
+
const fastMode = caps.supportsFastMode ? modelOptions?.fastMode : void 0;
|
|
147785
|
+
const nextOptions = {
|
|
147786
|
+
...reasoningEffort ? { reasoningEffort } : {},
|
|
147787
|
+
...fastMode !== void 0 ? { fastMode } : {}
|
|
147788
|
+
};
|
|
147789
|
+
return Object.keys(nextOptions).length > 0 ? nextOptions : void 0;
|
|
147790
|
+
}
|
|
147791
|
+
function normalizeClaudeModelOptionsWithCapabilities(caps, modelOptions) {
|
|
147792
|
+
const effort = resolveEffort(caps, modelOptions?.effort);
|
|
147793
|
+
const thinking = caps.supportsThinkingToggle ? modelOptions?.thinking : void 0;
|
|
147794
|
+
const fastMode = caps.supportsFastMode ? modelOptions?.fastMode : void 0;
|
|
147795
|
+
const contextWindow = resolveContextWindow(caps, modelOptions?.contextWindow);
|
|
147796
|
+
const nextOptions = {
|
|
147797
|
+
...thinking !== void 0 ? { thinking } : {},
|
|
147798
|
+
...effort ? { effort } : {},
|
|
147799
|
+
...fastMode !== void 0 ? { fastMode } : {},
|
|
147800
|
+
...contextWindow !== void 0 ? { contextWindow } : {}
|
|
147801
|
+
};
|
|
147802
|
+
return Object.keys(nextOptions).length > 0 ? nextOptions : void 0;
|
|
147803
|
+
}
|
|
147804
|
+
function normalizeModelSlug(model, provider = "codex") {
|
|
147805
|
+
if (typeof model !== "string") return null;
|
|
147806
|
+
const trimmed = model.trim();
|
|
147807
|
+
if (!trimmed) return null;
|
|
147808
|
+
const aliases = MODEL_SLUG_ALIASES_BY_PROVIDER[provider];
|
|
147809
|
+
const aliased = Object.prototype.hasOwnProperty.call(aliases, trimmed) ? aliases[trimmed] : void 0;
|
|
147810
|
+
return typeof aliased === "string" ? aliased : trimmed;
|
|
147811
|
+
}
|
|
147812
|
+
/** Trim a string, returning null for empty/missing values. */
|
|
147813
|
+
function trimOrNull(value) {
|
|
147814
|
+
if (typeof value !== "string") return null;
|
|
147815
|
+
return value.trim() || null;
|
|
147816
|
+
}
|
|
147817
|
+
/**
|
|
147818
|
+
* Resolve the actual API model identifier from a model selection.
|
|
147819
|
+
*
|
|
147820
|
+
* Provider-aware: each provider can map `contextWindow` (or other options)
|
|
147821
|
+
* to whatever the API requires — a model-id suffix, a separate parameter, etc.
|
|
147822
|
+
* The canonical slug stored in the selection stays unchanged so the
|
|
147823
|
+
* capabilities system keeps working.
|
|
147824
|
+
*
|
|
147825
|
+
* Expects `contextWindow` to already be resolved (via `resolveContextWindow`)
|
|
147826
|
+
* to the effective value, not stripped to `undefined` for defaults.
|
|
147827
|
+
*/
|
|
147828
|
+
function resolveApiModelId(modelSelection) {
|
|
147829
|
+
switch (modelSelection.provider) {
|
|
147830
|
+
case "claudeAgent": switch (modelSelection.options?.contextWindow) {
|
|
147831
|
+
case "1m": return `${modelSelection.model}[1m]`;
|
|
147832
|
+
default: return modelSelection.model;
|
|
147833
|
+
}
|
|
147834
|
+
default: return modelSelection.model;
|
|
147835
|
+
}
|
|
147836
|
+
}
|
|
147837
|
+
function applyClaudePromptEffortPrefix(text, effort) {
|
|
147838
|
+
const trimmed = text.trim();
|
|
147839
|
+
if (!trimmed) return trimmed;
|
|
147840
|
+
if (effort !== "ultrathink") return trimmed;
|
|
147841
|
+
if (trimmed.startsWith("Ultrathink:")) return trimmed;
|
|
147842
|
+
return `Ultrathink:\n${trimmed}`;
|
|
147843
|
+
}
|
|
147844
|
+
function getRawProviderOptionSelectionValue(selections, id) {
|
|
147845
|
+
return selections?.find((candidate) => candidate.id === id)?.value;
|
|
147846
|
+
}
|
|
147847
|
+
function getProviderOptionSelectionValue(selections, id) {
|
|
147848
|
+
return getRawProviderOptionSelectionValue(selections, id);
|
|
147849
|
+
}
|
|
147850
|
+
function getProviderOptionStringSelectionValue(selections, id) {
|
|
147851
|
+
const value = getProviderOptionSelectionValue(selections, id);
|
|
147852
|
+
return typeof value === "string" ? value : void 0;
|
|
147853
|
+
}
|
|
147854
|
+
function flatProviderOptions(selection) {
|
|
147855
|
+
if (!selection) return void 0;
|
|
147856
|
+
if (selection.provider !== "cursor" && selection.provider !== "opencode") return void 0;
|
|
147857
|
+
return selection.options;
|
|
147858
|
+
}
|
|
147859
|
+
function getModelSelectionStringOptionValue(selection, id) {
|
|
147860
|
+
return getProviderOptionStringSelectionValue(flatProviderOptions(selection), id);
|
|
147861
|
+
}
|
|
147862
|
+
function acceptableModelSlug(value) {
|
|
147863
|
+
const trimmed = value?.trim();
|
|
147864
|
+
if (!trimmed || trimmed.length > 120) return;
|
|
147865
|
+
return trimmed;
|
|
147866
|
+
}
|
|
147867
|
+
/**
|
|
147868
|
+
* Order the credential's model scope: selected model first, then the catalog,
|
|
147869
|
+
* deduplicated and capped.
|
|
147870
|
+
*
|
|
147871
|
+
* Returns `undefined` when there is no catalog to widen to, which is the signal
|
|
147872
|
+
* to send the old single-model body. A slug CMMD would refuse is dropped rather
|
|
147873
|
+
* than sent, because one bad entry 400s the whole mint and takes the session
|
|
147874
|
+
* with it.
|
|
147875
|
+
*/
|
|
147876
|
+
function providerEgressModelScope(model, models) {
|
|
147877
|
+
const catalog = (models ?? []).map(acceptableModelSlug).filter((slug) => slug !== void 0);
|
|
147878
|
+
if (catalog.length === 0) return;
|
|
147879
|
+
const selected = acceptableModelSlug(model);
|
|
147880
|
+
const ordered = new Set(selected ? [selected] : []);
|
|
147881
|
+
for (const slug of catalog) {
|
|
147882
|
+
if (ordered.size >= 32) break;
|
|
147883
|
+
ordered.add(slug);
|
|
147884
|
+
}
|
|
147885
|
+
return [...ordered];
|
|
147886
|
+
}
|
|
147887
|
+
//#endregion
|
|
147888
|
+
//#region src/provider/codexCredentialModelScope.ts
|
|
147889
|
+
/**
|
|
147890
|
+
* Which Codex models one workspace egress credential has to cover.
|
|
147891
|
+
*
|
|
147892
|
+
* FOR-36501: the credential was scoped to the model the user picked, and the
|
|
147893
|
+
* Codex app-server holds one credential for the whole process. A turn on
|
|
147894
|
+
* gpt-6-astra that called `spawn_agent` with gpt-5.6-terra therefore lost the
|
|
147895
|
+
* child to a 401 before it spent a token. The subagent model is the model's own
|
|
147896
|
+
* choice in the tool arguments, so Forge cannot predict it and has to scope the
|
|
147897
|
+
* credential to the catalog a spawn can pick from.
|
|
147898
|
+
*
|
|
147899
|
+
* The catalog is the built-in Codex list, which is what the picker offers. It
|
|
147900
|
+
* includes the Spark model even though only a Pro account may call it: the
|
|
147901
|
+
* account snapshot is not resolved at issue time in workspace mode, and CMMD
|
|
147902
|
+
* still decides per call which models the account may use, so a slug in the
|
|
147903
|
+
* scope is permission to ask, never permission to spend.
|
|
147904
|
+
*/
|
|
147905
|
+
/**
|
|
147906
|
+
* Normalize a Codex model slug to the one the app-server and the mint route use.
|
|
147907
|
+
*
|
|
147908
|
+
* Lives here rather than in codexAppServerManager.ts so the catalog builder can
|
|
147909
|
+
* use it without importing the manager back. The manager re-exports it, which is
|
|
147910
|
+
* where every existing caller still reads it from.
|
|
147911
|
+
*/
|
|
147912
|
+
function normalizeCodexModelSlug(model, preferredId) {
|
|
147913
|
+
const normalized = normalizeModelSlug(model);
|
|
147914
|
+
if (!normalized) return;
|
|
147915
|
+
if (preferredId?.endsWith("-codex") && preferredId !== normalized) return preferredId;
|
|
147916
|
+
return normalized;
|
|
147917
|
+
}
|
|
147918
|
+
/** The model a proxy token is minted for when the thread names none. */
|
|
147919
|
+
function resolveCodexProviderProxyTokenModel(model) {
|
|
147920
|
+
const displaySlug = model?.trim().toLowerCase().replace(/\s+/g, "-");
|
|
147921
|
+
return normalizeCodexModelSlug(displaySlug) ?? "gpt-6-astra";
|
|
147922
|
+
}
|
|
147923
|
+
/** Every built-in Codex slug a `spawn_agent` call can name. */
|
|
147924
|
+
function codexCredentialModelCatalog() {
|
|
147925
|
+
return CODEX_BUILT_IN_MODELS.map((model) => normalizeCodexModelSlug(model.slug) ?? model.slug);
|
|
147926
|
+
}
|
|
147927
|
+
/**
|
|
147928
|
+
* The `models` list to mint a Codex session credential with.
|
|
147929
|
+
*
|
|
147930
|
+
* `undefined` means the catalog is unknown, and the caller then sends `model`
|
|
147931
|
+
* alone, exactly as before this card. That is the only safe answer: an empty
|
|
147932
|
+
* list would narrow the credential rather than widen it.
|
|
147933
|
+
*/
|
|
147934
|
+
function buildCodexCredentialModelScope(input) {
|
|
147935
|
+
const catalog = (input.catalogModels ?? codexCredentialModelCatalog()).map((slug) => normalizeCodexModelSlug(slug) ?? slug).filter((slug) => slug.trim().length > 0);
|
|
147936
|
+
return providerEgressModelScope(input.selectedModel, catalog);
|
|
147937
|
+
}
|
|
147938
|
+
//#endregion
|
|
147681
147939
|
//#region src/egress/providerDeliveryReceipt.ts
|
|
147682
147940
|
const PROVIDER_ACCOUNT_IDENTITY$2 = /^pai_v1_[A-Za-z0-9_-]{43}$/;
|
|
147683
147941
|
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -147929,6 +148187,21 @@ function runtimeProviderEgressBaseUrl(provider, controlPlaneUrl) {
|
|
|
147929
148187
|
anthropic: "/api/provider-egress/anthropic"
|
|
147930
148188
|
}[provider]}`;
|
|
147931
148189
|
}
|
|
148190
|
+
/**
|
|
148191
|
+
* The model fields of a mint body.
|
|
148192
|
+
*
|
|
148193
|
+
* `model` stays the single selected model, which is what CMMD runs its
|
|
148194
|
+
* post-mint constraint check on. `models` appears only when the caller knows a
|
|
148195
|
+
* catalog, so a caller that does not know one sends exactly the body it sent
|
|
148196
|
+
* before FOR-36501.
|
|
148197
|
+
*/
|
|
148198
|
+
function providerEgressModelBodyFields(input) {
|
|
148199
|
+
const scope = providerEgressModelScope(input.model, input.models);
|
|
148200
|
+
return {
|
|
148201
|
+
...input.model ? { model: input.model } : {},
|
|
148202
|
+
...scope ? { models: scope } : {}
|
|
148203
|
+
};
|
|
148204
|
+
}
|
|
147932
148205
|
const issueProviderEgressToken = (input) => issueProviderEgressCredential(input).pipe(map$3((credential) => credential.token));
|
|
147933
148206
|
const issueProviderEgressCredential = (input) => tryPromise({
|
|
147934
148207
|
try: async () => {
|
|
@@ -147952,7 +148225,7 @@ async function issueCmmdRuntimeProviderEgressCredential(input) {
|
|
|
147952
148225
|
token: runtimeGrantToken,
|
|
147953
148226
|
body: JSON.stringify({
|
|
147954
148227
|
provider: input.provider,
|
|
147955
|
-
...input
|
|
148228
|
+
...providerEgressModelBodyFields(input),
|
|
147956
148229
|
...input.provider === "openai" && input.providerAccountId ? { provider_account_id: input.providerAccountId } : {}
|
|
147957
148230
|
})
|
|
147958
148231
|
});
|
|
@@ -148068,7 +148341,7 @@ function issueCmmdLocalUserProviderEgressCredential(input) {
|
|
|
148068
148341
|
},
|
|
148069
148342
|
body: JSON.stringify({
|
|
148070
148343
|
provider: input.provider,
|
|
148071
|
-
...input
|
|
148344
|
+
...providerEgressModelBodyFields(input),
|
|
148072
148345
|
...input.provider === "openai" && input.providerAccountId ? { provider_account_id: input.providerAccountId } : {},
|
|
148073
148346
|
client: "local-desktop",
|
|
148074
148347
|
sessionId,
|
|
@@ -148451,16 +148724,6 @@ function mapCodexRuntimeMode(runtimeMode) {
|
|
|
148451
148724
|
async function killChildTree(child) {
|
|
148452
148725
|
await killCodexChildProcess(child);
|
|
148453
148726
|
}
|
|
148454
|
-
function normalizeCodexModelSlug(model, preferredId) {
|
|
148455
|
-
const normalized = normalizeModelSlug(model);
|
|
148456
|
-
if (!normalized) return;
|
|
148457
|
-
if (preferredId?.endsWith("-codex") && preferredId !== normalized) return preferredId;
|
|
148458
|
-
return normalized;
|
|
148459
|
-
}
|
|
148460
|
-
function resolveCodexProviderProxyTokenModel(model) {
|
|
148461
|
-
const displaySlug = model?.trim().toLowerCase().replace(/\s+/g, "-");
|
|
148462
|
-
return normalizeCodexModelSlug(displaySlug) ?? "gpt-6-astra";
|
|
148463
|
-
}
|
|
148464
148727
|
function buildCodexCollaborationMode(input) {
|
|
148465
148728
|
if (input.interactionMode === void 0) return;
|
|
148466
148729
|
const model = normalizeCodexModelSlug(input.model) ?? "gpt-6-astra";
|
|
@@ -149011,9 +149274,11 @@ var CodexAppServerManager = class extends EventEmitter$1 {
|
|
|
149011
149274
|
const proxyConfig = getOpenAiProviderEgressProxyConfig({ allowLocalUser: true });
|
|
149012
149275
|
if (proxyConfig.mode === "disabled") return null;
|
|
149013
149276
|
if (proxyConfig.mode === "misconfigured") throw new ProviderEgressTokenError({ message: proxyConfig.message });
|
|
149277
|
+
const models = buildCodexCredentialModelScope({ selectedModel: input.model });
|
|
149014
149278
|
return await runPromise(issueProviderEgressCredential({
|
|
149015
149279
|
provider: "openai",
|
|
149016
149280
|
model: input.model,
|
|
149281
|
+
...models ? { models } : {},
|
|
149017
149282
|
threadId: input.threadId,
|
|
149018
149283
|
...input.providerAccountId ? { providerAccountId: input.providerAccountId } : {}
|
|
149019
149284
|
}));
|
|
@@ -206713,6 +206978,7 @@ function toCanonicalItemType(raw) {
|
|
|
206713
206978
|
if (type.includes("computer")) return "mcp_tool_call";
|
|
206714
206979
|
if (type.includes("mcp")) return "mcp_tool_call";
|
|
206715
206980
|
if (type.includes("dynamic tool")) return "dynamic_tool_call";
|
|
206981
|
+
if (type.includes("sub agent")) return "collab_agent_tool_call";
|
|
206716
206982
|
if (type.includes("collab")) return "collab_agent_tool_call";
|
|
206717
206983
|
if (type.includes("web search")) return "web_search";
|
|
206718
206984
|
if (type.includes("image")) return "image_view";
|
|
@@ -206777,6 +207043,21 @@ function itemDetail(item, payload) {
|
|
|
206777
207043
|
return trimmed;
|
|
206778
207044
|
}
|
|
206779
207045
|
}
|
|
207046
|
+
const SUB_AGENT_ACTIVITY_TITLE = "Subagent";
|
|
207047
|
+
/**
|
|
207048
|
+
* The text a subagent spawn shows in the timeline.
|
|
207049
|
+
*
|
|
207050
|
+
* A `SubAgentActivity` item carries only the agent path, the child thread id,
|
|
207051
|
+
* and whether the spawn started or completed. `itemDetail` reads none of those
|
|
207052
|
+
* fields, and both the started and the completed item arrive as `item/completed`,
|
|
207053
|
+
* so the lifecycle status cannot tell them apart either. Without this the row
|
|
207054
|
+
* renders as a bare title with no text under it. The app-server wire is
|
|
207055
|
+
* camelCase and the rollout file is snake_case, so read both.
|
|
207056
|
+
*/
|
|
207057
|
+
function subAgentActivityDetail(item) {
|
|
207058
|
+
const parts = [asString$2(item.agentPath)?.trim() || asString$2(item.agent_path)?.trim(), asString$2(item.kind)?.trim()].filter((part) => part !== void 0 && part.length > 0);
|
|
207059
|
+
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
207060
|
+
}
|
|
206780
207061
|
function toRequestTypeFromMethod(method) {
|
|
206781
207062
|
switch (method) {
|
|
206782
207063
|
case "item/commandExecution/requestApproval": return "command_execution_approval";
|
|
@@ -206948,7 +207229,9 @@ function mapItemLifecycle(event, canonicalThreadId, lifecycle) {
|
|
|
206948
207229
|
if ((itemType === "mcp_tool_call" || itemType === "dynamic_tool_call") && (isBrowserToolName(source.name) || isBrowserToolName(source.toolName) || isBrowserToolName(source.method) || isBrowserToolName(payload?.toolName) || isBrowserToolName(payload?.method))) itemType = "browser_automation";
|
|
206949
207230
|
if ((itemType === "unknown" || itemType === "mcp_tool_call" || itemType === "dynamic_tool_call") && (isComputerToolName(source.name) || isComputerToolName(source.toolName) || isComputerToolName(source.method) || isComputerToolName(payload?.toolName) || isComputerToolName(payload?.method))) itemType = "mcp_tool_call";
|
|
206950
207231
|
if (itemType === "unknown" && lifecycle !== "item.updated") return;
|
|
206951
|
-
const
|
|
207232
|
+
const subAgentDetail = normalizeItemType(source.type).includes("sub agent") ? subAgentActivityDetail(source) : void 0;
|
|
207233
|
+
const detail = subAgentDetail ?? itemDetail(source, payload ?? {});
|
|
207234
|
+
const title = subAgentDetail ? SUB_AGENT_ACTIVITY_TITLE : itemTitle(itemType);
|
|
206952
207235
|
const status = lifecycle === "item.started" ? "inProgress" : lifecycle === "item.completed" ? "completed" : void 0;
|
|
206953
207236
|
return {
|
|
206954
207237
|
...runtimeEventBase(event, canonicalThreadId),
|
|
@@ -206956,7 +207239,7 @@ function mapItemLifecycle(event, canonicalThreadId, lifecycle) {
|
|
|
206956
207239
|
payload: {
|
|
206957
207240
|
itemType,
|
|
206958
207241
|
...status ? { status } : {},
|
|
206959
|
-
...
|
|
207242
|
+
...title ? { title } : {},
|
|
206960
207243
|
...detail ? { detail } : {},
|
|
206961
207244
|
...event.payload !== void 0 ? { data: event.payload } : {}
|
|
206962
207245
|
}
|
|
@@ -207200,36 +207483,23 @@ function mapCodexThreadNameUpdatedEvent(event, canonicalThreadId, payload) {
|
|
|
207200
207483
|
}
|
|
207201
207484
|
}];
|
|
207202
207485
|
}
|
|
207203
|
-
/** One provider call's spend, from Codex's `last_token_usage`. */
|
|
207204
|
-
function codexTurnUsageDelta(value) {
|
|
207205
|
-
const usage = asObject$2(value);
|
|
207206
|
-
return codexUsageBuckets(usage?.last_token_usage ?? usage?.last, "call-delta");
|
|
207207
|
-
}
|
|
207208
207486
|
/**
|
|
207209
|
-
* One
|
|
207210
|
-
*
|
|
207211
|
-
*
|
|
207212
|
-
*
|
|
207487
|
+
* One provider call's spend, from Codex's `last_token_usage`. Reads the
|
|
207488
|
+
* buckets via `codexTokenBuckets`, the shared home of the Claude/Codex
|
|
207489
|
+
* disjointness rule (providerTokenBuckets.ts): Codex reports `input_tokens`
|
|
207490
|
+
* inclusive of the cached and cache-write portions, so the uncached bucket is
|
|
207491
|
+
* the remainder, and reasoning is reported inside output and surfaced
|
|
207492
|
+
* separately without being added again. Mirrors `parseCodexLine` in
|
|
207213
207493
|
* usage/usageTranscripts.ts so a Recorded turn and a scanned transcript agree
|
|
207214
207494
|
* on the same numbers.
|
|
207215
207495
|
*/
|
|
207216
|
-
function
|
|
207217
|
-
const
|
|
207218
|
-
|
|
207219
|
-
|
|
207220
|
-
|
|
207221
|
-
|
|
207222
|
-
|
|
207223
|
-
const outputTokens = int("output_tokens", "outputTokens");
|
|
207224
|
-
if (inputTokens + cachedInputTokens + cacheCreationTokens + outputTokens === 0) return void 0;
|
|
207225
|
-
return {
|
|
207226
|
-
scope,
|
|
207227
|
-
uncachedInputTokens: Math.max(0, inputTokens - cachedInputTokens - cacheCreationTokens),
|
|
207228
|
-
cachedInputTokens,
|
|
207229
|
-
cacheCreationTokens,
|
|
207230
|
-
outputTokens,
|
|
207231
|
-
reasoningTokens: Math.min(outputTokens, int("reasoning_output_tokens", "reasoningOutputTokens"))
|
|
207232
|
-
};
|
|
207496
|
+
function codexTurnUsageDelta(value) {
|
|
207497
|
+
const usage = asObject$2(value);
|
|
207498
|
+
const buckets = codexTokenBuckets(usage?.last_token_usage ?? usage?.last);
|
|
207499
|
+
return buckets ? {
|
|
207500
|
+
scope: "call-delta",
|
|
207501
|
+
...buckets
|
|
207502
|
+
} : void 0;
|
|
207233
207503
|
}
|
|
207234
207504
|
function mapCodexThreadTokenUsageEvent(event, canonicalThreadId, payload) {
|
|
207235
207505
|
const tokenUsage = asObject$2(payload?.tokenUsage);
|
|
@@ -207921,6 +208191,7 @@ const DEFAULT_PUBLIC_PROVIDER_ERROR = "CMMD is temporarily unavailable. Check th
|
|
|
207921
208191
|
function categorizePublicProviderError(message) {
|
|
207922
208192
|
if (!message) return null;
|
|
207923
208193
|
const m = message.toLowerCase();
|
|
208194
|
+
if (/\bforge_provider_model_not_allowed\b/.test(m) || /\bnot\s+scoped\s+to\s+the\s+requested\s+model\b/.test(m)) return "The workspace AI credential does not cover the model this turn asked for. Retry, or pick that model for the thread.";
|
|
207924
208195
|
if (/\bmodel\b[\s\S]*\b(not\s+(found|available|supported)|does\s+not\s+exist|unsupported|invalid|unknown)\b/.test(m) || /\b(unsupported|unknown|invalid)\b[\s\S]*\bmodel\b/.test(m) || /\b(model_not_found|invalid_model|model_not_supported)\b/.test(m)) return "The selected model isn't available right now. Pick a different model and retry.";
|
|
207925
208196
|
if (/\b(rate[\s-]?limit|too\s+many\s+requests|quota|insufficient_quota)\b/.test(m) || /\b429\b/.test(m)) return "The AI service is rate-limited or out of quota. Wait a moment and retry.";
|
|
207926
208197
|
if (/\b(unauthorized|forbidden|authentication\s+(failed|error|required)|invalid\s+api\s+key|expired\s+(token|credential))\b/.test(m) || /\b40[13]\b/.test(m)) return "Workspace AI authentication failed. Reconnect the workspace and retry.";
|
|
@@ -209769,9 +210040,6 @@ function buildClaudeSessionContext(input) {
|
|
|
209769
210040
|
query: input.queryRuntime,
|
|
209770
210041
|
streamFiber: void 0,
|
|
209771
210042
|
startedAt: input.startedAt,
|
|
209772
|
-
recordsPersonalUsageTelemetry: input.recordsPersonalUsageTelemetry,
|
|
209773
|
-
personalUsageGenerationHash: input.personalUsageGenerationHash,
|
|
209774
|
-
personalUsageProviderAccountId: input.personalUsageProviderAccountId,
|
|
209775
210043
|
basePermissionMode: input.permissionMode,
|
|
209776
210044
|
resumeSessionId: input.sessionId,
|
|
209777
210045
|
pendingApprovals: input.pendingApprovals,
|
|
@@ -210129,26 +210397,18 @@ function finiteNumberFieldOrZero(usage, key) {
|
|
|
210129
210397
|
}
|
|
210130
210398
|
/**
|
|
210131
210399
|
* The whole turn's spend from the SDK result message, cache split intact.
|
|
210132
|
-
*
|
|
210133
|
-
*
|
|
210134
|
-
*
|
|
210400
|
+
* Reads the buckets via `claudeTokenBuckets`, the shared home of the
|
|
210401
|
+
* Claude/Codex disjointness rule (providerTokenBuckets.ts): Claude reports
|
|
210402
|
+
* `input_tokens` exclusive of the cached and cache-creation portions, so the
|
|
210403
|
+
* buckets are already disjoint, and Claude does not report reasoning
|
|
210404
|
+
* separately.
|
|
210135
210405
|
*/
|
|
210136
210406
|
function claudeTurnUsageTotal(value) {
|
|
210137
|
-
const
|
|
210138
|
-
|
|
210139
|
-
const uncachedInputTokens = finiteNumberFieldOrZero(usage, "input_tokens");
|
|
210140
|
-
const cachedInputTokens = finiteNumberFieldOrZero(usage, "cache_read_input_tokens");
|
|
210141
|
-
const cacheCreationTokens = finiteNumberFieldOrZero(usage, "cache_creation_input_tokens");
|
|
210142
|
-
const outputTokens = finiteNumberFieldOrZero(usage, "output_tokens");
|
|
210143
|
-
if (uncachedInputTokens + cachedInputTokens + cacheCreationTokens + outputTokens <= 0) return;
|
|
210144
|
-
return {
|
|
210407
|
+
const buckets = claudeTokenBuckets(value);
|
|
210408
|
+
return buckets ? {
|
|
210145
210409
|
scope: "turn-total",
|
|
210146
|
-
|
|
210147
|
-
|
|
210148
|
-
cacheCreationTokens: Math.trunc(cacheCreationTokens),
|
|
210149
|
-
outputTokens: Math.trunc(outputTokens),
|
|
210150
|
-
reasoningTokens: 0
|
|
210151
|
-
};
|
|
210410
|
+
...buckets
|
|
210411
|
+
} : void 0;
|
|
210152
210412
|
}
|
|
210153
210413
|
const EMPTY_MODEL_USAGE_BUCKETS = {
|
|
210154
210414
|
uncachedInputTokens: 0,
|
|
@@ -210161,20 +210421,14 @@ function bucketsTotal(buckets) {
|
|
|
210161
210421
|
return buckets.uncachedInputTokens + buckets.cachedInputTokens + buckets.cacheCreationTokens + buckets.outputTokens;
|
|
210162
210422
|
}
|
|
210163
210423
|
/**
|
|
210164
|
-
* One `ModelUsage` entry as buckets
|
|
210165
|
-
* camelCase, unlike `result.usage`,
|
|
210166
|
-
* Claude reports `inputTokens` exclusive of the
|
|
210167
|
-
* portions, so the buckets are already disjoint, and
|
|
210424
|
+
* One `ModelUsage` entry as buckets, via `claudeTokenBuckets`. `ModelUsage`
|
|
210425
|
+
* names its fields in camelCase, unlike `result.usage`, but `claudeTokenBuckets`
|
|
210426
|
+
* already reads both spellings. Claude reports `inputTokens` exclusive of the
|
|
210427
|
+
* cached and cache-creation portions, so the buckets are already disjoint, and
|
|
210428
|
+
* it reports no reasoning.
|
|
210168
210429
|
*/
|
|
210169
210430
|
function claudeModelUsageBuckets(usage) {
|
|
210170
|
-
|
|
210171
|
-
return {
|
|
210172
|
-
uncachedInputTokens: Math.trunc(finiteNumberFieldOrZero(record, "inputTokens")),
|
|
210173
|
-
cachedInputTokens: Math.trunc(finiteNumberFieldOrZero(record, "cacheReadInputTokens")),
|
|
210174
|
-
cacheCreationTokens: Math.trunc(finiteNumberFieldOrZero(record, "cacheCreationInputTokens")),
|
|
210175
|
-
outputTokens: Math.trunc(finiteNumberFieldOrZero(record, "outputTokens")),
|
|
210176
|
-
reasoningTokens: 0
|
|
210177
|
-
};
|
|
210431
|
+
return claudeTokenBuckets(usage) ?? EMPTY_MODEL_USAGE_BUCKETS;
|
|
210178
210432
|
}
|
|
210179
210433
|
/**
|
|
210180
210434
|
* What each model spent during THIS turn, from the SDK's per-model totals.
|
|
@@ -211517,7 +211771,6 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
211517
211771
|
return;
|
|
211518
211772
|
}
|
|
211519
211773
|
if (message.type === "rate_limit_event") {
|
|
211520
|
-
if (context.recordsPersonalUsageTelemetry) recordClaudeRateLimitTelemetry(message.rate_limit_info, context.personalUsageGenerationHash, context.personalUsageProviderAccountId);
|
|
211521
211774
|
yield* offerRuntimeEvent({
|
|
211522
211775
|
...base,
|
|
211523
211776
|
type: "account.rate-limits.updated",
|
|
@@ -212015,10 +212268,7 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
212015
212268
|
inFlightTools,
|
|
212016
212269
|
resumeSessionAt: resumeState?.resumeSessionAt,
|
|
212017
212270
|
effectiveApiModelId: modelConfig.effectiveApiModelId,
|
|
212018
|
-
effectiveEffort: modelConfig.effectiveEffort
|
|
212019
|
-
recordsPersonalUsageTelemetry: sessionProvider === PROVIDER$11 && modelConfig.endpointProfile === void 0 && providerProxyCredential === null && !claudeSettings.anthropicBaseUrl && !claudeSettings.anthropicApiKey,
|
|
212020
|
-
personalUsageGenerationHash: currentClaudeUsageGenerationHash(),
|
|
212021
|
-
personalUsageProviderAccountId: modelConfig.modelSelection?.provider === "claudeAgent" ? modelConfig.modelSelection.providerAccountId : void 0
|
|
212271
|
+
effectiveEffort: modelConfig.effectiveEffort
|
|
212022
212272
|
});
|
|
212023
212273
|
yield* set$2(contextRef, context$4);
|
|
212024
212274
|
sessions.set(threadId, context$4);
|
|
@@ -284225,6 +284475,27 @@ const makeRuntimeDrainReporter = gen(function* () {
|
|
|
284225
284475
|
var RuntimeDrainReporter = class extends Service$1()("forge/runtimeDrain/RuntimeDrainReporter") {};
|
|
284226
284476
|
const RuntimeDrainReporterLive = effect(RuntimeDrainReporter, makeRuntimeDrainReporter);
|
|
284227
284477
|
//#endregion
|
|
284478
|
+
//#region src/usage/providerRateLimits.ts
|
|
284479
|
+
/**
|
|
284480
|
+
* The SDK only ever reports ONE window per event. Only `five_hour` and
|
|
284481
|
+
* `seven_day` map to the two windows the Usage page shows; the
|
|
284482
|
+
* per-model/overage variants (seven_day_opus, overage, ...) are ignored here
|
|
284483
|
+
* on purpose rather than silently overwriting the plain 7-day figure.
|
|
284484
|
+
*/
|
|
284485
|
+
function mapClaudeRateLimitInfo(info) {
|
|
284486
|
+
if (typeof info.utilization !== "number" || typeof info.resetsAt !== "number" || !info.status) return null;
|
|
284487
|
+
const kind = info.rateLimitType === "five_hour" ? "fiveHour" : info.rateLimitType === "seven_day" ? "sevenDay" : null;
|
|
284488
|
+
if (!kind) return null;
|
|
284489
|
+
return {
|
|
284490
|
+
kind,
|
|
284491
|
+
window: {
|
|
284492
|
+
usedPercent: Math.round(info.utilization * 100),
|
|
284493
|
+
resetsAt: (/* @__PURE__ */ new Date(info.resetsAt * 1e3)).toISOString(),
|
|
284494
|
+
status: info.status
|
|
284495
|
+
}
|
|
284496
|
+
};
|
|
284497
|
+
}
|
|
284498
|
+
//#endregion
|
|
284228
284499
|
//#region src/orchestration/Layers/ProviderRuntimeIngestion.ts
|
|
284229
284500
|
const providerTurnKey = (threadId, turnId) => `${threadId}:${turnId}`;
|
|
284230
284501
|
const providerCommandId = (event, tag) => CommandId.make(`provider:${event.eventId}:${tag}:${crypto.randomUUID()}`);
|
|
@@ -291239,7 +291510,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
291239
291510
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
291240
291511
|
*/
|
|
291241
291512
|
function readBakedBuildCommit() {
|
|
291242
|
-
return "
|
|
291513
|
+
return "ce557b7ba4e4d217f25ff499adb104f8cd18a703";
|
|
291243
291514
|
}
|
|
291244
291515
|
async function resolveServerBuildCommit(input) {
|
|
291245
291516
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -300422,6 +300693,7 @@ function resolveWsUrl(baseUrl) {
|
|
|
300422
300693
|
const callCmmdTool = legacyCmmdToolBridge.callTool;
|
|
300423
300694
|
const extractMcpToolText = legacyCmmdToolBridge.extractText;
|
|
300424
300695
|
const isCmmdMcpAuthError = legacyCmmdToolBridge.isAuthError;
|
|
300696
|
+
const __cmmdProxyRouteLayersStartIndex = registeredProxyRouteLayers().length;
|
|
300425
300697
|
/**
|
|
300426
300698
|
* CMMD-side path for the PROJECT-keyed Forge Cloud catalog. Shared by the list
|
|
300427
300699
|
* proxy, the SSE poll-and-emit proxy, and the register/unregister proxies so the
|
|
@@ -300431,8 +300703,9 @@ const CMMD_CLOUD_PROJECTS_PATH = "/api/forge/context/cloud-projects";
|
|
|
300431
300703
|
const CMMD_RUNTIMES_PATH = "/api/forge/context/runtimes";
|
|
300432
300704
|
/**
|
|
300433
300705
|
* Authenticate the browser session and resolve the CMMD JWT to forward
|
|
300434
|
-
* upstream.
|
|
300435
|
-
* turns into
|
|
300706
|
+
* upstream. `jwt` is null when none could be resolved, which every caller
|
|
300707
|
+
* turns into `respondCmmdConnectionRequired(session.sessionId)` — the same
|
|
300708
|
+
* unified `CMMD_AUTH_REQUIRED` body and auth-clear the registry uses.
|
|
300436
300709
|
*
|
|
300437
300710
|
* Shared so the auth preamble is written once rather than once per proxy route.
|
|
300438
300711
|
*/
|
|
@@ -300440,11 +300713,14 @@ function makeCmmdProxyAccessTokenEffect(logPrefix) {
|
|
|
300440
300713
|
return gen(function* () {
|
|
300441
300714
|
const request = yield* HttpServerRequest;
|
|
300442
300715
|
const session = yield* (yield* ServerAuth).authenticateHttpRequest(request);
|
|
300443
|
-
return
|
|
300444
|
-
|
|
300445
|
-
|
|
300446
|
-
|
|
300447
|
-
|
|
300716
|
+
return {
|
|
300717
|
+
session,
|
|
300718
|
+
jwt: yield* resolveCmmdJwtForSession({
|
|
300719
|
+
sessionId: session.sessionId,
|
|
300720
|
+
subject: session.subject,
|
|
300721
|
+
logPrefix
|
|
300722
|
+
})
|
|
300723
|
+
};
|
|
300448
300724
|
});
|
|
300449
300725
|
}
|
|
300450
300726
|
var WorkIntakeSnapshotReadError = class extends TaggedErrorClass()("WorkIntakeSnapshotReadError", {
|
|
@@ -300524,32 +300800,19 @@ const cmmdProfileRouteLayer = add$1("GET", "/api/cmmd/profile", gen(function* ()
|
|
|
300524
300800
|
* `resolution`/`sinceTime`/`untilTime` when the page is drawing hours, which is
|
|
300525
300801
|
* what lets CMMD cut hour buckets rather than only days.
|
|
300526
300802
|
*/
|
|
300527
|
-
|
|
300803
|
+
registerProxyRoute({
|
|
300528
300804
|
forgePath: "/api/cmmd/usage/summary",
|
|
300529
300805
|
method: "GET",
|
|
300530
300806
|
cmmdPath: "/api/forge/context/usage/summary",
|
|
300531
300807
|
orgIdSource: "none"
|
|
300532
300808
|
});
|
|
300533
|
-
|
|
300534
|
-
* The workspace's CMMD plan: entitlements, the current period, and how much of
|
|
300535
|
-
* each metered allowance is left. This is subscription consumption, which is a
|
|
300536
|
-
* different question from the API-equivalent estimate the usage summary above
|
|
300537
|
-
* computes from transcripts.
|
|
300538
|
-
*
|
|
300539
|
-
* `orgIdSource` is `query` (FOR-36406): a plan belongs to an organization, and
|
|
300540
|
-
* without one CMMD answers for the user's default organization, which is their
|
|
300541
|
-
* personal space rather than the workspace their Environment runs in. The web
|
|
300542
|
-
* passes the Environment's organization as `?orgId=` and the registry turns it
|
|
300543
|
-
* into `X-Organization-ID`; without it CMMD still answers, for the default.
|
|
300544
|
-
*/
|
|
300545
|
-
const cmmdBillingRouteLayer = registerProxyRoute({
|
|
300809
|
+
registerProxyRoute({
|
|
300546
300810
|
forgePath: "/api/cmmd/billing",
|
|
300547
300811
|
method: "GET",
|
|
300548
300812
|
cmmdPath: "/api/forge/context/billing",
|
|
300549
300813
|
orgIdSource: "query"
|
|
300550
300814
|
});
|
|
300551
|
-
|
|
300552
|
-
const cmmdBillingSeriesRouteLayer = registerProxyRoute({
|
|
300815
|
+
registerProxyRoute({
|
|
300553
300816
|
forgePath: "/api/cmmd/billing/series",
|
|
300554
300817
|
method: "GET",
|
|
300555
300818
|
cmmdPath: "/api/forge/context/billing/series",
|
|
@@ -300587,6 +300850,15 @@ function runCmmdRestProxy(session, proxy, dependencies = {}) {
|
|
|
300587
300850
|
});
|
|
300588
300851
|
}
|
|
300589
300852
|
/**
|
|
300853
|
+
* Adapts `runCmmdRestProxy`'s `{ ok, value | error }` outcome into a
|
|
300854
|
+
* `ProxyHandlerRoute.run` result: the shared shape every converted handler's
|
|
300855
|
+
* `run` uses so it stays the three or so lines of the actual gateway call
|
|
300856
|
+
* plus response shaping, with resolve-and-retry left to `runCmmdRestProxy`.
|
|
300857
|
+
*/
|
|
300858
|
+
function runCmmdRestProxyAsHandlerResult(session, proxy, shape) {
|
|
300859
|
+
return runCmmdRestProxy(session, proxy).pipe(flatMap((outcome) => outcome.ok ? succeed(shape(outcome.value)) : fail(outcome.error)));
|
|
300860
|
+
}
|
|
300861
|
+
/**
|
|
300590
300862
|
* Forge-context REST responses wrap their payload in `{ data, meta, pagination? }`
|
|
300591
300863
|
* (see CMMD `sendForgeEnvelope`). Unwrap to the bare payload so handler response
|
|
300592
300864
|
* shapes match what the web client expected from the prior MCP text path.
|
|
@@ -300750,22 +301022,34 @@ function buildCreateBrainDocumentInput(payload) {
|
|
|
300750
301022
|
...payload.tags && payload.tags.length > 0 ? { tags: payload.tags } : {}
|
|
300751
301023
|
};
|
|
300752
301024
|
}
|
|
300753
|
-
|
|
300754
|
-
|
|
300755
|
-
|
|
300756
|
-
|
|
300757
|
-
|
|
300758
|
-
|
|
300759
|
-
|
|
301025
|
+
function parseCreateBrainDocRequest(request) {
|
|
301026
|
+
return request.json.pipe(orElseSucceed(() => null), map$3((rawBody) => {
|
|
301027
|
+
const payload = parseBrainDocPayload(rawBody);
|
|
301028
|
+
return payload ? {
|
|
301029
|
+
ok: true,
|
|
301030
|
+
value: payload
|
|
301031
|
+
} : {
|
|
301032
|
+
ok: false,
|
|
301033
|
+
status: 400,
|
|
301034
|
+
body: { error: "Invalid request: title (1-500 chars) and content (1-100k chars) are required." }
|
|
301035
|
+
};
|
|
301036
|
+
}));
|
|
301037
|
+
}
|
|
301038
|
+
registerProxyHandler({
|
|
301039
|
+
forgePath: "/api/cmmd/brain-docs",
|
|
301040
|
+
method: "POST",
|
|
301041
|
+
parse: parseCreateBrainDocRequest,
|
|
301042
|
+
run: (payload, { session }) => runCmmdRestProxyAsHandlerResult(session, (jwt) => cmmdGateway.createBrainDocument({
|
|
300760
301043
|
jwt,
|
|
300761
301044
|
document: buildCreateBrainDocumentInput(payload)
|
|
300762
|
-
}))
|
|
300763
|
-
|
|
300764
|
-
|
|
300765
|
-
|
|
300766
|
-
|
|
300767
|
-
|
|
300768
|
-
})
|
|
301045
|
+
}), (value) => ({
|
|
301046
|
+
status: 201,
|
|
301047
|
+
body: {
|
|
301048
|
+
success: true,
|
|
301049
|
+
doc: unwrapForgeEnvelope(value)
|
|
301050
|
+
}
|
|
301051
|
+
}))
|
|
301052
|
+
});
|
|
300769
301053
|
function normalizeOptionalNullableString(value, options) {
|
|
300770
301054
|
if (value === void 0) return void 0;
|
|
300771
301055
|
if (value === null) return null;
|
|
@@ -300819,46 +301103,77 @@ function buildUpdateTaskToolInput(payload) {
|
|
|
300819
301103
|
...payload.labels !== void 0 ? { tags: payload.labels } : {}
|
|
300820
301104
|
};
|
|
300821
301105
|
}
|
|
300822
|
-
|
|
300823
|
-
|
|
300824
|
-
|
|
300825
|
-
|
|
300826
|
-
|
|
300827
|
-
|
|
301106
|
+
function parseUpdateCmmdTaskRequest(request) {
|
|
301107
|
+
return request.json.pipe(orElseSucceed(() => null), map$3((rawBody) => {
|
|
301108
|
+
const payload = parseUpdateTaskPayload(rawBody);
|
|
301109
|
+
return payload ? {
|
|
301110
|
+
ok: true,
|
|
301111
|
+
value: payload
|
|
301112
|
+
} : {
|
|
301113
|
+
ok: false,
|
|
301114
|
+
status: 400,
|
|
301115
|
+
body: { error: "Invalid request: taskId is required and at least one update field must be provided." }
|
|
301116
|
+
};
|
|
301117
|
+
}));
|
|
301118
|
+
}
|
|
301119
|
+
function runUpdateCmmdTask(payload, { session }) {
|
|
300828
301120
|
const { taskId, ...patch } = buildUpdateTaskToolInput(payload);
|
|
300829
|
-
|
|
301121
|
+
return runCmmdRestProxyAsHandlerResult(session, (jwt) => cmmdGateway.updateTask({
|
|
300830
301122
|
jwt,
|
|
300831
301123
|
taskId: String(taskId),
|
|
300832
301124
|
patch
|
|
300833
|
-
}))
|
|
300834
|
-
if (restOutcome.ok) {
|
|
301125
|
+
}), (value) => {
|
|
300835
301126
|
invalidateCachedCmmdWorkIntakeForSession(session.sessionId);
|
|
300836
|
-
return
|
|
300837
|
-
|
|
300838
|
-
|
|
300839
|
-
|
|
300840
|
-
|
|
300841
|
-
|
|
300842
|
-
}
|
|
300843
|
-
|
|
300844
|
-
|
|
300845
|
-
|
|
300846
|
-
|
|
300847
|
-
|
|
300848
|
-
|
|
300849
|
-
|
|
300850
|
-
|
|
300851
|
-
|
|
301127
|
+
return {
|
|
301128
|
+
status: 200,
|
|
301129
|
+
body: {
|
|
301130
|
+
success: true,
|
|
301131
|
+
details: unwrapForgeEnvelope(value)
|
|
301132
|
+
}
|
|
301133
|
+
};
|
|
301134
|
+
});
|
|
301135
|
+
}
|
|
301136
|
+
registerProxyHandler({
|
|
301137
|
+
forgePath: "/api/cmmd/tasks/update",
|
|
301138
|
+
method: "POST",
|
|
301139
|
+
parse: parseUpdateCmmdTaskRequest,
|
|
301140
|
+
run: runUpdateCmmdTask
|
|
301141
|
+
});
|
|
301142
|
+
registerProxyHandler({
|
|
301143
|
+
forgePath: "/api/command/tasks/update",
|
|
301144
|
+
method: "POST",
|
|
301145
|
+
parse: parseUpdateCmmdTaskRequest,
|
|
301146
|
+
run: runUpdateCmmdTask
|
|
301147
|
+
});
|
|
301148
|
+
function parseAddCmmdTaskCommentRequest(request) {
|
|
301149
|
+
return request.json.pipe(orElseSucceed(() => null), map$3((rawBody) => {
|
|
301150
|
+
const payload = parseTaskCommentPayload(rawBody);
|
|
301151
|
+
return payload ? {
|
|
301152
|
+
ok: true,
|
|
301153
|
+
value: payload
|
|
301154
|
+
} : {
|
|
301155
|
+
ok: false,
|
|
301156
|
+
status: 400,
|
|
301157
|
+
body: { error: "taskId and content (max 2000 chars) are required." }
|
|
301158
|
+
};
|
|
301159
|
+
}));
|
|
301160
|
+
}
|
|
301161
|
+
registerProxyHandler({
|
|
301162
|
+
forgePath: "/api/cmmd/tasks/comment",
|
|
301163
|
+
method: "POST",
|
|
301164
|
+
parse: parseAddCmmdTaskCommentRequest,
|
|
301165
|
+
run: (payload, { session }) => runCmmdRestProxyAsHandlerResult(session, (jwt) => cmmdGateway.addTaskComment({
|
|
300852
301166
|
jwt,
|
|
300853
301167
|
taskId: payload.taskId,
|
|
300854
301168
|
content: payload.content
|
|
300855
|
-
}))
|
|
300856
|
-
|
|
300857
|
-
|
|
300858
|
-
|
|
300859
|
-
|
|
300860
|
-
|
|
300861
|
-
})
|
|
301169
|
+
}), (value) => ({
|
|
301170
|
+
status: 201,
|
|
301171
|
+
body: {
|
|
301172
|
+
success: true,
|
|
301173
|
+
details: unwrapForgeEnvelope(value)
|
|
301174
|
+
}
|
|
301175
|
+
}))
|
|
301176
|
+
});
|
|
300862
301177
|
function parseTaskCommentPayload(body) {
|
|
300863
301178
|
if (typeof body !== "object" || body === null) return null;
|
|
300864
301179
|
const b = body;
|
|
@@ -300887,23 +301202,38 @@ function normalizeTaskSearchParams(url) {
|
|
|
300887
301202
|
limit: Math.min(Number(url.searchParams.get("limit") ?? "20"), 50)
|
|
300888
301203
|
};
|
|
300889
301204
|
}
|
|
300890
|
-
|
|
300891
|
-
|
|
300892
|
-
|
|
300893
|
-
|
|
300894
|
-
|
|
300895
|
-
|
|
300896
|
-
|
|
300897
|
-
|
|
300898
|
-
|
|
300899
|
-
|
|
301205
|
+
function parseSearchCmmdTasksRequest(request) {
|
|
301206
|
+
return sync$1(() => ({
|
|
301207
|
+
ok: true,
|
|
301208
|
+
value: normalizeTaskSearchParams(new URL(request.url, "http://localhost"))
|
|
301209
|
+
}));
|
|
301210
|
+
}
|
|
301211
|
+
function runSearchCmmdTasks(search, { session }) {
|
|
301212
|
+
if (!search) return succeed({
|
|
301213
|
+
status: 200,
|
|
301214
|
+
body: {
|
|
301215
|
+
tasks: [],
|
|
301216
|
+
total: 0
|
|
301217
|
+
}
|
|
301218
|
+
});
|
|
301219
|
+
const accessToken = readCommandAccessTokenForSession(session.sessionId) ?? "";
|
|
301220
|
+
return promise(() => callCmmdTool(accessToken, "search_tasks", {
|
|
300900
301221
|
query: search.query,
|
|
300901
301222
|
limit: search.limit
|
|
300902
|
-
})))
|
|
300903
|
-
|
|
300904
|
-
|
|
300905
|
-
|
|
300906
|
-
|
|
301223
|
+
})).pipe(map$3((result) => ({
|
|
301224
|
+
status: 200,
|
|
301225
|
+
body: parseJsonObjectText(extractMcpToolText(result)) ?? {
|
|
301226
|
+
tasks: [],
|
|
301227
|
+
total: 0
|
|
301228
|
+
}
|
|
301229
|
+
})));
|
|
301230
|
+
}
|
|
301231
|
+
registerProxyHandler({
|
|
301232
|
+
forgePath: "/api/cmmd/tasks/search",
|
|
301233
|
+
method: "GET",
|
|
301234
|
+
parse: parseSearchCmmdTasksRequest,
|
|
301235
|
+
run: runSearchCmmdTasks
|
|
301236
|
+
});
|
|
300907
301237
|
function parseJsonObjectText(text) {
|
|
300908
301238
|
if (!text) return null;
|
|
300909
301239
|
try {
|
|
@@ -300917,23 +301247,47 @@ function parsePositiveIntegerId(value) {
|
|
|
300917
301247
|
const numericId = Number(value);
|
|
300918
301248
|
return Number.isInteger(numericId) && numericId > 0 ? numericId : null;
|
|
300919
301249
|
}
|
|
300920
|
-
|
|
300921
|
-
|
|
300922
|
-
|
|
300923
|
-
|
|
300924
|
-
|
|
300925
|
-
|
|
300926
|
-
|
|
300927
|
-
|
|
300928
|
-
|
|
301250
|
+
function parseGetCmmdTaskRequest(request) {
|
|
301251
|
+
return sync$1(() => {
|
|
301252
|
+
const taskId = extractIdFromPath(new URL(request.url, "http://localhost").pathname, 1);
|
|
301253
|
+
if (!taskId) return {
|
|
301254
|
+
ok: false,
|
|
301255
|
+
status: 400,
|
|
301256
|
+
body: { error: "Task ID is required." }
|
|
301257
|
+
};
|
|
301258
|
+
const numericId = parsePositiveIntegerId(taskId);
|
|
301259
|
+
if (!numericId) return {
|
|
301260
|
+
ok: false,
|
|
301261
|
+
status: 400,
|
|
301262
|
+
body: { error: "Invalid task ID." }
|
|
301263
|
+
};
|
|
301264
|
+
return {
|
|
301265
|
+
ok: true,
|
|
301266
|
+
value: numericId
|
|
301267
|
+
};
|
|
301268
|
+
});
|
|
301269
|
+
}
|
|
301270
|
+
function runGetCmmdTask(numericId, { session }) {
|
|
301271
|
+
return runCmmdRestProxyAsHandlerResult(session, (jwt) => cmmdGateway.getTask({
|
|
300929
301272
|
jwt,
|
|
300930
301273
|
taskId: String(numericId)
|
|
300931
|
-
}))
|
|
300932
|
-
|
|
300933
|
-
|
|
300934
|
-
|
|
300935
|
-
|
|
300936
|
-
}
|
|
301274
|
+
}), (value) => {
|
|
301275
|
+
const task = unwrapForgeEnvelope(value);
|
|
301276
|
+
return task === null || task === void 0 ? {
|
|
301277
|
+
status: 404,
|
|
301278
|
+
body: { error: "Task not found." }
|
|
301279
|
+
} : {
|
|
301280
|
+
status: 200,
|
|
301281
|
+
body: task
|
|
301282
|
+
};
|
|
301283
|
+
});
|
|
301284
|
+
}
|
|
301285
|
+
registerProxyHandler({
|
|
301286
|
+
forgePath: "/api/cmmd/tasks/:id",
|
|
301287
|
+
method: "GET",
|
|
301288
|
+
parse: parseGetCmmdTaskRequest,
|
|
301289
|
+
run: runGetCmmdTask
|
|
301290
|
+
});
|
|
300937
301291
|
function extractIdFromPath(pathname, fromEnd) {
|
|
300938
301292
|
const parts = pathname.split("/").filter(Boolean);
|
|
300939
301293
|
return parts[parts.length - fromEnd];
|
|
@@ -300945,22 +301299,37 @@ function decodePathSegment(segment) {
|
|
|
300945
301299
|
return null;
|
|
300946
301300
|
}
|
|
300947
301301
|
}
|
|
300948
|
-
|
|
300949
|
-
|
|
300950
|
-
|
|
300951
|
-
|
|
300952
|
-
|
|
300953
|
-
|
|
300954
|
-
|
|
301302
|
+
function parseGetCmmdTaskCommentsRequest(request) {
|
|
301303
|
+
return sync$1(() => {
|
|
301304
|
+
const taskId = extractIdFromPath(new URL(request.url, "http://localhost").pathname, 2);
|
|
301305
|
+
return taskId ? {
|
|
301306
|
+
ok: true,
|
|
301307
|
+
value: taskId
|
|
301308
|
+
} : {
|
|
301309
|
+
ok: false,
|
|
301310
|
+
status: 400,
|
|
301311
|
+
body: { error: "Task ID is required." }
|
|
301312
|
+
};
|
|
301313
|
+
});
|
|
301314
|
+
}
|
|
301315
|
+
function runGetCmmdTaskComments(taskId, { session }) {
|
|
301316
|
+
return runCmmdRestProxyAsHandlerResult(session, (jwt) => cmmdGateway.listTaskComments({
|
|
300955
301317
|
jwt,
|
|
300956
301318
|
taskId
|
|
300957
|
-
}))
|
|
300958
|
-
|
|
300959
|
-
|
|
300960
|
-
|
|
300961
|
-
|
|
300962
|
-
|
|
300963
|
-
})
|
|
301319
|
+
}), (value) => {
|
|
301320
|
+
const data = unwrapForgeEnvelope(value);
|
|
301321
|
+
return {
|
|
301322
|
+
status: 200,
|
|
301323
|
+
body: { comments: Array.isArray(data) ? data : [] }
|
|
301324
|
+
};
|
|
301325
|
+
});
|
|
301326
|
+
}
|
|
301327
|
+
registerProxyHandler({
|
|
301328
|
+
forgePath: "/api/cmmd/tasks/:id/comments",
|
|
301329
|
+
method: "GET",
|
|
301330
|
+
parse: parseGetCmmdTaskCommentsRequest,
|
|
301331
|
+
run: runGetCmmdTaskComments
|
|
301332
|
+
});
|
|
300964
301333
|
function normalizeCommentList(value) {
|
|
300965
301334
|
if (Array.isArray(value)) return value;
|
|
300966
301335
|
if (!value || typeof value !== "object") return [];
|
|
@@ -301066,55 +301435,54 @@ const cmmdUpdateProjectRouteLayer = add$1("PATCH", "/api/cmmd/projects/:id", gen
|
|
|
301066
301435
|
project: outcome.value
|
|
301067
301436
|
}, { status: 200 });
|
|
301068
301437
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error))));
|
|
301069
|
-
|
|
301438
|
+
registerProxyRoute({
|
|
301070
301439
|
forgePath: "/api/cmmd/projects/:id/repository",
|
|
301071
301440
|
method: "GET",
|
|
301072
301441
|
cmmdPath: "/api/forge/context/projects/:id/repository",
|
|
301073
301442
|
orgIdSource: "none",
|
|
301074
301443
|
responseShape: "unwrapData"
|
|
301075
301444
|
});
|
|
301076
|
-
|
|
301077
|
-
const cmmdListProjectRepositoriesRouteLayer = registerProxyRoute({
|
|
301445
|
+
registerProxyRoute({
|
|
301078
301446
|
forgePath: "/api/cmmd/projects/:projectId/repositories",
|
|
301079
301447
|
method: "GET",
|
|
301080
301448
|
cmmdPath: "/api/forge/context/projects/:projectId/repositories",
|
|
301081
301449
|
orgIdSource: "none",
|
|
301082
301450
|
responseShape: "unwrapData"
|
|
301083
301451
|
});
|
|
301084
|
-
|
|
301452
|
+
registerProxyRoute({
|
|
301085
301453
|
forgePath: "/api/cmmd/organizations/:id/members",
|
|
301086
301454
|
method: "GET",
|
|
301087
301455
|
cmmdPath: "/api/organizations/:id/members",
|
|
301088
301456
|
orgIdSource: "none",
|
|
301089
301457
|
responseShape: "unwrapData"
|
|
301090
301458
|
});
|
|
301091
|
-
|
|
301459
|
+
registerProxyRoute({
|
|
301092
301460
|
forgePath: "/api/cmmd/sim-host/hosts",
|
|
301093
301461
|
method: "GET",
|
|
301094
301462
|
cmmdPath: "/api/forge/context/sim-host/hosts",
|
|
301095
301463
|
responseShape: "unwrapData"
|
|
301096
301464
|
});
|
|
301097
|
-
|
|
301465
|
+
registerProxyRoute({
|
|
301098
301466
|
forgePath: "/api/cmmd/sim-host/leases",
|
|
301099
301467
|
method: "GET",
|
|
301100
301468
|
cmmdPath: "/api/forge/context/sim-host/leases",
|
|
301101
301469
|
responseShape: "unwrapData"
|
|
301102
301470
|
});
|
|
301103
|
-
|
|
301471
|
+
registerProxyRoute({
|
|
301104
301472
|
forgePath: "/api/cmmd/sim-host/leases",
|
|
301105
301473
|
method: "POST",
|
|
301106
301474
|
cmmdPath: "/api/forge/context/sim-host/leases",
|
|
301107
301475
|
responseShape: "unwrapData",
|
|
301108
301476
|
successStatus: 200
|
|
301109
301477
|
});
|
|
301110
|
-
|
|
301478
|
+
registerProxyRoute({
|
|
301111
301479
|
forgePath: "/api/cmmd/sim-host/leases/:leaseId/release",
|
|
301112
301480
|
method: "POST",
|
|
301113
301481
|
cmmdPath: "/api/forge/context/sim-host/leases/:leaseId/release",
|
|
301114
301482
|
responseShape: "unwrapData",
|
|
301115
301483
|
successStatus: 200
|
|
301116
301484
|
});
|
|
301117
|
-
|
|
301485
|
+
registerProxyRoute({
|
|
301118
301486
|
forgePath: "/api/cmmd/sim-host/leases/:leaseId/renew",
|
|
301119
301487
|
method: "POST",
|
|
301120
301488
|
cmmdPath: "/api/forge/context/sim-host/leases/:leaseId/renew",
|
|
@@ -301138,7 +301506,7 @@ function getMultipartContentType(headers) {
|
|
|
301138
301506
|
const contentType = headers["content-type"] ?? "";
|
|
301139
301507
|
return contentType.includes("multipart/form-data") ? contentType : null;
|
|
301140
301508
|
}
|
|
301141
|
-
|
|
301509
|
+
registerProxyRoute({
|
|
301142
301510
|
forgePath: "/api/cmmd/tasks/:id/attachments",
|
|
301143
301511
|
method: "GET",
|
|
301144
301512
|
cmmdPath: "/api/forge/context/tasks/:id/attachments",
|
|
@@ -301173,150 +301541,150 @@ const cmmdUpdateTaskCommentRouteLayer = add$1("PATCH", "/api/cmmd/tasks/:taskId/
|
|
|
301173
301541
|
...outcome.value
|
|
301174
301542
|
}, { status: 200 });
|
|
301175
301543
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error))));
|
|
301176
|
-
|
|
301544
|
+
registerProxyRoute({
|
|
301177
301545
|
forgePath: "/api/cmmd/tasks/:taskId/comments/:commentId",
|
|
301178
301546
|
method: "DELETE",
|
|
301179
301547
|
cmmdPath: "/api/forge/context/tasks/:taskId/comments/:commentId",
|
|
301180
301548
|
orgIdSource: "none",
|
|
301181
301549
|
requestBody: "json"
|
|
301182
301550
|
});
|
|
301183
|
-
|
|
301551
|
+
registerProxyRoute({
|
|
301184
301552
|
forgePath: "/api/cmmd/projects/:projectId/agent-members",
|
|
301185
301553
|
method: "GET",
|
|
301186
301554
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members",
|
|
301187
301555
|
orgIdSource: "none",
|
|
301188
301556
|
responseShape: "unwrapData"
|
|
301189
301557
|
});
|
|
301190
|
-
|
|
301558
|
+
registerProxyRoute({
|
|
301191
301559
|
forgePath: "/api/cmmd/projects/:projectId/agent-members",
|
|
301192
301560
|
method: "POST",
|
|
301193
301561
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members",
|
|
301194
301562
|
orgIdSource: "none",
|
|
301195
301563
|
responseShape: "unwrapData"
|
|
301196
301564
|
});
|
|
301197
|
-
|
|
301565
|
+
registerProxyRoute({
|
|
301198
301566
|
forgePath: "/api/cmmd/projects/:projectId/agent-members/:memberId",
|
|
301199
301567
|
method: "GET",
|
|
301200
301568
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members/:memberId",
|
|
301201
301569
|
orgIdSource: "none",
|
|
301202
301570
|
responseShape: "unwrapData"
|
|
301203
301571
|
});
|
|
301204
|
-
|
|
301572
|
+
registerProxyRoute({
|
|
301205
301573
|
forgePath: "/api/cmmd/projects/:projectId/agent-members/:memberId",
|
|
301206
301574
|
method: "PATCH",
|
|
301207
301575
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members/:memberId",
|
|
301208
301576
|
orgIdSource: "none",
|
|
301209
301577
|
responseShape: "unwrapData"
|
|
301210
301578
|
});
|
|
301211
|
-
|
|
301579
|
+
registerProxyRoute({
|
|
301212
301580
|
forgePath: "/api/cmmd/projects/:projectId/agent-members/:memberId/retire",
|
|
301213
301581
|
method: "POST",
|
|
301214
301582
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members/:memberId/retire",
|
|
301215
301583
|
orgIdSource: "none",
|
|
301216
301584
|
responseShape: "unwrapData"
|
|
301217
301585
|
});
|
|
301218
|
-
|
|
301586
|
+
registerProxyRoute({
|
|
301219
301587
|
forgePath: "/api/cmmd/projects/:projectId/agent-members/:memberId/instances",
|
|
301220
301588
|
method: "GET",
|
|
301221
301589
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members/:memberId/instances",
|
|
301222
301590
|
orgIdSource: "none",
|
|
301223
301591
|
responseShape: "unwrapData"
|
|
301224
301592
|
});
|
|
301225
|
-
|
|
301593
|
+
registerProxyRoute({
|
|
301226
301594
|
forgePath: "/api/cmmd/projects/:projectId/agent-members/consolidation/preview",
|
|
301227
301595
|
method: "POST",
|
|
301228
301596
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members/consolidation/preview",
|
|
301229
301597
|
orgIdSource: "none",
|
|
301230
301598
|
responseShape: "unwrapData"
|
|
301231
301599
|
});
|
|
301232
|
-
|
|
301600
|
+
registerProxyRoute({
|
|
301233
301601
|
forgePath: "/api/cmmd/projects/:projectId/agent-members/consolidation/apply",
|
|
301234
301602
|
method: "POST",
|
|
301235
301603
|
cmmdPath: "/api/forge/context/projects/:projectId/agent-members/consolidation/apply",
|
|
301236
301604
|
orgIdSource: "none",
|
|
301237
301605
|
responseShape: "unwrapData"
|
|
301238
301606
|
});
|
|
301239
|
-
|
|
301607
|
+
registerProxyRoute({
|
|
301240
301608
|
forgePath: "/api/cmmd/projects/:projectId/tasks/:taskId/assignment",
|
|
301241
301609
|
method: "PUT",
|
|
301242
301610
|
cmmdPath: "/api/forge/context/projects/:projectId/tasks/:taskId/assignment",
|
|
301243
301611
|
orgIdSource: "none",
|
|
301244
301612
|
responseShape: "unwrapData"
|
|
301245
301613
|
});
|
|
301246
|
-
|
|
301614
|
+
registerProxyRoute({
|
|
301247
301615
|
forgePath: "/api/cmmd/tasks",
|
|
301248
301616
|
method: "GET",
|
|
301249
301617
|
cmmdPath: "/api/forge/context/tasks"
|
|
301250
301618
|
});
|
|
301251
|
-
|
|
301619
|
+
registerProxyRoute({
|
|
301252
301620
|
forgePath: "/api/cmmd/tasks",
|
|
301253
301621
|
method: "POST",
|
|
301254
301622
|
cmmdPath: "/api/forge/context/tasks"
|
|
301255
301623
|
});
|
|
301256
|
-
|
|
301624
|
+
registerProxyRoute({
|
|
301257
301625
|
forgePath: "/api/cmmd/tasks/:id/archive",
|
|
301258
301626
|
method: "POST",
|
|
301259
301627
|
cmmdPath: "/api/forge/context/tasks/:id/archive",
|
|
301260
301628
|
orgIdSource: "none"
|
|
301261
301629
|
});
|
|
301262
|
-
|
|
301630
|
+
registerProxyRoute({
|
|
301263
301631
|
forgePath: "/api/cmmd/tasks/:id/unarchive",
|
|
301264
301632
|
method: "POST",
|
|
301265
301633
|
cmmdPath: "/api/forge/context/tasks/:id/unarchive",
|
|
301266
301634
|
orgIdSource: "none"
|
|
301267
301635
|
});
|
|
301268
|
-
|
|
301636
|
+
registerProxyRoute({
|
|
301269
301637
|
forgePath: "/api/cmmd/saved-views",
|
|
301270
301638
|
method: "GET",
|
|
301271
301639
|
cmmdPath: "/api/forge/context/saved-views",
|
|
301272
301640
|
orgIdSource: "none"
|
|
301273
301641
|
});
|
|
301274
|
-
|
|
301642
|
+
registerProxyRoute({
|
|
301275
301643
|
forgePath: "/api/cmmd/saved-views",
|
|
301276
301644
|
method: "POST",
|
|
301277
301645
|
cmmdPath: "/api/forge/context/saved-views",
|
|
301278
301646
|
orgIdSource: "none",
|
|
301279
301647
|
successStatus: 201
|
|
301280
301648
|
});
|
|
301281
|
-
|
|
301649
|
+
registerProxyRoute({
|
|
301282
301650
|
forgePath: "/api/cmmd/saved-views/import",
|
|
301283
301651
|
method: "POST",
|
|
301284
301652
|
cmmdPath: "/api/forge/context/saved-views/import",
|
|
301285
301653
|
orgIdSource: "none"
|
|
301286
301654
|
});
|
|
301287
|
-
|
|
301655
|
+
registerProxyRoute({
|
|
301288
301656
|
forgePath: "/api/cmmd/saved-views/:viewId",
|
|
301289
301657
|
method: "PATCH",
|
|
301290
301658
|
cmmdPath: "/api/forge/context/saved-views/:viewId",
|
|
301291
301659
|
orgIdSource: "none"
|
|
301292
301660
|
});
|
|
301293
|
-
|
|
301661
|
+
registerProxyRoute({
|
|
301294
301662
|
forgePath: "/api/cmmd/saved-views/:viewId",
|
|
301295
301663
|
method: "DELETE",
|
|
301296
301664
|
cmmdPath: "/api/forge/context/saved-views/:viewId",
|
|
301297
301665
|
orgIdSource: "none",
|
|
301298
301666
|
forwardSearchParams: true
|
|
301299
301667
|
});
|
|
301300
|
-
|
|
301668
|
+
registerProxyRoute({
|
|
301301
301669
|
forgePath: "/api/cmmd/projects",
|
|
301302
301670
|
method: "GET",
|
|
301303
301671
|
cmmdPath: "/api/forge/context/projects",
|
|
301304
301672
|
responseShape: "passthrough"
|
|
301305
301673
|
});
|
|
301306
|
-
|
|
301674
|
+
registerProxyRoute({
|
|
301307
301675
|
forgePath: "/api/cmmd/projects/:id",
|
|
301308
301676
|
method: "GET",
|
|
301309
301677
|
cmmdPath: "/api/forge/context/projects/:id",
|
|
301310
301678
|
orgIdSource: "none",
|
|
301311
301679
|
responseShape: "passthrough"
|
|
301312
301680
|
});
|
|
301313
|
-
|
|
301681
|
+
registerProxyRoute({
|
|
301314
301682
|
forgePath: "/api/cmmd/projects",
|
|
301315
301683
|
method: "POST",
|
|
301316
301684
|
cmmdPath: "/api/projects",
|
|
301317
301685
|
responseShape: "passthrough"
|
|
301318
301686
|
});
|
|
301319
|
-
|
|
301687
|
+
registerProxyRoute({
|
|
301320
301688
|
forgePath: "/api/cmmd/projects/:id",
|
|
301321
301689
|
method: "DELETE",
|
|
301322
301690
|
cmmdPath: "/api/forge/context/projects/:id",
|
|
@@ -301324,78 +301692,78 @@ const cmmdDeleteProjectRouteLayer = registerProxyRoute({
|
|
|
301324
301692
|
fixedSearchParams: { soft: "false" },
|
|
301325
301693
|
workIntakeInvalidation: "always"
|
|
301326
301694
|
});
|
|
301327
|
-
|
|
301695
|
+
registerProxyRoute({
|
|
301328
301696
|
forgePath: "/api/cmmd/projects/:id/move",
|
|
301329
301697
|
method: "POST",
|
|
301330
301698
|
cmmdPath: "/api/forge/context/projects/:id/move",
|
|
301331
301699
|
orgIdSource: "none",
|
|
301332
301700
|
responseShape: "unwrapData"
|
|
301333
301701
|
});
|
|
301334
|
-
|
|
301702
|
+
registerProxyRoute({
|
|
301335
301703
|
forgePath: "/api/cmmd/projects/:id/members",
|
|
301336
301704
|
method: "GET",
|
|
301337
301705
|
cmmdPath: "/api/forge/context/projects/:id/team"
|
|
301338
301706
|
});
|
|
301339
|
-
|
|
301707
|
+
registerProxyRoute({
|
|
301340
301708
|
forgePath: "/api/cmmd/projects/:id/milestones",
|
|
301341
301709
|
method: "GET",
|
|
301342
301710
|
cmmdPath: "/api/forge/context/projects/:id/milestones"
|
|
301343
301711
|
});
|
|
301344
|
-
|
|
301712
|
+
registerProxyRoute({
|
|
301345
301713
|
forgePath: "/api/cmmd/projects/:id/milestones",
|
|
301346
301714
|
method: "POST",
|
|
301347
301715
|
cmmdPath: "/api/forge/context/projects/:id/milestones",
|
|
301348
301716
|
orgIdSource: "none",
|
|
301349
301717
|
responseShape: "unwrapData"
|
|
301350
301718
|
});
|
|
301351
|
-
|
|
301719
|
+
registerProxyRoute({
|
|
301352
301720
|
forgePath: "/api/cmmd/projects/:id/milestones/:milestoneId",
|
|
301353
301721
|
method: "PATCH",
|
|
301354
301722
|
cmmdPath: "/api/forge/context/projects/:id/milestones/:milestoneId",
|
|
301355
301723
|
orgIdSource: "none",
|
|
301356
301724
|
responseShape: "unwrapData"
|
|
301357
301725
|
});
|
|
301358
|
-
|
|
301726
|
+
registerProxyRoute({
|
|
301359
301727
|
forgePath: "/api/cmmd/projects/:id/milestones/:milestoneId",
|
|
301360
301728
|
method: "DELETE",
|
|
301361
301729
|
cmmdPath: "/api/forge/context/projects/:id/milestones/:milestoneId",
|
|
301362
301730
|
orgIdSource: "none"
|
|
301363
301731
|
});
|
|
301364
|
-
|
|
301732
|
+
registerProxyRoute({
|
|
301365
301733
|
forgePath: "/api/cmmd/projects/:id/updates",
|
|
301366
301734
|
method: "GET",
|
|
301367
301735
|
cmmdPath: "/api/forge/context/projects/:id/updates",
|
|
301368
301736
|
orgIdSource: "none",
|
|
301369
301737
|
responseShape: "passthrough"
|
|
301370
301738
|
});
|
|
301371
|
-
|
|
301739
|
+
registerProxyRoute({
|
|
301372
301740
|
forgePath: "/api/cmmd/projects/:id/updates",
|
|
301373
301741
|
method: "POST",
|
|
301374
301742
|
cmmdPath: "/api/forge/context/projects/:id/updates",
|
|
301375
301743
|
orgIdSource: "none",
|
|
301376
301744
|
responseShape: "unwrapData"
|
|
301377
301745
|
});
|
|
301378
|
-
|
|
301746
|
+
registerProxyRoute({
|
|
301379
301747
|
forgePath: "/api/cmmd/projects/:id/updates/:updateId",
|
|
301380
301748
|
method: "PATCH",
|
|
301381
301749
|
cmmdPath: "/api/forge/context/projects/:id/updates/:updateId",
|
|
301382
301750
|
orgIdSource: "none",
|
|
301383
301751
|
responseShape: "unwrapData"
|
|
301384
301752
|
});
|
|
301385
|
-
|
|
301753
|
+
registerProxyRoute({
|
|
301386
301754
|
forgePath: "/api/cmmd/projects/:id/updates/:updateId",
|
|
301387
301755
|
method: "DELETE",
|
|
301388
301756
|
cmmdPath: "/api/forge/context/projects/:id/updates/:updateId",
|
|
301389
301757
|
orgIdSource: "none"
|
|
301390
301758
|
});
|
|
301391
|
-
|
|
301759
|
+
registerProxyRoute({
|
|
301392
301760
|
forgePath: "/api/cmmd/projects/:id/content/readability",
|
|
301393
301761
|
method: "POST",
|
|
301394
301762
|
cmmdPath: "/api/forge/context/projects/:id/content/readability",
|
|
301395
301763
|
orgIdSource: "none",
|
|
301396
301764
|
responseShape: "unwrapData"
|
|
301397
301765
|
});
|
|
301398
|
-
|
|
301766
|
+
registerProxyRoute({
|
|
301399
301767
|
forgePath: "/api/cmmd/projects/:projectId/task-drafts",
|
|
301400
301768
|
method: "POST",
|
|
301401
301769
|
cmmdPath: "/api/forge/context/projects/:projectId/task-drafts",
|
|
@@ -301403,7 +301771,7 @@ const cmmdCreateProjectTaskDraftRouteLayer = registerProxyRoute({
|
|
|
301403
301771
|
responseShape: "unwrapData",
|
|
301404
301772
|
successStatus: 201
|
|
301405
301773
|
});
|
|
301406
|
-
|
|
301774
|
+
registerProxyRoute({
|
|
301407
301775
|
forgePath: "/api/cmmd/projects/:projectId/task-drafts/:draftId",
|
|
301408
301776
|
method: "GET",
|
|
301409
301777
|
cmmdPath: "/api/forge/context/projects/:projectId/task-drafts/:draftId",
|
|
@@ -301411,7 +301779,7 @@ const cmmdGetProjectTaskDraftRouteLayer = registerProxyRoute({
|
|
|
301411
301779
|
responseShape: "unwrapData",
|
|
301412
301780
|
successStatus: 200
|
|
301413
301781
|
});
|
|
301414
|
-
|
|
301782
|
+
registerProxyRoute({
|
|
301415
301783
|
forgePath: "/api/cmmd/projects/:projectId/task-drafts/:draftId",
|
|
301416
301784
|
method: "PATCH",
|
|
301417
301785
|
cmmdPath: "/api/forge/context/projects/:projectId/task-drafts/:draftId",
|
|
@@ -301419,7 +301787,7 @@ const cmmdUpdateProjectTaskDraftRouteLayer = registerProxyRoute({
|
|
|
301419
301787
|
responseShape: "unwrapData",
|
|
301420
301788
|
successStatus: 200
|
|
301421
301789
|
});
|
|
301422
|
-
|
|
301790
|
+
registerProxyRoute({
|
|
301423
301791
|
forgePath: "/api/cmmd/projects/:projectId/task-drafts/:draftId/preview",
|
|
301424
301792
|
method: "POST",
|
|
301425
301793
|
cmmdPath: "/api/forge/context/projects/:projectId/task-drafts/:draftId/preview",
|
|
@@ -301427,7 +301795,7 @@ const cmmdPreviewProjectTaskDraftRouteLayer = registerProxyRoute({
|
|
|
301427
301795
|
responseShape: "unwrapData",
|
|
301428
301796
|
successStatus: 200
|
|
301429
301797
|
});
|
|
301430
|
-
|
|
301798
|
+
registerProxyRoute({
|
|
301431
301799
|
forgePath: "/api/cmmd/projects/:projectId/task-drafts/:draftId/commit",
|
|
301432
301800
|
method: "POST",
|
|
301433
301801
|
cmmdPath: "/api/forge/context/projects/:projectId/task-drafts/:draftId/commit",
|
|
@@ -301435,7 +301803,7 @@ const cmmdCommitProjectTaskDraftRouteLayer = registerProxyRoute({
|
|
|
301435
301803
|
responseShape: "unwrapData",
|
|
301436
301804
|
successStatus: 200
|
|
301437
301805
|
});
|
|
301438
|
-
|
|
301806
|
+
registerProxyRoute({
|
|
301439
301807
|
forgePath: "/api/cmmd/projects/:projectId/task-drafts/:draftId/discard",
|
|
301440
301808
|
method: "POST",
|
|
301441
301809
|
cmmdPath: "/api/forge/context/projects/:projectId/task-drafts/:draftId/discard",
|
|
@@ -301443,352 +301811,352 @@ const cmmdDiscardProjectTaskDraftRouteLayer = registerProxyRoute({
|
|
|
301443
301811
|
responseShape: "unwrapData",
|
|
301444
301812
|
successStatus: 200
|
|
301445
301813
|
});
|
|
301446
|
-
|
|
301814
|
+
registerProxyRoute({
|
|
301447
301815
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/plan",
|
|
301448
301816
|
method: "GET",
|
|
301449
301817
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/plan",
|
|
301450
301818
|
orgIdSource: "none"
|
|
301451
301819
|
});
|
|
301452
|
-
|
|
301820
|
+
registerProxyRoute({
|
|
301453
301821
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/authority/activate",
|
|
301454
301822
|
method: "POST",
|
|
301455
301823
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/authority/activate",
|
|
301456
301824
|
orgIdSource: "none",
|
|
301457
301825
|
responseShape: "unwrapData"
|
|
301458
301826
|
});
|
|
301459
|
-
|
|
301827
|
+
registerProxyRoute({
|
|
301460
301828
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/readiness",
|
|
301461
301829
|
method: "GET",
|
|
301462
301830
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/readiness",
|
|
301463
301831
|
orgIdSource: "none"
|
|
301464
301832
|
});
|
|
301465
|
-
|
|
301833
|
+
registerProxyRoute({
|
|
301466
301834
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/capabilities",
|
|
301467
301835
|
method: "GET",
|
|
301468
301836
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/capabilities",
|
|
301469
301837
|
orgIdSource: "none"
|
|
301470
301838
|
});
|
|
301471
|
-
|
|
301839
|
+
registerProxyRoute({
|
|
301472
301840
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/summary",
|
|
301473
301841
|
method: "GET",
|
|
301474
301842
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/summary",
|
|
301475
301843
|
orgIdSource: "none"
|
|
301476
301844
|
});
|
|
301477
|
-
|
|
301845
|
+
registerProxyRoute({
|
|
301478
301846
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/detail",
|
|
301479
301847
|
method: "GET",
|
|
301480
301848
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/detail",
|
|
301481
301849
|
orgIdSource: "none"
|
|
301482
301850
|
});
|
|
301483
|
-
|
|
301851
|
+
registerProxyRoute({
|
|
301484
301852
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/briefing",
|
|
301485
301853
|
method: "GET",
|
|
301486
301854
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/briefing",
|
|
301487
301855
|
orgIdSource: "none"
|
|
301488
301856
|
});
|
|
301489
|
-
|
|
301857
|
+
registerProxyRoute({
|
|
301490
301858
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/events",
|
|
301491
301859
|
method: "GET",
|
|
301492
301860
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/events",
|
|
301493
301861
|
orgIdSource: "none"
|
|
301494
301862
|
});
|
|
301495
|
-
|
|
301863
|
+
registerProxyRoute({
|
|
301496
301864
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/explain",
|
|
301497
301865
|
method: "GET",
|
|
301498
301866
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/explain",
|
|
301499
301867
|
orgIdSource: "none"
|
|
301500
301868
|
});
|
|
301501
|
-
|
|
301869
|
+
registerProxyRoute({
|
|
301502
301870
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/pause",
|
|
301503
301871
|
method: "POST",
|
|
301504
301872
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/pause",
|
|
301505
301873
|
orgIdSource: "none"
|
|
301506
301874
|
});
|
|
301507
|
-
|
|
301875
|
+
registerProxyRoute({
|
|
301508
301876
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/resume",
|
|
301509
301877
|
method: "POST",
|
|
301510
301878
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/resume",
|
|
301511
301879
|
orgIdSource: "none"
|
|
301512
301880
|
});
|
|
301513
|
-
|
|
301881
|
+
registerProxyRoute({
|
|
301514
301882
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/tasks/:taskId/reservations",
|
|
301515
301883
|
method: "POST",
|
|
301516
301884
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/tasks/:taskId/reservations",
|
|
301517
301885
|
orgIdSource: "none"
|
|
301518
301886
|
});
|
|
301519
|
-
|
|
301887
|
+
registerProxyRoute({
|
|
301520
301888
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/reservations/:reservationId/release",
|
|
301521
301889
|
method: "POST",
|
|
301522
301890
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/reservations/:reservationId/release",
|
|
301523
301891
|
orgIdSource: "none"
|
|
301524
301892
|
});
|
|
301525
|
-
|
|
301893
|
+
registerProxyRoute({
|
|
301526
301894
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/reconcile",
|
|
301527
301895
|
method: "POST",
|
|
301528
301896
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/reconcile",
|
|
301529
301897
|
orgIdSource: "none"
|
|
301530
301898
|
});
|
|
301531
|
-
|
|
301899
|
+
registerProxyRoute({
|
|
301532
301900
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/attention/:attentionId/resolve",
|
|
301533
301901
|
method: "POST",
|
|
301534
301902
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/attention/:attentionId/resolve",
|
|
301535
301903
|
orgIdSource: "none"
|
|
301536
301904
|
});
|
|
301537
|
-
|
|
301905
|
+
registerProxyRoute({
|
|
301538
301906
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/controller/claim",
|
|
301539
301907
|
method: "POST",
|
|
301540
301908
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/controller/claim",
|
|
301541
301909
|
orgIdSource: "none"
|
|
301542
301910
|
});
|
|
301543
|
-
|
|
301911
|
+
registerProxyRoute({
|
|
301544
301912
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/controller/claim/renew",
|
|
301545
301913
|
method: "POST",
|
|
301546
301914
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/controller/claim/renew",
|
|
301547
301915
|
orgIdSource: "none"
|
|
301548
301916
|
});
|
|
301549
|
-
|
|
301917
|
+
registerProxyRoute({
|
|
301550
301918
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/controller/claim/yield",
|
|
301551
301919
|
method: "POST",
|
|
301552
301920
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/controller/claim/yield",
|
|
301553
301921
|
orgIdSource: "none"
|
|
301554
301922
|
});
|
|
301555
|
-
|
|
301923
|
+
registerProxyRoute({
|
|
301556
301924
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/controller/events/:eventId/acknowledge",
|
|
301557
301925
|
method: "POST",
|
|
301558
301926
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/controller/events/:eventId/acknowledge",
|
|
301559
301927
|
orgIdSource: "none"
|
|
301560
301928
|
});
|
|
301561
|
-
|
|
301929
|
+
registerProxyRoute({
|
|
301562
301930
|
forgePath: "/api/cmmd/projects/:projectId/project-lead/controller/decisions",
|
|
301563
301931
|
method: "POST",
|
|
301564
301932
|
cmmdPath: "/api/forge/context/projects/:projectId/project-lead/controller/decisions",
|
|
301565
301933
|
orgIdSource: "none"
|
|
301566
301934
|
});
|
|
301567
|
-
|
|
301935
|
+
registerProxyRoute({
|
|
301568
301936
|
forgePath: "/api/cmmd/automations/presets",
|
|
301569
301937
|
method: "GET",
|
|
301570
301938
|
cmmdPath: "/api/forge/context/automations/presets",
|
|
301571
301939
|
orgIdSource: "none",
|
|
301572
301940
|
responseShape: "unwrapData"
|
|
301573
301941
|
});
|
|
301574
|
-
|
|
301942
|
+
registerProxyRoute({
|
|
301575
301943
|
forgePath: "/api/cmmd/automations/user/rules",
|
|
301576
301944
|
method: "GET",
|
|
301577
301945
|
cmmdPath: "/api/forge/context/automations/user/rules",
|
|
301578
301946
|
orgIdSource: "none",
|
|
301579
301947
|
responseShape: "unwrapData"
|
|
301580
301948
|
});
|
|
301581
|
-
|
|
301949
|
+
registerProxyRoute({
|
|
301582
301950
|
forgePath: "/api/cmmd/automations/user/rules",
|
|
301583
301951
|
method: "POST",
|
|
301584
301952
|
cmmdPath: "/api/forge/context/automations/user/rules",
|
|
301585
301953
|
orgIdSource: "none",
|
|
301586
301954
|
responseShape: "unwrapData"
|
|
301587
301955
|
});
|
|
301588
|
-
|
|
301956
|
+
registerProxyRoute({
|
|
301589
301957
|
forgePath: "/api/cmmd/automations/user/rules/:ruleId",
|
|
301590
301958
|
method: "PATCH",
|
|
301591
301959
|
cmmdPath: "/api/forge/context/automations/user/rules/:ruleId",
|
|
301592
301960
|
orgIdSource: "none",
|
|
301593
301961
|
responseShape: "unwrapData"
|
|
301594
301962
|
});
|
|
301595
|
-
|
|
301963
|
+
registerProxyRoute({
|
|
301596
301964
|
forgePath: "/api/cmmd/automations/user/rules/:ruleId/runs",
|
|
301597
301965
|
method: "GET",
|
|
301598
301966
|
cmmdPath: "/api/forge/context/automations/user/rules/:ruleId/runs",
|
|
301599
301967
|
orgIdSource: "none",
|
|
301600
301968
|
responseShape: "unwrapData"
|
|
301601
301969
|
});
|
|
301602
|
-
|
|
301970
|
+
registerProxyRoute({
|
|
301603
301971
|
forgePath: "/api/cmmd/automations/user/rules/:ruleId/runs",
|
|
301604
301972
|
method: "POST",
|
|
301605
301973
|
cmmdPath: "/api/forge/context/automations/user/rules/:ruleId/runs",
|
|
301606
301974
|
orgIdSource: "none",
|
|
301607
301975
|
responseShape: "unwrapData"
|
|
301608
301976
|
});
|
|
301609
|
-
|
|
301977
|
+
registerProxyRoute({
|
|
301610
301978
|
forgePath: "/api/cmmd/automations/projects/:projectId/rules",
|
|
301611
301979
|
method: "GET",
|
|
301612
301980
|
cmmdPath: "/api/forge/context/automations/projects/:projectId/rules",
|
|
301613
301981
|
orgIdSource: "query",
|
|
301614
301982
|
responseShape: "unwrapData"
|
|
301615
301983
|
});
|
|
301616
|
-
|
|
301984
|
+
registerProxyRoute({
|
|
301617
301985
|
forgePath: "/api/cmmd/automations/projects/:projectId/rules",
|
|
301618
301986
|
method: "POST",
|
|
301619
301987
|
cmmdPath: "/api/forge/context/automations/projects/:projectId/rules",
|
|
301620
301988
|
orgIdSource: "query",
|
|
301621
301989
|
responseShape: "unwrapData"
|
|
301622
301990
|
});
|
|
301623
|
-
|
|
301991
|
+
registerProxyRoute({
|
|
301624
301992
|
forgePath: "/api/cmmd/automations/projects/:projectId/rules/:ruleId",
|
|
301625
301993
|
method: "PATCH",
|
|
301626
301994
|
cmmdPath: "/api/forge/context/automations/projects/:projectId/rules/:ruleId",
|
|
301627
301995
|
orgIdSource: "query",
|
|
301628
301996
|
responseShape: "unwrapData"
|
|
301629
301997
|
});
|
|
301630
|
-
|
|
301998
|
+
registerProxyRoute({
|
|
301631
301999
|
forgePath: "/api/cmmd/automations/projects/:projectId/runs",
|
|
301632
302000
|
method: "GET",
|
|
301633
302001
|
cmmdPath: "/api/forge/context/automations/projects/:projectId/runs",
|
|
301634
302002
|
orgIdSource: "query",
|
|
301635
302003
|
responseShape: "unwrapData"
|
|
301636
302004
|
});
|
|
301637
|
-
|
|
302005
|
+
registerProxyRoute({
|
|
301638
302006
|
forgePath: "/api/cmmd/automations/projects/:projectId/tasks/:taskId/runs",
|
|
301639
302007
|
method: "POST",
|
|
301640
302008
|
cmmdPath: "/api/forge/context/automations/projects/:projectId/tasks/:taskId/runs",
|
|
301641
302009
|
orgIdSource: "query",
|
|
301642
302010
|
responseShape: "unwrapData"
|
|
301643
302011
|
});
|
|
301644
|
-
|
|
302012
|
+
registerProxyRoute({
|
|
301645
302013
|
forgePath: "/api/cmmd/automations/runs/:runId",
|
|
301646
302014
|
method: "GET",
|
|
301647
302015
|
cmmdPath: "/api/forge/context/automations/runs/:runId",
|
|
301648
302016
|
orgIdSource: "query",
|
|
301649
302017
|
responseShape: "unwrapData"
|
|
301650
302018
|
});
|
|
301651
|
-
|
|
302019
|
+
registerProxyRoute({
|
|
301652
302020
|
forgePath: "/api/cmmd/automations/runs/:runId/retry",
|
|
301653
302021
|
method: "POST",
|
|
301654
302022
|
cmmdPath: "/api/forge/context/automations/runs/:runId/retry",
|
|
301655
302023
|
orgIdSource: "query",
|
|
301656
302024
|
responseShape: "unwrapData"
|
|
301657
302025
|
});
|
|
301658
|
-
|
|
302026
|
+
registerProxyRoute({
|
|
301659
302027
|
forgePath: "/api/cmmd/automations/runs/:runId/cancel",
|
|
301660
302028
|
method: "POST",
|
|
301661
302029
|
cmmdPath: "/api/forge/context/automations/runs/:runId/cancel",
|
|
301662
302030
|
orgIdSource: "query",
|
|
301663
302031
|
responseShape: "unwrapData"
|
|
301664
302032
|
});
|
|
301665
|
-
|
|
302033
|
+
registerProxyRoute({
|
|
301666
302034
|
forgePath: "/api/cmmd/automations/runs/:runId/escalations/approve",
|
|
301667
302035
|
method: "POST",
|
|
301668
302036
|
cmmdPath: "/api/forge/context/automations/runs/:runId/escalations/approve",
|
|
301669
302037
|
orgIdSource: "query",
|
|
301670
302038
|
responseShape: "unwrapData"
|
|
301671
302039
|
});
|
|
301672
|
-
|
|
302040
|
+
registerProxyRoute({
|
|
301673
302041
|
forgePath: "/api/cmmd/automations/runs/:runId/escalations/reject",
|
|
301674
302042
|
method: "POST",
|
|
301675
302043
|
cmmdPath: "/api/forge/context/automations/runs/:runId/escalations/reject",
|
|
301676
302044
|
orgIdSource: "query",
|
|
301677
302045
|
responseShape: "unwrapData"
|
|
301678
302046
|
});
|
|
301679
|
-
|
|
302047
|
+
registerProxyRoute({
|
|
301680
302048
|
forgePath: "/api/cmmd/projects/:id/board",
|
|
301681
302049
|
method: "GET",
|
|
301682
302050
|
cmmdPath: "/api/forge/context/projects/:id/board",
|
|
301683
302051
|
orgIdSource: "none",
|
|
301684
302052
|
responseShape: "unwrapData"
|
|
301685
302053
|
});
|
|
301686
|
-
|
|
302054
|
+
registerProxyRoute({
|
|
301687
302055
|
forgePath: "/api/cmmd/projects/:id/task-workflow",
|
|
301688
302056
|
method: "GET",
|
|
301689
302057
|
cmmdPath: "/api/forge/context/projects/:id/task-workflow",
|
|
301690
302058
|
orgIdSource: "none",
|
|
301691
302059
|
responseShape: "unwrapData"
|
|
301692
302060
|
});
|
|
301693
|
-
|
|
302061
|
+
registerProxyRoute({
|
|
301694
302062
|
forgePath: "/api/cmmd/projects/:id/task-workflow",
|
|
301695
302063
|
method: "PUT",
|
|
301696
302064
|
cmmdPath: "/api/forge/context/projects/:id/task-workflow",
|
|
301697
302065
|
orgIdSource: "none",
|
|
301698
302066
|
responseShape: "unwrapData"
|
|
301699
302067
|
});
|
|
301700
|
-
|
|
302068
|
+
registerProxyRoute({
|
|
301701
302069
|
forgePath: "/api/cmmd/projects/:id/board",
|
|
301702
302070
|
method: "POST",
|
|
301703
302071
|
cmmdPath: "/api/forge/context/projects/:id/board",
|
|
301704
302072
|
orgIdSource: "none",
|
|
301705
302073
|
responseShape: "unwrapData"
|
|
301706
302074
|
});
|
|
301707
|
-
|
|
302075
|
+
registerProxyRoute({
|
|
301708
302076
|
forgePath: "/api/cmmd/projects/:id/board/:taskId",
|
|
301709
302077
|
method: "PATCH",
|
|
301710
302078
|
cmmdPath: "/api/forge/context/projects/:id/board/:taskId",
|
|
301711
302079
|
orgIdSource: "none",
|
|
301712
302080
|
responseShape: "unwrapData"
|
|
301713
302081
|
});
|
|
301714
|
-
|
|
302082
|
+
registerProxyRoute({
|
|
301715
302083
|
forgePath: "/api/cmmd/projects/:id/board/:taskId/status",
|
|
301716
302084
|
method: "PATCH",
|
|
301717
302085
|
cmmdPath: "/api/forge/context/projects/:id/board/:taskId/status",
|
|
301718
302086
|
orgIdSource: "none",
|
|
301719
302087
|
responseShape: "unwrapData"
|
|
301720
302088
|
});
|
|
301721
|
-
|
|
302089
|
+
registerProxyRoute({
|
|
301722
302090
|
forgePath: "/api/cmmd/projects/:id/board/:taskId/execution-options",
|
|
301723
302091
|
method: "GET",
|
|
301724
302092
|
cmmdPath: "/api/forge/context/projects/:id/board/:taskId/execution-options",
|
|
301725
302093
|
orgIdSource: "none",
|
|
301726
302094
|
responseShape: "unwrapData"
|
|
301727
302095
|
});
|
|
301728
|
-
|
|
302096
|
+
registerProxyRoute({
|
|
301729
302097
|
forgePath: "/api/cmmd/projects/:id/board/:taskId/work-sessions",
|
|
301730
302098
|
method: "POST",
|
|
301731
302099
|
cmmdPath: "/api/forge/context/projects/:id/board/:taskId/work-sessions",
|
|
301732
302100
|
orgIdSource: "none",
|
|
301733
302101
|
responseShape: "unwrapData"
|
|
301734
302102
|
});
|
|
301735
|
-
|
|
302103
|
+
registerProxyRoute({
|
|
301736
302104
|
forgePath: "/api/cmmd/projects/:id/work-sessions",
|
|
301737
302105
|
method: "GET",
|
|
301738
302106
|
cmmdPath: "/api/forge/context/projects/:id/work-sessions",
|
|
301739
302107
|
orgIdSource: "none",
|
|
301740
302108
|
responseShape: "unwrapData"
|
|
301741
302109
|
});
|
|
301742
|
-
|
|
302110
|
+
registerProxyRoute({
|
|
301743
302111
|
forgePath: "/api/cmmd/work-sessions/:workSessionId",
|
|
301744
302112
|
method: "GET",
|
|
301745
302113
|
cmmdPath: "/api/forge/context/work-sessions/:workSessionId",
|
|
301746
302114
|
orgIdSource: "none",
|
|
301747
302115
|
responseShape: "unwrapData"
|
|
301748
302116
|
});
|
|
301749
|
-
|
|
302117
|
+
registerProxyRoute({
|
|
301750
302118
|
forgePath: "/api/cmmd/work-sessions/:workSessionId",
|
|
301751
302119
|
method: "PATCH",
|
|
301752
302120
|
cmmdPath: "/api/forge/context/work-sessions/:workSessionId",
|
|
301753
302121
|
orgIdSource: "none",
|
|
301754
302122
|
responseShape: "unwrapData"
|
|
301755
302123
|
});
|
|
301756
|
-
|
|
302124
|
+
registerProxyRoute({
|
|
301757
302125
|
forgePath: "/api/cmmd/work-sessions/:workSessionId/threads",
|
|
301758
302126
|
method: "POST",
|
|
301759
302127
|
cmmdPath: "/api/forge/context/work-sessions/:workSessionId/threads",
|
|
301760
302128
|
orgIdSource: "none",
|
|
301761
302129
|
responseShape: "unwrapData"
|
|
301762
302130
|
});
|
|
301763
|
-
|
|
302131
|
+
registerProxyRoute({
|
|
301764
302132
|
forgePath: "/api/cmmd/tasks/:taskId/conversations",
|
|
301765
302133
|
method: "GET",
|
|
301766
302134
|
cmmdPath: "/api/forge/context/tasks/:taskId/conversations",
|
|
301767
302135
|
orgIdSource: "none",
|
|
301768
302136
|
responseShape: "unwrapData"
|
|
301769
302137
|
});
|
|
301770
|
-
|
|
302138
|
+
registerProxyRoute({
|
|
301771
302139
|
forgePath: "/api/cmmd/tasks/:taskId/conversations",
|
|
301772
302140
|
method: "POST",
|
|
301773
302141
|
cmmdPath: "/api/forge/context/tasks/:taskId/conversations",
|
|
301774
302142
|
orgIdSource: "none",
|
|
301775
302143
|
responseShape: "unwrapData"
|
|
301776
302144
|
});
|
|
301777
|
-
|
|
302145
|
+
registerProxyRoute({
|
|
301778
302146
|
forgePath: "/api/cmmd/tasks/:taskId/history",
|
|
301779
302147
|
method: "GET",
|
|
301780
302148
|
cmmdPath: "/api/forge/context/tasks/:taskId/history",
|
|
301781
302149
|
orgIdSource: "none",
|
|
301782
302150
|
responseShape: "unwrapData"
|
|
301783
302151
|
});
|
|
301784
|
-
|
|
302152
|
+
registerProxyRoute({
|
|
301785
302153
|
forgePath: "/api/cmmd/tasks/:taskId/pull-requests",
|
|
301786
302154
|
method: "PUT",
|
|
301787
302155
|
cmmdPath: "/api/forge/context/tasks/:taskId/pull-requests",
|
|
301788
302156
|
orgIdSource: "none",
|
|
301789
302157
|
responseShape: "unwrapData"
|
|
301790
302158
|
});
|
|
301791
|
-
const
|
|
302159
|
+
for (const path of [
|
|
301792
302160
|
"list",
|
|
301793
302161
|
"list-stats",
|
|
301794
302162
|
"detail",
|
|
@@ -301806,70 +302174,70 @@ const cmmdPullRequestRouteLayers = [
|
|
|
301806
302174
|
"thread/resolution",
|
|
301807
302175
|
"reviewers",
|
|
301808
302176
|
"reaction"
|
|
301809
|
-
]
|
|
302177
|
+
]) registerProxyRoute({
|
|
301810
302178
|
forgePath: `/api/cmmd/pull-requests/${path}`,
|
|
301811
302179
|
method: "POST",
|
|
301812
302180
|
cmmdPath: `/api/forge/context/pull-requests/${path}`,
|
|
301813
302181
|
orgIdSource: "none",
|
|
301814
302182
|
responseShape: "unwrapData"
|
|
301815
|
-
})
|
|
301816
|
-
|
|
302183
|
+
});
|
|
302184
|
+
registerProxyRoute({
|
|
301817
302185
|
forgePath: "/api/cmmd/tasks/:taskId/conversations/:conversationId",
|
|
301818
302186
|
method: "GET",
|
|
301819
302187
|
cmmdPath: "/api/forge/context/tasks/:taskId/conversations/:conversationId",
|
|
301820
302188
|
orgIdSource: "none",
|
|
301821
302189
|
responseShape: "unwrapData"
|
|
301822
302190
|
});
|
|
301823
|
-
|
|
302191
|
+
registerProxyRoute({
|
|
301824
302192
|
forgePath: "/api/cmmd/projects/:id/board/:taskId/spawn-forge-thread",
|
|
301825
302193
|
method: "POST",
|
|
301826
302194
|
cmmdPath: "/api/forge/context/projects/:id/board/:taskId/spawn-forge-thread",
|
|
301827
302195
|
orgIdSource: "none",
|
|
301828
302196
|
responseShape: "unwrapData"
|
|
301829
302197
|
});
|
|
301830
|
-
|
|
302198
|
+
registerProxyRoute({
|
|
301831
302199
|
forgePath: "/api/cmmd/work-items/board",
|
|
301832
302200
|
method: "GET",
|
|
301833
302201
|
cmmdPath: "/api/forge/context/work-items/board",
|
|
301834
302202
|
orgIdSource: "none",
|
|
301835
302203
|
responseShape: "unwrapData"
|
|
301836
302204
|
});
|
|
301837
|
-
|
|
302205
|
+
registerProxyRoute({
|
|
301838
302206
|
forgePath: "/api/cmmd/work-items/board",
|
|
301839
302207
|
method: "POST",
|
|
301840
302208
|
cmmdPath: "/api/forge/context/work-items/board",
|
|
301841
302209
|
orgIdSource: "none",
|
|
301842
302210
|
responseShape: "unwrapData"
|
|
301843
302211
|
});
|
|
301844
|
-
|
|
302212
|
+
registerProxyRoute({
|
|
301845
302213
|
forgePath: "/api/cmmd/feedback",
|
|
301846
302214
|
method: "POST",
|
|
301847
302215
|
cmmdPath: "/api/forge/context/feedback",
|
|
301848
302216
|
orgIdSource: "none",
|
|
301849
302217
|
responseShape: "unwrapData"
|
|
301850
302218
|
});
|
|
301851
|
-
|
|
302219
|
+
registerProxyRoute({
|
|
301852
302220
|
forgePath: "/api/cmmd/work-items/board/:taskId",
|
|
301853
302221
|
method: "PATCH",
|
|
301854
302222
|
cmmdPath: "/api/forge/context/work-items/board/:taskId",
|
|
301855
302223
|
orgIdSource: "none",
|
|
301856
302224
|
responseShape: "unwrapData"
|
|
301857
302225
|
});
|
|
301858
|
-
|
|
302226
|
+
registerProxyRoute({
|
|
301859
302227
|
forgePath: "/api/cmmd/work-items/board/:taskId/move",
|
|
301860
302228
|
method: "PATCH",
|
|
301861
302229
|
cmmdPath: "/api/forge/context/work-items/board/:taskId/move",
|
|
301862
302230
|
orgIdSource: "none",
|
|
301863
302231
|
responseShape: "unwrapData"
|
|
301864
302232
|
});
|
|
301865
|
-
|
|
302233
|
+
registerProxyRoute({
|
|
301866
302234
|
forgePath: "/api/cmmd/projects/:projectId/board/:taskId/move",
|
|
301867
302235
|
method: "PATCH",
|
|
301868
302236
|
cmmdPath: "/api/forge/context/projects/:projectId/board/:taskId/move",
|
|
301869
302237
|
orgIdSource: "none",
|
|
301870
302238
|
responseShape: "unwrapData"
|
|
301871
302239
|
});
|
|
301872
|
-
|
|
302240
|
+
registerProxyRoute({
|
|
301873
302241
|
forgePath: "/api/cmmd/projects/:projectId/board/:taskId/archive",
|
|
301874
302242
|
method: "POST",
|
|
301875
302243
|
cmmdPath: "/api/forge/context/projects/:projectId/board/:taskId/archive",
|
|
@@ -301877,7 +302245,7 @@ const cmmdArchiveProjectBoardTaskRouteLayer = registerProxyRoute({
|
|
|
301877
302245
|
responseShape: "unwrapData",
|
|
301878
302246
|
requestBody: "none"
|
|
301879
302247
|
});
|
|
301880
|
-
|
|
302248
|
+
registerProxyRoute({
|
|
301881
302249
|
forgePath: "/api/cmmd/projects/:projectId/board/:taskId/unarchive",
|
|
301882
302250
|
method: "POST",
|
|
301883
302251
|
cmmdPath: "/api/forge/context/projects/:projectId/board/:taskId/unarchive",
|
|
@@ -301885,7 +302253,7 @@ const cmmdUnarchiveProjectBoardTaskRouteLayer = registerProxyRoute({
|
|
|
301885
302253
|
responseShape: "unwrapData",
|
|
301886
302254
|
requestBody: "none"
|
|
301887
302255
|
});
|
|
301888
|
-
|
|
302256
|
+
registerProxyRoute({
|
|
301889
302257
|
forgePath: "/api/cmmd/work-items/board/:taskId/archive",
|
|
301890
302258
|
method: "POST",
|
|
301891
302259
|
cmmdPath: "/api/forge/context/work-items/board/:taskId/archive",
|
|
@@ -301893,7 +302261,7 @@ const cmmdArchiveCenterBoardTaskRouteLayer = registerProxyRoute({
|
|
|
301893
302261
|
responseShape: "unwrapData",
|
|
301894
302262
|
requestBody: "none"
|
|
301895
302263
|
});
|
|
301896
|
-
|
|
302264
|
+
registerProxyRoute({
|
|
301897
302265
|
forgePath: "/api/cmmd/work-items/board/:taskId/unarchive",
|
|
301898
302266
|
method: "POST",
|
|
301899
302267
|
cmmdPath: "/api/forge/context/work-items/board/:taskId/unarchive",
|
|
@@ -301901,109 +302269,109 @@ const cmmdUnarchiveCenterBoardTaskRouteLayer = registerProxyRoute({
|
|
|
301901
302269
|
responseShape: "unwrapData",
|
|
301902
302270
|
requestBody: "none"
|
|
301903
302271
|
});
|
|
301904
|
-
|
|
302272
|
+
registerProxyRoute({
|
|
301905
302273
|
forgePath: "/api/cmmd/campaigns",
|
|
301906
302274
|
method: "GET",
|
|
301907
302275
|
cmmdPath: "/api/forge/context/campaigns",
|
|
301908
302276
|
orgIdSource: "none",
|
|
301909
302277
|
responseShape: "passthrough"
|
|
301910
302278
|
});
|
|
301911
|
-
|
|
302279
|
+
registerProxyRoute({
|
|
301912
302280
|
forgePath: "/api/cmmd/campaigns/:id",
|
|
301913
302281
|
method: "GET",
|
|
301914
302282
|
cmmdPath: "/api/forge/context/campaigns/:id",
|
|
301915
302283
|
orgIdSource: "none",
|
|
301916
302284
|
responseShape: "passthrough"
|
|
301917
302285
|
});
|
|
301918
|
-
|
|
302286
|
+
registerProxyRoute({
|
|
301919
302287
|
forgePath: "/api/cmmd/campaigns",
|
|
301920
302288
|
method: "POST",
|
|
301921
302289
|
cmmdPath: "/api/projects/campaigns",
|
|
301922
302290
|
responseShape: "passthrough"
|
|
301923
302291
|
});
|
|
301924
|
-
|
|
302292
|
+
registerProxyRoute({
|
|
301925
302293
|
forgePath: "/api/cmmd/campaigns/:id",
|
|
301926
302294
|
method: "PUT",
|
|
301927
302295
|
cmmdPath: "/api/projects/campaigns/:id",
|
|
301928
302296
|
responseShape: "passthrough"
|
|
301929
302297
|
});
|
|
301930
|
-
|
|
302298
|
+
registerProxyRoute({
|
|
301931
302299
|
forgePath: "/api/cmmd/campaigns/:id",
|
|
301932
302300
|
method: "DELETE",
|
|
301933
302301
|
cmmdPath: "/api/projects/campaigns/:id",
|
|
301934
302302
|
orgIdSource: "none"
|
|
301935
302303
|
});
|
|
301936
|
-
|
|
302304
|
+
registerProxyRoute({
|
|
301937
302305
|
forgePath: "/api/cmmd/bootstrap",
|
|
301938
302306
|
method: "GET",
|
|
301939
302307
|
cmmdPath: "/api/forge/context/bootstrap",
|
|
301940
302308
|
orgIdSource: "none",
|
|
301941
302309
|
responseShape: "passthrough"
|
|
301942
302310
|
});
|
|
301943
|
-
|
|
302311
|
+
registerProxyRoute({
|
|
301944
302312
|
forgePath: "/api/cmmd/account/preferences",
|
|
301945
302313
|
method: "GET",
|
|
301946
302314
|
cmmdPath: "/api/forge/context/account/preferences",
|
|
301947
302315
|
orgIdSource: "none",
|
|
301948
302316
|
responseShape: "unwrapData"
|
|
301949
302317
|
});
|
|
301950
|
-
|
|
302318
|
+
registerProxyRoute({
|
|
301951
302319
|
forgePath: "/api/cmmd/account/preferences",
|
|
301952
302320
|
method: "PATCH",
|
|
301953
302321
|
cmmdPath: "/api/forge/context/account/preferences",
|
|
301954
302322
|
orgIdSource: "none",
|
|
301955
302323
|
responseShape: "unwrapData"
|
|
301956
302324
|
});
|
|
301957
|
-
|
|
302325
|
+
registerProxyRoute({
|
|
301958
302326
|
forgePath: "/api/cmmd/org/provider-policy",
|
|
301959
302327
|
method: "GET",
|
|
301960
302328
|
cmmdPath: "/api/forge/context/org/provider-policy",
|
|
301961
302329
|
orgIdSource: "none",
|
|
301962
302330
|
responseShape: "unwrapData"
|
|
301963
302331
|
});
|
|
301964
|
-
|
|
302332
|
+
registerProxyRoute({
|
|
301965
302333
|
forgePath: "/api/cmmd/chats",
|
|
301966
302334
|
method: "GET",
|
|
301967
302335
|
cmmdPath: "/api/forge/context/chats",
|
|
301968
302336
|
orgIdSource: "none",
|
|
301969
302337
|
responseShape: "unwrapData"
|
|
301970
302338
|
});
|
|
301971
|
-
|
|
302339
|
+
registerProxyRoute({
|
|
301972
302340
|
forgePath: "/api/cmmd/chats/:threadId",
|
|
301973
302341
|
method: "GET",
|
|
301974
302342
|
cmmdPath: "/api/forge/context/chats/:threadId",
|
|
301975
302343
|
orgIdSource: "none",
|
|
301976
302344
|
responseShape: "unwrapData"
|
|
301977
302345
|
});
|
|
301978
|
-
|
|
302346
|
+
registerProxyRoute({
|
|
301979
302347
|
forgePath: "/api/cmmd/devices",
|
|
301980
302348
|
method: "GET",
|
|
301981
302349
|
cmmdPath: "/api/forge/context/devices",
|
|
301982
302350
|
orgIdSource: "none",
|
|
301983
302351
|
responseShape: "unwrapData"
|
|
301984
302352
|
});
|
|
301985
|
-
|
|
302353
|
+
registerProxyRoute({
|
|
301986
302354
|
forgePath: "/api/cmmd/devices/register",
|
|
301987
302355
|
method: "POST",
|
|
301988
302356
|
cmmdPath: "/api/forge/context/devices/register",
|
|
301989
302357
|
orgIdSource: "none",
|
|
301990
302358
|
responseShape: "unwrapData"
|
|
301991
302359
|
});
|
|
301992
|
-
|
|
302360
|
+
registerProxyRoute({
|
|
301993
302361
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/heartbeat",
|
|
301994
302362
|
method: "POST",
|
|
301995
302363
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/heartbeat",
|
|
301996
302364
|
orgIdSource: "none",
|
|
301997
302365
|
responseShape: "unwrapData"
|
|
301998
302366
|
});
|
|
301999
|
-
|
|
302367
|
+
registerProxyRoute({
|
|
302000
302368
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/access-grants",
|
|
302001
302369
|
method: "POST",
|
|
302002
302370
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/access-grants",
|
|
302003
302371
|
orgIdSource: "none",
|
|
302004
302372
|
responseShape: "unwrapData"
|
|
302005
302373
|
});
|
|
302006
|
-
|
|
302374
|
+
registerProxyRoute({
|
|
302007
302375
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/access-grants/:grantId/revoke",
|
|
302008
302376
|
method: "POST",
|
|
302009
302377
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/access-grants/:grantId/revoke",
|
|
@@ -302011,46 +302379,60 @@ const cmmdRevokeRuntimeAccessRouteLayer = registerProxyRoute({
|
|
|
302011
302379
|
responseShape: "unwrapData",
|
|
302012
302380
|
successStatus: 200
|
|
302013
302381
|
});
|
|
302014
|
-
|
|
302382
|
+
registerProxyRoute({
|
|
302015
302383
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/relay-routes",
|
|
302016
302384
|
method: "POST",
|
|
302017
302385
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/relay-routes",
|
|
302018
302386
|
orgIdSource: "none",
|
|
302019
302387
|
responseShape: "unwrapData"
|
|
302020
302388
|
});
|
|
302021
|
-
|
|
302389
|
+
registerProxyRoute({
|
|
302022
302390
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/relay-action-grants",
|
|
302023
302391
|
method: "POST",
|
|
302024
302392
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/relay-action-grants",
|
|
302025
302393
|
orgIdSource: "none",
|
|
302026
302394
|
responseShape: "unwrapData"
|
|
302027
302395
|
});
|
|
302028
|
-
|
|
302396
|
+
registerProxyRoute({
|
|
302029
302397
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/inventory",
|
|
302030
302398
|
method: "PUT",
|
|
302031
302399
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/inventory",
|
|
302032
302400
|
orgIdSource: "none",
|
|
302033
302401
|
responseShape: "unwrapData"
|
|
302034
302402
|
});
|
|
302035
|
-
|
|
302403
|
+
registerProxyRoute({
|
|
302036
302404
|
forgePath: "/api/cmmd/runtime-inventory",
|
|
302037
302405
|
method: "GET",
|
|
302038
302406
|
cmmdPath: "/api/forge/context/runtime-inventory",
|
|
302039
302407
|
orgIdSource: "none",
|
|
302040
302408
|
responseShape: "unwrapData"
|
|
302041
302409
|
});
|
|
302410
|
+
registerProxyRoute({
|
|
302411
|
+
forgePath: "/api/cmmd/threads/:runtimeId/:threadId/lifecycle-intent",
|
|
302412
|
+
method: "PUT",
|
|
302413
|
+
cmmdPath: "/api/forge/context/threads/:runtimeId/:threadId/lifecycle-intent",
|
|
302414
|
+
orgIdSource: "none",
|
|
302415
|
+
requestBody: "json",
|
|
302416
|
+
responseShape: "unwrapData"
|
|
302417
|
+
});
|
|
302418
|
+
registerProxyRoute({
|
|
302419
|
+
forgePath: "/api/cmmd/threads/:runtimeId/:threadId/lifecycle-intent",
|
|
302420
|
+
method: "DELETE",
|
|
302421
|
+
cmmdPath: "/api/forge/context/threads/:runtimeId/:threadId/lifecycle-intent",
|
|
302422
|
+
orgIdSource: "none"
|
|
302423
|
+
});
|
|
302042
302424
|
/**
|
|
302043
302425
|
* Owner-scoped, bounded control-plane observation. This is intentionally
|
|
302044
302426
|
* separate from the runtime inventory publisher and never wakes a runtime.
|
|
302045
302427
|
*/
|
|
302046
|
-
|
|
302428
|
+
registerProxyRoute({
|
|
302047
302429
|
forgePath: "/api/cmmd/runtime-diagnostics/v2/runtimes/:runtimeId",
|
|
302048
302430
|
method: "GET",
|
|
302049
302431
|
cmmdPath: "/api/forge/context/runtime-diagnostics/v2/runtimes/:runtimeId",
|
|
302050
302432
|
orgIdSource: "none",
|
|
302051
302433
|
responseShape: "unwrapData"
|
|
302052
302434
|
});
|
|
302053
|
-
|
|
302435
|
+
registerProxyRoute({
|
|
302054
302436
|
forgePath: "/api/cmmd/auth-runtime",
|
|
302055
302437
|
method: "POST",
|
|
302056
302438
|
cmmdPath: "/api/forge/context/auth-runtime",
|
|
@@ -302058,21 +302440,21 @@ const cmmdProvisionAuthRuntimeRouteLayer = registerProxyRoute({
|
|
|
302058
302440
|
responseShape: "unwrapData",
|
|
302059
302441
|
requestBody: "none"
|
|
302060
302442
|
});
|
|
302061
|
-
|
|
302443
|
+
registerProxyRoute({
|
|
302062
302444
|
forgePath: "/api/cmmd/auth-runtime",
|
|
302063
302445
|
method: "GET",
|
|
302064
302446
|
cmmdPath: "/api/forge/context/auth-runtime",
|
|
302065
302447
|
orgIdSource: "none",
|
|
302066
302448
|
responseShape: "unwrapData"
|
|
302067
302449
|
});
|
|
302068
|
-
|
|
302450
|
+
registerProxyRoute({
|
|
302069
302451
|
forgePath: "/api/cmmd/auth-runtime",
|
|
302070
302452
|
method: "DELETE",
|
|
302071
302453
|
cmmdPath: "/api/forge/context/auth-runtime",
|
|
302072
302454
|
orgIdSource: "none",
|
|
302073
302455
|
responseShape: "unwrapData"
|
|
302074
302456
|
});
|
|
302075
|
-
|
|
302457
|
+
registerProxyRoute({
|
|
302076
302458
|
forgePath: "/api/cmmd/auth-runtime/connect",
|
|
302077
302459
|
method: "POST",
|
|
302078
302460
|
cmmdPath: "/api/forge/context/auth-runtime/connect",
|
|
@@ -302080,14 +302462,14 @@ const cmmdConnectAuthRuntimeRouteLayer = registerProxyRoute({
|
|
|
302080
302462
|
responseShape: "unwrapData",
|
|
302081
302463
|
requestBody: "none"
|
|
302082
302464
|
});
|
|
302083
|
-
|
|
302465
|
+
registerProxyRoute({
|
|
302084
302466
|
forgePath: "/api/cmmd/providers/accounts",
|
|
302085
302467
|
method: "GET",
|
|
302086
302468
|
cmmdPath: "/api/forge/context/providers/accounts",
|
|
302087
302469
|
orgIdSource: "none",
|
|
302088
302470
|
responseShape: "unwrapData"
|
|
302089
302471
|
});
|
|
302090
|
-
|
|
302472
|
+
registerProxyRoute({
|
|
302091
302473
|
forgePath: "/api/cmmd/providers/accounts/:id",
|
|
302092
302474
|
method: "DELETE",
|
|
302093
302475
|
cmmdPath: "/api/forge/context/providers/accounts/:id",
|
|
@@ -302095,23 +302477,29 @@ const cmmdDeleteProviderAccountRouteLayer = registerProxyRoute({
|
|
|
302095
302477
|
responseShape: "unwrapData",
|
|
302096
302478
|
requestBody: "none"
|
|
302097
302479
|
});
|
|
302098
|
-
|
|
302480
|
+
registerProxyRoute({
|
|
302099
302481
|
forgePath: "/api/cmmd/providers/accounts/default",
|
|
302100
302482
|
method: "PUT",
|
|
302101
302483
|
cmmdPath: "/api/forge/context/providers/accounts/default",
|
|
302102
302484
|
orgIdSource: "none",
|
|
302103
302485
|
responseShape: "unwrapData"
|
|
302104
302486
|
});
|
|
302105
|
-
|
|
302106
|
-
|
|
302107
|
-
|
|
302487
|
+
registerProxyHandler({
|
|
302488
|
+
forgePath: "/api/cmmd/providers/usage",
|
|
302489
|
+
method: "GET",
|
|
302490
|
+
parse: () => succeed({
|
|
302491
|
+
ok: true,
|
|
302492
|
+
value: void 0
|
|
302493
|
+
}),
|
|
302494
|
+
run: (_parsed, { session }) => runCmmdRestProxyAsHandlerResult(session, (jwt) => cmmdGateway.request({
|
|
302108
302495
|
method: "GET",
|
|
302109
302496
|
jwt,
|
|
302110
302497
|
path: "/api/forge/context/providers/usage"
|
|
302111
|
-
}))
|
|
302112
|
-
|
|
302113
|
-
|
|
302114
|
-
})
|
|
302498
|
+
}), (value) => ({
|
|
302499
|
+
status: 200,
|
|
302500
|
+
body: unwrapForgeEnvelope(value)
|
|
302501
|
+
}))
|
|
302502
|
+
});
|
|
302115
302503
|
function parseProviderUsageRefreshInput(rawBody) {
|
|
302116
302504
|
if (rawBody === null || typeof rawBody !== "object") return null;
|
|
302117
302505
|
const body = rawBody;
|
|
@@ -302193,56 +302581,56 @@ function makeRefreshProviderUsageHandler(dependencies = {}) {
|
|
|
302193
302581
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error)));
|
|
302194
302582
|
}
|
|
302195
302583
|
const cmmdRefreshProviderUsageRouteLayer = add$1("POST", "/api/cmmd/providers/usage/refresh", makeRefreshProviderUsageHandler());
|
|
302196
|
-
|
|
302584
|
+
registerProxyRoute({
|
|
302197
302585
|
forgePath: "/api/cmmd/providers/codex/credential",
|
|
302198
302586
|
method: "GET",
|
|
302199
302587
|
cmmdPath: "/api/forge/context/providers/codex/credential",
|
|
302200
302588
|
orgIdSource: "none",
|
|
302201
302589
|
responseShape: "unwrapData"
|
|
302202
302590
|
});
|
|
302203
|
-
|
|
302591
|
+
registerProxyRoute({
|
|
302204
302592
|
forgePath: "/api/cmmd/providers/codex/credential",
|
|
302205
302593
|
method: "DELETE",
|
|
302206
302594
|
cmmdPath: "/api/forge/context/providers/codex/credential",
|
|
302207
302595
|
orgIdSource: "none",
|
|
302208
302596
|
responseShape: "unwrapData"
|
|
302209
302597
|
});
|
|
302210
|
-
|
|
302598
|
+
registerProxyRoute({
|
|
302211
302599
|
forgePath: "/api/cmmd/providers/claude/credential",
|
|
302212
302600
|
method: "GET",
|
|
302213
302601
|
cmmdPath: "/api/forge/context/providers/claude/credential",
|
|
302214
302602
|
orgIdSource: "none",
|
|
302215
302603
|
responseShape: "unwrapData"
|
|
302216
302604
|
});
|
|
302217
|
-
|
|
302605
|
+
registerProxyRoute({
|
|
302218
302606
|
forgePath: "/api/cmmd/providers/claude/credential",
|
|
302219
302607
|
method: "DELETE",
|
|
302220
302608
|
cmmdPath: "/api/forge/context/providers/claude/credential",
|
|
302221
302609
|
orgIdSource: "none",
|
|
302222
302610
|
responseShape: "unwrapData"
|
|
302223
302611
|
});
|
|
302224
|
-
|
|
302612
|
+
registerProxyRoute({
|
|
302225
302613
|
forgePath: "/api/cmmd/providers/claude/runtime-readiness/:runtimeId",
|
|
302226
302614
|
method: "GET",
|
|
302227
302615
|
cmmdPath: "/api/forge/context/providers/claude/runtime-readiness/:runtimeId",
|
|
302228
302616
|
orgIdSource: "none",
|
|
302229
302617
|
responseShape: "unwrapData"
|
|
302230
302618
|
});
|
|
302231
|
-
|
|
302619
|
+
registerProxyRoute({
|
|
302232
302620
|
forgePath: "/api/cmmd/devices/runtimes/:runtimeId/threads/:threadId/events",
|
|
302233
302621
|
method: "POST",
|
|
302234
302622
|
cmmdPath: "/api/forge/context/devices/runtimes/:runtimeId/threads/:threadId/events",
|
|
302235
302623
|
orgIdSource: "none",
|
|
302236
302624
|
responseShape: "unwrapData"
|
|
302237
302625
|
});
|
|
302238
|
-
|
|
302626
|
+
registerProxyRoute({
|
|
302239
302627
|
forgePath: "/api/cmmd/threads/:runtimeId/:threadId",
|
|
302240
302628
|
method: "GET",
|
|
302241
302629
|
cmmdPath: "/api/forge/context/threads/:runtimeId/:threadId",
|
|
302242
302630
|
orgIdSource: "none",
|
|
302243
302631
|
responseShape: "unwrapData"
|
|
302244
302632
|
});
|
|
302245
|
-
|
|
302633
|
+
registerProxyRoute({
|
|
302246
302634
|
forgePath: "/api/cmmd/devices/:deviceId/rename",
|
|
302247
302635
|
method: "POST",
|
|
302248
302636
|
cmmdPath: "/api/forge/context/devices/:deviceId/rename",
|
|
@@ -302258,7 +302646,7 @@ const cmmdRenameDeviceRouteLayer = registerProxyRoute({
|
|
|
302258
302646
|
* the status and the code reach the browser unchanged, which is what lets the
|
|
302259
302647
|
* rename field say something specific instead of "something went wrong".
|
|
302260
302648
|
*/
|
|
302261
|
-
|
|
302649
|
+
registerProxyRoute({
|
|
302262
302650
|
forgePath: "/api/cmmd/forge-runtimes/:runtimeId/rename",
|
|
302263
302651
|
method: "POST",
|
|
302264
302652
|
cmmdPath: "/api/forge/context/runtimes/:runtimeId/rename",
|
|
@@ -302266,7 +302654,7 @@ const cmmdRenameForgeRuntimeRouteLayer = registerProxyRoute({
|
|
|
302266
302654
|
responseShape: "unwrapData",
|
|
302267
302655
|
successStatus: 200
|
|
302268
302656
|
});
|
|
302269
|
-
|
|
302657
|
+
registerProxyRoute({
|
|
302270
302658
|
forgePath: "/api/cmmd/devices/:deviceId/revoke",
|
|
302271
302659
|
method: "POST",
|
|
302272
302660
|
cmmdPath: "/api/forge/context/devices/:deviceId/revoke",
|
|
@@ -302275,24 +302663,21 @@ const cmmdRevokeDeviceRouteLayer = registerProxyRoute({
|
|
|
302275
302663
|
requestBody: "none",
|
|
302276
302664
|
successStatus: 200
|
|
302277
302665
|
});
|
|
302278
|
-
|
|
302666
|
+
registerProxyRoute({
|
|
302279
302667
|
forgePath: "/api/cmmd/connectors",
|
|
302280
302668
|
method: "GET",
|
|
302281
302669
|
cmmdPath: "/api/forge/context/connectors",
|
|
302282
302670
|
orgIdSource: "none"
|
|
302283
302671
|
});
|
|
302284
|
-
|
|
302672
|
+
registerProxyRoute({
|
|
302285
302673
|
forgePath: "/api/cmmd/connectors/:connectorId/install",
|
|
302286
302674
|
method: "POST",
|
|
302287
302675
|
cmmdPath: "/api/forge/context/connectors/:connectorId/install",
|
|
302288
302676
|
orgIdSource: "none"
|
|
302289
302677
|
});
|
|
302290
302678
|
const cmmdForgeCloudProjectsListRouteLayer = add$1("GET", "/api/cmmd/forge-cloud-projects", gen(function* () {
|
|
302291
|
-
const accessToken = yield* makeCmmdProxyAccessTokenEffect("forge-cloud-projects");
|
|
302292
|
-
if (!accessToken) return
|
|
302293
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302294
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302295
|
-
});
|
|
302679
|
+
const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-cloud-projects");
|
|
302680
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302296
302681
|
const upstreamUrl = `${resolveCommandAppUrl()}${CMMD_CLOUD_PROJECTS_PATH}`;
|
|
302297
302682
|
const upstreamOrError = yield* fetchCmmdUpstreamWithRetry(() => fetch(upstreamUrl, { headers: {
|
|
302298
302683
|
Authorization: `Bearer ${accessToken}`,
|
|
@@ -302303,10 +302688,7 @@ const cmmdForgeCloudProjectsListRouteLayer = add$1("GET", "/api/cmmd/forge-cloud
|
|
|
302303
302688
|
code: "CMMD_UNAVAILABLE"
|
|
302304
302689
|
}, { status: 503 });
|
|
302305
302690
|
const upstream = upstreamOrError.res;
|
|
302306
|
-
if (upstream.status === 401 || upstream.status === 403) return
|
|
302307
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302308
|
-
message: "CMMD authentication expired. Sign in again to continue."
|
|
302309
|
-
});
|
|
302691
|
+
if (upstream.status === 401 || upstream.status === 403) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302310
302692
|
const bodyOrError = yield* tryPromise(() => upstream.text()).pipe(map$3((text) => ({
|
|
302311
302693
|
ok: true,
|
|
302312
302694
|
text
|
|
@@ -302328,35 +302710,35 @@ const cmmdForgeCloudProjectsListRouteLayer = add$1("GET", "/api/cmmd/forge-cloud
|
|
|
302328
302710
|
headers: { "content-type": "application/json" }
|
|
302329
302711
|
});
|
|
302330
302712
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error))));
|
|
302331
|
-
|
|
302713
|
+
registerProxyRoute({
|
|
302332
302714
|
forgePath: "/api/cmmd/forge-cloud-projects",
|
|
302333
302715
|
method: "POST",
|
|
302334
302716
|
cmmdPath: CMMD_CLOUD_PROJECTS_PATH,
|
|
302335
302717
|
orgIdSource: "none",
|
|
302336
302718
|
responseShape: "unwrapData"
|
|
302337
302719
|
});
|
|
302338
|
-
|
|
302720
|
+
registerProxyRoute({
|
|
302339
302721
|
forgePath: "/api/cmmd/forge-cloud-projects/:projectId",
|
|
302340
302722
|
method: "DELETE",
|
|
302341
302723
|
cmmdPath: `${CMMD_CLOUD_PROJECTS_PATH}/:projectId`,
|
|
302342
302724
|
orgIdSource: "none",
|
|
302343
302725
|
responseShape: "unwrapData"
|
|
302344
302726
|
});
|
|
302345
|
-
|
|
302727
|
+
registerProxyRoute({
|
|
302346
302728
|
forgePath: "/api/cmmd/forge-cloud-projects/:projectId/lifecycle-preflight",
|
|
302347
302729
|
method: "GET",
|
|
302348
302730
|
cmmdPath: `${CMMD_CLOUD_PROJECTS_PATH}/:projectId/lifecycle-preflight`,
|
|
302349
302731
|
orgIdSource: "none",
|
|
302350
302732
|
responseShape: "unwrapData"
|
|
302351
302733
|
});
|
|
302352
|
-
|
|
302734
|
+
registerProxyRoute({
|
|
302353
302735
|
forgePath: "/api/cmmd/forge-cloud-projects/:projectId/removal-preview",
|
|
302354
302736
|
method: "GET",
|
|
302355
302737
|
cmmdPath: `${CMMD_CLOUD_PROJECTS_PATH}/:projectId/removal-preview`,
|
|
302356
302738
|
orgIdSource: "none",
|
|
302357
302739
|
responseShape: "unwrapData"
|
|
302358
302740
|
});
|
|
302359
|
-
|
|
302741
|
+
registerProxyRoute({
|
|
302360
302742
|
forgePath: "/api/cmmd/forge-cloud-projects/:projectId/removal",
|
|
302361
302743
|
method: "POST",
|
|
302362
302744
|
cmmdPath: `${CMMD_CLOUD_PROJECTS_PATH}/:projectId/removal`,
|
|
@@ -302365,7 +302747,7 @@ const cmmdForgeCloudProjectRemovalRouteLayer = registerProxyRoute({
|
|
|
302365
302747
|
successStatus: 202,
|
|
302366
302748
|
workIntakeInvalidation: "completedPermanentRemoval"
|
|
302367
302749
|
});
|
|
302368
|
-
|
|
302750
|
+
registerProxyRoute({
|
|
302369
302751
|
forgePath: "/api/cmmd/forge-cloud-project-removals/:operationId",
|
|
302370
302752
|
method: "GET",
|
|
302371
302753
|
cmmdPath: `${CMMD_CLOUD_PROJECTS_PATH}/removals/:operationId`,
|
|
@@ -302429,11 +302811,8 @@ function makeFetchCloudProjectsFrameEffect(upstreamUrl, accessToken) {
|
|
|
302429
302811
|
})).pipe(catch_(() => succeed(null)));
|
|
302430
302812
|
}
|
|
302431
302813
|
const cmmdForgeCloudProjectsEventsRouteLayer = add$1("GET", "/api/cmmd/forge-cloud-projects/events", gen(function* () {
|
|
302432
|
-
const accessToken = yield* makeCmmdProxyAccessTokenEffect("forge-cloud-projects/events");
|
|
302433
|
-
if (!accessToken) return
|
|
302434
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302435
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302436
|
-
});
|
|
302814
|
+
const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-cloud-projects/events");
|
|
302815
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302437
302816
|
const fetchCloudProjectsFrame = makeFetchCloudProjectsFrameEffect(`${resolveCommandAppUrl()}${CMMD_CLOUD_PROJECTS_PATH}`, accessToken);
|
|
302438
302817
|
const dataStream = concat$2(fromEffect(fetchCloudProjectsFrame), tick(FORGE_RUNTIMES_POLL_INTERVAL).pipe(mapEffect$1(() => fetchCloudProjectsFrame))).pipe(filter$2((frame) => frame !== null));
|
|
302439
302818
|
const keepaliveStream = tick(FORGE_RUNTIMES_KEEPALIVE_INTERVAL).pipe(map$7(() => FORGE_RUNTIMES_KEEPALIVE_FRAME));
|
|
@@ -302505,11 +302884,8 @@ function fetchCmmdUpstreamWithRetry(send, policy = "idempotent") {
|
|
|
302505
302884
|
}
|
|
302506
302885
|
const cmmdForgeRuntimesEnsureRouteLayer = add$1("POST", "/api/cmmd/forge-runtimes/ensure", gen(function* () {
|
|
302507
302886
|
const request = yield* HttpServerRequest;
|
|
302508
|
-
const accessToken = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/ensure");
|
|
302509
|
-
if (!accessToken) return
|
|
302510
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302511
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302512
|
-
});
|
|
302887
|
+
const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/ensure");
|
|
302888
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302513
302889
|
const scopedBody = splitCmmdRuntimeOrganizationScope(yield* request.json.pipe(catch_(() => succeed({}))));
|
|
302514
302890
|
if (!scopedBody) return jsonUnsafe({ error: "A valid organizationId is required when organization scope is provided." }, { status: 400 });
|
|
302515
302891
|
const upstreamUrl = `${resolveCommandAppUrl()}/api/forge/context/runtimes/ensure`;
|
|
@@ -302528,10 +302904,7 @@ const cmmdForgeRuntimesEnsureRouteLayer = add$1("POST", "/api/cmmd/forge-runtime
|
|
|
302528
302904
|
code: "CMMD_UNAVAILABLE"
|
|
302529
302905
|
}, { status: 503 });
|
|
302530
302906
|
const upstream = upstreamOrError.res;
|
|
302531
|
-
if (upstream.status === 401 || upstream.status === 403) return
|
|
302532
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302533
|
-
message: "CMMD authentication expired. Sign in again to continue."
|
|
302534
|
-
});
|
|
302907
|
+
if (upstream.status === 401 || upstream.status === 403) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302535
302908
|
const bodyOrError = yield* tryPromise(() => upstream.text()).pipe(map$3((text) => ({
|
|
302536
302909
|
ok: true,
|
|
302537
302910
|
text
|
|
@@ -302555,11 +302928,8 @@ const cmmdForgeRuntimesEnsureRouteLayer = add$1("POST", "/api/cmmd/forge-runtime
|
|
|
302555
302928
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error))));
|
|
302556
302929
|
const cmmdForgeRuntimesConnectRouteLayer = add$1("POST", "/api/cmmd/forge-runtimes/:runtimeId/connect", gen(function* () {
|
|
302557
302930
|
const request = yield* HttpServerRequest;
|
|
302558
|
-
const accessToken = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/connect");
|
|
302559
|
-
if (!accessToken) return
|
|
302560
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302561
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302562
|
-
});
|
|
302931
|
+
const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/connect");
|
|
302932
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302563
302933
|
const runtimeId = extractIdFromPath(new URL(request.url, "http://localhost").pathname, 2);
|
|
302564
302934
|
if (!runtimeId) return jsonUnsafe({ error: "Runtime ID is required." }, { status: 400 });
|
|
302565
302935
|
const scopedBody = splitCmmdRuntimeOrganizationScope(yield* request.json.pipe(catch_(() => succeed({}))));
|
|
@@ -302580,10 +302950,7 @@ const cmmdForgeRuntimesConnectRouteLayer = add$1("POST", "/api/cmmd/forge-runtim
|
|
|
302580
302950
|
code: "CMMD_UNAVAILABLE"
|
|
302581
302951
|
}, { status: 503 });
|
|
302582
302952
|
const upstream = upstreamOrError.res;
|
|
302583
|
-
if (upstream.status === 401 || upstream.status === 403) return
|
|
302584
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302585
|
-
message: "CMMD authentication expired. Sign in again to continue."
|
|
302586
|
-
});
|
|
302953
|
+
if (upstream.status === 401 || upstream.status === 403) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302587
302954
|
const bodyOrError = yield* tryPromise(() => upstream.text()).pipe(map$3((text) => ({
|
|
302588
302955
|
ok: true,
|
|
302589
302956
|
text
|
|
@@ -302607,11 +302974,8 @@ const cmmdForgeRuntimesConnectRouteLayer = add$1("POST", "/api/cmmd/forge-runtim
|
|
|
302607
302974
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error))));
|
|
302608
302975
|
const cmmdForgeRuntimesStatusRouteLayer = add$1("GET", "/api/cmmd/forge-runtimes/:runtimeId/status", gen(function* () {
|
|
302609
302976
|
const request = yield* HttpServerRequest;
|
|
302610
|
-
const accessToken = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/status");
|
|
302611
|
-
if (!accessToken) return
|
|
302612
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302613
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302614
|
-
});
|
|
302977
|
+
const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/status");
|
|
302978
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302615
302979
|
const runtimeId = extractIdFromPath(new URL(request.url, "http://localhost").pathname, 2);
|
|
302616
302980
|
if (!runtimeId) return jsonUnsafe({ error: "Runtime ID is required." }, { status: 400 });
|
|
302617
302981
|
const upstreamUrl = `${resolveCommandAppUrl()}/api/forge/context/runtimes/${encodeURIComponent(runtimeId)}/status`;
|
|
@@ -302627,10 +302991,7 @@ const cmmdForgeRuntimesStatusRouteLayer = add$1("GET", "/api/cmmd/forge-runtimes
|
|
|
302627
302991
|
code: "CMMD_UNAVAILABLE"
|
|
302628
302992
|
}, { status: 503 });
|
|
302629
302993
|
const upstream = upstreamOrError.res;
|
|
302630
|
-
if (upstream.status === 401 || upstream.status === 403) return
|
|
302631
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302632
|
-
message: "CMMD authentication expired. Sign in again to continue."
|
|
302633
|
-
});
|
|
302994
|
+
if (upstream.status === 401 || upstream.status === 403) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302634
302995
|
const bodyOrError = yield* tryPromise(() => upstream.text()).pipe(map$3((text) => ({
|
|
302635
302996
|
ok: true,
|
|
302636
302997
|
text
|
|
@@ -302661,10 +303022,7 @@ function makeCmmdForgeRuntimesLifecycleHandler(action) {
|
|
|
302661
303022
|
subject: session.subject,
|
|
302662
303023
|
logPrefix: `forge-runtimes/${action}`
|
|
302663
303024
|
});
|
|
302664
|
-
if (!accessToken) return
|
|
302665
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302666
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302667
|
-
});
|
|
303025
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302668
303026
|
const runtimeId = extractIdFromPath(new URL(request.url, "http://localhost").pathname, 2);
|
|
302669
303027
|
if (!runtimeId) return jsonUnsafe({ error: "Runtime ID is required." }, { status: 400 });
|
|
302670
303028
|
const scopedBody = splitCmmdRuntimeOrganizationScope(yield* request.json.pipe(catch_(() => succeed({}))));
|
|
@@ -302685,10 +303043,7 @@ function makeCmmdForgeRuntimesLifecycleHandler(action) {
|
|
|
302685
303043
|
code: "CMMD_UNAVAILABLE"
|
|
302686
303044
|
}, { status: 503 });
|
|
302687
303045
|
const upstream = upstreamOrError.res;
|
|
302688
|
-
if (upstream.status === 401 || upstream.status === 403) return
|
|
302689
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302690
|
-
message: "CMMD authentication expired. Sign in again to continue."
|
|
302691
|
-
});
|
|
303046
|
+
if (upstream.status === 401 || upstream.status === 403) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302692
303047
|
const bodyOrError = yield* tryPromise(() => upstream.text()).pipe(map$3((text) => ({
|
|
302693
303048
|
ok: true,
|
|
302694
303049
|
text
|
|
@@ -302721,11 +303076,8 @@ const cmmdForgeRuntimesRecycleRouteLayer = add$1("POST", "/api/cmmd/forge-runtim
|
|
|
302721
303076
|
const cmmdForgeRuntimesUpdateCommitRouteLayer = add$1("POST", "/api/cmmd/forge-runtimes/:runtimeId/update-commit", __cmmdForgeRuntimesUpdateCommitHandlerForTests);
|
|
302722
303077
|
const cmmdForgeRuntimesDestroyRouteLayer = add$1("POST", "/api/cmmd/forge-runtimes/:runtimeId/destroy", gen(function* () {
|
|
302723
303078
|
const request = yield* HttpServerRequest;
|
|
302724
|
-
const accessToken = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/destroy");
|
|
302725
|
-
if (!accessToken) return
|
|
302726
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302727
|
-
message: "CMMD authentication is required. Sign in again to continue."
|
|
302728
|
-
});
|
|
303079
|
+
const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-runtimes/destroy");
|
|
303080
|
+
if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302729
303081
|
const runtimeId = extractIdFromPath(new URL(request.url, "http://localhost").pathname, 2);
|
|
302730
303082
|
if (!runtimeId) return jsonUnsafe({ error: "Runtime ID is required." }, { status: 400 });
|
|
302731
303083
|
const scopedBody = splitCmmdRuntimeOrganizationScope(yield* request.json.pipe(catch_(() => succeed({}))));
|
|
@@ -302746,10 +303098,7 @@ const cmmdForgeRuntimesDestroyRouteLayer = add$1("POST", "/api/cmmd/forge-runtim
|
|
|
302746
303098
|
code: "CMMD_UNAVAILABLE"
|
|
302747
303099
|
}, { status: 503 });
|
|
302748
303100
|
const upstream = upstreamOrError.res;
|
|
302749
|
-
if (upstream.status === 401 || upstream.status === 403) return
|
|
302750
|
-
code: "CMMD_AUTH_REQUIRED",
|
|
302751
|
-
message: "CMMD authentication expired. Sign in again to continue."
|
|
302752
|
-
});
|
|
303101
|
+
if (upstream.status === 401 || upstream.status === 403) return yield* respondCmmdConnectionRequired(session.sessionId);
|
|
302753
303102
|
const bodyOrError = yield* tryPromise(() => upstream.text()).pipe(map$3((text) => ({
|
|
302754
303103
|
ok: true,
|
|
302755
303104
|
text
|
|
@@ -302771,6 +303120,7 @@ const cmmdForgeRuntimesDestroyRouteLayer = add$1("POST", "/api/cmmd/forge-runtim
|
|
|
302771
303120
|
headers: { "content-type": "application/json" }
|
|
302772
303121
|
});
|
|
302773
303122
|
}).pipe(catchTag("AuthError", (error) => respondToAuthError(error))));
|
|
303123
|
+
const cmmdProxyRouteLayers = registeredProxyRouteLayers().slice(__cmmdProxyRouteLayersStartIndex);
|
|
302774
303124
|
//#endregion
|
|
302775
303125
|
//#region src/cmmdData/projectTeamProxyRoutes.ts
|
|
302776
303126
|
const cmmdListWorkspaceMembersRouteLayer = registerProxyRoute({
|
|
@@ -304013,6 +304363,103 @@ function recordRuntimeReplicationOutboxDiagnostics(diagnostics, now = Date.now()
|
|
|
304013
304363
|
]).pipe(asVoid);
|
|
304014
304364
|
}
|
|
304015
304365
|
//#endregion
|
|
304366
|
+
//#region src/runtimeReplication/pendingLifecycleIntents.ts
|
|
304367
|
+
/**
|
|
304368
|
+
* The newest moment a person or a turn touched this thread, mirroring the
|
|
304369
|
+
* client's `threadLastActivityAt` over the full thread rather than its shell:
|
|
304370
|
+
* the shell's `latestUserMessageAt` is projected from exactly these messages.
|
|
304371
|
+
*/
|
|
304372
|
+
function readModelThreadLastActivityAt(thread) {
|
|
304373
|
+
const candidates = [
|
|
304374
|
+
...thread.messages.filter((message) => message.role === "user").map((m) => m.createdAt),
|
|
304375
|
+
thread.latestTurn?.requestedAt,
|
|
304376
|
+
thread.latestTurn?.startedAt,
|
|
304377
|
+
thread.latestTurn?.completedAt
|
|
304378
|
+
];
|
|
304379
|
+
let latest = null;
|
|
304380
|
+
let latestTimestamp = Number.NEGATIVE_INFINITY;
|
|
304381
|
+
for (const candidate of candidates) {
|
|
304382
|
+
if (candidate === null || candidate === void 0) continue;
|
|
304383
|
+
const timestamp = Date.parse(candidate);
|
|
304384
|
+
if (timestamp > latestTimestamp) {
|
|
304385
|
+
latest = candidate;
|
|
304386
|
+
latestTimestamp = timestamp;
|
|
304387
|
+
}
|
|
304388
|
+
}
|
|
304389
|
+
return latest;
|
|
304390
|
+
}
|
|
304391
|
+
function intentIsSpent(thread, intent) {
|
|
304392
|
+
const lastActivityAt = readModelThreadLastActivityAt(thread);
|
|
304393
|
+
if (lastActivityAt === null) return false;
|
|
304394
|
+
const activity = Date.parse(lastActivityAt);
|
|
304395
|
+
const requested = Date.parse(intent.requestedAt);
|
|
304396
|
+
return Number.isFinite(activity) && Number.isFinite(requested) && activity > requested;
|
|
304397
|
+
}
|
|
304398
|
+
function commandFor(runtimeId, intent) {
|
|
304399
|
+
const commandId = lifecycleIntentCommandId(runtimeId, intent.threadId, intent.requestedAt);
|
|
304400
|
+
const threadId = ThreadId.make(intent.threadId);
|
|
304401
|
+
return intent.action === "settle" ? {
|
|
304402
|
+
type: "thread.settle",
|
|
304403
|
+
commandId,
|
|
304404
|
+
threadId,
|
|
304405
|
+
settledOverride: "settled"
|
|
304406
|
+
} : {
|
|
304407
|
+
type: "thread.unsettle",
|
|
304408
|
+
commandId,
|
|
304409
|
+
threadId
|
|
304410
|
+
};
|
|
304411
|
+
}
|
|
304412
|
+
const applyOne = fn$1("applyLifecycleIntent")(function* (runtimeId, intent, dependencies) {
|
|
304413
|
+
const base = {
|
|
304414
|
+
runtimeId,
|
|
304415
|
+
threadId: intent.threadId,
|
|
304416
|
+
action: intent.action,
|
|
304417
|
+
requestedAt: intent.requestedAt
|
|
304418
|
+
};
|
|
304419
|
+
const report = (outcome, detail) => dependencies.log({
|
|
304420
|
+
...base,
|
|
304421
|
+
outcome,
|
|
304422
|
+
...detail === void 0 ? {} : { detail }
|
|
304423
|
+
}).pipe(as$3(outcome));
|
|
304424
|
+
const thread = (yield* dependencies.getReadModel()).threads.find((candidate) => candidate.id === intent.threadId);
|
|
304425
|
+
if (thread === void 0) return yield* report("missing-thread");
|
|
304426
|
+
if (intentIsSpent(thread, intent)) return yield* report("spent");
|
|
304427
|
+
return yield* dependencies.dispatch(commandFor(runtimeId, intent)).pipe(flatMap(() => report("applied")), catch_((error) => error._tag === "OrchestrationCommandInvariantError" || error._tag === "OrchestrationCommandPreviouslyRejectedError" ? report("refused", error.detail) : report("failed", error.message)));
|
|
304428
|
+
});
|
|
304429
|
+
/**
|
|
304430
|
+
* One tick: list, apply each, acknowledge everything that got an answer.
|
|
304431
|
+
*
|
|
304432
|
+
* A signed-out owner is not an error to retry into the log every five
|
|
304433
|
+
* minutes; it is a state the desktop leaves when someone signs in, so it is
|
|
304434
|
+
* logged once at info and the tick ends. Any other listing or acknowledgement
|
|
304435
|
+
* failure is returned typed, and the intents stay pending on CMMD.
|
|
304436
|
+
*/
|
|
304437
|
+
function applyPendingLifecycleIntents(input, dependencies) {
|
|
304438
|
+
return gen(function* () {
|
|
304439
|
+
const intents = yield* dependencies.listPending();
|
|
304440
|
+
if (intents.length === 0) return;
|
|
304441
|
+
const answered = [];
|
|
304442
|
+
for (const intent of intents) if ((yield* applyOne(input.runtimeId, intent, dependencies)) !== "failed") answered.push({
|
|
304443
|
+
threadId: intent.threadId,
|
|
304444
|
+
requestedAt: intent.requestedAt
|
|
304445
|
+
});
|
|
304446
|
+
if (answered.length === 0) return;
|
|
304447
|
+
yield* dependencies.acknowledge(answered);
|
|
304448
|
+
}).pipe(catch_((error) => error.kind === "auth" ? logInfo("Lifecycle intents skipped: CMMD sign-in is required.", {
|
|
304449
|
+
runtimeId: input.runtimeId,
|
|
304450
|
+
code: error.code
|
|
304451
|
+
}) : fail(error)));
|
|
304452
|
+
}
|
|
304453
|
+
/**
|
|
304454
|
+
* One structured line per intent, so a row that "came back" after a wake can
|
|
304455
|
+
* be explained from the log: applied, refused by the decider, or spent by
|
|
304456
|
+
* newer activity.
|
|
304457
|
+
*/
|
|
304458
|
+
function logLifecycleIntentOutcome(outcome) {
|
|
304459
|
+
const message = `Lifecycle intent ${outcome.outcome}.`;
|
|
304460
|
+
return outcome.outcome === "refused" || outcome.outcome === "failed" ? logWarning$1(message, outcome) : logInfo(message, outcome);
|
|
304461
|
+
}
|
|
304462
|
+
//#endregion
|
|
304016
304463
|
//#region src/runtimeReplication/processOutboxItem.ts
|
|
304017
304464
|
function publicationMetricAttributes(item, outcome, failure) {
|
|
304018
304465
|
return {
|
|
@@ -304209,6 +304656,31 @@ const RuntimeReplicationLive = effect(RuntimeReplication, gen(function* () {
|
|
|
304209
304656
|
}).pipe(asVoid, catchCause((cause) => logError("Runtime replication reconciliation failed.", { cause })));
|
|
304210
304657
|
const heartbeat = enqueueAll.pipe(repeat(spaced("5 minutes")), forkScoped);
|
|
304211
304658
|
/**
|
|
304659
|
+
* Settle and un-settle requests a person recorded in CMMD while this
|
|
304660
|
+
* runtime was offline. The first tick runs at once, which is the
|
|
304661
|
+
* startup case (this phase starts after the orchestration reactors);
|
|
304662
|
+
* every heartbeat after that picks up requests made while awake. The
|
|
304663
|
+
* tick handles its own expected failures; the supervisor restarts the
|
|
304664
|
+
* schedule if it ever dies between ticks.
|
|
304665
|
+
*/
|
|
304666
|
+
const lifecycleIntents = runSupervisedRepeat({
|
|
304667
|
+
label: "Lifecycle intent applier",
|
|
304668
|
+
work: applyPendingLifecycleIntents({ runtimeId }, {
|
|
304669
|
+
listPending: () => client.listPendingLifecycleIntents({ runtimeId }),
|
|
304670
|
+
acknowledge: (intents) => client.acknowledgeLifecycleIntents({
|
|
304671
|
+
runtimeId,
|
|
304672
|
+
intents
|
|
304673
|
+
}),
|
|
304674
|
+
dispatch: engine.dispatch,
|
|
304675
|
+
getReadModel: engine.getReadModel,
|
|
304676
|
+
log: logLifecycleIntentOutcome
|
|
304677
|
+
}).pipe(catchCause((cause) => logError("Lifecycle intent tick failed.", {
|
|
304678
|
+
cause,
|
|
304679
|
+
runtimeId
|
|
304680
|
+
}))),
|
|
304681
|
+
interval: "5 minutes"
|
|
304682
|
+
}).pipe(forkScoped);
|
|
304683
|
+
/**
|
|
304212
304684
|
* Closes and reports whatever Active Hour interval is currently open,
|
|
304213
304685
|
* every 5 minutes -- the same cadence as the inventory heartbeat, not
|
|
304214
304686
|
* because the two are related, but because it is a reasonable default
|
|
@@ -304227,6 +304699,7 @@ const RuntimeReplicationLive = effect(RuntimeReplication, gen(function* () {
|
|
|
304227
304699
|
reactor,
|
|
304228
304700
|
providerRegistry.streamChanges.pipe(debounce$1("250 millis"), mapEffect$1(() => enqueueAll, { concurrency: 1 }), runDrain, forkScoped),
|
|
304229
304701
|
heartbeat,
|
|
304702
|
+
lifecycleIntents,
|
|
304230
304703
|
activeHourFlush,
|
|
304231
304704
|
gen(function* () {
|
|
304232
304705
|
yield* outbox.recover();
|
|
@@ -313627,7 +314100,7 @@ const MiscRuntimeLayerLive = mergeAll(AnalyticsServiceLayerLive, OpenLive, Serve
|
|
|
313627
314100
|
const RuntimeDependenciesWithoutPullRequestsLive = ReactorLayerLive.pipe(provideMerge(CheckpointingLayerLive), provideMerge(GitLayerLive), provideMerge(OrchestrationLayerLive), provideMerge(ProviderLayerLive), provideMerge(TerminalLayerLive), provideMerge(AgentBrowserManagerLive), provideMerge(mergeAll(ThreadDevRuntimeLive, DevTunnelLive.pipe(provide$1(ThreadDevRuntimeLive)))), provideMerge(PersistenceLayerLive), provideMerge(KeybindingsLive), provideMerge(ProviderRegistryLive), provideMerge(mergeAll(ServerSettingsLive, UsageServiceLive.pipe(provide$1(ServerSettingsLive), provide$1(UsageSessionLookupLive), provide$1(UsageRecordedSourceLive.pipe(provide$1(OrchestrationLayerLive), provide$1(RuntimeReplicationOutboxLive), provide$1(ProviderSessionRuntimeRepositoryLive), provide$1(TextGenerationSessionRepositoryLive)))))), provideMerge(WorkspaceLayerLive), provideMerge(WorkspaceReadinessStateLive), provideMerge(ProjectFaviconResolverLive), provideMerge(RepositoryIdentityResolverLive), provideMerge(ServerEnvironmentLive), provideMerge(AuthLayerLive), provideMerge(ServerSecretStoreLayerLive), provideMerge(mergeAll(CloudRedisCoordinationLive, CloudStateSyncLive.pipe(provide$1(PersistenceLayerLive)))), provideMerge(MiscRuntimeLayerLive));
|
|
313628
314101
|
const RuntimeDependenciesLive = pullRequestServiceFactoryLayer.pipe(provideMerge(RuntimeDependenciesWithoutPullRequestsLive), provideMerge(cmmdProjectIdentityResolverLive.pipe(provide$1(RuntimeDependenciesWithoutPullRequestsLive))), provideMerge(pullRequestProviderRuntimeLive));
|
|
313629
314102
|
const RuntimeServicesLive = ServerRuntimeStartupLive.pipe(provideMerge(RuntimeDependenciesLive));
|
|
313630
|
-
const makeRoutesLayer = mergeAll(authBearerBootstrapRouteLayer, authBootstrapRouteLayer, authCommandBearerBootstrapRouteLayer, authCommandBootstrapRouteLayer, authOAuthTokenExchangeRouteLayer, authWebSocketTicketRouteLayer, authCmmdOAuthDeviceRouteLayer, authCmmdOAuthTokenRouteLayer, authCmmdPasswordTokenRouteLayer, authClientsRevokeOthersRouteLayer, authClientsRevokeRouteLayer, authClientsRouteLayer, authLogoutRouteLayer, authPairingLinksRevokeRouteLayer, authPairingLinksRouteLayer, authPairingCredentialRouteLayer, authSessionRouteLayer, authWebSocketTokenRouteLayer, authWebLoginRouteLayer, authWebCallbackRouteLayer, desktopLocalWebBridgePublishRouteLayer, desktopLocalWebBridgeBootstrapRouteLayer, desktopRelayControlPlaneRouteLayer, apiDocsHtmlRouteLayer, apiDocsOpenApiRouteLayer, pulseSignalStateListRouteLayer, pulseSignalStateUpsertRouteLayer, cmmdProfileRouteLayer,
|
|
314103
|
+
const makeRoutesLayer = mergeAll(authBearerBootstrapRouteLayer, authBootstrapRouteLayer, authCommandBearerBootstrapRouteLayer, authCommandBootstrapRouteLayer, authOAuthTokenExchangeRouteLayer, authWebSocketTicketRouteLayer, authCmmdOAuthDeviceRouteLayer, authCmmdOAuthTokenRouteLayer, authCmmdPasswordTokenRouteLayer, authClientsRevokeOthersRouteLayer, authClientsRevokeRouteLayer, authClientsRouteLayer, authLogoutRouteLayer, authPairingLinksRevokeRouteLayer, authPairingLinksRouteLayer, authPairingCredentialRouteLayer, authSessionRouteLayer, authWebSocketTokenRouteLayer, authWebLoginRouteLayer, authWebCallbackRouteLayer, desktopLocalWebBridgePublishRouteLayer, desktopLocalWebBridgeBootstrapRouteLayer, desktopRelayControlPlaneRouteLayer, apiDocsHtmlRouteLayer, apiDocsOpenApiRouteLayer, pulseSignalStateListRouteLayer, pulseSignalStateUpsertRouteLayer, cmmdProfileRouteLayer, ...cmmdProxyRouteLayers, cmmdWorkIntakeRouteLayer, cmmdWsTokenRouteLayer, cmmdGetProjectCommentsRouteLayer, cmmdAddProjectCommentRouteLayer, cmmdUpdateProjectRouteLayer, cmmdUploadTaskAttachmentRouteLayer, cmmdUpdateTaskCommentRouteLayer, cmmdListWorkspaceMembersRouteLayer, cmmdAddProjectMemberRouteLayer, cmmdUpdateProjectAgentMemberAvatarRouteLayer, runtimeReplicationStatusRouteLayer, cmmdRefreshProviderUsageRouteLayer, cmmdForgeCloudProjectsListRouteLayer, cmmdForgeCloudProjectsEventsRouteLayer, cmmdForgeRuntimesEnsureRouteLayer, cmmdForgeRuntimesConnectRouteLayer, ownerRuntimeCodexReadinessRouteLayer, cmmdForgeRuntimesStatusRouteLayer, cmmdForgeRuntimesStartRouteLayer, cmmdForgeRuntimesStopRouteLayer, cmmdForgeRuntimesRecycleRouteLayer, cmmdForgeRuntimesUpdateCommitRouteLayer, cmmdForgeRuntimesDestroyRouteLayer, mobileProviderCatalogRouteLayer, attachmentsRouteLayer, orchestrationDispatchRouteLayer, orchestrationCmmdWorkRunEventRouteLayer, orchestrationAutomationStartThreadRouteLayer, orchestrationAutomationRebindRouteLayer, orchestrationAutomationTerminalReconcileRouteLayer, mobileGitRunStackedActionRouteLayer, pullRequestDiffRouteLayer, orchestrationSnapshotRouteLayer, localAutomationListRouteLayer, localAutomationCreateRouteLayer, localAutomationUpdateRouteLayer, localAutomationDeleteRouteLayer, localAutomationRunRouteLayer, otlpTracesProxyRouteLayer, devTunnelProxyRouteLayer, devTunnelLocalPortProxyRouteLayer, projectFaviconRouteLayer, serverEnvironmentRouteLayer, browserWebRtcReadinessRouteLayer, staticAndDevRouteLayer, githubStatusRouteLayer, githubAuthorizeUrlRouteLayer, githubDisconnectRouteLayer, githubReposRouteLayer, githubCloneRouteLayer, githubCloneJobStartRouteLayer, githubCloneJobStatusRouteLayer, githubRefreshCredentialsRouteLayer, githubToolConfirmationApproveRouteLayer, projectLinkGetRouteLayer, projectLinkListRouteLayer, projectLinkSetRouteLayer, projectLinkDeleteRouteLayer, cmmdWorkspacesRouteLayer, cmmdCampaignsRouteLayer, cmmdProjectLinksRouteLayer, cmmdEnsureGitHubProjectContextRouteLayer, cmmdProjectRepositoryEnsureRouteLayer, cmmdProjectsGetRouteLayer, cmmdProjectsCreateRouteLayer, workspaceReadinessRouteLayer, runtimeLivenessRouteLayer, claudeNativeGenerationProofRouteLayer, claudeUsageRouteLayer, codexRuntimeProviderReadinessRouteLayer, runtimeDiagnosticsRouteLayer, cloudFoldersRouteLayer, cloudProjectCreateRouteLayer, gitUrlCloneRouteLayer, websocketRpcRouteLayer).pipe(provide$1(browserApiCorsLayer));
|
|
313631
314104
|
const runServer = launch$1(unwrap(gen(function* () {
|
|
313632
314105
|
const config = yield* ServerConfig;
|
|
313633
314106
|
fixPath({ preferProcessPath: config.forgeCmmdRuntimeMode === true });
|