@p4code/cli 0.0.50 → 0.0.51

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.
Files changed (88) hide show
  1. package/dist/bin.mjs +486 -7
  2. package/dist/client/assets/{DiffPanel-BUvVWIMX.js → DiffPanel-4ZPfw-bt.js} +3 -3
  3. package/dist/client/assets/{FilePreviewPanel-Bk7x7hMd.js → FilePreviewPanel-DPl3V4qz.js} +5 -5
  4. package/dist/client/assets/PreviewPanel-DENxqydi.js +2 -0
  5. package/dist/client/assets/{angular-html-CvITUhcj.js → angular-html-SfFqn_n1.js} +2 -2
  6. package/dist/client/assets/{angular-ts-CI8oh2Bi.js → angular-ts-TqTMcSgN.js} +2 -2
  7. package/dist/client/assets/{apl-BewkNmrv.js → apl-DvTVLZcC.js} +2 -2
  8. package/dist/client/assets/arrow-right-BHEVGFLQ.js +2 -0
  9. package/dist/client/assets/{astro-CNN681lo.js → astro-DEpzE1sb.js} +2 -2
  10. package/dist/client/assets/{blade-X4RszKFf.js → blade-Brgi-xhV.js} +2 -2
  11. package/dist/client/assets/{c-C8AJe2jK.js → c-7H0fCJJT.js} +2 -2
  12. package/dist/client/assets/{cobol-DQjALrRk.js → cobol-Cq_E3Ld9.js} +2 -2
  13. package/dist/client/assets/{coffee-uHbL69mO.js → coffee-DpUX5Xcz.js} +2 -2
  14. package/dist/client/assets/{cpp-D3rb3O4A.js → cpp-BEjZmHLc.js} +2 -2
  15. package/dist/client/assets/{crystal-spyqFjYj.js → crystal-CycEJw4X.js} +2 -2
  16. package/dist/client/assets/{css-CbxXkRaq.js → css-y3Oj4fDi.js} +2 -2
  17. package/dist/client/assets/{edge-YESgrh6X.js → edge-DIFYHFsA.js} +2 -2
  18. package/dist/client/assets/{elixir-7069ioPL.js → elixir-raLzjUMQ.js} +2 -2
  19. package/dist/client/assets/{elm-Eb4zNBLt.js → elm-CZsXcOy1.js} +2 -2
  20. package/dist/client/assets/{erb-Ddb27xlO.js → erb-DhXjIste.js} +2 -2
  21. package/dist/client/assets/{fileCommentAnnotations-OW7TQ0uO.js → fileCommentAnnotations-DkadV_kZ.js} +2 -2
  22. package/dist/client/assets/{git-rebase-CdERns2w.js → git-rebase-CZvi6-AX.js} +2 -2
  23. package/dist/client/assets/{glimmer-js-C6s5Isxr.js → glimmer-js-N_UF0Pmi.js} +2 -2
  24. package/dist/client/assets/{glimmer-ts-BV7NBmEc.js → glimmer-ts-Cxd1tQNi.js} +2 -2
  25. package/dist/client/assets/{glsl-jd9QEV4q.js → glsl-B8RUupmi.js} +2 -2
  26. package/dist/client/assets/{graphql-CXqIl6Zm.js → graphql-Cz2mi8GF.js} +2 -2
  27. package/dist/client/assets/{hack-lLvPp6HR.js → hack-DD3q-ECT.js} +2 -2
  28. package/dist/client/assets/{haml-DfPUmRcz.js → haml-C75rIu1p.js} +2 -2
  29. package/dist/client/assets/{handlebars-QzjSM_We.js → handlebars-C1zz9h1i.js} +2 -2
  30. package/dist/client/assets/{html-derivative-CkX2Wmz3.js → html-derivative-HEAA-Z2a.js} +2 -2
  31. package/dist/client/assets/{html-BySpIsKh.js → html-mXOatteF.js} +2 -2
  32. package/dist/client/assets/{http-CD7dw1li.js → http-DO0ZHyk0.js} +2 -2
  33. package/dist/client/assets/{hurl-nzp7hSsy.js → hurl-DyDQ6Iuv.js} +2 -2
  34. package/dist/client/assets/index-30avYZEg.js +663 -0
  35. package/dist/client/assets/index-C7UXI10J.css +1 -0
  36. package/dist/client/assets/{java-D2TcotRb.js → java-DicQ_x8H.js} +2 -2
  37. package/dist/client/assets/{javascript-CpW0WD7L.js → javascript-CTx-kiCR.js} +2 -2
  38. package/dist/client/assets/{jinja-BL1anCEN.js → jinja-ERQPZ9pQ.js} +2 -2
  39. package/dist/client/assets/{jison-B-sCtmJb.js → jison-BEedW5zW.js} +2 -2
  40. package/dist/client/assets/{json-BXeO84aE.js → json-MMdgCPnh.js} +2 -2
  41. package/dist/client/assets/{jsx-CgueyhKv.js → jsx-CJ--w_e-.js} +2 -2
  42. package/dist/client/assets/{julia-PMog-fIJ.js → julia-BvGAE4O0.js} +2 -2
  43. package/dist/client/assets/{just-Bi73ZAuY.js → just-BvBn61hL.js} +2 -2
  44. package/dist/client/assets/{latex-D6Hw5PyK.js → latex-P2_b6CEl.js} +2 -2
  45. package/dist/client/assets/{liquid-CuvsknsU.js → liquid-Dm2xzeBN.js} +2 -2
  46. package/dist/client/assets/{lua-6tqLQzzk.js → lua-DYQLFKMA.js} +2 -2
  47. package/dist/client/assets/{marko-Bv1DHr8G.js → marko-DCc0fplW.js} +2 -2
  48. package/dist/client/assets/{mdc-DIKkjN2a.js → mdc-BI6uqWRL.js} +2 -2
  49. package/dist/client/assets/{nginx-B2JFBlIu.js → nginx-ijGdX1bh.js} +2 -2
  50. package/dist/client/assets/{nim-D8qC29Zr.js → nim-CUp-JGxu.js} +2 -2
  51. package/dist/client/assets/{perl-De_VpaHg.js → perl-BKpwnNRr.js} +2 -2
  52. package/dist/client/assets/{php-zSI5z7ZS.js → php-DDStFT9W.js} +2 -2
  53. package/dist/client/assets/{pug-rUGxU82h.js → pug-HXcSxf00.js} +2 -2
  54. package/dist/client/assets/{qml-CXAY6cUl.js → qml-CbzgrBYo.js} +2 -2
  55. package/dist/client/assets/{r-Cm15VoHH.js → r-CgMrZP2h.js} +2 -2
  56. package/dist/client/assets/{razor-DkcxdUAy.js → razor-0ZAHbKMz.js} +2 -2
  57. package/dist/client/assets/{regexp-BOilP6p2.js → regexp-Bzi1hKAb.js} +2 -2
  58. package/dist/client/assets/{rst-BfN2oPCh.js → rst-qWyAhT77.js} +2 -2
  59. package/dist/client/assets/{ruby-B1jLvIIs.js → ruby-LCEp4zKA.js} +2 -2
  60. package/dist/client/assets/{sas-CF03ALyS.js → sas-BFhxcd3b.js} +2 -2
  61. package/dist/client/assets/{scss-BrFzdYUJ.js → scss-BK0-84uz.js} +2 -2
  62. package/dist/client/assets/{shellscript-B_6ownRV.js → shellscript-CyZVCH9y.js} +2 -2
  63. package/dist/client/assets/{shellsession-D9grZ02W.js → shellsession-BMyVGgke.js} +2 -2
  64. package/dist/client/assets/{soy-Ca44AVp-.js → soy-C5EqpU05.js} +2 -2
  65. package/dist/client/assets/{sql-CkHELsvP.js → sql-D51Kht_s.js} +2 -2
  66. package/dist/client/assets/{stata-C9ALGlol.js → stata-ClgcFk9O.js} +2 -2
  67. package/dist/client/assets/{surrealql-Cta1X2o7.js → surrealql-DcFIgIgS.js} +2 -2
  68. package/dist/client/assets/{svelte-BogBuioE.js → svelte-5uir_iV_.js} +2 -2
  69. package/dist/client/assets/{templ-C4v7sOsC.js → templ-IHhNUhu5.js} +2 -2
  70. package/dist/client/assets/{tex-KXY3LBOg.js → tex-DbjEQBr6.js} +2 -2
  71. package/dist/client/assets/textarea-C6kz4NLj.js +46 -0
  72. package/dist/client/assets/{ts-tags-BUzdov0d.js → ts-tags-xML8Swir.js} +2 -2
  73. package/dist/client/assets/{tsx-DCEZNbvU.js → tsx-BwMUW3gO.js} +2 -2
  74. package/dist/client/assets/{twig-lX5bLK2U.js → twig-BRlCEyLn.js} +2 -2
  75. package/dist/client/assets/{typescript-D0XyCzdv.js → typescript-DC1qlCSF.js} +2 -2
  76. package/dist/client/assets/{vue-BVUKhxXR.js → vue-Cta_ijHF.js} +2 -2
  77. package/dist/client/assets/{vue-html-BFZ9Hu9Q.js → vue-html-C6cjjUjR.js} +2 -2
  78. package/dist/client/assets/{vue-vine-DwK9p9S2.js → vue-vine-DMiSqDlT.js} +2 -2
  79. package/dist/client/assets/{xml-BZnktucc.js → xml-DJpzo_Kg.js} +2 -2
  80. package/dist/client/assets/{xsl-BQvXVv3K.js → xsl-DAqFroi4.js} +2 -2
  81. package/dist/client/assets/{yaml-CjmvH72q.js → yaml-Brab7tCG.js} +2 -2
  82. package/dist/client/index.html +3 -3
  83. package/package.json +1 -1
  84. package/dist/client/assets/PreviewPanel-CR9iyxF2.js +0 -2
  85. package/dist/client/assets/arrow-right-BG7cUHWK.js +0 -2
  86. package/dist/client/assets/index-C0FwegCm.css +0 -1
  87. package/dist/client/assets/index-CHboeMs4.js +0 -640
  88. package/dist/client/assets/textarea-DHdA8g53.js +0 -46
