replicas-engine 0.1.987 → 0.1.989

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.
@@ -5,12 +5,12 @@ import {
5
5
  getCodexAspHost,
6
6
  restartCodexAspHost,
7
7
  restartCodexAspHostIfRunning
8
- } from "./chunk-D5B72SUV.js";
9
- import "./chunk-TYH3IEXZ.js";
10
- import "./chunk-KAJYMTYA.js";
11
- import "./chunk-2PMHC6IL.js";
8
+ } from "./chunk-VUUSZ5JS.js";
9
+ import "./chunk-LM4J2GLY.js";
10
+ import "./chunk-BAJGQWIO.js";
11
+ import "./chunk-TFUEJW43.js";
12
12
  import "./chunk-UZSNFLDQ.js";
13
- import "./chunk-QU4FXL4X.js";
13
+ import "./chunk-RZBMLP2H.js";
14
14
  import "./chunk-VEQXQN22.js";
15
15
  export {
16
16
  getCodexAspHost,
@@ -3,10 +3,10 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  execFileAsync
6
- } from "./chunk-2PMHC6IL.js";
6
+ } from "./chunk-TFUEJW43.js";
7
7
  import {
8
8
  isVersionBelow
9
- } from "./chunk-QU4FXL4X.js";
9
+ } from "./chunk-RZBMLP2H.js";
10
10
 
11
11
  // src/utils/codex-agent-env.ts
12
12
  function buildCodexAgentEnv(source = process.env) {
@@ -240,7 +240,7 @@ function getCodexModelProvider(method) {
240
240
  if (method === "foundry") return "azure";
241
241
  return method === "ollama" || method === "openai-compatible" ? "replicas_openai_compatible" : "openai";
242
242
  }
243
- var ENGINE_PACKAGE_VERSION = "0.1.987";
243
+ var ENGINE_PACKAGE_VERSION = "0.1.989";
244
244
  var INITIALIZE_METHOD = "initialize";
245
245
  var INITIALIZED_NOTIFICATION = "initialized";
246
246
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -3,18 +3,18 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  monolithRequest
6
- } from "./chunk-TYH3IEXZ.js";
6
+ } from "./chunk-LM4J2GLY.js";
7
7
  import {
8
8
  SUBPROCESS_MAX_BUFFER,
9
9
  execFileAsync
10
- } from "./chunk-2PMHC6IL.js";
10
+ } from "./chunk-TFUEJW43.js";
11
11
  import {
12
12
  extractCommandProtectionCommandText,
13
13
  findCommandProtectionGitLookups,
14
14
  findGitCommitSignals,
15
15
  findPrMergeSignals,
16
16
  parseCommandProtectionRequest
17
- } from "./chunk-QU4FXL4X.js";
17
+ } from "./chunk-RZBMLP2H.js";
18
18
 
19
19
  // src/services/command-protection-service.ts
20
20
  import { readFile, stat } from "fs/promises";
@@ -14,7 +14,7 @@ import {
14
14
  isValidAgentProvider,
15
15
  parsePosixEnvFile,
16
16
  readReplicasRuntimeEnv
17
- } from "./chunk-QU4FXL4X.js";
17
+ } from "./chunk-RZBMLP2H.js";
18
18
 
19
19
  // src/runtime-env-loader.ts
20
20
  import { readFileSync } from "fs";
@@ -3274,7 +3274,7 @@ replicas computer record stop
3274
3274
  replicas media upload /tmp/walkthrough.mp4 --name "<Project> walkthrough"
