@dotobokuri/fleet-console 1.58.1 → 1.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/AGENTS.md +1 -1
  2. package/dist/cli.mjs +664 -193
  3. package/dist/client/assets/{_baseUniq-DJ4C0UQF.js → _baseUniq-CA3I-KTP.js} +1 -1
  4. package/dist/client/assets/{arc-DkQKttnC.js → arc-DOkIWugv.js} +1 -1
  5. package/dist/client/assets/{architectureDiagram-Q4EWVU46-BpuET3uK.js → architectureDiagram-Q4EWVU46--Z_t3Gn9.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-DXYQGD6D-CatlulZp.js → blockDiagram-DXYQGD6D-CrRA5qvl.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AHTNJAMY-BPfWevDh.js → c4Diagram-AHTNJAMY-DKvbMOAM.js} +1 -1
  8. package/dist/client/assets/channel-Bjfd2afp.js +1 -0
  9. package/dist/client/assets/{chunk-4BX2VUAB-a7lkla2P.js → chunk-4BX2VUAB-D6wc2KrB.js} +1 -1
  10. package/dist/client/assets/{chunk-4TB4RGXK-Bh-20OVN.js → chunk-4TB4RGXK-B4QvYh7f.js} +1 -1
  11. package/dist/client/assets/{chunk-55IACEB6-DiPm-_AS.js → chunk-55IACEB6-B0VZPoad.js} +1 -1
  12. package/dist/client/assets/{chunk-EDXVE4YY-BcGep4mz.js → chunk-EDXVE4YY-BdHIgvVh.js} +1 -1
  13. package/dist/client/assets/{chunk-FMBD7UC4-Cn0A6Wm1.js → chunk-FMBD7UC4-BAYTd_pU.js} +1 -1
  14. package/dist/client/assets/{chunk-OYMX7WX6-DNTIDjw4.js → chunk-OYMX7WX6-DkZ-neug.js} +1 -1
  15. package/dist/client/assets/{chunk-QZHKN3VN-cji_BhbG.js → chunk-QZHKN3VN-B5h7E8GE.js} +1 -1
  16. package/dist/client/assets/{chunk-YZCP3GAM-B6I5kLlB.js → chunk-YZCP3GAM-COMJ2EwJ.js} +1 -1
  17. package/dist/client/assets/classDiagram-6PBFFD2Q-DgpHvFOU.js +1 -0
  18. package/dist/client/assets/classDiagram-v2-HSJHXN6E-DgpHvFOU.js +1 -0
  19. package/dist/client/assets/clone-sFXqwEZz.js +1 -0
  20. package/dist/client/assets/{cose-bilkent-S5V4N54A-_Xmui3Dj.js → cose-bilkent-S5V4N54A-JvC7pCqe.js} +1 -1
  21. package/dist/client/assets/{dagre-KV5264BT-BI_m6tGN.js → dagre-KV5264BT-jZdVPQcJ.js} +1 -1
  22. package/dist/client/assets/{diagram-5BDNPKRD-JDBqcRRR.js → diagram-5BDNPKRD-B6-u7AU2.js} +1 -1
  23. package/dist/client/assets/{diagram-G4DWMVQ6-CdIHKaZT.js → diagram-G4DWMVQ6-CV5G3KNM.js} +1 -1
  24. package/dist/client/assets/{diagram-MMDJMWI5-CULX6wM5.js → diagram-MMDJMWI5-ZLrEkNww.js} +1 -1
  25. package/dist/client/assets/{diagram-TYMM5635-C1JXiI2W.js → diagram-TYMM5635-D1tv2JX9.js} +1 -1
  26. package/dist/client/assets/{erDiagram-SMLLAGMA-RJI8bZrW.js → erDiagram-SMLLAGMA-Bta0Mt3t.js} +1 -1
  27. package/dist/client/assets/{flowDiagram-DWJPFMVM-CSrF7U0E.js → flowDiagram-DWJPFMVM-C282oRLT.js} +1 -1
  28. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-CHp3LObA.js → ganttDiagram-T4ZO3ILL-D9P4CVIW.js} +1 -1
  29. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-BEeoTjqh.js → gitGraphDiagram-UUTBAWPF-DLQnTjJ2.js} +1 -1
  30. package/dist/client/assets/{graph-DNvMdh3j.js → graph-Cd8Q-8WG.js} +1 -1
  31. package/dist/client/assets/index-B3gusU1E.js +465 -0
  32. package/dist/client/assets/index-_PHObHQ-.css +1 -0
  33. package/dist/client/assets/{infoDiagram-42DDH7IO-31kh8JMu.js → infoDiagram-42DDH7IO-ClhLpons.js} +1 -1
  34. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-DZgEgolJ.js → ishikawaDiagram-UXIWVN3A-BDeZ2vOG.js} +1 -1
  35. package/dist/client/assets/{journeyDiagram-VCZTEJTY-DfZ3i3Bu.js → journeyDiagram-VCZTEJTY-DbJhbFKN.js} +1 -1
  36. package/dist/client/assets/{kanban-definition-6JOO6SKY-giivFfnv.js → kanban-definition-6JOO6SKY-CYKcE2fE.js} +1 -1
  37. package/dist/client/assets/{layout-DdVRNrH8.js → layout-CuAgTRkn.js} +1 -1
  38. package/dist/client/assets/{linear-3cmeYdGh.js → linear-3EL9MakS.js} +1 -1
  39. package/dist/client/assets/{mermaid.core-Cjqy_Y5Z.js → mermaid.core-7qKaxHEA.js} +4 -4
  40. package/dist/client/assets/{min-Cgsd0one.js → min-4mJsdKjT.js} +1 -1
  41. package/dist/client/assets/{mindmap-definition-QFDTVHPH-PfuGubxC.js → mindmap-definition-QFDTVHPH-B-Zve2OH.js} +1 -1
  42. package/dist/client/assets/{pieDiagram-DEJITSTG-B9O6H439.js → pieDiagram-DEJITSTG-DlsdbAii.js} +1 -1
  43. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-DJH7RQzs.js → quadrantDiagram-34T5L4WZ-Cb4h0xwt.js} +1 -1
  44. package/dist/client/assets/{requirementDiagram-MS252O5E-BZHTYV2q.js → requirementDiagram-MS252O5E-CZNGYqJt.js} +1 -1
  45. package/dist/client/assets/{sankeyDiagram-XADWPNL6-B5aGVyLG.js → sankeyDiagram-XADWPNL6-DeVSGR6W.js} +1 -1
  46. package/dist/client/assets/{sequenceDiagram-FGHM5R23-D2890FYU.js → sequenceDiagram-FGHM5R23-Te7TkLIe.js} +1 -1
  47. package/dist/client/assets/{stateDiagram-FHFEXIEX-DWmhZMWZ.js → stateDiagram-FHFEXIEX-Be-0oYyv.js} +1 -1
  48. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BnQ2lBhr.js +1 -0
  49. package/dist/client/assets/{timeline-definition-GMOUNBTQ-B0pTOfcD.js → timeline-definition-GMOUNBTQ-DQyUgC-K.js} +1 -1
  50. package/dist/client/assets/{vennDiagram-DHZGUBPP-D-S4XLnE.js → vennDiagram-DHZGUBPP-BrArIWI8.js} +1 -1
  51. package/dist/client/assets/{wardley-RL74JXVD-ClPA8Fc3.js → wardley-RL74JXVD-6-sWm8kk.js} +1 -1
  52. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-JJgj7CxJ.js → wardleyDiagram-NUSXRM2D-C4MvFXGS.js} +1 -1
  53. package/dist/client/assets/{xychartDiagram-5P7HB3ND-BBIy9-Kq.js → xychartDiagram-5P7HB3ND-CGrtjhmr.js} +1 -1
  54. package/dist/client/index.html +2 -2
  55. package/dist/fleet-plugins/file-explorer/routes.mjs +132 -13
  56. package/dist/fleet-plugins/ledger/routes.mjs +223 -16
  57. package/dist/fleet-plugins/quota/routes.mjs +206 -270
  58. package/dist/fleet-plugins/scuttlebutt/routes.mjs +557 -130
  59. package/dist/fleet-plugins/terminal/routes.mjs +7107 -5403
  60. package/dist/fleet.mjs +6063 -5545
  61. package/package.json +1 -1
  62. package/dist/client/assets/channel-DDcyY5eB.js +0 -1
  63. package/dist/client/assets/classDiagram-6PBFFD2Q-CqqUqRwS.js +0 -1
  64. package/dist/client/assets/classDiagram-v2-HSJHXN6E-CqqUqRwS.js +0 -1
  65. package/dist/client/assets/clone-CjMEm_X8.js +0 -1
  66. package/dist/client/assets/index-BG857Idy.css +0 -1
  67. package/dist/client/assets/index-CCNdSGui.js +0 -483
  68. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-DoQKtZ4H.js +0 -1