package/dist/bin.mjs CHANGED
@@ -233,7 +233,7 @@ const make$72 = () => {
233
233
  const layer$68 = Layer.sync(NetService, make$72);
234
234
  //#endregion
235
235
  //#region package.json
236
- var version = "0.0.50";
236
+ var version = "0.0.51";
237
237
  //#endregion
238
238
  //#region src/config.ts
239
239
  /**
@@ -4819,6 +4819,87 @@ const ThreadMetadataUpdatedPayload = Schema$1.Struct({
4819
4819
  name: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
4820
4820
  metadata: Schema$1.optional(UnknownRecordSchema)
4821
4821
  });
4822
+ /**
4823
+ * Per-source attribution for what is occupying the context window, as reported
4824
+ * by a provider that can answer the question. Only the Claude adapter fills this
4825
+ * in today; every field is optional so a provider can report the parts it knows.
4826
+ *
4827
+ * `isDeferred` / `isLoaded` are the interesting half. Providers defer most tool
4828
+ * definitions behind tool search, so a deferred entry's tokens are what it
4829
+ * *would* cost rather than what it costs right now, and presenting the two as
4830
+ * one number overstates usage.
4831
+ */
4832
+ const ContextWindowNamedCost = Schema$1.Struct({
4833
+ name: TrimmedNonEmptyStringSchema$1,
4834
+ tokens: NonNegativeInt
4835
+ });
4836
+ const ContextWindowDeferrableTool = Schema$1.Struct({
4837
+ name: TrimmedNonEmptyStringSchema$1,
4838
+ tokens: NonNegativeInt,
4839
+ isLoaded: Schema$1.optional(Schema$1.Boolean)
4840
+ });
4841
+ const ContextWindowBreakdown = Schema$1.Struct({
4842
+ /** The model the breakdown was measured against, which is not always the thread's current selection. */
4843
+ model: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
4844
+ /** Top-level buckets the provider itself divides the window into. */
4845
+ categories: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
4846
+ name: TrimmedNonEmptyStringSchema$1,
4847
+ tokens: NonNegativeInt,
4848
+ isDeferred: Schema$1.optional(Schema$1.Boolean)
4849
+ }))),
4850
+ mcpTools: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
4851
+ name: TrimmedNonEmptyStringSchema$1,
4852
+ serverName: TrimmedNonEmptyStringSchema$1,
4853
+ tokens: NonNegativeInt,
4854
+ isLoaded: Schema$1.optional(Schema$1.Boolean)
4855
+ }))),
4856
+ skills: Schema$1.optional(Schema$1.Struct({
4857
+ totalSkills: NonNegativeInt,
4858
+ includedSkills: NonNegativeInt,
4859
+ tokens: NonNegativeInt,
4860
+ entries: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
4861
+ name: TrimmedNonEmptyStringSchema$1,
4862
+ source: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
4863
+ tokens: NonNegativeInt
4864
+ })))
4865
+ })),
4866
+ memoryFiles: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
4867
+ path: TrimmedNonEmptyStringSchema$1,
4868
+ type: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
4869
+ tokens: NonNegativeInt
4870
+ }))),
4871
+ agents: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
4872
+ agentType: TrimmedNonEmptyStringSchema$1,
4873
+ source: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
4874
+ tokens: NonNegativeInt
4875
+ }))),
4876
+ systemTools: Schema$1.optional(Schema$1.Array(ContextWindowNamedCost)),
4877
+ deferredBuiltinTools: Schema$1.optional(Schema$1.Array(ContextWindowDeferrableTool)),
4878
+ systemPromptSections: Schema$1.optional(Schema$1.Array(ContextWindowNamedCost)),
4879
+ slashCommands: Schema$1.optional(Schema$1.Struct({
4880
+ totalCommands: NonNegativeInt,
4881
+ includedCommands: NonNegativeInt,
4882
+ tokens: NonNegativeInt
4883
+ })),
4884
+ /** How the conversation itself divides up, as opposed to the prompt scaffolding above. */
4885
+ messages: Schema$1.optional(Schema$1.Struct({
4886
+ toolCallTokens: NonNegativeInt,
4887
+ toolResultTokens: NonNegativeInt,
4888
+ attachmentTokens: NonNegativeInt,
4889
+ assistantMessageTokens: NonNegativeInt,
4890
+ userMessageTokens: NonNegativeInt,
4891
+ redirectedContextTokens: NonNegativeInt,
4892
+ unattributedTokens: NonNegativeInt,
4893
+ toolCallsByType: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
4894
+ name: TrimmedNonEmptyStringSchema$1,
4895
+ callTokens: NonNegativeInt,
4896
+ resultTokens: NonNegativeInt
4897
+ }))),
4898
+ attachmentsByType: Schema$1.optional(Schema$1.Array(ContextWindowNamedCost))
4899
+ })),
4900
+ /** Token count at which the provider compacts on its own, when it does. */
4901
+ autoCompactThreshold: Schema$1.optional(NonNegativeInt)
4902
+ });
4822
4903
  const ThreadTokenUsageSnapshot = Schema$1.Struct({
4823
4904
  usedTokens: NonNegativeInt,
4824
4905
  totalProcessedTokens: Schema$1.optional(NonNegativeInt),
@@ -4834,7 +4915,8 @@ const ThreadTokenUsageSnapshot = Schema$1.Struct({
4834
4915
  lastReasoningOutputTokens: Schema$1.optional(NonNegativeInt),
4835
4916
  toolUses: Schema$1.optional(NonNegativeInt),
4836
4917
  durationMs: Schema$1.optional(NonNegativeInt),
4837
- compactsAutomatically: Schema$1.optional(Schema$1.Boolean)
4918
+ compactsAutomatically: Schema$1.optional(Schema$1.Boolean),
4919
+ breakdown: Schema$1.optional(ContextWindowBreakdown)
4838
4920
  });
4839
4921
  const ThreadTokenUsageUpdatedPayload = Schema$1.Struct({ usage: ThreadTokenUsageSnapshot });
4840
4922
  const ThreadRealtimeStartedPayload = Schema$1.Struct({ realtimeSessionId: Schema$1.optional(TrimmedNonEmptyStringSchema$1) });
@@ -7235,6 +7317,59 @@ const TaskStreamEvent = Schema$1.Union([
7235
7317
  taskId: TaskId
7236
7318
  })
7237
7319
  ]);
