@overdeck/contracts 0.72.0 → 0.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -564,6 +564,7 @@ const AgentSnapshot = effect.Schema.Struct({
564
564
  askedAt: effect.Schema.String,
565
565
  questions: effect.Schema.Array(effect.Schema.Struct({
566
566
  question: effect.Schema.String,
567
+ context: effect.Schema.optional(effect.Schema.String),
567
568
  header: effect.Schema.optional(effect.Schema.String),
568
569
  multiSelect: effect.Schema.optional(effect.Schema.Boolean),
569
570
  options: effect.Schema.Array(effect.Schema.Struct({
@@ -1824,6 +1825,7 @@ const AgentEnrichmentChangedEvent = effect.Schema.Struct({
1824
1825
  askedAt: effect.Schema.String,
1825
1826
  questions: effect.Schema.Array(effect.Schema.Struct({
1826
1827
  question: effect.Schema.String,
1828
+ context: effect.Schema.optional(effect.Schema.String),
1827
1829
  header: effect.Schema.optional(effect.Schema.String),
1828
1830
  multiSelect: effect.Schema.optional(effect.Schema.Boolean),
1829
1831
  options: effect.Schema.Array(effect.Schema.Struct({
@@ -2831,6 +2833,14 @@ const ConversationPullRequestsChangedEvent = effect.Schema.Struct({
2831
2833
  effective: effect.Schema.NullOr(PullRequestLink)
2832
2834
  })
2833
2835
  });
2836
+ /** Emitted (in-memory only) when a conversation's schedules change (PAN-4657), so the
2837
+ * list and the schedule dialog refresh the next-run badge. */
2838
+ const ConversationSchedulesChangedEvent = effect.Schema.Struct({
2839
+ type: effect.Schema.Literal("conversation.schedules_changed"),
2840
+ sequence: SequenceNumber,
2841
+ timestamp: effect.Schema.String,
2842
+ payload: effect.Schema.Struct({ conversationName: effect.Schema.String })
2843
+ });
2834
2844
  /** Emitted (in-memory only) when a PermissionRequest hook fires or resolves for a conversation. */
2835
2845
  const ConversationPermissionChangedEvent = effect.Schema.Struct({
2836
2846
  type: effect.Schema.Literal("conversation.permission_changed"),
@@ -3058,6 +3068,7 @@ const DomainEvent = effect.Schema.Union([
3058
3068
  ConversationMovedEvent,
3059
3069
  ConversationTitleChangedEvent,
3060
3070
  ConversationPullRequestsChangedEvent,
3071
+ ConversationSchedulesChangedEvent,
3061
3072
  ConversationPermissionChangedEvent,
3062
3073
  ScanStartedEvent,
3063
3074
  ScanProgressEvent,
@@ -3234,6 +3245,63 @@ const OpenInEditorInput = effect.Schema.Struct({
3234
3245
  editor: EditorIdSchema,
3235
3246
  reveal: effect.Schema.optional(effect.Schema.Boolean)
3236
3247
  });
3248
+ const BROWSERS = [
3249
+ {
3250
+ id: "default-browser",
3251
+ label: "browser",
3252
+ linuxCommands: [],
3253
+ macApp: null
3254
+ },
3255
+ {
3256
+ id: "chrome",
3257
+ label: "Google Chrome",
3258
+ linuxCommands: ["google-chrome"],
3259
+ macApp: "Google Chrome"
3260
+ },
3261
+ {
3262
+ id: "chromium",
3263
+ label: "Chromium",
3264
+ linuxCommands: ["chromium", "chromium-browser"],
3265
+ macApp: "Chromium"
3266
+ },
3267
+ {
3268
+ id: "firefox",
3269
+ label: "Firefox",
3270
+ linuxCommands: ["firefox"],
3271
+ macApp: "Firefox"
3272
+ },
3273
+ {
3274
+ id: "brave",
3275
+ label: "Brave",
3276
+ linuxCommands: ["brave-browser"],
3277
+ macApp: "Brave Browser"
3278
+ },
3279
+ {
3280
+ id: "edge",
3281
+ label: "Microsoft Edge",
3282
+ linuxCommands: ["microsoft-edge"],
3283
+ macApp: "Microsoft Edge"
3284
+ },
3285
+ {
3286
+ id: "vivaldi",
3287
+ label: "Vivaldi",
3288
+ linuxCommands: ["vivaldi"],
3289
+ macApp: "Vivaldi"
3290
+ }
3291
+ ];
3292
+ const BrowserIdSchema = effect.Schema.Literals([
3293
+ "default-browser",
3294
+ "chrome",
3295
+ "chromium",
3296
+ "firefox",
3297
+ "brave",
3298
+ "edge",
3299
+ "vivaldi"
3300
+ ]);
3301
+ const OpenInBrowserInput = effect.Schema.Struct({
3302
+ path: effect.Schema.String,
3303
+ browser: BrowserIdSchema
3304
+ });
3237
3305
  //#endregion
3238
3306
  //#region src/effort.ts
3239
3307
  /**
@@ -3294,7 +3362,9 @@ const WS_METHODS = {
3294
3362
  sendTerminalInput: "pan.sendTerminalInput",
3295
3363
  resizeTerminal: "pan.resizeTerminal",
3296
3364
  shellOpenInEditor: "pan.shellOpenInEditor",
3297
- getAvailableEditors: "pan.getAvailableEditors"
3365
+ getAvailableEditors: "pan.getAvailableEditors",
3366
+ shellOpenInBrowser: "pan.shellOpenInBrowser",
3367
+ getAvailableBrowsers: "pan.getAvailableBrowsers"
3298
3368
  };
3299
3369
  var PanRpcError = class extends effect.Schema.TaggedErrorClass()("PanRpcError", {
3300
3370
  message: effect.Schema.String,
@@ -3740,6 +3810,16 @@ const GetAvailableEditorsRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.getAvaila
3740
3810
  }),
3741
3811
  error: PanRpcError
3742
3812
  });
3813
+ /** Open a local file in a browser (PAN-4762) */
3814
+ const ShellOpenInBrowserRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.shellOpenInBrowser, {
3815
+ payload: OpenInBrowserInput,
3816
+ error: PanRpcError
3817
+ });
3818
+ /** Get available (installed) browsers (PAN-4762) */
3819
+ const GetAvailableBrowsersRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.getAvailableBrowsers, {
3820
+ success: effect.Schema.Struct({ browsers: effect.Schema.Array(BrowserIdSchema) }),
3821
+ error: PanRpcError
3822
+ });
3743
3823
  const DiscoveredSessionListResult = effect.Schema.Struct({
3744
3824
  sessions: effect.Schema.Array(DiscoveredSessionSnapshot),
3745
3825
  count: effect.Schema.Number,
@@ -3900,7 +3980,7 @@ const GetConversationStatsRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.getConve
3900
3980
  error: PanRpcError
3901
3981
  });
3902
3982
  /** All Overdeck WebSocket RPC methods */
3903
- const PanRpcGroup = effect_unstable_rpc_RpcGroup.make(SubscribeDomainEventsRpc, SubscribeIssueEventsRpc, SubscribeTerminalRpc, SubscribeAgentOutputRpc, GetSnapshotRpc, ReplayEventsRpc, ReadWorkspaceFileRpc, ReadFileAtPathRpc, WriteFileAtPathRpc, ResolveFilePathExistsRpc, TerminalOpenRpc, TerminalWriteRpc, TerminalResizeRpc, TerminalCloseRpc, StartPlanningRpc, StartAgentRpc, DeepWipeRpc, SendTerminalInputRpc, ResizeTerminalRpc, SubscribeConversationMessagesRpc, SubscribeProjectSessionTreeRpc, ShellOpenInEditorRpc, GetAvailableEditorsRpc, ScanConversationsRpc, SearchConversationsRpc, ListDiscoveredSessionsRpc, ListSessionsFeedRpc, GetSessionsFeedFacetsRpc, GetDiscoveredSessionRpc, EnrichSessionsRpc, EmbedSessionsRpc, GetConversationCostRpc, GetConversationCostByWorkspaceRpc, GetConversationStatsRpc);
3983
+ const PanRpcGroup = effect_unstable_rpc_RpcGroup.make(SubscribeDomainEventsRpc, SubscribeIssueEventsRpc, SubscribeTerminalRpc, SubscribeAgentOutputRpc, GetSnapshotRpc, ReplayEventsRpc, ReadWorkspaceFileRpc, ReadFileAtPathRpc, WriteFileAtPathRpc, ResolveFilePathExistsRpc, TerminalOpenRpc, TerminalWriteRpc, TerminalResizeRpc, TerminalCloseRpc, StartPlanningRpc, StartAgentRpc, DeepWipeRpc, SendTerminalInputRpc, ResizeTerminalRpc, SubscribeConversationMessagesRpc, SubscribeProjectSessionTreeRpc, ShellOpenInEditorRpc, GetAvailableEditorsRpc, ShellOpenInBrowserRpc, GetAvailableBrowsersRpc, ScanConversationsRpc, SearchConversationsRpc, ListDiscoveredSessionsRpc, ListSessionsFeedRpc, GetSessionsFeedFacetsRpc, GetDiscoveredSessionRpc, EnrichSessionsRpc, EmbedSessionsRpc, GetConversationCostRpc, GetConversationCostByWorkspaceRpc, GetConversationStatsRpc);
3904
3984
  //#endregion
3905
3985
  //#region src/agent-runtime-merge.ts
3906
3986
  function defaultRuntimeSnapshot(agentId, timestamp, sequence) {
@@ -5231,6 +5311,10 @@ function applyEvent(state, event) {
5231
5311
  ...state,
5232
5312
  conversationsListRevision: state.conversationsListRevision + 1
5233
5313
  };
5314
+ case "conversation.schedules_changed": return {
5315
+ ...state,
5316
+ conversationsListRevision: state.conversationsListRevision + 1
5317
+ };
5234
5318
  case "conversation.permission_changed": {
5235
5319
  const { conversationName, waiting } = event.payload;
5236
5320
  if (!waiting) {
@@ -5681,7 +5765,9 @@ const FlywheelLastTick = effect.Schema.Struct({
5681
5765
  inFlight: effect.Schema.Array(effect.Schema.String),
5682
5766
  needsYou: effect.Schema.NullOr(effect.Schema.String),
5683
5767
  /** The assistant message's `createdAt`. */
5684
- at: effect.Schema.String
5768
+ at: effect.Schema.String,
5769
+ /** The assistant message's id, when the harness records one. */
5770
+ messageId: effect.Schema.optional(effect.Schema.String)
5685
5771
  });
5686
5772
  const FlywheelPolicies = effect.Schema.Struct({
5687
5773
  auto_pickup_backlog: effect.Schema.Boolean,
@@ -5711,6 +5797,8 @@ const FlywheelInFlightRow = effect.Schema.Struct({
5711
5797
  pr: effect.Schema.optional(DerivedPrState),
5712
5798
  /** Set when no configured tracker answered: the state is a guess, not a fact. */
5713
5799
  trackerUnknown: effect.Schema.optional(effect.Schema.Literal(true)),
5800
+ /** The row folds a feature-<id>-strike workspace onto its base issue (PAN-4752). */
5801
+ strike: effect.Schema.optional(effect.Schema.Literal(true)),
5714
5802
  /** Live agent panes on this issue. `working` with 0 means nobody is driving it. */
5715
5803
  liveAgents: effect.Schema.Number,
5716
5804
  /** The loop named this id in its newest tick marker's in-flight list. */
@@ -6111,10 +6199,15 @@ const HARNESS_CAPABILITY_KEYS = [
6111
6199
  "hostEffortFlag",
6112
6200
  "binaryLabel",
6113
6201
  "installHint",
6202
+ "updateArgs",
6203
+ "npmPackage",
6114
6204
  "binaryConfigKey",
6115
6205
  "launchPreflight",
6116
6206
  "workspaceResolution",
6117
- "correlatesBySessionId"
6207
+ "correlatesBySessionId",
6208
+ "answersQuestionByMessage",
6209
+ "askAnswerDelivery",
6210
+ "runsOnFlyMachine"
6118
6211
  ];
6119
6212
  const CLAUDE_CODE_CAPABILITIES = {
6120
6213
  contextChannel: "append-system-prompt-file",
@@ -6129,10 +6222,15 @@ const CLAUDE_CODE_CAPABILITIES = {
6129
6222
  hostEffortFlag: false,
6130
6223
  binaryLabel: "Claude Code",
6131
6224
  installHint: "curl -fsSL https://claude.ai/install.sh | bash",
6225
+ updateArgs: ["update"],
6226
+ npmPackage: "@anthropic-ai/claude-code",
6132
6227
  binaryConfigKey: null,
6133
6228
  launchPreflight: "claude-code-model-minimum",
6134
6229
  workspaceResolution: "claude-project-hash",
6135
- correlatesBySessionId: false
6230
+ correlatesBySessionId: false,
6231
+ answersQuestionByMessage: true,
6232
+ askAnswerDelivery: "message",
6233
+ runsOnFlyMachine: true
6136
6234
  };
6137
6235
  const OHMYPI_CAPABILITIES = {
6138
6236
  contextChannel: "append-system-prompt",
@@ -6147,10 +6245,15 @@ const OHMYPI_CAPABILITIES = {
6147
6245
  hostEffortFlag: false,
6148
6246
  binaryLabel: "OhMyPi",
6149
6247
  installHint: null,
6248
+ updateArgs: null,
6249
+ npmPackage: null,
6150
6250
  binaryConfigKey: null,
6151
6251
  launchPreflight: null,
6152
6252
  workspaceResolution: "first-message-only",
6153
- correlatesBySessionId: true
6253
+ correlatesBySessionId: true,
6254
+ answersQuestionByMessage: false,
6255
+ askAnswerDelivery: "pi-ask-modal",
6256
+ runsOnFlyMachine: false
6154
6257
  };
6155
6258
  const CODEX_CAPABILITIES = {
6156
6259
  contextChannel: "developer_instructions",
@@ -6165,10 +6268,15 @@ const CODEX_CAPABILITIES = {
6165
6268
  hostEffortFlag: false,
6166
6269
  binaryLabel: "Codex CLI",
6167
6270
  installHint: null,
6271
+ updateArgs: ["update"],
6272
+ npmPackage: "@openai/codex",
6168
6273
  binaryConfigKey: null,
6169
6274
  launchPreflight: null,
6170
6275
  workspaceResolution: "agent-dir",
6171
- correlatesBySessionId: true
6276
+ correlatesBySessionId: true,
6277
+ answersQuestionByMessage: false,
6278
+ askAnswerDelivery: "message",
6279
+ runsOnFlyMachine: true
6172
6280
  };
6173
6281
  const ACP_CAPABILITIES = {
6174
6282
  contextChannel: "acp-initial-context",
@@ -6183,10 +6291,15 @@ const ACP_CAPABILITIES = {
6183
6291
  hostEffortFlag: false,
6184
6292
  binaryLabel: "Kimi Code CLI",
6185
6293
  installHint: null,
6294
+ updateArgs: ["upgrade", "--yes"],
6295
+ npmPackage: null,
6186
6296
  binaryConfigKey: "acp.kimi.binaryPath",
6187
6297
  launchPreflight: null,
6188
6298
  workspaceResolution: "agent-dir",
6189
- correlatesBySessionId: true
6299
+ correlatesBySessionId: true,
6300
+ answersQuestionByMessage: false,
6301
+ askAnswerDelivery: "message",
6302
+ runsOnFlyMachine: false
6190
6303
  };
6191
6304
  const KIMI_CODE_CAPABILITIES = {
6192
6305
  contextChannel: "initial-message-envelope",
@@ -6201,10 +6314,15 @@ const KIMI_CODE_CAPABILITIES = {
6201
6314
  hostEffortFlag: false,
6202
6315
  binaryLabel: "Kimi Code CLI",
6203
6316
  installHint: null,
6317
+ updateArgs: ["upgrade", "--yes"],
6318
+ npmPackage: null,
6204
6319
  binaryConfigKey: "kimiCode.binaryPath",
6205
6320
  launchPreflight: null,
6206
6321
  workspaceResolution: "first-message-only",
6207
- correlatesBySessionId: true
6322
+ correlatesBySessionId: true,
6323
+ answersQuestionByMessage: false,
6324
+ askAnswerDelivery: "message",
6325
+ runsOnFlyMachine: false
6208
6326
  };
6209
6327
  const OPENCODE_CAPABILITIES = {
6210
6328
  contextChannel: "acp-initial-context",
@@ -6219,10 +6337,15 @@ const OPENCODE_CAPABILITIES = {
6219
6337
  hostEffortFlag: true,
6220
6338
  binaryLabel: "OpenCode",
6221
6339
  installHint: null,
6340
+ updateArgs: ["upgrade"],
6341
+ npmPackage: "opencode-ai",
6222
6342
  binaryConfigKey: null,
6223
6343
  launchPreflight: null,
6224
6344
  workspaceResolution: "agent-dir",
6225
- correlatesBySessionId: true
6345
+ correlatesBySessionId: true,
6346
+ answersQuestionByMessage: false,
6347
+ askAnswerDelivery: "message",
6348
+ runsOnFlyMachine: false
6226
6349
  };
6227
6350
  const MUSE_CAPABILITIES = {
6228
6351
  contextChannel: "append-system-prompt-file",
@@ -6237,10 +6360,15 @@ const MUSE_CAPABILITIES = {
6237
6360
  hostEffortFlag: false,
6238
6361
  binaryLabel: "Muse Code",
6239
6362
  installHint: null,
6363
+ updateArgs: null,
6364
+ npmPackage: null,
6240
6365
  binaryConfigKey: null,
6241
6366
  launchPreflight: null,
6242
6367
  workspaceResolution: "first-message-only",
6243
- correlatesBySessionId: true
6368
+ correlatesBySessionId: true,
6369
+ answersQuestionByMessage: false,
6370
+ askAnswerDelivery: "message",
6371
+ runsOnFlyMachine: false
6244
6372
  };
6245
6373
  const PRIME_AGENT_CAPABILITIES = {
6246
6374
  contextChannel: "prime-agent-append-system-prompt",
@@ -6255,10 +6383,15 @@ const PRIME_AGENT_CAPABILITIES = {
6255
6383
  hostEffortFlag: false,
6256
6384
  binaryLabel: "Prime Agent",
6257
6385
  installHint: null,
6386
+ updateArgs: null,
6387
+ npmPackage: null,
6258
6388
  binaryConfigKey: null,
6259
6389
  launchPreflight: null,
6260
6390
  workspaceResolution: "first-message-only",
6261
- correlatesBySessionId: true
6391
+ correlatesBySessionId: true,
6392
+ answersQuestionByMessage: false,
6393
+ askAnswerDelivery: "message",
6394
+ runsOnFlyMachine: false
6262
6395
  };
6263
6396
  //#endregion
6264
6397
  //#region src/harness-behavior.ts
@@ -6686,7 +6819,12 @@ const TELEMETRY_CLI_VERBS = [
6686
6819
  ];
6687
6820
  const TELEMETRY_PROPERTY_DOMAINS = {
6688
6821
  agent_spawn_mode: ["spawn-and-send", "spawn-work-and-send"],
6689
- answer_type: ["custom", "selection"],
6822
+ answer_type: [
6823
+ "custom",
6824
+ "selection",
6825
+ "note",
6826
+ "selection+note"
6827
+ ],
6690
6828
  auto_merge_variant: ["segmented", "badge"],
6691
6829
  boolean: [false, true],
6692
6830
  cli_verb: TELEMETRY_CLI_VERBS,
@@ -7219,29 +7357,35 @@ const COMPOSER_COMMAND_MANIFEST = [
7219
7357
  "add"
7220
7358
  ],
7221
7359
  "display": "/pan skills pack add",
7222
- "description": "Register a git skill pack at the commit a ref resolves to (enables nothing)",
7360
+ "description": "Register a git skill pack at the commit a ref resolves to (enables nothing); known packs default the url and ref",
7223
7361
  "args": [{
7224
7362
  "name": "id",
7225
7363
  "required": true,
7226
7364
  "variadic": false
7227
7365
  }, {
7228
7366
  "name": "url",
7229
- "required": true,
7367
+ "required": false,
7230
7368
  "variadic": false
7231
7369
  }],
7232
7370
  "options": [
7233
7371
  {
7234
7372
  "flags": "--ref <ref>",
7235
- "description": "Tag or branch to pin",
7373
+ "description": "Tag, branch or commit to pin (default: the known pack ref)",
7236
7374
  "required": true,
7237
7375
  "valueHint": "ref"
7238
7376
  },
7239
7377
  {
7240
7378
  "flags": "--adapter <adapter>",
7241
- "description": "plain, claude-plugin, or deft-readonly",
7379
+ "description": "plain, claude-plugin, deft-readonly, or gstack-runtime",
7242
7380
  "required": true,
7243
7381
  "valueHint": "adapter"
7244
7382
  },
7383
+ {
7384
+ "flags": "--browser",
7385
+ "description": "Also build the browser runtime (gstack; asks separately)",
7386
+ "required": false,
7387
+ "valueHint": null
7388
+ },
7245
7389
  {
7246
7390
  "flags": "--yes",
7247
7391
  "description": "Trust the resolved commit without asking",
@@ -7280,6 +7424,33 @@ const COMPOSER_COMMAND_MANIFEST = [
7280
7424
  "aliases": [],
7281
7425
  "category": "Core"
7282
7426
  },
7427
+ {
7428
+ "id": "pan-skills-pack-browser",
7429
+ "path": [
7430
+ "skills",
7431
+ "pack",
7432
+ "browser"
7433
+ ],
7434
+ "display": "/pan skills pack browser",
7435
+ "description": "Turn a runtime pack's browser runtime on or off (gstack)",
7436
+ "args": [{
7437
+ "name": "id",
7438
+ "required": true,
7439
+ "variadic": false
7440
+ }, {
7441
+ "name": "state",
7442
+ "required": false,
7443
+ "variadic": false
7444
+ }],
7445
+ "options": [{
7446
+ "flags": "--yes",
7447
+ "description": "Trust without asking",
7448
+ "required": false,
7449
+ "valueHint": null
7450
+ }],
7451
+ "aliases": [],
7452
+ "category": "Core"
7453
+ },
7283
7454
  {
7284
7455
  "id": "pan-skills-pack-list",
7285
7456
  "path": [
@@ -7348,7 +7519,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7348
7519
  "gc"
7349
7520
  ],
7350
7521
  "display": "/pan skills pack gc",
7351
- "description": "Remove unused skill pack mounts and dangling launch links",
7522
+ "description": "Remove unused skill pack mounts, dangling launch links, stale renders and orphaned pack state",
7352
7523
  "args": [],
7353
7524
  "options": [{
7354
7525
  "flags": "--max-age-days <n>",
@@ -7426,7 +7597,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7426
7597
  "id": "pan-skills-deft",
7427
7598
  "path": ["skills", "deft"],
7428
7599
  "display": "/pan skills deft",
7429
- "description": "Deft Directive detection, ownership report, and managed mode",
7600
+ "description": "Deft Directive detection, managed mode, and running an issue on Deft",
7430
7601
  "args": [],
7431
7602
  "options": [],
7432
7603
  "aliases": [],
@@ -7499,6 +7670,98 @@ const COMPOSER_COMMAND_MANIFEST = [
7499
7670
  "aliases": [],
7500
7671
  "category": "Core"
7501
7672
  },
7673
+ {
7674
+ "id": "pan-skills-deft-use",
7675
+ "path": [
7676
+ "skills",
7677
+ "deft",
7678
+ "use"
7679
+ ],
7680
+ "display": "/pan skills deft use",
7681
+ "description": "Run an issue on Deft Directive's pipeline: install Directive into its workspace, hidden from git",
7682
+ "args": [{
7683
+ "name": "issue",
7684
+ "required": true,
7685
+ "variadic": false
7686
+ }],
7687
+ "options": [{
7688
+ "flags": "--start",
7689
+ "description": "Start the work agent afterwards (pan start)",
7690
+ "required": false,
7691
+ "valueHint": null
7692
+ }, {
7693
+ "flags": "--json",
7694
+ "description": "Output as JSON",
7695
+ "required": false,
7696
+ "valueHint": null
7697
+ }],
7698
+ "aliases": [],
7699
+ "category": "Core"
7700
+ },
7701
+ {
7702
+ "id": "pan-skills-deft-back",
7703
+ "path": [
7704
+ "skills",
7705
+ "deft",
7706
+ "back"
7707
+ ],
7708
+ "display": "/pan skills deft back",
7709
+ "description": "Switch an issue back to Overdeck's pipeline: save the Deft state, then remove the install",
7710
+ "args": [{
7711
+ "name": "issue",
7712
+ "required": true,
7713
+ "variadic": false
7714
+ }],
7715
+ "options": [{
7716
+ "flags": "--json",
7717
+ "description": "Output as JSON",
7718
+ "required": false,
7719
+ "valueHint": null
7720
+ }],
7721
+ "aliases": [],
7722
+ "category": "Core"
7723
+ },
7724
+ {
7725
+ "id": "pan-skills-deft-save",
7726
+ "path": [
7727
+ "skills",
7728
+ "deft",
7729
+ "save"
7730
+ ],
7731
+ "display": "/pan skills deft save",
7732
+ "description": "Commit the issue's Deft state archive under .pan/deft/<ISSUE>/",
7733
+ "args": [{
7734
+ "name": "issue",
7735
+ "required": true,
7736
+ "variadic": false
7737
+ }],
7738
+ "options": [],
7739
+ "aliases": [],
7740
+ "category": "Core"
7741
+ },
7742
+ {
7743
+ "id": "pan-skills-deft-show",
7744
+ "path": [
7745
+ "skills",
7746
+ "deft",
7747
+ "show"
7748
+ ],
7749
+ "display": "/pan skills deft show",
7750
+ "description": "Show an issue's pipeline, Deft install, drift, and merge-guard verdict",
7751
+ "args": [{
7752
+ "name": "issue",
7753
+ "required": true,
7754
+ "variadic": false
7755
+ }],
7756
+ "options": [{
7757
+ "flags": "--json",
7758
+ "description": "Output as JSON",
7759
+ "required": false,
7760
+ "valueHint": null
7761
+ }],
7762
+ "aliases": [],
7763
+ "category": "Core"
7764
+ },
7502
7765
  {
7503
7766
  "id": "pan-pair",
7504
7767
  "path": ["pair"],
@@ -7568,48 +7831,63 @@ const COMPOSER_COMMAND_MANIFEST = [
7568
7831
  "category": "CLI"
7569
7832
  },
7570
7833
  {
7571
- "id": "pan-token",
7572
- "path": ["token"],
7573
- "display": "/pan token",
7574
- "description": "Create, list or revoke scoped access tokens (see configuration/remote-access.mdx)",
7834
+ "id": "pan-machines",
7835
+ "path": ["machines"],
7836
+ "display": "/pan machines",
7837
+ "description": "Link this dashboard to other machines and manage the links (see configuration/linked-machines.mdx)",
7575
7838
  "args": [],
7576
7839
  "options": [],
7577
7840
  "aliases": [],
7578
7841
  "category": "CLI"
7579
7842
  },
7580
7843
  {
7581
- "id": "pan-token-create",
7582
- "path": ["token", "create"],
7583
- "display": "/pan token create",
7584
- "description": "Create a scoped access token and print it once",
7844
+ "id": "pan-machines-link",
7845
+ "path": ["machines", "link"],
7846
+ "display": "/pan machines link",
7847
+ "description": "Link to the machine whose `pan pair` link this is (links both ways unless --one-way)",
7585
7848
  "args": [{
7586
- "name": "name",
7849
+ "name": "pairing-url",
7587
7850
  "required": true,
7588
7851
  "variadic": false
7589
7852
  }],
7590
- "options": [{
7591
- "flags": "--scopes <list>",
7592
- "description": "Comma-separated scopes: read:events, read:state, read:conversations, tell, operate, admin",
7593
- "required": true,
7594
- "valueHint": "list"
7595
- }, {
7596
- "flags": "--json",
7597
- "description": "Print { id, name, scopes, token } as JSON",
7598
- "required": false,
7599
- "valueHint": null
7600
- }],
7853
+ "options": [
7854
+ {
7855
+ "flags": "--one-way",
7856
+ "description": "Only this machine reaches the other; do not give it a link back",
7857
+ "required": false,
7858
+ "valueHint": null
7859
+ },
7860
+ {
7861
+ "flags": "--agent-fenced",
7862
+ "description": "Agent-fenced access: forwarded requests are never operator-level",
7863
+ "required": false,
7864
+ "valueHint": null
7865
+ },
7866
+ {
7867
+ "flags": "--allow-loopback",
7868
+ "description": "Accept a localhost pairing link (both servers on this host)",
7869
+ "required": false,
7870
+ "valueHint": null
7871
+ },
7872
+ {
7873
+ "flags": "--json",
7874
+ "description": "Print the new link as JSON",
7875
+ "required": false,
7876
+ "valueHint": null
7877
+ }
7878
+ ],
7601
7879
  "aliases": [],
7602
7880
  "category": "CLI"
7603
7881
  },
7604
7882
  {
7605
- "id": "pan-token-list",
7606
- "path": ["token", "list"],
7607
- "display": "/pan token list",
7608
- "description": "List access tokens with scopes and created, last-used and revoked times",
7883
+ "id": "pan-machines-list",
7884
+ "path": ["machines", "list"],
7885
+ "display": "/pan machines list",
7886
+ "description": "List linked machines with state and route, then the machines that link here",
7609
7887
  "args": [],
7610
7888
  "options": [{
7611
7889
  "flags": "--json",
7612
- "description": "Print the tokens as JSON",
7890
+ "description": "Print { self, links, inbound } as JSON",
7613
7891
  "required": false,
7614
7892
  "valueHint": null
7615
7893
  }],
@@ -7617,84 +7895,758 @@ const COMPOSER_COMMAND_MANIFEST = [
7617
7895
  "category": "CLI"
7618
7896
  },
7619
7897
  {
7620
- "id": "pan-token-revoke",
7621
- "path": ["token", "revoke"],
7622
- "display": "/pan token revoke",
7623
- "description": "Revoke an access token and close its live connections",
7898
+ "id": "pan-machines-unlink",
7899
+ "path": ["machines", "unlink"],
7900
+ "display": "/pan machines unlink",
7901
+ "description": "Remove a link by label, environment id or link id, revoking the token the other machine holds",
7624
7902
  "args": [{
7625
- "name": "id",
7903
+ "name": "target",
7626
7904
  "required": true,
7627
7905
  "variadic": false
7628
7906
  }],
7629
- "options": [],
7907
+ "options": [{
7908
+ "flags": "--keep-server",
7909
+ "description": "For an SSH machine this dashboard started: leave its Overdeck server running; for a Fly machine: do not destroy it",
7910
+ "required": false,
7911
+ "valueHint": null
7912
+ }, {
7913
+ "flags": "--json",
7914
+ "description": "Print { ok, peerNotified, ssh, fly } as JSON",
7915
+ "required": false,
7916
+ "valueHint": null
7917
+ }],
7630
7918
  "aliases": [],
7631
7919
  "category": "CLI"
7632
7920
  },
7633
7921
  {
7634
- "id": "pan-issues",
7635
- "path": ["issues"],
7636
- "display": "/pan issues",
7637
- "description": "List and triage work across configured trackers",
7638
- "args": [],
7922
+ "id": "pan-machines-forward",
7923
+ "path": ["machines", "forward"],
7924
+ "display": "/pan machines forward",
7925
+ "description": "Forward a TCP port of a linked machine to 127.0.0.1 here and print the URL (for a dev-server preview)",
7926
+ "args": [{
7927
+ "name": "machine",
7928
+ "required": false,
7929
+ "variadic": false
7930
+ }, {
7931
+ "name": "port",
7932
+ "required": false,
7933
+ "variadic": false
7934
+ }],
7639
7935
  "options": [
7640
7936
  {
7641
- "flags": "--all",
7642
- "description": "Include closed issues",
7643
- "required": false,
7644
- "valueHint": null
7645
- },
7646
- {
7647
- "flags": "--mine",
7648
- "description": "Show only my assigned issues",
7649
- "required": false,
7650
- "valueHint": null
7651
- },
7652
- {
7653
- "flags": "--json",
7654
- "description": "Output as JSON",
7937
+ "flags": "--list",
7938
+ "description": "List the open forwards",
7655
7939
  "required": false,
7656
7940
  "valueHint": null
7657
7941
  },
7658
7942
  {
7659
- "flags": "--tracker <type>",
7660
- "description": "Query specific tracker (linear/github/gitlab)",
7943
+ "flags": "--stop <id>",
7944
+ "description": "Close a forward",
7661
7945
  "required": true,
7662
- "valueHint": "type"
7663
- },
7664
- {
7665
- "flags": "--all-trackers",
7666
- "description": "Query all configured trackers",
7667
- "required": false,
7668
- "valueHint": null
7946
+ "valueHint": "id"
7669
7947
  },
7670
7948
  {
7671
- "flags": "--triage",
7672
- "description": "Show triage queue",
7949
+ "flags": "--json",
7950
+ "description": "Print JSON",
7673
7951
  "required": false,
7674
7952
  "valueHint": null
7675
7953
  }
7676
7954
  ],
7677
7955
  "aliases": [],
7678
- "category": "Lifecycle"
7956
+ "category": "CLI"
7679
7957
  },
7680
7958
  {
7681
- "id": "pan-show",
7682
- "path": ["show"],
7683
- "display": "/pan show",
7684
- "description": "Unified lens: derived issue state, CV, context, health for one issue",
7685
- "args": [{
7686
- "name": "id",
7687
- "required": true,
7688
- "variadic": false
7959
+ "id": "pan-machines-directory",
7960
+ "path": ["machines", "directory"],
7961
+ "display": "/pan machines directory",
7962
+ "description": "List this account's machines in the overdeck.ai directory, with pending approvals and joins",
7963
+ "args": [],
7964
+ "options": [{
7965
+ "flags": "--json",
7966
+ "description": "Print the GET /api/directory response as JSON",
7967
+ "required": false,
7968
+ "valueHint": null
7689
7969
  }],
7690
- "options": [
7691
- {
7692
- "flags": "--cv",
7693
- "description": "Agent work history only",
7694
- "required": false,
7695
- "valueHint": null
7696
- },
7697
- {
7970
+ "aliases": [],
7971
+ "category": "CLI"
7972
+ },
7973
+ {
7974
+ "id": "pan-machines-join",
7975
+ "path": ["machines", "join"],
7976
+ "display": "/pan machines join",
7977
+ "description": "Ask your other machines (or one) to link with this one; confirm the code on both screens",
7978
+ "args": [],
7979
+ "options": [{
7980
+ "flags": "--to <machine>",
7981
+ "description": "Ask only this machine (label or environment id)",
7982
+ "required": true,
7983
+ "valueHint": "machine"
7984
+ }, {
7985
+ "flags": "--json",
7986
+ "description": "Print { requestId, sas, fingerprint, approver } as JSON once a machine opens the request",
7987
+ "required": false,
7988
+ "valueHint": null
7989
+ }],
7990
+ "aliases": [],
7991
+ "category": "CLI"
7992
+ },
7993
+ {
7994
+ "id": "pan-machines-accept",
7995
+ "path": ["machines", "accept"],
7996
+ "display": "/pan machines accept",
7997
+ "description": "Accept a join request after checking that both screens show the same code",
7998
+ "args": [{
7999
+ "name": "request-id",
8000
+ "required": true,
8001
+ "variadic": false
8002
+ }],
8003
+ "options": [],
8004
+ "aliases": [],
8005
+ "category": "CLI"
8006
+ },
8007
+ {
8008
+ "id": "pan-machines-reject",
8009
+ "path": ["machines", "reject"],
8010
+ "display": "/pan machines reject",
8011
+ "description": "Reject an approval or join request",
8012
+ "args": [{
8013
+ "name": "request-id",
8014
+ "required": true,
8015
+ "variadic": false
8016
+ }],
8017
+ "options": [],
8018
+ "aliases": [],
8019
+ "category": "CLI"
8020
+ },
8021
+ {
8022
+ "id": "pan-machines-approve",
8023
+ "path": ["machines", "approve"],
8024
+ "display": "/pan machines approve",
8025
+ "description": "Open an approval request, show its code and approve it",
8026
+ "args": [{
8027
+ "name": "request-id",
8028
+ "required": true,
8029
+ "variadic": false
8030
+ }],
8031
+ "options": [{
8032
+ "flags": "--yes",
8033
+ "description": "Approve without asking",
8034
+ "required": false,
8035
+ "valueHint": null
8036
+ }],
8037
+ "aliases": [],
8038
+ "category": "CLI"
8039
+ },
8040
+ {
8041
+ "id": "pan-machines-forget",
8042
+ "path": ["machines", "forget"],
8043
+ "display": "/pan machines forget",
8044
+ "description": "Remove a machine from the overdeck.ai directory (label or environment id)",
8045
+ "args": [{
8046
+ "name": "machine",
8047
+ "required": true,
8048
+ "variadic": false
8049
+ }],
8050
+ "options": [],
8051
+ "aliases": [],
8052
+ "category": "CLI"
8053
+ },
8054
+ {
8055
+ "id": "pan-machines-versions",
8056
+ "path": ["machines", "versions"],
8057
+ "display": "/pan machines versions",
8058
+ "description": "Show Overdeck and harness CLI versions on every machine",
8059
+ "args": [],
8060
+ "options": [{
8061
+ "flags": "--json",
8062
+ "description": "Print { rows } as JSON",
8063
+ "required": false,
8064
+ "valueHint": null
8065
+ }],
8066
+ "aliases": [],
8067
+ "category": "CLI"
8068
+ },
8069
+ {
8070
+ "id": "pan-machines-update",
8071
+ "path": ["machines", "update"],
8072
+ "display": "/pan machines update",
8073
+ "description": "Update Overdeck and the harness CLIs on every online machine, after running turns end",
8074
+ "args": [],
8075
+ "options": [
8076
+ {
8077
+ "flags": "--now",
8078
+ "description": "Do not wait for running turns to end",
8079
+ "required": false,
8080
+ "valueHint": null
8081
+ },
8082
+ {
8083
+ "flags": "--machine <label>",
8084
+ "description": "Only this machine; repeat for more",
8085
+ "required": true,
8086
+ "valueHint": "label"
8087
+ },
8088
+ {
8089
+ "flags": "--cancel",
8090
+ "description": "Cancel waiting updates",
8091
+ "required": false,
8092
+ "valueHint": null
8093
+ },
8094
+ {
8095
+ "flags": "--json",
8096
+ "description": "Print { started, skipped } as JSON",
8097
+ "required": false,
8098
+ "valueHint": null
8099
+ }
8100
+ ],
8101
+ "aliases": [],
8102
+ "category": "CLI"
8103
+ },
8104
+ {
8105
+ "id": "pan-machines-add-ssh",
8106
+ "path": ["machines", "add-ssh"],
8107
+ "display": "/pan machines add-ssh",
8108
+ "description": "Link a machine reached over SSH: this dashboard starts or adopts Overdeck there and forwards a port to it",
8109
+ "args": [{
8110
+ "name": "host",
8111
+ "required": true,
8112
+ "variadic": false
8113
+ }],
8114
+ "options": [
8115
+ {
8116
+ "flags": "--pan-path <path>",
8117
+ "description": "Absolute path to pan on the host (default: pan from its login PATH)",
8118
+ "required": true,
8119
+ "valueHint": "path"
8120
+ },
8121
+ {
8122
+ "flags": "--one-way",
8123
+ "description": "Only this machine reaches the other; do not give it a link back",
8124
+ "required": false,
8125
+ "valueHint": null
8126
+ },
8127
+ {
8128
+ "flags": "--agent-fenced",
8129
+ "description": "Agent-fenced access: forwarded requests are never operator-level",
8130
+ "required": false,
8131
+ "valueHint": null
8132
+ },
8133
+ {
8134
+ "flags": "--json",
8135
+ "description": "Print the new link as JSON",
8136
+ "required": false,
8137
+ "valueHint": null
8138
+ }
8139
+ ],
8140
+ "aliases": [],
8141
+ "category": "CLI"
8142
+ },
8143
+ {
8144
+ "id": "pan-machines-test-ssh",
8145
+ "path": ["machines", "test-ssh"],
8146
+ "display": "/pan machines test-ssh",
8147
+ "description": "Check that this dashboard reaches <host> over SSH and that it has the same pan version",
8148
+ "args": [{
8149
+ "name": "host",
8150
+ "required": true,
8151
+ "variadic": false
8152
+ }],
8153
+ "options": [{
8154
+ "flags": "--pan-path <path>",
8155
+ "description": "Absolute path to pan on the host (default: pan from its login PATH)",
8156
+ "required": true,
8157
+ "valueHint": "path"
8158
+ }, {
8159
+ "flags": "--json",
8160
+ "description": "Print { reachable, panVersion, localVersion, versionMatches, error, message } as JSON",
8161
+ "required": false,
8162
+ "valueHint": null
8163
+ }],
8164
+ "aliases": [],
8165
+ "category": "CLI"
8166
+ },
8167
+ {
8168
+ "id": "pan-machines-add-project",
8169
+ "path": ["machines", "add-project"],
8170
+ "display": "/pan machines add-project",
8171
+ "description": "Clone a linked machine's project here (or, with --to, this machine's project there) and copy its .env-style files (0600, never overwriting)",
8172
+ "args": [{
8173
+ "name": "machine",
8174
+ "required": true,
8175
+ "variadic": false
8176
+ }, {
8177
+ "name": "project-key",
8178
+ "required": true,
8179
+ "variadic": false
8180
+ }],
8181
+ "options": [
8182
+ {
8183
+ "flags": "--to <machine>",
8184
+ "description": "Add this machine's project <project-key> to <machine> instead",
8185
+ "required": true,
8186
+ "valueHint": "machine"
8187
+ },
8188
+ {
8189
+ "flags": "--file <path>",
8190
+ "description": "Also copy this git-ignored file; repeat for more",
8191
+ "required": true,
8192
+ "valueHint": "path"
8193
+ },
8194
+ {
8195
+ "flags": "--no-env",
8196
+ "description": "Do not copy .env, .envrc and .dev.vars",
8197
+ "required": false,
8198
+ "valueHint": null
8199
+ },
8200
+ {
8201
+ "flags": "--parent-dir <dir>",
8202
+ "description": "Clone under this directory (default: the projects folder)",
8203
+ "required": true,
8204
+ "valueHint": "dir"
8205
+ },
8206
+ {
8207
+ "flags": "--json",
8208
+ "description": "Print the finished add job as JSON",
8209
+ "required": false,
8210
+ "valueHint": null
8211
+ }
8212
+ ],
8213
+ "aliases": [],
8214
+ "category": "CLI"
8215
+ },
8216
+ {
8217
+ "id": "pan-machines-who",
8218
+ "path": ["machines", "who"],
8219
+ "display": "/pan machines who",
8220
+ "description": "Show which machines run agents or conversations for an issue",
8221
+ "args": [{
8222
+ "name": "issue",
8223
+ "required": true,
8224
+ "variadic": false
8225
+ }],
8226
+ "options": [{
8227
+ "flags": "--json",
8228
+ "description": "Print the fleet answer as JSON",
8229
+ "required": false,
8230
+ "valueHint": null
8231
+ }],
8232
+ "aliases": [],
8233
+ "category": "CLI"
8234
+ },
8235
+ {
8236
+ "id": "pan-machines-add-fly",
8237
+ "path": ["machines", "add-fly"],
8238
+ "display": "/pan machines add-fly",
8239
+ "description": "Start a Fly.io VM that runs Overdeck, link it from here, and optionally start a Claude Code or Codex conversation on it",
8240
+ "args": [],
8241
+ "options": [
8242
+ {
8243
+ "flags": "--project <key>",
8244
+ "description": "Clone this project onto the VM (GitHub projects only)",
8245
+ "required": true,
8246
+ "valueHint": "key"
8247
+ },
8248
+ {
8249
+ "flags": "--message <text>",
8250
+ "description": "Start a conversation with this first message (needs --project)",
8251
+ "required": true,
8252
+ "valueHint": "text"
8253
+ },
8254
+ {
8255
+ "flags": "--harness <name>",
8256
+ "description": "Harness for the conversation: claude-code (default) or codex",
8257
+ "required": true,
8258
+ "valueHint": "name"
8259
+ },
8260
+ {
8261
+ "flags": "--model <id>",
8262
+ "description": "Model for the conversation (required with --harness codex)",
8263
+ "required": true,
8264
+ "valueHint": "id"
8265
+ },
8266
+ {
8267
+ "flags": "--effort <level>",
8268
+ "description": "Reasoning effort for the conversation",
8269
+ "required": true,
8270
+ "valueHint": "level"
8271
+ },
8272
+ {
8273
+ "flags": "--region <code>",
8274
+ "description": "Fly region (default: remote.fly.region, else iad)",
8275
+ "required": true,
8276
+ "valueHint": "code"
8277
+ },
8278
+ {
8279
+ "flags": "--image <ref>",
8280
+ "description": "Image (default: remote.fly.image, else registry.fly.io/<app>:latest)",
8281
+ "required": true,
8282
+ "valueHint": "ref"
8283
+ },
8284
+ {
8285
+ "flags": "--json",
8286
+ "description": "Print { link, record, conversation? } as JSON",
8287
+ "required": false,
8288
+ "valueHint": null
8289
+ }
8290
+ ],
8291
+ "aliases": [],
8292
+ "category": "CLI"
8293
+ },
8294
+ {
8295
+ "id": "pan-connect",
8296
+ "path": ["connect"],
8297
+ "display": "/pan connect",
8298
+ "description": "Install this machine's server as a lasting service and print one link that links it from another machine (see cli/machines.mdx)",
8299
+ "args": [],
8300
+ "options": [
8301
+ {
8302
+ "flags": "--url <base>",
8303
+ "description": "Address another machine reaches this one at (default: picked automatically)",
8304
+ "required": true,
8305
+ "valueHint": "base"
8306
+ },
8307
+ {
8308
+ "flags": "--label <name>",
8309
+ "description": "Name recorded for the pairing in the activity log",
8310
+ "required": true,
8311
+ "valueHint": "name"
8312
+ },
8313
+ {
8314
+ "flags": "--json",
8315
+ "description": "Print the result as JSON",
8316
+ "required": false,
8317
+ "valueHint": null
8318
+ }
8319
+ ],
8320
+ "aliases": [],
8321
+ "category": "CLI"
8322
+ },
8323
+ {
8324
+ "id": "pan-tailscale",
8325
+ "path": ["tailscale"],
8326
+ "display": "/pan tailscale",
8327
+ "description": "Reach this machine over Tailscale: state, setup and tailnet peers (see configuration/tailscale.mdx)",
8328
+ "args": [],
8329
+ "options": [],
8330
+ "aliases": [],
8331
+ "category": "CLI"
8332
+ },
8333
+ {
8334
+ "id": "pan-tailscale-status",
8335
+ "path": ["tailscale", "status"],
8336
+ "display": "/pan tailscale status",
8337
+ "description": "Show Tailscale state, the next setup step and Overdeck machines on the tailnet",
8338
+ "args": [],
8339
+ "options": [{
8340
+ "flags": "--json",
8341
+ "description": "Print { state, peers } as JSON",
8342
+ "required": false,
8343
+ "valueHint": null
8344
+ }],
8345
+ "aliases": [],
8346
+ "category": "CLI"
8347
+ },
8348
+ {
8349
+ "id": "pan-tailscale-setup",
8350
+ "path": ["tailscale", "setup"],
8351
+ "display": "/pan tailscale setup",
8352
+ "description": "Install Tailscale, sign in and turn on protected HTTPS access to this dashboard",
8353
+ "args": [],
8354
+ "options": [{
8355
+ "flags": "--userspace",
8356
+ "description": "On Linux, install for this user without an administrator password",
8357
+ "required": false,
8358
+ "valueHint": null
8359
+ }],
8360
+ "aliases": [],
8361
+ "category": "CLI"
8362
+ },
8363
+ {
8364
+ "id": "pan-token",
8365
+ "path": ["token"],
8366
+ "display": "/pan token",
8367
+ "description": "Create, list or revoke scoped access tokens (see configuration/remote-access.mdx)",
8368
+ "args": [],
8369
+ "options": [],
8370
+ "aliases": [],
8371
+ "category": "CLI"
8372
+ },
8373
+ {
8374
+ "id": "pan-token-create",
8375
+ "path": ["token", "create"],
8376
+ "display": "/pan token create",
8377
+ "description": "Create a scoped access token and print it once",
8378
+ "args": [{
8379
+ "name": "name",
8380
+ "required": true,
8381
+ "variadic": false
8382
+ }],
8383
+ "options": [{
8384
+ "flags": "--scopes <list>",
8385
+ "description": "Comma-separated scopes: read:events, read:state, read:conversations, read:costs, read:settings, tell, operate, approve, forward, admin",
8386
+ "required": true,
8387
+ "valueHint": "list"
8388
+ }, {
8389
+ "flags": "--json",
8390
+ "description": "Print { id, name, scopes, token } as JSON",
8391
+ "required": false,
8392
+ "valueHint": null
8393
+ }],
8394
+ "aliases": [],
8395
+ "category": "CLI"
8396
+ },
8397
+ {
8398
+ "id": "pan-token-list",
8399
+ "path": ["token", "list"],
8400
+ "display": "/pan token list",
8401
+ "description": "List access tokens with scopes and created, last-used and revoked times",
8402
+ "args": [],
8403
+ "options": [{
8404
+ "flags": "--json",
8405
+ "description": "Print the tokens as JSON",
8406
+ "required": false,
8407
+ "valueHint": null
8408
+ }],
8409
+ "aliases": [],
8410
+ "category": "CLI"
8411
+ },
8412
+ {
8413
+ "id": "pan-token-revoke",
8414
+ "path": ["token", "revoke"],
8415
+ "display": "/pan token revoke",
8416
+ "description": "Revoke an access token and close its live connections",
8417
+ "args": [{
8418
+ "name": "id",
8419
+ "required": true,
8420
+ "variadic": false
8421
+ }],
8422
+ "options": [],
8423
+ "aliases": [],
8424
+ "category": "CLI"
8425
+ },
8426
+ {
8427
+ "id": "pan-mcp",
8428
+ "path": ["mcp"],
8429
+ "display": "/pan mcp",
8430
+ "description": "Serve Overdeck to MCP clients (see configuration/mcp.mdx)",
8431
+ "args": [],
8432
+ "options": [],
8433
+ "aliases": [],
8434
+ "category": "CLI"
8435
+ },
8436
+ {
8437
+ "id": "pan-mcp-serve",
8438
+ "path": ["mcp", "serve"],
8439
+ "display": "/pan mcp serve",
8440
+ "description": "Serve Overdeck as an MCP server over stdio (token from OVERDECK_MCP_TOKEN; see configuration/mcp.mdx)",
8441
+ "args": [],
8442
+ "options": [],
8443
+ "aliases": [],
8444
+ "category": "CLI"
8445
+ },
8446
+ {
8447
+ "id": "pan-triggers",
8448
+ "path": ["triggers"],
8449
+ "display": "/pan triggers",
8450
+ "description": "Manage webhook triggers that message or start conversations (see configuration/triggers.mdx)",
8451
+ "args": [],
8452
+ "options": [],
8453
+ "aliases": [],
8454
+ "category": "CLI"
8455
+ },
8456
+ {
8457
+ "id": "pan-triggers-add",
8458
+ "path": ["triggers", "add"],
8459
+ "display": "/pan triggers add",
8460
+ "description": "Create a trigger and print its secret URL once",
8461
+ "args": [{
8462
+ "name": "name",
8463
+ "required": true,
8464
+ "variadic": false
8465
+ }],
8466
+ "options": [
8467
+ {
8468
+ "flags": "--conversation <name-or-id>",
8469
+ "description": "Send each event as a message to this conversation",
8470
+ "required": true,
8471
+ "valueHint": "name-or-id"
8472
+ },
8473
+ {
8474
+ "flags": "--project <key>",
8475
+ "description": "Start a new conversation in this project for each event",
8476
+ "required": true,
8477
+ "valueHint": "key"
8478
+ },
8479
+ {
8480
+ "flags": "--prompt <text>",
8481
+ "description": "Prompt template placed before the event (required for --project)",
8482
+ "required": true,
8483
+ "valueHint": "text"
8484
+ },
8485
+ {
8486
+ "flags": "--prompt-file <path>",
8487
+ "description": "Read the prompt template from a file",
8488
+ "required": true,
8489
+ "valueHint": "path"
8490
+ },
8491
+ {
8492
+ "flags": "--verify <kind>",
8493
+ "description": "Signature check: none, github or stripe",
8494
+ "required": true,
8495
+ "valueHint": "kind"
8496
+ },
8497
+ {
8498
+ "flags": "--signing-secret <value>",
8499
+ "description": "HMAC signing secret (github generates one when omitted)",
8500
+ "required": true,
8501
+ "valueHint": "value"
8502
+ },
8503
+ {
8504
+ "flags": "--model <id>",
8505
+ "description": "Model for conversations a project trigger starts",
8506
+ "required": true,
8507
+ "valueHint": "id"
8508
+ },
8509
+ {
8510
+ "flags": "--harness <name>",
8511
+ "description": "Harness for conversations a project trigger starts",
8512
+ "required": true,
8513
+ "valueHint": "name"
8514
+ },
8515
+ {
8516
+ "flags": "--effort <level>",
8517
+ "description": "Reasoning effort for conversations a project trigger starts",
8518
+ "required": true,
8519
+ "valueHint": "level"
8520
+ },
8521
+ {
8522
+ "flags": "--inbox",
8523
+ "description": "Hold events while this machine is offline in an overdeck.ai inbox (Anywhere plan; needs the dashboard)",
8524
+ "required": false,
8525
+ "valueHint": null
8526
+ },
8527
+ {
8528
+ "flags": "--json",
8529
+ "description": "Print { trigger, hookPath, url, localUrl, funnelCommand, generatedSigningSecret } as JSON",
8530
+ "required": false,
8531
+ "valueHint": null
8532
+ }
8533
+ ],
8534
+ "aliases": [],
8535
+ "category": "CLI"
8536
+ },
8537
+ {
8538
+ "id": "pan-triggers-list",
8539
+ "path": ["triggers", "list"],
8540
+ "display": "/pan triggers list",
8541
+ "description": "List triggers with their targets and verification; never prints secrets",
8542
+ "args": [],
8543
+ "options": [{
8544
+ "flags": "--json",
8545
+ "description": "Print the triggers as JSON",
8546
+ "required": false,
8547
+ "valueHint": null
8548
+ }],
8549
+ "aliases": [],
8550
+ "category": "CLI"
8551
+ },
8552
+ {
8553
+ "id": "pan-triggers-remove",
8554
+ "path": ["triggers", "remove"],
8555
+ "display": "/pan triggers remove",
8556
+ "description": "Remove a trigger; its URL answers 404 at once",
8557
+ "args": [{
8558
+ "name": "id",
8559
+ "required": true,
8560
+ "variadic": false
8561
+ }],
8562
+ "options": [],
8563
+ "aliases": [],
8564
+ "category": "CLI"
8565
+ },
8566
+ {
8567
+ "id": "pan-triggers-set-secret",
8568
+ "path": ["triggers", "set-secret"],
8569
+ "display": "/pan triggers set-secret",
8570
+ "description": "Set the signing secret of a github or stripe trigger (reads one line from stdin without --secret)",
8571
+ "args": [{
8572
+ "name": "id",
8573
+ "required": true,
8574
+ "variadic": false
8575
+ }],
8576
+ "options": [{
8577
+ "flags": "--secret <value>",
8578
+ "description": "The signing secret",
8579
+ "required": true,
8580
+ "valueHint": "value"
8581
+ }],
8582
+ "aliases": [],
8583
+ "category": "CLI"
8584
+ },
8585
+ {
8586
+ "id": "pan-issues",
8587
+ "path": ["issues"],
8588
+ "display": "/pan issues",
8589
+ "description": "List and triage work across configured trackers",
8590
+ "args": [],
8591
+ "options": [
8592
+ {
8593
+ "flags": "--all",
8594
+ "description": "Include closed issues",
8595
+ "required": false,
8596
+ "valueHint": null
8597
+ },
8598
+ {
8599
+ "flags": "--mine",
8600
+ "description": "Show only my assigned issues",
8601
+ "required": false,
8602
+ "valueHint": null
8603
+ },
8604
+ {
8605
+ "flags": "--json",
8606
+ "description": "Output as JSON",
8607
+ "required": false,
8608
+ "valueHint": null
8609
+ },
8610
+ {
8611
+ "flags": "--tracker <type>",
8612
+ "description": "Query specific tracker (linear/github/gitlab)",
8613
+ "required": true,
8614
+ "valueHint": "type"
8615
+ },
8616
+ {
8617
+ "flags": "--all-trackers",
8618
+ "description": "Query all configured trackers",
8619
+ "required": false,
8620
+ "valueHint": null
8621
+ },
8622
+ {
8623
+ "flags": "--triage",
8624
+ "description": "Show triage queue",
8625
+ "required": false,
8626
+ "valueHint": null
8627
+ }
8628
+ ],
8629
+ "aliases": [],
8630
+ "category": "Lifecycle"
8631
+ },
8632
+ {
8633
+ "id": "pan-show",
8634
+ "path": ["show"],
8635
+ "display": "/pan show",
8636
+ "description": "Unified lens: derived issue state, CV, context, health for one issue",
8637
+ "args": [{
8638
+ "name": "id",
8639
+ "required": true,
8640
+ "variadic": false
8641
+ }],
8642
+ "options": [
8643
+ {
8644
+ "flags": "--cv",
8645
+ "description": "Agent work history only",
8646
+ "required": false,
8647
+ "valueHint": null
8648
+ },
8649
+ {
7698
8650
  "flags": "--context",
7699
8651
  "description": "Context engineering state only",
7700
8652
  "required": false,
@@ -7997,7 +8949,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7997
8949
  "id": "pan-tell",
7998
8950
  "path": ["tell"],
7999
8951
  "display": "/pan tell",
8000
- "description": "Send message to running agent",
8952
+ "description": "Send message to running agent, or to a linked machine's conversation as @<machine>/<conv>",
8001
8953
  "args": [{
8002
8954
  "name": "id",
8003
8955
  "required": true,
@@ -8007,17 +8959,32 @@ const COMPOSER_COMMAND_MANIFEST = [
8007
8959
  "required": true,
8008
8960
  "variadic": false
8009
8961
  }],
8010
- "options": [{
8011
- "flags": "--force",
8012
- "description": "Deliver even to a critic or verifier lane that already filed its verdict",
8013
- "required": false,
8014
- "valueHint": null
8015
- }, {
8016
- "flags": "--steer",
8017
- "description": "Interrupt the running turn and send now (Claude Code send-now; Ctrl+X Ctrl+S)",
8018
- "required": false,
8019
- "valueHint": null
8020
- }],
8962
+ "options": [
8963
+ {
8964
+ "flags": "--force",
8965
+ "description": "Deliver even to a critic or verifier lane that already filed its verdict",
8966
+ "required": false,
8967
+ "valueHint": null
8968
+ },
8969
+ {
8970
+ "flags": "--steer",
8971
+ "description": "Interrupt the running turn and send now (Claude Code send-now; Ctrl+X Ctrl+S)",
8972
+ "required": false,
8973
+ "valueHint": null
8974
+ },
8975
+ {
8976
+ "flags": "--when-limit-resets",
8977
+ "description": "Queue the message on the server; it sends when the conversation's usage limit resets (conversations only)",
8978
+ "required": false,
8979
+ "valueHint": null
8980
+ },
8981
+ {
8982
+ "flags": "--message-id <id>",
8983
+ "description": "Idempotency key: a repeat with the same id is delivered once",
8984
+ "required": true,
8985
+ "valueHint": "id"
8986
+ }
8987
+ ],
8021
8988
  "aliases": [],
8022
8989
  "category": "Lifecycle"
8023
8990
  },
@@ -8746,20 +9713,44 @@ const COMPOSER_COMMAND_MANIFEST = [
8746
9713
  "valueHint": null
8747
9714
  },
8748
9715
  {
8749
- "flags": "--host",
8750
- "description": "Bypass workspace docker stack-health gate and spawn on the host",
8751
- "required": false,
8752
- "valueHint": null
9716
+ "flags": "--host",
9717
+ "description": "Bypass workspace docker stack-health gate and spawn on the host",
9718
+ "required": false,
9719
+ "valueHint": null
9720
+ },
9721
+ {
9722
+ "flags": "--yes",
9723
+ "description": "Confirm --host in non-interactive contexts",
9724
+ "required": false,
9725
+ "valueHint": null
9726
+ },
9727
+ {
9728
+ "flags": "--skip-freshness",
9729
+ "description": "Bypass the plan-freshness preflight and spawn even if the plan names files deleted since it was written",
9730
+ "required": false,
9731
+ "valueHint": null
9732
+ },
9733
+ {
9734
+ "flags": "--machine <label|auto>",
9735
+ "description": "Start the issue agent on a linked machine (label or environment id), or auto to place it by load",
9736
+ "required": true,
9737
+ "valueHint": "label|auto"
8753
9738
  },
8754
9739
  {
8755
- "flags": "--yes",
8756
- "description": "Confirm --host in non-interactive contexts",
9740
+ "flags": "--needs <tags>",
9741
+ "description": "Comma-separated capability tags the machine must have (docker, gpu, ios-sim, …)",
9742
+ "required": true,
9743
+ "valueHint": "tags"
9744
+ },
9745
+ {
9746
+ "flags": "--push-first",
9747
+ "description": "With --machine: push unpushed workspace commits before starting on the other machine",
8757
9748
  "required": false,
8758
9749
  "valueHint": null
8759
9750
  },
8760
9751
  {
8761
- "flags": "--skip-freshness",
8762
- "description": "Bypass the plan-freshness preflight and spawn even if the plan names files deleted since it was written",
9752
+ "flags": "--ignore-unpushed",
9753
+ "description": "With --machine: start even though local workspace commits are not pushed",
8763
9754
  "required": false,
8764
9755
  "valueHint": null
8765
9756
  }
@@ -10236,6 +11227,56 @@ const COMPOSER_COMMAND_MANIFEST = [
10236
11227
  "aliases": [],
10237
11228
  "category": "CLI"
10238
11229
  },
11230
+ {
11231
+ "id": "pan-account",
11232
+ "path": ["account"],
11233
+ "display": "/pan account",
11234
+ "description": "Optional overdeck.ai sign-in for this machine (directory and hosted features)",
11235
+ "args": [],
11236
+ "options": [],
11237
+ "aliases": [],
11238
+ "category": "CLI"
11239
+ },
11240
+ {
11241
+ "id": "pan-account-login",
11242
+ "path": ["account", "login"],
11243
+ "display": "/pan account login",
11244
+ "description": "Sign in to overdeck.ai with the device flow and store this machine's device token",
11245
+ "args": [],
11246
+ "options": [{
11247
+ "flags": "--base-url <url>",
11248
+ "description": "Account service URL (default https://account.overdeck.ai, or OVERDECK_ACCOUNT_URL)",
11249
+ "required": true,
11250
+ "valueHint": "url"
11251
+ }],
11252
+ "aliases": [],
11253
+ "category": "CLI"
11254
+ },
11255
+ {
11256
+ "id": "pan-account-status",
11257
+ "path": ["account", "status"],
11258
+ "display": "/pan account status",
11259
+ "description": "Show the signed-in GitHub account and this device",
11260
+ "args": [],
11261
+ "options": [{
11262
+ "flags": "--json",
11263
+ "description": "Output in JSON format",
11264
+ "required": false,
11265
+ "valueHint": null
11266
+ }],
11267
+ "aliases": [],
11268
+ "category": "CLI"
11269
+ },
11270
+ {
11271
+ "id": "pan-account-logout",
11272
+ "path": ["account", "logout"],
11273
+ "display": "/pan account logout",
11274
+ "description": "Revoke this machine's device token and delete it locally",
11275
+ "args": [],
11276
+ "options": [],
11277
+ "aliases": [],
11278
+ "category": "CLI"
11279
+ },
10239
11280
  {
10240
11281
  "id": "pan-test",
10241
11282
  "path": ["test"],
@@ -12777,6 +13818,28 @@ const COMPOSER_COMMAND_MANIFEST = [
12777
13818
  "aliases": [],
12778
13819
  "category": "Admin"
12779
13820
  },
13821
+ {
13822
+ "id": "pan-admin-config-set",
13823
+ "path": [
13824
+ "admin",
13825
+ "config",
13826
+ "set"
13827
+ ],
13828
+ "display": "/pan admin config set",
13829
+ "description": "Set one config.yaml value (dotted snake_case key; the value is parsed as YAML), keeping comments",
13830
+ "args": [{
13831
+ "name": "key",
13832
+ "required": true,
13833
+ "variadic": false
13834
+ }, {
13835
+ "name": "value",
13836
+ "required": true,
13837
+ "variadic": false
13838
+ }],
13839
+ "options": [],
13840
+ "aliases": [],
13841
+ "category": "Admin"
13842
+ },
12780
13843
  {
12781
13844
  "id": "pan-admin-hooks",
12782
13845
  "path": ["admin", "hooks"],
@@ -13261,6 +14324,68 @@ const COMPOSER_COMMAND_MANIFEST = [
13261
14324
  "aliases": ["transcript"],
13262
14325
  "category": "Conversation"
13263
14326
  },
14327
+ {
14328
+ "id": "pan-conversations-pending",
14329
+ "path": ["conversations", "pending"],
14330
+ "display": "/pan conversations pending",
14331
+ "description": "List messages queued to send when the conversation's usage limit resets",
14332
+ "args": [{
14333
+ "name": "conv",
14334
+ "required": true,
14335
+ "variadic": false
14336
+ }],
14337
+ "options": [{
14338
+ "flags": "--json",
14339
+ "description": "Print JSON",
14340
+ "required": false,
14341
+ "valueHint": null
14342
+ }],
14343
+ "aliases": [],
14344
+ "category": "Conversation"
14345
+ },
14346
+ {
14347
+ "id": "pan-conversations-pull",
14348
+ "path": ["conversations", "pull"],
14349
+ "display": "/pan conversations pull",
14350
+ "description": "Make this machine own a conversation that runs on a linked machine (@<machine>/<conv>)",
14351
+ "args": [{
14352
+ "name": "conv",
14353
+ "required": true,
14354
+ "variadic": false
14355
+ }],
14356
+ "options": [{
14357
+ "flags": "--stop-turn",
14358
+ "description": "Stop a running turn instead of waiting for it",
14359
+ "required": false,
14360
+ "valueHint": null
14361
+ }, {
14362
+ "flags": "--json",
14363
+ "description": "Print the final job state as JSON",
14364
+ "required": false,
14365
+ "valueHint": null
14366
+ }],
14367
+ "aliases": [],
14368
+ "category": "Conversation"
14369
+ },
14370
+ {
14371
+ "id": "pan-conversations-reclaim",
14372
+ "path": ["conversations", "reclaim"],
14373
+ "display": "/pan conversations reclaim",
14374
+ "description": "Take back a conversation this machine released when the other machine does not run it",
14375
+ "args": [{
14376
+ "name": "conv",
14377
+ "required": true,
14378
+ "variadic": false
14379
+ }],
14380
+ "options": [{
14381
+ "flags": "--force",
14382
+ "description": "Reclaim even when the other machine cannot be asked",
14383
+ "required": false,
14384
+ "valueHint": null
14385
+ }],
14386
+ "aliases": [],
14387
+ "category": "Conversation"
14388
+ },
13264
14389
  {
13265
14390
  "id": "pan-conversations-move",
13266
14391
  "path": ["conversations", "move"],
@@ -13308,11 +14433,206 @@ const COMPOSER_COMMAND_MANIFEST = [
13308
14433
  "display": "/pan conversations unlink-pr",
13309
14434
  "description": "Unlink a pull request from a conversation (the sweep will not re-add it)",
13310
14435
  "args": [{
13311
- "name": "query",
13312
- "required": true,
13313
- "variadic": false
13314
- }, {
13315
- "name": "ref",
14436
+ "name": "query",
14437
+ "required": true,
14438
+ "variadic": false
14439
+ }, {
14440
+ "name": "ref",
14441
+ "required": true,
14442
+ "variadic": false
14443
+ }],
14444
+ "options": [],
14445
+ "aliases": [],
14446
+ "category": "Conversation"
14447
+ },
14448
+ {
14449
+ "id": "pan-conversations-prs",
14450
+ "path": ["conversations", "prs"],
14451
+ "display": "/pan conversations prs",
14452
+ "description": "List the pull requests linked to a conversation (* = the one shown)",
14453
+ "args": [{
14454
+ "name": "query",
14455
+ "required": true,
14456
+ "variadic": false
14457
+ }],
14458
+ "options": [{
14459
+ "flags": "--json",
14460
+ "description": "Output { links, effective } as JSON",
14461
+ "required": false,
14462
+ "valueHint": null
14463
+ }],
14464
+ "aliases": [],
14465
+ "category": "Conversation"
14466
+ },
14467
+ {
14468
+ "id": "pan-conversations-auto-settle-on-merge",
14469
+ "path": ["conversations", "auto-settle-on-merge"],
14470
+ "display": "/pan conversations auto-settle-on-merge",
14471
+ "description": "Show or set (on|off) settling conversations once all their linked PRs are merged or closed (default on)",
14472
+ "args": [{
14473
+ "name": "value",
14474
+ "required": false,
14475
+ "variadic": false
14476
+ }],
14477
+ "options": [],
14478
+ "aliases": [],
14479
+ "category": "Conversation"
14480
+ },
14481
+ {
14482
+ "id": "pan-conversations-auto-settle",
14483
+ "path": ["conversations", "auto-settle"],
14484
+ "display": "/pan conversations auto-settle",
14485
+ "description": "Show or set (on|off|inherit) one conversation's auto-settle-on-merge override",
14486
+ "args": [{
14487
+ "name": "query",
14488
+ "required": true,
14489
+ "variadic": false
14490
+ }, {
14491
+ "name": "value",
14492
+ "required": false,
14493
+ "variadic": false
14494
+ }],
14495
+ "options": [],
14496
+ "aliases": [],
14497
+ "category": "Conversation"
14498
+ },
14499
+ {
14500
+ "id": "pan-conversations-auto-settle-idle-days",
14501
+ "path": ["conversations", "auto-settle-idle-days"],
14502
+ "display": "/pan conversations auto-settle-idle-days",
14503
+ "description": "Show or set how many days without activity before an operator conversation is settled (0 = off, default 3)",
14504
+ "args": [{
14505
+ "name": "days",
14506
+ "required": false,
14507
+ "variadic": false
14508
+ }],
14509
+ "options": [],
14510
+ "aliases": [],
14511
+ "category": "Conversation"
14512
+ },
14513
+ {
14514
+ "id": "pan-conversations-schedule",
14515
+ "path": ["conversations", "schedule"],
14516
+ "display": "/pan conversations schedule",
14517
+ "description": "Run a prompt in a conversation on a recurring schedule (Overdeck fires it, even after restarts)",
14518
+ "args": [],
14519
+ "options": [],
14520
+ "aliases": [],
14521
+ "category": "Conversation"
14522
+ },
14523
+ {
14524
+ "id": "pan-conversations-schedule-add",
14525
+ "path": [
14526
+ "conversations",
14527
+ "schedule",
14528
+ "add"
14529
+ ],
14530
+ "display": "/pan conversations schedule add",
14531
+ "description": "Add a schedule; <conv> is self, a conversation number, a name, or a title match",
14532
+ "args": [{
14533
+ "name": "conv",
14534
+ "required": true,
14535
+ "variadic": false
14536
+ }],
14537
+ "options": [
14538
+ {
14539
+ "flags": "--cron <expr>",
14540
+ "description": "5-field cron expression, evaluated in --tz",
14541
+ "required": true,
14542
+ "valueHint": "expr"
14543
+ },
14544
+ {
14545
+ "flags": "--hourly",
14546
+ "description": "Every hour on the hour",
14547
+ "required": false,
14548
+ "valueHint": null
14549
+ },
14550
+ {
14551
+ "flags": "--daily <HH:MM>",
14552
+ "description": "Every day at HH:MM",
14553
+ "required": true,
14554
+ "valueHint": "HH:MM"
14555
+ },
14556
+ {
14557
+ "flags": "--weekdays <HH:MM>",
14558
+ "description": "Monday to Friday at HH:MM",
14559
+ "required": true,
14560
+ "valueHint": "HH:MM"
14561
+ },
14562
+ {
14563
+ "flags": "--weekly <spec>",
14564
+ "description": "Once a week: \"<day> HH:MM\", e.g. \"mon 09:00\"",
14565
+ "required": true,
14566
+ "valueHint": "spec"
14567
+ },
14568
+ {
14569
+ "flags": "--prompt <text>",
14570
+ "description": "The prompt to send",
14571
+ "required": true,
14572
+ "valueHint": "text"
14573
+ },
14574
+ {
14575
+ "flags": "--prompt-file <path>",
14576
+ "description": "Read the prompt from a file",
14577
+ "required": true,
14578
+ "valueHint": "path"
14579
+ },
14580
+ {
14581
+ "flags": "--tz <zone>",
14582
+ "description": "IANA time zone (default: this machine's zone)",
14583
+ "required": true,
14584
+ "valueHint": "zone"
14585
+ },
14586
+ {
14587
+ "flags": "--paused",
14588
+ "description": "Create the schedule paused",
14589
+ "required": false,
14590
+ "valueHint": null
14591
+ },
14592
+ {
14593
+ "flags": "--json",
14594
+ "description": "Output the created schedule as JSON",
14595
+ "required": false,
14596
+ "valueHint": null
14597
+ }
14598
+ ],
14599
+ "aliases": [],
14600
+ "category": "Conversation"
14601
+ },
14602
+ {
14603
+ "id": "pan-conversations-schedule-list",
14604
+ "path": [
14605
+ "conversations",
14606
+ "schedule",
14607
+ "list"
14608
+ ],
14609
+ "display": "/pan conversations schedule list",
14610
+ "description": "List schedules (all, or one conversation's)",
14611
+ "args": [{
14612
+ "name": "conv",
14613
+ "required": false,
14614
+ "variadic": false
14615
+ }],
14616
+ "options": [{
14617
+ "flags": "--json",
14618
+ "description": "Output as JSON",
14619
+ "required": false,
14620
+ "valueHint": null
14621
+ }],
14622
+ "aliases": [],
14623
+ "category": "Conversation"
14624
+ },
14625
+ {
14626
+ "id": "pan-conversations-schedule-pause",
14627
+ "path": [
14628
+ "conversations",
14629
+ "schedule",
14630
+ "pause"
14631
+ ],
14632
+ "display": "/pan conversations schedule pause",
14633
+ "description": "Pause a schedule",
14634
+ "args": [{
14635
+ "name": "id",
13316
14636
  "required": true,
13317
14637
  "variadic": false
13318
14638
  }],
@@ -13321,32 +14641,35 @@ const COMPOSER_COMMAND_MANIFEST = [
13321
14641
  "category": "Conversation"
13322
14642
  },
13323
14643
  {
13324
- "id": "pan-conversations-prs",
13325
- "path": ["conversations", "prs"],
13326
- "display": "/pan conversations prs",
13327
- "description": "List the pull requests linked to a conversation (* = the one shown)",
14644
+ "id": "pan-conversations-schedule-resume",
14645
+ "path": [
14646
+ "conversations",
14647
+ "schedule",
14648
+ "resume"
14649
+ ],
14650
+ "display": "/pan conversations schedule resume",
14651
+ "description": "Resume a paused schedule; the next run is computed from now",
13328
14652
  "args": [{
13329
- "name": "query",
14653
+ "name": "id",
13330
14654
  "required": true,
13331
14655
  "variadic": false
13332
14656
  }],
13333
- "options": [{
13334
- "flags": "--json",
13335
- "description": "Output { links, effective } as JSON",
13336
- "required": false,
13337
- "valueHint": null
13338
- }],
14657
+ "options": [],
13339
14658
  "aliases": [],
13340
14659
  "category": "Conversation"
13341
14660
  },
13342
14661
  {
13343
- "id": "pan-conversations-auto-archive-on-merge",
13344
- "path": ["conversations", "auto-archive-on-merge"],
13345
- "display": "/pan conversations auto-archive-on-merge",
13346
- "description": "Show or set (on|off) archiving operator conversations once all their linked PRs are merged or closed (default off)",
14662
+ "id": "pan-conversations-schedule-rm",
14663
+ "path": [
14664
+ "conversations",
14665
+ "schedule",
14666
+ "rm"
14667
+ ],
14668
+ "display": "/pan conversations schedule rm",
14669
+ "description": "Delete a schedule",
13347
14670
  "args": [{
13348
- "name": "value",
13349
- "required": false,
14671
+ "name": "id",
14672
+ "required": true,
13350
14673
  "variadic": false
13351
14674
  }],
13352
14675
  "options": [],
@@ -13932,6 +15255,30 @@ const COMPOSER_COMMAND_MANIFEST = [
13932
15255
  "description": "Stop the worker after its first report",
13933
15256
  "required": false,
13934
15257
  "valueHint": null
15258
+ },
15259
+ {
15260
+ "flags": "--machine <label|auto>",
15261
+ "description": "Run on a linked machine (label or environment id), or auto to place it by load",
15262
+ "required": true,
15263
+ "valueHint": "label|auto"
15264
+ },
15265
+ {
15266
+ "flags": "--needs <tags>",
15267
+ "description": "Comma-separated capability tags the machine must have (docker, gpu, ios-sim, …)",
15268
+ "required": true,
15269
+ "valueHint": "tags"
15270
+ },
15271
+ {
15272
+ "flags": "--push-first",
15273
+ "description": "With --machine: push unpushed commits before starting on the other machine",
15274
+ "required": false,
15275
+ "valueHint": null
15276
+ },
15277
+ {
15278
+ "flags": "--ignore-unpushed",
15279
+ "description": "With --machine: start even though local commits are not pushed",
15280
+ "required": false,
15281
+ "valueHint": null
13935
15282
  }
13936
15283
  ],
13937
15284
  "aliases": [],
@@ -14231,6 +15578,18 @@ const COMPOSER_COMMAND_MANIFEST = [
14231
15578
  "required": false,
14232
15579
  "valueHint": null
14233
15580
  },
15581
+ {
15582
+ "flags": "--machine <label|auto>",
15583
+ "description": "Where to run: a linked machine's label or environment id, or auto",
15584
+ "required": true,
15585
+ "valueHint": "label|auto"
15586
+ },
15587
+ {
15588
+ "flags": "--needs <tags>",
15589
+ "description": "With --machine auto: comma-separated capability tags the machine must have",
15590
+ "required": true,
15591
+ "valueHint": "tags"
15592
+ },
14234
15593
  {
14235
15594
  "flags": "--no-wait",
14236
15595
  "description": "Return without waiting for the lane to start",
@@ -14405,7 +15764,7 @@ const COMPOSER_COMMAND_MANIFEST = [
14405
15764
  "id": "pan-lane-stop",
14406
15765
  "path": ["lane", "stop"],
14407
15766
  "display": "/pan lane stop",
14408
- "description": "Stop a lane through the conversation stop door",
15767
+ "description": "Stop a lane through the conversation stop door (on its own machine for a remote lane)",
14409
15768
  "args": [{
14410
15769
  "name": "lane",
14411
15770
  "required": true,
@@ -15562,6 +16921,11 @@ const COMPOSER_COMMAND_MANIFEST = [
15562
16921
  "description": "Exit non-zero if any optional dependency is missing (e.g. Pi binary)",
15563
16922
  "required": false,
15564
16923
  "valueHint": null
16924
+ }, {
16925
+ "flags": "--json",
16926
+ "description": "Print every check as JSON (name, status, message, fix); same exit code as text mode",
16927
+ "required": false,
16928
+ "valueHint": null
15565
16929
  }],
15566
16930
  "aliases": [],
15567
16931
  "category": "Core"
@@ -15581,6 +16945,47 @@ const COMPOSER_COMMAND_MANIFEST = [
15581
16945
  "aliases": [],
15582
16946
  "category": "Core"
15583
16947
  },
16948
+ {
16949
+ "id": "pan-diagnose",
16950
+ "path": ["diagnose"],
16951
+ "display": "/pan diagnose",
16952
+ "description": "Collect a redacted diagnostic bundle and start Claude Code or Codex to fix the problem",
16953
+ "args": [],
16954
+ "options": [
16955
+ {
16956
+ "flags": "--harness <harness>",
16957
+ "description": "Harness to start",
16958
+ "required": true,
16959
+ "valueHint": "harness"
16960
+ },
16961
+ {
16962
+ "flags": "--describe <text>",
16963
+ "description": "What went wrong, in your words (saved in the bundle)",
16964
+ "required": true,
16965
+ "valueHint": "text"
16966
+ },
16967
+ {
16968
+ "flags": "--bundle-only",
16969
+ "description": "Write the bundle and print its path; do not start a harness",
16970
+ "required": false,
16971
+ "valueHint": null
16972
+ },
16973
+ {
16974
+ "flags": "--no-issue",
16975
+ "description": "Do not let the session draft or create an upstream issue",
16976
+ "required": false,
16977
+ "valueHint": null
16978
+ },
16979
+ {
16980
+ "flags": "--yes",
16981
+ "description": "Start the harness without asking to confirm the bundle",
16982
+ "required": false,
16983
+ "valueHint": null
16984
+ }
16985
+ ],
16986
+ "aliases": [],
16987
+ "category": "CLI"
16988
+ },
15584
16989
  {
15585
16990
  "id": "pan-resources",
15586
16991
  "path": ["resources"],
@@ -15900,6 +17305,11 @@ const COMPOSER_COMMAND_MANIFEST = [
15900
17305
  "description": "Port to listen on",
15901
17306
  "required": true,
15902
17307
  "valueHint": "port"
17308
+ }, {
17309
+ "flags": "--no-open",
17310
+ "description": "Do not open a browser",
17311
+ "required": false,
17312
+ "valueHint": null
15903
17313
  }],
15904
17314
  "aliases": [],
15905
17315
  "category": "CLI"
@@ -16302,6 +17712,39 @@ function isConfiguredPullRequestRepo(ref, repos) {
16302
17712
  return repos.some((repo) => repo.host === ref.host && repo.repository === ref.repository);
16303
17713
  }
16304
17714
  //#endregion
17715
+ //#region src/tracker-issue-ref.ts
17716
+ const GITHUB_ISSUE = /^(?:https?:\/\/)?github\.com\/([\w.-]+\/[\w.-]+)\/issues\/(\d+)\/?(?:[?#].*)?$/i;
17717
+ const LINEAR_ISSUE = /^(?:https?:\/\/)?linear\.app\/[\w.-]+\/issue\/([A-Za-z]+-\d+)(?:\/[^?#]*)?(?:[?#].*)?$/i;
17718
+ function parseTrackerIssueUrl(input) {
17719
+ const text = input.trim();
17720
+ const github = GITHUB_ISSUE.exec(text);
17721
+ if (github) {
17722
+ const number = Number(github[2]);
17723
+ if (!Number.isSafeInteger(number) || number <= 0) return null;
17724
+ return {
17725
+ tracker: "github",
17726
+ repository: github[1].toLowerCase().replace(/\.git$/, ""),
17727
+ number
17728
+ };
17729
+ }
17730
+ const linear = LINEAR_ISSUE.exec(text);
17731
+ if (linear) return {
17732
+ tracker: "linear",
17733
+ identifier: linear[1].toUpperCase()
17734
+ };
17735
+ return null;
17736
+ }
17737
+ function resolveTrackerIssueId(ref, projects) {
17738
+ for (const project of projects) {
17739
+ const prefix = typeof project?.linearTeam === "string" ? project.linearTeam.trim().toUpperCase() : "";
17740
+ if (!prefix || project.tracker !== ref.tracker) continue;
17741
+ if (ref.tracker === "github") {
17742
+ if (project.githubRepo?.toLowerCase() === ref.repository) return `${prefix}-${ref.number}`;
17743
+ } else if (ref.identifier.slice(0, ref.identifier.lastIndexOf("-")) === prefix) return ref.identifier;
17744
+ }
17745
+ return null;
17746
+ }
17747
+ //#endregion
16305
17748
  //#region src/conversation-rows.ts
16306
17749
  /**
16307
17750
  * Conversation-row classifiers shared by the dashboard server (`src/lib`) and
@@ -16405,6 +17848,241 @@ function hasToolResult(e) {
16405
17848
  return !!e.result || (e.resultBytes ?? 0) > 0;
16406
17849
  }
16407
17850
  //#endregion
17851
+ //#region src/machines.ts
17852
+ /**
17853
+ * Secure-channel link protocol version (D-4645-11). Independent of
17854
+ * `ENVIRONMENT_PROTOCOL_VERSION`: a peer whose descriptor reports another value,
17855
+ * or no `capabilities.machineLinks`, is `unsupported`.
17856
+ */
17857
+ const LINK_PROTOCOL_VERSION = 1;
17858
+ /** The exact command that installs one Overdeck version (PAN-4654 FR-1, D-2). */
17859
+ function overdeckInstallCommand(version) {
17860
+ return `npm install -g @overdeck/core@${version}`;
17861
+ }
17862
+ /** Route kinds, ranked best to worst (D-10 of the Anywhere PRD). */
17863
+ const ROUTE_KINDS = [
17864
+ "lan",
17865
+ "tailnet",
17866
+ "ssh",
17867
+ "public",
17868
+ "direct",
17869
+ "relay"
17870
+ ];
17871
+ const RouteKind = effect.Schema.Literals(ROUTE_KINDS);
17872
+ /**
17873
+ * Where a route on a link came from. `directory` routes (PAN-2356) are dynamic: offered while the
17874
+ * overdeck.ai directory lists the peer, never stored in machine-links.json.
17875
+ */
17876
+ const RouteSource = effect.Schema.Literals([
17877
+ "pairing",
17878
+ "manual",
17879
+ "advertised",
17880
+ "directory"
17881
+ ]);
17882
+ /** An endpoint a machine advertises in its descriptor (`lan` and `tailnet` only in this issue). */
17883
+ const AdvertisedEndpoint = effect.Schema.Struct({
17884
+ kind: effect.Schema.Literals(["lan", "tailnet"]),
17885
+ /** `tcp://host:port` or `wss://host[:port]/ws/link`. */
17886
+ url: effect.Schema.String
17887
+ });
17888
+ /** Link supervisor state (FR-3). */
17889
+ const LinkState = effect.Schema.Literals([
17890
+ "online",
17891
+ "connecting",
17892
+ "offline",
17893
+ "unsupported",
17894
+ "revoked"
17895
+ ]);
17896
+ /** Access level of a link (FR-4). */
17897
+ const LinkAccess = effect.Schema.Literals(["operator", "agent-fenced"]);
17898
+ /** Last known result of probing one route. */
17899
+ const LinkRouteStatus = effect.Schema.Literals([
17900
+ "untried",
17901
+ "current",
17902
+ "reachable",
17903
+ "unreachable"
17904
+ ]);
17905
+ const LinkRouteView = effect.Schema.Struct({
17906
+ url: effect.Schema.String,
17907
+ kind: RouteKind,
17908
+ source: RouteSource,
17909
+ status: LinkRouteStatus
17910
+ });
17911
+ /** A heartbeat gap, diagnosed as a peer freeze or a network failure (FR-9). */
17912
+ const LinkIncident = effect.Schema.Struct({
17913
+ kind: effect.Schema.Literals(["froze", "network"]),
17914
+ durationMs: effect.Schema.Number,
17915
+ /** ISO-8601 UTC time the gap ended, in the linking machine's clock. */
17916
+ at: effect.Schema.String
17917
+ });
17918
+ /** Whether the linking server started the SSH host's Overdeck or adopted one already running (PAN-4404). */
17919
+ const SshLaunch = effect.Schema.Literals(["managed", "external"]);
17920
+ /** State of the local SSH port forward that carries an SSH machine's link (PAN-4404 D-4404-10). */
17921
+ const SshForwardState = effect.Schema.Literals([
17922
+ "starting",
17923
+ "up",
17924
+ "down",
17925
+ "attention"
17926
+ ]);
17927
+ /** The SSH side of a link that this server set up over SSH. */
17928
+ const SshLinkInfo = effect.Schema.Struct({
17929
+ destination: effect.Schema.String,
17930
+ launch: SshLaunch,
17931
+ forward: SshForwardState,
17932
+ forwardDetail: effect.Schema.NullOr(effect.Schema.String),
17933
+ localPort: effect.Schema.Number,
17934
+ remotePort: effect.Schema.Number
17935
+ });
17936
+ /** PAN-4651 D-4651-8: a machine's load, sampled every 15 s and carried in the link heartbeat. */
17937
+ const LoadSample = effect.Schema.Struct({
17938
+ /** CPU PSI `some avg10` (percent); null off Linux. */
17939
+ cpuPsiSomeAvg10: effect.Schema.NullOr(effect.Schema.Number),
17940
+ cpuSaturated: effect.Schema.Boolean,
17941
+ memAvailableBytes: effect.Schema.NullOr(effect.Schema.Number),
17942
+ workingAgents: effect.Schema.Number,
17943
+ sampledAt: effect.Schema.String
17944
+ });
17945
+ /** PAN-4651 FR-7: `on-request` reserves a machine — Auto skips it unless only it has a needed tag. */
17946
+ const MachinePlacementMode = effect.Schema.Literals(["auto", "on-request"]);
17947
+ /** PAN-4651 FR-6: `CPU 3% · 41 GB · 2 agents` (unknown parts `n/a`); null without a sample. */
17948
+ function formatMachineLoad(load) {
17949
+ if (!load) return null;
17950
+ return `CPU ${load.cpuPsiSomeAvg10 === null ? "n/a" : `${Math.round(load.cpuPsiSomeAvg10)}%`} · ${load.memAvailableBytes === null ? "n/a" : `${Math.floor(load.memAvailableBytes / 2 ** 30)}`} GB · ${load.workingAgents} agents`;
17951
+ }
17952
+ /** PAN-4651 FR-7: `tags: docker, linux · reserved`; null when there is neither. */
17953
+ function formatMachineProfile(tags, placement) {
17954
+ const parts = [...tags && tags.length > 0 ? [`tags: ${tags.join(", ")}`] : [], ...placement === "on-request" ? ["reserved"] : []];
17955
+ return parts.length > 0 ? parts.join(" · ") : null;
17956
+ }
17957
+ /** PAN-4651 D-4651-9: why Auto placement skipped one machine. */
17958
+ const PlacementRejection = effect.Schema.Struct({
17959
+ environmentId: effect.Schema.String,
17960
+ label: effect.Schema.String,
17961
+ /** `offline`, `unsupported`, `no project`, `no <tag>`, `CPU saturated` or `reserved`. */
17962
+ reason: effect.Schema.String
17963
+ });
17964
+ /** PAN-4651 D-4651-9: the machine Auto chose (with the one-line reason), or why none fits. */
17965
+ const PlacementAnswer = effect.Schema.Union([effect.Schema.Struct({
17966
+ ok: effect.Schema.Literal(true),
17967
+ environmentId: effect.Schema.String,
17968
+ label: effect.Schema.String,
17969
+ self: effect.Schema.Boolean,
17970
+ reason: effect.Schema.String,
17971
+ rejections: effect.Schema.Array(PlacementRejection)
17972
+ }), effect.Schema.Struct({
17973
+ ok: effect.Schema.Literal(false),
17974
+ rejections: effect.Schema.Array(PlacementRejection)
17975
+ })]);
17976
+ /** PAN-4651 D-4651-11: one project a machine has registered, as linked machines see it (never a path). */
17977
+ const MachineProject = effect.Schema.Struct({
17978
+ key: effect.Schema.String,
17979
+ name: effect.Schema.String,
17980
+ /** `github.com/<owner>/<repo>` or `gitlab.com/<path>`; null when the project has no remote repo. */
17981
+ gitOrigin: effect.Schema.NullOr(effect.Schema.String)
17982
+ });
17983
+ /** PAN-4651 D-4651-13: one repository across machines, as `GET /api/fleet/projects` lists it. */
17984
+ const FleetProjectRow = effect.Schema.Struct({
17985
+ /** The git origin slug; null for a local project without one (its own row). */
17986
+ gitOrigin: effect.Schema.NullOr(effect.Schema.String),
17987
+ name: effect.Schema.String,
17988
+ /** This machine's project for the slug, or null when only other machines have it. */
17989
+ local: effect.Schema.NullOr(effect.Schema.Struct({ key: effect.Schema.String })),
17990
+ machines: effect.Schema.Array(effect.Schema.Struct({
17991
+ environmentId: effect.Schema.String,
17992
+ label: effect.Schema.String,
17993
+ key: effect.Schema.String,
17994
+ state: LinkState
17995
+ }))
17996
+ });
17997
+ const FleetProjectsResponse = effect.Schema.Struct({
17998
+ combine: effect.Schema.Boolean,
17999
+ projects: effect.Schema.Array(FleetProjectRow)
18000
+ });
18001
+ /** One outbound link as shown by `GET /api/machines` and `pan machines list`. */
18002
+ const MachineLinkView = effect.Schema.Struct({
18003
+ id: effect.Schema.String,
18004
+ environmentId: effect.Schema.String,
18005
+ label: effect.Schema.String,
18006
+ /** Fingerprint of the pinned machine key: five dash-separated groups of four hex. */
18007
+ fingerprint: effect.Schema.String,
18008
+ access: LinkAccess,
18009
+ state: LinkState,
18010
+ stateDetail: effect.Schema.NullOr(effect.Schema.String),
18011
+ currentRoute: effect.Schema.NullOr(effect.Schema.String),
18012
+ routes: effect.Schema.Array(LinkRouteView),
18013
+ lastHeartbeatAt: effect.Schema.NullOr(effect.Schema.String),
18014
+ incident: effect.Schema.NullOr(LinkIncident),
18015
+ peerVersion: effect.Schema.NullOr(effect.Schema.String),
18016
+ createdAt: effect.Schema.String,
18017
+ /** PAN-4650: Hide this machine — its conversations are left out of the conversation list. */
18018
+ hidden: effect.Schema.optional(effect.Schema.Boolean),
18019
+ /** Present only on links this server set up over SSH. */
18020
+ ssh: effect.Schema.optional(SshLinkInfo),
18021
+ /** PAN-4651: the peer's last heartbeat load sample; null before one arrives or from a peer that predates it. */
18022
+ load: effect.Schema.optional(effect.Schema.NullOr(LoadSample)),
18023
+ /** PAN-4651: the peer's capability tags (detected plus `anywhere.machine.tags`). */
18024
+ tags: effect.Schema.optional(effect.Schema.Array(effect.Schema.String)),
18025
+ placement: effect.Schema.optional(MachinePlacementMode)
18026
+ });
18027
+ /** One `machine` token this machine issued to another machine (inbound access). */
18028
+ const InboundMachineView = effect.Schema.Struct({
18029
+ tokenId: effect.Schema.String,
18030
+ environmentId: effect.Schema.String,
18031
+ label: effect.Schema.String,
18032
+ fingerprint: effect.Schema.String,
18033
+ access: LinkAccess,
18034
+ createdAt: effect.Schema.String,
18035
+ lastUsedAt: effect.Schema.NullOr(effect.Schema.String)
18036
+ });
18037
+ const MachinesResponse = effect.Schema.Struct({
18038
+ self: effect.Schema.Struct({
18039
+ environmentId: effect.Schema.String,
18040
+ label: effect.Schema.String,
18041
+ fingerprint: effect.Schema.String,
18042
+ /** PAN-4650 D-4: linked machines list this machine's conversations (anywhere.json, default on). */
18043
+ shareConversations: effect.Schema.Boolean,
18044
+ /** PAN-4651 D-4651-13: one project per git origin across machines (anywhere.json, default on). */
18045
+ combineRepositories: effect.Schema.optional(effect.Schema.Boolean),
18046
+ /** PAN-4651: this machine's own load sample, tags and placement mode. */
18047
+ load: effect.Schema.optional(effect.Schema.NullOr(LoadSample)),
18048
+ tags: effect.Schema.optional(effect.Schema.Array(effect.Schema.String)),
18049
+ placement: effect.Schema.optional(MachinePlacementMode)
18050
+ }),
18051
+ links: effect.Schema.Array(MachineLinkView),
18052
+ inbound: effect.Schema.Array(InboundMachineView)
18053
+ });
18054
+ /**
18055
+ * Version of the `OVERDECK_SSH_HELPER` result line that `pan machines ssh-helper`
18056
+ * prints on the SSH host (PAN-4404).
18057
+ */
18058
+ const SSH_HELPER_PROTOCOL = 1;
18059
+ /** Error codes of the SSH machine flow (PAN-4404 D-4404-9). */
18060
+ const SSH_MACHINE_ERROR_CODES = [
18061
+ "bad-destination",
18062
+ "busy",
18063
+ "unresolvable",
18064
+ "unreachable",
18065
+ "host-key",
18066
+ "auth-failed",
18067
+ "pan-missing",
18068
+ "version-mismatch",
18069
+ "helper-failed",
18070
+ "start-failed",
18071
+ "forward-failed",
18072
+ "self-link",
18073
+ "not-found"
18074
+ ];
18075
+ const SshMachineErrorCode = effect.Schema.Literals(SSH_MACHINE_ERROR_CODES);
18076
+ /** Answer of `POST /api/machines/ssh/test` and `pan machines test-ssh`. */
18077
+ const SshTestResult = effect.Schema.Struct({
18078
+ reachable: effect.Schema.Boolean,
18079
+ panVersion: effect.Schema.NullOr(effect.Schema.String),
18080
+ localVersion: effect.Schema.String,
18081
+ versionMatches: effect.Schema.Boolean,
18082
+ error: effect.Schema.NullOr(SshMachineErrorCode),
18083
+ message: effect.Schema.NullOr(effect.Schema.String)
18084
+ });
18085
+ //#endregion
16408
18086
  //#region src/environment.ts
16409
18087
  /** Wire protocol version a client and server must agree on. */
16410
18088
  const ENVIRONMENT_PROTOCOL_VERSION = 1;
@@ -16415,7 +18093,9 @@ const EnvironmentCapabilities = effect.Schema.Struct({
16415
18093
  /** `GET/DELETE /api/devices` is available. */
16416
18094
  deviceSessions: effect.Schema.Boolean,
16417
18095
  /** `/ws/*` upgrades require a credential (PAN-1166). */
16418
- terminalAuth: effect.Schema.Boolean
18096
+ terminalAuth: effect.Schema.Boolean,
18097
+ /** Secure machine links are accepted (PAN-4645). Absent on older servers ⇒ `unsupported`. */
18098
+ machineLinks: effect.Schema.optional(effect.Schema.Boolean)
16419
18099
  });
16420
18100
  const EnvironmentDescriptor = effect.Schema.Struct({
16421
18101
  descriptorVersion: effect.Schema.Literal(1),
@@ -16429,7 +18109,13 @@ const EnvironmentDescriptor = effect.Schema.Struct({
16429
18109
  serverVersion: effect.Schema.String,
16430
18110
  /** The server's `ENVIRONMENT_PROTOCOL_VERSION`. */
16431
18111
  protocolVersion: effect.Schema.Number,
16432
- capabilities: EnvironmentCapabilities
18112
+ capabilities: EnvironmentCapabilities,
18113
+ /** Long-term X25519 machine public key, 64 lowercase hex (PAN-4645). */
18114
+ machineKey: effect.Schema.optional(effect.Schema.String),
18115
+ /** The server's `LINK_PROTOCOL_VERSION`; optional so older descriptors still decode (D-4645-11). */
18116
+ linkProtocol: effect.Schema.optional(effect.Schema.Number),
18117
+ /** Endpoints this machine advertises for secure channels. */
18118
+ endpoints: effect.Schema.optional(effect.Schema.Array(AdvertisedEndpoint))
16433
18119
  });
16434
18120
  /** A server-local id qualified by the environment that owns it. */
16435
18121
  const ScopedRef = (localId) => effect.Schema.Struct({
@@ -16446,15 +18132,548 @@ function isProtocolCompatible(descriptor, clientProtocolVersion) {
16446
18132
  return descriptor.protocolVersion === clientProtocolVersion;
16447
18133
  }
16448
18134
  //#endregion
18135
+ //#region src/linked-conversations.ts
18136
+ /** The viewing machine's name for a linked conversation: `@<environmentId>/<name>`. */
18137
+ function linkedConversationName(environmentId, name) {
18138
+ return `@${environmentId}/${name}`;
18139
+ }
18140
+ const LINKED_NAME = /^@([^/]+)\/([^/]+)$/;
18141
+ /**
18142
+ * Parse `@<target>/<name>`, where target is an environment id or a machine
18143
+ * label. Returns null for a local name or a malformed value.
18144
+ */
18145
+ function parseLinkedConversationName(value) {
18146
+ const match = LINKED_NAME.exec(value);
18147
+ if (!match) return null;
18148
+ return {
18149
+ target: match[1],
18150
+ name: match[2]
18151
+ };
18152
+ }
18153
+ //#endregion
18154
+ //#region src/connect.ts
18155
+ const CONNECT_PROTOCOL_VERSION = 1;
18156
+ /** Relay allowance per account per UTC calendar month (OD-3): 50 GB. */
18157
+ const RELAY_MONTHLY_CAP_BYTES = 5e10;
18158
+ /** Largest webhook body the directory inbox accepts (D-2356-14). */
18159
+ const INBOX_BODY_MAX_BYTES = 262144;
18160
+ /** How long the inbox holds a sealed event before it expires (D-2356-18). */
18161
+ const INBOX_HOLD_MS = 864e5;
18162
+ /** How long an approval request stays live (D-2356-9). */
18163
+ const APPROVAL_TTL_MS = 6e5;
18164
+ const FREE_MACHINE_LIMIT_MESSAGE = "The free account includes 3 machines";
18165
+ const NO_DIRECT_PATH_MESSAGE = "No direct path; install Tailscale or use the relay plan";
18166
+ const RELAY_CAP_MESSAGE = "Relay allowance used; install Tailscale or add 50 GB";
18167
+ /** WebSocket close codes the directory uses. */
18168
+ const CONNECT_CLOSE_CODES = {
18169
+ unauthorized: 4001,
18170
+ grantExpired: 4003,
18171
+ machineLimit: 4009,
18172
+ unsupportedProtocol: 4010,
18173
+ /** Replaced by a newer socket for the same machine. */
18174
+ replaced: 4011,
18175
+ forgotten: 4012
18176
+ };
18177
+ //#endregion
18178
+ //#region src/connect-view.ts
18179
+ const DirectoryClientState = effect.Schema.Literals([
18180
+ "off",
18181
+ "connecting",
18182
+ "online",
18183
+ "refused"
18184
+ ]);
18185
+ const DirectoryPlan = effect.Schema.Literals(["free", "tester"]);
18186
+ /** One machine of the account, as the directory lists it. */
18187
+ const DirectoryMachineView = effect.Schema.Struct({
18188
+ environmentId: effect.Schema.String,
18189
+ label: effect.Schema.String,
18190
+ publicKeyHex: effect.Schema.String,
18191
+ fingerprint: effect.Schema.String,
18192
+ online: effect.Schema.Boolean,
18193
+ /** ISO-8601 UTC. */
18194
+ lastSeenAt: effect.Schema.String,
18195
+ serverVersion: effect.Schema.String,
18196
+ endpoints: effect.Schema.Array(AdvertisedEndpoint),
18197
+ /** This machine holds a link to it. */
18198
+ linked: effect.Schema.Boolean
18199
+ });
18200
+ /**
18201
+ * Approver side: `pending` (request arrived), `open` (approval channel open, SAS known),
18202
+ * `approving` (this operator approved; waiting for the other machine to accept), `failed`.
18203
+ */
18204
+ const DirectoryApprovalState = effect.Schema.Literals([
18205
+ "pending",
18206
+ "open",
18207
+ "approving",
18208
+ "failed"
18209
+ ]);
18210
+ /** Requester side: `waiting` (no approver yet), `open` (SAS known), `accepted`, `rejected`. */
18211
+ const DirectoryJoinState = effect.Schema.Literals([
18212
+ "waiting",
18213
+ "open",
18214
+ "accepted",
18215
+ "rejected"
18216
+ ]);
18217
+ /** An incoming approval request: another machine asks to link with this one. */
18218
+ const DirectoryApprovalView = effect.Schema.Struct({
18219
+ requestId: effect.Schema.String,
18220
+ /** Environment id of the requesting machine. */
18221
+ from: effect.Schema.String,
18222
+ label: effect.Schema.String,
18223
+ fingerprint: effect.Schema.String,
18224
+ /** Unix milliseconds. */
18225
+ expiresAt: effect.Schema.Number,
18226
+ /** Six-digit code, set once the approval channel is open. */
18227
+ sas: effect.Schema.NullOr(effect.Schema.String),
18228
+ state: DirectoryApprovalState,
18229
+ /** Why the approval failed, when `state` is `failed`. */
18230
+ error: effect.Schema.NullOr(effect.Schema.String)
18231
+ });
18232
+ /** An outgoing join request this machine made. */
18233
+ const DirectoryJoinView = effect.Schema.Struct({
18234
+ requestId: effect.Schema.String,
18235
+ /** Target environment id, or null for every machine of the account. */
18236
+ to: effect.Schema.NullOr(effect.Schema.String),
18237
+ /** Unix milliseconds. */
18238
+ expiresAt: effect.Schema.Number,
18239
+ /** Six-digit code, set once an approver opened the approval channel. */
18240
+ sas: effect.Schema.NullOr(effect.Schema.String),
18241
+ /** The approver's fingerprint, from the handshake key (never from the directory). */
18242
+ fingerprint: effect.Schema.NullOr(effect.Schema.String),
18243
+ state: DirectoryJoinState
18244
+ });
18245
+ const RelayStatusView = effect.Schema.Struct({
18246
+ /** UTC calendar month, `YYYY-MM`. */
18247
+ month: effect.Schema.String,
18248
+ bytesUsed: effect.Schema.Number,
18249
+ capBytes: effect.Schema.Number,
18250
+ stopped: effect.Schema.Boolean
18251
+ });
18252
+ const DirectoryResponse = effect.Schema.Struct({
18253
+ signedIn: effect.Schema.Boolean,
18254
+ state: DirectoryClientState,
18255
+ /** The configured directory URL, or null when it is invalid. */
18256
+ url: effect.Schema.NullOr(effect.Schema.String),
18257
+ plan: effect.Schema.NullOr(DirectoryPlan),
18258
+ refusal: effect.Schema.NullOr(effect.Schema.String),
18259
+ machines: effect.Schema.Array(DirectoryMachineView),
18260
+ approvals: effect.Schema.Array(DirectoryApprovalView),
18261
+ joins: effect.Schema.Array(DirectoryJoinView),
18262
+ relay: effect.Schema.NullOr(RelayStatusView)
18263
+ });
18264
+ //#endregion
18265
+ //#region src/fleet-versions.ts
18266
+ const FleetInstallMode = effect.Schema.Literals([
18267
+ "npm-global",
18268
+ "development",
18269
+ "desktop"
18270
+ ]);
18271
+ const FleetComponentStatus = effect.Schema.Literals([
18272
+ "pending",
18273
+ "running",
18274
+ "updated",
18275
+ "current",
18276
+ "skipped",
18277
+ "failed"
18278
+ ]);
18279
+ const FleetJobPhase = effect.Schema.Literals([
18280
+ "waiting",
18281
+ "updating",
18282
+ "restarting",
18283
+ "done",
18284
+ "failed",
18285
+ "cancelled"
18286
+ ]);
18287
+ const FleetUpdateMode = effect.Schema.Literals(["when-idle", "now"]);
18288
+ /** Fleet-table column order (D-16): these binaries first, then any other binary alphabetically. */
18289
+ const FLEET_BINARY_ORDER = [
18290
+ "claude",
18291
+ "codex",
18292
+ "kimi",
18293
+ "opencode",
18294
+ "muse",
18295
+ "prime-agent",
18296
+ "omp"
18297
+ ];
18298
+ /** Sort comparator for harness binary names in D-16 order. */
18299
+ function compareFleetBinaries(a, b) {
18300
+ const rank = (binary) => {
18301
+ const index = FLEET_BINARY_ORDER.indexOf(binary);
18302
+ return index === -1 ? FLEET_BINARY_ORDER.length : index;
18303
+ };
18304
+ return rank(a) - rank(b) || a.localeCompare(b);
18305
+ }
18306
+ /** After this long waiting for turns, the row says it is still waiting and points at Update now (FR-8). */
18307
+ const FLEET_UPDATE_STILL_WAITING_MS = 30 * 6e4;
18308
+ const FleetComponentSchema = effect.Schema.Struct({
18309
+ name: effect.Schema.String,
18310
+ label: effect.Schema.String,
18311
+ before: effect.Schema.NullOr(effect.Schema.String),
18312
+ after: effect.Schema.NullOr(effect.Schema.String),
18313
+ status: FleetComponentStatus,
18314
+ detail: effect.Schema.NullOr(effect.Schema.String)
18315
+ });
18316
+ /** Decodes a persisted job file. */
18317
+ const FleetUpdateJobSchema = effect.Schema.Struct({
18318
+ id: effect.Schema.String,
18319
+ mode: FleetUpdateMode,
18320
+ phase: FleetJobPhase,
18321
+ requestedBy: effect.Schema.String,
18322
+ startedAt: effect.Schema.String,
18323
+ waitingTurns: effect.Schema.Number,
18324
+ waitingSince: effect.Schema.NullOr(effect.Schema.String),
18325
+ finishedAt: effect.Schema.NullOr(effect.Schema.String),
18326
+ components: effect.Schema.Array(FleetComponentSchema)
18327
+ });
18328
+ /** Decodes a peer's `GET /api/versions/self` body. */
18329
+ const MachineVersionsReportSchema = effect.Schema.Struct({
18330
+ environmentId: effect.Schema.String,
18331
+ label: effect.Schema.String,
18332
+ overdeck: effect.Schema.Struct({
18333
+ version: effect.Schema.String,
18334
+ installMode: FleetInstallMode,
18335
+ linkProtocol: effect.Schema.Number
18336
+ }),
18337
+ harnesses: effect.Schema.Array(effect.Schema.Struct({
18338
+ binary: effect.Schema.String,
18339
+ label: effect.Schema.String,
18340
+ harnesses: effect.Schema.Array(effect.Schema.String),
18341
+ version: effect.Schema.NullOr(effect.Schema.String),
18342
+ updatable: effect.Schema.Boolean,
18343
+ command: effect.Schema.String,
18344
+ reason: effect.Schema.NullOr(effect.Schema.String)
18345
+ })),
18346
+ job: effect.Schema.NullOr(FleetUpdateJobSchema)
18347
+ });
18348
+ //#endregion
18349
+ //#region src/color-theme.ts
18350
+ const TERMINAL_PALETTE_KEYS = [
18351
+ "background",
18352
+ "foreground",
18353
+ "cursor",
18354
+ "cursorAccent",
18355
+ "selectionBackground",
18356
+ "black",
18357
+ "red",
18358
+ "green",
18359
+ "yellow",
18360
+ "blue",
18361
+ "magenta",
18362
+ "cyan",
18363
+ "white",
18364
+ "brightBlack",
18365
+ "brightRed",
18366
+ "brightGreen",
18367
+ "brightYellow",
18368
+ "brightBlue",
18369
+ "brightMagenta",
18370
+ "brightCyan",
18371
+ "brightWhite"
18372
+ ];
18373
+ const UI_KEYS = [
18374
+ "background",
18375
+ "surface",
18376
+ "overlay",
18377
+ "border",
18378
+ "foreground",
18379
+ "muted",
18380
+ "accent"
18381
+ ];
18382
+ const COLOR_THEME_ID_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
18383
+ const RESERVED_COLOR_THEME_IDS = ["overdeck-dark", "overdeck-light"];
18384
+ const HEX_COLOR_RE = /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
18385
+ const FONT_STYLE_RE = /^[a-z ]*$/i;
18386
+ const BUILTIN_COLOR_THEMES = {
18387
+ "overdeck-dark": {
18388
+ id: "overdeck-dark",
18389
+ name: "Overdeck Dark",
18390
+ type: "dark",
18391
+ builtin: true,
18392
+ terminal: {
18393
+ background: "#1a1a2e",
18394
+ foreground: "#eaeaea",
18395
+ cursor: "#eaeaea",
18396
+ cursorAccent: "#1a1a2e",
18397
+ selectionBackground: "#3a3a5e",
18398
+ black: "#1a1a2e",
18399
+ red: "#ff5555",
18400
+ green: "#50fa7b",
18401
+ yellow: "#f1fa8c",
18402
+ blue: "#6272a4",
18403
+ magenta: "#ff79c6",
18404
+ cyan: "#8be9fd",
18405
+ white: "#f8f8f2",
18406
+ brightBlack: "#6272a4",
18407
+ brightRed: "#ff6e6e",
18408
+ brightGreen: "#69ff94",
18409
+ brightYellow: "#ffffa5",
18410
+ brightBlue: "#d6acff",
18411
+ brightMagenta: "#ff92df",
18412
+ brightCyan: "#a4ffff",
18413
+ brightWhite: "#ffffff"
18414
+ }
18415
+ },
18416
+ "overdeck-light": {
18417
+ id: "overdeck-light",
18418
+ name: "Overdeck Light",
18419
+ type: "light",
18420
+ builtin: true,
18421
+ terminal: {
18422
+ background: "#ffffff",
18423
+ foreground: "#24292e",
18424
+ cursor: "#24292e",
18425
+ cursorAccent: "#ffffff",
18426
+ selectionBackground: "#bcd3f5",
18427
+ black: "#24292e",
18428
+ red: "#d73a49",
18429
+ green: "#22863a",
18430
+ yellow: "#b08800",
18431
+ blue: "#0366d6",
18432
+ magenta: "#6f42c1",
18433
+ cyan: "#1b7c83",
18434
+ white: "#6a737d",
18435
+ brightBlack: "#959da5",
18436
+ brightRed: "#cb2431",
18437
+ brightGreen: "#28a745",
18438
+ brightYellow: "#dbab09",
18439
+ brightBlue: "#2188ff",
18440
+ brightMagenta: "#8a63d2",
18441
+ brightCyan: "#3192aa",
18442
+ brightWhite: "#24292e"
18443
+ }
18444
+ }
18445
+ };
18446
+ function builtinFor(type) {
18447
+ return type === "dark" ? BUILTIN_COLOR_THEMES["overdeck-dark"] : BUILTIN_COLOR_THEMES["overdeck-light"];
18448
+ }
18449
+ /** Expands "#rgb" to "#rrggbb" and drops an alpha channel, lowercased, so xterm and tmux render the same opaque color. */
18450
+ function toOpaqueHex(hex) {
18451
+ const lower = hex.toLowerCase();
18452
+ const digits = lower.slice(1);
18453
+ if (digits.length === 3) return `#${digits[0]}${digits[0]}${digits[1]}${digits[1]}${digits[2]}${digits[2]}`;
18454
+ if (digits.length === 4) return `#${digits[0]}${digits[0]}${digits[1]}${digits[1]}${digits[2]}${digits[2]}`;
18455
+ if (digits.length === 8) return `#${digits.slice(0, 6)}`;
18456
+ return lower;
18457
+ }
18458
+ /** WCAG-contrast-based readable text color for a background hex: whichever of black/white has the higher contrast ratio. */
18459
+ function readableForeground(hex) {
18460
+ const opaque = toOpaqueHex(hex);
18461
+ const r = parseInt(opaque.slice(1, 3), 16) / 255;
18462
+ const g = parseInt(opaque.slice(3, 5), 16) / 255;
18463
+ const b = parseInt(opaque.slice(5, 7), 16) / 255;
18464
+ const channel = (c) => c <= .03928 ? c / 12.92 : Math.pow((c + .055) / 1.055, 2.4);
18465
+ const luminance = .2126 * channel(r) + .7152 * channel(g) + .0722 * channel(b);
18466
+ const contrastWithWhite = 1.05 / (luminance + .05);
18467
+ return (luminance + .05) / .05 >= contrastWithWhite ? "#000000" : "#ffffff";
18468
+ }
18469
+ /** Lowercase slug: runs of non-[a-z0-9] become "-", trimmed, capped at 64 chars, "theme" if empty. */
18470
+ function slugifyThemeId(name) {
18471
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
18472
+ return slug.length > 0 ? slug : "theme";
18473
+ }
18474
+ /** The built-in palette for the theme's type, overlaid with the theme's own terminal colors. */
18475
+ function effectiveTerminalPalette(theme) {
18476
+ const palette = {
18477
+ ...builtinFor(theme.type).terminal,
18478
+ ...theme.terminal
18479
+ };
18480
+ return {
18481
+ ...palette,
18482
+ background: toOpaqueHex(palette.background)
18483
+ };
18484
+ }
18485
+ function isPlainObject(value) {
18486
+ return typeof value === "object" && value !== null && !Array.isArray(value);
18487
+ }
18488
+ function normalizeSource(raw) {
18489
+ if (!isPlainObject(raw)) return void 0;
18490
+ if (raw.kind !== "vscode-import") return void 0;
18491
+ if (typeof raw.fileName !== "string" || typeof raw.importedAt !== "string") return void 0;
18492
+ return {
18493
+ kind: "vscode-import",
18494
+ fileName: raw.fileName,
18495
+ importedAt: raw.importedAt
18496
+ };
18497
+ }
18498
+ function normalizeTerminal(raw, warnings) {
18499
+ if (raw === void 0) return void 0;
18500
+ if (!isPlainObject(raw)) {
18501
+ warnings.push("terminal must be an object; ignoring");
18502
+ return;
18503
+ }
18504
+ const result = {};
18505
+ for (const [key, value] of Object.entries(raw)) {
18506
+ if (!TERMINAL_PALETTE_KEYS.includes(key)) {
18507
+ warnings.push(`unknown terminal key terminal.${key}; dropping`);
18508
+ continue;
18509
+ }
18510
+ if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
18511
+ warnings.push(`invalid color for terminal.${key}; dropping`);
18512
+ continue;
18513
+ }
18514
+ result[key] = value;
18515
+ }
18516
+ return Object.keys(result).length > 0 ? result : void 0;
18517
+ }
18518
+ function normalizeUi(raw, warnings) {
18519
+ if (raw === void 0) return void 0;
18520
+ if (!isPlainObject(raw)) {
18521
+ warnings.push("ui must be an object; ignoring");
18522
+ return;
18523
+ }
18524
+ const result = {};
18525
+ for (const [key, value] of Object.entries(raw)) {
18526
+ if (!UI_KEYS.includes(key)) {
18527
+ warnings.push(`unknown ui key ui.${key}; dropping`);
18528
+ continue;
18529
+ }
18530
+ if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
18531
+ warnings.push(`invalid color for ui.${key}; dropping`);
18532
+ continue;
18533
+ }
18534
+ result[key] = value;
18535
+ }
18536
+ return Object.keys(result).length > 0 ? result : void 0;
18537
+ }
18538
+ function normalizeTokenColors(raw, warnings) {
18539
+ if (raw === void 0) return [];
18540
+ if (!Array.isArray(raw)) {
18541
+ warnings.push("syntax.tokenColors must be an array; ignoring");
18542
+ return [];
18543
+ }
18544
+ const entries = [];
18545
+ for (const entry of raw.slice(0, 2e3)) {
18546
+ if (!isPlainObject(entry) || !isPlainObject(entry.settings)) continue;
18547
+ const settings = {};
18548
+ const rawSettings = entry.settings;
18549
+ if (typeof rawSettings.foreground === "string" && HEX_COLOR_RE.test(rawSettings.foreground)) settings.foreground = rawSettings.foreground;
18550
+ if (typeof rawSettings.background === "string" && HEX_COLOR_RE.test(rawSettings.background)) settings.background = rawSettings.background;
18551
+ if (typeof rawSettings.fontStyle === "string" && FONT_STYLE_RE.test(rawSettings.fontStyle)) settings.fontStyle = rawSettings.fontStyle;
18552
+ const result = { settings };
18553
+ if (typeof entry.scope === "string") result.scope = entry.scope;
18554
+ else if (Array.isArray(entry.scope) && entry.scope.every((s) => typeof s === "string")) result.scope = entry.scope;
18555
+ entries.push(result);
18556
+ }
18557
+ return entries;
18558
+ }
18559
+ function normalizeSyntax(raw, warnings) {
18560
+ if (raw === void 0) return void 0;
18561
+ if (!isPlainObject(raw)) {
18562
+ warnings.push("syntax must be an object; ignoring");
18563
+ return;
18564
+ }
18565
+ const tokenColors = normalizeTokenColors(raw.tokenColors, warnings);
18566
+ let colors;
18567
+ if (isPlainObject(raw.colors)) {
18568
+ const filtered = {};
18569
+ const background = raw.colors["editor.background"];
18570
+ const foreground = raw.colors["editor.foreground"];
18571
+ if (typeof background === "string" && HEX_COLOR_RE.test(background)) filtered["editor.background"] = background;
18572
+ if (typeof foreground === "string" && HEX_COLOR_RE.test(foreground)) filtered["editor.foreground"] = foreground;
18573
+ if (Object.keys(filtered).length > 0) colors = filtered;
18574
+ }
18575
+ if (tokenColors.length === 0 && colors === void 0) return void 0;
18576
+ return {
18577
+ tokenColors,
18578
+ ...colors !== void 0 ? { colors } : {}
18579
+ };
18580
+ }
18581
+ /**
18582
+ * Validates and sanitizes a raw theme. An invalid color or unknown key is
18583
+ * dropped with a warning naming it — never an error. A missing/invalid
18584
+ * `name` or `type` is an error: there is no sensible default for either.
18585
+ */
18586
+ function normalizeColorTheme(raw, id) {
18587
+ const errors = [];
18588
+ if (!isPlainObject(raw)) return { errors: ["theme must be an object"] };
18589
+ const rawName = raw.name;
18590
+ let name;
18591
+ if (typeof rawName === "string" && rawName.trim().length > 0) name = rawName.trim().slice(0, 80);
18592
+ else errors.push("name is required");
18593
+ const rawType = raw.type;
18594
+ let type;
18595
+ if (rawType === "light" || rawType === "dark") type = rawType;
18596
+ else errors.push("type must be \"light\" or \"dark\"");
18597
+ if (errors.length > 0 || name === void 0 || type === void 0) return { errors };
18598
+ const warnings = [];
18599
+ const terminal = normalizeTerminal(raw.terminal, warnings);
18600
+ const ui = normalizeUi(raw.ui, warnings);
18601
+ const syntax = normalizeSyntax(raw.syntax, warnings);
18602
+ const source = normalizeSource(raw.source);
18603
+ return {
18604
+ theme: {
18605
+ id,
18606
+ builtin: false,
18607
+ name,
18608
+ type,
18609
+ ...terminal !== void 0 ? { terminal } : {},
18610
+ ...syntax !== void 0 ? { syntax } : {},
18611
+ ...ui !== void 0 ? { ui } : {},
18612
+ ...source !== void 0 ? { source } : {}
18613
+ },
18614
+ warnings
18615
+ };
18616
+ }
18617
+ //#endregion
18618
+ //#region src/conversation-schedule-presets.ts
18619
+ const SCHEDULE_PRESET_DAYS = [
18620
+ "mon",
18621
+ "tue",
18622
+ "wed",
18623
+ "thu",
18624
+ "fri",
18625
+ "sat",
18626
+ "sun"
18627
+ ];
18628
+ const TIME_PATTERN = /^([01]\d|2[0-3]):([0-5]\d)$/;
18629
+ const DAY_NUMBERS = {
18630
+ sun: 0,
18631
+ mon: 1,
18632
+ tue: 2,
18633
+ wed: 3,
18634
+ thu: 4,
18635
+ fri: 5,
18636
+ sat: 6
18637
+ };
18638
+ function parseTime(time) {
18639
+ const match = TIME_PATTERN.exec(time);
18640
+ if (!match) throw new Error(`Invalid time "${time}": expected HH:MM (24-hour)`);
18641
+ return {
18642
+ hour: Number(match[1]),
18643
+ minute: Number(match[2])
18644
+ };
18645
+ }
18646
+ function presetToCron(preset) {
18647
+ switch (preset.kind) {
18648
+ case "hourly": return "0 * * * *";
18649
+ case "daily": {
18650
+ const { hour, minute } = parseTime(preset.time);
18651
+ return `${minute} ${hour} * * *`;
18652
+ }
18653
+ case "weekdays": {
18654
+ const { hour, minute } = parseTime(preset.time);
18655
+ return `${minute} ${hour} * * 1-5`;
18656
+ }
18657
+ case "weekly": {
18658
+ const day = DAY_NUMBERS[preset.day.toLowerCase()];
18659
+ if (day === void 0) throw new Error(`Invalid day "${preset.day}": expected sun, mon, tue, wed, thu, fri or sat`);
18660
+ const { hour, minute } = parseTime(preset.time);
18661
+ return `${minute} ${hour} * * ${day}`;
18662
+ }
18663
+ }
18664
+ }
18665
+ //#endregion
16449
18666
  exports.ACP_BEHAVIOR = ACP_BEHAVIOR;
16450
18667
  exports.ACP_CAPABILITIES = ACP_CAPABILITIES;
16451
18668
  exports.AGENT_ROLES = AGENT_ROLES;
18669
+ exports.APPROVAL_TTL_MS = APPROVAL_TTL_MS;
16452
18670
  exports.Activity = Activity;
16453
18671
  exports.ActivityDetailedEvent = ActivityDetailedEvent;
16454
18672
  exports.ActivityEntryEvent = ActivityEntryEvent;
16455
18673
  exports.ActivityTtsEvent = ActivityTtsEvent;
16456
18674
  exports.ActivityUpdatedEvent = ActivityUpdatedEvent;
16457
18675
  exports.AdmissionState = AdmissionState;
18676
+ exports.AdvertisedEndpoint = AdvertisedEndpoint;
16458
18677
  exports.AgentActivityChangedEvent = AgentActivityChangedEvent;
16459
18678
  exports.AgentChannelReply = AgentChannelReply;
16460
18679
  exports.AgentChannelReplyEvent = AgentChannelReplyEvent;
@@ -16508,20 +18727,26 @@ exports.ArtifactUrls = ArtifactUrls;
16508
18727
  exports.ArtifactValidationCode = ArtifactValidationCode;
16509
18728
  exports.ArtifactValidationFinding = ArtifactValidationFinding;
16510
18729
  exports.ArtifactValidationResult = ArtifactValidationResult;
18730
+ exports.BROWSERS = BROWSERS;
18731
+ exports.BUILTIN_COLOR_THEMES = BUILTIN_COLOR_THEMES;
16511
18732
  exports.BackendPane = BackendPane;
16512
18733
  exports.BackendPaneChangedEvent = BackendPaneChangedEvent;
16513
18734
  exports.BackendPaneRemovedEvent = BackendPaneRemovedEvent;
16514
18735
  exports.BeadsFreshnessChangedEvent = BeadsFreshnessChangedEvent;
18736
+ exports.BrowserIdSchema = BrowserIdSchema;
16515
18737
  exports.CHANNEL_REPLY_KIND_VALUES = CHANNEL_REPLY_KIND_VALUES;
16516
18738
  exports.CLAUDE_CODE_BEHAVIOR = CLAUDE_CODE_BEHAVIOR;
16517
18739
  exports.CLAUDE_CODE_CAPABILITIES = CLAUDE_CODE_CAPABILITIES;
16518
18740
  exports.CODEX_BEHAVIOR = CODEX_BEHAVIOR;
16519
18741
  exports.CODEX_CAPABILITIES = CODEX_CAPABILITIES;
18742
+ exports.COLOR_THEME_ID_RE = COLOR_THEME_ID_RE;
16520
18743
  exports.COMPANION_TERMINAL_CLOSE_BODY_KEYS = COMPANION_TERMINAL_CLOSE_BODY_KEYS;
16521
18744
  exports.COMPANION_TERMINAL_OPEN_BODY_KEYS = COMPANION_TERMINAL_OPEN_BODY_KEYS;
16522
18745
  exports.COMPOSER_COMMAND_INSERT_OVERRIDES = COMPOSER_COMMAND_INSERT_OVERRIDES;
16523
18746
  exports.COMPOSER_COMMAND_MANIFEST = COMPOSER_COMMAND_MANIFEST;
16524
18747
  exports.COMPOSER_COMMAND_VARIANTS = COMPOSER_COMMAND_VARIANTS;
18748
+ exports.CONNECT_CLOSE_CODES = CONNECT_CLOSE_CODES;
18749
+ exports.CONNECT_PROTOCOL_VERSION = CONNECT_PROTOCOL_VERSION;
16525
18750
  exports.CONTEXT_LAYER_KINDS = CONTEXT_LAYER_KINDS;
16526
18751
  exports.CONTEXT_PREVIEW_HARNESSES = CONTEXT_PREVIEW_HARNESSES;
16527
18752
  exports.CONVERSATION_PAGE_DEFAULT_LIMIT = CONVERSATION_PAGE_DEFAULT_LIMIT;
@@ -16564,6 +18789,7 @@ exports.ConversationPullRequests = ConversationPullRequests;
16564
18789
  exports.ConversationPullRequestsChangedEvent = ConversationPullRequestsChangedEvent;
16565
18790
  exports.ConversationResponse = ConversationResponse;
16566
18791
  exports.ConversationResume = ConversationResume;
18792
+ exports.ConversationSchedulesChangedEvent = ConversationSchedulesChangedEvent;
16567
18793
  exports.ConversationTitleChangedEvent = ConversationTitleChangedEvent;
16568
18794
  exports.ConversationWindow = ConversationWindow;
16569
18795
  exports.CostEventRecordedEvent = CostEventRecordedEvent;
@@ -16581,14 +18807,22 @@ exports.DerivedIssueState = DerivedIssueState;
16581
18807
  exports.DerivedPrOutsidePipeline = DerivedPrOutsidePipeline;
16582
18808
  exports.DerivedPrState = DerivedPrState;
16583
18809
  exports.DerivedWorkStart = DerivedWorkStart;
18810
+ exports.DirectoryApprovalState = DirectoryApprovalState;
18811
+ exports.DirectoryApprovalView = DirectoryApprovalView;
18812
+ exports.DirectoryClientState = DirectoryClientState;
16584
18813
  exports.DirectoryEntry = DirectoryEntry;
16585
18814
  exports.DirectoryEntryKind = DirectoryEntryKind;
16586
18815
  exports.DirectoryEntryLocation = DirectoryEntryLocation;
16587
18816
  exports.DirectoryEntrySource = DirectoryEntrySource;
16588
18817
  exports.DirectoryEntryState = DirectoryEntryState;
18818
+ exports.DirectoryJoinState = DirectoryJoinState;
18819
+ exports.DirectoryJoinView = DirectoryJoinView;
18820
+ exports.DirectoryMachineView = DirectoryMachineView;
16589
18821
  exports.DirectoryPause = DirectoryPause;
16590
18822
  exports.DirectoryPauseBy = DirectoryPauseBy;
18823
+ exports.DirectoryPlan = DirectoryPlan;
16591
18824
  exports.DirectoryProviderError = DirectoryProviderError;
18825
+ exports.DirectoryResponse = DirectoryResponse;
16592
18826
  exports.DirectoryScope = DirectoryScope;
16593
18827
  exports.DirectoryTranscriptRef = DirectoryTranscriptRef;
16594
18828
  exports.DiscoveredSessionSnapshot = DiscoveredSessionSnapshot;
@@ -16611,9 +18845,19 @@ exports.EnvironmentDescriptor = EnvironmentDescriptor;
16611
18845
  exports.EnvironmentId = EnvironmentId;
16612
18846
  exports.ExtractionProviderConfig = ExtractionProviderConfig;
16613
18847
  exports.ExtractionProviderTarget = ExtractionProviderTarget;
18848
+ exports.FLEET_BINARY_ORDER = FLEET_BINARY_ORDER;
18849
+ exports.FLEET_UPDATE_STILL_WAITING_MS = FLEET_UPDATE_STILL_WAITING_MS;
18850
+ exports.FREE_MACHINE_LIMIT_MESSAGE = FREE_MACHINE_LIMIT_MESSAGE;
16614
18851
  exports.FeatureNode = FeatureNode;
16615
18852
  exports.FeatureRegistryEntry = FeatureRegistryEntry;
16616
18853
  exports.FeatureRegistryStatus = FeatureRegistryStatus;
18854
+ exports.FleetComponentStatus = FleetComponentStatus;
18855
+ exports.FleetInstallMode = FleetInstallMode;
18856
+ exports.FleetJobPhase = FleetJobPhase;
18857
+ exports.FleetProjectRow = FleetProjectRow;
18858
+ exports.FleetProjectsResponse = FleetProjectsResponse;
18859
+ exports.FleetUpdateJobSchema = FleetUpdateJobSchema;
18860
+ exports.FleetUpdateMode = FleetUpdateMode;
16617
18861
  exports.FlywheelAgent = FlywheelAgent;
16618
18862
  exports.FlywheelAgentStatus = FlywheelAgentStatus;
16619
18863
  exports.FlywheelAgentSummary = FlywheelAgentSummary;
@@ -16656,6 +18900,7 @@ exports.FlywheelSystemStatus = FlywheelSystemStatus;
16656
18900
  exports.GITHUB_QUOTA_BUCKETS = GITHUB_QUOTA_BUCKETS;
16657
18901
  exports.GITHUB_QUOTA_CALLERS = GITHUB_QUOTA_CALLERS;
16658
18902
  exports.GITHUB_QUOTA_POOLS = GITHUB_QUOTA_POOLS;
18903
+ exports.GetAvailableBrowsersRpc = GetAvailableBrowsersRpc;
16659
18904
  exports.GetAvailableEditorsRpc = GetAvailableEditorsRpc;
16660
18905
  exports.GetConversationCostByWorkspaceRpc = GetConversationCostByWorkspaceRpc;
16661
18906
  exports.GetConversationCostRpc = GetConversationCostRpc;
@@ -16684,10 +18929,13 @@ exports.HostPlatform = HostPlatform;
16684
18929
  exports.HygieneFinding = HygieneFinding;
16685
18930
  exports.HygienePullRequest = HygienePullRequest;
16686
18931
  exports.HygieneReport = HygieneReport;
18932
+ exports.INBOX_BODY_MAX_BYTES = INBOX_BODY_MAX_BYTES;
18933
+ exports.INBOX_HOLD_MS = INBOX_HOLD_MS;
16687
18934
  exports.INITIAL_READ_MODEL_STATE = INITIAL_READ_MODEL_STATE;
16688
18935
  exports.ISSUE_ATTENTIONS = ISSUE_ATTENTIONS;
16689
18936
  exports.ISSUE_STATES = ISSUE_STATES;
16690
18937
  exports.ISSUE_STATE_PRECEDENCE = ISSUE_STATE_PRECEDENCE;
18938
+ exports.InboundMachineView = InboundMachineView;
16691
18939
  exports.IssueAttention = IssueAttention;
16692
18940
  exports.IssueId = IssueId;
16693
18941
  exports.IssueState = IssueState;
@@ -16701,14 +18949,21 @@ exports.KIMI_CODE_BEHAVIOR = KIMI_CODE_BEHAVIOR;
16701
18949
  exports.KIMI_CODE_CAPABILITIES = KIMI_CODE_CAPABILITIES;
16702
18950
  exports.KNOWN_HARNESSES = KNOWN_HARNESSES;
16703
18951
  exports.LANE_STARTING_GRACE_MS = LANE_STARTING_GRACE_MS;
18952
+ exports.LINK_PROTOCOL_VERSION = LINK_PROTOCOL_VERSION;
16704
18953
  exports.LegacySystemHealthSummary = LegacySystemHealthSummary;
16705
18954
  exports.LegacyWebhookRelaySummary = LegacyWebhookRelaySummary;
16706
18955
  exports.LinearMcpAuthCallbackRelayedEvent = LinearMcpAuthCallbackRelayedEvent;
16707
18956
  exports.LinearMcpAuthHealthyEvent = LinearMcpAuthHealthyEvent;
16708
18957
  exports.LinearMcpAuthNotifiedEvent = LinearMcpAuthNotifiedEvent;
16709
18958
  exports.LinearMcpAuthRequiredEvent = LinearMcpAuthRequiredEvent;
18959
+ exports.LinkAccess = LinkAccess;
18960
+ exports.LinkIncident = LinkIncident;
18961
+ exports.LinkRouteStatus = LinkRouteStatus;
18962
+ exports.LinkRouteView = LinkRouteView;
18963
+ exports.LinkState = LinkState;
16710
18964
  exports.ListDiscoveredSessionsRpc = ListDiscoveredSessionsRpc;
16711
18965
  exports.ListSessionsFeedRpc = ListSessionsFeedRpc;
18966
+ exports.LoadSample = LoadSample;
16712
18967
  exports.MAX_CHANNEL_REPLY_ARTIFACT_LABEL_LENGTH = MAX_CHANNEL_REPLY_ARTIFACT_LABEL_LENGTH;
16713
18968
  exports.MAX_CHANNEL_REPLY_ARTIFACT_REFS = MAX_CHANNEL_REPLY_ARTIFACT_REFS;
16714
18969
  exports.MAX_CHANNEL_REPLY_ARTIFACT_URI_LENGTH = MAX_CHANNEL_REPLY_ARTIFACT_URI_LENGTH;
@@ -16716,6 +18971,11 @@ exports.MAX_CHANNEL_REPLY_SUMMARY_LENGTH = MAX_CHANNEL_REPLY_SUMMARY_LENGTH;
16716
18971
  exports.MEMBERSHIP_UNAVAILABLE_REASONS = MEMBERSHIP_UNAVAILABLE_REASONS;
16717
18972
  exports.MUSE_BEHAVIOR = MUSE_BEHAVIOR;
16718
18973
  exports.MUSE_CAPABILITIES = MUSE_CAPABILITIES;
18974
+ exports.MachineLinkView = MachineLinkView;
18975
+ exports.MachinePlacementMode = MachinePlacementMode;
18976
+ exports.MachineProject = MachineProject;
18977
+ exports.MachineVersionsReportSchema = MachineVersionsReportSchema;
18978
+ exports.MachinesResponse = MachinesResponse;
16719
18979
  exports.MemoryAgentRole = MemoryAgentRole;
16720
18980
  exports.MemoryHealthChangedEvent = MemoryHealthChangedEvent;
16721
18981
  exports.MemoryIdentity = MemoryIdentity;
@@ -16731,12 +18991,14 @@ exports.MergeReadyEvent = MergeReadyEvent;
16731
18991
  exports.ModelOrigin = ModelOrigin;
16732
18992
  exports.ModelOriginEntry = ModelOriginEntry;
16733
18993
  exports.NON_ESSENTIAL_GITHUB_CALLERS = NON_ESSENTIAL_GITHUB_CALLERS;
18994
+ exports.NO_DIRECT_PATH_MESSAGE = NO_DIRECT_PATH_MESSAGE;
16734
18995
  exports.OHMYPI_BEHAVIOR = OHMYPI_BEHAVIOR;
16735
18996
  exports.OHMYPI_CAPABILITIES = OHMYPI_CAPABILITIES;
16736
18997
  exports.OPENCODE_BEHAVIOR = OPENCODE_BEHAVIOR;
16737
18998
  exports.OPENCODE_CAPABILITIES = OPENCODE_CAPABILITIES;
16738
18999
  exports.OVERDECK_AGENT_PROTOCOL_VERSION = OVERDECK_AGENT_PROTOCOL_VERSION;
16739
19000
  exports.OVERDECK_DASHBOARD_PROTOCOL_VERSION = OVERDECK_DASHBOARD_PROTOCOL_VERSION;
19001
+ exports.OpenInBrowserInput = OpenInBrowserInput;
16740
19002
  exports.OpenInEditorInput = OpenInEditorInput;
16741
19003
  exports.OperatorInterventionEvent = OperatorInterventionEvent;
16742
19004
  exports.OrderBook = OrderBook;
@@ -16758,6 +19020,8 @@ exports.PipelineTestCompletedEvent = PipelineTestCompletedEvent;
16758
19020
  exports.PipelineTestStartedEvent = PipelineTestStartedEvent;
16759
19021
  exports.PipelineVerificationFailedEvent = PipelineVerificationFailedEvent;
16760
19022
  exports.PipelineVerificationStartedEvent = PipelineVerificationStartedEvent;
19023
+ exports.PlacementAnswer = PlacementAnswer;
19024
+ exports.PlacementRejection = PlacementRejection;
16761
19025
  exports.PlanItemStatusChangedEvent = PlanItemStatusChangedEvent;
16762
19026
  exports.PlanItemsUnblockedEvent = PlanItemsUnblockedEvent;
16763
19027
  exports.PlanSubitemStatusChangedEvent = PlanSubitemStatusChangedEvent;
@@ -16784,7 +19048,11 @@ exports.PullRequestLinkSource = PullRequestLinkSource;
16784
19048
  exports.PullRequestLinkedConversation = PullRequestLinkedConversation;
16785
19049
  exports.PullRequestSnapshot = PullRequestSnapshot;
16786
19050
  exports.PullRequestState = PullRequestState;
19051
+ exports.RELAY_CAP_MESSAGE = RELAY_CAP_MESSAGE;
19052
+ exports.RELAY_MONTHLY_CAP_BYTES = RELAY_MONTHLY_CAP_BYTES;
19053
+ exports.RESERVED_COLOR_THEME_IDS = RESERVED_COLOR_THEME_IDS;
16787
19054
  exports.RESUME_OPEN_IDS_MAX = RESUME_OPEN_IDS_MAX;
19055
+ exports.ROUTE_KINDS = ROUTE_KINDS;
16788
19056
  exports.RagDecision = RagDecision;
16789
19057
  exports.RagDecisionSource = RagDecisionSource;
16790
19058
  exports.ReadFileAtPathInput = ReadFileAtPathInput;
@@ -16793,6 +19061,7 @@ exports.ReadFileAtPathRpc = ReadFileAtPathRpc;
16793
19061
  exports.ReadWorkspaceFileInput = ReadWorkspaceFileInput;
16794
19062
  exports.ReadWorkspaceFileResult = ReadWorkspaceFileResult;
16795
19063
  exports.ReadWorkspaceFileRpc = ReadWorkspaceFileRpc;
19064
+ exports.RelayStatusView = RelayStatusView;
16796
19065
  exports.ReplayEventsResult = ReplayEventsResult;
16797
19066
  exports.ReplayEventsRpc = ReplayEventsRpc;
16798
19067
  exports.ReplayTooFarBehind = ReplayTooFarBehind;
@@ -16821,7 +19090,12 @@ exports.ReviewVerdictRestoreBlockedEvent = ReviewVerdictRestoreBlockedEvent;
16821
19090
  exports.ReviewerRoundMetadata = ReviewerRoundMetadata;
16822
19091
  exports.ReviewerRoundSummary = ReviewerRoundSummary;
16823
19092
  exports.Role = Role;
19093
+ exports.RouteKind = RouteKind;
19094
+ exports.RouteSource = RouteSource;
19095
+ exports.SCHEDULE_PRESET_DAYS = SCHEDULE_PRESET_DAYS;
16824
19096
  exports.SINGLETON_AGENT_IDS = SINGLETON_AGENT_IDS;
19097
+ exports.SSH_HELPER_PROTOCOL = SSH_HELPER_PROTOCOL;
19098
+ exports.SSH_MACHINE_ERROR_CODES = SSH_MACHINE_ERROR_CODES;
16825
19099
  exports.ScanCompleteEvent = ScanCompleteEvent;
16826
19100
  exports.ScanConversationsRpc = ScanConversationsRpc;
16827
19101
  exports.ScanProgressEvent = ScanProgressEvent;
@@ -16847,11 +19121,17 @@ exports.SessionsFeedFacetsSnapshot = SessionsFeedFacetsSnapshot;
16847
19121
  exports.SessionsFeedRowSnapshot = SessionsFeedRowSnapshot;
16848
19122
  exports.SessionsFeedSource = SessionsFeedSource;
16849
19123
  exports.ShadowInferenceUpdateEvent = ShadowInferenceUpdateEvent;
19124
+ exports.ShellOpenInBrowserRpc = ShellOpenInBrowserRpc;
16850
19125
  exports.ShellOpenInEditorRpc = ShellOpenInEditorRpc;
16851
19126
  exports.SpecialistCompletedEvent = SpecialistCompletedEvent;
16852
19127
  exports.SpecialistFailedEvent = SpecialistFailedEvent;
16853
19128
  exports.SpecialistLifecycle = SpecialistLifecycle;
16854
19129
  exports.SpecialistStartedEvent = SpecialistStartedEvent;
19130
+ exports.SshForwardState = SshForwardState;
19131
+ exports.SshLaunch = SshLaunch;
19132
+ exports.SshLinkInfo = SshLinkInfo;
19133
+ exports.SshMachineErrorCode = SshMachineErrorCode;
19134
+ exports.SshTestResult = SshTestResult;
16855
19135
  exports.StartAgentRpc = StartAgentRpc;
16856
19136
  exports.StartPlanningRpc = StartPlanningRpc;
16857
19137
  exports.SubagentHumanInput = SubagentHumanInput;
@@ -16913,9 +19193,11 @@ exports.applyEvents = applyEvents;
16913
19193
  exports.applyIssueDelta = applyIssueDelta;
16914
19194
  exports.bucketQuotaPoints = bucketQuotaPoints;
16915
19195
  exports.bucketQuotaRemaining = bucketQuotaRemaining;
19196
+ exports.builtinFor = builtinFor;
16916
19197
  exports.canonicalPullRequestUrl = canonicalPullRequestUrl;
16917
19198
  exports.companionTerminalKindFor = companionTerminalKindFor;
16918
19199
  exports.compareEffort = compareEffort;
19200
+ exports.compareFleetBinaries = compareFleetBinaries;
16919
19201
  exports.compareIssueIds = compareIssueIds;
16920
19202
  exports.compareTimelineKeys = compareTimelineKeys;
16921
19203
  exports.createIssueDelta = createIssueDelta;
@@ -16923,8 +19205,11 @@ exports.decodeFlywheelDerivedStatus = decodeFlywheelDerivedStatus;
16923
19205
  exports.decodeFlywheelStats = decodeFlywheelStats;
16924
19206
  exports.decodeTimelineCursor = decodeTimelineCursor;
16925
19207
  exports.deriveProjectCi = deriveProjectCi;
19208
+ exports.effectiveTerminalPalette = effectiveTerminalPalette;
16926
19209
  exports.encodeFlywheelStats = encodeFlywheelStats;
16927
19210
  exports.encodeTimelineCursor = encodeTimelineCursor;
19211
+ exports.formatMachineLoad = formatMachineLoad;
19212
+ exports.formatMachineProfile = formatMachineProfile;
16928
19213
  exports.getHarness = getHarness;
16929
19214
  exports.getHarnessBehavior = getHarnessBehavior;
16930
19215
  exports.getMaxMemoryObservationsPerIssue = getMaxMemoryObservationsPerIssue;
@@ -16945,17 +19230,27 @@ exports.isSingletonConversation = isSingletonConversation;
16945
19230
  exports.isTerminalBackendName = isTerminalBackendName;
16946
19231
  exports.isTerminalTurnDiffSummaryStatus = isTerminalTurnDiffSummaryStatus;
16947
19232
  exports.laneActivityOf = laneActivityOf;
19233
+ exports.linkedConversationName = linkedConversationName;
16948
19234
  exports.normalizeChannelReplyPayload = normalizeChannelReplyPayload;
19235
+ exports.normalizeColorTheme = normalizeColorTheme;
16949
19236
  exports.normalizeHarnessName = normalizeHarnessName;
16950
19237
  exports.omitTurnDiffSummariesForAgent = omitTurnDiffSummariesForAgent;
19238
+ exports.overdeckInstallCommand = overdeckInstallCommand;
16951
19239
  exports.paneAgentKey = paneAgentKey;
19240
+ exports.parseLinkedConversationName = parseLinkedConversationName;
16952
19241
  exports.parsePullRequestRef = parsePullRequestRef;
19242
+ exports.parseTrackerIssueUrl = parseTrackerIssueUrl;
19243
+ exports.presetToCron = presetToCron;
16953
19244
  exports.projectLegacySystemHealthSummary = projectLegacySystemHealthSummary;
19245
+ exports.readableForeground = readableForeground;
16954
19246
  exports.repoFromRemoteUrl = repoFromRemoteUrl;
16955
19247
  exports.resolveEffectivePullRequest = resolveEffectivePullRequest;
19248
+ exports.resolveTrackerIssueId = resolveTrackerIssueId;
19249
+ exports.slugifyThemeId = slugifyThemeId;
16956
19250
  exports.syncSnapshot = syncSnapshot;
16957
19251
  exports.timelineKeyOfMessage = timelineKeyOfMessage;
16958
19252
  exports.timelineKeyOfWork = timelineKeyOfWork;
19253
+ exports.toOpaqueHex = toOpaqueHex;
16959
19254
  exports.trimMemoryObservations = trimMemoryObservations;
16960
19255
  exports.trimTurnDiffSummaries = trimTurnDiffSummaries;
16961
19256
  exports.withPaneLivenessAlias = withPaneLivenessAlias;