3275
3275
  \`\`\`
3276
3276
 
3277
- Keep the recording short (one to three minutes) and focused on the flow that proves the environment works. \`replicas media upload\` prints a chat embed line and a \`View in Replicas\` link ending in \`?media=<media-id>\`; keep both. The media id goes into the proposal, and the embed line goes into your final message. Follow \`MEDIA.md\` for anything shared outside the dashboard.
3277
+ Keep the recording short (one to three minutes) and focused on the flow that proves the environment works. \`replicas media upload\` prints a chat embed line and a \`View in Replicas\` link ending in \`?mode=media&media=<media-id>\`; keep both. The media id goes into the proposal, and the embed line goes into your final message. Follow \`MEDIA.md\` for anything shared outside the dashboard.
3278
3278
 
3279
3279
  Add screenshots of important states (a passing test run, the running app) with \`replicas computer screenshot\` and upload them the same way when they help the user trust the result.
3280
3280
 
@@ -3798,7 +3798,7 @@ For each media file, the CLI prints an embed line and a dashboard link:
3798
3798
 
3799
3799
  1. Images always print \`![filename](<public-url>)\`. This public, stable link works in Replicas chat, GitHub, and anywhere else Markdown images render. No flag is needed.
3800
3800
  2. Video and audio print \`Replicas chat embed: ![filename](<api-url>)\` by default; this authenticated URL renders inline in Replicas chat **only** \u2014 see below. \`--access public\` prints a public embed instead.
3801
- 3. \`View in Replicas: <deep-link>\` is a per-file dashboard URL of the form \`https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>\` that opens directly to that specific file.
3801
+ 3. \`View in Replicas: <deep-link>\` is a per-file dashboard URL of the form \`https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>\` that opens directly to that specific file.
3802
3802
 
3803
3803
  Match each "View in Replicas" line to the embed line directly above it \u2014 that's the deep link for that file.
3804
3804
 
@@ -3829,7 +3829,7 @@ Permanently delete an upload with \`replicas media delete <media-id>\`. The back
3829
3829
  | \`https://api.replicas.dev/v1/media/<id>\` (inside \`![\u2026](\u2026)\`) | Authenticated API redirect printed for private video, audio, and HTML \u2014 requires the Replicas chat session | **Only** in the Replicas chat reply. Nowhere else. |
3830
3830
  | \`https://replicas.dev/organizations/<organization-id>/media/<media-id>\` | Organization-only page printed by \`--access organization\` | Pull requests and other places where every viewer belongs to the Replicas organization. |
3831
3831
  | \`https://api.replicas.dev/v1/media/public/<id>/<token>\` | Public bearer URL printed for every image, and for video or audio with \`--access public\` | The Replicas chat reply and GitHub embeds. |
3832
- | \`https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>\` | Authenticated dashboard deep link that opens the media file in the workspace | Everywhere external: Slack, GitHub, GitLab, Linear, PR bodies, comments, emails. |
3832
+ | \`https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>\` | Authenticated dashboard deep link that opens the media file in the workspace | Everywhere external: Slack, GitHub, GitLab, Linear, PR bodies, comments, emails. |
3833
3833
 
3834
3834
  ### NEVER link the API redirect URL outside the Replicas chat reply
3835
3835
 
@@ -3848,10 +3848,10 @@ This rule has no exceptions:
3848
3848
  For an organization-only HTML page, use the \`Forge link\` printed by \`--access organization\`. For other authenticated media references, use the dashboard form:
3849
3849
 
3850
3850
  \`\`\`
3851
- https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>
3851
+ https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>
3852
3852
  \`\`\`
3853
3853
 
3854
- The \`media=<media-id>\` query param opens that specific file in the workspace.
3854
+ The \`mode=media&media=<media-id>\` query params open that specific file in the workspace.
3855
3855
 
3856
3856
  When you have a specific file in mind, never link the bare workspace URL without the \`media=<id>\` param.
3857
3857
 
@@ -3861,6 +3861,8 @@ Always render as a markdown / mrkdwn hyperlink labeled **View in Replicas** \u20
3861
3861
 
3862
3862
  Include each markdown embed line **verbatim** where you want that file to render inline. The chat substitutes each one with an embedded image, video, or audio player. For HTML, use the printed \`HTML page\` link. Multiple embeds can appear in a single reply.
3863
3863
 
3864
+ Never reply with only dashboard links (for example a "Links:" list of \`?mode=media&media=\` URLs) in place of the embeds: a dashboard link renders as plain text, so the user sees nothing inline. This applies even when the task came from Slack, Linear, GitHub, or GitLab; the chat reply still gets the embeds.
3865
+
3864
3866
  After (or alongside) the embeds, include a \`[View in Canvas](<deep-link>)\` hyperlink for each file using the per-file dashboard URL printed by the CLI as **View in Replicas**. Keep that URL unchanged so it opens the specific media item in the workspace's Canvas. External messages still label this dashboard link **View in Replicas**.
3865
3867
 
3866
3868
  ## On external platforms: embed the file AND link the dashboard
@@ -3868,7 +3870,7 @@ After (or alongside) the embeds, include a \`[View in Canvas](<deep-link>)\` hyp
3868
3870
  After \`replicas media upload\` succeeds, external delivery has two required follow-up steps for every file:
3869
3871
 
3870
3872
  1. **Use the destination's inline representation:** upload the raw bytes to Slack, Linear, or GitLab; embed the image's printed public link on GitHub.
3871
- 2. **Link the Replicas dashboard deep link** (\`?media=<id>\` form) so the user can jump straight to the file in the workspace.
3873
+ 2. **Link the Replicas dashboard deep link** (\`?mode=media&media=<id>\` form) so the user can jump straight to the file in the workspace.
3872
3874
 
3873
3875
  A dashboard link alone is not enough. An embed without the dashboard link is not enough. Do both.
3874
3876
 
@@ -3897,7 +3899,7 @@ await replicas.slack.call('files.completeUploadExternal', {
3897
3899
  files: [{ id: reservation.file_id, title: 'Screenshot' }],
3898
3900
  channel_id: 'CHANNEL_ID',
3899
3901
  thread_ts: 'THREAD_TS',
3900
- initial_comment: '<https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>|View in Replicas>',
3902
+ initial_comment: '<https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>|View in Replicas>',
3901
3903
  });
3902
3904
  \`\`\`
3903
3905
 
@@ -3920,7 +3922,7 @@ Use \`jq\` to build the JSON bodies \u2014 the GraphQL variables (\`size\`, \`fi
3920
3922
  FILE=/abs/path/to/screenshot.png
3921
3923
  FILENAME=$(basename "$FILE")
3922
3924
  SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
3923
- CONTENT_TYPE=image/png
3925
+ CONTENT_TYPE=image/png # the file's real MIME type, e.g. video/mp4 for a recording
3924
3926
  ISSUE_UUID=... # the Linear issue's UUID
3925
3927
  MEDIA_ID=... # the media ID printed by \`replicas media upload\`
3926
3928
 
@@ -3957,7 +3959,7 @@ curl -s -X PUT "$UPLOAD_URL" \\
3957
3959
  --data-binary @"$FILE"
3958
3960
 
3959
3961
  # 3. Reference assetUrl inline in the comment body, alongside the dashboard link.
3960
- BODY=$(printf '![screenshot](%s)\\n\\n[View in Replicas](https://app.replicas.dev/workspaces/%s?media=%s)' \\
3962
+ BODY=$(printf '![screenshot](%s)\\n\\n[View in Replicas](https://app.replicas.dev/workspaces/%s?mode=media&media=%s)' \\
3961
3963
  "$ASSET_URL" "$REPLICAS_WORKSPACE_ID" "$MEDIA_ID")
3962
3964
 
3963
3965
  jq -n \\
@@ -3969,6 +3971,8 @@ jq -n \\
3969
3971
  }' | linear_graphql
3970
3972
  \`\`\`
3971
3973
 
3974
+ For a recording, upload the MP4 with its own MIME type, then upload a poster frame (\`ffmpeg -i /tmp/demo.mp4 -frames:v 1 /tmp/demo-poster.png\`) the same way as \`image/png\` and link it: \`[![Demo recording](<poster-asset-url>)](<recording-asset-url>)\`.
3975
+
3972
3976
  The same flow works for issue bodies (use \`issueCreate\` / \`issueUpdate\` with the same markdown body).
3973
3977
 
3974
3978
  Never paste the \`api.replicas.dev/v1/media/<id>\` URL into a Linear body or comment \u2014 it will render as a broken image to anyone outside your Replicas chat.
@@ -4008,7 +4012,7 @@ Do **not** commit screenshots to the repo, use placeholder URLs, expose the auth
4008
4012
 
4009
4013
  GitLab supports native project Markdown uploads. For a GitLab destination, always upload the media to Replicas first, then POST the same original file to the repository's \`/projects/:id/uploads\` API using the workspace GitLab credential. Insert the returned \`markdown\` value into the merge request body or comment and include the Replicas dashboard link. Image uploads render inline; MP4, MOV, and WebM uploads render as inline video players.
4010
4014
 
4011
- Do not use a Replicas public link for GitLab when the native project upload succeeds; native uploads preserve project access controls.
4015
+ Do not use a Replicas public link for GitLab when the native project upload succeeds; native uploads preserve project access controls. \`replicas.gitlab.request\` only sends JSON and cannot POST multipart file bytes, so without another supported upload path use the GitHub flow above instead: the image's printed public embed, and a poster linked to the recording's **View in Replicas** URL.
4012
4016
 
4013
4017
  ## Recording defaults
4014
4018
 
@@ -4056,7 +4060,7 @@ replicas media upload chart-a.svg chart-b.svg --name "Latency chart" --name "Err
4056
4060
  var MEDIA_ABILITY = {
4057
4061
  label: "Media",
4058
4062
  description: "Deliver media to Replicas and destination workflows with inline uploads.",
4059
- bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips, or HTML recap pages \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms",
4063
+ bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips, or HTML recap pages \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms. Paste the printed `![\u2026](\u2026)` embeds in your chat reply, never only dashboard links, and upload the file itself to Slack, Linear, or GitLab",
4060
4064
  section: SECTION7,
4061
4065
  referenceFile: { name: "MEDIA.md", content: REFERENCE7 }
4062
4066
  };
@@ -7180,10 +7184,6 @@ function detectLanguageByPath(filePath) {
7180
7184
  }
7181
7185
 
7182
7186
  // ../shared/src/context-usage.ts
7183
- var CODEX_CATEGORY_COLORS = {
7184
- input: "#3eeba3",
7185
- output: "#56b6c2"
7186
- };
7187
7187
  function isRecord2(value) {
7188
7188
  return typeof value === "object" && value !== null;
7189
7189
  }
@@ -7214,9 +7214,7 @@ function normalizeAutoCompactThreshold(threshold, maxTokens) {
7214
7214
  return clampPercentage(value);
7215
7215
  }
7216
7216
  function clampTokensToWindow(rawTokens, maxTokens) {
7217
- if (!maxTokens || maxTokens <= 0) return { totalTokens: rawTokens };
7218
- if (rawTokens <= maxTokens) return { totalTokens: rawTokens };
7219
- return { totalTokens: maxTokens, totalProcessedTokens: rawTokens };
7217
+ return maxTokens && maxTokens > 0 ? Math.min(rawTokens, maxTokens) : rawTokens;
7220
7218
  }
7221
7219
  function compactCategories(categories) {
7222
7220
  return categories.filter((category) => Boolean(category && category.tokens > 0)).map((category) => ({
@@ -7228,16 +7226,12 @@ function buildCodexTokenUsageContextUsagePayload(usage) {
7228
7226
  const maxTokens = usage.modelContextWindow;
7229
7227
  const inputTokens = usage.last.inputTokens;
7230
7228
  const outputTokens = usage.last.outputTokens;
7231
- const lastTurnTokens = usage.last.totalTokens;
7232
- const { totalTokens } = clampTokensToWindow(lastTurnTokens, maxTokens);
7233
- const cumulativeTotalTokens = usage.total?.totalTokens ?? null;
7234
- const totalProcessedTokens = cumulativeTotalTokens !== null && cumulativeTotalTokens > totalTokens ? cumulativeTotalTokens : clampTokensToWindow(lastTurnTokens, maxTokens).totalProcessedTokens;
7229
+ const totalTokens = clampTokensToWindow(usage.last.totalTokens, maxTokens);
7235
7230
  return {
7236
7231
  provider: "codex",
7237
7232
  source: "codex_token_count",
7238
7233
  ...usage.model !== void 0 ? { model: usage.model } : {},
7239
7234
  totalTokens,
7240
- ...totalProcessedTokens !== void 0 ? { totalProcessedTokens } : {},
7241
7235
  maxTokens,
7242
7236
  rawMaxTokens: maxTokens,
7243
7237
  percentage: percentage(totalTokens, maxTokens),
@@ -7246,23 +7240,14 @@ function buildCodexTokenUsageContextUsagePayload(usage) {
7246
7240
  {
7247
7241
  name: "Input context",
7248
7242
  tokens: inputTokens,
7249
- percentage: percentage(inputTokens, maxTokens),
7250
- color: CODEX_CATEGORY_COLORS.input
7243
+ percentage: percentage(inputTokens, maxTokens)
7251
7244
  },
7252
7245
  {
7253
7246
  name: "Generated output",
7254
7247
  tokens: outputTokens,
7255
- percentage: percentage(outputTokens, maxTokens),
7256
- color: CODEX_CATEGORY_COLORS.output
7248
+ percentage: percentage(outputTokens, maxTokens)
7257
7249
  }
7258
7250
  ]),
7259
- apiUsage: {
7260
- inputTokens,
7261
- outputTokens,
7262
- ...usage.last.cachedInputTokens !== null && usage.last.cachedInputTokens !== void 0 ? { cachedInputTokens: usage.last.cachedInputTokens } : {},
7263
- ...usage.last.reasoningOutputTokens !== null && usage.last.reasoningOutputTokens !== void 0 ? { reasoningOutputTokens: usage.last.reasoningOutputTokens } : {},
7264
- ...cumulativeTotalTokens !== null ? { totalTokens: cumulativeTotalTokens } : {}
7265
- },
7266
7251
  updatedAt: usage.updatedAt
7267
7252
  };
7268
7253
  }
@@ -7288,10 +7273,7 @@ function coerceContextUsagePayload(payload, timestamp) {
7288
7273
  const reportedMaxTokens = numberOrNull(payload.maxTokens);
7289
7274
  const { maxTokens, usedKnownWindow } = resolveClaudeContextWindow(provider, model, reportedMaxTokens);
7290
7275
  const rawMaxTokens = usedKnownWindow ? maxTokens : numberOrNull(payload.rawMaxTokens);
7291
- const clamped = clampTokensToWindow(rawTotalTokens, maxTokens);
7292
- const totalTokens = clamped.totalTokens;
7293
- const payloadTotalProcessedTokens = numberOrNull(payload.totalProcessedTokens);
7294
- const totalProcessedTokens = payloadTotalProcessedTokens !== null ? payloadTotalProcessedTokens : clamped.totalProcessedTokens ?? null;
7276
+ const totalTokens = clampTokensToWindow(rawTotalTokens, maxTokens);
7295
7277
  const source = payload.source === "codex_token_count" || payload.source === "claude_usage" || payload.source === "provider_usage" ? payload.source : "claude_context";
7296
7278
  const categories = Array.isArray(payload.categories) ? compactCategories(payload.categories.map((item) => {
7297
7279
  if (!isRecord2(item)) return null;
@@ -7299,23 +7281,13 @@ function coerceContextUsagePayload(payload, timestamp) {
7299
7281
  const tokens = numberOrNull(item.tokens);
7300
7282
  const categoryPercentage = numberOrNull(item.percentage);
7301
7283
  if (!name || tokens === null || categoryPercentage === null) return null;
7284
+ if (item.isDeferred === true || name === "Free space" || name === "Autocompact buffer") return null;
7302
7285
  return {
7303
7286
  name,
7304
7287
  tokens,
7305
- percentage: usedKnownWindow ? percentage(tokens, maxTokens) : categoryPercentage,
7306
- ...typeof item.color === "string" ? { color: item.color } : {},
7307
- ...typeof item.isDeferred === "boolean" ? { isDeferred: item.isDeferred } : {}
7288
+ percentage: usedKnownWindow ? percentage(tokens, maxTokens) : categoryPercentage
7308
7289
  };
7309
7290
  })) : [];
7310
- const apiUsage = isRecord2(payload.apiUsage) ? {
7311
- ...numberOrNull(payload.apiUsage.inputTokens) !== null ? { inputTokens: numberOrNull(payload.apiUsage.inputTokens) } : {},
7312
- ...numberOrNull(payload.apiUsage.outputTokens) !== null ? { outputTokens: numberOrNull(payload.apiUsage.outputTokens) } : {},
7313
- ...numberOrNull(payload.apiUsage.cacheCreationInputTokens) !== null ? { cacheCreationInputTokens: numberOrNull(payload.apiUsage.cacheCreationInputTokens) } : {},
7314
- ...numberOrNull(payload.apiUsage.cacheReadInputTokens) !== null ? { cacheReadInputTokens: numberOrNull(payload.apiUsage.cacheReadInputTokens) } : {},
7315
- ...numberOrNull(payload.apiUsage.cachedInputTokens) !== null ? { cachedInputTokens: numberOrNull(payload.apiUsage.cachedInputTokens) } : {},
7316
- ...numberOrNull(payload.apiUsage.reasoningOutputTokens) !== null ? { reasoningOutputTokens: numberOrNull(payload.apiUsage.reasoningOutputTokens) } : {},
7317
- ...numberOrNull(payload.apiUsage.totalTokens) !== null ? { totalTokens: numberOrNull(payload.apiUsage.totalTokens) } : {}
7318
- } : null;
7319
7291
  const compactsAutomatically = typeof payload.compactsAutomatically === "boolean" ? payload.compactsAutomatically : void 0;
7320
7292
  const autoCompactThreshold = normalizeAutoCompactThreshold(payload.autoCompactThreshold, maxTokens);
7321
7293
  return {
@@ -7323,14 +7295,12 @@ function coerceContextUsagePayload(payload, timestamp) {
7323
7295
  source,
7324
7296
  ...model ? { model } : {},
7325
7297
  totalTokens,
7326
- ...totalProcessedTokens !== null ? { totalProcessedTokens } : {},
7327
7298
  maxTokens,
7328
7299
  rawMaxTokens,
7329
7300
  percentage: usedKnownWindow ? percentage(totalTokens, maxTokens) : clampPercentage(percentageValue),
7330
7301
  ...compactsAutomatically !== void 0 ? { compactsAutomatically } : {},
7331
7302
  ...autoCompactThreshold !== null ? { autoCompactThreshold } : {},
7332
7303
  categories,
7333
- apiUsage,
7334
7304
  updatedAt: typeof payload.updatedAt === "string" ? payload.updatedAt : timestamp
7335
7305
  };
7336
7306
  }
@@ -7341,20 +7311,15 @@ function codexTokenCountToContextUsage(event) {
7341
7311
  if (!info) return null;
7342
7312
  const lastUsage = isRecord2(info.last_token_usage) ? info.last_token_usage : null;
7343
7313
  if (!lastUsage) return null;
7344
- const totalUsage = isRecord2(info.total_token_usage) ? info.total_token_usage : null;
7345
7314
  const maxTokens = numberOrNull(info.model_context_window);
7346
7315
  const inputTokens = numberOrNull(lastUsage.input_tokens) ?? 0;
7347
7316
  const outputTokens = numberOrNull(lastUsage.output_tokens) ?? 0;
7348
- const cumulativeTotalTokens = numberOrNull(totalUsage?.total_tokens);
7349
7317
  return buildCodexTokenUsageContextUsagePayload({
7350
7318
  last: {
7351
7319
  inputTokens,
7352
7320
  outputTokens,
7353
- totalTokens: numberOrNull(lastUsage.total_tokens) ?? inputTokens + outputTokens,
7354
- cachedInputTokens: numberOrNull(lastUsage.cached_input_tokens),
7355
- reasoningOutputTokens: numberOrNull(lastUsage.reasoning_output_tokens)
7321
+ totalTokens: numberOrNull(lastUsage.total_tokens) ?? inputTokens + outputTokens
7356
7322
  },
7357
- total: cumulativeTotalTokens !== null ? { totalTokens: cumulativeTotalTokens } : null,
7358
7323
  modelContextWindow: maxTokens,
7359
7324
  updatedAt: event.timestamp
7360
7325
  });
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  HOOK_EXEC_MAX_BUFFER_BYTES
6
- } from "./chunk-QU4FXL4X.js";
6
+ } from "./chunk-RZBMLP2H.js";
7
7
 
8
8
  // src/utils/exec.ts
9
9
  import { exec, execFile } from "child_process";
@@ -5,15 +5,15 @@ import {
5
5
  ENGINE_ENV,
6
6
  monolithRequest,
7
7
  setAgentCredentialSnapshot
8
- } from "./chunk-TYH3IEXZ.js";
8
+ } from "./chunk-LM4J2GLY.js";
9
9
  import {
10
10
  AppServerProcess,
11
11
  buildCodexAgentEnv
12
- } from "./chunk-KAJYMTYA.js";
12
+ } from "./chunk-BAJGQWIO.js";
13
13
  import {
14
14
  SUBPROCESS_MAX_BUFFER,
15
15
  execFileAsync
16
- } from "./chunk-2PMHC6IL.js";
16
+ } from "./chunk-TFUEJW43.js";
17
17
  import {
18
18
  isRecord
19
19
  } from "./chunk-UZSNFLDQ.js";
@@ -27,7 +27,7 @@ import {
27
27
  listOpenAICompatibleModels,
28
28
  readOllamaAuthEnv,
29
29
  resolveOpenAICompatibleModelsUrl
30
- } from "./chunk-QU4FXL4X.js";
30
+ } from "./chunk-RZBMLP2H.js";
31
31
 
32
32
  // src/managers/codex-token-manager.ts
33
33
  import { promises as fs } from "fs";
@@ -260,7 +260,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
260
260
  await this.applyCredentialUpdate(++this.credentialGeneration, async () => {
261
261
  await this.applyCredentialsResponse(data);
262
262
  setAgentCredentialSnapshot("codex", data);
263
- const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-LOTCGOVD.js");
263
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-O3JY7A6A.js");
264
264
  await restartCodexAspHostIfRunning2();
265
265
  });
266
266
  await this.start(true);
@@ -280,7 +280,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
280
280
  await this.applyCredentialUpdate(generation, async () => {
281
281
  await this.applyCredentialsResponse(data);
282
282
  if (restartOnChange && CODEX_AUTH_ENV_KEYS.some((key, index) => process.env[key] !== previousEnv[index])) {
283
- const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-LOTCGOVD.js");
283
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-O3JY7A6A.js");
284
284
  await restartCodexAspHostIfRunning2();
285
285
  }
286
286
  setAgentCredentialSnapshot("codex", data);
@@ -5,7 +5,7 @@ import {
5
5
  extractCommandProtectionCommandText,
6
6
  isRecord,
7
7
  parseCodeHostPrUrl
8
- } from "./chunk-QU4FXL4X.js";
8
+ } from "./chunk-RZBMLP2H.js";
9
9
 
10
10
  // src/services/published-pull-request-urls.ts
11
11
  function publishedPullRequestUrls(result) {
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  evaluateCommandProtection
6
- } from "./chunk-G6QBYUZR.js";
7
- import "./chunk-TYH3IEXZ.js";
8
- import "./chunk-2PMHC6IL.js";
6
+ } from "./chunk-JBMI42EJ.js";
7
+ import "./chunk-LM4J2GLY.js";
8
+ import "./chunk-TFUEJW43.js";
9
9
  import {
10
10
  isRecord
11
11
  } from "./chunk-UZSNFLDQ.js";
12
- import "./chunk-QU4FXL4X.js";
12
+ import "./chunk-RZBMLP2H.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/command-protection-hook.ts
@@ -7,12 +7,12 @@ import {
7
7
  import {
8
8
  AppServerProcess,
9
9
  buildCodexAgentEnv
10
- } from "./chunk-KAJYMTYA.js";
11
- import "./chunk-2PMHC6IL.js";
10
+ } from "./chunk-BAJGQWIO.js";
11
+ import "./chunk-TFUEJW43.js";
12
12
  import {
13
13
  AGENT,
14
14
  headlessAgentRequestSchema
15
- } from "./chunk-QU4FXL4X.js";
15
+ } from "./chunk-RZBMLP2H.js";
16
16
  import "./chunk-VEQXQN22.js";
17
17
 
18
18
  // src/headless-agent.ts
package/dist/src/index.js CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  reportCommandProtectionBlock,
33
33
  resolveDiffBase,
34
34
  runGitCommand
35
- } from "./chunk-G6QBYUZR.js";
35
+ } from "./chunk-JBMI42EJ.js";
36
36
  import {
37
37
  ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
38
38
  AGENT_MESSAGE_DELTA_METHOD,
@@ -57,7 +57,7 @@ import {
57
57
  } from "./chunk-P73LGPQO.js";
58
58
  import {
59
59
  publishedPullRequestUrls
60
- } from "./chunk-5EHMJ4OT.js";
60
+ } from "./chunk-WYERDOJD.js";
61
61
  import {
62
62
  BaseRefreshManager,
63
63
  CodexAspAuthMethodChangedError,
@@ -72,7 +72,7 @@ import {
72
72
  refreshDelayMs,
73
73
  restartCodexAspHost,
74
74
  routineRefreshExclusions
75
- } from "./chunk-D5B72SUV.js";
75
+ } from "./chunk-VUUSZ5JS.js";
76
76
  import {
77
77
  ENGINE_ENV,
78
78
  monolithRequest,
@@ -80,16 +80,16 @@ import {
80
80
  readRuntimeEnvFile,
81
81
  reloadEngineEnv,
82
82
  setAgentCredentialSnapshot
83
- } from "./chunk-TYH3IEXZ.js";
83
+ } from "./chunk-LM4J2GLY.js";
84
84
  import {
85
85
  AspClient,
86
86
  getCodexModelProvider
87
- } from "./chunk-KAJYMTYA.js";
87
+ } from "./chunk-BAJGQWIO.js";
88
88
  import {
89
89
  SUBPROCESS_MAX_BUFFER,
90
90
  execAsync,
91
91
  execFileAsync
92
- } from "./chunk-2PMHC6IL.js";
92
+ } from "./chunk-TFUEJW43.js";
93
93
  import {
94
94
  isRecord as isRecord2
95
95
  } from "./chunk-UZSNFLDQ.js";
@@ -315,7 +315,7 @@ import {
315
315
  workspaceCredentialProviderSchema,
316
316
  workspaceTokenRequestSchema,
317
317
  workspaceTokenResponseSchema
318
- } from "./chunk-QU4FXL4X.js";
318
+ } from "./chunk-RZBMLP2H.js";
319
319
  import {
320
320
  cloneMcpConfig,
321
321
  ensureCompatibilityImports,
@@ -14392,32 +14392,23 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
14392
14392
  const reportedMaxTokens = Number.isFinite(usage.maxTokens) ? usage.maxTokens : null;
14393
14393
  const knownMaxTokens = getClaudeModelContextWindow(usage.model);
14394
14394
  const maxTokens = knownMaxTokens ?? reportedMaxTokens;
14395
- const clamped = clampTokensToWindow(usage.totalTokens, maxTokens);
14395
+ const totalTokens = clampTokensToWindow(usage.totalTokens, maxTokens);
14396
14396
  const autoCompactThreshold = normalizeAutoCompactThreshold(usage.autoCompactThreshold, maxTokens);
14397
14397
  return {
14398
14398
  provider: "claude",
14399
14399
  source: "claude_context",
14400
14400
  model: usage.model,
14401
- totalTokens: clamped.totalTokens,
14402
- ...clamped.totalProcessedTokens !== void 0 ? { totalProcessedTokens: clamped.totalProcessedTokens } : {},
14401
+ totalTokens,
14403
14402
  maxTokens,
14404
14403
  rawMaxTokens: knownMaxTokens ?? (Number.isFinite(usage.rawMaxTokens) ? usage.rawMaxTokens : maxTokens),
14405
- percentage: percentage(clamped.totalTokens, maxTokens),
14404
+ percentage: percentage(totalTokens, maxTokens),
14406
14405
  compactsAutomatically: usage.isAutoCompactEnabled === true,
14407
14406
  ...autoCompactThresholdField(autoCompactThreshold),
14408
- categories: usage.categories.map((category) => ({
14407
+ categories: usage.categories.filter((category) => category.kind === "used").map((category) => ({
14409
14408
  name: category.name,
14410
14409
  tokens: category.tokens,
14411
- percentage: percentage(category.tokens, maxTokens),
14412
- color: category.color,
14413
- ...category.isDeferred !== void 0 ? { isDeferred: category.isDeferred } : {}
14410
+ percentage: percentage(category.tokens, maxTokens)
14414
14411
  })),
14415
- apiUsage: usage.apiUsage ? {
14416
- inputTokens: usage.apiUsage.input_tokens,
14417
- outputTokens: usage.apiUsage.output_tokens,
14418
- cacheCreationInputTokens: usage.apiUsage.cache_creation_input_tokens,
14419
- cacheReadInputTokens: usage.apiUsage.cache_read_input_tokens
14420
- } : null,
14421
14412
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
14422
14413
  };
14423
14414
  }
@@ -16404,12 +16395,7 @@ ${text.slice(-24e3)}`
16404
16395
  last: {
16405
16396
  inputTokens: tokenUsage.last.inputTokens,
16406
16397
  outputTokens: tokenUsage.last.outputTokens,
16407
- totalTokens: tokenUsage.last.totalTokens,
16408
- cachedInputTokens: tokenUsage.last.cachedInputTokens,
16409
- reasoningOutputTokens: tokenUsage.last.reasoningOutputTokens
16410
- },
16411
- total: {
16412
- totalTokens: tokenUsage.total.totalTokens
16398
+ totalTokens: tokenUsage.last.totalTokens
16413
16399
  },