7320
+ /**
7321
+ * Start an agent on a task.
7322
+ *
7323
+ * The input is only the task, deliberately. Everything else the thread needs —
7324
+ * which project, which model, what prompt — is resolved server-side from the
7325
+ * task's own project, because the caller that matters next is not a person
7326
+ * clicking a button but Phase 12's orchestrator, and a client that supplies the
7327
+ * model is a client that can start a task on a provider the user does not use.
7328
+ *
7329
+ * Worktrees are absent for a harder reason: `prepareWorktree` needs a base
7330
+ * branch, a task carries none, and nothing resolves one server-side. A thread
7331
+ * started from a task therefore runs in the project's own checkout.
7332
+ */
7333
+ const TaskStartThreadInput = Schema$1.Struct({ taskId: TaskIdField });
7334
+ /**
7335
+ * The started thread and the task as it now stands.
7336
+ *
7337
+ * Both are returned because both changed: the caller navigates to the thread,
7338
+ * and the board would otherwise show the old status until the change event
7339
+ * arrived.
7340
+ */
7341
+ const TaskStartThreadResult = Schema$1.Struct({
7342
+ task: Task,
7343
+ threadId: ThreadId
7344
+ });
7345
+ /**
7346
+ * A task cannot be started, and the reason is a property of the task or the
7347
+ * server rather than a failure.
7348
+ *
7349
+ * Each reason is a different thing for the user to fix, which is why this is a
7350
+ * union and not one message. `no-model` is the one worth explaining: a task
7351
+ * carries no model selection, so the thread runs on the project's default. The
7352
+ * server-side fallback that exists for first-run bootstrap is deliberately not
7353
+ * used here — it hardcodes a provider, so reaching for it would silently start
7354
+ * someone who works in Claude on Codex. Failing is the honest answer.
7355
+ */
7356
+ const TaskNotStartableReason = Schema$1.Literals([
7357
+ "no-project",
7358
+ "project-missing",
7359
+ "no-model"
7360
+ ]);
7361
+ var TaskNotStartableError = class extends Schema$1.TaggedErrorClass()("TaskNotStartableError", {
7362
+ taskId: TaskId,
7363
+ reason: TaskNotStartableReason
7364
+ }) {
7365
+ get message() {
7366
+ switch (this.reason) {
7367
+ case "no-project": return "This task has no project, so there is nowhere to run it. Set a project on the task first.";
7368
+ case "project-missing": return "This task's project is not registered on this server. Point it at a project that is.";
7369
+ case "no-model": return "This task's project has no default model. Choose one in the project's settings, then start the task again.";
7370
+ }
7371
+ }
7372
+ };
7238
7373
  /** Result shape for the board's list RPC. */