@@ -1,14 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import * as fs from 'node:fs';
3
- import { constants, promises } from 'node:fs';
3
+ import { promises } from 'node:fs';
4
4
  import * as path3 from 'node:path';
5
5
  import path3__default from 'node:path';
6
6
  import crypto2 from 'node:crypto';
7
- import fs2, { mkdtemp, mkdir, rm, writeFile, rename } from 'node:fs/promises';
8
- import { execFile } from 'node:child_process';
7
+ import fs3, { mkdtemp, mkdir, rm, writeFile, rename } from 'node:fs/promises';
8
+ import { execFile } from 'child_process';
9
+ import { constants } from 'fs';
10
+ import 'fs/promises';
11
+ import os2 from 'os';
12
+ import { promisify } from 'util';
13
+ import { deflateRawSync } from 'zlib';
9
14
  import * as os from 'node:os';
10
- import os__default, { tmpdir } from 'node:os';
11
- import { promisify } from 'node:util';
15
+ import { tmpdir } from 'node:os';
12
16
  import { query } from '@anthropic-ai/claude-agent-sdk';
13
17
 
14
18
  var __defProp = Object.defineProperty;
@@ -17637,6 +17641,26 @@ var benchmarks_default = {
17637
17641
  }
17638
17642
  }
17639
17643
  },
