@dotobokuri/fleet-console 1.62.0 → 1.64.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/README.md +1 -0
- package/dist/cli.mjs +571 -96
- package/dist/client/assets/{_baseUniq-B6CLI4cf.js → _baseUniq-DurhRkUz.js} +1 -1
- package/dist/client/assets/{arc-r3CRqUQ5.js → arc-CRs5BdYr.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-CJfgw2eJ.js → architectureDiagram-Q4EWVU46-Djo8uCUV.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-CkBuOBUs.js → blockDiagram-DXYQGD6D-hQdc3yPb.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-Ln5TenJL.js → c4Diagram-AHTNJAMY-Czv6wUeb.js} +1 -1
- package/dist/client/assets/channel-DluRfcgW.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-BiYTw90k.js → chunk-4BX2VUAB-DXjqdOUQ.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-nPQaGu1w.js → chunk-4TB4RGXK-vvWT5R7G.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-BU2oCJkl.js → chunk-55IACEB6-DMDBDn4n.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-Ej7y6KOv.js → chunk-EDXVE4YY-CvZM4UpD.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-hOkBpfhE.js → chunk-FMBD7UC4-BArng_V9.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-Cv43HwvT.js → chunk-OYMX7WX6-DwNWyoK7.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-Bi7AEJxb.js → chunk-QZHKN3VN--guvcrYz.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-CBwmJdga.js → chunk-YZCP3GAM-BqxZQZyX.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-CwNh44Lk.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-CwNh44Lk.js +1 -0
- package/dist/client/assets/clone-ClWdaAWG.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-ERDn7bly.js → cose-bilkent-S5V4N54A-BMg_LOnu.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-DapcbnEu.js → dagre-KV5264BT-Dr7w5bQR.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-DbRBVaVH.js → diagram-5BDNPKRD-B3mTbXqP.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-CLP0MwBH.js → diagram-G4DWMVQ6-qb3u5_YF.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-BMZ9AsEI.js → diagram-MMDJMWI5-CBBgto41.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-DtPPkZ2y.js → diagram-TYMM5635-Cmo3cjOQ.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-DIvbhhTb.js → erDiagram-SMLLAGMA-HeqZPhtI.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-C_R3RpTk.js → flowDiagram-DWJPFMVM-C34ZouQN.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-eaIqpHsY.js → ganttDiagram-T4ZO3ILL-BL2_YoJe.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-CYCsHY_E.js → gitGraphDiagram-UUTBAWPF-DSC8Gr0E.js} +1 -1
- package/dist/client/assets/{graph-HfvOsgk2.js → graph-C4jsVwYI.js} +1 -1
- package/dist/client/assets/index-BuMY4qU-.js +465 -0
- package/dist/client/assets/index-DxjgOu3C.css +1 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-rmDH5YRZ.js → infoDiagram-42DDH7IO-BX_lYqHx.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-EAZO3mIY.js → ishikawaDiagram-UXIWVN3A-CsXWVwyY.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-4vWYlXOF.js → journeyDiagram-VCZTEJTY-ETPWVMNg.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-CkkSfsbD.js → kanban-definition-6JOO6SKY-m7hLIKgZ.js} +1 -1
- package/dist/client/assets/{layout-DWbhbrdO.js → layout-DrRXjJzL.js} +1 -1
- package/dist/client/assets/{linear-BjRBsqi0.js → linear-DzDd2m9j.js} +1 -1
- package/dist/client/assets/{mermaid.core-RuG-kUU2.js → mermaid.core-BHkit2JY.js} +4 -4
- package/dist/client/assets/{min-D--jZrv5.js → min-DtwEer1D.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-fLwhQBcX.js → mindmap-definition-QFDTVHPH-BO-uheb7.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-DJkWnAQK.js → pieDiagram-DEJITSTG-B_4VqNKt.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-Kd4q9kEz.js → quadrantDiagram-34T5L4WZ-HhtqXdkD.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-Bgrtq8Kh.js → requirementDiagram-MS252O5E-CSotIpLH.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-BW9BdQ-8.js → sankeyDiagram-XADWPNL6-a8krBcEy.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-KpgcxIJb.js → sequenceDiagram-FGHM5R23-D9Tlp8oT.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-CNaCHtL2.js → stateDiagram-FHFEXIEX-CbEP_Jmm.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-B9iCjiGH.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-MGPKEXGI.js → timeline-definition-GMOUNBTQ-CxAJtY22.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-bDOCVDJ1.js → vennDiagram-DHZGUBPP-BSTXi411.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-DuvLJQPg.js → wardley-RL74JXVD-BipCMOcx.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-BdBIEtIl.js → wardleyDiagram-NUSXRM2D-BudrJ8a1.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-vycMI6c3.js → xychartDiagram-5P7HB3ND-BYlMZf2g.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/fleet-plugins/ledger/routes.mjs +265 -12
- package/dist/fleet-plugins/quota/routes.mjs +265 -12
- package/dist/fleet-plugins/scuttlebutt/routes.mjs +545 -79
- package/dist/fleet-plugins/terminal/routes.mjs +1150 -237
- package/dist/fleet.mjs +954 -300
- package/package.json +1 -1
- package/dist/client/assets/channel-DBCxCWtI.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-QQSWiJjR.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-QQSWiJjR.js +0 -1
- package/dist/client/assets/clone-vom5rXcJ.js +0 -1
- package/dist/client/assets/index-C2erdgSj.css +0 -1
- package/dist/client/assets/index-CrEYBugN.js +0 -465
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-D3k4sLJ4.js +0 -1
|
@@ -20834,12 +20834,12 @@ var benchmarks_default = {
|
|
|
20834
20834
|
};
|
|
20835
20835
|
var models_default = {
|
|
20836
20836
|
version: 1,
|
|
20837
|
-
updatedAt: "2026-08-
|
|
20837
|
+
updatedAt: "2026-08-17T00:00:00Z",
|
|
20838
20838
|
providers: {
|
|
20839
20839
|
codex: {
|
|
20840
20840
|
name: "Codex",
|
|
20841
20841
|
defaultModel: "gpt-5.6-sol",
|
|
20842
|
-
source: "codex app-server model/list (codex-cli 0.147.0, 2026-08-11
|
|
20842
|
+
source: "codex app-server model/list (codex-cli 0.147.0, observed 2026-08-11) for model/effort/service-tier and the unsuffixed 272000 defaults; Fleet catalog effort ladders are capped at max because harness launch capabilities are not model rungs; 2026-08-17 production Codex live observations added explicit 512K (524288) and explicit 1M (1000000) variants on the same upstream bases",
|
|
20843
20843
|
models: [
|
|
20844
20844
|
{
|
|
20845
20845
|
modelId: "gpt-5.6-sol",
|
|
@@ -20853,8 +20853,7 @@ var models_default = {
|
|
|
20853
20853
|
"medium",
|
|
20854
20854
|
"high",
|
|
20855
20855
|
"xhigh",
|
|
20856
|
-
"max"
|
|
20857
|
-
"ultra"
|
|
20856
|
+
"max"
|
|
20858
20857
|
]
|
|
20859
20858
|
},
|
|
20860
20859
|
aliases: [
|
|
@@ -20876,8 +20875,7 @@ var models_default = {
|
|
|
20876
20875
|
"medium",
|
|
20877
20876
|
"high",
|
|
20878
20877
|
"xhigh",
|
|
20879
|
-
"max"
|
|
20880
|
-
"ultra"
|
|
20878
|
+
"max"
|
|
20881
20879
|
]
|
|
20882
20880
|
},
|
|
20883
20881
|
aliases: [
|
|
@@ -20897,8 +20895,7 @@ var models_default = {
|
|
|
20897
20895
|
"medium",
|
|
20898
20896
|
"high",
|
|
20899
20897
|
"xhigh",
|
|
20900
|
-
"max"
|
|
20901
|
-
"ultra"
|
|
20898
|
+
"max"
|
|
20902
20899
|
]
|
|
20903
20900
|
},
|
|
20904
20901
|
aliases: [
|
|
@@ -20920,8 +20917,7 @@ var models_default = {
|
|
|
20920
20917
|
"medium",
|
|
20921
20918
|
"high",
|
|
20922
20919
|
"xhigh",
|
|
20923
|
-
"max"
|
|
20924
|
-
"ultra"
|
|
20920
|
+
"max"
|
|
20925
20921
|
]
|
|
20926
20922
|
},
|
|
20927
20923
|
aliases: [
|
|
@@ -20970,6 +20966,264 @@ var models_default = {
|
|
|
20970
20966
|
"gpt-5.6-luna-fast"
|
|
20971
20967
|
],
|
|
20972
20968
|
benchmarkKey: "gpt-5.6-luna"
|
|
20969
|
+
},
|
|
20970
|
+
{
|
|
20971
|
+
modelId: "gpt-5.6-sol-512k",
|
|
20972
|
+
name: "GPT-5.6-Sol-512K",
|
|
20973
|
+
capabilityClass: "flagship",
|
|
20974
|
+
providerModelId: "gpt-5.6-sol",
|
|
20975
|
+
contextWindow: 524288,
|
|
20976
|
+
effort: {
|
|
20977
|
+
supported: true,
|
|
20978
|
+
levels: [
|
|
20979
|
+
"low",
|
|
20980
|
+
"medium",
|
|
20981
|
+
"high",
|
|
20982
|
+
"xhigh",
|
|
20983
|
+
"max"
|
|
20984
|
+
]
|
|
20985
|
+
},
|
|
20986
|
+
aliases: [
|
|
20987
|
+
"gpt-5.6-sol-512k"
|
|
20988
|
+
],
|
|
20989
|
+
benchmarkKey: "gpt-5.6-sol"
|
|
20990
|
+
},
|
|
20991
|
+
{
|
|
20992
|
+
modelId: "gpt-5.6-sol-512k-fast",
|
|
20993
|
+
name: "GPT-5.6-Sol-512K-Fast",
|
|
20994
|
+
capabilityClass: "flagship",
|
|
20995
|
+
providerModelId: "gpt-5.6-sol",
|
|
20996
|
+
serviceTier: "priority",
|
|
20997
|
+
contextWindow: 524288,
|
|
20998
|
+
effort: {
|
|
20999
|
+
supported: true,
|
|
21000
|
+
levels: [
|
|
21001
|
+
"low",
|
|
21002
|
+
"medium",
|
|
21003
|
+
"high",
|
|
21004
|
+
"xhigh",
|
|
21005
|
+
"max"
|
|
21006
|
+
]
|
|
21007
|
+
},
|
|
21008
|
+
aliases: [
|
|
21009
|
+
"gpt-5.6-sol-512k-fast"
|
|
21010
|
+
],
|
|
21011
|
+
benchmarkKey: "gpt-5.6-sol"
|
|
21012
|
+
},
|
|
21013
|
+
{
|
|
21014
|
+
modelId: "gpt-5.6-luna-512k",
|
|
21015
|
+
name: "GPT-5.6-Luna-512K",
|
|
21016
|
+
capabilityClass: "light",
|
|
21017
|
+
providerModelId: "gpt-5.6-luna",
|
|
21018
|
+
contextWindow: 524288,
|
|
21019
|
+
effort: {
|
|
21020
|
+
supported: true,
|
|
21021
|
+
levels: [
|
|
21022
|
+
"low",
|
|
21023
|
+
"medium",
|
|
21024
|
+
"high",
|
|
21025
|
+
"xhigh",
|
|
21026
|
+
"max"
|
|
21027
|
+
]
|
|
21028
|
+
},
|
|
21029
|
+
aliases: [
|
|
21030
|
+
"gpt-5.6-luna-512k"
|
|
21031
|
+
],
|
|
21032
|
+
benchmarkKey: "gpt-5.6-luna"
|
|
21033
|
+
},
|
|
21034
|
+
{
|
|
21035
|
+
modelId: "gpt-5.6-luna-512k-fast",
|
|
21036
|
+
name: "GPT-5.6-Luna-512K-Fast",
|
|
21037
|
+
capabilityClass: "light",
|
|
21038
|
+
providerModelId: "gpt-5.6-luna",
|
|
21039
|
+
serviceTier: "priority",
|
|
21040
|
+
contextWindow: 524288,
|
|
21041
|
+
effort: {
|
|
21042
|
+
supported: true,
|
|
21043
|
+
levels: [
|
|
21044
|
+
"low",
|
|
21045
|
+
"medium",
|
|
21046
|
+
"high",
|
|
21047
|
+
"xhigh",
|
|
21048
|
+
"max"
|
|
21049
|
+
]
|
|
21050
|
+
},
|
|
21051
|
+
aliases: [
|
|
21052
|
+
"gpt-5.6-luna-512k-fast"
|
|
21053
|
+
],
|
|
21054
|
+
benchmarkKey: "gpt-5.6-luna"
|
|
21055
|
+
},
|
|
21056
|
+
{
|
|
21057
|
+
modelId: "gpt-5.6-terra-512k",
|
|
21058
|
+
name: "GPT-5.6-Terra-512K",
|
|
21059
|
+
capabilityClass: "standard",
|
|
21060
|
+
providerModelId: "gpt-5.6-terra",
|
|
21061
|
+
contextWindow: 524288,
|
|
21062
|
+
effort: {
|
|
21063
|
+
supported: true,
|
|
21064
|
+
levels: [
|
|
21065
|
+
"low",
|
|
21066
|
+
"medium",
|
|
21067
|
+
"high",
|
|
21068
|
+
"xhigh",
|
|
21069
|
+
"max"
|
|
21070
|
+
]
|
|
21071
|
+
},
|
|
21072
|
+
aliases: [
|
|
21073
|
+
"gpt-5.6-terra-512k"
|
|
21074
|
+
],
|
|
21075
|
+
benchmarkKey: "gpt-5.6-terra"
|
|
21076
|
+
},
|
|
21077
|
+
{
|
|
21078
|
+
modelId: "gpt-5.6-terra-512k-fast",
|
|
21079
|
+
name: "GPT-5.6-Terra-512K-Fast",
|
|
21080
|
+
capabilityClass: "standard",
|
|
21081
|
+
providerModelId: "gpt-5.6-terra",
|
|
21082
|
+
serviceTier: "priority",
|
|
21083
|
+
contextWindow: 524288,
|
|
21084
|
+
effort: {
|
|
21085
|
+
supported: true,
|
|
21086
|
+
levels: [
|
|
21087
|
+
"low",
|
|
21088
|
+
"medium",
|
|
21089
|
+
"high",
|
|
21090
|
+
"xhigh",
|
|
21091
|
+
"max"
|
|
21092
|
+
]
|
|
21093
|
+
},
|
|
21094
|
+
aliases: [
|
|
21095
|
+
"gpt-5.6-terra-512k-fast"
|
|
21096
|
+
],
|
|
21097
|
+
benchmarkKey: "gpt-5.6-terra"
|
|
21098
|
+
},
|
|
21099
|
+
{
|
|
21100
|
+
modelId: "gpt-5.6-sol-1m",
|
|
21101
|
+
name: "GPT-5.6-Sol-1M",
|
|
21102
|
+
capabilityClass: "flagship",
|
|
21103
|
+
providerModelId: "gpt-5.6-sol",
|
|
21104
|
+
contextWindow: 1e6,
|
|
21105
|
+
effort: {
|
|
21106
|
+
supported: true,
|
|
21107
|
+
levels: [
|
|
21108
|
+
"low",
|
|
21109
|
+
"medium",
|
|
21110
|
+
"high",
|
|
21111
|
+
"xhigh",
|
|
21112
|
+
"max"
|
|
21113
|
+
]
|
|
21114
|
+
},
|
|
21115
|
+
aliases: [
|
|
21116
|
+
"gpt-5.6-sol-1m"
|
|
21117
|
+
],
|
|
21118
|
+
benchmarkKey: "gpt-5.6-sol"
|
|
21119
|
+
},
|
|
21120
|
+
{
|
|
21121
|
+
modelId: "gpt-5.6-sol-1m-fast",
|
|
21122
|
+
name: "GPT-5.6-Sol-1M-Fast",
|
|
21123
|
+
capabilityClass: "flagship",
|
|
21124
|
+
providerModelId: "gpt-5.6-sol",
|
|
21125
|
+
serviceTier: "priority",
|
|
21126
|
+
contextWindow: 1e6,
|
|
21127
|
+
effort: {
|
|
21128
|
+
supported: true,
|
|
21129
|
+
levels: [
|
|
21130
|
+
"low",
|
|
21131
|
+
"medium",
|
|
21132
|
+
"high",
|
|
21133
|
+
"xhigh",
|
|
21134
|
+
"max"
|
|
21135
|
+
]
|
|
21136
|
+
},
|
|
21137
|
+
aliases: [
|
|
21138
|
+
"gpt-5.6-sol-1m-fast"
|
|
21139
|
+
],
|
|
21140
|
+
benchmarkKey: "gpt-5.6-sol"
|
|
21141
|
+
},
|
|
21142
|
+
{
|
|
21143
|
+
modelId: "gpt-5.6-luna-1m",
|
|
21144
|
+
name: "GPT-5.6-Luna-1M",
|
|
21145
|
+
capabilityClass: "light",
|
|
21146
|
+
providerModelId: "gpt-5.6-luna",
|
|
21147
|
+
contextWindow: 1e6,
|
|
21148
|
+
effort: {
|
|
21149
|
+
supported: true,
|
|
21150
|
+
levels: [
|
|
21151
|
+
"low",
|
|
21152
|
+
"medium",
|
|
21153
|
+
"high",
|
|
21154
|
+
"xhigh",
|
|
21155
|
+
"max"
|
|
21156
|
+
]
|
|
21157
|
+
},
|
|
21158
|
+
aliases: [
|
|
21159
|
+
"gpt-5.6-luna-1m"
|
|
21160
|
+
],
|
|
21161
|
+
benchmarkKey: "gpt-5.6-luna"
|
|
21162
|
+
},
|
|
21163
|
+
{
|
|
21164
|
+
modelId: "gpt-5.6-luna-1m-fast",
|
|
21165
|
+
name: "GPT-5.6-Luna-1M-Fast",
|
|
21166
|
+
capabilityClass: "light",
|
|
21167
|
+
providerModelId: "gpt-5.6-luna",
|
|
21168
|
+
serviceTier: "priority",
|
|
21169
|
+
contextWindow: 1e6,
|
|
21170
|
+
effort: {
|
|
21171
|
+
supported: true,
|
|
21172
|
+
levels: [
|
|
21173
|
+
"low",
|
|
21174
|
+
"medium",
|
|
21175
|
+
"high",
|
|
21176
|
+
"xhigh",
|
|
21177
|
+
"max"
|
|
21178
|
+
]
|
|
21179
|
+
},
|
|
21180
|
+
aliases: [
|
|
21181
|
+
"gpt-5.6-luna-1m-fast"
|
|
21182
|
+
],
|
|
21183
|
+
benchmarkKey: "gpt-5.6-luna"
|
|
21184
|
+
},
|
|
21185
|
+
{
|
|
21186
|
+
modelId: "gpt-5.6-terra-1m",
|
|
21187
|
+
name: "GPT-5.6-Terra-1M",
|
|
21188
|
+
capabilityClass: "standard",
|
|
21189
|
+
providerModelId: "gpt-5.6-terra",
|
|
21190
|
+
contextWindow: 1e6,
|
|
21191
|
+
effort: {
|
|
21192
|
+
supported: true,
|
|
21193
|
+
levels: [
|
|
21194
|
+
"low",
|
|
21195
|
+
"medium",
|
|
21196
|
+
"high",
|
|
21197
|
+
"xhigh",
|
|
21198
|
+
"max"
|
|
21199
|
+
]
|
|
21200
|
+
},
|
|
21201
|
+
aliases: [
|
|
21202
|
+
"gpt-5.6-terra-1m"
|
|
21203
|
+
],
|
|
21204
|
+
benchmarkKey: "gpt-5.6-terra"
|
|
21205
|
+
},
|
|
21206
|
+
{
|
|
21207
|
+
modelId: "gpt-5.6-terra-1m-fast",
|
|
21208
|
+
name: "GPT-5.6-Terra-1M-Fast",
|
|
21209
|
+
capabilityClass: "standard",
|
|
21210
|
+
providerModelId: "gpt-5.6-terra",
|
|
21211
|
+
serviceTier: "priority",
|
|
21212
|
+
contextWindow: 1e6,
|
|
21213
|
+
effort: {
|
|
21214
|
+
supported: true,
|
|
21215
|
+
levels: [
|
|
21216
|
+
"low",
|
|
21217
|
+
"medium",
|
|
21218
|
+
"high",
|
|
21219
|
+
"xhigh",
|
|
21220
|
+
"max"
|
|
21221
|
+
]
|
|
21222
|
+
},
|
|
21223
|
+
aliases: [
|
|
21224
|
+
"gpt-5.6-terra-1m-fast"
|
|
21225
|
+
],
|
|
21226
|
+
benchmarkKey: "gpt-5.6-terra"
|
|
20973
21227
|
}
|
|
20974
21228
|
]
|
|
20975
21229
|
},
|
|
@@ -21453,8 +21707,7 @@ var GATEWAY_REASONING_EFFORTS = [
|
|
|
21453
21707
|
"medium",
|
|
21454
21708
|
"high",
|
|
21455
21709
|
"xhigh",
|
|
21456
|
-
"max"
|
|
21457
|
-
"ultra"
|
|
21710
|
+
"max"
|
|
21458
21711
|
];
|
|
21459
21712
|
var GatewayEffortUpstreamModelIdsSchema = external_exports.partialRecord(
|
|
21460
21713
|
external_exports.enum(GATEWAY_REASONING_EFFORTS),
|
|
@@ -21881,8 +22134,7 @@ var ANTHROPIC_EFFORT_RUNGS = /* @__PURE__ */ new Set([
|
|
|
21881
22134
|
"medium",
|
|
21882
22135
|
"high",
|
|
21883
22136
|
"xhigh",
|
|
21884
|
-
"max"
|
|
21885
|
-
"ultra"
|
|
22137
|
+
"max"
|
|
21886
22138
|
]);
|
|
21887
22139
|
function freezeGatewayModelEffort(effort) {
|
|
21888
22140
|
if (!effort?.supported) return UNSUPPORTED_GATEWAY_MODEL_EFFORT;
|
|
@@ -31491,11 +31743,10 @@ var GENERAL_PURPOSE_AGENT_PROMPT = [
|
|
|
31491
31743
|
].join("\n");
|
|
31492
31744
|
var FLEET_PLUGIN_NAME = "fleet";
|
|
31493
31745
|
function exposedEffortLadder(modelId, ladder, exposure) {
|
|
31494
|
-
const deliverable = ladder.filter((rung) => rung !== "ultra");
|
|
31495
31746
|
const chosen = exposure?.[modelId];
|
|
31496
|
-
if (chosen === void 0 || chosen.length === 0) return
|
|
31497
|
-
const narrowed =
|
|
31498
|
-
return narrowed.length > 0 ? narrowed :
|
|
31747
|
+
if (chosen === void 0 || chosen.length === 0) return ladder;
|
|
31748
|
+
const narrowed = ladder.filter((rung) => chosen.includes(rung));
|
|
31749
|
+
return narrowed.length > 0 ? narrowed : ladder;
|
|
31499
31750
|
}
|
|
31500
31751
|
function buildGatewayCustomAgents(exposed, exposure) {
|
|
31501
31752
|
const agents = {};
|
|
@@ -44313,6 +44564,9 @@ function shouldSyncDirectoryForTest(platform) {
|
|
|
44313
44564
|
function readSocketRole(value) {
|
|
44314
44565
|
return value === "viewer" ? "viewer" : void 0;
|
|
44315
44566
|
}
|
|
44567
|
+
function readTicketChannel(value) {
|
|
44568
|
+
return value === "chat" ? "chat" : void 0;
|
|
44569
|
+
}
|
|
44316
44570
|
var DEFAULT_TICKET_TTL_MS = 1e4;
|
|
44317
44571
|
function createPluginTerminalTicketRegistry(deps = {}) {
|
|
44318
44572
|
const ttlMs = deps.ttlMs ?? DEFAULT_TICKET_TTL_MS;
|
|
@@ -45000,7 +45254,23 @@ function createPluginTerminalUpgradeHandler(deps) {
|
|
|
45000
45254
|
return true;
|
|
45001
45255
|
}
|
|
45002
45256
|
const context = deps.tickets.consume(url2.searchParams.get("ticket"));
|
|
45003
|
-
if (!context
|
|
45257
|
+
if (!context) {
|
|
45258
|
+
socket.destroy();
|
|
45259
|
+
return true;
|
|
45260
|
+
}
|
|
45261
|
+
if (context.channel === "chat") {
|
|
45262
|
+
const attachChat = deps.attachChat;
|
|
45263
|
+
if (!attachChat) {
|
|
45264
|
+
socket.destroy();
|
|
45265
|
+
return true;
|
|
45266
|
+
}
|
|
45267
|
+
const server2 = getWebSocketServer();
|
|
45268
|
+
server2.handleUpgrade(req, socket, head, (ws) => {
|
|
45269
|
+
attachChat(ws, context);
|
|
45270
|
+
});
|
|
45271
|
+
return true;
|
|
45272
|
+
}
|
|
45273
|
+
if (!deps.sessions.canAttach(context.sessionId)) {
|
|
45004
45274
|
socket.destroy();
|
|
45005
45275
|
return true;
|
|
45006
45276
|
}
|
|
@@ -45039,6 +45309,7 @@ function readUpgradeUrl(req) {
|
|
|
45039
45309
|
var SHELL_OPERATION_TYPE = "shell";
|
|
45040
45310
|
function createTerminalRuntime(ctx) {
|
|
45041
45311
|
const tickets = createPluginTerminalTicketRegistry();
|
|
45312
|
+
let chatAttach = null;
|
|
45042
45313
|
const terminalExitListeners = /* @__PURE__ */ new Set();
|
|
45043
45314
|
const terminalTitleListeners = /* @__PURE__ */ new Map();
|
|
45044
45315
|
const terminalLaunchResolvers = /* @__PURE__ */ new Map();
|
|
@@ -45061,7 +45332,14 @@ function createTerminalRuntime(ctx) {
|
|
|
45061
45332
|
const upgrade = createPluginTerminalUpgradeHandler({
|
|
45062
45333
|
tickets,
|
|
45063
45334
|
sessions,
|
|
45064
|
-
isAuthorized: ctx.host.security.isTerminalAuthorized
|
|
45335
|
+
isAuthorized: ctx.host.security.isTerminalAuthorized,
|
|
45336
|
+
attachChat: (socket, context) => {
|
|
45337
|
+
if (!chatAttach) {
|
|
45338
|
+
socket.close(1013, "chat_unavailable");
|
|
45339
|
+
return;
|
|
45340
|
+
}
|
|
45341
|
+
chatAttach(socket, context);
|
|
45342
|
+
}
|
|
45065
45343
|
});
|
|
45066
45344
|
return {
|
|
45067
45345
|
handleUpgrade: upgrade.handleUpgrade,
|
|
@@ -45097,7 +45375,14 @@ function createTerminalRuntime(ctx) {
|
|
|
45097
45375
|
if (terminalLaunchResolvers.get(operationType) === resolver) terminalLaunchResolvers.delete(operationType);
|
|
45098
45376
|
};
|
|
45099
45377
|
},
|
|
45378
|
+
bindChatAttach: (attach) => {
|
|
45379
|
+
chatAttach = attach;
|
|
45380
|
+
return () => {
|
|
45381
|
+
if (chatAttach === attach) chatAttach = null;
|
|
45382
|
+
};
|
|
45383
|
+
},
|
|
45100
45384
|
stop: async () => {
|
|
45385
|
+
chatAttach = null;
|
|
45101
45386
|
upgrade.close();
|
|
45102
45387
|
await sessions.stop();
|
|
45103
45388
|
terminalExitListeners.clear();
|
|
@@ -45345,6 +45630,7 @@ var EFFORT_LABELS = {
|
|
|
45345
45630
|
ultra: "ULTRACODE"
|
|
45346
45631
|
};
|
|
45347
45632
|
var APEX_EFFORTS = ["max", "ultra"];
|
|
45633
|
+
var ULTRACODE_LAUNCH_EFFORT = "ultra";
|
|
45348
45634
|
var NATIVE_MODEL_LABELS = {
|
|
45349
45635
|
// Claude Code's 1M coordinates stay under their plain menu labels.
|
|
45350
45636
|
"fable[1m]": "Fable",
|
|
@@ -45401,27 +45687,27 @@ function buildClaudeGatewayLaunchVariants(selection) {
|
|
|
45401
45687
|
}
|
|
45402
45688
|
return groups;
|
|
45403
45689
|
}
|
|
45404
|
-
var EFFORT_AXIS = [...NATIVE_CLAUDE_EFFORTS,
|
|
45690
|
+
var EFFORT_AXIS = [...NATIVE_CLAUDE_EFFORTS, ULTRACODE_LAUNCH_EFFORT];
|
|
45405
45691
|
function providerGroupId(provider) {
|
|
45406
45692
|
return `gateway:${provider}`;
|
|
45407
45693
|
}
|
|
45408
45694
|
function toGatewayRow(model, selection) {
|
|
45409
|
-
const
|
|
45410
|
-
const
|
|
45411
|
-
const effortAxis =
|
|
45695
|
+
const ordinary = selection.effortExposure[model.id] ?? exposableEffortLadder(model);
|
|
45696
|
+
const hasMax = ordinary.includes("max");
|
|
45697
|
+
const effortAxis = ordinary.length === 0 ? [ULTRACODE_LAUNCH_EFFORT] : [...NATIVE_CLAUDE_EFFORTS.filter((effort) => effort !== "max" || hasMax), ULTRACODE_LAUNCH_EFFORT];
|
|
45698
|
+
const gatedEfforts = hasMax ? ["max", ULTRACODE_LAUNCH_EFFORT] : [ULTRACODE_LAUNCH_EFFORT];
|
|
45699
|
+
const chips = [...ordinary, ULTRACODE_LAUNCH_EFFORT];
|
|
45412
45700
|
return {
|
|
45413
45701
|
id: model.id,
|
|
45414
45702
|
label: bareModelName(model),
|
|
45415
45703
|
launch: { model: model.id },
|
|
45416
|
-
|
|
45417
|
-
|
|
45418
|
-
|
|
45419
|
-
|
|
45420
|
-
|
|
45421
|
-
|
|
45422
|
-
|
|
45423
|
-
}))
|
|
45424
|
-
} : {}
|
|
45704
|
+
effortAxis,
|
|
45705
|
+
gatedEfforts,
|
|
45706
|
+
chips: chips.map((effort) => ({
|
|
45707
|
+
id: effort,
|
|
45708
|
+
label: EFFORT_LABELS[effort] ?? effort.toUpperCase(),
|
|
45709
|
+
launch: { model: model.id, effort }
|
|
45710
|
+
}))
|
|
45425
45711
|
};
|
|
45426
45712
|
}
|
|
45427
45713
|
function resolveDisabledReason(cli) {
|
|
@@ -45624,6 +45910,9 @@ var CLAUDE_GATEWAY_TURN_KEYS = Object.freeze([
|
|
|
45624
45910
|
"abortController",
|
|
45625
45911
|
"stderr"
|
|
45626
45912
|
]);
|
|
45913
|
+
var CLAUDE_GATEWAY_SESSION_KEYS = Object.freeze(
|
|
45914
|
+
CLAUDE_GATEWAY_TURN_KEYS.filter((key) => key !== "prompt")
|
|
45915
|
+
);
|
|
45627
45916
|
|
|
45628
45917
|
// ../../packages/core-agent/src/claude/launch-env.ts
|
|
45629
45918
|
var CLAUDE_GATEWAY_MODEL_CACHE_RELPATH = "cache/gateway-models.json";
|
|
@@ -45684,6 +45973,32 @@ async function createIsolatedClaudeConfigDir(tempRoot = tmpdir()) {
|
|
|
45684
45973
|
}
|
|
45685
45974
|
};
|
|
45686
45975
|
}
|
|
45976
|
+
function readVendorContextUsage(response) {
|
|
45977
|
+
if (typeof response !== "object" || response === null) return null;
|
|
45978
|
+
const usage4 = response;
|
|
45979
|
+
if (typeof usage4.totalTokens !== "number" || typeof usage4.maxTokens !== "number") return null;
|
|
45980
|
+
const rows = Array.isArray(usage4.categories) ? usage4.categories : [];
|
|
45981
|
+
const memory = Array.isArray(usage4.memoryFiles) ? usage4.memoryFiles : [];
|
|
45982
|
+
const mcp = Array.isArray(usage4.mcpTools) ? usage4.mcpTools : [];
|
|
45983
|
+
return {
|
|
45984
|
+
total: usage4.totalTokens,
|
|
45985
|
+
max: usage4.maxTokens,
|
|
45986
|
+
model: typeof usage4.model === "string" ? usage4.model : "",
|
|
45987
|
+
compactAt: usage4.isAutoCompactEnabled === true && typeof usage4.autoCompactThreshold === "number" ? usage4.autoCompactThreshold : null,
|
|
45988
|
+
categories: rows.flatMap((row) => {
|
|
45989
|
+
const entry = row;
|
|
45990
|
+
return typeof entry?.name === "string" && typeof entry.tokens === "number" ? [{ name: entry.name, tokens: entry.tokens, deferred: entry.isDeferred === true }] : [];
|
|
45991
|
+
}),
|
|
45992
|
+
memoryFiles: memory.flatMap((row) => {
|
|
45993
|
+
const entry = row;
|
|
45994
|
+
return typeof entry?.path === "string" && typeof entry.tokens === "number" ? [{ path: entry.path, tokens: entry.tokens }] : [];
|
|
45995
|
+
}),
|
|
45996
|
+
mcpTools: mcp.flatMap((row) => {
|
|
45997
|
+
const entry = row;
|
|
45998
|
+
return typeof entry?.name === "string" && typeof entry.tokens === "number" ? [{ name: entry.name, server: typeof entry.serverName === "string" ? entry.serverName : "", tokens: entry.tokens }] : [];
|
|
45999
|
+
})
|
|
46000
|
+
};
|
|
46001
|
+
}
|
|
45687
46002
|
function runVendorQuery(input) {
|
|
45688
46003
|
const run = query({
|
|
45689
46004
|
prompt: input.prompt,
|
|
@@ -45691,6 +46006,14 @@ function runVendorQuery(input) {
|
|
|
45691
46006
|
});
|
|
45692
46007
|
let closed = false;
|
|
45693
46008
|
return {
|
|
46009
|
+
async getContextUsage() {
|
|
46010
|
+
if (closed || typeof run.getContextUsage !== "function") return null;
|
|
46011
|
+
try {
|
|
46012
|
+
return readVendorContextUsage(await run.getContextUsage());
|
|
46013
|
+
} catch {
|
|
46014
|
+
return null;
|
|
46015
|
+
}
|
|
46016
|
+
},
|
|
45694
46017
|
[Symbol.asyncIterator]() {
|
|
45695
46018
|
const iterator = run[Symbol.asyncIterator]();
|
|
45696
46019
|
return {
|
|
@@ -45711,7 +46034,112 @@ function runVendorQuery(input) {
|
|
|
45711
46034
|
}
|
|
45712
46035
|
};
|
|
45713
46036
|
}
|
|
45714
|
-
|
|
46037
|
+
var VendorInputQueue = class {
|
|
46038
|
+
pending = [];
|
|
46039
|
+
waiting = null;
|
|
46040
|
+
closed = false;
|
|
46041
|
+
push(message) {
|
|
46042
|
+
if (this.closed) return;
|
|
46043
|
+
const waiting = this.waiting;
|
|
46044
|
+
if (waiting) {
|
|
46045
|
+
this.waiting = null;
|
|
46046
|
+
waiting({ done: false, value: message });
|
|
46047
|
+
return;
|
|
46048
|
+
}
|
|
46049
|
+
this.pending.push(message);
|
|
46050
|
+
}
|
|
46051
|
+
close() {
|
|
46052
|
+
if (this.closed) return;
|
|
46053
|
+
this.closed = true;
|
|
46054
|
+
const waiting = this.waiting;
|
|
46055
|
+
if (waiting) {
|
|
46056
|
+
this.waiting = null;
|
|
46057
|
+
waiting({ done: true, value: void 0 });
|
|
46058
|
+
}
|
|
46059
|
+
}
|
|
46060
|
+
[Symbol.asyncIterator]() {
|
|
46061
|
+
return {
|
|
46062
|
+
next: async () => {
|
|
46063
|
+
if (this.pending.length > 0) return { done: false, value: this.pending.shift() };
|
|
46064
|
+
if (this.closed) return { done: true, value: void 0 };
|
|
46065
|
+
return await new Promise((resolve3) => {
|
|
46066
|
+
this.waiting = resolve3;
|
|
46067
|
+
});
|
|
46068
|
+
}
|
|
46069
|
+
};
|
|
46070
|
+
}
|
|
46071
|
+
};
|
|
46072
|
+
function vendorUserMessage(text2) {
|
|
46073
|
+
return {
|
|
46074
|
+
type: "user",
|
|
46075
|
+
session_id: "",
|
|
46076
|
+
message: { role: "user", content: [{ type: "text", text: text2 }] },
|
|
46077
|
+
parent_tool_use_id: null
|
|
46078
|
+
};
|
|
46079
|
+
}
|
|
46080
|
+
function runVendorSession(input) {
|
|
46081
|
+
const queue = new VendorInputQueue();
|
|
46082
|
+
const run = query({
|
|
46083
|
+
prompt: queue,
|
|
46084
|
+
options: input.options
|
|
46085
|
+
});
|
|
46086
|
+
let closed = false;
|
|
46087
|
+
return {
|
|
46088
|
+
send(text2) {
|
|
46089
|
+
if (closed) return;
|
|
46090
|
+
queue.push(vendorUserMessage(text2));
|
|
46091
|
+
},
|
|
46092
|
+
async interrupt() {
|
|
46093
|
+
if (closed || typeof run.interrupt !== "function") return;
|
|
46094
|
+
await run.interrupt();
|
|
46095
|
+
},
|
|
46096
|
+
async stopTask(taskId) {
|
|
46097
|
+
if (closed) return;
|
|
46098
|
+
if (typeof run.stopTask !== "function") {
|
|
46099
|
+
throw new TypeError("This Claude Agent SDK build has no stopTask control request.");
|
|
46100
|
+
}
|
|
46101
|
+
await run.stopTask(taskId);
|
|
46102
|
+
},
|
|
46103
|
+
async backgroundTasks(toolUseId) {
|
|
46104
|
+
if (closed) return false;
|
|
46105
|
+
if (typeof run.backgroundTasks !== "function") {
|
|
46106
|
+
throw new TypeError("This Claude Agent SDK build has no background_tasks control request.");
|
|
46107
|
+
}
|
|
46108
|
+
return await run.backgroundTasks(toolUseId);
|
|
46109
|
+
},
|
|
46110
|
+
async getContextUsage() {
|
|
46111
|
+
if (closed || typeof run.getContextUsage !== "function") return null;
|
|
46112
|
+
try {
|
|
46113
|
+
return readVendorContextUsage(await run.getContextUsage());
|
|
46114
|
+
} catch {
|
|
46115
|
+
return null;
|
|
46116
|
+
}
|
|
46117
|
+
},
|
|
46118
|
+
[Symbol.asyncIterator]() {
|
|
46119
|
+
const iterator = run[Symbol.asyncIterator]();
|
|
46120
|
+
return {
|
|
46121
|
+
async next() {
|
|
46122
|
+
const result = await iterator.next();
|
|
46123
|
+
return result.done === true ? { done: true, value: void 0 } : { done: false, value: result.value };
|
|
46124
|
+
}
|
|
46125
|
+
};
|
|
46126
|
+
},
|
|
46127
|
+
close() {
|
|
46128
|
+
if (closed) return;
|
|
46129
|
+
closed = true;
|
|
46130
|
+
queue.close();
|
|
46131
|
+
try {
|
|
46132
|
+
if (typeof run.close === "function") run.close();
|
|
46133
|
+
else {
|
|
46134
|
+
const closing = run.return?.(void 0);
|
|
46135
|
+
if (closing !== void 0) void closing.catch(() => void 0);
|
|
46136
|
+
}
|
|
46137
|
+
} catch {
|
|
46138
|
+
}
|
|
46139
|
+
}
|
|
46140
|
+
};
|
|
46141
|
+
}
|
|
46142
|
+
function defineVendorTool(name, description, inputSchema, handler, extras) {
|
|
45715
46143
|
const definition = tool(
|
|
45716
46144
|
name,
|
|
45717
46145
|
description,
|
|
@@ -45745,79 +46173,135 @@ async function createClaudeGatewaySdk(options) {
|
|
|
45745
46173
|
const configDir = options.home?.kind === "shared" ? createSharedClaudeConfigHome(options.home.configDir) : await createIsolatedClaudeConfigDir(options.tempRoot);
|
|
45746
46174
|
let disposed = false;
|
|
45747
46175
|
let active = null;
|
|
46176
|
+
const reserveSlot = (kind) => {
|
|
46177
|
+
if (disposed) throw new Error("This Claude gateway SDK instance has been disposed.");
|
|
46178
|
+
if (active) {
|
|
46179
|
+
throw new Error(kind === "turn" ? "A turn is already running on this instance. Await it, or create another instance." : "A turn or session is already running on this instance. Close it, or create another instance.");
|
|
46180
|
+
}
|
|
46181
|
+
const reservation = { close: () => void 0 };
|
|
46182
|
+
active = reservation;
|
|
46183
|
+
return reservation;
|
|
46184
|
+
};
|
|
46185
|
+
const prepareLaunch = async () => {
|
|
46186
|
+
await configDir.writeModelCache({ baseUrl, models: catalogModels, fetchedAt: Date.now() });
|
|
46187
|
+
return claudeGatewayLaunchEnv(inherited, {
|
|
46188
|
+
baseUrl,
|
|
46189
|
+
configDir: configDir.path,
|
|
46190
|
+
homeKind: options.home?.kind === "shared" ? "shared" : "isolated"
|
|
46191
|
+
});
|
|
46192
|
+
};
|
|
46193
|
+
const vendorRunOptions = (request, model, env) => ({
|
|
46194
|
+
env,
|
|
46195
|
+
model,
|
|
46196
|
+
...request.systemPrompt === void 0 ? {} : { systemPrompt: vendorSystemPrompt(request.systemPrompt) },
|
|
46197
|
+
// 패키지가 스스로 지어내는 지시는 없다 — 여기 실리는 것은 전부 호출자가 고른 것이고,
|
|
46198
|
+
// 고르지 않으면 아무것도 붙지 않는다. 두 기본값이 그 규율을 구조로 만든다:
|
|
46199
|
+
// `settingSources: []`가 사용자·프로젝트 설정과 CLAUDE.md를 끄고, `strictMcpConfig`가
|
|
46200
|
+
// 그와 별개인 ambient .mcp.json·플러그인 MCP를 막는다.
|
|
46201
|
+
settingSources: options.settingSources ? [...options.settingSources] : [],
|
|
46202
|
+
strictMcpConfig: options.allowAmbientMcpServers !== true,
|
|
46203
|
+
// 플러그인의 MCP 선언은 읽지 않는다 — 좌표는 호출자가 이미 소유한다.
|
|
46204
|
+
...options.plugins && options.plugins.length > 0 ? { plugins: options.plugins.map((plugin) => ({ type: "local", path: plugin.path, skipMcpDiscovery: true })) } : {},
|
|
46205
|
+
// `--settings`와 같은 자리다. flag 소스로 병합되므로 사용자·프로젝트 설정을 대체하지 않는다.
|
|
46206
|
+
// skillOverrides와 ultracode만 연다 — settings 전체를 열면 호출자가 쓰지 않은 지시가 들어온다.
|
|
46207
|
+
...vendorFlagSettings(options),
|
|
46208
|
+
...request.effort === void 0 ? {} : { effort: request.effort },
|
|
46209
|
+
...request.cwd === void 0 ? {} : { cwd: request.cwd },
|
|
46210
|
+
...request.resume === void 0 ? {} : { resume: request.resume },
|
|
46211
|
+
...request.maxTurns === void 0 ? {} : { maxTurns: request.maxTurns },
|
|
46212
|
+
...request.maxBudgetUsd === void 0 ? {} : { maxBudgetUsd: request.maxBudgetUsd },
|
|
46213
|
+
...request.tools === void 0 ? {} : { tools: [...request.tools] },
|
|
46214
|
+
...request.allowedTools === void 0 ? {} : { allowedTools: [...request.allowedTools] },
|
|
46215
|
+
...request.disallowedTools === void 0 ? {} : { disallowedTools: [...request.disallowedTools] },
|
|
46216
|
+
...request.permissionMode === void 0 ? {} : { permissionMode: request.permissionMode },
|
|
46217
|
+
...request.canUseTool === void 0 ? {} : { canUseTool: vendorCanUseTool(request.canUseTool) },
|
|
46218
|
+
...request.mcpServers === void 0 && request.servedMcpServers === void 0 ? {} : { mcpServers: { ...request.mcpServers, ...vendorServedMcpServers(request.servedMcpServers) } },
|
|
46219
|
+
...request.includePartialMessages === void 0 ? {} : { includePartialMessages: request.includePartialMessages },
|
|
46220
|
+
...request.abortController === void 0 ? {} : { abortController: request.abortController },
|
|
46221
|
+
...request.stderr === void 0 ? {} : { stderr: request.stderr }
|
|
46222
|
+
});
|
|
45748
46223
|
const sdk = {
|
|
45749
46224
|
configDir: configDir.path,
|
|
45750
46225
|
models: Object.freeze(accepted.map((entry) => entry.id)),
|
|
45751
46226
|
async startTurn(turn) {
|
|
45752
|
-
|
|
45753
|
-
|
|
45754
|
-
|
|
45755
|
-
|
|
45756
|
-
|
|
45757
|
-
|
|
45758
|
-
|
|
45759
|
-
|
|
45760
|
-
|
|
45761
|
-
|
|
45762
|
-
|
|
45763
|
-
|
|
45764
|
-
|
|
45765
|
-
|
|
45766
|
-
|
|
45767
|
-
|
|
45768
|
-
|
|
45769
|
-
|
|
45770
|
-
|
|
45771
|
-
|
|
45772
|
-
|
|
45773
|
-
|
|
45774
|
-
|
|
45775
|
-
|
|
45776
|
-
|
|
45777
|
-
|
|
45778
|
-
|
|
45779
|
-
|
|
45780
|
-
|
|
45781
|
-
|
|
45782
|
-
|
|
45783
|
-
|
|
45784
|
-
|
|
45785
|
-
|
|
45786
|
-
|
|
45787
|
-
|
|
45788
|
-
|
|
45789
|
-
|
|
45790
|
-
...turn.canUseTool === void 0 ? {} : { canUseTool: vendorCanUseTool(turn.canUseTool) },
|
|
45791
|
-
...turn.mcpServers === void 0 && turn.servedMcpServers === void 0 ? {} : { mcpServers: { ...turn.mcpServers, ...vendorServedMcpServers(turn.servedMcpServers) } },
|
|
45792
|
-
...turn.includePartialMessages === void 0 ? {} : { includePartialMessages: turn.includePartialMessages },
|
|
45793
|
-
...turn.abortController === void 0 ? {} : { abortController: turn.abortController },
|
|
45794
|
-
...turn.stderr === void 0 ? {} : { stderr: turn.stderr }
|
|
46227
|
+
const reservation = reserveSlot("turn");
|
|
46228
|
+
try {
|
|
46229
|
+
assertKnownTurnKeys(turn);
|
|
46230
|
+
if (typeof turn.prompt !== "string" || turn.prompt.length === 0) {
|
|
46231
|
+
throw new TypeError("turn.prompt must be a non-empty string.");
|
|
46232
|
+
}
|
|
46233
|
+
const model = resolveTurnModel(turn.model, accepted);
|
|
46234
|
+
const env = await prepareLaunch();
|
|
46235
|
+
const run = runVendorQuery({
|
|
46236
|
+
prompt: turn.prompt,
|
|
46237
|
+
options: vendorRunOptions(turn, model, env)
|
|
46238
|
+
});
|
|
46239
|
+
const release = () => {
|
|
46240
|
+
if (active === tracked) active = null;
|
|
46241
|
+
};
|
|
46242
|
+
const tracked = {
|
|
46243
|
+
[Symbol.asyncIterator]() {
|
|
46244
|
+
const iterator = run[Symbol.asyncIterator]();
|
|
46245
|
+
return {
|
|
46246
|
+
async next() {
|
|
46247
|
+
const result = await iterator.next();
|
|
46248
|
+
if (result.done === true) release();
|
|
46249
|
+
return result;
|
|
46250
|
+
}
|
|
46251
|
+
};
|
|
46252
|
+
},
|
|
46253
|
+
close() {
|
|
46254
|
+
try {
|
|
46255
|
+
run.close();
|
|
46256
|
+
} finally {
|
|
46257
|
+
release();
|
|
46258
|
+
}
|
|
46259
|
+
},
|
|
46260
|
+
getContextUsage: () => run.getContextUsage()
|
|
46261
|
+
};
|
|
46262
|
+
if (active !== reservation) {
|
|
46263
|
+
run.close();
|
|
46264
|
+
throw new Error("This Claude gateway SDK instance has been disposed.");
|
|
45795
46265
|
}
|
|
45796
|
-
|
|
45797
|
-
|
|
45798
|
-
|
|
45799
|
-
|
|
45800
|
-
|
|
45801
|
-
|
|
45802
|
-
|
|
45803
|
-
|
|
45804
|
-
|
|
45805
|
-
|
|
45806
|
-
|
|
45807
|
-
|
|
46266
|
+
active = tracked;
|
|
46267
|
+
return tracked;
|
|
46268
|
+
} catch (error51) {
|
|
46269
|
+
if (active === reservation) active = null;
|
|
46270
|
+
throw error51;
|
|
46271
|
+
}
|
|
46272
|
+
},
|
|
46273
|
+
async openSession(request) {
|
|
46274
|
+
const reservation = reserveSlot("session");
|
|
46275
|
+
try {
|
|
46276
|
+
assertKnownSessionKeys(request);
|
|
46277
|
+
const model = resolveTurnModel(request.model, accepted);
|
|
46278
|
+
const env = await prepareLaunch();
|
|
46279
|
+
const session = runVendorSession({ options: vendorRunOptions(request, model, env) });
|
|
46280
|
+
const tracked = {
|
|
46281
|
+
send: (text2) => session.send(text2),
|
|
46282
|
+
interrupt: () => session.interrupt(),
|
|
46283
|
+
stopTask: (taskId) => session.stopTask(taskId),
|
|
46284
|
+
backgroundTasks: (toolUseId) => session.backgroundTasks(toolUseId),
|
|
46285
|
+
getContextUsage: () => session.getContextUsage(),
|
|
46286
|
+
[Symbol.asyncIterator]: () => session[Symbol.asyncIterator](),
|
|
46287
|
+
close() {
|
|
46288
|
+
try {
|
|
46289
|
+
session.close();
|
|
46290
|
+
} finally {
|
|
46291
|
+
if (active === tracked) active = null;
|
|
45808
46292
|
}
|
|
45809
|
-
};
|
|
45810
|
-
},
|
|
45811
|
-
close() {
|
|
45812
|
-
try {
|
|
45813
|
-
run.close();
|
|
45814
|
-
} finally {
|
|
45815
|
-
release();
|
|
45816
46293
|
}
|
|
46294
|
+
};
|
|
46295
|
+
if (active !== reservation) {
|
|
46296
|
+
session.close();
|
|
46297
|
+
throw new Error("This Claude gateway SDK instance has been disposed.");
|
|
45817
46298
|
}
|
|
45818
|
-
|
|
45819
|
-
|
|
45820
|
-
|
|
46299
|
+
active = tracked;
|
|
46300
|
+
return tracked;
|
|
46301
|
+
} catch (error51) {
|
|
46302
|
+
if (active === reservation) active = null;
|
|
46303
|
+
throw error51;
|
|
46304
|
+
}
|
|
45821
46305
|
},
|
|
45822
46306
|
async dispose() {
|
|
45823
46307
|
if (disposed) return;
|
|
@@ -45899,6 +46383,14 @@ function vendorCanUseTool(canUseTool) {
|
|
|
45899
46383
|
}
|
|
45900
46384
|
};
|
|
45901
46385
|
}
|
|
46386
|
+
function vendorFlagSettings(options) {
|
|
46387
|
+
const settings2 = {};
|
|
46388
|
+
if (options.skillOverrides && Object.keys(options.skillOverrides).length > 0) {
|
|
46389
|
+
settings2.skillOverrides = { ...options.skillOverrides };
|
|
46390
|
+
}
|
|
46391
|
+
if (options.ultracode === true) settings2.ultracode = true;
|
|
46392
|
+
return Object.keys(settings2).length > 0 ? { settings: settings2 } : {};
|
|
46393
|
+
}
|
|
45902
46394
|
function vendorSystemPrompt(systemPrompt) {
|
|
45903
46395
|
const text2 = systemPrompt?.text;
|
|
45904
46396
|
if (typeof text2 !== "string" || text2.length === 0) {
|
|
@@ -45916,6 +46408,14 @@ function assertKnownTurnKeys(turn) {
|
|
|
45916
46408
|
);
|
|
45917
46409
|
}
|
|
45918
46410
|
}
|
|
46411
|
+
function assertKnownSessionKeys(request) {
|
|
46412
|
+
const unknown2 = Object.keys(request).filter((key) => !CLAUDE_GATEWAY_SESSION_KEYS.includes(key));
|
|
46413
|
+
if (unknown2.length > 0) {
|
|
46414
|
+
throw new TypeError(
|
|
46415
|
+
`Unsupported session option(s): ${unknown2.join(", ")}. Only an instruction the caller authored may reach the child, through systemPrompt; every other instruction channel is closed, so those options do not exist. A session receives its prompts through send(), never as an option.`
|
|
46416
|
+
);
|
|
46417
|
+
}
|
|
46418
|
+
}
|
|
45919
46419
|
function vendorServedMcpServers(servers) {
|
|
45920
46420
|
if (!servers?.length) return {};
|
|
45921
46421
|
return Object.fromEntries(servers.map((server) => [server.name, {
|
|
@@ -46401,7 +46901,8 @@ var GatewayLaunchOptionError = class extends Error {
|
|
|
46401
46901
|
}
|
|
46402
46902
|
};
|
|
46403
46903
|
function isGatewayLaunchEffortAllowed(selection, model, effort) {
|
|
46404
|
-
if (
|
|
46904
|
+
if (effort === "ultra") return true;
|
|
46905
|
+
if (!GATEWAY_REASONING_EFFORTS.includes(effort)) return false;
|
|
46405
46906
|
const efforts = selection.effortExposure[model.id] ?? exposableEffortLadder(model);
|
|
46406
46907
|
return efforts.includes(effort);
|
|
46407
46908
|
}
|
|
@@ -47405,6 +47906,14 @@ function readAnalysisProviderSession(value) {
|
|
|
47405
47906
|
...typeof candidate.source === "string" ? { source: candidate.source } : {}
|
|
47406
47907
|
};
|
|
47407
47908
|
}
|
|
47909
|
+
|
|
47910
|
+
// ../fleet-plugins/terminal/server/agent-api/chat-launch-effort.ts
|
|
47911
|
+
var WIRE_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
47912
|
+
function resolveChatLaunchEffort(value) {
|
|
47913
|
+
if (value.length === 0) return void 0;
|
|
47914
|
+
if (value === "ultra") return { effort: "xhigh", ultracode: true };
|
|
47915
|
+
return WIRE_EFFORTS.includes(value) ? { effort: value } : void 0;
|
|
47916
|
+
}
|
|
47408
47917
|
var MAX_TOOL_DETAIL_CHARS = 160;
|
|
47409
47918
|
var MAX_TOOL_RESULT_CHARS = 120;
|
|
47410
47919
|
var MAX_TEXT_CHARS = 6e4;
|
|
@@ -47454,6 +47963,9 @@ function eventsFromTranscriptLine(line, options) {
|
|
|
47454
47963
|
return [];
|
|
47455
47964
|
}
|
|
47456
47965
|
function chatEventsFromSdkMessage(message, options = {}) {
|
|
47966
|
+
if (typeof message.parent_tool_use_id === "string" && message.parent_tool_use_id.length > 0) {
|
|
47967
|
+
return [];
|
|
47968
|
+
}
|
|
47457
47969
|
if (message.type === "stream_event") {
|
|
47458
47970
|
const inner = message.event;
|
|
47459
47971
|
if (!inner || typeof inner !== "object") return [];
|
|
@@ -47951,6 +48463,8 @@ function capText(text2) {
|
|
|
47951
48463
|
// ../fleet-plugins/terminal/server/agent-api/chat-session.ts
|
|
47952
48464
|
var JOURNAL_CAP = 2e3;
|
|
47953
48465
|
var TOOL_NAME_CAP = 500;
|
|
48466
|
+
var CONTEXT_RESERVED_NAME = "Autocompact buffer";
|
|
48467
|
+
var CONTEXT_UNSPENT = /* @__PURE__ */ new Set([CONTEXT_RESERVED_NAME, "Free space"]);
|
|
47954
48468
|
var JOB_KIND_CAP = 200;
|
|
47955
48469
|
var JOB_TAIL_READ_BYTES = 256 * 1024;
|
|
47956
48470
|
var JOB_TRANSCRIPT_READ_BYTES = 4 * 1024 * 1024;
|
|
@@ -48001,6 +48515,10 @@ var AgentChatSession = class {
|
|
|
48001
48515
|
latestSessionId;
|
|
48002
48516
|
/** 이미 Operation에 심은 세션 id. 같은 좌표를 매 턴 다시 심지 않기 위한 축이다. */
|
|
48003
48517
|
reportedSessionId = null;
|
|
48518
|
+
/** 날고 있는 좌표 심기. 리더가 메시지마다 이 자리를 지나므로 겹치지 않게 붙든다. */
|
|
48519
|
+
syncFlight = null;
|
|
48520
|
+
/** 그 비행 중에 들어온 요청이 있었다. 착지 후 좌표가 아직 남아 있으면 한 번 더 간다. */
|
|
48521
|
+
syncDirty = false;
|
|
48004
48522
|
journal = [];
|
|
48005
48523
|
seq = 0;
|
|
48006
48524
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -48008,11 +48526,52 @@ var AgentChatSession = class {
|
|
|
48008
48526
|
pendingTurns = 0;
|
|
48009
48527
|
disposed = false;
|
|
48010
48528
|
/**
|
|
48011
|
-
*
|
|
48012
|
-
*
|
|
48013
|
-
*
|
|
48529
|
+
* 이 세션이 붙들고 있는 자식. 턴마다 세우고 접는 것이 아니라 **Operation이 열려 있는 동안**
|
|
48530
|
+
* 살아 있으며, 그 수명이 곧 백그라운드 작업의 수명이다 — 턴 단위 실행은 vendor가 single-turn으로
|
|
48531
|
+
* 보고 자식의 입력을 닫아, Claude Code의 wind-down이 백그라운드 셸을 유예 뒤 kill한다.
|
|
48014
48532
|
*/
|
|
48015
|
-
|
|
48533
|
+
session = null;
|
|
48534
|
+
sessionFlight = null;
|
|
48535
|
+
/** 세션 스트림을 소진하는 리더. dispose가 착지를 기다리는 자리다. */
|
|
48536
|
+
readerDone = null;
|
|
48537
|
+
/**
|
|
48538
|
+
* 지금 화면에 열려 있는 턴이 있는가.
|
|
48539
|
+
*
|
|
48540
|
+
* 스트림이 턴마다 끝나지 않으므로 이 축이 필요하다. 여는 자리는 둘 — 사용자가 보낸 디스패치와,
|
|
48541
|
+
* 백그라운드 작업이 끝나 자식이 모델을 다시 깨운 뒤 흐르기 시작한 내용이다. 닫는 자리는 `result`
|
|
48542
|
+
* 하나이고, 중지도 여기를 닫는다.
|
|
48543
|
+
*/
|
|
48544
|
+
turnOpen = false;
|
|
48545
|
+
/** 열린 턴의 완주를 기다리는 디스패치. 턴이 닫히면 풀린다. */
|
|
48546
|
+
awaitingTurn = null;
|
|
48547
|
+
/**
|
|
48548
|
+
* 열린 턴이 닫히기를 기다리는 디스패치들.
|
|
48549
|
+
*
|
|
48550
|
+
* 자식이 백그라운드 완료로 스스로 깨어나 연 턴은 아무도 기다리지 않는다. 그 창에 사용자
|
|
48551
|
+
* 메시지가 들어오면 자기 턴을 세우지 못한 채 남의 결말에 실려 나가므로, 여기서 줄을 세운다.
|
|
48552
|
+
*/
|
|
48553
|
+
turnCloseWaiters = /* @__PURE__ */ new Set();
|
|
48554
|
+
/**
|
|
48555
|
+
* 중지한 턴이 아직 자기 `result`를 내지 않았다.
|
|
48556
|
+
*
|
|
48557
|
+
* 자식은 중단을 받아도 그 턴의 결말을 **반드시** 낸다(실측: `interrupt()` 뒤 2ms에
|
|
48558
|
+
* `error_during_execution`). 그것은 이미 닫은 턴의 것이므로 새 턴의 결말로 읽으면 안 되고,
|
|
48559
|
+
* 그 사이에 들어온 디스패치는 그 한 건이 지나갈 때까지 기다린다.
|
|
48560
|
+
*/
|
|
48561
|
+
settlingStoppedTurn = false;
|
|
48562
|
+
/**
|
|
48563
|
+
* 지금 열린 턴의 프롬프트가 자식에 실제로 닿았는가.
|
|
48564
|
+
*
|
|
48565
|
+
* 닿지 않은 턴에는 자식이 낼 결말도 없다 — 세션을 여는 동안(자식 spawn·플러그인·MCP 발급은
|
|
48566
|
+
* 몇 초가 걸린다) 사용자가 중지하면 그 턴은 자식이 존재조차 모른 채 닫힌다. 그때 결말을
|
|
48567
|
+
* 기다리기 시작하면 오지 않을 것을 기다리며 세션이 영구히 막힌다.
|
|
48568
|
+
*/
|
|
48569
|
+
turnReachedChild = false;
|
|
48570
|
+
/**
|
|
48571
|
+
* 지금 살아 있다고 알려진 잡. 세션이 끊기면 이 잡들은 자식과 함께 사라지므로, 원장에 "도는 중"
|
|
48572
|
+
* 으로 남겨 두지 않고 거둬진 것으로 닫는다 — 화면이 없는 작업을 기다리게 두지 않기 위해서다.
|
|
48573
|
+
*/
|
|
48574
|
+
liveJobs = /* @__PURE__ */ new Set();
|
|
48016
48575
|
/**
|
|
48017
48576
|
* 중지 세대. 중지는 도는 턴 하나가 아니라 **그 시점의 큐 전체**를 끊어야 한다 — 큐에 밀려
|
|
48018
48577
|
* 있던 턴이 중지 직후 태연히 시작하면, 사용자가 멈춘 것은 화면에서 멈추지 않는다. 각 턴은
|
|
@@ -48041,6 +48600,11 @@ var AgentChatSession = class {
|
|
|
48041
48600
|
* dispose(). 어느 경로로도 비워지지 않으면 SDK는 무기한 멈춘다(권한 요청에 park deadline이 없다).
|
|
48042
48601
|
*/
|
|
48043
48602
|
pendingAsks = /* @__PURE__ */ new Map();
|
|
48603
|
+
/**
|
|
48604
|
+
* 문맥 스냅숏의 세대. 턴마다 하나씩 오르며, 늦게 도착한 응답이 자기 턴의 것인지 가른다 —
|
|
48605
|
+
* 답은 턴이 끝난 뒤에 오므로(실측), 그 사이 새 턴이 시작했다면 그 값은 남의 턴 자리에 앉는다.
|
|
48606
|
+
*/
|
|
48607
|
+
contextGeneration = 0;
|
|
48044
48608
|
constructor(operationId, seed, createSdk) {
|
|
48045
48609
|
this.operationId = operationId;
|
|
48046
48610
|
this.seed = seed;
|
|
@@ -48109,31 +48673,49 @@ var AgentChatSession = class {
|
|
|
48109
48673
|
if (this.disposed) return;
|
|
48110
48674
|
const epoch = this.stopEpoch;
|
|
48111
48675
|
this.pendingTurns += 1;
|
|
48112
|
-
this.turnFlight = this.turnFlight.then(() => epoch === this.stopEpoch ? this.
|
|
48676
|
+
this.turnFlight = this.turnFlight.then(() => epoch === this.stopEpoch ? this.dispatch(text2) : void 0).catch(() => void 0).finally(() => {
|
|
48113
48677
|
this.pendingTurns -= 1;
|
|
48114
48678
|
});
|
|
48115
48679
|
}
|
|
48116
48680
|
/**
|
|
48117
48681
|
* 도는 턴을 사용자가 끊는다.
|
|
48118
48682
|
*
|
|
48119
|
-
* 이 자리가 여는 문은 **턴 하나**다.
|
|
48120
|
-
*
|
|
48121
|
-
* 멈추는 척하지 않는다 — 턴을 끊어도 이미 태어난 백그라운드 작업은 계속 살고, 원장의 잡
|
|
48122
|
-
* 표면이 그것을 그대로 말한다.
|
|
48683
|
+
* 이 자리가 여는 문은 **턴 하나**다. 자식은 죽지 않으며, 이미 태어난 백그라운드 작업도 계속
|
|
48684
|
+
* 산다 — 그것을 멈추는 문은 `stopJob`이 따로 연다. 턴만 끊는 것이 CLI의 Esc와 같은 자리다.
|
|
48123
48685
|
*
|
|
48124
48686
|
* 돌려주는 값은 "끊을 것이 있었는가"다. 없는데 true를 돌려주면 화면이 멈춤을 그리고 아무 일도
|
|
48125
48687
|
* 일어나지 않는다.
|
|
48126
48688
|
*/
|
|
48127
48689
|
stopTurn() {
|
|
48128
48690
|
if (this.disposed) return false;
|
|
48129
|
-
if (this.pendingTurns === 0) return false;
|
|
48691
|
+
if (this.pendingTurns === 0 && !this.turnOpen) return false;
|
|
48130
48692
|
this.stopEpoch += 1;
|
|
48131
|
-
const run = this.activeRun;
|
|
48132
|
-
this.activeRun = null;
|
|
48133
48693
|
this.abandonAsks("The turn was stopped before the question was answered.");
|
|
48134
|
-
|
|
48694
|
+
void this.session?.interrupt().catch(() => void 0);
|
|
48695
|
+
if (this.turnOpen && this.turnReachedChild) this.settlingStoppedTurn = true;
|
|
48696
|
+
this.closeTurn({ stopped: true });
|
|
48135
48697
|
return true;
|
|
48136
48698
|
}
|
|
48699
|
+
/**
|
|
48700
|
+
* 백그라운드 작업 하나를 사용자가 멈춘다.
|
|
48701
|
+
*
|
|
48702
|
+
* 좌표는 SDK가 발급한 `task_id`이며, 우리가 그 잡을 실제로 본 적이 있어야 한다(`jobKinds`가
|
|
48703
|
+
* 그 문이다) — 브라우저가 지어낸 id는 자식에 닿지 않는다. 결말은 자식이 내는 `stopped` 알림이
|
|
48704
|
+
* 말하므로, 여기서 원장을 미리 고쳐 쓰지 않는다.
|
|
48705
|
+
*/
|
|
48706
|
+
async stopJob(jobId) {
|
|
48707
|
+
if (this.disposed) return false;
|
|
48708
|
+
if (!/^[A-Za-z0-9_-]{1,128}$/.test(jobId)) return false;
|
|
48709
|
+
if (!this.jobKinds.has(jobId)) return false;
|
|
48710
|
+
const session = this.session;
|
|
48711
|
+
if (!session) return false;
|
|
48712
|
+
try {
|
|
48713
|
+
await session.stopTask(jobId);
|
|
48714
|
+
return true;
|
|
48715
|
+
} catch {
|
|
48716
|
+
return false;
|
|
48717
|
+
}
|
|
48718
|
+
}
|
|
48137
48719
|
/** 지금 답을 기다리는 도구 호출이 있는가. 라우트가 대기 유무를 묻는 자리. */
|
|
48138
48720
|
get awaiting() {
|
|
48139
48721
|
return this.pendingAsks.size > 0;
|
|
@@ -48212,10 +48794,16 @@ var AgentChatSession = class {
|
|
|
48212
48794
|
if (this.disposed) return;
|
|
48213
48795
|
this.disposed = true;
|
|
48214
48796
|
this.abandonAsks("The chat session closed before the question was answered.");
|
|
48797
|
+
const session = this.session;
|
|
48798
|
+
this.session = null;
|
|
48799
|
+
session?.close();
|
|
48215
48800
|
const sdk = this.sdk;
|
|
48216
48801
|
this.sdk = null;
|
|
48217
48802
|
if (sdk) await sdk.dispose().catch(() => void 0);
|
|
48803
|
+
if (this.readerDone) await this.readerDone.catch(() => void 0);
|
|
48804
|
+
this.releaseTurnCloseWaiters();
|
|
48218
48805
|
await this.turnFlight.catch(() => void 0);
|
|
48806
|
+
if (this.syncFlight) await this.syncFlight.catch(() => void 0);
|
|
48219
48807
|
if (this.fleetMcpFlight) await this.fleetMcpFlight.catch(() => void 0);
|
|
48220
48808
|
this.seed.releaseFleetMcpServers?.();
|
|
48221
48809
|
this.listeners.clear();
|
|
@@ -48352,6 +48940,58 @@ var AgentChatSession = class {
|
|
|
48352
48940
|
this.seed.reportAwaiting(true);
|
|
48353
48941
|
});
|
|
48354
48942
|
}
|
|
48943
|
+
/**
|
|
48944
|
+
* 턴이 시작하는 순간 자식에게 문맥 내역을 묻고, 답이 오면 그대로 저널에 싣는다.
|
|
48945
|
+
*
|
|
48946
|
+
* **이 한 번이 유일한 기회다**(실측). 자식은 턴이 시작되면 control 채널을 닫아, +0ms의 요청만
|
|
48947
|
+
* 답을 받고 그 뒤의 요청은 턴이 10초를 돌든 전부 "Query closed before response received"로
|
|
48948
|
+
* 끝난다. 주기적으로 물어 최신값을 좇는 설계는 이 자식에서 성립하지 않는다.
|
|
48949
|
+
*
|
|
48950
|
+
* 그래서 값은 **이 턴이 시작될 때까지의** 문맥이다 — 방금 끝난 턴이 더한 몫은 다음 턴이
|
|
48951
|
+
* 시작될 때 비로소 드러난다. 화면은 그 지연을 감추지 않는다.
|
|
48952
|
+
*
|
|
48953
|
+
* 응답을 기다리지 않는 이유는 스트림 때문이다: 여기서 await하면 첫 메시지 소비가 그만큼 늦다.
|
|
48954
|
+
* 늦게 도착한 답도 같은 턴의 시작 시점 값이므로, 그때 실어도 뜻이 달라지지 않는다.
|
|
48955
|
+
*/
|
|
48956
|
+
snapshotContextAtTurnStart(session) {
|
|
48957
|
+
const generation = ++this.contextGeneration;
|
|
48958
|
+
try {
|
|
48959
|
+
void session.getContextUsage().then((usage4) => {
|
|
48960
|
+
if (usage4 && generation === this.contextGeneration) this.pushContext(usage4);
|
|
48961
|
+
}, () => void 0);
|
|
48962
|
+
} catch {
|
|
48963
|
+
}
|
|
48964
|
+
}
|
|
48965
|
+
/**
|
|
48966
|
+
* 턴 시작 시점의 문맥을 저널에 심는다.
|
|
48967
|
+
*
|
|
48968
|
+
* 총량을 vendor의 `total`이 아니라 **카테고리 합으로 다시 세는** 이유는 실측이다: 게이트웨이
|
|
48969
|
+
* 세션에서 그 값(24,948)은 카테고리 합(129,670)과 크게 어긋났다 — 전자는 게이트웨이가 실제로
|
|
48970
|
+
* 읽은 토큰이고 후자는 CLI가 센 로컬 배분이다. 화면은 내역과 총량을 나란히 세우므로 둘이
|
|
48971
|
+
* 다른 셈을 쓰면 사용자가 보는 자리에서 모순이 드러난다. 내역이 곧 총량이어야 한다.
|
|
48972
|
+
*
|
|
48973
|
+
* 예약분(자동 압축 여유)과 남은 자리는 **쓴 것이 아니다**. 같은 목록에 두면 합이 언제나 창
|
|
48974
|
+
* 전체가 되어 미터가 항상 100%를 가리킨다.
|
|
48975
|
+
*/
|
|
48976
|
+
pushContext(usage4) {
|
|
48977
|
+
const spent = usage4.categories.filter((category) => !category.deferred && category.tokens > 0 && !CONTEXT_UNSPENT.has(category.name));
|
|
48978
|
+
const reserved = usage4.categories.find((category) => category.name === CONTEXT_RESERVED_NAME);
|
|
48979
|
+
this.push({
|
|
48980
|
+
kind: "context",
|
|
48981
|
+
total: spent.reduce((sum, category) => sum + category.tokens, 0),
|
|
48982
|
+
max: usage4.max,
|
|
48983
|
+
...reserved && reserved.tokens > 0 ? { reserved: reserved.tokens } : {},
|
|
48984
|
+
...usage4.compactAt === null ? {} : { compactAt: usage4.compactAt },
|
|
48985
|
+
slices: spent.map((category) => ({ name: category.name, tokens: category.tokens })),
|
|
48986
|
+
...usage4.memoryFiles.length > 0 ? { memoryFiles: usage4.memoryFiles.map((file2) => ({ name: file2.path, tokens: file2.tokens })) } : {},
|
|
48987
|
+
...usage4.mcpTools.length > 0 ? {
|
|
48988
|
+
mcpTools: usage4.mcpTools.map((tool) => ({
|
|
48989
|
+
name: tool.server ? `${tool.server} \xB7 ${tool.name}` : tool.name,
|
|
48990
|
+
tokens: tool.tokens
|
|
48991
|
+
}))
|
|
48992
|
+
} : {}
|
|
48993
|
+
});
|
|
48994
|
+
}
|
|
48355
48995
|
push(event) {
|
|
48356
48996
|
const entry = { seq: ++this.seq, event };
|
|
48357
48997
|
if (event.kind === "job-progress") {
|
|
@@ -48389,6 +49029,7 @@ var AgentChatSession = class {
|
|
|
48389
49029
|
settingSources: ["user", "project", "local"],
|
|
48390
49030
|
allowAmbientMcpServers: true,
|
|
48391
49031
|
...this.seed.skillOverrides ? { skillOverrides: this.seed.skillOverrides } : {},
|
|
49032
|
+
...this.seed.ultracode ? { ultracode: true } : {},
|
|
48392
49033
|
// 플러그인이 실은 훅은 세션 식별자로 자기 축을 찾는다. 이 자식에게는 그 식별자가
|
|
48393
49034
|
// 없어야 한다 — 상속된 값이 남으면 남의 세션 축에 보고한다.
|
|
48394
49035
|
env: chatChildEnv(process.env),
|
|
@@ -48425,87 +49066,229 @@ var AgentChatSession = class {
|
|
|
48425
49066
|
}
|
|
48426
49067
|
return this.fleetMcpFlight;
|
|
48427
49068
|
}
|
|
48428
|
-
|
|
49069
|
+
/**
|
|
49070
|
+
* 자식 하나를 열고, 그 스트림을 끝까지 소진하는 리더를 세운다. 세션당 한 번이다.
|
|
49071
|
+
*
|
|
49072
|
+
* 턴이 아니라 세션이 실행 정책을 소유한다 — 모델·강도·doctrine·도구 좌표·cwd는 자식이 사는
|
|
49073
|
+
* 동안 바뀌지 않고, 바뀌어야 한다면 그것은 이 세션을 접고 새로 여는 사건이다.
|
|
49074
|
+
*/
|
|
49075
|
+
async ensureSession() {
|
|
49076
|
+
if (this.session) return this.session;
|
|
49077
|
+
if (!this.sessionFlight) {
|
|
49078
|
+
this.sessionFlight = (async () => {
|
|
49079
|
+
const sdk = await this.ensureSdk();
|
|
49080
|
+
const fleetMcpServers = await this.ensureFleetMcpServers().catch(() => {
|
|
49081
|
+
this.push({ kind: "error", code: "chat_fleet_tools_unavailable" });
|
|
49082
|
+
return [];
|
|
49083
|
+
});
|
|
49084
|
+
const session = await sdk.openSession({
|
|
49085
|
+
model: this.seed.model,
|
|
49086
|
+
...this.seed.effort ? { effort: this.seed.effort } : {},
|
|
49087
|
+
...this.seed.systemPrompt ? { systemPrompt: this.seed.systemPrompt } : {},
|
|
49088
|
+
...fleetMcpServers.length > 0 ? { servedMcpServers: fleetMcpServers } : {},
|
|
49089
|
+
cwd: this.seed.cwd,
|
|
49090
|
+
// 이어붙일 좌표는 세션을 열 때 한 번 선다. 채팅으로 태어난 세션에는 그것이 없고,
|
|
49091
|
+
// SDK가 돌려주는 session_id가 그 자리를 채운다 — 자식이 사는 동안은 그 세션이 계속
|
|
49092
|
+
// 자라므로 매 턴 다시 이어붙일 일이 없다.
|
|
49093
|
+
...this.latestSessionId ? { resume: this.latestSessionId } : {},
|
|
49094
|
+
permissionMode: "bypassPermissions",
|
|
49095
|
+
// 이 콜백은 권한 게이트가 아니다. 모드는 그대로 bypass이고 평범한 도구는 여기서 그냥
|
|
49096
|
+
// 통과한다 — 콜백을 주는 이유는 그래야 자식이 대화형 도구를 갖기 때문이다(실측: 29→32).
|
|
49097
|
+
canUseTool: (name, input, context) => this.askUser(name, input, context),
|
|
49098
|
+
// 스트리밍 감각의 근거 — 글자 단위 text_delta를 받으려면 부분 메시지가 필요하다.
|
|
49099
|
+
includePartialMessages: true
|
|
49100
|
+
});
|
|
49101
|
+
if (this.disposed) {
|
|
49102
|
+
session.close();
|
|
49103
|
+
throw new Error("chat session disposed");
|
|
49104
|
+
}
|
|
49105
|
+
this.session = session;
|
|
49106
|
+
this.readerDone = this.readSession(session);
|
|
49107
|
+
return session;
|
|
49108
|
+
})().finally(() => {
|
|
49109
|
+
this.sessionFlight = null;
|
|
49110
|
+
});
|
|
49111
|
+
}
|
|
49112
|
+
return this.sessionFlight;
|
|
49113
|
+
}
|
|
49114
|
+
/**
|
|
49115
|
+
* 세션 스트림을 끝까지 읽는다. 이 루프가 사는 동안 자식은 "사용자가 아직 있다"고 보므로,
|
|
49116
|
+
* 백그라운드 작업이 턴을 넘어 살고 그 결말 알림도 받을 자리가 있다.
|
|
49117
|
+
*
|
|
49118
|
+
* 여기서 끝나는 것은 턴이 아니라 세션이다 — 자식이 죽거나 우리가 접었을 때만 빠져나온다.
|
|
49119
|
+
*/
|
|
49120
|
+
async readSession(session) {
|
|
49121
|
+
try {
|
|
49122
|
+
for await (const message of session) {
|
|
49123
|
+
if (typeof message.session_id === "string" && message.session_id.length > 0) {
|
|
49124
|
+
this.latestSessionId = message.session_id;
|
|
49125
|
+
if (this.latestSessionId !== this.reportedSessionId) this.syncProviderSessionOnce();
|
|
49126
|
+
}
|
|
49127
|
+
this.rememberJobOutput(message);
|
|
49128
|
+
for (const event of chatEventsFromSdkMessage(message, { cwd: this.seed.cwd, toolNames: this.toolNames })) {
|
|
49129
|
+
this.ingest(event);
|
|
49130
|
+
}
|
|
49131
|
+
}
|
|
49132
|
+
} catch {
|
|
49133
|
+
if (!this.disposed) this.push({ kind: "error", code: "chat_session_lost" });
|
|
49134
|
+
} finally {
|
|
49135
|
+
this.retireSession(session);
|
|
49136
|
+
}
|
|
49137
|
+
}
|
|
49138
|
+
/**
|
|
49139
|
+
* 리더가 만든 이벤트 하나를 원장에 반영한다. 턴 경계도 여기서 결정된다.
|
|
49140
|
+
*
|
|
49141
|
+
* 스트림이 턴마다 끝나지 않으므로 경계는 내용이 말한다: `result`가 열린 턴을 닫고, 닫힌 뒤에
|
|
49142
|
+
* 다시 흐르기 시작한 내용이 새 턴을 연다. 후자가 백그라운드 작업이 끝나 자식이 모델을 다시
|
|
49143
|
+
* 깨운 자리이며, 그것을 앞 턴에 이어 붙이면 사용자가 읽은 답이 갈아치워진다.
|
|
49144
|
+
*/
|
|
49145
|
+
ingest(event) {
|
|
49146
|
+
if (event.kind === "turn-end") {
|
|
49147
|
+
const settling = this.settlingStoppedTurn;
|
|
49148
|
+
this.settlingStoppedTurn = false;
|
|
49149
|
+
if (this.turnOpen) {
|
|
49150
|
+
this.closeTurn({ ok: event.ok, ...event.durationMs === void 0 ? {} : { durationMs: event.durationMs }, ...event.answer === void 0 ? {} : { answer: event.answer } });
|
|
49151
|
+
} else if (settling) {
|
|
49152
|
+
this.releaseTurnCloseWaiters();
|
|
49153
|
+
}
|
|
49154
|
+
return;
|
|
49155
|
+
}
|
|
49156
|
+
if (!this.turnOpen && opensChatTurn(event)) this.openTurn({ dispatched: false });
|
|
49157
|
+
this.rememberTool(event);
|
|
49158
|
+
this.trackJob(event);
|
|
49159
|
+
if ((event.kind === "tool" || event.kind === "tool-start") && AGENT_CHAT_ASK_TOOLS.has(event.name)) return;
|
|
49160
|
+
if (event.kind === "text-delta" || event.kind === "tool-start") this.pushEphemeral(event);
|
|
49161
|
+
else this.push(event);
|
|
49162
|
+
}
|
|
49163
|
+
/** 살아 있는 잡의 집합을 이벤트대로 따라간다. `jobs`는 세는 것이 아니라 통째로 갈아 끼운다. */
|
|
49164
|
+
trackJob(event) {
|
|
49165
|
+
if (event.kind === "job") this.liveJobs.add(event.id);
|
|
49166
|
+
else if (event.kind === "job-end") this.liveJobs.delete(event.id);
|
|
49167
|
+
else if (event.kind === "jobs") {
|
|
49168
|
+
this.liveJobs.clear();
|
|
49169
|
+
for (const id of event.ids) this.liveJobs.add(id);
|
|
49170
|
+
}
|
|
49171
|
+
}
|
|
49172
|
+
/**
|
|
49173
|
+
* 턴 하나를 연다. 화면의 스피너와 활동축이 같은 순간에 켜지는 자리다.
|
|
49174
|
+
*
|
|
49175
|
+
* 이미 열려 있으면 다시 열지 않는다. 자식은 자기 큐를 갖고 있어 도는 중에도 메시지를 받는데
|
|
49176
|
+
* (백그라운드가 끝나 모델이 다시 깨어난 턴이 그 상태다), 그때 두 번째 `turn-start`를 세우면
|
|
49177
|
+
* 원장에 닫히지 않는 턴이 겹쳐 남는다 — 결말은 하나뿐이기 때문이다.
|
|
49178
|
+
*/
|
|
49179
|
+
openTurn(options) {
|
|
49180
|
+
if (this.turnOpen) return;
|
|
49181
|
+
this.turnOpen = true;
|
|
49182
|
+
this.turnReachedChild = !options.dispatched;
|
|
49183
|
+
this.push({ kind: "turn-start", at: Date.now() });
|
|
49184
|
+
if (!options.dispatched) this.seed.reportActivity(true);
|
|
49185
|
+
}
|
|
49186
|
+
/**
|
|
49187
|
+
* 열린 턴을 닫는다. 부르는 자리는 셋 — 자식의 `result`, 사용자의 중지, 세션의 소멸.
|
|
49188
|
+
*
|
|
49189
|
+
* 대기 중인 디스패치를 여기서 푼다. 그것이 풀려야 큐에 있던 다음 메시지가 시작하고, 풀리지
|
|
49190
|
+
* 않으면 세션은 조용히 멈춘 채 사용자의 다음 문장을 영영 받지 않는다.
|
|
49191
|
+
*/
|
|
49192
|
+
closeTurn(end) {
|
|
49193
|
+
if (!this.turnOpen) return;
|
|
49194
|
+
this.turnOpen = false;
|
|
49195
|
+
this.turnReachedChild = false;
|
|
49196
|
+
this.push({
|
|
49197
|
+
kind: "turn-end",
|
|
49198
|
+
ok: end.ok ?? end.stopped !== true,
|
|
49199
|
+
...end.stopped === true ? { stopped: true } : {},
|
|
49200
|
+
...end.durationMs === void 0 ? {} : { durationMs: end.durationMs },
|
|
49201
|
+
...end.answer === void 0 ? {} : { answer: end.answer }
|
|
49202
|
+
});
|
|
49203
|
+
this.abandonAsks("The turn ended before the question was answered.");
|
|
49204
|
+
this.seed.reportActivity(false);
|
|
49205
|
+
const awaiting = this.awaitingTurn;
|
|
49206
|
+
this.awaitingTurn = null;
|
|
49207
|
+
awaiting?.();
|
|
49208
|
+
this.releaseTurnCloseWaiters();
|
|
49209
|
+
}
|
|
49210
|
+
/** 자리가 비었음을 줄 서 있던 디스패치들에게 알린다. 결말 하나가 전부를 깨운다. */
|
|
49211
|
+
releaseTurnCloseWaiters() {
|
|
49212
|
+
if (this.turnCloseWaiters.size === 0) return;
|
|
49213
|
+
const waiters = [...this.turnCloseWaiters];
|
|
49214
|
+
this.turnCloseWaiters.clear();
|
|
49215
|
+
for (const wake of waiters) wake();
|
|
49216
|
+
}
|
|
49217
|
+
/**
|
|
49218
|
+
* 열린 턴이 닫힐 때까지 기다린다.
|
|
49219
|
+
*
|
|
49220
|
+
* 억제가 아니라 대기여야 하는 이유: 열린 턴에 그냥 올라타면 그 턴의 `result`가 이 디스패치를
|
|
49221
|
+
* 풀어 버린다. 사용자의 프롬프트는 아직 자식 안에서 도는데 원장은 끝났다고 말하고, 큐의 다음
|
|
49222
|
+
* 메시지가 그 위에서 조기에 시작한다.
|
|
49223
|
+
*/
|
|
49224
|
+
async awaitTurnClose() {
|
|
49225
|
+
if (!this.turnOpen && !this.settlingStoppedTurn) return;
|
|
49226
|
+
await new Promise((resolve3) => {
|
|
49227
|
+
this.turnCloseWaiters.add(resolve3);
|
|
49228
|
+
});
|
|
49229
|
+
}
|
|
49230
|
+
/**
|
|
49231
|
+
* 자식이 사라졌다. 열린 턴과 살아 있던 잡을 정직하게 닫고, 다음 디스패치가 새 자식을 세우도록
|
|
49232
|
+
* 자리를 비운다.
|
|
49233
|
+
*
|
|
49234
|
+
* 잡을 `stopped`로 닫는 이유: 그 작업들은 자식과 함께 사라졌다. 원장에 "도는 중"으로 남겨 두면
|
|
49235
|
+
* 화면은 오지 않을 결말을 기다리고, 그 조용한 거짓말이 이 원장이 고치려던 바로 그것이다.
|
|
49236
|
+
*/
|
|
49237
|
+
retireSession(session) {
|
|
49238
|
+
if (this.session === session) this.session = null;
|
|
49239
|
+
this.readerDone = null;
|
|
49240
|
+
try {
|
|
49241
|
+
session.close();
|
|
49242
|
+
} catch {
|
|
49243
|
+
}
|
|
49244
|
+
for (const id of [...this.liveJobs]) this.push({ kind: "job-end", id, status: "stopped" });
|
|
49245
|
+
this.liveJobs.clear();
|
|
49246
|
+
this.settlingStoppedTurn = false;
|
|
49247
|
+
this.closeTurn({ ok: false });
|
|
49248
|
+
this.releaseTurnCloseWaiters();
|
|
49249
|
+
}
|
|
49250
|
+
/**
|
|
49251
|
+
* 사용자의 메시지 하나를 자식에게 보내고 그 턴이 닫힐 때까지 기다린다.
|
|
49252
|
+
*
|
|
49253
|
+
* 기다리는 이유는 자식의 사정이 아니라 화면의 사정이다 — 자식은 자기 큐를 갖고 있어 턴 중에
|
|
49254
|
+
* 받아도 잃지 않지만, 원장은 턴 하나씩 그리므로 앞 턴이 닫힌 뒤 다음 디스패치를 세운다.
|
|
49255
|
+
*/
|
|
49256
|
+
async dispatch(text2) {
|
|
48429
49257
|
if (this.disposed) return;
|
|
48430
49258
|
const epoch = this.stopEpoch;
|
|
48431
49259
|
const stopped = () => epoch !== this.stopEpoch;
|
|
49260
|
+
await this.awaitTurnClose();
|
|
49261
|
+
if (this.disposed || stopped()) return;
|
|
48432
49262
|
this.push({ kind: "dispatch", text: text2, at: Date.now() });
|
|
48433
|
-
this.push({ kind: "turn-start", at: Date.now() });
|
|
48434
49263
|
if (!this.seed.reportActivity(true)) {
|
|
48435
49264
|
this.push({ kind: "error", code: "chat_activity_unavailable" });
|
|
48436
49265
|
this.push({ kind: "turn-end", ok: false });
|
|
48437
49266
|
return;
|
|
48438
49267
|
}
|
|
48439
|
-
|
|
49268
|
+
this.openTurn({ dispatched: true });
|
|
48440
49269
|
try {
|
|
48441
|
-
const
|
|
48442
|
-
const fleetMcpServers = await this.ensureFleetMcpServers().catch(() => {
|
|
48443
|
-
this.push({ kind: "error", code: "chat_fleet_tools_unavailable" });
|
|
48444
|
-
return [];
|
|
48445
|
-
});
|
|
48446
|
-
const run = await sdk.startTurn({
|
|
48447
|
-
prompt: text2,
|
|
48448
|
-
model: this.seed.model,
|
|
48449
|
-
...this.seed.effort ? { effort: this.seed.effort } : {},
|
|
48450
|
-
...this.seed.systemPrompt ? { systemPrompt: this.seed.systemPrompt } : {},
|
|
48451
|
-
...fleetMcpServers.length > 0 ? { servedMcpServers: fleetMcpServers } : {},
|
|
48452
|
-
cwd: this.seed.cwd,
|
|
48453
|
-
// 채팅으로 태어난 세션의 첫 턴에는 이어붙일 좌표가 없다 — resume 없이 시작하고,
|
|
48454
|
-
// SDK가 돌려주는 session_id가 그 자리를 채운다(그다음 턴부터는 resume이 선다).
|
|
48455
|
-
...this.latestSessionId ? { resume: this.latestSessionId } : {},
|
|
48456
|
-
permissionMode: "bypassPermissions",
|
|
48457
|
-
// 이 콜백은 권한 게이트가 아니다. 모드는 그대로 bypass이고 평범한 도구는 여기서 그냥
|
|
48458
|
-
// 통과한다 — 콜백을 주는 이유는 그래야 자식이 대화형 도구를 갖기 때문이다(실측: 29→32).
|
|
48459
|
-
canUseTool: (name, input, context) => this.askUser(name, input, context),
|
|
48460
|
-
// 스트리밍 감각의 근거 — 글자 단위 text_delta를 받으려면 부분 메시지가 필요하다.
|
|
48461
|
-
includePartialMessages: true
|
|
48462
|
-
});
|
|
49270
|
+
const session = await this.ensureSession();
|
|
48463
49271
|
if (stopped()) {
|
|
48464
|
-
|
|
48465
|
-
this.push({ kind: "turn-end", ok: false, stopped: true });
|
|
49272
|
+
this.closeTurn({ stopped: true });
|
|
48466
49273
|
return;
|
|
48467
49274
|
}
|
|
48468
|
-
this.
|
|
48469
|
-
|
|
48470
|
-
|
|
48471
|
-
if (typeof message.session_id === "string" && message.session_id.length > 0) {
|
|
48472
|
-
this.latestSessionId = message.session_id;
|
|
48473
|
-
}
|
|
48474
|
-
this.rememberJobOutput(message);
|
|
48475
|
-
for (const event of chatEventsFromSdkMessage(message, { cwd: this.seed.cwd, toolNames: this.toolNames })) {
|
|
48476
|
-
if (event.kind === "turn-end") {
|
|
48477
|
-
turnClosed = true;
|
|
48478
|
-
} else if (turnClosed && opensChatTurn(event)) {
|
|
48479
|
-
this.push({ kind: "turn-start", at: Date.now() });
|
|
48480
|
-
turnClosed = false;
|
|
48481
|
-
}
|
|
48482
|
-
this.rememberTool(event);
|
|
48483
|
-
if ((event.kind === "tool" || event.kind === "tool-start") && AGENT_CHAT_ASK_TOOLS.has(event.name)) continue;
|
|
48484
|
-
if (event.kind === "text-delta" || event.kind === "tool-start") this.pushEphemeral(event);
|
|
48485
|
-
else this.push(event);
|
|
48486
|
-
}
|
|
48487
|
-
}
|
|
48488
|
-
} finally {
|
|
48489
|
-
this.activeRun = null;
|
|
48490
|
-
run.close();
|
|
48491
|
-
}
|
|
48492
|
-
if (!turnClosed) {
|
|
48493
|
-
if (stopped()) this.push({ kind: "turn-end", ok: false, stopped: true });
|
|
48494
|
-
else this.push({ kind: "turn-end", ok: true });
|
|
49275
|
+
if (this.session !== session) {
|
|
49276
|
+
this.closeTurn({ ok: false });
|
|
49277
|
+
return;
|
|
48495
49278
|
}
|
|
48496
|
-
|
|
49279
|
+
const settled = new Promise((resolve3) => {
|
|
49280
|
+
this.awaitingTurn = resolve3;
|
|
49281
|
+
});
|
|
49282
|
+
this.snapshotContextAtTurnStart(session);
|
|
49283
|
+
session.send(text2);
|
|
49284
|
+
this.turnReachedChild = true;
|
|
49285
|
+
await settled;
|
|
48497
49286
|
} catch {
|
|
48498
|
-
this.
|
|
48499
|
-
|
|
48500
|
-
if (!turnClosed) this.push({ kind: "turn-end", ok: false, stopped: true });
|
|
48501
|
-
await this.syncProviderSession().catch(() => void 0);
|
|
48502
|
-
} else {
|
|
49287
|
+
if (stopped()) this.closeTurn({ stopped: true });
|
|
49288
|
+
else {
|
|
48503
49289
|
this.push({ kind: "error", code: "chat_turn_failed" });
|
|
48504
|
-
|
|
49290
|
+
this.closeTurn({ ok: false });
|
|
48505
49291
|
}
|
|
48506
|
-
} finally {
|
|
48507
|
-
this.abandonAsks("The turn ended before the question was answered.");
|
|
48508
|
-
this.seed.reportActivity(false);
|
|
48509
49292
|
}
|
|
48510
49293
|
}
|
|
48511
49294
|
/**
|
|
@@ -48515,6 +49298,25 @@ var AgentChatSession = class {
|
|
|
48515
49298
|
* 좌표를 확정하는 것뿐이며, 세션 id가 바뀌지 않는 한 다시 할 일도 없다(resume이 새 id를 낳는
|
|
48516
49299
|
* 경우에만 다시 확정한다).
|
|
48517
49300
|
*/
|
|
49301
|
+
/**
|
|
49302
|
+
* 좌표 심기를 한 번에 하나만 날린다.
|
|
49303
|
+
*
|
|
49304
|
+
* 리더는 메시지마다 이 자리를 지난다. 첫 시도가 파일을 못 찾아 실패하는 것은 정상이므로
|
|
49305
|
+
* (자식이 아직 트랜스크립트를 만들지 않았다) 다음 메시지가 다시 시도해야 하는데, 가드가 없으면
|
|
49306
|
+
* 그 사이 도착한 메시지들이 같은 좌표를 겹쳐 심어 Operation write-back이 여러 번 인다.
|
|
49307
|
+
*/
|
|
49308
|
+
syncProviderSessionOnce() {
|
|
49309
|
+
if (this.syncFlight) {
|
|
49310
|
+
this.syncDirty = true;
|
|
49311
|
+
return;
|
|
49312
|
+
}
|
|
49313
|
+
this.syncDirty = false;
|
|
49314
|
+
this.syncFlight = this.syncProviderSession().catch(() => void 0).finally(() => {
|
|
49315
|
+
this.syncFlight = null;
|
|
49316
|
+
if (this.disposed || !this.syncDirty) return;
|
|
49317
|
+
if (this.latestSessionId !== this.reportedSessionId) this.syncProviderSessionOnce();
|
|
49318
|
+
});
|
|
49319
|
+
}
|
|
48518
49320
|
async syncProviderSession() {
|
|
48519
49321
|
const sessionId = this.latestSessionId;
|
|
48520
49322
|
if (!sessionId || sessionId === this.reportedSessionId) return;
|
|
@@ -48617,6 +49419,105 @@ var AgentChatRegistry = class {
|
|
|
48617
49419
|
}
|
|
48618
49420
|
};
|
|
48619
49421
|
|
|
49422
|
+
// ../fleet-plugins/terminal/server/agent-api/chat-ws.ts
|
|
49423
|
+
var MAX_CHAT_ANSWER_MESSAGE_CHARS = 2e3;
|
|
49424
|
+
var CHAT_UNAVAILABLE_CLOSE_CODE = 1013;
|
|
49425
|
+
function attachAgentChatSocket(socket, start) {
|
|
49426
|
+
let closed = false;
|
|
49427
|
+
let unsubscribe = null;
|
|
49428
|
+
let session = null;
|
|
49429
|
+
socket.once("close", () => {
|
|
49430
|
+
closed = true;
|
|
49431
|
+
unsubscribe?.();
|
|
49432
|
+
unsubscribe = null;
|
|
49433
|
+
session = null;
|
|
49434
|
+
});
|
|
49435
|
+
socket.on("message", (data, isBinary) => {
|
|
49436
|
+
if (closed || isBinary || !session) return;
|
|
49437
|
+
const command = readChatSocketCommand(decodeSocketText(data));
|
|
49438
|
+
if (!command) {
|
|
49439
|
+
sendJson(socket, { type: "nack", error: "invalid_command", ...commandId(data) ? { id: commandId(data) } : {} });
|
|
49440
|
+
return;
|
|
49441
|
+
}
|
|
49442
|
+
if (command.type === "stop") {
|
|
49443
|
+
if (!session.stopTurn()) {
|
|
49444
|
+
sendJson(socket, { type: "nack", id: command.id, error: "chat_idle" });
|
|
49445
|
+
return;
|
|
49446
|
+
}
|
|
49447
|
+
sendJson(socket, { type: "ok", id: command.id });
|
|
49448
|
+
return;
|
|
49449
|
+
}
|
|
49450
|
+
const result = session.answer(command.askId, {
|
|
49451
|
+
...command.answers ? { answers: command.answers } : {},
|
|
49452
|
+
...command.approve === true ? { approve: true } : {},
|
|
49453
|
+
...command.message !== void 0 ? { message: command.message.slice(0, MAX_CHAT_ANSWER_MESSAGE_CHARS) } : {}
|
|
49454
|
+
});
|
|
49455
|
+
if (!result.ok) {
|
|
49456
|
+
sendJson(socket, { type: "nack", id: command.id, error: result.error });
|
|
49457
|
+
return;
|
|
49458
|
+
}
|
|
49459
|
+
sendJson(socket, { type: "ok", id: command.id });
|
|
49460
|
+
});
|
|
49461
|
+
void start().then((ready) => {
|
|
49462
|
+
if (closed) return;
|
|
49463
|
+
if ("error" in ready) {
|
|
49464
|
+
sendJson(socket, { seq: 0, event: { kind: "error", code: ready.error } });
|
|
49465
|
+
socket.close(CHAT_UNAVAILABLE_CLOSE_CODE, ready.error);
|
|
49466
|
+
return;
|
|
49467
|
+
}
|
|
49468
|
+
session = ready;
|
|
49469
|
+
unsubscribe = ready.subscribe((entry) => {
|
|
49470
|
+
if (!closed) sendJson(socket, entry);
|
|
49471
|
+
});
|
|
49472
|
+
}).catch(() => {
|
|
49473
|
+
if (closed) return;
|
|
49474
|
+
sendJson(socket, { seq: 0, event: { kind: "error", code: "chat_unavailable" } });
|
|
49475
|
+
socket.close(CHAT_UNAVAILABLE_CLOSE_CODE, "chat_unavailable");
|
|
49476
|
+
});
|
|
49477
|
+
}
|
|
49478
|
+
function sendJson(socket, value) {
|
|
49479
|
+
if (socket.readyState !== 1) return;
|
|
49480
|
+
socket.send(Buffer.from(JSON.stringify(value), "utf8"), { binary: false });
|
|
49481
|
+
}
|
|
49482
|
+
function decodeSocketText(data) {
|
|
49483
|
+
if (Buffer.isBuffer(data)) return data.toString("utf8");
|
|
49484
|
+
if (Array.isArray(data)) return Buffer.concat(data).toString("utf8");
|
|
49485
|
+
return Buffer.from(data).toString("utf8");
|
|
49486
|
+
}
|
|
49487
|
+
function commandId(data) {
|
|
49488
|
+
try {
|
|
49489
|
+
const parsed = JSON.parse(decodeSocketText(data));
|
|
49490
|
+
if (parsed && typeof parsed === "object" && typeof parsed.id === "string") {
|
|
49491
|
+
return parsed.id;
|
|
49492
|
+
}
|
|
49493
|
+
} catch {
|
|
49494
|
+
}
|
|
49495
|
+
return void 0;
|
|
49496
|
+
}
|
|
49497
|
+
function readChatSocketCommand(raw) {
|
|
49498
|
+
let parsed;
|
|
49499
|
+
try {
|
|
49500
|
+
parsed = JSON.parse(raw);
|
|
49501
|
+
} catch {
|
|
49502
|
+
return null;
|
|
49503
|
+
}
|
|
49504
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
49505
|
+
const value = parsed;
|
|
49506
|
+
if (typeof value.id !== "string" || value.id.length === 0) return null;
|
|
49507
|
+
if (value.type === "stop") return { type: "stop", id: value.id };
|
|
49508
|
+
if (value.type !== "answer" || typeof value.askId !== "string" || value.askId.length === 0) return null;
|
|
49509
|
+
const answers = Array.isArray(value.answers) ? value.answers.filter((entry) => typeof entry === "string") : void 0;
|
|
49510
|
+
if (Array.isArray(value.answers) && answers?.length !== value.answers.length) return null;
|
|
49511
|
+
return {
|
|
49512
|
+
type: "answer",
|
|
49513
|
+
id: value.id,
|
|
49514
|
+
askId: value.askId,
|
|
49515
|
+
...answers ? { answers } : {},
|
|
49516
|
+
...value.approve === true ? { approve: true } : {},
|
|
49517
|
+
...typeof value.message === "string" ? { message: value.message } : {}
|
|
49518
|
+
};
|
|
49519
|
+
}
|
|
49520
|
+
|
|
48620
49521
|
// ../fleet-plugins/terminal/server/agent-api/analysis-types.ts
|
|
48621
49522
|
var ANALYSIS_ERROR_CODES = {
|
|
48622
49523
|
captureMissing: "analysis_capture_missing",
|
|
@@ -48909,7 +49810,7 @@ var TERMINAL_PLUGIN_ID = "terminal";
|
|
|
48909
49810
|
var CHAT_MODE_PAYLOAD_KEY = "chatMode";
|
|
48910
49811
|
var CHAT_BORN_PAYLOAD_KEY = "chatBorn";
|
|
48911
49812
|
var CHAT_SUPPORTED_CLI_ID = "claude-gateway";
|
|
48912
|
-
var
|
|
49813
|
+
var MAX_CHAT_ANSWER_MESSAGE_CHARS2 = 2e3;
|
|
48913
49814
|
function resolveClaudeConfigDir() {
|
|
48914
49815
|
const configured = process4.env.CLAUDE_CONFIG_DIR;
|
|
48915
49816
|
return configured && configured.length > 0 ? configured : path19__default.join(os3__default.homedir(), ".claude");
|
|
@@ -48934,7 +49835,7 @@ async function registerAgentRoutes(ctx, terminalRuntime, deps) {
|
|
|
48934
49835
|
{ method: "POST", path: "/sessions/:sessionId/message", summary: "Deliver a prompt to an Agent session.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
48935
49836
|
{ method: "POST", path: "/sessions/:sessionId/chat", summary: "Switch an Agent session to chat mode.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
48936
49837
|
{ method: "DELETE", path: "/sessions/:sessionId/chat", summary: "Leave chat mode for an Agent session.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
48937
|
-
{ method: "GET", path: "/sessions/:sessionId/chat-stream", summary: "
|
|
49838
|
+
{ method: "GET", path: "/sessions/:sessionId/chat-stream", summary: "Removed \u2014 Chat Mode observation uses the ticketed WebSocket.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
48938
49839
|
{ method: "POST", path: "/sessions/:sessionId/chat-answer", summary: "Answer a pending Agent chat question.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
48939
49840
|
{ method: "POST", path: "/sessions/:sessionId/chat-stop", summary: "Stop the in-flight Agent chat turn.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
48940
49841
|
{ method: "GET", path: "/sessions/:sessionId/chat-job", summary: "Read one Agent chat background job's detail.", category: "Terminal Plugin", gate: "origin-write", transport: "http" },
|
|
@@ -49001,6 +49902,27 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49001
49902
|
const oscActivityTrackers = /* @__PURE__ */ new Map();
|
|
49002
49903
|
const testChatSdkFactory = globalThis.__fleetAgentChatSdkFactory;
|
|
49003
49904
|
const chatRegistry = testChatSdkFactory ? new AgentChatRegistry(testChatSdkFactory) : new AgentChatRegistry();
|
|
49905
|
+
const unbindChatAttach = terminalRuntime.bindChatAttach((socket, context) => {
|
|
49906
|
+
const sessionId = context.sessionId;
|
|
49907
|
+
attachAgentChatSocket(socket, async () => {
|
|
49908
|
+
const node = ctx.host.operations.get(sessionId);
|
|
49909
|
+
if (!node || node.pluginId !== ctx.pluginId || node.type !== AGENT_OPERATION_TYPE) {
|
|
49910
|
+
return { error: "session_not_found" };
|
|
49911
|
+
}
|
|
49912
|
+
if (node.payload[CHAT_MODE_PAYLOAD_KEY] !== true) return { error: "chat_not_active" };
|
|
49913
|
+
const seed = await resolveChatSeed(node);
|
|
49914
|
+
if (!seed.ok) return { error: seed.error };
|
|
49915
|
+
if (ctx.host.operations.get(sessionId)?.payload[CHAT_MODE_PAYLOAD_KEY] !== true) {
|
|
49916
|
+
return { error: "chat_not_active" };
|
|
49917
|
+
}
|
|
49918
|
+
try {
|
|
49919
|
+
return await chatRegistry.ensure(sessionId, () => seed.seed);
|
|
49920
|
+
} catch {
|
|
49921
|
+
return { error: "chat_unavailable" };
|
|
49922
|
+
}
|
|
49923
|
+
});
|
|
49924
|
+
});
|
|
49925
|
+
ctx.host.lifecycle.registerCleanup(unbindChatAttach);
|
|
49004
49926
|
const launchResolver = createAgentTerminalLaunchResolver({
|
|
49005
49927
|
agentRuntime: runtime,
|
|
49006
49928
|
...deps.aiGateway ? { aiGateway: deps.aiGateway } : {},
|
|
@@ -49136,6 +50058,23 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49136
50058
|
ctx.host.http.writeJson(res, 404, { error: "terminal_session_not_found" });
|
|
49137
50059
|
return true;
|
|
49138
50060
|
}
|
|
50061
|
+
const channel = readTicketChannel(body?.channel);
|
|
50062
|
+
if (channel === "chat") {
|
|
50063
|
+
if (operation.payload[CHAT_MODE_PAYLOAD_KEY] !== true) {
|
|
50064
|
+
ctx.host.http.writeJson(res, 409, { error: "chat_not_active" });
|
|
50065
|
+
return true;
|
|
50066
|
+
}
|
|
50067
|
+
ctx.host.http.writeJson(res, 200, terminalRuntime.issueTicket({
|
|
50068
|
+
cwd: readPayloadString(operation.payload, "cwd") ?? ctx.host.paths.resolveTheaterPath(operation.theaterId) ?? "",
|
|
50069
|
+
sessionId: operation.id,
|
|
50070
|
+
operationId: operation.id,
|
|
50071
|
+
operationType: operation.type,
|
|
50072
|
+
pluginId: operation.pluginId,
|
|
50073
|
+
theaterId: operation.theaterId,
|
|
50074
|
+
channel: "chat"
|
|
50075
|
+
}));
|
|
50076
|
+
return true;
|
|
50077
|
+
}
|
|
49139
50078
|
if (observability.getTerminalSessionInfo(operation.id)?.status === "dormant") {
|
|
49140
50079
|
ctx.host.http.writeJson(res, 409, { error: "operation_dormant" });
|
|
49141
50080
|
return true;
|
|
@@ -49319,6 +50258,7 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49319
50258
|
if (action === "chat-answer") return handleChatAnswer(req, res, sessionId);
|
|
49320
50259
|
if (action === "chat-stop") return handleChatStop(req, res, sessionId);
|
|
49321
50260
|
if (action === "chat-job") return handleChatJob(req, res, sessionId);
|
|
50261
|
+
if (action === "chat-job-stop") return handleChatJobStop(req, res, sessionId);
|
|
49322
50262
|
if (!ctx.host.security.isTerminalAuthorized(req)) {
|
|
49323
50263
|
ctx.host.http.writeJson(res, 401, { error: "unauthorized" });
|
|
49324
50264
|
return true;
|
|
@@ -49750,7 +50690,7 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49750
50690
|
const result = chat.answer(askId, {
|
|
49751
50691
|
...answers ? { answers } : {},
|
|
49752
50692
|
...body?.approve === true ? { approve: true } : {},
|
|
49753
|
-
...typeof body?.message === "string" ? { message: body.message.slice(0,
|
|
50693
|
+
...typeof body?.message === "string" ? { message: body.message.slice(0, MAX_CHAT_ANSWER_MESSAGE_CHARS2) } : {}
|
|
49754
50694
|
});
|
|
49755
50695
|
if (!result.ok) {
|
|
49756
50696
|
const status = result.error === "ask_not_found" ? 404 : result.error === "plan_truncated" ? 409 : 400;
|
|
@@ -49780,6 +50720,32 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49780
50720
|
ctx.host.http.writeJson(res, 200, { ok: true });
|
|
49781
50721
|
return true;
|
|
49782
50722
|
}
|
|
50723
|
+
async function handleChatJobStop(req, res, sessionId) {
|
|
50724
|
+
if (req.method !== "POST") return methodNotAllowed2(res);
|
|
50725
|
+
if (!ctx.host.security.validateHost(req) || !ctx.host.security.isTerminalAuthorized(req)) return unauthorized(res);
|
|
50726
|
+
const node = ctx.host.operations.get(sessionId);
|
|
50727
|
+
if (!node || node.pluginId !== ctx.pluginId || node.type !== AGENT_OPERATION_TYPE) {
|
|
50728
|
+
ctx.host.http.writeJson(res, 404, { error: "session_not_found" });
|
|
50729
|
+
return true;
|
|
50730
|
+
}
|
|
50731
|
+
const chat = chatRegistry.get(sessionId);
|
|
50732
|
+
if (!chat) {
|
|
50733
|
+
ctx.host.http.writeJson(res, 409, { error: "chat_not_active" });
|
|
50734
|
+
return true;
|
|
50735
|
+
}
|
|
50736
|
+
const body = await ctx.host.http.readJsonBody(req);
|
|
50737
|
+
const jobId = typeof body?.jobId === "string" ? body.jobId : "";
|
|
50738
|
+
if (jobId.length === 0) {
|
|
50739
|
+
ctx.host.http.writeJson(res, 400, { error: "invalid_job_id" });
|
|
50740
|
+
return true;
|
|
50741
|
+
}
|
|
50742
|
+
if (!await chat.stopJob(jobId)) {
|
|
50743
|
+
ctx.host.http.writeJson(res, 409, { error: "job_stop_unavailable" });
|
|
50744
|
+
return true;
|
|
50745
|
+
}
|
|
50746
|
+
ctx.host.http.writeJson(res, 200, { ok: true });
|
|
50747
|
+
return true;
|
|
50748
|
+
}
|
|
49783
50749
|
async function handleChatJob(req, res, sessionId) {
|
|
49784
50750
|
if (req.method !== "GET") return methodNotAllowed2(res);
|
|
49785
50751
|
if (!ctx.host.security.validateHost(req) || !ctx.host.security.isTerminalAuthorized(req)) return unauthorized(res);
|
|
@@ -49818,56 +50784,7 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49818
50784
|
ctx.host.http.writeJson(res, 409, { error: "chat_not_active" });
|
|
49819
50785
|
return true;
|
|
49820
50786
|
}
|
|
49821
|
-
|
|
49822
|
-
let unsubscribe = null;
|
|
49823
|
-
const write = (data) => {
|
|
49824
|
-
if (!closed && !res.writableEnded && !res.destroyed) res.write(data);
|
|
49825
|
-
};
|
|
49826
|
-
res.writeHead(200, {
|
|
49827
|
-
"Content-Type": "text/event-stream",
|
|
49828
|
-
"Cache-Control": "no-store",
|
|
49829
|
-
Connection: "keep-alive",
|
|
49830
|
-
"Cross-Origin-Opener-Policy": "same-origin",
|
|
49831
|
-
"Cross-Origin-Resource-Policy": "same-origin",
|
|
49832
|
-
"Referrer-Policy": "no-referrer",
|
|
49833
|
-
"X-Content-Type-Options": "nosniff"
|
|
49834
|
-
});
|
|
49835
|
-
write(": open\n\n");
|
|
49836
|
-
const keepalive = setInterval(() => write(": keepalive\n\n"), 3e4);
|
|
49837
|
-
req.on("close", () => {
|
|
49838
|
-
closed = true;
|
|
49839
|
-
clearInterval(keepalive);
|
|
49840
|
-
unsubscribe?.();
|
|
49841
|
-
});
|
|
49842
|
-
void (async () => {
|
|
49843
|
-
const seed = await resolveChatSeed(node);
|
|
49844
|
-
if (!seed.ok) {
|
|
49845
|
-
write(`data: ${JSON.stringify({ seq: 0, event: { kind: "error", code: seed.error } })}
|
|
49846
|
-
|
|
49847
|
-
`);
|
|
49848
|
-
res.end();
|
|
49849
|
-
return;
|
|
49850
|
-
}
|
|
49851
|
-
if (ctx.host.operations.get(sessionId)?.payload[CHAT_MODE_PAYLOAD_KEY] !== true) {
|
|
49852
|
-
write(`data: ${JSON.stringify({ seq: 0, event: { kind: "error", code: "chat_not_active" } })}
|
|
49853
|
-
|
|
49854
|
-
`);
|
|
49855
|
-
res.end();
|
|
49856
|
-
return;
|
|
49857
|
-
}
|
|
49858
|
-
try {
|
|
49859
|
-
const chat = await chatRegistry.ensure(sessionId, () => seed.seed);
|
|
49860
|
-
if (closed) return;
|
|
49861
|
-
unsubscribe = chat.subscribe((entry) => write(`data: ${JSON.stringify(entry)}
|
|
49862
|
-
|
|
49863
|
-
`));
|
|
49864
|
-
} catch {
|
|
49865
|
-
write(`data: ${JSON.stringify({ seq: 0, event: { kind: "error", code: "chat_unavailable" } })}
|
|
49866
|
-
|
|
49867
|
-
`);
|
|
49868
|
-
res.end();
|
|
49869
|
-
}
|
|
49870
|
-
})();
|
|
50787
|
+
ctx.host.http.writeJson(res, 410, { error: "chat_stream_moved" });
|
|
49871
50788
|
return true;
|
|
49872
50789
|
}
|
|
49873
50790
|
async function resolveChatSeed(node) {
|
|
@@ -49884,7 +50801,7 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49884
50801
|
const cwd = readPayloadString(node.payload, "cwd") || ctx.host.paths.resolveTheaterPath(node.theaterId);
|
|
49885
50802
|
if (!cwd) return { ok: false, status: 404, error: "theater_not_found" };
|
|
49886
50803
|
const model = readPayloadString(node.payload, "launchModel") || "opus[1m]";
|
|
49887
|
-
const
|
|
50804
|
+
const launchEffort = resolveChatLaunchEffort(readPayloadString(node.payload, "launchEffort"));
|
|
49888
50805
|
const claudeConfigDir = resolveClaudeConfigDir();
|
|
49889
50806
|
const gatewayBaseUrl = resolveAnalysisGatewayBaseUrl(origin);
|
|
49890
50807
|
try {
|
|
@@ -49905,7 +50822,7 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49905
50822
|
seed: {
|
|
49906
50823
|
baseUrl: gatewayBaseUrl,
|
|
49907
50824
|
model,
|
|
49908
|
-
...
|
|
50825
|
+
...launchEffort ? { effort: launchEffort.effort } : {},
|
|
49909
50826
|
cwd,
|
|
49910
50827
|
claudeConfigDir,
|
|
49911
50828
|
origin: sessionOrigin,
|
|
@@ -49932,6 +50849,7 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
49932
50849
|
// 터미널이 `--settings`로 강제하는 것과 같은 값이다. 없으면 같은 프롬프트가 표면에
|
|
49933
50850
|
// 따라 다른 내장 스킬을 깨운다.
|
|
49934
50851
|
...chatSkillOverrides ? { skillOverrides: chatSkillOverrides } : {},
|
|
50852
|
+
...launchEffort?.ultracode ? { ultracode: true } : {},
|
|
49935
50853
|
// 터미널 런치와 같은 자리에 같은 옵션으로 렌더한다 — 두 표면이 한 플러그인을 공유한다.
|
|
49936
50854
|
resolveFleetPluginRoots: () => renderFleetPluginRootsForChat({
|
|
49937
50855
|
cwd,
|
|
@@ -50259,11 +51177,6 @@ async function createAgentApi(ctx, terminalRuntime, deps) {
|
|
|
50259
51177
|
return true;
|
|
50260
51178
|
}
|
|
50261
51179
|
}
|
|
50262
|
-
function chatEffortFromLaunchEffort(value) {
|
|
50263
|
-
if (value.length === 0) return void 0;
|
|
50264
|
-
if (value === "ultra") return "max";
|
|
50265
|
-
return ["low", "medium", "high", "xhigh", "max"].includes(value) ? value : void 0;
|
|
50266
|
-
}
|
|
50267
51180
|
function isOperationDeletedEventPayload(value) {
|
|
50268
51181
|
if (!value || typeof value !== "object") return false;
|
|
50269
51182
|
const event = value;
|