7239
7374
  const TaskListResult$1 = Schema$1.Struct({ tasks: Schema$1.Array(Task) });
7240
7375
  /** Result shape for every RPC that resolves to a single task. */
@@ -8004,6 +8139,7 @@ const WS_METHODS = {
8004
8139
  tasksCreate: "tasks.create",
8005
8140
  tasksUpdate: "tasks.update",
8006
8141
  tasksDelete: "tasks.delete",
8142
+ tasksStartThread: "tasks.startThread",
8007
8143
  hubGetSyncStatus: "hub.getSyncStatus",
8008
8144
  hubConnect: "hub.connect",
8009
8145
  hubDisconnect: "hub.disconnect",
@@ -8078,6 +8214,30 @@ const WsTasksDeleteRpc = Rpc.make(WS_METHODS.tasksDelete, {
8078
8214
  error: TaskRpcError
8079
8215
  });
8080
8216
  /**
8217
+ * Start an agent on a task.
8218
+ *
8219
+ * This is the one task RPC that is not CRUD: it creates a thread, seeds it from
8220
+ * the task, and links the two. It lives in the `tasks.*` namespace because the
8221
+ * task is what it reads and writes — the thread is the side effect, not the
8222
+ * subject — and because the caller always names a task and never a thread.
8223
+ *
8224
+ * The error union is wider than the other task methods for the same reason. A
8225
+ * start can fail because the task is not startable, which is a property of the
8226
+ * row, or because the turn could not be dispatched, which is the orchestration
8227
+ * engine's own failure and already has a type.
8228
+ */
8229
+ const WsTasksStartThreadRpc = Rpc.make(WS_METHODS.tasksStartThread, {
8230
+ payload: TaskStartThreadInput,
8231
+ success: TaskStartThreadResult,
8232
+ error: Schema$1.Union([
8233
+ TaskNotFoundError,
8234
+ TaskNotStartableError,
8235
+ TaskStoreError,
8236
+ OrchestrationDispatchCommandError,
8237
+ EnvironmentAuthorizationError
8238
+ ])
8239
+ });
8240
+ /**
8081
8241
  * Hub link and skill sync.
8082
8242
  *
8083
8243
  * Every one of these answers with the whole status rather than an
@@ -8590,7 +8750,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
8590
8750
  error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
8591
8751
  stream: true
8592
8752
  });
8593
- const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
8753
+ const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
8594
8754
  //#endregion
8595
8755
  //#region ../../packages/shared/src/oauthScope.ts
8596
8756
  const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
@@ -30964,11 +31124,25 @@ function isResolvableContextWindowActivity(activity) {
30964
31124
  * newer updates still stream through and supersede the retained rows on the
30965
31125
  * client.
30966
31126
  */
31127
+ function withoutContextWindowBreakdown$1(activity) {
31128
+ const payload = asRecord$1(activity.payload);
31129
+ if (!payload || payload.breakdown === void 0) return activity;
31130
+ const { breakdown: _breakdown, ...rest } = payload;
31131
+ return {
31132
+ ...activity,
31133
+ payload: rest
31134
+ };
31135
+ }
30967
31136
  function dropStaleContextWindowActivities(activities) {
30968
31137
  const latestIndexByTurn = /* @__PURE__ */ new Map();
30969
31138
  for (let index = 0; index < activities.length; index += 1) if (isResolvableContextWindowActivity(activities[index])) latestIndexByTurn.set(activities[index].turnId, index);
30970
31139
  if (latestIndexByTurn.size === 0) return activities;
30971
- return activities.filter((activity, index) => !isResolvableContextWindowActivity(activity) || latestIndexByTurn.get(activity.turnId) === index);
31140
+ const newestIndex = Math.max(...latestIndexByTurn.values());
31141
+ return activities.flatMap((activity, index) => {
31142
+ if (!isResolvableContextWindowActivity(activity)) return [activity];
31143
+ if (latestIndexByTurn.get(activity.turnId) !== index) return [];
31144
+ return [index === newestIndex ? activity : withoutContextWindowBreakdown$1(activity)];
31145
+ });
30972
31146
  }
30973
31147
  function projectThreadDetailSnapshot(snapshot) {
30974
31148
  return {
@@ -31116,6 +31290,39 @@ const resolveTaskRepositoryKey = Effect.fn("taskBoard.resolveRepositoryKey")(fun
31116
31290
  return (yield* (yield* RepositoryIdentityResolver).resolve(project.value.workspaceRoot))?.canonicalKey ?? null;
31117
31291
  });
31118
31292
  /**
31293
+ * Everything that decides whether a task can be started, as one pure function.
31294
+ *
31295
+ * Kept out of the RPC handler because the three refusals are the whole of the
31296
+ * interesting behaviour and each is a different thing for the user to fix,
31297
+ * while the handler around them is two store calls and a dispatch. Phase 12's
31298
+ * orchestrator has to make the same three decisions before it may claim a task,
31299
+ * and it should reach the same verdicts by calling this rather than by reading
31300
+ * the handler and reimplementing it.
31301
+ *
31302
+ * The project is passed in as the repository returns it — including soft-deleted
31303
+ * rows, which is why `deletedAt` is checked here rather than assumed away.
31304
+ */
31305
+ const resolveTaskStart = (task, project) => {
31306
+ if (task.projectId === null) return {
31307
+ startable: false,
31308
+ reason: "no-project"
31309
+ };
31310
+ if (Option.isNone(project) || project.value.deletedAt !== null) return {
31311
+ startable: false,
31312
+ reason: "project-missing"
31313
+ };
31314
+ const model = project.value.defaultModelSelection;
31315
+ if (model === null) return {
31316
+ startable: false,
31317
+ reason: "no-model"
31318
+ };
31319
+ return {
31320
+ startable: true,
31321
+ projectId: task.projectId,
31322
+ model
31323
+ };
31324
+ };
31325
+ /**
31119
31326
  * Map a persistence failure to the caller-facing error.
31120
31327
  *
31121
31328
  * The underlying error carries SQL detail, which is noise to a client and, for
@@ -31127,6 +31334,54 @@ const toTaskStoreError = (operation) => (cause) => Effect.logWarning("task store
31127
31334
  cause
31128
31335
  }).pipe(Effect.andThen(Effect.fail(new TaskStoreError({ operation }))));
31129
31336
  //#endregion
31337
+ //#region ../../packages/shared/src/taskExecution.ts
31338
+ /**
31339
+ * The `auto` rendering: here is the task, do it.
31340
+ *
31341
+ * Two instructions carry their weight. The agent is told its thread is already
31342
+ * linked to the task, because otherwise its first useful move is to guess which
31343
+ * board row it is on. And it is told to leave `status` alone: the server moved
31344
+ * the task to `in_progress` when it started the thread, and where the work goes
31345
+ * after that is the user's call — the same rule the scoping prompt follows, and
31346
+ * the reason the board's columns still mean something.
31347
+ */
31348
+ const buildAutoPrompt = (task) => {
31349
+ const body = task.body.trim();
31350
+ return `You are picking up a task from the board. Do the work.
31351
+
31352
+ ## ${task.title}
31353
+
31354
+ ${body.length === 0 ? "_The task has no description. Read enough of the repository to work out what it means, and ask if it is genuinely ambiguous._" : body}
31355
+
31356
+ This thread is linked to task \`${task.taskId}\`, which is now In progress. \`task_current\` re-reads it if you need the fields again.
31357
+
31358
+ Record what you find with \`task_update\` as you go — a decision you made, a constraint you hit, something the task turned out to be wrong about. That is what makes the row worth reading afterwards. Leave \`status\` alone: moving work across the board is the user's call.
31359
+
31360
+ Start by reading the code the task concerns. If it turns out to be specified too poorly to act on, say so and stop rather than guessing at what was meant.`;
31361
+ };
31362
+ /**
31363
+ * Render a task into the prompt that seeds its thread.
31364
+ *
31365
+ * Exhaustive over the mode on purpose: adding a member to [TaskExecutionMode]
31366
+ * without a rendering should fail to compile rather than fall through to `auto`.
31367
+ */
31368
+ const buildTaskExecutionPrompt = (input) => {
31369
+ switch (input.mode) {
31370
+ case "auto": return buildAutoPrompt(input.task);
31371
+ }
31372
+ };
31373
+ const TASK_THREAD_TITLE_MAX_LENGTH = 60;
31374
+ /**
31375
+ * The thread's title, which is the task's own — a thread started from a task is
31376
+ * that task, and a derived-from-the-prompt title would read as a sentence of
31377
+ * instructions in the sidebar.
31378
+ */
31379
+ const buildTaskThreadTitle = (title) => {
31380
+ const compact = title.trim().replace(/\s+/gu, " ");
31381
+ if (compact.length === 0) return "Task";
31382
+ return compact.length > TASK_THREAD_TITLE_MAX_LENGTH ? `${compact.slice(0, TASK_THREAD_TITLE_MAX_LENGTH - 1).trimEnd()}…` : compact;
31383
+ };
31384
+ //#endregion
31130
31385
  //#region src/observability/RpcInstrumentation.ts
31131
31386
  const RPC_SPAN_PREFIX = "ws.rpc";
31132
31387
  const DEFAULT_RPC_SPAN_ATTRIBUTES = {
@@ -40853,6 +41108,7 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
40853
41108
  [WS_METHODS.tasksCreate, AuthOrchestrationOperateScope],
40854
41109
  [WS_METHODS.tasksUpdate, AuthOrchestrationOperateScope],
40855
41110
  [WS_METHODS.tasksDelete, AuthOrchestrationOperateScope],
41111
+ [WS_METHODS.tasksStartThread, AuthOrchestrationOperateScope],
40856
41112
  [WS_METHODS.subscribeTasks, AuthOrchestrationReadScope],
40857
41113
  [WS_METHODS.hubGetSyncStatus, AuthOrchestrationReadScope],
40858
41114
  [WS_METHODS.hubConnect, AuthOrchestrationOperateScope],
@@ -40965,7 +41221,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
40965
41221
  const checkpointDiffQuery = yield* CheckpointDiffQuery;
40966
41222
  const keybindings = yield* Keybindings;
40967
41223
  const taskRepository = yield* TaskRepository;
40968
- yield* ProjectionProjectRepository;
41224
+ const projectionProjects = yield* ProjectionProjectRepository;
40969
41225
  const externalLauncher = yield* ExternalLauncher;
40970
41226
  const gitWorkflow = yield* GitWorkflowService;
40971
41227
  const review = yield* ReviewService;
@@ -41443,6 +41699,64 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
41443
41699
  return { task: patched.value };
41444
41700
  }), { "rpc.aggregate": "tasks" }),