17644
+ "claude-opus-5": {
17645
+ source: "cursorbench",
17646
+ rungs: {
17647
+ low: { score: 62.8, tokensPerTask: 18529, stepsPerTask: 37 },
17648
+ medium: { score: 64.3, tokensPerTask: 23612, stepsPerTask: 44 },
17649
+ high: { score: 66.7, tokensPerTask: 27932, stepsPerTask: 48 },
17650
+ xhigh: { score: 69.3, tokensPerTask: 54239, stepsPerTask: 72 },
17651
+ max: { score: 70, tokensPerTask: 61838, stepsPerTask: 78 }
17652
+ }
17653
+ },
17654
+ "claude-fable-5": {
17655
+ source: "cursorbench",
17656
+ rungs: {
17657
+ low: { score: 62.1, tokensPerTask: 18182, stepsPerTask: 31 },
17658
+ medium: { score: 65.2, tokensPerTask: 30366, stepsPerTask: 41 },
17659
+ high: { score: 66.5, tokensPerTask: 43747, stepsPerTask: 48 },
17660
+ xhigh: { score: 68.4, tokensPerTask: 64971, stepsPerTask: 56 },
17661
+ max: { score: 70.5, tokensPerTask: 103525, stepsPerTask: 72 }
17662
+ }
17663
+ },
17640
17664
  "kimi-k3": {
17641
17665
  source: "cursorbench",
17642
17666
  rungs: {
@@ -17685,7 +17709,7 @@ var benchmarks_default = {
17685
17709
  };
17686
17710
  var models_default = {
17687
17711
  version: 1,
17688
- updatedAt: "2026-08-14T00:00:00Z",
17712
+ updatedAt: "2026-08-15T00:00:00Z",
17689
17713
  providers: {
17690
17714
  codex: {
17691
17715
  name: "Codex",
@@ -17827,7 +17851,7 @@ var models_default = {
17827
17851
  cursor: {
17828
17852
  name: "Cursor",
17829
17853
  defaultModel: "auto",
17830
- source: "Cursor GetUsableModels + Run conversationCheckpointUpdate.token_details.max_tokens (cli-2026.07.08-0c04a8a; auto, composer-2.5, and grok-4.5 families observed 2026-08-01); cursor-agent 2026.08.11-e8db854 observed 2026-08-13 for grok-4.6; quotaScope from DashboardService/GetCurrentPeriodUsage autoBucketModels (2026-08-05)",
17854
+ source: "Cursor GetUsableModels + Run conversationCheckpointUpdate.token_details.max_tokens (cli-2026.07.08-0c04a8a; auto, composer-2.5, and grok-4.5 families observed 2026-08-01); cursor-agent 2026.08.11-e8db854 observed 2026-08-13 for grok-4.6; claude-opus-5 and claude-fable-5 standard/Max Mode windows observed 2026-08-10; quotaScope from DashboardService/GetCurrentPeriodUsage autoBucketModels (2026-08-05)",
17831
17855
  models: [
17832
17856
  {
17833
17857
  modelId: "auto",
@@ -17921,6 +17945,94 @@ var models_default = {
17921
17945
  ],
17922
17946
  upstreamModelIdTemplate: "cursor-grok-4.6-{effort}-fast"
17923
17947
  }
17948
+ },
17949
+ {
17950
+ modelId: "claude-opus-5",
17951
+ name: "Opus-5",
17952
+ capabilityClass: "flagship",
17953
+ quotaScope: "api",
17954
+ contextWindow: 3e5,
17955
+ effort: {
17956
+ supported: true,
17957
+ levels: [
17958
+ "low",
17959
+ "medium",
17960
+ "high",
17961
+ "xhigh",
17962
+ "max"
17963
+ ],
17964
+ upstreamModelIdTemplate: "claude-opus-5-{effort}",
17965
+ upstreamModelIds: {
17966
+ xhigh: "claude-opus-5-thinking-xhigh",
17967
+ max: "claude-opus-5-thinking-max"
17968
+ }
17969
+ },
17970
+ benchmarkKey: "claude-opus-5"
17971
+ },
17972
+ {
17973
+ modelId: "claude-opus-5-1m",
17974
+ name: "Opus-5-1M",
17975
+ capabilityClass: "flagship",
17976
+ quotaScope: "api",
17977
+ contextWindow: 1e6,
17978
+ cursorMaxMode: true,
17979
+ effort: {
17980
+ supported: true,
17981
+ levels: [
17982
+ "low",
17983
+ "medium",
17984
+ "high",
17985
+ "xhigh",
17986
+ "max"
17987
+ ],
17988
+ upstreamModelIdTemplate: "claude-opus-5-{effort}",
17989
+ upstreamModelIds: {
17990
+ xhigh: "claude-opus-5-thinking-xhigh",
17991
+ max: "claude-opus-5-thinking-max"
17992
+ }
17993
+ },
17994
+ benchmarkKey: "claude-opus-5"
17995
+ },
17996
+ {
17997
+ modelId: "claude-fable-5",
17998
+ name: "Fable-5",
17999
+ capabilityClass: "flagship",
18000
+ quotaScope: "api",
18001
+ description: "NO ZDR",
18002
+ contextWindow: 3e5,
18003
+ effort: {
18004
+ supported: true,
18005
+ levels: [
18006
+ "low",
18007
+ "medium",
18008
+ "high",
18009
+ "xhigh",
18010
+ "max"
18011
+ ],
18012
+ upstreamModelIdTemplate: "claude-fable-5-{effort}"
18013
+ },
18014
+ benchmarkKey: "claude-fable-5"
18015
+ },
18016
+ {
18017
+ modelId: "claude-fable-5-1m",
18018
+ name: "Fable-5-1M",
18019
+ capabilityClass: "flagship",
18020
+ quotaScope: "api",
18021
+ description: "NO ZDR",
18022
+ contextWindow: 1e6,
18023
+ cursorMaxMode: true,
18024
+ effort: {
18025
+ supported: true,
18026
+ levels: [
18027
+ "low",
18028
+ "medium",
18029
+ "high",
18030
+ "xhigh",
18031
+ "max"
18032
+ ],
18033
+ upstreamModelIdTemplate: "claude-fable-5-{effort}"
18034
+ },
18035
+ benchmarkKey: "claude-fable-5"
17924
18036
  }
17925
18037
  ]
17926
18038
  },
@@ -18534,13 +18646,14 @@ promisify(execFile);
18534
18646
  process.platform === "win32" ? constants.O_RDONLY : constants.O_RDONLY | constants.O_NONBLOCK;
18535
18647
  ({
18536
18648
  platform: process.platform,
18537
- homedir: os__default.homedir,
18649
+ homedir: os2.homedir,
18538
18650
  env: process.env});
18539
- var CURSOR_GREP_RECEIPT_PREFIX = "FLEET_CURSOR_GREP_V1:";
18540
- String.raw`
18651
+ var CURSOR_GREP_RECEIPT_PREFIX = "FLEET_CURSOR_GREP_V2:";
18652
+ var CURSOR_GREP_RECEIPT_SCRIPT = String.raw`
18541
18653
  const {spawn}=require("node:child_process");
18542
18654
  const {TextDecoder}=require("node:util");
18543
- const emit=(value)=>process.stdout.write("${CURSOR_GREP_RECEIPT_PREFIX}"+Buffer.from(JSON.stringify(value)).toString("base64url"));
18655
+ const {deflateRawSync}=require("node:zlib");
18656
+ const emit=(value)=>process.stdout.write("${CURSOR_GREP_RECEIPT_PREFIX}"+deflateRawSync(Buffer.from(JSON.stringify(value))).toString("base64url"));
18544
18657
  (async()=>{try {
18545
18658
  const input=JSON.parse(Buffer.from(process.argv[1],"base64url").toString("utf8"));
18546
18659
  const matchSeparator=30;
@@ -18626,6 +18739,7 @@ const emit=(value)=>process.stdout.write("${CURSOR_GREP_RECEIPT_PREFIX}"+Buffer.
18626
18739
  emit({ok:true,outputMode:input.outputMode,files,counts,matches,totalFiles,totalLines,totalMatchedLines,clientTruncated});
18627
18740
  }catch(error){emit({ok:false,error:error instanceof Error?error.message:String(error)});}})();
18628
18741
  `.trim();
18742
+ deflateRawSync(CURSOR_GREP_RECEIPT_SCRIPT).toString("base64url");
18629
18743
  var cursorAgentDescriptor = [
18630
18744
  "CgthZ2VudC5wcm90bxIIYWdlbnQudjEicgoOR2xvYlRvb2xSZXN1bHQSLAoHc3VjY2VzcxgBIAEoCzIZLmFnZW50LnYxLkdsb2JUb29sU3VjY2Vzc0gAEigK",
18631
18745
  "BWVycm9yGAIgASgLMhcuYWdlbnQudjEuR2xvYlRvb2xFcnJvckgAQggKBnJlc3VsdCIeCg1HbG9iVG9vbEVycm9yEg0KBWVycm9yGAEgASgJIokBCg9HbG9i",
@@ -19479,7 +19593,11 @@ function runVendorQuery(input) {
19479
19593
  close() {
19480
19594
  if (closed) return;
19481
19595
  closed = true;
19482
- void run.return?.(void 0);
19596
+ try {
19597
+ const closing = run.return?.(void 0);
19598
+ if (closing !== void 0) void closing.catch(() => void 0);
19599
+ } catch {
19600
+ }
19483
19601
  }
19484
19602
  };
19485
19603
  }
@@ -19549,8 +19667,11 @@ async function createClaudeGatewaySdk(options) {
19549
19667
  };
19550
19668
  },
19551
19669
  close() {
19552
- run.close();
19553
- release();
19670
+ try {
19671
+ run.close();
19672
+ } finally {
19673
+ release();
19674
+ }
19554
19675
  }
19555
19676
  };
19556
19677
  active = tracked;
@@ -19647,6 +19768,364 @@ function vendorServedMcpServers(servers) {
19647
19768
  }]));
19648
19769
  }
19649
19770
 
19771
+ // ../../packages/core-agent/src/claude/execution-events.ts
19772
+ function createClaudeExecutionEventDecoder() {
19773
+ const toolNames = /* @__PURE__ */ new Map();
19774
+ return {
19775
+ decode(message2) {
19776
+ if (!isRecord(message2)) return [];
19777
+ if (message2.type === "stream_event") return decodeStreamEvent(message2);
19778
+ if (message2.type === "assistant") return decodeAssistant(message2, toolNames);
19779
+ if (message2.type === "user") return decodeUser(message2, toolNames);
19780
+ if (message2.type === "result") return decodeResult(message2);
19781
+ return [];
19782
+ }
19783
+ };
19784
+ }
19785
+ function decodeStreamEvent(message2) {
19786
+ const inner = record2(message2.event);
19787
+ if (inner.type !== "content_block_delta") return [];
19788
+ const delta = record2(inner.delta);
19789
+ if (delta.type === "text_delta" && typeof delta.text === "string" && delta.text.length > 0) {
19790
+ return [{ kind: "text", text: delta.text }];
19791
+ }
19792
+ if (delta.type === "thinking_delta" && typeof delta.thinking === "string" && delta.thinking.length > 0) {
19793
+ return [{ kind: "thinking", text: delta.thinking }];
19794
+ }
19795
+ return [];
19796
+ }
19797
+ function decodeAssistant(message2, toolNames) {
19798
+ const events = [];
19799
+ for (const block of blocks(message2.message)) {
19800
+ if (block.type !== "tool_use") continue;
19801
+ const name = typeof block.name === "string" ? block.name : "tool";
19802
+ const id = typeof block.id === "string" ? block.id : void 0;
19803
+ if (id !== void 0) toolNames.set(id, name);
19804
+ events.push({
19805
+ kind: "tool-start",
19806
+ ...id === void 0 ? {} : { id },
19807
+ name,
19808
+ input: block.input
19809
+ });
19810
+ }
19811
+ return events;
19812
+ }
19813
+ function decodeUser(message2, toolNames) {
19814
+ const events = [];
19815
+ for (const block of blocks(message2.message)) {
19816
+ if (block.type !== "tool_result") continue;
19817
+ const id = typeof block.tool_use_id === "string" ? block.tool_use_id : void 0;
19818
+ const name = id === void 0 ? void 0 : toolNames.get(id);
19819
+ events.push({
19820
+ kind: "tool-end",
19821
+ ...id === void 0 ? {} : { id },
19822
+ ...name === void 0 ? {} : { name },
19823
+ isError: block.is_error === true
19824
+ });
19825
+ }
19826
+ return events;
19827
+ }
19828
+ function decodeResult(message2) {
19829
+ return [{
19830
+ kind: "result",
19831
+ isError: message2.is_error === true,
19832
+ ...typeof message2.result === "string" ? { detail: message2.result } : {},
19833
+ source: "message"
19834
+ }];
19835
+ }
19836
+ function blocks(message2) {
19837
+ const content = record2(message2).content;
19838
+ return Array.isArray(content) ? content.map(record2) : [];
19839
+ }
19840
+ function record2(value) {
19841
+ return isRecord(value) ? value : {};
19842
+ }
19843
+ function isRecord(value) {
19844
+ return value !== null && typeof value === "object" && !Array.isArray(value);
19845
+ }
19846
+
19847
+ // ../../packages/core-agent/src/claude/execution-loop.ts
19848
+ function createClaudeExecutionLoop(options) {
19849
+ let sdk = null;
19850
+ let started = false;
19851
+ let disposed = false;
19852
+ let active = null;
19853
+ let cancelTurn = null;
19854
+ let resumeId = null;
19855
+ let queueTail = Promise.resolve();
19856
+ let startFlight = null;
19857
+ let disposeFlight = null;
19858
+ async function start() {
19859
+ if (disposed) throw new Error("Session disposed");
19860
+ if (started) return;
19861
+ if (startFlight === null) startFlight = startSdk();
19862
+ try {
19863
+ await startFlight;
19864
+ } catch (error51) {
19865
+ if (!disposed) startFlight = null;
19866
+ throw error51;
19867
+ }
19868
+ }
19869
+ async function startSdk() {
19870
+ const created = await options.createSdk();
19871
+ if (disposed) {
19872
+ await created.dispose().catch(() => void 0);
19873
+ throw new Error("Session disposed");
19874
+ }
19875
+ sdk = created;
19876
+ started = true;
19877
+ if (disposed) {
19878
+ sdk = null;
19879
+ started = false;
19880
+ await created.dispose().catch(() => void 0);
19881
+ throw new Error("Session disposed");
19882
+ }
19883
+ }
19884
+ function run(prompt) {
19885
+ if (disposed) return Promise.reject(new Error("Session disposed"));
19886
+ if (!started || sdk === null) return Promise.reject(new Error("Session not started"));
19887
+ if (typeof prompt !== "string" || prompt.trim().length === 0) {
19888
+ return Promise.reject(new Error("Message required"));
19889
+ }
19890
+ const control = createTurnControl();
19891
+ if (cancelTurn === null) cancelTurn = control.cancel;
19892
+ const work = queueTail.then(async () => {
19893
+ if (cancelTurn === null) cancelTurn = control.cancel;
19894
+ try {
19895
+ await runTurn(prompt, control);
19896
+ } finally {
19897
+ if (cancelTurn === control.cancel) cancelTurn = null;
19898
+ }
19899
+ });
19900
+ queueTail = work.catch(() => void 0);
19901
+ return work;
19902
+ }
19903
+ function closeRun(expected) {
19904
+ const current = active;
19905
+ if (current === null || current.run !== expected) return;
19906
+ current.close();
19907
+ }
19908
+ function cancel() {
19909
+ cancelTurn?.();
19910
+ }
19911
+ function dispose() {
19912
+ if (disposeFlight) return disposeFlight;
19913
+ disposed = true;
19914
+ active?.stop();
19915
+ disposeFlight = disposeResources();
19916
+ return disposeFlight;
19917
+ }
19918
+ async function disposeResources() {
19919
+ let observed = queueTail;
19920
+ for (; ; ) {
19921
+ await observed.catch(() => void 0);
19922
+ if (observed === queueTail) break;
19923
+ observed = queueTail;
19924
+ }
19925
+ await startFlight?.catch(() => void 0);
19926
+ const owned = sdk;
19927
+ sdk = null;
19928
+ started = false;
19929
+ await owned?.dispose().catch(() => void 0);
19930
+ }
19931
+ async function runTurn(prompt, control) {
19932
+ if (disposed) return;
19933
+ const owned = sdk;
19934
+ if (!owned) throw new Error("Session not started");
19935
+ let settled = false;
19936
+ let failed = false;
19937
+ let failure;
19938
+ let pendingResult;
19939
+ let timer;
19940
+ let handle = null;
19941
+ const decoder = createClaudeExecutionEventDecoder();
19942
+ const gate = createGate();
19943
+ const clearTimer = () => {
19944
+ if (timer === void 0) return;
19945
+ clearTimeout(timer);
19946
+ timer = void 0;
19947
+ };
19948
+ const complete = () => {
19949
+ if (settled) return;
19950
+ settled = true;
19951
+ try {
19952
+ clearTimer();
19953
+ if (handle !== null) closeRun(handle.run);
19954
+ } finally {
19955
+ gate.open();
19956
+ }
19957
+ };
19958
+ const fail = (error51) => {
19959
+ if (!failed) {
19960
+ failed = true;
19961
+ failure = error51;
19962
+ }
19963
+ complete();
19964
+ };
19965
+ const queueResult = (event) => {
19966
+ if (settled) return;
19967
+ pendingResult = event;
19968
+ complete();
19969
+ };
19970
+ control.onCancel = () => {
19971
+ if (handle !== null) complete();
19972
+ };
19973
+ try {
19974
+ if (control.canceled) return;
19975
+ const built = await options.buildTurn(prompt);
19976
+ if (disposed || control.canceled) return;
19977
+ assertLoopOwnedKeysAbsent(built);
19978
+ const resume = options.continuation.kind === "resume-child" && resumeId !== null ? { resume: resumeId } : {};
19979
+ let run2;
19980
+ try {
19981
+ run2 = await owned.startTurn({ ...built, prompt, ...resume });
19982
+ } catch (error51) {
19983
+ if (disposed || control.canceled) return;
19984
+ throw error51;
19985
+ }
19986
+ const startedRun = run2;
19987
+ let closed = false;
19988
+ handle = {
19989
+ run: startedRun,
19990
+ stop() {
19991
+ complete();
19992
+ },
19993
+ close() {
19994
+ if (closed) return;
19995
+ closed = true;
19996
+ if (active === handle) active = null;
19997
+ try {
19998
+ startedRun.close();
19999
+ } catch {
20000
+ }
20001
+ }
20002
+ };
20003
+ active = handle;
20004
+ if (disposed || control.canceled) {
20005
+ complete();
20006
+ return;
20007
+ }
20008
+ timer = armWatchdog(options.settlement, () => {
20009
+ try {
20010
+ if (settled || disposed) return;
20011
+ queueResult({ kind: "result", isError: true, source: "watchdog" });
20012
+ } catch {
20013
+ }
20014
+ });
20015
+ const consume = async () => {
20016
+ let iterator;
20017
+ try {
20018
+ iterator = startedRun[Symbol.asyncIterator]();
20019
+ while (!settled) {
20020
+ const step = await iterator.next();
20021
+ if (step.done) {
20022
+ if (!settled && !disposed && options.settlement.kind === "result-required") {
20023
+ queueResult({ kind: "result", isError: true, source: "incomplete" });
20024
+ }
20025
+ break;
20026
+ }
20027
+ if (settled || disposed) break;
20028
+ const message2 = step.value;
20029
+ if (options.continuation.kind === "resume-child" && resumeId === null && typeof message2.session_id === "string") {
20030
+ resumeId = message2.session_id;
20031
+ }
20032
+ for (const event of decoder.decode(message2)) {
20033
+ if (event.kind === "result") {
20034
+ queueResult(event);
20035
+ break;
20036
+ }
20037
+ try {
20038
+ options.onEvent?.(event);
20039
+ } catch (error51) {
20040
+ fail(error51);
20041
+ break;
20042
+ }
20043
+ }
20044
+ }
20045
+ } catch (error51) {
20046
+ if (disposed || settled) return;
20047
+ fail(error51);
20048
+ } finally {
20049
+ complete();
20050
+ const closing = iterator?.return?.();
20051
+ if (closing !== void 0) void closing.catch(() => void 0);
20052
+ }
20053
+ };
20054
+ const consumption = consume();
20055
+ consumption.catch(() => void 0);
20056
+ await gate.promise;
20057
+ if (disposed) return;
20058
+ if (pendingResult !== void 0 && !failed) {
20059
+ try {
20060
+ options.onEvent?.(pendingResult);
20061
+ } catch (error51) {
20062
+ failed = true;
20063
+ failure = error51;
20064
+ }
20065
+ }
20066
+ } catch (error51) {
20067
+ if (!disposed && !control.canceled && !failed) {
20068
+ failed = true;
20069
+ failure = error51;
20070
+ }
20071
+ } finally {
20072
+ control.onCancel = null;
20073
+ complete();
20074
+ }
20075
+ if (disposed) return;
20076
+ if (failed) return Promise.reject(failure);
20077
+ }
20078
+ return { start, run, cancel, dispose };
20079
+ }
20080
+ function createTurnControl() {
20081
+ const control = {
20082
+ canceled: false,
20083
+ onCancel: null,
20084
+ cancel() {
20085
+ control.canceled = true;
20086
+ control.onCancel?.();
20087
+ }
20088
+ };
20089
+ return control;
20090
+ }
20091
+ function assertLoopOwnedKeysAbsent(built) {
20092
+ if (!built || typeof built !== "object") return;
20093
+ const record4 = built;
20094
+ if (Object.hasOwn(record4, "prompt") || Object.hasOwn(record4, "resume")) {
20095
+ throw new TypeError("buildTurn must not set prompt or resume; those keys are loop-owned.");
20096
+ }
20097
+ }
20098
+ function watchdogMsOf(settlement) {
20099
+ if (settlement.kind !== "result-required") return void 0;
20100
+ const watchdogMs = settlement.watchdogMs;
20101
+ if (typeof watchdogMs !== "number" || !Number.isFinite(watchdogMs) || watchdogMs <= 0) {
20102
+ return void 0;
20103
+ }
20104
+ return watchdogMs;
20105
+ }
20106
+ function createGate() {
20107
+ let opened = false;
20108
+ let resolvePromise = () => void 0;
20109
+ const promise2 = new Promise((resolve) => {
20110
+ resolvePromise = resolve;
20111
+ });
20112
+ return {
20113
+ promise: promise2,
20114
+ open() {
20115
+ if (opened) return;
20116
+ opened = true;
20117
+ resolvePromise();
20118
+ }
20119
+ };
20120
+ }
20121
+ function armWatchdog(settlement, onTimeout) {
20122
+ const watchdogMs = watchdogMsOf(settlement);
20123
+ if (watchdogMs === void 0) return void 0;
20124
+ const timer = setTimeout(onTimeout, watchdogMs);
20125
+ timer.unref?.();
20126
+ return timer;
20127
+ }
20128
+
19650
20129
  // ../fleet-plugins/scuttlebutt/server/chat-session.ts
19651
20130
  var SCUTTLEBUTT_AGENT = {
19652
20131
  /**
@@ -19698,7 +20177,7 @@ fact interesting without decorating it.`,
19698
20177
  function buildAdmiralSystemPrompt(name, species, bearing, voice) {
19699
20178
  return `# Role
19700
20179
 
19701
- You are Admiral ${name}, ${species} of the Fleet Console \u2014 a small uniformed bird
20180
+ You are Aide ${name}, ${species} of the Fleet Console \u2014 a small uniformed bird
19702
20181
  who keeps station at the scuttlebutt, where the crew stops for water and quick
19703
20182
  talk. You are a quick-answer companion, not a coding agent: no project of your
19704
20183
  own, no repository checked out, no engineering assignment. You are who the crew
@@ -19707,9 +20186,9 @@ asks when they want an answer without leaving what they were doing.
19707
20186
  # Who you are talking to
19708
20187
 
19709
20188
  The person writing to you is the Admiral of the Navy \u2014 your commanding officer,
19710
- several ranks above you. Take their questions as orders and answer promptly,
19711
- with the respect the rank is due. Writing in Korean, call them \uB300\uC6D0\uC218 \u2014 never
19712
- \uC81C\uB3C5, which is your own rank and would put them at your level.
20189
+ far above you. Take their questions as orders and answer promptly, with the
20190
+ respect the rank is due. Writing in Korean, call them \uB300\uC6D0\uC218 \u2014 never
20191
+ \uBD80\uAD00, which is your own rank and would put them at your level.
19713
20192
 
19714
20193
  Respect means telling them the truth: if they are working from a wrong premise,
19715
20194
  say so and give them the right one. Never flatter, and never claim to have
@@ -19742,7 +20221,7 @@ ${bearing}
19742
20221
  is not reading this machine; the ban above is about local files and shell,
19743
20222
  nothing else.
19744
20223
  - Never describe yourself as a coding assistant or list software-engineering
19745
- capabilities. If asked what you are, answer as Admiral ${name} in a sentence or two.
20224
+ capabilities. If asked what you are, answer as Aide ${name} in a sentence or two.
19746
20225
  - Never disclose file paths, directory names, session identifiers, or details of
19747
20226
  the machine you run on.
19748
20227
  - Answer in the language the user wrote in.
@@ -19777,52 +20256,16 @@ work without opening a terminal, a project, or a browser tab.
19777
20256
  }
19778
20257
  var ChatSession = class {
19779
20258
  options;
19780
- sdk = null;
19781
- run = null;
19782
- /** 같은 대화를 이어 가기 위한 자식 세션 id. 첫 턴이 알려 준다. */
19783
- resumeId = null;
19784
- started = false;
19785
- disposed = false;
19786
- turn = Promise.resolve();
19787
- disposeFlight = null;
20259
+ loop;
19788
20260
  constructor(options) {
19789
20261
  this.options = { ...options };
19790
- }
19791
- async start() {
19792
- if (this.disposed) throw new Error("Session disposed");
19793
- if (this.started) return;
19794
- const create2 = { baseUrl: this.options.baseUrl, models: [SCUTTLEBUTT_AGENT.model] };
19795
- const sdk = await (this.options.createSdk?.(create2) ?? createClaudeGatewaySdk(create2));
19796
- if (this.disposed) {
19797
- await sdk.dispose().catch(() => void 0);
19798
- throw new Error("Session disposed");
19799
- }
19800
- this.sdk = sdk;
19801
- this.started = true;
19802
- }
19803
- send(text) {
19804
- if (this.disposed) return Promise.reject(new Error("Session disposed"));
19805
- if (!this.started || !this.sdk) return Promise.reject(new Error("Session not started"));
19806
- if (!text.trim()) return Promise.reject(new Error("Message required"));
19807
- const run = this.turn.then(() => this.runTurn(text));
19808
- this.turn = run.catch(() => void 0);
19809
- return run;
19810
- }
19811
- dispose() {
19812
- if (this.disposeFlight) return this.disposeFlight;
19813
- this.disposed = true;
19814
- this.disposeFlight = this.disposeResources();
19815
- return this.disposeFlight;
19816
- }
19817
- async runTurn(text) {
19818
- const sdk = this.sdk;
19819
- if (!sdk) throw new Error("Session not started");
19820
- const emit = (event) => this.options.onEvent?.(event);
19821
20262
  const redact = (value) => redactScratchPath(value, this.options.cwd);
19822
- let run;
19823
- try {
19824
- run = await sdk.startTurn({
19825
- prompt: text,
20263
+ this.loop = createClaudeExecutionLoop({
20264
+ createSdk: () => {
20265
+ const create2 = { baseUrl: this.options.baseUrl, models: [SCUTTLEBUTT_AGENT.model] };
20266
+ return this.options.createSdk?.(create2) ?? createClaudeGatewaySdk(create2);
20267
+ },
20268
+ buildTurn: () => ({
19826
20269
  model: SCUTTLEBUTT_AGENT.model,
19827
20270
  effort: SCUTTLEBUTT_AGENT.effort,
19828
20271
  systemPrompt: { mode: "replace", text: ADMIRAL_SYSTEM_PROMPTS[this.options.admiral] },
@@ -19831,85 +20274,69 @@ var ChatSession = class {
19831
20274
  allowedTools: [...PET_TOOLS],
19832
20275
  permissionMode: "dontAsk",
19833
20276
  // 텍스트를 흘려 보내려면 부분 메시지가 필요하다. SSE `chunk` 계약이 그것으로 만들어진다.
19834
- includePartialMessages: true,
19835
- ...this.resumeId === null ? {} : { resume: this.resumeId }
19836
- });
19837
- } catch (error51) {
19838
- emit({ type: "error", error: { code: "chat_error", message: redact(message(error51)) } });
19839
- throw error51;
19840
- }
19841
- this.run = run;
19842
- const toolNames = /* @__PURE__ */ new Map();
19843
- try {
19844
- for await (const event of run) {
19845
- if (typeof event.session_id === "string" && this.resumeId === null) this.resumeId = event.session_id;
19846
- for (const mapped of toChatEvents(event, toolNames, redact)) emit(mapped);
20277
+ includePartialMessages: true
20278
+ }),
20279
+ continuation: { kind: "resume-child" },
20280
+ settlement: { kind: "result" },
20281
+ onEvent: (event) => {
20282
+ for (const mapped of toChatEvents(event, redact)) this.options.onEvent?.(mapped);
20283
+ }
20284
+ });
20285
+ }
20286
+ start() {
20287
+ return this.loop.start();
20288
+ }
20289
+ send(text) {
20290
+ return this.loop.run(text).catch((error51) => {
20291
+ if (!isLifecycleError(error51)) {
20292
+ const redact = (value) => redactScratchPath(value, this.options.cwd);
20293
+ this.options.onEvent?.({
20294
+ type: "error",
20295
+ error: { code: "chat_error", message: redact(message(error51)) }
20296
+ });
19847
20297
  }
19848
- } catch (error51) {
19849
- if (this.disposed) return;
19850
- emit({ type: "error", error: { code: "chat_error", message: redact(message(error51)) } });
19851
20298
  throw error51;
19852
- } finally {
19853
- if (this.run === run) this.run = null;
19854
- }
20299
+ });
19855
20300
  }
19856
- async disposeResources() {
19857
- this.run?.close();
19858
- this.run = null;
19859
- await this.turn.catch(() => void 0);
19860
- const sdk = this.sdk;
19861
- this.sdk = null;
19862
- this.started = false;
19863
- await sdk?.dispose().catch(() => void 0);
20301
+ dispose() {
20302
+ return this.loop.dispose();
19864
20303
  }
19865
20304
  };
19866
- function toChatEvents(event, toolNames, redact) {
19867
- if (event.type === "stream_event") {
19868
- const inner = record2(event.event);
19869
- if (inner.type !== "content_block_delta") return [];
19870
- const delta = record2(inner.delta);
19871
- if (delta.type !== "text_delta" || typeof delta.text !== "string" || delta.text.length === 0) return [];
19872
- return [{ type: "chunk", text: redact(delta.text) }];
19873
- }
19874
- if (event.type === "assistant") {
19875
- const events = [];
19876
- for (const block of blocks(event.message)) {
19877
- if (block.type !== "tool_use") continue;
19878
- const name = typeof block.name === "string" ? block.name : "tool";
19879
- if (typeof block.id === "string") toolNames.set(block.id, name);
19880
- events.push({ type: "tool", title: redact(toolTitle(name, block.input)), status: "running" });
19881
- }
19882
- return events;
19883
- }
19884
- if (event.type === "user") {
19885
- const events = [];
19886
- for (const block of blocks(event.message)) {
19887
- if (block.type !== "tool_result") continue;
19888
- const name = typeof block.tool_use_id === "string" ? toolNames.get(block.tool_use_id) ?? "tool" : "tool";
19889
- events.push({ type: "tool", title: redact(name), status: block.is_error === true ? "error" : "done" });
19890
- }
19891
- return events;
19892
- }
19893
- if (event.type === "result") {
19894
- if (event.is_error === true) {
19895
- const detail = typeof event.result === "string" ? event.result : "Chat turn failed";
19896
- return [{ type: "error", error: { code: "chat_error", message: redact(detail) } }];
20305
+ function toChatEvents(event, redact) {
20306
+ if (event.kind === "text") return [{ type: "chunk", text: redact(event.text) }];
20307
+ if (event.kind === "thinking") return [];
20308
+ if (event.kind === "tool-start") {
20309
+ return [{ type: "tool", title: redact(toolTitle(event.name, event.input)), status: "running" }];
20310
+ }
20311
+ if (event.kind === "tool-end") {
20312
+ return [{
20313
+ type: "tool",
20314
+ title: redact(event.name ?? "tool"),
20315
+ status: event.isError ? "error" : "done"
20316
+ }];
20317
+ }
20318
+ if (event.kind === "result") {
20319
+ if (event.isError) {
20320
+ return [{
20321
+ type: "error",
20322
+ error: { code: "chat_error", message: redact(event.detail ?? "Chat turn failed") }
20323
+ }];
19897
20324
  }
19898
20325
  return [{ type: "complete" }];
19899
20326
  }
19900
20327
  return [];
19901
20328
  }
19902
20329
  function toolTitle(name, input) {
19903
- const detail = record2(input);
20330
+ const detail = record3(input);
19904
20331
  for (const key of ["query", "url", "prompt"]) {
19905
20332
  const value = detail[key];
19906
20333
  if (typeof value === "string" && value.trim()) return `${name}: ${value.trim()}`;
19907
20334
  }
19908
20335
  return name;
19909
20336
  }
19910
- function blocks(message2) {
19911
- const content = record2(message2).content;
19912
- return Array.isArray(content) ? content.map(record2) : [];
20337
+ function isLifecycleError(error51) {
20338
+ const text = message(error51);
20339
+ return text === "Session disposed" || text === "Session not started" || text === "Message required";
19913
20340
  }
19914
20341
  function message(error51) {
19915
20342
  return error51 instanceof Error ? error51.message : String(error51);
@@ -19923,7 +20350,7 @@ function redactScratchPath(text, cwd) {
19923
20350
  }
19924
20351
  return redacted;
19925
20352
  }
19926
- function record2(value) {
20353
+ function record3(value) {
19927
20354
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
19928
20355
  }
19929
20356
 
@@ -20030,7 +20457,7 @@ function registerChatRoutes(ctx, deps = {}) {
20030
20457
  const createSession = deps.createSession ?? ((options) => new ChatSession(options));
20031
20458
  const id = deps.id ?? crypto2.randomUUID;
20032
20459
  const ensureDir = deps.ensureDir ?? (async (dir) => {
20033
- await fs2.mkdir(dir, { recursive: true });
20460
+ await fs3.mkdir(dir, { recursive: true });
20034
20461
  });
20035
20462
  registerRouter(ctx, "chat", async ({ req, res, pathname }) => {
20036
20463
  if (!ctx.host.security.isTerminalAuthorized(req)) {
@@ -20146,7 +20573,7 @@ async function handleStop(ctx, req, res, chatId, registry3) {
20146
20573
  if (req.method !== "POST") return methodNotAllowed(ctx, res);
20147
20574
  if (!isJsonRequest(req)) return unsupportedMediaType(ctx, res);
20148
20575
  const body = await ctx.host.http.readJsonBody(req);
20149
- if (!isRecord(body) || Object.keys(body).length > 0) {
20576
+ if (!isRecord2(body) || Object.keys(body).length > 0) {
20150
20577
  ctx.host.http.writeJson(res, 400, { error: "invalid_stop" });
20151
20578
  return true;
20152
20579
  }
@@ -20155,10 +20582,10 @@ async function handleStop(ctx, req, res, chatId, registry3) {
20155
20582
  return true;
20156
20583
  }
20157
20584
  function isMessageBody(value) {
20158
- return isRecord(value) && Object.keys(value).length === 1 && typeof value.text === "string" && value.text.trim().length > 0;
20585
+ return isRecord2(value) && Object.keys(value).length === 1 && typeof value.text === "string" && value.text.trim().length > 0;
20159
20586
  }
20160
20587
  function isStartBody(value) {
20161
- return isRecord(value) && Object.keys(value).length === 1 && typeof value.admiral === "string" && ADMIRAL_IDS.some((admiral) => admiral === value.admiral);
20588
+ return isRecord2(value) && Object.keys(value).length === 1 && typeof value.admiral === "string" && ADMIRAL_IDS.some((admiral) => admiral === value.admiral);
20162
20589
  }
20163
20590
  function isJsonRequest(req) {
20164
20591
  const contentType = req.headers["content-type"];
@@ -20189,7 +20616,7 @@ function securityHeaders(headers) {
20189
20616
  "X-Content-Type-Options": "nosniff"
20190
20617
  };
20191
20618
  }
20192
- function isRecord(value) {
20619
+ function isRecord2(value) {
20193
20620
  return typeof value === "object" && value !== null && !Array.isArray(value);
20194
20621
  }
20195
20622