16414
16400
  updatedAt
16415
16401
  });
@@ -16514,12 +16500,6 @@ var CURSOR_CANCEL_TIMEOUT_MS = 1e4;
16514
16500
  var CURSOR_RECONNECT_NOTICE_DELAY_MS = 15e3;
16515
16501
  var TURN_ABORTED = /* @__PURE__ */ Symbol("cursor-turn-aborted");
16516
16502
  var CURSOR_COMPOSER_CONTEXT_WINDOW = 2e5;
16517
- var CURSOR_CATEGORY_COLORS = {
16518
- input: "#3eeba3",
16519
- cacheRead: "#61afef",
16520
- cacheWrite: "#e5c07b",
16521
- output: "#56b6c2"
16522
- };
16523
16503
  var CURSOR_TRANSPORT_ERROR_PATTERNS = [
16524
16504
  /connection failed/,
16525
16505
  /connection stalled/,
@@ -16879,31 +16859,27 @@ ${instructions}
16879
16859
  if (rawTotalTokens <= 0) return;
16880
16860
  this.onUsageUpdate(update, (/* @__PURE__ */ new Date()).toISOString());
16881
16861
  const maxTokens = CURSOR_COMPOSER_CONTEXT_WINDOW;
16882
- const { totalTokens, totalProcessedTokens } = clampTokensToWindow(rawTotalTokens, maxTokens);
16862
+ const totalTokens = clampTokensToWindow(rawTotalTokens, maxTokens);
16883
16863
  const categories = [
16884
16864
  {
16885
16865
  name: "Input",
16886
16866
  tokens: inputTokens,
16887
- percentage: percentage(inputTokens, maxTokens),
16888
- color: CURSOR_CATEGORY_COLORS.input
16867
+ percentage: percentage(inputTokens, maxTokens)
16889
16868
  },
16890
16869
  {
16891
16870
  name: "Cache read",
16892
16871
  tokens: cacheReadTokens,
16893
- percentage: percentage(cacheReadTokens, maxTokens),
16894
- color: CURSOR_CATEGORY_COLORS.cacheRead
16872
+ percentage: percentage(cacheReadTokens, maxTokens)
16895
16873
  },
16896
16874
  {
16897
16875
  name: "Cache write",
16898
16876
  tokens: cacheWriteTokens,
16899
- percentage: percentage(cacheWriteTokens, maxTokens),
16900
- color: CURSOR_CATEGORY_COLORS.cacheWrite
16877
+ percentage: percentage(cacheWriteTokens, maxTokens)
16901
16878
  },
16902
16879
  {
16903
16880
  name: "Output",
16904
16881
  tokens: outputTokens,
16905
- percentage: percentage(outputTokens, maxTokens),
16906
- color: CURSOR_CATEGORY_COLORS.output
16882
+ percentage: percentage(outputTokens, maxTokens)
16907
16883
  }
16908
16884
  ].filter((category) => category.tokens > 0);
16909
16885
  const payload = {
@@ -16911,18 +16887,11 @@ ${instructions}
16911
16887
  source: "provider_usage",
16912
16888
  model: this.activeModel,
16913
16889
  totalTokens,
16914
- ...totalProcessedTokens !== void 0 ? { totalProcessedTokens } : {},
16915
16890
  maxTokens,
16916
16891
  rawMaxTokens: maxTokens,
16917
16892
  percentage: percentage(totalTokens, maxTokens),
16918
16893
  compactsAutomatically: true,
16919
16894
  categories,
16920
- apiUsage: {
16921
- inputTokens,
16922
- outputTokens,
16923
- cacheReadInputTokens: cacheReadTokens,
16924
- cacheCreationInputTokens: cacheWriteTokens
16925
- },
16926
16895
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
16927
16896
  };
16928
16897
  this.historyFile.append(this.emitContextUsage(payload));
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  publishedPullRequestUrls
6
- } from "./chunk-5EHMJ4OT.js";
6
+ } from "./chunk-WYERDOJD.js";
7
7
  import {
8
8
  isRecord
9
9
  } from "./chunk-UZSNFLDQ.js";
10
10
  import {
11
11
  shouldRefreshPullRequests
12
- } from "./chunk-QU4FXL4X.js";
12
+ } from "./chunk-RZBMLP2H.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/services/post-tool-pr-notifier.ts
@@ -9,7 +9,7 @@ import {
9
9
  spawnSubagentRequestSchema,
10
10
  subagentResponseSchema,
11
11
  waitSubagentRequestSchema
12
- } from "./chunk-QU4FXL4X.js";
12
+ } from "./chunk-RZBMLP2H.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/subagent-mcp.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.987",
3
+ "version": "0.1.989",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",