41445
41701
  [WS_METHODS.tasksDelete]: ({ taskId }) => observeRpcEffect$1(WS_METHODS.tasksDelete, taskRepository.deleteById({ taskId }).pipe(Effect.catch(toTaskStoreError("tasks.delete")), Effect.as({})), { "rpc.aggregate": "tasks" }),
41702
+ [WS_METHODS.tasksStartThread]: ({ taskId }) => observeRpcEffect$1(WS_METHODS.tasksStartThread, Effect.gen(function* () {
41703
+ const found = yield* taskRepository.getById({ taskId }).pipe(Effect.catch(toTaskStoreError("tasks.startThread")));
41704
+ if (Option.isNone(found)) return yield* new TaskNotFoundError({ taskId });
41705
+ const task = found.value;
41706
+ const plan = resolveTaskStart(task, task.projectId === null ? Option.none() : yield* projectionProjects.getById({ projectId: task.projectId }).pipe(Effect.catch(toTaskStoreError("tasks.startThread.project"))));
41707
+ if (!plan.startable) return yield* new TaskNotStartableError({
41708
+ taskId,
41709
+ reason: plan.reason
41710
+ });
41711
+ const modelSelection = plan.model;
41712
+ const threadId = ThreadId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
41713
+ const createdAt = yield* nowIso$5;
41714
+ const threadTitle = buildTaskThreadTitle(task.title);
41715
+ const normalizedCommand = yield* normalizeDispatchCommand({
41716
+ type: "thread.turn.start",
41717
+ commandId: yield* serverCommandId("task-start-thread"),
41718
+ threadId,
41719
+ message: {
41720
+ messageId: MessageId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie)),
41721
+ role: "user",
41722
+ text: buildTaskExecutionPrompt({
41723
+ mode: "auto",
41724
+ task: {
41725
+ taskId,
41726
+ title: task.title,
41727
+ body: task.body
41728
+ }
41729
+ }),
41730
+ attachments: []
41731
+ },
41732
+ modelSelection,
41733
+ titleSeed: threadTitle,
41734
+ runtimeMode: DEFAULT_RUNTIME_MODE$2,
41735
+ interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
41736
+ bootstrap: { createThread: {
41737
+ projectId: plan.projectId,
41738
+ title: threadTitle,
41739
+ modelSelection,
41740
+ runtimeMode: DEFAULT_RUNTIME_MODE$2,
41741
+ interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
41742
+ branch: null,
41743
+ worktreePath: null,
41744
+ createdAt
41745
+ } },
41746
+ createdAt
41747
+ });
41748
+ yield* dispatchNormalizedCommand(normalizedCommand);
41749
+ const patched = yield* taskRepository.patch({
41750
+ taskId,
41751
+ threadId,
41752
+ status: "in_progress"
41753
+ }, yield* nowIso$5).pipe(Effect.catch(toTaskStoreError("tasks.startThread.link")));
41754
+ if (Option.isNone(patched)) return yield* new TaskNotFoundError({ taskId });
41755
+ return {
41756
+ task: patched.value,
41757
+ threadId
41758
+ };
41759
+ }), { "rpc.aggregate": "tasks" }),
41446
41760
  [WS_METHODS.subscribeTasks]: (_input) => observeRpcStreamEffect$1(WS_METHODS.subscribeTasks, Effect.succeed(taskRepository.streamWithSnapshot.pipe(Stream.catch((cause) => Stream.fromEffect(toTaskStoreError("tasks.subscribe")(cause))))), { "rpc.aggregate": "tasks" }),
41447
41761
  [WS_METHODS.hubGetSyncStatus]: (_input) => observeRpcEffect$1(WS_METHODS.hubGetSyncStatus, assetSync.status, { "rpc.aggregate": "hub" }),
41448
41762
  [WS_METHODS.hubConnect]: (input) => observeRpcEffect$1(WS_METHODS.hubConnect, hubLink.connect(input).pipe(Effect.mapError((cause) => new HubLinkError({ detail: cause.message })), Effect.andThen(assetSync.status)), { "rpc.aggregate": "hub" }),
@@ -45240,13 +45554,178 @@ function normalizeClaudeActiveTokenUsage(value, contextWindow, totalProcessedTok
45240
45554
  ...totalProcessedTokens !== void 0 ? { totalProcessedTokens } : {}
45241
45555
  });
45242
45556
  }
45557
+ /**
45558
+ * The contract's string fields are non-empty, and this payload is decoded on the
45559
+ * way out, so an entry the SDK reports with a blank name would fail the whole
45560
+ * event rather than lose one row. Drop those instead.
45561
+ */
45562
+ function trimmedName(value) {
45563
+ if (typeof value !== "string") return;
45564
+ const trimmed = value.trim();
45565
+ return trimmed.length > 0 ? trimmed : void 0;
45566
+ }
45567
+ function mapNamedCosts(entries) {
45568
+ if (!entries || entries.length === 0) return;
45569
+ const mapped = entries.flatMap((entry) => {
45570
+ const name = trimmedName(entry.name);
45571
+ const tokens = finiteNonNegativeInteger(entry.tokens);
45572
+ return name !== void 0 && tokens !== void 0 ? [{
45573
+ name,
45574
+ tokens
45575
+ }] : [];
45576
+ });
45577
+ return mapped.length > 0 ? mapped : void 0;
45578
+ }
45579
+ /**
45580
+ * Keeps the per-source attribution the SDK already computes on every turn. The
45581
+ * `gridRows` and `color` fields are dropped: they describe how the vendor CLI
45582
+ * paints its own meter, and this UI has its own.
45583
+ */
45584
+ function claudeContextWindowBreakdown(value) {
45585
+ const model = trimmedName(value.model);
45586
+ const categories = value.categories.flatMap((category) => {
45587
+ const name = trimmedName(category.name);
45588
+ const tokens = finiteNonNegativeInteger(category.tokens);
45589
+ if (name === void 0 || tokens === void 0) return [];
45590
+ return [{
45591
+ name,
45592
+ tokens,
45593
+ ...category.isDeferred !== void 0 ? { isDeferred: category.isDeferred } : {}
45594
+ }];
45595
+ });
45596
+ const mcpTools = value.mcpTools.flatMap((tool) => {
45597
+ const name = trimmedName(tool.name);
45598
+ const serverName = trimmedName(tool.serverName);
45599
+ const tokens = finiteNonNegativeInteger(tool.tokens);
45600
+ if (name === void 0 || serverName === void 0 || tokens === void 0) return [];
45601
+ return [{
45602
+ name,
45603
+ serverName,
45604
+ tokens,
45605
+ ...tool.isLoaded !== void 0 ? { isLoaded: tool.isLoaded } : {}
45606
+ }];
45607
+ });
45608
+ const memoryFiles = value.memoryFiles.flatMap((file) => {
45609
+ const path = trimmedName(file.path);
45610
+ const tokens = finiteNonNegativeInteger(file.tokens);
45611
+ if (path === void 0 || tokens === void 0) return [];
45612
+ const type = trimmedName(file.type);
45613
+ return [{
45614
+ path,
45615
+ tokens,
45616
+ ...type !== void 0 ? { type } : {}
45617
+ }];
45618
+ });
45619
+ const agents = value.agents.flatMap((agent) => {
45620
+ const agentType = trimmedName(agent.agentType);
45621
+ const tokens = finiteNonNegativeInteger(agent.tokens);
45622
+ if (agentType === void 0 || tokens === void 0) return [];
45623
+ const source = trimmedName(agent.source);
45624
+ return [{
45625
+ agentType,
45626
+ tokens,
45627
+ ...source !== void 0 ? { source } : {}
45628
+ }];
45629
+ });
45630
+ const deferredBuiltinTools = value.deferredBuiltinTools?.flatMap((tool) => {
45631
+ const name = trimmedName(tool.name);
45632
+ const tokens = finiteNonNegativeInteger(tool.tokens);
45633
+ return name !== void 0 && tokens !== void 0 ? [{
45634
+ name,
45635
+ tokens,
45636
+ isLoaded: tool.isLoaded
45637
+ }] : [];
45638
+ });
45639
+ const skillsSource = value.skills;
45640
+ const skillEntries = skillsSource?.skillFrontmatter.flatMap((skill) => {
45641
+ const name = trimmedName(skill.name);
45642
+ const tokens = finiteNonNegativeInteger(skill.tokens);
45643
+ if (name === void 0 || tokens === void 0) return [];
45644
+ const source = trimmedName(skill.source);
45645
+ return [{
45646
+ name,
45647
+ tokens,
45648
+ ...source !== void 0 ? { source } : {}
45649
+ }];
45650
+ });
45651
+ const skills = skillsSource === void 0 ? void 0 : {
45652
+ totalSkills: finiteNonNegativeInteger(skillsSource.totalSkills) ?? 0,
45653
+ includedSkills: finiteNonNegativeInteger(skillsSource.includedSkills) ?? 0,
45654
+ tokens: finiteNonNegativeInteger(skillsSource.tokens) ?? 0,
45655
+ ...skillEntries && skillEntries.length > 0 ? { entries: skillEntries } : {}
45656
+ };
45657
+ const slashCommandsSource = value.slashCommands;
45658
+ const slashCommands = slashCommandsSource === void 0 ? void 0 : {
45659
+ totalCommands: finiteNonNegativeInteger(slashCommandsSource.totalCommands) ?? 0,
45660
+ includedCommands: finiteNonNegativeInteger(slashCommandsSource.includedCommands) ?? 0,
45661
+ tokens: finiteNonNegativeInteger(slashCommandsSource.tokens) ?? 0
45662
+ };
45663
+ const messagesSource = value.messageBreakdown;
45664
+ const toolCallsByType = messagesSource?.toolCallsByType.flatMap((entry) => {
45665
+ const name = trimmedName(entry.name);
45666
+ const callTokens = finiteNonNegativeInteger(entry.callTokens);
45667
+ const resultTokens = finiteNonNegativeInteger(entry.resultTokens);
45668
+ return name !== void 0 && callTokens !== void 0 && resultTokens !== void 0 ? [{
45669
+ name,
45670
+ callTokens,
45671
+ resultTokens
45672
+ }] : [];
45673
+ });
45674
+ const attachmentsByType = mapNamedCosts(messagesSource?.attachmentsByType);
45675
+ const messages = messagesSource === void 0 ? void 0 : {
45676
+ toolCallTokens: finiteNonNegativeInteger(messagesSource.toolCallTokens) ?? 0,
45677
+ toolResultTokens: finiteNonNegativeInteger(messagesSource.toolResultTokens) ?? 0,
45678
+ attachmentTokens: finiteNonNegativeInteger(messagesSource.attachmentTokens) ?? 0,
45679
+ assistantMessageTokens: finiteNonNegativeInteger(messagesSource.assistantMessageTokens) ?? 0,
45680
+ userMessageTokens: finiteNonNegativeInteger(messagesSource.userMessageTokens) ?? 0,
45681
+ redirectedContextTokens: finiteNonNegativeInteger(messagesSource.redirectedContextTokens) ?? 0,
45682
+ unattributedTokens: finiteNonNegativeInteger(messagesSource.unattributedTokens) ?? 0,
45683
+ ...toolCallsByType && toolCallsByType.length > 0 ? { toolCallsByType } : {},
45684
+ ...attachmentsByType !== void 0 ? { attachmentsByType } : {}
45685
+ };
45686
+ const systemTools = mapNamedCosts(value.systemTools);
45687
+ const systemPromptSections = mapNamedCosts(value.systemPromptSections);
45688
+ const autoCompactThreshold = finiteNonNegativeInteger(value.autoCompactThreshold);
45689
+ const breakdown = {
45690
+ ...model !== void 0 ? { model } : {},
45691
+ ...categories.length > 0 ? { categories } : {},
45692
+ ...mcpTools.length > 0 ? { mcpTools } : {},
45693
+ ...skills !== void 0 ? { skills } : {},
45694
+ ...memoryFiles.length > 0 ? { memoryFiles } : {},
45695
+ ...agents.length > 0 ? { agents } : {},
45696
+ ...systemTools !== void 0 ? { systemTools } : {},
45697
+ ...deferredBuiltinTools && deferredBuiltinTools.length > 0 ? { deferredBuiltinTools } : {},
45698
+ ...systemPromptSections !== void 0 ? { systemPromptSections } : {},
45699
+ ...slashCommands !== void 0 ? { slashCommands } : {},
45700
+ ...messages !== void 0 ? { messages } : {},
45701
+ ...autoCompactThreshold !== void 0 ? { autoCompactThreshold } : {}
45702
+ };
45703
+ return Object.keys(breakdown).length > 0 ? breakdown : void 0;
45704
+ }
45705
+ /**
45706
+ * Drops the attribution from a snapshot that is being carried forward. The token
45707
+ * counts still describe the thread, but the breakdown was measured against a
45708
+ * turn that has since moved on. A stale breakdown presented as the current one
45709
+ * is worse than none, because nothing about it looks stale.
45710
+ */
45711
+ function withoutContextWindowBreakdown(usage) {
45712
+ if (!usage || usage.breakdown === void 0) return usage;
45713
+ const { breakdown: _breakdown, ...rest } = usage;
45714
+ return rest;
45715
+ }
45243
45716
  function normalizeClaudeContextUsageApiSnapshot(value, totalProcessedTokens) {
45244
- return makeClaudeTokenUsageSnapshot({
45717
+ const snapshot = makeClaudeTokenUsageSnapshot({
45245
45718
  activeTokens: value.totalTokens,
45246
45719
  contextWindow: value.maxTokens,
45247
45720
  ...totalProcessedTokens !== void 0 ? { totalProcessedTokens } : {},
45248
45721
  compactsAutomatically: value.isAutoCompactEnabled
45249
45722
  });
45723
+ if (!snapshot) return;
45724
+ const breakdown = claudeContextWindowBreakdown(value);
45725
+ return breakdown !== void 0 ? {
45726
+ ...snapshot,
45727
+ breakdown
45728
+ } : snapshot;
45250
45729
  }
45251
45730
  function compactBoundaryTokenUsageSnapshot(message, contextWindow, totalProcessedTokens) {
45252
45731
  const metadata = message.compact_metadata;
@@ -46039,7 +46518,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
46039
46518
  const resultHasActiveUsage = resultUsageRecord !== void 0 && (hasResultUsageIteration || claudeUsageInputTokens(resultUsageRecord) + claudeUsageOutputTokens(resultUsageRecord) > 0);
46040
46519
  const resultTotalOnly = resultUsageRecord !== void 0 && !resultHasActiveUsage && claudeTotalProcessedTokens(resultUsageRecord) !== void 0;
46041
46520
  const resultIterationSnapshot = resultUsageRecord ? normalizeClaudeActiveTokenUsage(resultUsageRecord, maxTokens, accumulatedTotalProcessedTokens ?? context.lastKnownTotalProcessedTokens) : void 0;
46042
- const lastGoodUsage = context.lastKnownTokenUsage;
46521
+ const lastGoodUsage = withoutContextWindowBreakdown(context.lastKnownTokenUsage);
46043
46522
  const usageSnapshot = contextUsageSnapshot ?? (resultTotalOnly && lastGoodUsage ? {
46044
46523
  ...lastGoodUsage,
46045
46524
  ...typeof maxTokens === "number" && Number.isFinite(maxTokens) && maxTokens > 0 ? { maxTokens } : {},