@pensar/apex 2.4.0 → 2.5.0-canary.aa559068
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/build/agent-48xj79bj.js +20 -0
- package/build/{agent-nhs1w5w0.js → agent-7q3c9cjt.js} +11 -10
- package/build/{agent-5ejt5vpz.js → agent-ve8pkr6q.js} +9 -8
- package/build/{apps-17wvz1d7.js → apps-4rsrnftx.js} +72 -31
- package/build/{auth-z3h9859n.js → auth-0w07dbg2.js} +25 -20
- package/build/authentication-87zzmjdd.js +20 -0
- package/build/blackboxAgent-x0e1wqjx.js +20 -0
- package/build/blackboxPentest-0hwj49dr.js +70 -0
- package/build/{cli-32z0017y.js → cli-12ky98ey.js} +2 -2
- package/build/{cli-5k33webc.js → cli-2ar3m569.js} +45 -43
- package/build/cli-53rm0rrz.js +15 -0
- package/build/{cli-72cvcqhg.js → cli-54egv3xw.js} +1 -1
- package/build/cli-68260ckj.js +12136 -0
- package/build/{cli-gq40s5b3.js → cli-6cq67y5m.js} +5 -3
- package/build/{cli-mavved45.js → cli-7735d17s.js} +46 -25
- package/build/cli-7q3ae3ft.js +6 -0
- package/build/{cli-tznv8pf1.js → cli-8mws7sa5.js} +1 -1
- package/build/cli-9pbk8m32.js +32 -0
- package/build/{cli-swpbx60z.js → cli-avmhkjtv.js} +1 -1481
- package/build/{cli-9rhzhgx2.js → cli-eaaqeve1.js} +1 -1
- package/build/{cli-qqt4gj1w.js → cli-g0whajsq.js} +5 -3
- package/build/{cli-vq52kp7j.js → cli-gb1s7k3v.js} +17 -5
- package/build/{cli-2cbwdk78.js → cli-h8xsqggy.js} +1 -1
- package/build/{cli-0n4r54hq.js → cli-jsw8vt43.js} +1 -1
- package/build/cli-knd276ed.js +1485 -0
- package/build/{cli-repbyhkk.js → cli-kya26m6f.js} +1136 -525
- package/build/{cli-k8kc47pq.js → cli-mmyn6wmb.js} +3 -3
- package/build/{cli-tkc598ey.js → cli-qwv4jsj2.js} +371 -279
- package/build/{cli-xshasbwe.js → cli-r3w58pmq.js} +30 -4
- package/build/{cli-vnynf0js.js → cli-w51z9qjr.js} +10 -4
- package/build/{cli-b1adytsy.js → cli-whp0f8gp.js} +28 -5
- package/build/cli.js +553 -95
- package/build/{config-f1mj4nhd.js → config-z9k13rvy.js} +18 -15
- package/build/{doctor-ekneewa3.js → doctor-tc5zs6pn.js} +8 -7
- package/build/{fastStrike-8zka43xs.js → fastStrike-ssm7df42.js} +13 -10
- package/build/{fixes-b89s5haw.js → fixes-av9nq0hq.js} +25 -20
- package/build/getMachineId-bsd-xj3bn2fv.js +36 -0
- package/build/getMachineId-darwin-07jzjcx6.js +36 -0
- package/build/getMachineId-linux-ahngynxd.js +29 -0
- package/build/getMachineId-unsupported-vy43b44z.js +19 -0
- package/build/getMachineId-win-8x66cynz.js +38 -0
- package/build/{index-hqjdg6fg.js → index-1ppbwgf9.js} +17 -9
- package/build/{index-mtq7kmxz.js → index-5wh7gq37.js} +4 -2
- package/build/{index-6d22pyxt.js → index-718m7jw9.js} +1669 -1193
- package/build/{index-rbzhk712.js → index-gng8ebqf.js} +11 -10
- package/build/{index-y5w6n3tb.js → index-hhcjyc6j.js} +2 -2
- package/build/{index-sf16jm0m.js → index-mffgf5hg.js} +9 -7
- package/build/{index-ghwf5z3v.js → index-p1atm3ha.js} +3 -3
- package/build/{index-4ad3sdwk.js → index-vvkvwmyr.js} +4 -4
- package/build/{issues-xx5bs4md.js → issues-hfg8jydv.js} +72 -26
- package/build/{logs-qtxe51w2.js → logs-0rd1z7ct.js} +25 -20
- package/build/{offesecAgent-b9e2xm6v.js → offesecAgent-j4epj93p.js} +10 -9
- package/build/pentest-dp9w88pw.js +30 -0
- package/build/{pentests-6ks3szc4.js → pentests-enyxjtg6.js} +26 -21
- package/build/{targetedPentest-s1ptvq8e.js → targetedPentest-kwabfy86.js} +11 -10
- package/build/{targets-sxygyj87.js → targets-7x0pcmws.js} +27 -22
- package/build/threatModel-zwk5eb6r.js +29 -0
- package/build/{uninstall-tvsh81v8.js → uninstall-psm9btpt.js} +6 -3
- package/build/{upload-7wdyyqmr.js → upload-dybnknjs.js} +8 -7
- package/build/{utils-7fwdkqk6.js → utils-dsfk965b.js} +7 -6
- package/package.json +8 -2
- package/build/agent-mvpgvgks.js +0 -19
- package/build/authentication-3s97cpk4.js +0 -19
- package/build/blackboxAgent-gw0a1ca4.js +0 -19
- package/build/blackboxPentest-44333zss.js +0 -37
- package/build/main-mmjp338j.js +0 -324
- package/build/pentest-xtc1sjdw.js +0 -29
- package/build/threatModel-xsm6fwk5.js +0 -27
|
@@ -7,23 +7,36 @@ import {
|
|
|
7
7
|
buildThreatModelPrompt,
|
|
8
8
|
createSkillsRegistry,
|
|
9
9
|
runOffensiveSecurityAgent
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-gb1s7k3v.js";
|
|
11
|
+
import {
|
|
12
|
+
EMPTY_SESSION_TOKEN_USAGE,
|
|
13
|
+
accumulateSessionTokens,
|
|
14
|
+
contextPercentage
|
|
15
|
+
} from "./cli-9pbk8m32.js";
|
|
11
16
|
import {
|
|
12
17
|
convertModelMessagesToUI,
|
|
13
18
|
loadSubagents,
|
|
14
19
|
readExecutionMetrics,
|
|
15
20
|
writeExecutionMetrics
|
|
16
|
-
} from "./cli-
|
|
17
|
-
import"./cli-
|
|
21
|
+
} from "./cli-2ar3m569.js";
|
|
22
|
+
import"./cli-mmyn6wmb.js";
|
|
23
|
+
import"./cli-6cq67y5m.js";
|
|
24
|
+
import"./cli-7735d17s.js";
|
|
18
25
|
import {
|
|
19
26
|
REPORT_FILENAME_MD
|
|
20
|
-
} from "./cli-
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
} from "./cli-whp0f8gp.js";
|
|
28
|
+
import {
|
|
29
|
+
createWeaveTracer,
|
|
30
|
+
resolveConfig
|
|
31
|
+
} from "./cli-h8xsqggy.js";
|
|
32
|
+
import {
|
|
33
|
+
AVAILABLE_PROVIDERS,
|
|
34
|
+
init_types
|
|
35
|
+
} from "./cli-ee3axgts.js";
|
|
36
|
+
import"./cli-r3w58pmq.js";
|
|
37
|
+
import"./cli-12ky98ey.js";
|
|
25
38
|
import"./cli-9fsre5pt.js";
|
|
26
|
-
import"./cli-
|
|
39
|
+
import"./cli-g0whajsq.js";
|
|
27
40
|
import {
|
|
28
41
|
ALL_TOOL_NAMES,
|
|
29
42
|
ASK_USER_QUESTIONS_TOOL_NAME,
|
|
@@ -39,10 +52,19 @@ import {
|
|
|
39
52
|
hasPlan,
|
|
40
53
|
planFilePath,
|
|
41
54
|
readPlan
|
|
42
|
-
} from "./cli-
|
|
55
|
+
} from "./cli-kya26m6f.js";
|
|
43
56
|
import {
|
|
44
57
|
detectOSAndEnhancePrompt
|
|
45
|
-
} from "./cli-
|
|
58
|
+
} from "./cli-8mws7sa5.js";
|
|
59
|
+
import {
|
|
60
|
+
require_index_node_http,
|
|
61
|
+
require_index_shim,
|
|
62
|
+
require_src as require_src2,
|
|
63
|
+
require_src1 as require_src3,
|
|
64
|
+
require_src2 as require_src4,
|
|
65
|
+
require_src3 as require_src5,
|
|
66
|
+
require_src4 as require_src6
|
|
67
|
+
} from "./cli-68260ckj.js";
|
|
46
68
|
import {
|
|
47
69
|
formatParseError,
|
|
48
70
|
parseHeaderLine
|
|
@@ -55,19 +77,15 @@ import {
|
|
|
55
77
|
getAutoPopulatedPorts,
|
|
56
78
|
parseTargetUrl
|
|
57
79
|
} from "./cli-c8131c4q.js";
|
|
58
|
-
import {
|
|
59
|
-
createWeaveTracer,
|
|
60
|
-
resolveConfig
|
|
61
|
-
} from "./cli-2cbwdk78.js";
|
|
62
|
-
import {
|
|
63
|
-
AVAILABLE_PROVIDERS,
|
|
64
|
-
init_types
|
|
65
|
-
} from "./cli-ee3axgts.js";
|
|
66
80
|
import {
|
|
67
81
|
AVAILABLE_MODELS,
|
|
68
82
|
DEFAULT_OPENAI_REASONING_EFFORT,
|
|
83
|
+
addRecentModelId,
|
|
69
84
|
buildAuthConfig,
|
|
85
|
+
getContextWindow,
|
|
70
86
|
getOpenAIReasoningEfforts,
|
|
87
|
+
getRecentModels,
|
|
88
|
+
getResumeMessages,
|
|
71
89
|
hasToolCall,
|
|
72
90
|
init_ai,
|
|
73
91
|
init_dist,
|
|
@@ -85,7 +103,7 @@ import {
|
|
|
85
103
|
stepCountIs,
|
|
86
104
|
write,
|
|
87
105
|
writeErrorLog
|
|
88
|
-
} from "./cli-
|
|
106
|
+
} from "./cli-qwv4jsj2.js";
|
|
89
107
|
import {
|
|
90
108
|
disconnect,
|
|
91
109
|
ensureValidToken,
|
|
@@ -100,21 +118,23 @@ import {
|
|
|
100
118
|
selectWorkspace,
|
|
101
119
|
startDeviceFlow,
|
|
102
120
|
validateGateway
|
|
103
|
-
} from "./cli-
|
|
104
|
-
import"./cli-
|
|
121
|
+
} from "./cli-jsw8vt43.js";
|
|
122
|
+
import"./cli-avmhkjtv.js";
|
|
105
123
|
import"./cli-j54qa6tm.js";
|
|
106
124
|
import {
|
|
107
125
|
config,
|
|
108
|
-
init_config
|
|
109
|
-
} from "./cli-
|
|
110
|
-
import
|
|
111
|
-
init_config,
|
|
112
|
-
update
|
|
113
|
-
} from "./cli-9rhzhgx2.js";
|
|
126
|
+
init_config
|
|
127
|
+
} from "./cli-54egv3xw.js";
|
|
128
|
+
import"./cli-eaaqeve1.js";
|
|
114
129
|
import {
|
|
115
130
|
checkForUpdate,
|
|
116
|
-
init_installation
|
|
117
|
-
|
|
131
|
+
init_installation,
|
|
132
|
+
init_package,
|
|
133
|
+
version
|
|
134
|
+
} from "./cli-w51z9qjr.js";
|
|
135
|
+
import {
|
|
136
|
+
require_src
|
|
137
|
+
} from "./cli-knd276ed.js";
|
|
118
138
|
import {
|
|
119
139
|
__commonJS,
|
|
120
140
|
__esm,
|
|
@@ -752,11 +772,11 @@ var require_core = __commonJS(function(exports, module) {
|
|
|
752
772
|
var warn = (message, ...args) => {
|
|
753
773
|
console.log(`WARN: ${message}`, ...args);
|
|
754
774
|
};
|
|
755
|
-
var deprecated = (
|
|
756
|
-
if (seenDeprecations[`${
|
|
775
|
+
var deprecated = (version3, message) => {
|
|
776
|
+
if (seenDeprecations[`${version3}/${message}`])
|
|
757
777
|
return;
|
|
758
|
-
console.log(`Deprecated as of ${
|
|
759
|
-
seenDeprecations[`${
|
|
778
|
+
console.log(`Deprecated as of ${version3}. ${message}`);
|
|
779
|
+
seenDeprecations[`${version3}/${message}`] = true;
|
|
760
780
|
};
|
|
761
781
|
var MultiClassError = new Error;
|
|
762
782
|
function remapScopeNames(mode, regexes, { key }) {
|
|
@@ -1006,7 +1026,7 @@ var require_core = __commonJS(function(exports, module) {
|
|
|
1006
1026
|
}
|
|
1007
1027
|
return mode;
|
|
1008
1028
|
}
|
|
1009
|
-
var
|
|
1029
|
+
var version2 = "11.11.1";
|
|
1010
1030
|
|
|
1011
1031
|
class HTMLInjectionError extends Error {
|
|
1012
1032
|
constructor(reason, html) {
|
|
@@ -1070,13 +1090,13 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
|
|
|
1070
1090
|
if (ignoreIllegals === undefined) {
|
|
1071
1091
|
ignoreIllegals = true;
|
|
1072
1092
|
}
|
|
1073
|
-
const
|
|
1093
|
+
const context2 = {
|
|
1074
1094
|
code,
|
|
1075
1095
|
language: languageName
|
|
1076
1096
|
};
|
|
1077
|
-
fire("before:highlight",
|
|
1078
|
-
const result =
|
|
1079
|
-
result.code =
|
|
1097
|
+
fire("before:highlight", context2);
|
|
1098
|
+
const result = context2.result ? context2.result : _highlight(context2.language, context2.code, ignoreIllegals);
|
|
1099
|
+
result.code = context2.code;
|
|
1080
1100
|
fire("after:highlight", result);
|
|
1081
1101
|
return result;
|
|
1082
1102
|
}
|
|
@@ -1628,7 +1648,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
|
|
|
1628
1648
|
hljs.safeMode = function() {
|
|
1629
1649
|
SAFE_MODE = true;
|
|
1630
1650
|
};
|
|
1631
|
-
hljs.versionString =
|
|
1651
|
+
hljs.versionString = version2;
|
|
1632
1652
|
hljs.regex = {
|
|
1633
1653
|
concat,
|
|
1634
1654
|
lookahead,
|
|
@@ -49370,13 +49390,110 @@ var require_lib = __commonJS(function(exports, module) {
|
|
|
49370
49390
|
});
|
|
49371
49391
|
|
|
49372
49392
|
// src/tui/index.tsx
|
|
49373
|
-
|
|
49393
|
+
init_config();
|
|
49374
49394
|
init_installation();
|
|
49375
49395
|
init_logger();
|
|
49376
49396
|
import { createCliRenderer, FrameBufferRenderable, RGBA as RGBA25 } from "@opentui/core";
|
|
49377
49397
|
import { createRoot, extend } from "@opentui/react";
|
|
49378
49398
|
import { useEffect as useEffect27, useState as useState40 } from "react";
|
|
49379
49399
|
|
|
49400
|
+
// src/core/observability/runtime.ts
|
|
49401
|
+
init_package();
|
|
49402
|
+
var import_api = __toESM(require_src(), 1);
|
|
49403
|
+
var import_context_async_hooks = __toESM(require_src2(), 1);
|
|
49404
|
+
var import_exporter_trace_otlp_http = __toESM(require_src6(), 1);
|
|
49405
|
+
var import_otlp_exporter_base = __toESM(require_src3(), 1);
|
|
49406
|
+
var import_node_http = __toESM(require_index_node_http(), 1);
|
|
49407
|
+
var import_otlp_transformer = __toESM(require_src5(), 1);
|
|
49408
|
+
var import_resources = __toESM(require_src4(), 1);
|
|
49409
|
+
var import_sdk_trace_base = __toESM(require_index_shim(), 1);
|
|
49410
|
+
import { randomUUID } from "node:crypto";
|
|
49411
|
+
var NOOP_RUNTIME = {
|
|
49412
|
+
async forceFlush() {},
|
|
49413
|
+
async shutdown() {}
|
|
49414
|
+
};
|
|
49415
|
+
function isOtelSdkDisabled(env) {
|
|
49416
|
+
return env.OTEL_SDK_DISABLED === "true";
|
|
49417
|
+
}
|
|
49418
|
+
function resolveTracesEndpoint(env) {
|
|
49419
|
+
const specific = env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT?.trim();
|
|
49420
|
+
if (specific)
|
|
49421
|
+
return specific;
|
|
49422
|
+
const generic = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim();
|
|
49423
|
+
if (!generic)
|
|
49424
|
+
return null;
|
|
49425
|
+
return `${generic.endsWith("/") ? generic : `${generic}/`}v1/traces`;
|
|
49426
|
+
}
|
|
49427
|
+
function resolveTracesProtocol(env) {
|
|
49428
|
+
const raw = (env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ?? env.OTEL_EXPORTER_OTLP_PROTOCOL ?? "").trim();
|
|
49429
|
+
return raw === "http/protobuf" ? "http/protobuf" : "http/json";
|
|
49430
|
+
}
|
|
49431
|
+
function parseResourceAttributes(env) {
|
|
49432
|
+
const raw = env.OTEL_RESOURCE_ATTRIBUTES;
|
|
49433
|
+
if (!raw)
|
|
49434
|
+
return {};
|
|
49435
|
+
const attrs = {};
|
|
49436
|
+
for (const pair of raw.split(",")) {
|
|
49437
|
+
const eq = pair.indexOf("=");
|
|
49438
|
+
if (eq <= 0)
|
|
49439
|
+
continue;
|
|
49440
|
+
const key = pair.slice(0, eq).trim();
|
|
49441
|
+
const value = pair.slice(eq + 1).trim();
|
|
49442
|
+
if (key && value)
|
|
49443
|
+
attrs[key] = value;
|
|
49444
|
+
}
|
|
49445
|
+
return attrs;
|
|
49446
|
+
}
|
|
49447
|
+
function buildResource(env) {
|
|
49448
|
+
const resourceAttributes = parseResourceAttributes(env);
|
|
49449
|
+
return import_resources.resourceFromAttributes({
|
|
49450
|
+
"service.version": version,
|
|
49451
|
+
"service.instance.id": randomUUID(),
|
|
49452
|
+
...resourceAttributes,
|
|
49453
|
+
"service.name": env.OTEL_SERVICE_NAME?.trim() || resourceAttributes["service.name"] || "apex"
|
|
49454
|
+
});
|
|
49455
|
+
}
|
|
49456
|
+
function createTraceExporter(protocol) {
|
|
49457
|
+
if (protocol === "http/json") {
|
|
49458
|
+
return new import_exporter_trace_otlp_http.OTLPTraceExporter;
|
|
49459
|
+
}
|
|
49460
|
+
return new import_otlp_exporter_base.OTLPExporterBase(import_node_http.createOtlpHttpExportDelegate(import_node_http.convertLegacyHttpOptions({}, "TRACES", "v1/traces", {
|
|
49461
|
+
"Content-Type": "application/x-protobuf"
|
|
49462
|
+
}), import_otlp_transformer.ProtobufTraceSerializer, "otlp_http_span_exporter", import_otlp_transformer.TraceExporterMetricsHelper, undefined));
|
|
49463
|
+
}
|
|
49464
|
+
var activeRuntime = null;
|
|
49465
|
+
function startObservabilityRuntime(env = process.env) {
|
|
49466
|
+
if (activeRuntime)
|
|
49467
|
+
return activeRuntime;
|
|
49468
|
+
if (isOtelSdkDisabled(env))
|
|
49469
|
+
return NOOP_RUNTIME;
|
|
49470
|
+
if (!resolveTracesEndpoint(env))
|
|
49471
|
+
return NOOP_RUNTIME;
|
|
49472
|
+
const exporter = createTraceExporter(resolveTracesProtocol(env));
|
|
49473
|
+
const provider = new import_sdk_trace_base.BasicTracerProvider({
|
|
49474
|
+
resource: buildResource(env),
|
|
49475
|
+
spanProcessors: [new import_sdk_trace_base.BatchSpanProcessor(exporter)]
|
|
49476
|
+
});
|
|
49477
|
+
const contextManager = new import_context_async_hooks.AsyncLocalStorageContextManager;
|
|
49478
|
+
contextManager.enable();
|
|
49479
|
+
import_api.trace.setGlobalTracerProvider(provider);
|
|
49480
|
+
import_api.context.setGlobalContextManager(contextManager);
|
|
49481
|
+
const runtime = {
|
|
49482
|
+
async forceFlush() {
|
|
49483
|
+
await provider.forceFlush();
|
|
49484
|
+
},
|
|
49485
|
+
async shutdown() {
|
|
49486
|
+
activeRuntime = null;
|
|
49487
|
+
await provider.shutdown();
|
|
49488
|
+
contextManager.disable();
|
|
49489
|
+
import_api.trace.disable();
|
|
49490
|
+
import_api.context.disable();
|
|
49491
|
+
}
|
|
49492
|
+
};
|
|
49493
|
+
activeRuntime = runtime;
|
|
49494
|
+
return runtime;
|
|
49495
|
+
}
|
|
49496
|
+
|
|
49380
49497
|
// src/core/providers/index.ts
|
|
49381
49498
|
init_types();
|
|
49382
49499
|
init_utils();
|
|
@@ -52796,16 +52913,15 @@ function createClipboardManager(renderer) {
|
|
|
52796
52913
|
|
|
52797
52914
|
// src/tui/components/chat/index.tsx
|
|
52798
52915
|
init_session();
|
|
52799
|
-
import { useCallback as
|
|
52916
|
+
import { useCallback as useCallback14, useEffect as useEffect12, useState as useState19 } from "react";
|
|
52800
52917
|
|
|
52801
52918
|
// src/tui/context/agent.tsx
|
|
52802
52919
|
init_ai();
|
|
52803
|
-
init_config();
|
|
52804
52920
|
init_logger();
|
|
52805
52921
|
init_utils();
|
|
52806
52922
|
import {
|
|
52807
52923
|
createContext as createContext3,
|
|
52808
|
-
useCallback as
|
|
52924
|
+
useCallback as useCallback4,
|
|
52809
52925
|
useContext as useContext3,
|
|
52810
52926
|
useEffect as useEffect2,
|
|
52811
52927
|
useMemo as useMemo3,
|
|
@@ -52814,9 +52930,10 @@ import {
|
|
|
52814
52930
|
} from "react";
|
|
52815
52931
|
|
|
52816
52932
|
// src/tui/context/config.tsx
|
|
52817
|
-
|
|
52933
|
+
init_config();
|
|
52818
52934
|
import {
|
|
52819
52935
|
createContext as createContext2,
|
|
52936
|
+
useCallback as useCallback2,
|
|
52820
52937
|
useContext as useContext2,
|
|
52821
52938
|
useMemo as useMemo2,
|
|
52822
52939
|
useState as useState2
|
|
@@ -52825,20 +52942,22 @@ import { jsxDEV as jsxDEV2 } from "@opentui/react/jsx-dev-runtime";
|
|
|
52825
52942
|
var ctx = createContext2(null);
|
|
52826
52943
|
function ConfigProvider({ children, config: config2 }) {
|
|
52827
52944
|
const [appConfig, setAppConfig] = useState2(config2);
|
|
52945
|
+
const update = useCallback2(async (newConfig) => {
|
|
52946
|
+
await config.update(newConfig);
|
|
52947
|
+
setAppConfig((current) => ({
|
|
52948
|
+
...current,
|
|
52949
|
+
...newConfig
|
|
52950
|
+
}));
|
|
52951
|
+
}, []);
|
|
52952
|
+
const reload = useCallback2(async () => {
|
|
52953
|
+
const freshConfig = await config.get();
|
|
52954
|
+
setAppConfig(freshConfig);
|
|
52955
|
+
}, []);
|
|
52828
52956
|
const value = useMemo2(() => ({
|
|
52829
52957
|
data: appConfig,
|
|
52830
|
-
update
|
|
52831
|
-
|
|
52832
|
-
|
|
52833
|
-
...appConfig,
|
|
52834
|
-
...newConfig
|
|
52835
|
-
});
|
|
52836
|
-
},
|
|
52837
|
-
reload: async () => {
|
|
52838
|
-
const freshConfig = await config.get();
|
|
52839
|
-
setAppConfig(freshConfig);
|
|
52840
|
-
}
|
|
52841
|
-
}), [appConfig]);
|
|
52958
|
+
update,
|
|
52959
|
+
reload
|
|
52960
|
+
}), [appConfig, reload, update]);
|
|
52842
52961
|
return /* @__PURE__ */ jsxDEV2(ctx.Provider, {
|
|
52843
52962
|
value,
|
|
52844
52963
|
children
|
|
@@ -52852,15 +52971,133 @@ var useConfig = () => {
|
|
|
52852
52971
|
return config2;
|
|
52853
52972
|
};
|
|
52854
52973
|
|
|
52974
|
+
// src/tui/context/session-usage.ts
|
|
52975
|
+
import { useCallback as useCallback3, useSyncExternalStore } from "react";
|
|
52976
|
+
var EMPTY_STATE = {
|
|
52977
|
+
tokenUsage: EMPTY_SESSION_TOKEN_USAGE,
|
|
52978
|
+
contextUsage: null
|
|
52979
|
+
};
|
|
52980
|
+
|
|
52981
|
+
class SessionUsageStore {
|
|
52982
|
+
sessions = new Map;
|
|
52983
|
+
listeners = new Map;
|
|
52984
|
+
activeListeners = new Set;
|
|
52985
|
+
activeId = null;
|
|
52986
|
+
provisionalState = EMPTY_STATE;
|
|
52987
|
+
get activeSessionId() {
|
|
52988
|
+
return this.activeId;
|
|
52989
|
+
}
|
|
52990
|
+
beginNewSession() {
|
|
52991
|
+
const changed = this.activeId !== null || this.provisionalState !== EMPTY_STATE;
|
|
52992
|
+
this.activeId = null;
|
|
52993
|
+
this.provisionalState = EMPTY_STATE;
|
|
52994
|
+
if (changed)
|
|
52995
|
+
this.emitActive();
|
|
52996
|
+
}
|
|
52997
|
+
enterSession(sessionId, seed) {
|
|
52998
|
+
if (!this.sessions.has(sessionId)) {
|
|
52999
|
+
this.sessions.set(sessionId, {
|
|
53000
|
+
tokenUsage: seed?.tokenUsage ?? this.provisionalState.tokenUsage,
|
|
53001
|
+
contextUsage: seed?.contextUsage ?? null
|
|
53002
|
+
});
|
|
53003
|
+
this.provisionalState = EMPTY_STATE;
|
|
53004
|
+
}
|
|
53005
|
+
if (this.activeId !== sessionId) {
|
|
53006
|
+
this.activeId = sessionId;
|
|
53007
|
+
this.emit(sessionId);
|
|
53008
|
+
}
|
|
53009
|
+
}
|
|
53010
|
+
forgetSession(sessionId) {
|
|
53011
|
+
this.sessions.delete(sessionId);
|
|
53012
|
+
this.listeners.delete(sessionId);
|
|
53013
|
+
if (this.activeId === sessionId)
|
|
53014
|
+
this.activeId = null;
|
|
53015
|
+
}
|
|
53016
|
+
getSnapshot(sessionId) {
|
|
53017
|
+
if (sessionId === null)
|
|
53018
|
+
return EMPTY_STATE;
|
|
53019
|
+
return this.sessions.get(sessionId) ?? EMPTY_STATE;
|
|
53020
|
+
}
|
|
53021
|
+
subscribe(sessionId, listener) {
|
|
53022
|
+
let set = this.listeners.get(sessionId);
|
|
53023
|
+
if (!set) {
|
|
53024
|
+
set = new Set;
|
|
53025
|
+
this.listeners.set(sessionId, set);
|
|
53026
|
+
}
|
|
53027
|
+
set.add(listener);
|
|
53028
|
+
return () => {
|
|
53029
|
+
set.delete(listener);
|
|
53030
|
+
};
|
|
53031
|
+
}
|
|
53032
|
+
addSessionTokens(sessionId, step) {
|
|
53033
|
+
if (sessionId === null) {
|
|
53034
|
+
const next = accumulateSessionTokens(this.provisionalState.tokenUsage, step);
|
|
53035
|
+
if (next !== this.provisionalState.tokenUsage) {
|
|
53036
|
+
this.provisionalState = { tokenUsage: next, contextUsage: null };
|
|
53037
|
+
if (this.activeId === null)
|
|
53038
|
+
this.emitActive();
|
|
53039
|
+
}
|
|
53040
|
+
return;
|
|
53041
|
+
}
|
|
53042
|
+
this.update(sessionId, (state) => ({
|
|
53043
|
+
...state,
|
|
53044
|
+
tokenUsage: accumulateSessionTokens(state.tokenUsage, step)
|
|
53045
|
+
}));
|
|
53046
|
+
}
|
|
53047
|
+
setRootContext(sessionId, sample) {
|
|
53048
|
+
if (sessionId === null)
|
|
53049
|
+
return;
|
|
53050
|
+
this.update(sessionId, (state) => ({
|
|
53051
|
+
...state,
|
|
53052
|
+
contextUsage: sample
|
|
53053
|
+
}));
|
|
53054
|
+
}
|
|
53055
|
+
update(sessionId, updater) {
|
|
53056
|
+
const current = this.sessions.get(sessionId);
|
|
53057
|
+
if (!current)
|
|
53058
|
+
return;
|
|
53059
|
+
const next = updater(current);
|
|
53060
|
+
if (next === current || next.tokenUsage === current.tokenUsage && next.contextUsage === current.contextUsage) {
|
|
53061
|
+
return;
|
|
53062
|
+
}
|
|
53063
|
+
this.sessions.set(sessionId, next);
|
|
53064
|
+
this.emit(sessionId);
|
|
53065
|
+
}
|
|
53066
|
+
getActiveSnapshot() {
|
|
53067
|
+
return this.activeId === null ? this.provisionalState : this.getSnapshot(this.activeId);
|
|
53068
|
+
}
|
|
53069
|
+
subscribeActive(listener) {
|
|
53070
|
+
this.activeListeners.add(listener);
|
|
53071
|
+
return () => {
|
|
53072
|
+
this.activeListeners.delete(listener);
|
|
53073
|
+
};
|
|
53074
|
+
}
|
|
53075
|
+
emit(sessionId) {
|
|
53076
|
+
for (const listener of this.listeners.get(sessionId) ?? [])
|
|
53077
|
+
listener();
|
|
53078
|
+
if (sessionId === this.activeId)
|
|
53079
|
+
this.emitActive();
|
|
53080
|
+
}
|
|
53081
|
+
emitActive() {
|
|
53082
|
+
for (const listener of this.activeListeners)
|
|
53083
|
+
listener();
|
|
53084
|
+
}
|
|
53085
|
+
}
|
|
53086
|
+
function useActiveSessionUsage(store) {
|
|
53087
|
+
const subscribe = useCallback3((listener) => store.subscribeActive(listener), [store]);
|
|
53088
|
+
const getSnapshot = useCallback3(() => store.getActiveSnapshot(), [store]);
|
|
53089
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
53090
|
+
}
|
|
53091
|
+
|
|
52855
53092
|
// src/tui/context/agent.tsx
|
|
52856
53093
|
import { jsxDEV as jsxDEV3 } from "@opentui/react/jsx-dev-runtime";
|
|
52857
53094
|
var AgentContext = createContext3(null);
|
|
52858
53095
|
function useAgent() {
|
|
52859
|
-
const
|
|
52860
|
-
if (!
|
|
53096
|
+
const context2 = useContext3(AgentContext);
|
|
53097
|
+
if (!context2) {
|
|
52861
53098
|
throw new Error("useAgent must be used within AgentProvider");
|
|
52862
53099
|
}
|
|
52863
|
-
return
|
|
53100
|
+
return context2;
|
|
52864
53101
|
}
|
|
52865
53102
|
function AgentProvider({ children }) {
|
|
52866
53103
|
const appConfig = useConfig();
|
|
@@ -52868,13 +53105,7 @@ function AgentProvider({ children }) {
|
|
|
52868
53105
|
return getDefaultModelForConfig(appConfig.data) ?? AVAILABLE_MODELS[0];
|
|
52869
53106
|
});
|
|
52870
53107
|
const [isModelUserSelected, setIsModelUserSelected] = useState3(false);
|
|
52871
|
-
const
|
|
52872
|
-
inputTokens: 0,
|
|
52873
|
-
outputTokens: 0,
|
|
52874
|
-
totalTokens: 0,
|
|
52875
|
-
cachedTokens: 0,
|
|
52876
|
-
cacheWriteTokens: 0
|
|
52877
|
-
});
|
|
53108
|
+
const usageStore = useMemo3(() => new SessionUsageStore, []);
|
|
52878
53109
|
const [hasExecuted, setHasExecuted] = useState3(false);
|
|
52879
53110
|
const [thinking, setThinking] = useState3(false);
|
|
52880
53111
|
const [reasoningEnabled, setReasoningEnabledInternal] = useState3(() => appConfig.data?.reasoningEnabled ?? false);
|
|
@@ -52885,12 +53116,17 @@ function AgentProvider({ children }) {
|
|
|
52885
53116
|
reasoningEnabledRef.current = reasoningEnabled;
|
|
52886
53117
|
const openAIReasoningEffortRef = useRef(openAIReasoningEffort);
|
|
52887
53118
|
openAIReasoningEffortRef.current = openAIReasoningEffort;
|
|
52888
|
-
const
|
|
53119
|
+
const recentModelIdsRef = useRef(appConfig.data.recentModelIds ?? []);
|
|
53120
|
+
const updateConfig = appConfig.update;
|
|
53121
|
+
const setModel = useCallback4((newModel, persist = true) => {
|
|
52889
53122
|
setModelInternal(newModel);
|
|
52890
53123
|
if (persist) {
|
|
52891
53124
|
setIsModelUserSelected(true);
|
|
53125
|
+
const nextRecentModelIds = addRecentModelId(recentModelIdsRef.current, newModel.id);
|
|
53126
|
+
recentModelIdsRef.current = nextRecentModelIds;
|
|
52892
53127
|
const configUpdate = {
|
|
52893
|
-
selectedModelId: newModel.id
|
|
53128
|
+
selectedModelId: newModel.id,
|
|
53129
|
+
recentModelIds: nextRecentModelIds
|
|
52894
53130
|
};
|
|
52895
53131
|
if (reasoningEnabledRef.current && !modelSupportsThinking(newModel.id)) {
|
|
52896
53132
|
configUpdate.reasoningEnabled = false;
|
|
@@ -52901,23 +53137,26 @@ function AgentProvider({ children }) {
|
|
|
52901
53137
|
configUpdate.openAIReasoningEffort = DEFAULT_OPENAI_REASONING_EFFORT;
|
|
52902
53138
|
setOpenAIReasoningEffortInternal(DEFAULT_OPENAI_REASONING_EFFORT);
|
|
52903
53139
|
}
|
|
52904
|
-
|
|
53140
|
+
updateConfig(configUpdate).catch((err) => {
|
|
52905
53141
|
writeErrorLog(err, "AGENT_CONTEXT");
|
|
52906
53142
|
});
|
|
52907
53143
|
}
|
|
52908
|
-
}, []);
|
|
52909
|
-
const setReasoningEnabled =
|
|
53144
|
+
}, [updateConfig]);
|
|
53145
|
+
const setReasoningEnabled = useCallback4((enabled) => {
|
|
52910
53146
|
setReasoningEnabledInternal(enabled);
|
|
52911
|
-
|
|
53147
|
+
updateConfig({ reasoningEnabled: enabled }).catch((err) => {
|
|
52912
53148
|
writeErrorLog(err, "AGENT_CONTEXT");
|
|
52913
53149
|
});
|
|
52914
|
-
}, []);
|
|
52915
|
-
const setOpenAIReasoningEffort =
|
|
53150
|
+
}, [updateConfig]);
|
|
53151
|
+
const setOpenAIReasoningEffort = useCallback4((effort) => {
|
|
52916
53152
|
setOpenAIReasoningEffortInternal(effort);
|
|
52917
|
-
|
|
53153
|
+
updateConfig({ openAIReasoningEffort: effort }).catch((err) => {
|
|
52918
53154
|
writeErrorLog(err, "AGENT_CONTEXT");
|
|
52919
53155
|
});
|
|
52920
|
-
}, []);
|
|
53156
|
+
}, [updateConfig]);
|
|
53157
|
+
useEffect2(() => {
|
|
53158
|
+
recentModelIdsRef.current = appConfig.data.recentModelIds ?? [];
|
|
53159
|
+
}, [appConfig.data.recentModelIds]);
|
|
52921
53160
|
useEffect2(() => {
|
|
52922
53161
|
if (appConfig.data?.reasoningEnabled != null) {
|
|
52923
53162
|
setReasoningEnabledInternal(appConfig.data.reasoningEnabled);
|
|
@@ -52948,40 +53187,13 @@ function AgentProvider({ children }) {
|
|
|
52948
53187
|
setModelInternal(defaultModel);
|
|
52949
53188
|
}
|
|
52950
53189
|
}, [appConfig.data, isModelUserSelected]);
|
|
52951
|
-
const
|
|
52952
|
-
setHasExecuted(true);
|
|
52953
|
-
setTokenUsage((prev) => ({
|
|
52954
|
-
...prev,
|
|
52955
|
-
inputTokens: prev.inputTokens + input,
|
|
52956
|
-
outputTokens: prev.outputTokens + output,
|
|
52957
|
-
totalTokens: prev.totalTokens + input + output
|
|
52958
|
-
}));
|
|
52959
|
-
}, []);
|
|
52960
|
-
const addCacheUsage = useCallback2((cacheRead, cacheWrite) => {
|
|
52961
|
-
setTokenUsage((prev) => ({
|
|
52962
|
-
...prev,
|
|
52963
|
-
cachedTokens: prev.cachedTokens + cacheRead,
|
|
52964
|
-
cacheWriteTokens: prev.cacheWriteTokens + cacheWrite
|
|
52965
|
-
}));
|
|
52966
|
-
}, []);
|
|
52967
|
-
const resetTokenUsage = useCallback2(() => {
|
|
52968
|
-
setHasExecuted(false);
|
|
52969
|
-
setTokenUsage({
|
|
52970
|
-
inputTokens: 0,
|
|
52971
|
-
outputTokens: 0,
|
|
52972
|
-
totalTokens: 0,
|
|
52973
|
-
cachedTokens: 0,
|
|
52974
|
-
cacheWriteTokens: 0
|
|
52975
|
-
});
|
|
52976
|
-
}, []);
|
|
53190
|
+
const markExecuted = useCallback4(() => setHasExecuted(true), []);
|
|
52977
53191
|
const contextValue = useMemo3(() => ({
|
|
52978
53192
|
model,
|
|
52979
53193
|
setModel,
|
|
52980
53194
|
isModelUserSelected,
|
|
52981
|
-
|
|
52982
|
-
|
|
52983
|
-
addCacheUsage,
|
|
52984
|
-
resetTokenUsage,
|
|
53195
|
+
usageStore,
|
|
53196
|
+
markExecuted,
|
|
52985
53197
|
hasExecuted,
|
|
52986
53198
|
thinking,
|
|
52987
53199
|
setThinking,
|
|
@@ -52997,7 +53209,6 @@ function AgentProvider({ children }) {
|
|
|
52997
53209
|
model,
|
|
52998
53210
|
setModel,
|
|
52999
53211
|
isModelUserSelected,
|
|
53000
|
-
tokenUsage,
|
|
53001
53212
|
hasExecuted,
|
|
53002
53213
|
thinking,
|
|
53003
53214
|
reasoningEnabled,
|
|
@@ -53005,9 +53216,8 @@ function AgentProvider({ children }) {
|
|
|
53005
53216
|
openAIReasoningEffort,
|
|
53006
53217
|
isExecuting,
|
|
53007
53218
|
sessionCwd,
|
|
53008
|
-
|
|
53009
|
-
|
|
53010
|
-
resetTokenUsage,
|
|
53219
|
+
usageStore,
|
|
53220
|
+
markExecuted,
|
|
53011
53221
|
setOpenAIReasoningEffort
|
|
53012
53222
|
]);
|
|
53013
53223
|
return /* @__PURE__ */ jsxDEV3(AgentContext.Provider, {
|
|
@@ -53019,14 +53229,14 @@ function AgentProvider({ children }) {
|
|
|
53019
53229
|
// src/tui/components/chat/config-view.tsx
|
|
53020
53230
|
init_utils();
|
|
53021
53231
|
import { useKeyboard as useKeyboard2 } from "@opentui/react";
|
|
53022
|
-
import { useCallback as
|
|
53232
|
+
import { useCallback as useCallback6, useEffect as useEffect4, useState as useState5 } from "react";
|
|
53023
53233
|
|
|
53024
53234
|
// src/tui/components/model-picker/ModelPicker.tsx
|
|
53025
53235
|
init_ai();
|
|
53026
53236
|
init_utils();
|
|
53027
53237
|
import { useKeyboard } from "@opentui/react";
|
|
53028
53238
|
import {
|
|
53029
|
-
useCallback as
|
|
53239
|
+
useCallback as useCallback5,
|
|
53030
53240
|
useEffect as useEffect3,
|
|
53031
53241
|
useMemo as useMemo4,
|
|
53032
53242
|
useRef as useRef2,
|
|
@@ -53094,18 +53304,105 @@ function findChildById(scrollBox, id) {
|
|
|
53094
53304
|
return;
|
|
53095
53305
|
}
|
|
53096
53306
|
|
|
53097
|
-
// src/tui/components/model-picker/
|
|
53098
|
-
|
|
53099
|
-
|
|
53100
|
-
|
|
53307
|
+
// src/tui/components/model-picker/model-navigation.ts
|
|
53308
|
+
function findSelectedModelIndex(navigationItems, selectedModelId) {
|
|
53309
|
+
return navigationItems.findIndex((item) => (item.type === "model" || item.type === "recent-model") && item.model?.id === selectedModelId);
|
|
53310
|
+
}
|
|
53311
|
+
function retainAvailableProviders(expandedProviders, availableProviders) {
|
|
53312
|
+
const retainedProviders = new Set([...expandedProviders].filter((provider) => availableProviders.has(provider)));
|
|
53313
|
+
return retainedProviders.size === expandedProviders.size ? expandedProviders : retainedProviders;
|
|
53314
|
+
}
|
|
53315
|
+
function getSelectedModelRevealKey({
|
|
53316
|
+
availableModels,
|
|
53317
|
+
selectedModel,
|
|
53318
|
+
lastRevealedSelectedModelKey
|
|
53319
|
+
}) {
|
|
53320
|
+
const selectedModelKey = `${selectedModel.provider}:${selectedModel.id}`;
|
|
53321
|
+
if (lastRevealedSelectedModelKey === selectedModelKey)
|
|
53322
|
+
return null;
|
|
53323
|
+
const selectedModelIsAvailable = availableModels.some((model) => model.id === selectedModel.id && model.provider === selectedModel.provider);
|
|
53324
|
+
return selectedModelIsAvailable ? selectedModelKey : null;
|
|
53325
|
+
}
|
|
53326
|
+
|
|
53327
|
+
// src/tui/components/model-picker/model-search.ts
|
|
53328
|
+
var PROVIDER_DISPLAY_NAMES = {
|
|
53329
|
+
anthropic: "Anthropic",
|
|
53101
53330
|
openai: "OpenAI",
|
|
53102
|
-
google: "
|
|
53331
|
+
google: "Google",
|
|
53103
53332
|
openrouter: "OpenRouter",
|
|
53104
53333
|
concentrate: "Concentrate",
|
|
53105
|
-
bedrock: "Bedrock",
|
|
53334
|
+
bedrock: "AWS Bedrock",
|
|
53335
|
+
"bedrock-mantle": "Bedrock Mantle",
|
|
53106
53336
|
pensar: "Pensar",
|
|
53337
|
+
inception: "Inception",
|
|
53107
53338
|
local: "Local LLM"
|
|
53108
53339
|
};
|
|
53340
|
+
function getProviderDisplayName(provider) {
|
|
53341
|
+
return PROVIDER_DISPLAY_NAMES[provider];
|
|
53342
|
+
}
|
|
53343
|
+
function normalizeSearchText(value) {
|
|
53344
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
53345
|
+
}
|
|
53346
|
+
function filterModels(models, searchQuery) {
|
|
53347
|
+
const terms = normalizeSearchText(searchQuery).split(/\s+/).filter(Boolean);
|
|
53348
|
+
if (terms.length === 0)
|
|
53349
|
+
return models;
|
|
53350
|
+
return models.filter((model) => {
|
|
53351
|
+
const searchableText = normalizeSearchText(`${model.name} ${model.id} ${model.provider} ${getProviderDisplayName(model.provider)}`);
|
|
53352
|
+
return terms.every((term) => searchableText.includes(term));
|
|
53353
|
+
});
|
|
53354
|
+
}
|
|
53355
|
+
|
|
53356
|
+
// src/tui/components/model-picker/model-visibility.ts
|
|
53357
|
+
var HIDDEN_MODEL_IDS = {
|
|
53358
|
+
anthropic: new Set([
|
|
53359
|
+
"claude-3-haiku-20240307",
|
|
53360
|
+
"claude-opus-4-0",
|
|
53361
|
+
"claude-opus-4-20250514",
|
|
53362
|
+
"claude-opus-4-1",
|
|
53363
|
+
"claude-opus-4-1-20250805",
|
|
53364
|
+
"claude-sonnet-4-0",
|
|
53365
|
+
"claude-sonnet-4-20250514"
|
|
53366
|
+
]),
|
|
53367
|
+
openai: new Set([
|
|
53368
|
+
"gpt-5.3-chat-latest",
|
|
53369
|
+
"gpt-5.2-chat-latest",
|
|
53370
|
+
"gpt-5.2-codex",
|
|
53371
|
+
"gpt-5.1-chat-latest",
|
|
53372
|
+
"gpt-5.1-codex-mini",
|
|
53373
|
+
"gpt-5.1-codex",
|
|
53374
|
+
"gpt-5.1-codex-max",
|
|
53375
|
+
"gpt-5-chat-latest",
|
|
53376
|
+
"gpt-5-codex",
|
|
53377
|
+
"gpt-4.1-nano",
|
|
53378
|
+
"gpt-4.1-nano-2025-04-14",
|
|
53379
|
+
"gpt-4o-2024-05-13",
|
|
53380
|
+
"gpt-3.5-turbo",
|
|
53381
|
+
"gpt-3.5-turbo-0125",
|
|
53382
|
+
"gpt-3.5-turbo-1106",
|
|
53383
|
+
"o4-mini",
|
|
53384
|
+
"o4-mini-2025-04-16",
|
|
53385
|
+
"o3-mini",
|
|
53386
|
+
"o3-mini-2025-01-31",
|
|
53387
|
+
"o1",
|
|
53388
|
+
"o1-2024-12-17"
|
|
53389
|
+
]),
|
|
53390
|
+
google: new Set([
|
|
53391
|
+
"gemini-2.0-flash",
|
|
53392
|
+
"gemini-2.0-flash-001",
|
|
53393
|
+
"gemini-2.0-flash-lite",
|
|
53394
|
+
"gemini-2.0-flash-lite-001",
|
|
53395
|
+
"gemini-3-pro-preview",
|
|
53396
|
+
"gemini-3.1-flash-lite-preview",
|
|
53397
|
+
"gemini-robotics-er-1.5-preview"
|
|
53398
|
+
])
|
|
53399
|
+
};
|
|
53400
|
+
function getVisiblePickerModels(models, selectedModel) {
|
|
53401
|
+
return models.filter((model) => !HIDDEN_MODEL_IDS[model.provider]?.has(model.id) || model.id === selectedModel?.id && model.provider === selectedModel.provider);
|
|
53402
|
+
}
|
|
53403
|
+
|
|
53404
|
+
// src/tui/components/model-picker/ModelPicker.tsx
|
|
53405
|
+
import { jsxDEV as jsxDEV4, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
53109
53406
|
var providerOrder = [
|
|
53110
53407
|
"pensar",
|
|
53111
53408
|
"anthropic",
|
|
@@ -53114,11 +53411,10 @@ var providerOrder = [
|
|
|
53114
53411
|
"openrouter",
|
|
53115
53412
|
"concentrate",
|
|
53116
53413
|
"bedrock",
|
|
53414
|
+
"bedrock-mantle",
|
|
53415
|
+
"inception",
|
|
53117
53416
|
"local"
|
|
53118
53417
|
];
|
|
53119
|
-
function setsAreEqual(a, b) {
|
|
53120
|
-
return a.size === b.size && [...a].every((value) => b.has(value));
|
|
53121
|
-
}
|
|
53122
53418
|
function PickerRow({
|
|
53123
53419
|
children,
|
|
53124
53420
|
id,
|
|
@@ -53145,6 +53441,8 @@ function getNavItemId(item) {
|
|
|
53145
53441
|
return `provider-${item.provider}`;
|
|
53146
53442
|
if (item.type === "model")
|
|
53147
53443
|
return `model-${item.model.id}`;
|
|
53444
|
+
if (item.type === "recent-model")
|
|
53445
|
+
return `recent-model-${item.model.id}`;
|
|
53148
53446
|
if (item.type === "reasoning")
|
|
53149
53447
|
return "reasoning-toggle";
|
|
53150
53448
|
if (item.type === "openai-reasoning")
|
|
@@ -53169,8 +53467,10 @@ function ModelPicker({
|
|
|
53169
53467
|
const scrollBoxRef = useRef2(null);
|
|
53170
53468
|
const [availableModels, setAvailableModels] = useState4([]);
|
|
53171
53469
|
const [searchQuery, setSearchQuery] = useState4("");
|
|
53172
|
-
const [expandedProviders, setExpandedProviders] = useState4(new Set([
|
|
53470
|
+
const [expandedProviders, setExpandedProviders] = useState4(new Set([selectedModel.provider]));
|
|
53173
53471
|
const [focusedIndex, setFocusedIndex] = useState4(0);
|
|
53472
|
+
const lastRevealedSelectedModelRef = useRef2(null);
|
|
53473
|
+
const lastFocusedSelectedModelIdRef = useRef2(null);
|
|
53174
53474
|
const [localUrl, setLocalUrl] = useState4(config2?.localModelUrl ?? "");
|
|
53175
53475
|
const [localModelName, setLocalModelName] = useState4(config2?.localModelName ?? "");
|
|
53176
53476
|
const [editingLocalField, setEditingLocalField] = useState4(null);
|
|
@@ -53183,86 +53483,105 @@ function ModelPicker({
|
|
|
53183
53483
|
setAvailableModels([]);
|
|
53184
53484
|
return;
|
|
53185
53485
|
}
|
|
53186
|
-
setAvailableModels(getAvailableModels(config2)
|
|
53187
|
-
|
|
53486
|
+
setAvailableModels(getVisiblePickerModels(getAvailableModels(config2), {
|
|
53487
|
+
id: selectedModel.id,
|
|
53488
|
+
provider: selectedModel.provider
|
|
53489
|
+
}));
|
|
53490
|
+
}, [config2, selectedModel.id, selectedModel.provider]);
|
|
53188
53491
|
useEffect3(() => {
|
|
53189
53492
|
const availableProviders = new Set(availableModels.map((model) => model.provider));
|
|
53190
|
-
setExpandedProviders((prev) =>
|
|
53191
|
-
|
|
53192
|
-
|
|
53193
|
-
|
|
53194
|
-
|
|
53195
|
-
|
|
53196
|
-
|
|
53197
|
-
|
|
53198
|
-
|
|
53199
|
-
|
|
53200
|
-
return prev.size === 0 ? prev : new Set;
|
|
53201
|
-
}
|
|
53202
|
-
return prev.size === 1 && prev.has(fallbackProvider) ? prev : new Set([fallbackProvider]);
|
|
53493
|
+
setExpandedProviders((prev) => retainAvailableProviders(prev, availableProviders));
|
|
53494
|
+
}, [availableModels]);
|
|
53495
|
+
useEffect3(() => {
|
|
53496
|
+
const selectedModelKey = getSelectedModelRevealKey({
|
|
53497
|
+
availableModels,
|
|
53498
|
+
selectedModel: {
|
|
53499
|
+
id: selectedModel.id,
|
|
53500
|
+
provider: selectedModel.provider
|
|
53501
|
+
},
|
|
53502
|
+
lastRevealedSelectedModelKey: lastRevealedSelectedModelRef.current
|
|
53203
53503
|
});
|
|
53204
|
-
|
|
53504
|
+
if (!selectedModelKey)
|
|
53505
|
+
return;
|
|
53506
|
+
lastRevealedSelectedModelRef.current = selectedModelKey;
|
|
53507
|
+
setExpandedProviders((prev) => prev.has(selectedModel.provider) ? prev : new Set([...prev, selectedModel.provider]));
|
|
53508
|
+
}, [availableModels, selectedModel.id, selectedModel.provider]);
|
|
53509
|
+
const filteredModels = useMemo4(() => filterModels(availableModels, searchQuery), [availableModels, searchQuery]);
|
|
53510
|
+
const isSearching = searchQuery.trim().length > 0;
|
|
53511
|
+
const recentModels = useMemo4(() => getRecentModels(availableModels, config2?.recentModelIds ?? []), [availableModels, config2?.recentModelIds]);
|
|
53205
53512
|
const groupedModels = useMemo4(() => {
|
|
53206
53513
|
const groups = {};
|
|
53207
|
-
const query = searchQuery.toLowerCase().trim();
|
|
53208
53514
|
for (const m of availableModels) {
|
|
53209
|
-
if (query && !m.name.toLowerCase().includes(query) && !m.id.toLowerCase().includes(query)) {
|
|
53210
|
-
continue;
|
|
53211
|
-
}
|
|
53212
53515
|
if (!groups[m.provider]) {
|
|
53213
53516
|
groups[m.provider] = [];
|
|
53214
53517
|
}
|
|
53215
53518
|
groups[m.provider].push(m);
|
|
53216
53519
|
}
|
|
53217
53520
|
return groups;
|
|
53218
|
-
}, [availableModels
|
|
53521
|
+
}, [availableModels]);
|
|
53219
53522
|
const navigationItems = useMemo4(() => {
|
|
53220
53523
|
const items = [];
|
|
53221
|
-
|
|
53222
|
-
|
|
53223
|
-
items.push({ type: "
|
|
53224
|
-
|
|
53225
|
-
|
|
53226
|
-
|
|
53227
|
-
|
|
53228
|
-
|
|
53229
|
-
|
|
53230
|
-
|
|
53524
|
+
if (isSearching) {
|
|
53525
|
+
for (const model of filteredModels) {
|
|
53526
|
+
items.push({ type: "model", model });
|
|
53527
|
+
}
|
|
53528
|
+
} else {
|
|
53529
|
+
for (const model of recentModels) {
|
|
53530
|
+
items.push({ type: "recent-model", model });
|
|
53531
|
+
}
|
|
53532
|
+
for (const provider of providerOrder) {
|
|
53533
|
+
if (provider === "local") {
|
|
53534
|
+
items.push({ type: "provider", provider: "local" });
|
|
53535
|
+
if (expandedProviders.has("local")) {
|
|
53536
|
+
items.push({ type: "local-input", field: "url" });
|
|
53537
|
+
items.push({ type: "local-input", field: "model" });
|
|
53538
|
+
const localModels = groupedModels.local;
|
|
53539
|
+
if (localModels) {
|
|
53540
|
+
for (const m of localModels) {
|
|
53541
|
+
items.push({ type: "model", model: m });
|
|
53542
|
+
}
|
|
53231
53543
|
}
|
|
53232
53544
|
}
|
|
53545
|
+
continue;
|
|
53233
53546
|
}
|
|
53234
|
-
|
|
53235
|
-
|
|
53236
|
-
|
|
53237
|
-
|
|
53238
|
-
|
|
53239
|
-
|
|
53240
|
-
|
|
53241
|
-
|
|
53242
|
-
items.push({ type: "model", model: m });
|
|
53547
|
+
const models = groupedModels[provider];
|
|
53548
|
+
if (!models || models.length === 0)
|
|
53549
|
+
continue;
|
|
53550
|
+
items.push({ type: "provider", provider });
|
|
53551
|
+
if (expandedProviders.has(provider)) {
|
|
53552
|
+
for (const m of models) {
|
|
53553
|
+
items.push({ type: "model", model: m });
|
|
53554
|
+
}
|
|
53243
53555
|
}
|
|
53244
53556
|
}
|
|
53245
53557
|
}
|
|
53246
|
-
if (onReasoningToggle && modelSupportsThinking(selectedModel.id)) {
|
|
53558
|
+
if (!isSearching && onReasoningToggle && modelSupportsThinking(selectedModel.id)) {
|
|
53247
53559
|
items.push({ type: "reasoning" });
|
|
53248
53560
|
}
|
|
53249
|
-
if (onOpenAIReasoningEffortChange && modelSupportsOpenAIReasoning(selectedModel.id)) {
|
|
53561
|
+
if (!isSearching && onOpenAIReasoningEffortChange && modelSupportsOpenAIReasoning(selectedModel.id)) {
|
|
53250
53562
|
items.push({ type: "openai-reasoning" });
|
|
53251
53563
|
}
|
|
53252
53564
|
return items;
|
|
53253
53565
|
}, [
|
|
53254
53566
|
groupedModels,
|
|
53567
|
+
filteredModels,
|
|
53568
|
+
recentModels,
|
|
53569
|
+
isSearching,
|
|
53255
53570
|
expandedProviders,
|
|
53256
53571
|
onReasoningToggle,
|
|
53257
53572
|
onOpenAIReasoningEffortChange,
|
|
53258
53573
|
selectedModel.id
|
|
53259
53574
|
]);
|
|
53260
53575
|
useEffect3(() => {
|
|
53261
|
-
|
|
53262
|
-
|
|
53263
|
-
setFocusedIndex(idx);
|
|
53576
|
+
if (isSearching || lastFocusedSelectedModelIdRef.current === selectedModel.id) {
|
|
53577
|
+
return;
|
|
53264
53578
|
}
|
|
53265
|
-
|
|
53579
|
+
const index = findSelectedModelIndex(navigationItems, selectedModel.id);
|
|
53580
|
+
if (index === -1)
|
|
53581
|
+
return;
|
|
53582
|
+
lastFocusedSelectedModelIdRef.current = selectedModel.id;
|
|
53583
|
+
setFocusedIndex(index);
|
|
53584
|
+
}, [isSearching, navigationItems, selectedModel.id]);
|
|
53266
53585
|
useEffect3(() => {
|
|
53267
53586
|
setFocusedIndex((prev) => Math.min(prev, Math.max(0, navigationItems.length - 1)));
|
|
53268
53587
|
}, [navigationItems.length]);
|
|
@@ -53272,16 +53591,16 @@ function ModelPicker({
|
|
|
53272
53591
|
return;
|
|
53273
53592
|
scrollToChild(scrollBoxRef.current, getNavItemId(item));
|
|
53274
53593
|
}, [focusedIndex, navigationItems]);
|
|
53275
|
-
const commitLocalConfig =
|
|
53594
|
+
const commitLocalConfig = useCallback5((url, modelName) => {
|
|
53276
53595
|
if (!onConfigUpdate)
|
|
53277
53596
|
return;
|
|
53278
|
-
const
|
|
53597
|
+
const update = {
|
|
53279
53598
|
localModelUrl: url || null,
|
|
53280
53599
|
localModelName: modelName || null
|
|
53281
53600
|
};
|
|
53282
|
-
onConfigUpdate(
|
|
53601
|
+
onConfigUpdate(update);
|
|
53283
53602
|
}, [onConfigUpdate]);
|
|
53284
|
-
const finishEditing =
|
|
53603
|
+
const finishEditing = useCallback5(() => {
|
|
53285
53604
|
setEditingLocalField(null);
|
|
53286
53605
|
commitLocalConfig(localUrl, localModelName);
|
|
53287
53606
|
}, [localUrl, localModelName, commitLocalConfig]);
|
|
@@ -53290,7 +53609,7 @@ function ModelPicker({
|
|
|
53290
53609
|
const openAIReasoningEfforts = getOpenAIReasoningEfforts(selectedModel.id);
|
|
53291
53610
|
const isReasoningFocused = navigationItems[focusedIndex]?.type === "reasoning";
|
|
53292
53611
|
const isOpenAIReasoningFocused = navigationItems[focusedIndex]?.type === "openai-reasoning";
|
|
53293
|
-
const cycleOpenAIReasoningEffort =
|
|
53612
|
+
const cycleOpenAIReasoningEffort = useCallback5(() => {
|
|
53294
53613
|
if (!onOpenAIReasoningEffortChange || openAIReasoningEfforts.length === 0) {
|
|
53295
53614
|
return;
|
|
53296
53615
|
}
|
|
@@ -53302,7 +53621,7 @@ function ModelPicker({
|
|
|
53302
53621
|
openAIReasoningEffort,
|
|
53303
53622
|
openAIReasoningEfforts
|
|
53304
53623
|
]);
|
|
53305
|
-
const handleKeyboard =
|
|
53624
|
+
const handleKeyboard = useCallback5((key) => {
|
|
53306
53625
|
if (!focused)
|
|
53307
53626
|
return false;
|
|
53308
53627
|
if (editingLocalField) {
|
|
@@ -53312,24 +53631,18 @@ function ModelPicker({
|
|
|
53312
53631
|
}
|
|
53313
53632
|
return false;
|
|
53314
53633
|
}
|
|
53315
|
-
if (navigationItems.length === 0)
|
|
53316
|
-
return false;
|
|
53317
53634
|
if (key.name === "up" || key.name === "down") {
|
|
53318
|
-
|
|
53635
|
+
if (navigationItems.length === 0)
|
|
53636
|
+
return false;
|
|
53637
|
+
const direction = key.name === "up" ? -1 : 1;
|
|
53638
|
+
const newIndex = (focusedIndex + direction + navigationItems.length) % navigationItems.length;
|
|
53319
53639
|
setFocusedIndex(newIndex);
|
|
53320
|
-
const item = navigationItems[newIndex];
|
|
53321
|
-
if (item && item.type === "model") {
|
|
53322
|
-
onSelectModel(item.model);
|
|
53323
|
-
}
|
|
53324
|
-
return true;
|
|
53325
|
-
}
|
|
53326
|
-
if (key.name === "backspace") {
|
|
53327
|
-
setSearchQuery((prev) => prev.slice(0, -1));
|
|
53328
53640
|
return true;
|
|
53329
53641
|
}
|
|
53330
53642
|
if (key.name === "escape") {
|
|
53331
53643
|
if (searchQuery) {
|
|
53332
53644
|
setSearchQuery("");
|
|
53645
|
+
setFocusedIndex(0);
|
|
53333
53646
|
return true;
|
|
53334
53647
|
}
|
|
53335
53648
|
if (onCancel) {
|
|
@@ -53338,16 +53651,16 @@ function ModelPicker({
|
|
|
53338
53651
|
}
|
|
53339
53652
|
return false;
|
|
53340
53653
|
}
|
|
53341
|
-
|
|
53654
|
+
const currentItem = navigationItems[focusedIndex];
|
|
53655
|
+
if (key.name === "space" && currentItem?.type === "reasoning" && onReasoningToggle && thinkingSupported) {
|
|
53342
53656
|
onReasoningToggle(!reasoningEnabled);
|
|
53343
53657
|
return true;
|
|
53344
53658
|
}
|
|
53345
|
-
if (key.name === "space" && onOpenAIReasoningEffortChange && openAIReasoningSupported) {
|
|
53659
|
+
if (key.name === "space" && currentItem?.type === "openai-reasoning" && onOpenAIReasoningEffortChange && openAIReasoningSupported) {
|
|
53346
53660
|
cycleOpenAIReasoningEffort();
|
|
53347
53661
|
return true;
|
|
53348
53662
|
}
|
|
53349
53663
|
if (key.name === "return") {
|
|
53350
|
-
const currentItem = navigationItems[focusedIndex];
|
|
53351
53664
|
if (!currentItem)
|
|
53352
53665
|
return false;
|
|
53353
53666
|
if (currentItem.type === "local-input") {
|
|
@@ -53369,17 +53682,20 @@ function ModelPicker({
|
|
|
53369
53682
|
}
|
|
53370
53683
|
return next;
|
|
53371
53684
|
});
|
|
53372
|
-
} else {
|
|
53685
|
+
} else if (currentItem.type === "model" || currentItem.type === "recent-model") {
|
|
53686
|
+
onSelectModel(currentItem.model);
|
|
53373
53687
|
onConfirm?.();
|
|
53374
53688
|
}
|
|
53375
53689
|
return true;
|
|
53376
53690
|
}
|
|
53377
53691
|
if (key.name === "left" || key.name === "right") {
|
|
53378
|
-
|
|
53379
|
-
|
|
53692
|
+
if (isSearching)
|
|
53693
|
+
return false;
|
|
53694
|
+
const currentItem2 = navigationItems[focusedIndex];
|
|
53695
|
+
if (!currentItem2 || currentItem2.type === "recent-model" || currentItem2.type === "reasoning" || currentItem2.type === "openai-reasoning") {
|
|
53380
53696
|
return false;
|
|
53381
53697
|
}
|
|
53382
|
-
const targetProvider =
|
|
53698
|
+
const targetProvider = currentItem2.type === "provider" ? currentItem2.provider : currentItem2.type === "model" ? currentItem2.model.provider : "local";
|
|
53383
53699
|
if (key.name === "left") {
|
|
53384
53700
|
setExpandedProviders((prev) => {
|
|
53385
53701
|
const next = new Set(prev);
|
|
@@ -53395,13 +53711,6 @@ function ModelPicker({
|
|
|
53395
53711
|
}
|
|
53396
53712
|
return true;
|
|
53397
53713
|
}
|
|
53398
|
-
if (key.sequence && key.sequence.length === 1 && /[a-zA-Z0-9\-_.]/.test(key.sequence)) {
|
|
53399
|
-
setSearchQuery((prev) => prev + key.sequence);
|
|
53400
|
-
if (!searchQuery) {
|
|
53401
|
-
setExpandedProviders(new Set(providerOrder));
|
|
53402
|
-
}
|
|
53403
|
-
return true;
|
|
53404
|
-
}
|
|
53405
53714
|
return false;
|
|
53406
53715
|
}, [
|
|
53407
53716
|
focused,
|
|
@@ -53418,7 +53727,8 @@ function ModelPicker({
|
|
|
53418
53727
|
thinkingSupported,
|
|
53419
53728
|
onOpenAIReasoningEffortChange,
|
|
53420
53729
|
openAIReasoningSupported,
|
|
53421
|
-
cycleOpenAIReasoningEffort
|
|
53730
|
+
cycleOpenAIReasoningEffort,
|
|
53731
|
+
isSearching
|
|
53422
53732
|
]);
|
|
53423
53733
|
useKeyboard((key) => {
|
|
53424
53734
|
const handled = handleKeyboard(key);
|
|
@@ -53427,7 +53737,11 @@ function ModelPicker({
|
|
|
53427
53737
|
}
|
|
53428
53738
|
});
|
|
53429
53739
|
const isProviderFocused = (provider) => navigationItems[focusedIndex]?.type === "provider" && navigationItems[focusedIndex].provider === provider;
|
|
53430
|
-
const isModelFocused = (modelId
|
|
53740
|
+
const isModelFocused = (modelId, recent = false) => {
|
|
53741
|
+
const item = navigationItems[focusedIndex];
|
|
53742
|
+
const expectedType = recent ? "recent-model" : "model";
|
|
53743
|
+
return item?.type === expectedType && item.model.id === modelId;
|
|
53744
|
+
};
|
|
53431
53745
|
const isLocalFieldFocused = (field) => navigationItems[focusedIndex]?.type === "local-input" && navigationItems[focusedIndex].field === field;
|
|
53432
53746
|
return /* @__PURE__ */ jsxDEV4("box", {
|
|
53433
53747
|
flexDirection: "column",
|
|
@@ -53438,21 +53752,42 @@ function ModelPicker({
|
|
|
53438
53752
|
children: [
|
|
53439
53753
|
/* @__PURE__ */ jsxDEV4("box", {
|
|
53440
53754
|
flexShrink: 0,
|
|
53441
|
-
|
|
53442
|
-
|
|
53443
|
-
|
|
53755
|
+
marginBottom: 1,
|
|
53756
|
+
children: [
|
|
53757
|
+
/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53444
53758
|
children: [
|
|
53445
|
-
|
|
53446
|
-
|
|
53759
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
53760
|
+
fg: colors2.primary,
|
|
53761
|
+
children: "Search "
|
|
53762
|
+
}, undefined, false, undefined, this),
|
|
53763
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
53764
|
+
flexGrow: 1,
|
|
53765
|
+
value: searchQuery,
|
|
53766
|
+
onInput: (value) => {
|
|
53767
|
+
setSearchQuery(value);
|
|
53768
|
+
setFocusedIndex(0);
|
|
53769
|
+
},
|
|
53770
|
+
focused: focused && editingLocalField === null,
|
|
53771
|
+
placeholder: "family, model name, or provider...",
|
|
53772
|
+
textColor: colors2.text,
|
|
53773
|
+
focusedTextColor: colors2.text,
|
|
53774
|
+
backgroundColor: "transparent",
|
|
53775
|
+
cursorColor: colors2.textMuted
|
|
53776
|
+
}, undefined, false, undefined, this)
|
|
53447
53777
|
]
|
|
53448
|
-
}, undefined, true, undefined, this)
|
|
53449
|
-
|
|
53450
|
-
|
|
53451
|
-
|
|
53452
|
-
|
|
53778
|
+
}, undefined, true, undefined, this),
|
|
53779
|
+
isSearching && /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53780
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53781
|
+
fg: colors2.primary,
|
|
53782
|
+
children: [
|
|
53783
|
+
"Results (",
|
|
53784
|
+
filteredModels.length,
|
|
53785
|
+
")"
|
|
53786
|
+
]
|
|
53787
|
+
}, undefined, true, undefined, this)
|
|
53453
53788
|
}, undefined, false, undefined, this)
|
|
53454
|
-
|
|
53455
|
-
}, undefined,
|
|
53789
|
+
]
|
|
53790
|
+
}, undefined, true, undefined, this),
|
|
53456
53791
|
/* @__PURE__ */ jsxDEV4("scrollbox", {
|
|
53457
53792
|
ref: scrollBoxRef,
|
|
53458
53793
|
style: {
|
|
@@ -53460,170 +53795,240 @@ function ModelPicker({
|
|
|
53460
53795
|
flexShrink: 1,
|
|
53461
53796
|
width: "100%",
|
|
53462
53797
|
overflow: "hidden",
|
|
53463
|
-
maxHeight: navigationItems.length
|
|
53798
|
+
maxHeight: Math.max(1, navigationItems.length + (!isSearching && recentModels.length > 0 ? 1 : 0))
|
|
53464
53799
|
},
|
|
53465
53800
|
contentOptions: {
|
|
53466
53801
|
flexDirection: "column"
|
|
53467
53802
|
},
|
|
53468
53803
|
scrollbarOptions: {
|
|
53469
|
-
|
|
53804
|
+
trackOptions: {
|
|
53805
|
+
foregroundColor: colors2.textMuted,
|
|
53806
|
+
backgroundColor: colors2.backgroundElement
|
|
53807
|
+
}
|
|
53470
53808
|
}
|
|
53471
53809
|
},
|
|
53472
53810
|
stickyScroll: false,
|
|
53473
|
-
children:
|
|
53474
|
-
|
|
53475
|
-
|
|
53476
|
-
|
|
53477
|
-
|
|
53478
|
-
|
|
53479
|
-
|
|
53480
|
-
|
|
53481
|
-
|
|
53482
|
-
|
|
53811
|
+
children: [
|
|
53812
|
+
!isSearching && recentModels.length > 0 && /* @__PURE__ */ jsxDEV4(Fragment, {
|
|
53813
|
+
children: [
|
|
53814
|
+
/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53815
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53816
|
+
fg: colors2.primary,
|
|
53817
|
+
children: "Recent"
|
|
53818
|
+
}, undefined, false, undefined, this)
|
|
53819
|
+
}, undefined, false, undefined, this),
|
|
53820
|
+
recentModels.map((model) => {
|
|
53821
|
+
const isSelected = model.id === selectedModel.id;
|
|
53822
|
+
const isFocused = isModelFocused(model.id, true);
|
|
53823
|
+
return /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53824
|
+
id: `recent-model-${model.id}`,
|
|
53825
|
+
backgroundColor: isFocused ? colors2.backgroundSelected : undefined,
|
|
53826
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53827
|
+
children: [
|
|
53828
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53829
|
+
fg: isFocused ? colors2.primary : colors2.text,
|
|
53830
|
+
children: [
|
|
53831
|
+
isSelected ? "●" : "○",
|
|
53832
|
+
" ",
|
|
53833
|
+
model.name
|
|
53834
|
+
]
|
|
53835
|
+
}, undefined, true, undefined, this),
|
|
53836
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53837
|
+
fg: colors2.textMuted,
|
|
53838
|
+
children: ` ${getProviderDisplayName(model.provider)}`
|
|
53839
|
+
}, undefined, false, undefined, this)
|
|
53840
|
+
]
|
|
53841
|
+
}, undefined, true, undefined, this)
|
|
53842
|
+
}, `recent-${model.id}`, false, undefined, this);
|
|
53843
|
+
})
|
|
53844
|
+
]
|
|
53845
|
+
}, undefined, true, undefined, this),
|
|
53846
|
+
isSearching && (filteredModels.length === 0 ? /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53847
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53848
|
+
fg: colors2.textMuted,
|
|
53849
|
+
children: "No matching models"
|
|
53850
|
+
}, undefined, false, undefined, this)
|
|
53851
|
+
}, undefined, false, undefined, this) : filteredModels.map((model) => {
|
|
53852
|
+
const isSelected = model.id === selectedModel.id;
|
|
53853
|
+
const isFocused = isModelFocused(model.id);
|
|
53854
|
+
return /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53855
|
+
id: `model-${model.id}`,
|
|
53856
|
+
backgroundColor: isFocused ? colors2.backgroundSelected : undefined,
|
|
53483
53857
|
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53484
|
-
fg: isFocused ? colors2.primary : isExpanded ? colors2.text : colors2.textMuted,
|
|
53485
53858
|
children: [
|
|
53486
|
-
|
|
53487
|
-
|
|
53488
|
-
|
|
53489
|
-
|
|
53859
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53860
|
+
fg: isFocused ? colors2.primary : colors2.text,
|
|
53861
|
+
children: [
|
|
53862
|
+
isSelected ? "●" : "○",
|
|
53863
|
+
" ",
|
|
53864
|
+
model.name
|
|
53865
|
+
]
|
|
53866
|
+
}, undefined, true, undefined, this),
|
|
53867
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53868
|
+
fg: colors2.textMuted,
|
|
53869
|
+
children: ` ${getProviderDisplayName(model.provider)}`
|
|
53870
|
+
}, undefined, false, undefined, this)
|
|
53490
53871
|
]
|
|
53491
53872
|
}, undefined, true, undefined, this)
|
|
53492
|
-
},
|
|
53493
|
-
|
|
53494
|
-
|
|
53495
|
-
|
|
53496
|
-
|
|
53497
|
-
|
|
53498
|
-
|
|
53499
|
-
|
|
53873
|
+
}, model.id, false, undefined, this);
|
|
53874
|
+
})),
|
|
53875
|
+
providerOrder.flatMap((provider) => {
|
|
53876
|
+
if (isSearching)
|
|
53877
|
+
return [];
|
|
53878
|
+
const isExpanded = expandedProviders.has(provider);
|
|
53879
|
+
const providerName = getProviderDisplayName(provider);
|
|
53880
|
+
const isFocused = isProviderFocused(provider);
|
|
53881
|
+
if (provider === "local") {
|
|
53882
|
+
const localModels = groupedModels.local;
|
|
53883
|
+
const modelCount = localModels?.length ?? 0;
|
|
53884
|
+
const elements2 = [];
|
|
53885
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53886
|
+
id: "provider-local",
|
|
53887
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53888
|
+
fg: isFocused ? colors2.primary : isExpanded ? colors2.text : colors2.textMuted,
|
|
53500
53889
|
children: [
|
|
53501
|
-
|
|
53502
|
-
|
|
53503
|
-
|
|
53504
|
-
|
|
53505
|
-
/* @__PURE__ */ jsxDEV4("input", {
|
|
53506
|
-
focused: true,
|
|
53507
|
-
value: localUrl,
|
|
53508
|
-
backgroundColor: "transparent",
|
|
53509
|
-
cursorColor: colors2.textMuted,
|
|
53510
|
-
onInput: (v) => setLocalUrl(typeof v === "string" ? v : ""),
|
|
53511
|
-
onPaste: (event) => {
|
|
53512
|
-
const cleaned = getPasteText(event).replace(/\r?\n/g, "");
|
|
53513
|
-
setLocalUrl((prev) => `${prev}${cleaned}`);
|
|
53514
|
-
},
|
|
53515
|
-
onSubmit: finishEditing
|
|
53516
|
-
}, undefined, false, undefined, this)
|
|
53890
|
+
isFocused ? "❯" : isExpanded ? "▾" : "▸",
|
|
53891
|
+
" ",
|
|
53892
|
+
providerName,
|
|
53893
|
+
modelCount > 0 ? ` (${modelCount})` : ""
|
|
53517
53894
|
]
|
|
53518
|
-
},
|
|
53519
|
-
}
|
|
53520
|
-
|
|
53521
|
-
|
|
53522
|
-
|
|
53523
|
-
|
|
53524
|
-
|
|
53525
|
-
|
|
53526
|
-
|
|
53527
|
-
|
|
53528
|
-
|
|
53529
|
-
|
|
53530
|
-
|
|
53531
|
-
|
|
53532
|
-
|
|
53533
|
-
|
|
53534
|
-
|
|
53535
|
-
|
|
53536
|
-
|
|
53537
|
-
|
|
53538
|
-
|
|
53539
|
-
|
|
53540
|
-
|
|
53541
|
-
|
|
53542
|
-
|
|
53543
|
-
|
|
53544
|
-
|
|
53545
|
-
|
|
53546
|
-
|
|
53547
|
-
|
|
53548
|
-
|
|
53549
|
-
|
|
53550
|
-
|
|
53895
|
+
}, undefined, true, undefined, this)
|
|
53896
|
+
}, "local", false, undefined, this));
|
|
53897
|
+
if (isExpanded) {
|
|
53898
|
+
const isUrlFocused = isLocalFieldFocused("url");
|
|
53899
|
+
const isUrlEditing = editingLocalField === "url";
|
|
53900
|
+
if (isUrlEditing) {
|
|
53901
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53902
|
+
id: "local-input-url",
|
|
53903
|
+
paddingLeft: 2,
|
|
53904
|
+
children: [
|
|
53905
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
53906
|
+
fg: colors2.primary,
|
|
53907
|
+
children: " URL: "
|
|
53908
|
+
}, undefined, false, undefined, this),
|
|
53909
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
53910
|
+
focused: true,
|
|
53911
|
+
value: localUrl,
|
|
53912
|
+
backgroundColor: "transparent",
|
|
53913
|
+
cursorColor: colors2.textMuted,
|
|
53914
|
+
onInput: (v) => setLocalUrl(typeof v === "string" ? v : ""),
|
|
53915
|
+
onPaste: (event) => {
|
|
53916
|
+
const cleaned = getPasteText(event).replace(/\r?\n/g, "");
|
|
53917
|
+
setLocalUrl((prev) => `${prev}${cleaned}`);
|
|
53918
|
+
},
|
|
53919
|
+
onSubmit: finishEditing
|
|
53920
|
+
}, undefined, false, undefined, this)
|
|
53921
|
+
]
|
|
53922
|
+
}, "local-url", true, undefined, this));
|
|
53923
|
+
} else {
|
|
53924
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53925
|
+
id: "local-input-url",
|
|
53926
|
+
paddingLeft: 2,
|
|
53927
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53928
|
+
fg: isUrlFocused ? colors2.primary : colors2.textMuted,
|
|
53929
|
+
children: ` URL: ${localUrl || "(press Enter to set)"}`
|
|
53551
53930
|
}, undefined, false, undefined, this)
|
|
53552
|
-
|
|
53553
|
-
}
|
|
53554
|
-
|
|
53555
|
-
|
|
53556
|
-
|
|
53557
|
-
|
|
53558
|
-
|
|
53559
|
-
|
|
53560
|
-
children:
|
|
53561
|
-
|
|
53562
|
-
|
|
53563
|
-
|
|
53564
|
-
|
|
53565
|
-
|
|
53566
|
-
|
|
53567
|
-
|
|
53931
|
+
}, "local-url", false, undefined, this));
|
|
53932
|
+
}
|
|
53933
|
+
const isModelFieldFocused = isLocalFieldFocused("model");
|
|
53934
|
+
const isModelEditing = editingLocalField === "model";
|
|
53935
|
+
if (isModelEditing) {
|
|
53936
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53937
|
+
id: "local-input-model",
|
|
53938
|
+
paddingLeft: 2,
|
|
53939
|
+
children: [
|
|
53940
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
53941
|
+
fg: colors2.primary,
|
|
53942
|
+
children: " Model: "
|
|
53943
|
+
}, undefined, false, undefined, this),
|
|
53944
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
53945
|
+
focused: true,
|
|
53946
|
+
value: localModelName,
|
|
53947
|
+
backgroundColor: "transparent",
|
|
53948
|
+
cursorColor: colors2.textMuted,
|
|
53949
|
+
onInput: (v) => setLocalModelName(typeof v === "string" ? v : ""),
|
|
53950
|
+
onPaste: (event) => {
|
|
53951
|
+
const cleaned = getPasteText(event).replace(/\r?\n/g, "");
|
|
53952
|
+
setLocalModelName((prev) => `${prev}${cleaned}`);
|
|
53953
|
+
},
|
|
53954
|
+
onSubmit: finishEditing
|
|
53955
|
+
}, undefined, false, undefined, this)
|
|
53956
|
+
]
|
|
53957
|
+
}, "local-model", true, undefined, this));
|
|
53958
|
+
} else {
|
|
53568
53959
|
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53569
|
-
id:
|
|
53960
|
+
id: "local-input-model",
|
|
53570
53961
|
paddingLeft: 2,
|
|
53571
53962
|
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53572
|
-
fg:
|
|
53573
|
-
children:
|
|
53574
|
-
|
|
53575
|
-
|
|
53576
|
-
|
|
53577
|
-
|
|
53578
|
-
|
|
53579
|
-
|
|
53963
|
+
fg: isModelFieldFocused ? colors2.primary : colors2.textMuted,
|
|
53964
|
+
children: ` Model: ${localModelName || "(press Enter to set)"}`
|
|
53965
|
+
}, undefined, false, undefined, this)
|
|
53966
|
+
}, "local-model", false, undefined, this));
|
|
53967
|
+
}
|
|
53968
|
+
if (localModels) {
|
|
53969
|
+
for (const m of localModels) {
|
|
53970
|
+
const isSelected = m.id === selectedModel.id;
|
|
53971
|
+
const isMFocused = isModelFocused(m.id);
|
|
53972
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53973
|
+
id: `model-${m.id}`,
|
|
53974
|
+
paddingLeft: 2,
|
|
53975
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53976
|
+
fg: isMFocused ? colors2.primary : colors2.textMuted,
|
|
53977
|
+
children: [
|
|
53978
|
+
isSelected ? "●" : "○",
|
|
53979
|
+
" ",
|
|
53980
|
+
m.name
|
|
53981
|
+
]
|
|
53982
|
+
}, undefined, true, undefined, this)
|
|
53983
|
+
}, m.id, false, undefined, this));
|
|
53984
|
+
}
|
|
53580
53985
|
}
|
|
53581
53986
|
}
|
|
53987
|
+
return elements2;
|
|
53582
53988
|
}
|
|
53583
|
-
|
|
53584
|
-
|
|
53585
|
-
|
|
53586
|
-
|
|
53587
|
-
|
|
53588
|
-
|
|
53589
|
-
|
|
53590
|
-
|
|
53591
|
-
|
|
53592
|
-
|
|
53593
|
-
|
|
53594
|
-
|
|
53595
|
-
|
|
53596
|
-
|
|
53597
|
-
|
|
53598
|
-
|
|
53599
|
-
|
|
53600
|
-
|
|
53601
|
-
|
|
53602
|
-
|
|
53603
|
-
|
|
53604
|
-
|
|
53605
|
-
|
|
53606
|
-
|
|
53607
|
-
|
|
53608
|
-
|
|
53609
|
-
|
|
53610
|
-
|
|
53611
|
-
|
|
53612
|
-
|
|
53613
|
-
|
|
53614
|
-
|
|
53615
|
-
|
|
53616
|
-
|
|
53617
|
-
|
|
53618
|
-
|
|
53619
|
-
|
|
53620
|
-
}, m.id, false, undefined, this));
|
|
53989
|
+
const models = groupedModels[provider];
|
|
53990
|
+
if (!models || models.length === 0)
|
|
53991
|
+
return [];
|
|
53992
|
+
const elements = [];
|
|
53993
|
+
elements.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53994
|
+
id: `provider-${provider}`,
|
|
53995
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53996
|
+
fg: isFocused ? colors2.primary : isExpanded ? colors2.text : colors2.textMuted,
|
|
53997
|
+
children: [
|
|
53998
|
+
isFocused ? "❯" : isExpanded ? "▾" : "▸",
|
|
53999
|
+
" ",
|
|
54000
|
+
providerName,
|
|
54001
|
+
" (",
|
|
54002
|
+
models.length,
|
|
54003
|
+
")"
|
|
54004
|
+
]
|
|
54005
|
+
}, undefined, true, undefined, this)
|
|
54006
|
+
}, provider, false, undefined, this));
|
|
54007
|
+
if (isExpanded) {
|
|
54008
|
+
for (const m of models) {
|
|
54009
|
+
const isSelected = m.id === selectedModel.id;
|
|
54010
|
+
const isMFocused = isModelFocused(m.id);
|
|
54011
|
+
const isDefault = m.id === "claude-haiku-4-5" || m.id === "gpt-4o-mini";
|
|
54012
|
+
elements.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
54013
|
+
id: `model-${m.id}`,
|
|
54014
|
+
paddingLeft: 2,
|
|
54015
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
54016
|
+
fg: isMFocused ? colors2.primary : colors2.textMuted,
|
|
54017
|
+
children: [
|
|
54018
|
+
isSelected ? "●" : "○",
|
|
54019
|
+
" ",
|
|
54020
|
+
m.name,
|
|
54021
|
+
isDefault && !isModelUserSelected && isSelected ? " [default]" : ""
|
|
54022
|
+
]
|
|
54023
|
+
}, undefined, true, undefined, this)
|
|
54024
|
+
}, m.id, false, undefined, this));
|
|
54025
|
+
}
|
|
53621
54026
|
}
|
|
53622
|
-
|
|
53623
|
-
|
|
53624
|
-
|
|
53625
|
-
},
|
|
53626
|
-
onReasoningToggle && thinkingSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
54027
|
+
return elements;
|
|
54028
|
+
})
|
|
54029
|
+
]
|
|
54030
|
+
}, isSearching ? "search-results" : "model-browser", true, undefined, this),
|
|
54031
|
+
!isSearching && onReasoningToggle && thinkingSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
53627
54032
|
flexShrink: 0,
|
|
53628
54033
|
paddingTop: 1,
|
|
53629
54034
|
children: /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
@@ -53637,7 +54042,7 @@ function ModelPicker({
|
|
|
53637
54042
|
}, undefined, true, undefined, this)
|
|
53638
54043
|
}, undefined, false, undefined, this)
|
|
53639
54044
|
}, undefined, false, undefined, this),
|
|
53640
|
-
onOpenAIReasoningEffortChange && openAIReasoningSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
54045
|
+
!isSearching && onOpenAIReasoningEffortChange && openAIReasoningSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
53641
54046
|
flexShrink: 0,
|
|
53642
54047
|
paddingTop: 1,
|
|
53643
54048
|
children: /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
@@ -53737,7 +54142,7 @@ function ConfigView({ config: config2, onBack, onStart }) {
|
|
|
53737
54142
|
return;
|
|
53738
54143
|
}
|
|
53739
54144
|
});
|
|
53740
|
-
const handleModelSelect =
|
|
54145
|
+
const handleModelSelect = useCallback6((model) => {
|
|
53741
54146
|
setSelectedModel(model);
|
|
53742
54147
|
setIsModelUserSelected(true);
|
|
53743
54148
|
}, []);
|
|
@@ -53913,7 +54318,7 @@ function isValidUrl(url) {
|
|
|
53913
54318
|
}
|
|
53914
54319
|
|
|
53915
54320
|
// src/tui/components/chat/home-view.tsx
|
|
53916
|
-
import { useCallback as
|
|
54321
|
+
import { useCallback as useCallback13, useEffect as useEffect11, useState as useState18 } from "react";
|
|
53917
54322
|
|
|
53918
54323
|
// src/core/history.ts
|
|
53919
54324
|
init_storage();
|
|
@@ -53970,7 +54375,7 @@ function getEntries() {
|
|
|
53970
54375
|
// src/tui/context/command.tsx
|
|
53971
54376
|
import {
|
|
53972
54377
|
createContext as createContext7,
|
|
53973
|
-
useCallback as
|
|
54378
|
+
useCallback as useCallback8,
|
|
53974
54379
|
useContext as useContext7,
|
|
53975
54380
|
useEffect as useEffect5,
|
|
53976
54381
|
useMemo as useMemo8,
|
|
@@ -54365,7 +54770,7 @@ function deobfuscate(input) {
|
|
|
54365
54770
|
return output;
|
|
54366
54771
|
}
|
|
54367
54772
|
// src/tui/command-registry.ts
|
|
54368
|
-
|
|
54773
|
+
init_config();
|
|
54369
54774
|
|
|
54370
54775
|
// src/tui/utils/command-flags.ts
|
|
54371
54776
|
import { readFileSync } from "node:fs";
|
|
@@ -55268,7 +55673,7 @@ var useRoute = () => {
|
|
|
55268
55673
|
// src/tui/context/toast.tsx
|
|
55269
55674
|
import {
|
|
55270
55675
|
createContext as createContext6,
|
|
55271
|
-
useCallback as
|
|
55676
|
+
useCallback as useCallback7,
|
|
55272
55677
|
useContext as useContext6,
|
|
55273
55678
|
useMemo as useMemo7,
|
|
55274
55679
|
useState as useState8
|
|
@@ -55283,10 +55688,10 @@ var DEFAULT_DURATION = {
|
|
|
55283
55688
|
};
|
|
55284
55689
|
function ToastProvider({ children }) {
|
|
55285
55690
|
const [toasts, setToasts] = useState8([]);
|
|
55286
|
-
const dismiss =
|
|
55691
|
+
const dismiss = useCallback7((id) => {
|
|
55287
55692
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
55288
55693
|
}, []);
|
|
55289
|
-
const toast =
|
|
55694
|
+
const toast = useCallback7((message, variant = "default", duration) => {
|
|
55290
55695
|
const id = nextId++;
|
|
55291
55696
|
const ms = duration ?? DEFAULT_DURATION[variant];
|
|
55292
55697
|
setToasts((prev) => [...prev, { id, message, variant, duration: ms }]);
|
|
@@ -55309,11 +55714,11 @@ function useToast() {
|
|
|
55309
55714
|
import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
|
|
55310
55715
|
var CommandContext = createContext7(null);
|
|
55311
55716
|
function useCommand() {
|
|
55312
|
-
const
|
|
55313
|
-
if (!
|
|
55717
|
+
const context2 = useContext7(CommandContext);
|
|
55718
|
+
if (!context2) {
|
|
55314
55719
|
throw new Error("useCommand must be used within CommandProvider");
|
|
55315
55720
|
}
|
|
55316
|
-
return
|
|
55721
|
+
return context2;
|
|
55317
55722
|
}
|
|
55318
55723
|
function CommandProvider({
|
|
55319
55724
|
children,
|
|
@@ -55372,7 +55777,7 @@ function CommandProvider({
|
|
|
55372
55777
|
obfuscation,
|
|
55373
55778
|
toast
|
|
55374
55779
|
]);
|
|
55375
|
-
const refreshSkills =
|
|
55780
|
+
const refreshSkills = useCallback8(async () => {
|
|
55376
55781
|
await registry.refresh();
|
|
55377
55782
|
setRegistryVersion((v) => v + 1);
|
|
55378
55783
|
}, [registry]);
|
|
@@ -55388,7 +55793,7 @@ function CommandProvider({
|
|
|
55388
55793
|
}
|
|
55389
55794
|
return router2;
|
|
55390
55795
|
}, []);
|
|
55391
|
-
const resolveSkillContent =
|
|
55796
|
+
const resolveSkillContent = useCallback8((input) => {
|
|
55392
55797
|
const trimmed = input.trim().replace(/^\/+/, "").toLowerCase();
|
|
55393
55798
|
const entry = registry.get(trimmed);
|
|
55394
55799
|
if (entry) {
|
|
@@ -55458,7 +55863,7 @@ function CommandProvider({
|
|
|
55458
55863
|
}
|
|
55459
55864
|
return names;
|
|
55460
55865
|
}, []);
|
|
55461
|
-
const executeCommand =
|
|
55866
|
+
const executeCommand = useCallback8(async (input) => {
|
|
55462
55867
|
return await router.execute(input, ctx3);
|
|
55463
55868
|
}, [router, ctx3]);
|
|
55464
55869
|
const value = useMemo8(() => ({
|
|
@@ -55493,7 +55898,7 @@ function CommandProvider({
|
|
|
55493
55898
|
import { useKeyboard as useKeyboard3, useRenderer as useRenderer3 } from "@opentui/react";
|
|
55494
55899
|
import {
|
|
55495
55900
|
createContext as createContext9,
|
|
55496
|
-
useCallback as
|
|
55901
|
+
useCallback as useCallback9,
|
|
55497
55902
|
useContext as useContext9,
|
|
55498
55903
|
useRef as useRef4,
|
|
55499
55904
|
useState as useState10
|
|
@@ -55578,7 +55983,7 @@ function DialogProvider({ children }) {
|
|
|
55578
55983
|
const [externalDialogOpen, setExternalDialogOpen] = useState10(false);
|
|
55579
55984
|
const renderer = useRenderer3();
|
|
55580
55985
|
const focusRef = useRef4(null);
|
|
55581
|
-
const refocus =
|
|
55986
|
+
const refocus = useCallback9(() => {
|
|
55582
55987
|
setTimeout(() => {
|
|
55583
55988
|
const focus = focusRef.current;
|
|
55584
55989
|
if (!focus)
|
|
@@ -55600,7 +56005,7 @@ function DialogProvider({ children }) {
|
|
|
55600
56005
|
focus.focus();
|
|
55601
56006
|
}, 1);
|
|
55602
56007
|
}, [renderer]);
|
|
55603
|
-
const clear =
|
|
56008
|
+
const clear = useCallback9(() => {
|
|
55604
56009
|
for (const item of stack) {
|
|
55605
56010
|
if (item.onClose)
|
|
55606
56011
|
item.onClose();
|
|
@@ -55609,7 +56014,7 @@ function DialogProvider({ children }) {
|
|
|
55609
56014
|
setStack([]);
|
|
55610
56015
|
refocus();
|
|
55611
56016
|
}, [stack, refocus]);
|
|
55612
|
-
const replace =
|
|
56017
|
+
const replace = useCallback9((element, options) => {
|
|
55613
56018
|
if (stack.length === 0) {
|
|
55614
56019
|
focusRef.current = renderer.currentFocusedRenderable;
|
|
55615
56020
|
}
|
|
@@ -55673,7 +56078,7 @@ function useDialog() {
|
|
|
55673
56078
|
// src/tui/context/focus.tsx
|
|
55674
56079
|
import {
|
|
55675
56080
|
createContext as createContext10,
|
|
55676
|
-
useCallback as
|
|
56081
|
+
useCallback as useCallback10,
|
|
55677
56082
|
useContext as useContext10,
|
|
55678
56083
|
useRef as useRef5
|
|
55679
56084
|
} from "react";
|
|
@@ -55681,17 +56086,17 @@ import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
|
|
|
55681
56086
|
var FocusContext = createContext10(undefined);
|
|
55682
56087
|
function FocusProvider({ children }) {
|
|
55683
56088
|
const promptRef = useRef5(null);
|
|
55684
|
-
const refocusPrompt =
|
|
56089
|
+
const refocusPrompt = useCallback10(() => {
|
|
55685
56090
|
setTimeout(() => {
|
|
55686
56091
|
promptRef.current?.focus();
|
|
55687
56092
|
}, 1);
|
|
55688
56093
|
}, []);
|
|
55689
|
-
const focusPrompt =
|
|
55690
|
-
const blurPrompt =
|
|
55691
|
-
const resetPrompt =
|
|
55692
|
-
const setPromptValue =
|
|
55693
|
-
const getPromptValue =
|
|
55694
|
-
const registerPromptRef =
|
|
56094
|
+
const focusPrompt = useCallback10(() => promptRef.current?.focus(), []);
|
|
56095
|
+
const blurPrompt = useCallback10(() => promptRef.current?.blur(), []);
|
|
56096
|
+
const resetPrompt = useCallback10(() => promptRef.current?.reset(), []);
|
|
56097
|
+
const setPromptValue = useCallback10((value) => promptRef.current?.setValue(value), []);
|
|
56098
|
+
const getPromptValue = useCallback10(() => promptRef.current?.getValue() ?? "", []);
|
|
56099
|
+
const registerPromptRef = useCallback10((ref) => {
|
|
55695
56100
|
promptRef.current = ref;
|
|
55696
56101
|
}, []);
|
|
55697
56102
|
return /* @__PURE__ */ jsxDEV12(FocusContext.Provider, {
|
|
@@ -55709,17 +56114,17 @@ function FocusProvider({ children }) {
|
|
|
55709
56114
|
}, undefined, false, undefined, this);
|
|
55710
56115
|
}
|
|
55711
56116
|
function useFocus() {
|
|
55712
|
-
const
|
|
55713
|
-
if (!
|
|
56117
|
+
const context2 = useContext10(FocusContext);
|
|
56118
|
+
if (!context2) {
|
|
55714
56119
|
throw new Error("useFocus must be used within FocusProvider");
|
|
55715
56120
|
}
|
|
55716
|
-
return
|
|
56121
|
+
return context2;
|
|
55717
56122
|
}
|
|
55718
56123
|
|
|
55719
56124
|
// src/tui/context/input.tsx
|
|
55720
56125
|
import {
|
|
55721
56126
|
createContext as createContext11,
|
|
55722
|
-
useCallback as
|
|
56127
|
+
useCallback as useCallback11,
|
|
55723
56128
|
useContext as useContext11,
|
|
55724
56129
|
useState as useState11
|
|
55725
56130
|
} from "react";
|
|
@@ -55727,7 +56132,7 @@ import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
|
|
|
55727
56132
|
var InputContext = createContext11(undefined);
|
|
55728
56133
|
function InputProvider({ children }) {
|
|
55729
56134
|
const [inputValue, setInputValue] = useState11("");
|
|
55730
|
-
const clearInput =
|
|
56135
|
+
const clearInput = useCallback11(() => {
|
|
55731
56136
|
setInputValue("");
|
|
55732
56137
|
}, []);
|
|
55733
56138
|
return /* @__PURE__ */ jsxDEV13(InputContext.Provider, {
|
|
@@ -55741,11 +56146,11 @@ function InputProvider({ children }) {
|
|
|
55741
56146
|
}, undefined, false, undefined, this);
|
|
55742
56147
|
}
|
|
55743
56148
|
function useInput() {
|
|
55744
|
-
const
|
|
55745
|
-
if (!
|
|
56149
|
+
const context2 = useContext11(InputContext);
|
|
56150
|
+
if (!context2) {
|
|
55746
56151
|
throw new Error("useInput must be used within InputProvider");
|
|
55747
56152
|
}
|
|
55748
|
-
return
|
|
56153
|
+
return context2;
|
|
55749
56154
|
}
|
|
55750
56155
|
|
|
55751
56156
|
// src/tui/components/shared/tool-registry.ts
|
|
@@ -57371,7 +57776,7 @@ function markdownToStyledText(rawContent, colors2) {
|
|
|
57371
57776
|
import {
|
|
57372
57777
|
SyntaxStyle
|
|
57373
57778
|
} from "@opentui/core";
|
|
57374
|
-
import { useCallback as
|
|
57779
|
+
import { useCallback as useCallback12, useMemo as useMemo9, useRef as useRef6 } from "react";
|
|
57375
57780
|
function useMarkdownSyntaxStyle() {
|
|
57376
57781
|
const { colors: colors2 } = useTheme();
|
|
57377
57782
|
return useMemo9(() => SyntaxStyle.fromStyles({
|
|
@@ -57392,7 +57797,7 @@ function useMarkdownSyntaxStyle() {
|
|
|
57392
57797
|
}
|
|
57393
57798
|
function useMarkdownRenderNode() {
|
|
57394
57799
|
const { colors: colors2 } = useTheme();
|
|
57395
|
-
return
|
|
57800
|
+
return useCallback12((token, ctx3) => {
|
|
57396
57801
|
if (token.type === "code") {
|
|
57397
57802
|
const renderable = ctx3.defaultRender();
|
|
57398
57803
|
if (renderable) {
|
|
@@ -58780,7 +59185,7 @@ function isToolMessage(msg) {
|
|
|
58780
59185
|
}
|
|
58781
59186
|
|
|
58782
59187
|
// src/tui/components/shared/tool-renderer.tsx
|
|
58783
|
-
import { jsxDEV as jsxDEV19, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
59188
|
+
import { jsxDEV as jsxDEV19, Fragment as Fragment2 } from "@opentui/react/jsx-dev-runtime";
|
|
58784
59189
|
var TOOLS_WITH_LOG_WINDOW = new Set([
|
|
58785
59190
|
"execute_command",
|
|
58786
59191
|
"run_attack_surface",
|
|
@@ -58843,7 +59248,7 @@ var ToolRenderer = memo2(function ToolRenderer2({
|
|
|
58843
59248
|
children: isPending ? /* @__PURE__ */ jsxDEV19(ShiningText, {
|
|
58844
59249
|
text: summary,
|
|
58845
59250
|
fg: colors2.warning
|
|
58846
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19(
|
|
59251
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19(Fragment2, {
|
|
58847
59252
|
children: [
|
|
58848
59253
|
/* @__PURE__ */ jsxDEV19("text", {
|
|
58849
59254
|
fg: isError ? colors2.error : colors2.success,
|
|
@@ -59990,7 +60395,7 @@ var PromptInput = forwardRef(function PromptInput2({
|
|
|
59990
60395
|
import { useKeyboard as useKeyboard5 } from "@opentui/react";
|
|
59991
60396
|
import { useEffect as useEffect9, useRef as useRef9, useState as useState16 } from "react";
|
|
59992
60397
|
import { jsxDEV as jsxDEV22 } from "@opentui/react/jsx-dev-runtime";
|
|
59993
|
-
var
|
|
60398
|
+
var PROVIDER_DISPLAY_NAMES2 = {
|
|
59994
60399
|
anthropic: "Anthropic",
|
|
59995
60400
|
openai: "OpenAI",
|
|
59996
60401
|
google: "Google",
|
|
@@ -60001,7 +60406,7 @@ var PROVIDER_DISPLAY_NAMES = {
|
|
|
60001
60406
|
inception: "Inception",
|
|
60002
60407
|
local: "Local"
|
|
60003
60408
|
};
|
|
60004
|
-
var providerDisplayName = (p) =>
|
|
60409
|
+
var providerDisplayName = (p) => PROVIDER_DISPLAY_NAMES2[p] ?? p;
|
|
60005
60410
|
function OperatorModeBar({
|
|
60006
60411
|
operatorMode,
|
|
60007
60412
|
modelName,
|
|
@@ -60582,7 +60987,7 @@ function HomeView({ onNavigate, onStartSession }) {
|
|
|
60582
60987
|
useEffect11(() => {
|
|
60583
60988
|
load().then(setCommandHistory);
|
|
60584
60989
|
}, []);
|
|
60585
|
-
const launchOperator =
|
|
60990
|
+
const launchOperator = useCallback13((message, options) => {
|
|
60586
60991
|
const requireApproval = options?.requireApproval ?? true;
|
|
60587
60992
|
route.navigate({
|
|
60588
60993
|
type: "operator",
|
|
@@ -60593,10 +60998,10 @@ function HomeView({ onNavigate, onStartSession }) {
|
|
|
60593
60998
|
}
|
|
60594
60999
|
});
|
|
60595
61000
|
}, [route]);
|
|
60596
|
-
const pushHistory =
|
|
61001
|
+
const pushHistory = useCallback13((entry) => {
|
|
60597
61002
|
push(entry).then(() => setCommandHistory([...getEntries()]));
|
|
60598
61003
|
}, []);
|
|
60599
|
-
const handleSubmit =
|
|
61004
|
+
const handleSubmit = useCallback13((value) => {
|
|
60600
61005
|
if (!value.trim())
|
|
60601
61006
|
return;
|
|
60602
61007
|
pushHistory(value.trim());
|
|
@@ -60608,7 +61013,7 @@ function HomeView({ onNavigate, onStartSession }) {
|
|
|
60608
61013
|
const timer = setTimeout(() => setHintMessage(null), 3000);
|
|
60609
61014
|
return () => clearTimeout(timer);
|
|
60610
61015
|
}, [hintMessage]);
|
|
60611
|
-
const handleCommandExecute =
|
|
61016
|
+
const handleCommandExecute = useCallback13(async (command) => {
|
|
60612
61017
|
const trimmed = command.trim();
|
|
60613
61018
|
pushHistory(trimmed);
|
|
60614
61019
|
const handled = await executeCommand(command);
|
|
@@ -60805,7 +61210,7 @@ function ChatApp({
|
|
|
60805
61210
|
});
|
|
60806
61211
|
}
|
|
60807
61212
|
}, [initialSessionId]);
|
|
60808
|
-
const handleNavigate =
|
|
61213
|
+
const handleNavigate = useCallback14((view, options) => {
|
|
60809
61214
|
if (view === "chat" && options?.sessionId) {
|
|
60810
61215
|
sessions.get(options.sessionId).then((session) => {
|
|
60811
61216
|
if (session) {
|
|
@@ -60817,7 +61222,7 @@ function ChatApp({
|
|
|
60817
61222
|
setCurrentView(view);
|
|
60818
61223
|
}
|
|
60819
61224
|
}, []);
|
|
60820
|
-
const handleStartSession =
|
|
61225
|
+
const handleStartSession = useCallback14(async (directive) => {
|
|
60821
61226
|
const session = await sessions.create({
|
|
60822
61227
|
name: `exploration-${Date.now()}`,
|
|
60823
61228
|
targets: []
|
|
@@ -60826,7 +61231,7 @@ function ChatApp({
|
|
|
60826
61231
|
setInitialDirective(directive);
|
|
60827
61232
|
setCurrentView("chat");
|
|
60828
61233
|
}, []);
|
|
60829
|
-
const handleConfigSubmit =
|
|
61234
|
+
const handleConfigSubmit = useCallback14(async (configData) => {
|
|
60830
61235
|
const hostname = parseHostFromTarget(configData.targetUrl);
|
|
60831
61236
|
const timestamp = new Date().toISOString().split("T")[0];
|
|
60832
61237
|
const sessionName = `${hostname}-${timestamp}`;
|
|
@@ -60849,12 +61254,12 @@ function ChatApp({
|
|
|
60849
61254
|
setSessionModel(configData.model);
|
|
60850
61255
|
setCurrentView("chat");
|
|
60851
61256
|
}, []);
|
|
60852
|
-
const handleExitChat =
|
|
61257
|
+
const handleExitChat = useCallback14(() => {
|
|
60853
61258
|
setCurrentView("home");
|
|
60854
61259
|
setActiveSession(null);
|
|
60855
61260
|
setInitialDirective(undefined);
|
|
60856
61261
|
}, []);
|
|
60857
|
-
const handleBackFromConfig =
|
|
61262
|
+
const handleBackFromConfig = useCallback14(() => {
|
|
60858
61263
|
setCurrentView("home");
|
|
60859
61264
|
}, []);
|
|
60860
61265
|
return /* @__PURE__ */ jsxDEV25("box", {
|
|
@@ -60887,7 +61292,7 @@ function parseHostFromTarget(target) {
|
|
|
60887
61292
|
|
|
60888
61293
|
// src/tui/components/commands/advanced-settings.tsx
|
|
60889
61294
|
import { useKeyboard as useKeyboard6 } from "@opentui/react";
|
|
60890
|
-
import { useCallback as
|
|
61295
|
+
import { useCallback as useCallback15, useState as useState20 } from "react";
|
|
60891
61296
|
|
|
60892
61297
|
// src/tui/components/dialog-layout.tsx
|
|
60893
61298
|
import { jsxDEV as jsxDEV26 } from "@opentui/react/jsx-dev-runtime";
|
|
@@ -60959,7 +61364,7 @@ function AdvancedSettings({ onClose }) {
|
|
|
60959
61364
|
const [saving, setSaving] = useState20(false);
|
|
60960
61365
|
const [error, setError] = useState20(null);
|
|
60961
61366
|
const [draftStrikeMode, setDraftStrikeMode] = useState20(config2.data.strikeMode ?? false);
|
|
60962
|
-
const saveSettings =
|
|
61367
|
+
const saveSettings = useCallback15(async () => {
|
|
60963
61368
|
if (saving)
|
|
60964
61369
|
return;
|
|
60965
61370
|
setSaving(true);
|
|
@@ -61041,9 +61446,9 @@ function AdvancedSettings({ onClose }) {
|
|
|
61041
61446
|
|
|
61042
61447
|
// src/tui/components/commands/auth-flow.tsx
|
|
61043
61448
|
import { useKeyboard as useKeyboard7 } from "@opentui/react";
|
|
61044
|
-
import { useCallback as
|
|
61449
|
+
import { useCallback as useCallback16, useEffect as useEffect13, useRef as useRef11, useState as useState21 } from "react";
|
|
61045
61450
|
init_auth();
|
|
61046
|
-
|
|
61451
|
+
init_config();
|
|
61047
61452
|
|
|
61048
61453
|
// src/tui/utils/open-url.ts
|
|
61049
61454
|
var OPEN_FAILED_MSG = "Couldn't open browser — visit the URL shown instead";
|
|
@@ -61117,7 +61522,7 @@ function AuthFlow({ onClose, hideEsc }) {
|
|
|
61117
61522
|
const goHome = () => {
|
|
61118
61523
|
onClose();
|
|
61119
61524
|
};
|
|
61120
|
-
const cleanup =
|
|
61525
|
+
const cleanup = useCallback16(() => {
|
|
61121
61526
|
abortRef.current?.abort();
|
|
61122
61527
|
abortRef.current = null;
|
|
61123
61528
|
}, []);
|
|
@@ -61678,9 +62083,9 @@ function AuthFlow({ onClose, hideEsc }) {
|
|
|
61678
62083
|
|
|
61679
62084
|
// src/tui/components/commands/credits-flow.tsx
|
|
61680
62085
|
import { useKeyboard as useKeyboard8 } from "@opentui/react";
|
|
61681
|
-
import { useCallback as
|
|
62086
|
+
import { useCallback as useCallback17, useEffect as useEffect14, useState as useState22 } from "react";
|
|
61682
62087
|
init_auth();
|
|
61683
|
-
import { jsxDEV as jsxDEV29, Fragment as
|
|
62088
|
+
import { jsxDEV as jsxDEV29, Fragment as Fragment3 } from "@opentui/react/jsx-dev-runtime";
|
|
61684
62089
|
function CreditsFlow({
|
|
61685
62090
|
onClose,
|
|
61686
62091
|
onOpenAuthDialog
|
|
@@ -61706,7 +62111,7 @@ function CreditsFlow({
|
|
|
61706
62111
|
});
|
|
61707
62112
|
setStep("browser-opened");
|
|
61708
62113
|
};
|
|
61709
|
-
const fetchBalance =
|
|
62114
|
+
const fetchBalance = useCallback17(async () => {
|
|
61710
62115
|
setStep("loading");
|
|
61711
62116
|
setError(null);
|
|
61712
62117
|
try {
|
|
@@ -61816,7 +62221,7 @@ function CreditsFlow({
|
|
|
61816
62221
|
error
|
|
61817
62222
|
]
|
|
61818
62223
|
}, undefined, true, undefined, this)
|
|
61819
|
-
}, undefined, false, undefined, this) : credits ? /* @__PURE__ */ jsxDEV29(
|
|
62224
|
+
}, undefined, false, undefined, this) : credits ? /* @__PURE__ */ jsxDEV29(Fragment3, {
|
|
61820
62225
|
children: [
|
|
61821
62226
|
/* @__PURE__ */ jsxDEV29("box", {
|
|
61822
62227
|
children: /* @__PURE__ */ jsxDEV29("text", {
|
|
@@ -62109,7 +62514,6 @@ function HelpDialog({ onClose }) {
|
|
|
62109
62514
|
// src/tui/components/commands/models-display.tsx
|
|
62110
62515
|
import { useKeyboard as useKeyboard10 } from "@opentui/react";
|
|
62111
62516
|
// src/tui/components/model-picker/ModelPickerDialog.tsx
|
|
62112
|
-
init_ai();
|
|
62113
62517
|
import { jsxDEV as jsxDEV31 } from "@opentui/react/jsx-dev-runtime";
|
|
62114
62518
|
function ModelPickerDialog({ onClose }) {
|
|
62115
62519
|
const { colors: colors2 } = useTheme();
|
|
@@ -62123,17 +62527,9 @@ function ModelPickerDialog({ onClose }) {
|
|
|
62123
62527
|
openAIReasoningEffort,
|
|
62124
62528
|
setOpenAIReasoningEffort
|
|
62125
62529
|
} = useAgent();
|
|
62126
|
-
const thinkingSupported = modelSupportsThinking(model.id);
|
|
62127
|
-
const openAIReasoningSupported = modelSupportsOpenAIReasoning(model.id);
|
|
62128
62530
|
const footerActions = [
|
|
62129
62531
|
{ key: "Enter", label: "confirm", variant: "primary" }
|
|
62130
62532
|
];
|
|
62131
|
-
if (thinkingSupported) {
|
|
62132
|
-
footerActions.push({ key: "Space", label: "Extended Thinking" });
|
|
62133
|
-
}
|
|
62134
|
-
if (openAIReasoningSupported) {
|
|
62135
|
-
footerActions.push({ key: "Space", label: "Reasoning Effort" });
|
|
62136
|
-
}
|
|
62137
62533
|
const title = /* @__PURE__ */ jsxDEV31("text", {
|
|
62138
62534
|
children: [
|
|
62139
62535
|
/* @__PURE__ */ jsxDEV31("span", {
|
|
@@ -62609,7 +63005,7 @@ function HITLWizard(props) {
|
|
|
62609
63005
|
}
|
|
62610
63006
|
|
|
62611
63007
|
// src/tui/components/commands/provider-manager.tsx
|
|
62612
|
-
|
|
63008
|
+
init_config();
|
|
62613
63009
|
import { useKeyboard as useKeyboard14 } from "@opentui/react";
|
|
62614
63010
|
import { useState as useState27 } from "react";
|
|
62615
63011
|
|
|
@@ -62863,7 +63259,7 @@ function ProviderSelection({
|
|
|
62863
63259
|
}
|
|
62864
63260
|
|
|
62865
63261
|
// src/tui/components/commands/provider-manager.tsx
|
|
62866
|
-
import { jsxDEV as jsxDEV37, Fragment as
|
|
63262
|
+
import { jsxDEV as jsxDEV37, Fragment as Fragment4 } from "@opentui/react/jsx-dev-runtime";
|
|
62867
63263
|
function ProviderManager({
|
|
62868
63264
|
onClose,
|
|
62869
63265
|
onOpenModelDialog
|
|
@@ -62939,7 +63335,7 @@ function ProviderManager({
|
|
|
62939
63335
|
};
|
|
62940
63336
|
const otherProviders = AVAILABLE_PROVIDERS.filter((p) => p.id !== "pensar");
|
|
62941
63337
|
const selectedProviderInfo = AVAILABLE_PROVIDERS.find((p) => p.id === selectedProvider);
|
|
62942
|
-
return /* @__PURE__ */ jsxDEV37(
|
|
63338
|
+
return /* @__PURE__ */ jsxDEV37(Fragment4, {
|
|
62943
63339
|
children: [
|
|
62944
63340
|
flowState === "choosing" && /* @__PURE__ */ jsxDEV37(OnboardingChoice, {
|
|
62945
63341
|
onPensarSelected: () => setFlowState("auth"),
|
|
@@ -63052,13 +63448,13 @@ function OnboardingChoice({
|
|
|
63052
63448
|
|
|
63053
63449
|
// src/tui/components/commands/sessions-display.tsx
|
|
63054
63450
|
import { useKeyboard as useKeyboard16 } from "@opentui/react";
|
|
63055
|
-
import { useCallback as
|
|
63451
|
+
import { useCallback as useCallback19, useEffect as useEffect18, useRef as useRef14, useState as useState29 } from "react";
|
|
63056
63452
|
init_session();
|
|
63057
63453
|
|
|
63058
63454
|
// src/tui/hooks/use-sessions-list.ts
|
|
63059
63455
|
import { existsSync, readdirSync } from "node:fs";
|
|
63060
63456
|
import { join } from "node:path";
|
|
63061
|
-
import { useCallback as
|
|
63457
|
+
import { useCallback as useCallback18, useEffect as useEffect17, useState as useState28 } from "react";
|
|
63062
63458
|
init_session();
|
|
63063
63459
|
function countFindings(findingsPath) {
|
|
63064
63460
|
try {
|
|
@@ -63076,7 +63472,7 @@ function useSessionsList() {
|
|
|
63076
63472
|
const [allSessions, setAllSessions] = useState28([]);
|
|
63077
63473
|
const [loading, setLoading] = useState28(true);
|
|
63078
63474
|
const [searchTerm, setSearchTerm] = useState28("");
|
|
63079
|
-
const loadSessions =
|
|
63475
|
+
const loadSessions = useCallback18(async () => {
|
|
63080
63476
|
try {
|
|
63081
63477
|
const enriched = [];
|
|
63082
63478
|
for await (const session of list()) {
|
|
@@ -63101,7 +63497,7 @@ function useSessionsList() {
|
|
|
63101
63497
|
useEffect17(() => {
|
|
63102
63498
|
loadSessions();
|
|
63103
63499
|
}, [loadSessions]);
|
|
63104
|
-
const deleteSession =
|
|
63500
|
+
const deleteSession = useCallback18(async (id) => {
|
|
63105
63501
|
setAllSessions((prev) => prev.filter((s) => s.id !== id));
|
|
63106
63502
|
await sessions.remove({ sessionId: id });
|
|
63107
63503
|
await loadSessions();
|
|
@@ -63334,7 +63730,7 @@ function SessionsDisplay({ onClose }) {
|
|
|
63334
63730
|
initialOverflowRef.current = estimatedRows > availableListHeight;
|
|
63335
63731
|
}
|
|
63336
63732
|
const listHeight = initialOverflowRef.current ? availableListHeight : undefined;
|
|
63337
|
-
const viewReport =
|
|
63733
|
+
const viewReport = useCallback19(async (sessionId) => {
|
|
63338
63734
|
const session = await sessions.get(sessionId);
|
|
63339
63735
|
const content = readSessionReport(session.rootPath);
|
|
63340
63736
|
if (!content) {
|
|
@@ -63345,7 +63741,7 @@ function SessionsDisplay({ onClose }) {
|
|
|
63345
63741
|
setReportSessionPath(session.rootPath);
|
|
63346
63742
|
setShowReportViewer(true);
|
|
63347
63743
|
}, [toast]);
|
|
63348
|
-
const openReportExternal =
|
|
63744
|
+
const openReportExternal = useCallback19(async () => {
|
|
63349
63745
|
if (!reportSessionPath)
|
|
63350
63746
|
return;
|
|
63351
63747
|
const err = await openSessionReport(reportSessionPath);
|
|
@@ -63971,9 +64367,9 @@ function SkillsDialog({
|
|
|
63971
64367
|
}
|
|
63972
64368
|
|
|
63973
64369
|
// src/tui/components/commands/theme-picker.tsx
|
|
63974
|
-
|
|
64370
|
+
init_config();
|
|
63975
64371
|
import { useKeyboard as useKeyboard19 } from "@opentui/react";
|
|
63976
|
-
import { useCallback as
|
|
64372
|
+
import { useCallback as useCallback20, useRef as useRef16, useState as useState31 } from "react";
|
|
63977
64373
|
import { jsxDEV as jsxDEV42 } from "@opentui/react/jsx-dev-runtime";
|
|
63978
64374
|
function ThemePicker({ onClose }) {
|
|
63979
64375
|
const dimensions = useDimensions();
|
|
@@ -63992,14 +64388,14 @@ function ThemePicker({ onClose }) {
|
|
|
63992
64388
|
const originalThemeRef = useRef16(theme.name);
|
|
63993
64389
|
const originalModeRef = useRef16(mode);
|
|
63994
64390
|
const originalTransparentRef = useRef16(transparent);
|
|
63995
|
-
const handleClose =
|
|
64391
|
+
const handleClose = useCallback20(() => {
|
|
63996
64392
|
setTheme(originalThemeRef.current);
|
|
63997
64393
|
setMode(originalModeRef.current);
|
|
63998
64394
|
if (transparent !== originalTransparentRef.current)
|
|
63999
64395
|
toggleTransparent();
|
|
64000
64396
|
onClose();
|
|
64001
64397
|
}, [setTheme, setMode, transparent, toggleTransparent, onClose]);
|
|
64002
|
-
const handleConfirm =
|
|
64398
|
+
const handleConfirm = useCallback20(async () => {
|
|
64003
64399
|
const currentThemeName = availableThemes[selectedIndex];
|
|
64004
64400
|
if (currentThemeName) {
|
|
64005
64401
|
await config.update({ theme: currentThemeName });
|
|
@@ -64125,7 +64521,7 @@ function ThemePicker({ onClose }) {
|
|
|
64125
64521
|
// src/tui/components/commands/web-wizard.tsx
|
|
64126
64522
|
import { useKeyboard as useKeyboard20 } from "@opentui/react";
|
|
64127
64523
|
import { useEffect as useEffect20, useRef as useRef17, useState as useState32 } from "react";
|
|
64128
|
-
import { jsxDEV as jsxDEV43, Fragment as
|
|
64524
|
+
import { jsxDEV as jsxDEV43, Fragment as Fragment5 } from "@opentui/react/jsx-dev-runtime";
|
|
64129
64525
|
function capitalize(s) {
|
|
64130
64526
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
64131
64527
|
}
|
|
@@ -64611,7 +65007,7 @@ function WebWizard({
|
|
|
64611
65007
|
}, undefined, false, undefined, this)
|
|
64612
65008
|
]
|
|
64613
65009
|
}, undefined, true, undefined, this),
|
|
64614
|
-
advancedExpanded && /* @__PURE__ */ jsxDEV43(
|
|
65010
|
+
advancedExpanded && /* @__PURE__ */ jsxDEV43(Fragment5, {
|
|
64615
65011
|
children: [
|
|
64616
65012
|
/* @__PURE__ */ jsxDEV43("box", {
|
|
64617
65013
|
id: `field-${promptFieldIndex}`,
|
|
@@ -64849,7 +65245,7 @@ function WebWizard({
|
|
|
64849
65245
|
}, undefined, false, undefined, this)
|
|
64850
65246
|
]
|
|
64851
65247
|
}, undefined, true, undefined, this),
|
|
64852
|
-
state.headers.mode === "custom" && /* @__PURE__ */ jsxDEV43(
|
|
65248
|
+
state.headers.mode === "custom" && /* @__PURE__ */ jsxDEV43(Fragment5, {
|
|
64853
65249
|
children: [
|
|
64854
65250
|
/* @__PURE__ */ jsxDEV43("box", {
|
|
64855
65251
|
id: `field-${headersNameIndex}`,
|
|
@@ -64897,7 +65293,7 @@ function WebWizard({
|
|
|
64897
65293
|
|
|
64898
65294
|
// src/tui/components/error-boundary.tsx
|
|
64899
65295
|
init_logger();
|
|
64900
|
-
import React, { useCallback as
|
|
65296
|
+
import React, { useCallback as useCallback21 } from "react";
|
|
64901
65297
|
var MAX_ERRORS = 3;
|
|
64902
65298
|
var ERROR_WINDOW_MS = 5000;
|
|
64903
65299
|
|
|
@@ -64932,7 +65328,7 @@ class ErrorBoundaryInner extends React.Component {
|
|
|
64932
65328
|
}
|
|
64933
65329
|
function ErrorBoundary({ children }) {
|
|
64934
65330
|
const { toast } = useToast();
|
|
64935
|
-
const handleError =
|
|
65331
|
+
const handleError = useCallback21((message) => {
|
|
64936
65332
|
toast(message, "error");
|
|
64937
65333
|
}, [toast]);
|
|
64938
65334
|
return React.createElement(ErrorBoundaryInner, { onError: handleError }, children);
|
|
@@ -64986,19 +65382,52 @@ var useSession = () => {
|
|
|
64986
65382
|
return session;
|
|
64987
65383
|
};
|
|
64988
65384
|
|
|
64989
|
-
// src/tui/components/
|
|
64990
|
-
|
|
65385
|
+
// src/tui/components/usage-labels.ts
|
|
65386
|
+
var WIDE_MIN_WIDTH = 86;
|
|
65387
|
+
var NARROW_MIN_WIDTH = 56;
|
|
64991
65388
|
function formatTokenCount(count) {
|
|
64992
65389
|
if (count >= 1e6) {
|
|
64993
65390
|
const v2 = count / 1e6;
|
|
64994
|
-
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}
|
|
65391
|
+
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}m`;
|
|
64995
65392
|
}
|
|
64996
65393
|
if (count >= 1000) {
|
|
64997
65394
|
const v2 = count / 1000;
|
|
64998
|
-
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}
|
|
65395
|
+
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}k`;
|
|
64999
65396
|
}
|
|
65000
65397
|
return count.toString();
|
|
65001
65398
|
}
|
|
65399
|
+
function buildUsageFooterLabels(input) {
|
|
65400
|
+
const { tokenUsage, contextUsage, width } = input;
|
|
65401
|
+
if (width < NARROW_MIN_WIDTH) {
|
|
65402
|
+
return { tokensLabel: null, contextLabel: null };
|
|
65403
|
+
}
|
|
65404
|
+
if (width >= WIDE_MIN_WIDTH) {
|
|
65405
|
+
let tokensLabel = `in ${formatTokenCount(tokenUsage.inputTokens)} out ${formatTokenCount(tokenUsage.outputTokens)}`;
|
|
65406
|
+
if (tokenUsage.cacheReadTokens > 0) {
|
|
65407
|
+
tokensLabel += ` cached ${formatTokenCount(tokenUsage.cacheReadTokens)}`;
|
|
65408
|
+
}
|
|
65409
|
+
return {
|
|
65410
|
+
tokensLabel,
|
|
65411
|
+
contextLabel: contextLabel(contextUsage, true)
|
|
65412
|
+
};
|
|
65413
|
+
}
|
|
65414
|
+
const total = tokenUsage.inputTokens + tokenUsage.outputTokens;
|
|
65415
|
+
return {
|
|
65416
|
+
tokensLabel: `${formatTokenCount(total)} tokens`,
|
|
65417
|
+
contextLabel: contextLabel(contextUsage, false)
|
|
65418
|
+
};
|
|
65419
|
+
}
|
|
65420
|
+
function contextLabel(context2, wide) {
|
|
65421
|
+
const percentage = contextPercentage(context2);
|
|
65422
|
+
if (percentage === null || !context2)
|
|
65423
|
+
return null;
|
|
65424
|
+
const pct = Math.floor(percentage);
|
|
65425
|
+
const limit = formatTokenCount(context2.contextLimit);
|
|
65426
|
+
return wide ? `context ${pct}% / ${limit}` : `${pct}% / ${limit}`;
|
|
65427
|
+
}
|
|
65428
|
+
|
|
65429
|
+
// src/tui/components/footer.tsx
|
|
65430
|
+
import { jsxDEV as jsxDEV45, Fragment as Fragment6 } from "@opentui/react/jsx-dev-runtime";
|
|
65002
65431
|
function Footer({
|
|
65003
65432
|
cwd = process.cwd(),
|
|
65004
65433
|
showExitWarning = false
|
|
@@ -65077,126 +65506,54 @@ function Footer({
|
|
|
65077
65506
|
}
|
|
65078
65507
|
function AgentStatus() {
|
|
65079
65508
|
const { colors: colors2 } = useTheme();
|
|
65080
|
-
const {
|
|
65509
|
+
const { usageStore } = useAgent();
|
|
65081
65510
|
const { width: termWidth } = useDimensions();
|
|
65082
|
-
const
|
|
65083
|
-
const
|
|
65511
|
+
const usage = useActiveSessionUsage(usageStore);
|
|
65512
|
+
const { tokensLabel, contextLabel: contextLabel2 } = buildUsageFooterLabels({
|
|
65513
|
+
tokenUsage: usage.tokenUsage,
|
|
65514
|
+
contextUsage: usage.contextUsage,
|
|
65515
|
+
width: termWidth
|
|
65516
|
+
});
|
|
65517
|
+
if (!tokensLabel)
|
|
65518
|
+
return null;
|
|
65084
65519
|
return /* @__PURE__ */ jsxDEV45("box", {
|
|
65085
65520
|
flexDirection: "row",
|
|
65086
65521
|
gap: 1,
|
|
65087
65522
|
children: [
|
|
65088
|
-
|
|
65523
|
+
/* @__PURE__ */ jsxDEV45("text", {
|
|
65524
|
+
fg: colors2.text,
|
|
65525
|
+
children: tokensLabel
|
|
65526
|
+
}, undefined, false, undefined, this),
|
|
65527
|
+
contextLabel2 && /* @__PURE__ */ jsxDEV45(Fragment6, {
|
|
65089
65528
|
children: [
|
|
65090
|
-
/* @__PURE__ */ jsxDEV45("
|
|
65091
|
-
|
|
65092
|
-
|
|
65529
|
+
/* @__PURE__ */ jsxDEV45("text", {
|
|
65530
|
+
fg: colors2.textMuted,
|
|
65531
|
+
children: "|"
|
|
65093
65532
|
}, undefined, false, undefined, this),
|
|
65094
65533
|
/* @__PURE__ */ jsxDEV45("text", {
|
|
65095
65534
|
fg: colors2.text,
|
|
65096
|
-
children:
|
|
65097
|
-
}, undefined, false, undefined, this),
|
|
65098
|
-
/* @__PURE__ */ jsxDEV45("box", {
|
|
65099
|
-
border: ["right"],
|
|
65100
|
-
borderColor: colors2.primary
|
|
65535
|
+
children: contextLabel2
|
|
65101
65536
|
}, undefined, false, undefined, this)
|
|
65102
65537
|
]
|
|
65103
|
-
}, undefined, true, undefined, this)
|
|
65104
|
-
/* @__PURE__ */ jsxDEV45(ContextProgress, {
|
|
65105
|
-
width: 16,
|
|
65106
|
-
showPercent: true
|
|
65107
|
-
}, undefined, false, undefined, this)
|
|
65538
|
+
}, undefined, true, undefined, this)
|
|
65108
65539
|
]
|
|
65109
65540
|
}, undefined, true, undefined, this);
|
|
65110
65541
|
}
|
|
65111
|
-
var FILL_CHAR = "▬";
|
|
65112
|
-
var DASH_CHAR = "─";
|
|
65113
|
-
function ContextProgress({
|
|
65114
|
-
width = 20,
|
|
65115
|
-
showPercent = false
|
|
65116
|
-
}) {
|
|
65117
|
-
const { colors: colors2 } = useTheme();
|
|
65118
|
-
const { model, tokenUsage } = useAgent();
|
|
65119
|
-
const contextLength = model.contextLength ?? 200000;
|
|
65120
|
-
const fraction = Math.max(0, Math.min(1, tokenUsage.totalTokens / contextLength));
|
|
65121
|
-
const inner = Math.max(1, width - 2);
|
|
65122
|
-
const filledCells = Math.round(fraction * inner);
|
|
65123
|
-
const fillColor = colors2.success;
|
|
65124
|
-
const sizeText = formatTokenCount(contextLength);
|
|
65125
|
-
const labelText = showPercent ? `${Math.floor(fraction * 100)}% ${sizeText}` : sizeText;
|
|
65126
|
-
const labelLen = labelText.length;
|
|
65127
|
-
const labelStart = Math.max(0, inner - labelLen - 1);
|
|
65128
|
-
const labelEnd = labelStart + labelLen;
|
|
65129
|
-
const dashColor = withAlpha2(colors2.textMuted, 0.35);
|
|
65130
|
-
const bracketColor = withAlpha2(colors2.textMuted, 0.7);
|
|
65131
|
-
const cells = [];
|
|
65132
|
-
cells.push({ ch: "[", fg: bracketColor });
|
|
65133
|
-
for (let col = 0;col < inner; col++) {
|
|
65134
|
-
const inLabel = col >= labelStart && col < labelEnd;
|
|
65135
|
-
const isFilled = col < filledCells;
|
|
65136
|
-
if (inLabel) {
|
|
65137
|
-
cells.push({
|
|
65138
|
-
ch: labelText[col - labelStart],
|
|
65139
|
-
fg: colors2.text
|
|
65140
|
-
});
|
|
65141
|
-
} else if (isFilled) {
|
|
65142
|
-
cells.push({ ch: FILL_CHAR, fg: fillColor });
|
|
65143
|
-
} else {
|
|
65144
|
-
cells.push({ ch: DASH_CHAR, fg: dashColor });
|
|
65145
|
-
}
|
|
65146
|
-
}
|
|
65147
|
-
cells.push({ ch: "]", fg: bracketColor });
|
|
65148
|
-
return /* @__PURE__ */ jsxDEV45("box", {
|
|
65149
|
-
flexDirection: "row",
|
|
65150
|
-
children: cells.map((cell, i) => /* @__PURE__ */ jsxDEV45("text", {
|
|
65151
|
-
fg: cell.fg,
|
|
65152
|
-
content: cell.ch
|
|
65153
|
-
}, i, false, undefined, this))
|
|
65154
|
-
}, undefined, false, undefined, this);
|
|
65155
|
-
}
|
|
65156
65542
|
|
|
65157
65543
|
// src/tui/components/operator-dashboard/index.tsx
|
|
65158
65544
|
init_dist();
|
|
65159
|
-
import { existsSync as
|
|
65160
|
-
import { isAbsolute as isAbsolute2, join as
|
|
65545
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
65546
|
+
import { isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "node:path";
|
|
65161
65547
|
import { useKeyboard as useKeyboard26 } from "@opentui/react";
|
|
65162
65548
|
import {
|
|
65163
|
-
useCallback as
|
|
65549
|
+
useCallback as useCallback22,
|
|
65164
65550
|
useEffect as useEffect25,
|
|
65165
65551
|
useMemo as useMemo22,
|
|
65166
65552
|
useRef as useRef21,
|
|
65167
65553
|
useState as useState39,
|
|
65168
|
-
useSyncExternalStore as
|
|
65554
|
+
useSyncExternalStore as useSyncExternalStore3
|
|
65169
65555
|
} from "react";
|
|
65170
65556
|
init_ai();
|
|
65171
|
-
|
|
65172
|
-
// src/core/integrations/wandb/upload.ts
|
|
65173
|
-
async function createWandbUploader(session, opts) {
|
|
65174
|
-
const resolved = resolveConfig(opts);
|
|
65175
|
-
if (!resolved.available)
|
|
65176
|
-
return null;
|
|
65177
|
-
const tracer = await createWeaveTracer(resolved.config);
|
|
65178
|
-
if (!tracer)
|
|
65179
|
-
return null;
|
|
65180
|
-
return {
|
|
65181
|
-
onRecord: (record) => tracer.logRecord(record, session.id),
|
|
65182
|
-
finalize: () => tracer.finish()
|
|
65183
|
-
};
|
|
65184
|
-
}
|
|
65185
|
-
async function attachWandbToEventBus(session, eventBus, opts) {
|
|
65186
|
-
const uploader = await createWandbUploader(session, opts);
|
|
65187
|
-
if (!uploader)
|
|
65188
|
-
return null;
|
|
65189
|
-
const handler = (e) => {
|
|
65190
|
-
uploader.onRecord(e.record);
|
|
65191
|
-
};
|
|
65192
|
-
eventBus.on("trace-record", handler);
|
|
65193
|
-
return async () => {
|
|
65194
|
-
eventBus.off("trace-record", handler);
|
|
65195
|
-
await uploader.finalize();
|
|
65196
|
-
};
|
|
65197
|
-
}
|
|
65198
|
-
|
|
65199
|
-
// src/tui/components/operator-dashboard/index.tsx
|
|
65200
65557
|
init_session();
|
|
65201
65558
|
|
|
65202
65559
|
// src/tui/components/chat/approval-inline.tsx
|
|
@@ -66464,6 +66821,202 @@ function ScreenshotModal({ screenshots, initialIndex, onClose }) {
|
|
|
66464
66821
|
}, undefined, true, undefined, this);
|
|
66465
66822
|
}
|
|
66466
66823
|
|
|
66824
|
+
// src/tui/components/operator-dashboard/conversation.ts
|
|
66825
|
+
init_session();
|
|
66826
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
66827
|
+
import { join as join3 } from "node:path";
|
|
66828
|
+
function recoverAbortedConversation(conversation, partialText, displayMessages) {
|
|
66829
|
+
if (conversation.at(-1)?.role !== "user")
|
|
66830
|
+
return null;
|
|
66831
|
+
const pendingTools = displayMessages.filter((message) => message.role === "tool" && typeof message.toolCallId === "string" && typeof message.toolName === "string" && (message.status === "pending" || message.status === "streaming"));
|
|
66832
|
+
const assistantContent = [
|
|
66833
|
+
{
|
|
66834
|
+
type: "text",
|
|
66835
|
+
text: partialText.trim() || "[Response interrupted by user.]"
|
|
66836
|
+
},
|
|
66837
|
+
...pendingTools.map((tool) => ({
|
|
66838
|
+
type: "tool-call",
|
|
66839
|
+
toolCallId: tool.toolCallId,
|
|
66840
|
+
toolName: tool.toolName,
|
|
66841
|
+
input: tool.args ?? {}
|
|
66842
|
+
}))
|
|
66843
|
+
];
|
|
66844
|
+
const recovered = [
|
|
66845
|
+
...conversation,
|
|
66846
|
+
{
|
|
66847
|
+
role: "assistant",
|
|
66848
|
+
content: assistantContent
|
|
66849
|
+
}
|
|
66850
|
+
];
|
|
66851
|
+
if (pendingTools.length === 0)
|
|
66852
|
+
return recovered;
|
|
66853
|
+
return [
|
|
66854
|
+
...recovered,
|
|
66855
|
+
{
|
|
66856
|
+
role: "tool",
|
|
66857
|
+
content: pendingTools.map((tool) => ({
|
|
66858
|
+
type: "tool-result",
|
|
66859
|
+
toolCallId: tool.toolCallId,
|
|
66860
|
+
toolName: tool.toolName ?? "unknown",
|
|
66861
|
+
output: {
|
|
66862
|
+
type: "text",
|
|
66863
|
+
value: "Cancelled by user."
|
|
66864
|
+
}
|
|
66865
|
+
}))
|
|
66866
|
+
}
|
|
66867
|
+
];
|
|
66868
|
+
}
|
|
66869
|
+
function rewriteToolResultOutput(conversation, toolCallId, value) {
|
|
66870
|
+
const wrappedOutput = {
|
|
66871
|
+
type: "json",
|
|
66872
|
+
value
|
|
66873
|
+
};
|
|
66874
|
+
let changed = false;
|
|
66875
|
+
const next = conversation.map((msg) => {
|
|
66876
|
+
if (msg.role !== "tool")
|
|
66877
|
+
return msg;
|
|
66878
|
+
if (!Array.isArray(msg.content))
|
|
66879
|
+
return msg;
|
|
66880
|
+
let mutated = false;
|
|
66881
|
+
const nextContent = msg.content.map((part) => {
|
|
66882
|
+
if (part && typeof part === "object" && "type" in part && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
66883
|
+
mutated = true;
|
|
66884
|
+
return {
|
|
66885
|
+
...part,
|
|
66886
|
+
output: wrappedOutput
|
|
66887
|
+
};
|
|
66888
|
+
}
|
|
66889
|
+
return part;
|
|
66890
|
+
});
|
|
66891
|
+
if (!mutated)
|
|
66892
|
+
return msg;
|
|
66893
|
+
changed = true;
|
|
66894
|
+
return { ...msg, content: nextContent };
|
|
66895
|
+
});
|
|
66896
|
+
return changed ? next : conversation;
|
|
66897
|
+
}
|
|
66898
|
+
function recoverAbortedTranscript(input) {
|
|
66899
|
+
const messagesPath = join3(input.rootPath, "messages.json");
|
|
66900
|
+
let conversation = input.conversation;
|
|
66901
|
+
let recovered = null;
|
|
66902
|
+
try {
|
|
66903
|
+
if (existsSync3(messagesPath)) {
|
|
66904
|
+
const raw = JSON.parse(readFileSync3(messagesPath, "utf-8"));
|
|
66905
|
+
if (Array.isArray(raw) && raw.length > 0) {
|
|
66906
|
+
conversation = normalizeMessages(getResumeMessages(raw));
|
|
66907
|
+
}
|
|
66908
|
+
}
|
|
66909
|
+
recovered = recoverAbortedConversation(conversation, input.partialText, input.displayMessages);
|
|
66910
|
+
} catch {}
|
|
66911
|
+
if (!recovered)
|
|
66912
|
+
return conversation;
|
|
66913
|
+
conversation = recovered;
|
|
66914
|
+
try {
|
|
66915
|
+
writeFileSync(messagesPath, JSON.stringify(recovered, null, 2));
|
|
66916
|
+
} catch {}
|
|
66917
|
+
return conversation;
|
|
66918
|
+
}
|
|
66919
|
+
|
|
66920
|
+
// src/tui/components/operator-dashboard/display-state.ts
|
|
66921
|
+
var MAX_LOG_LINES = 200;
|
|
66922
|
+
function appendStreamedText(messages, accumulated) {
|
|
66923
|
+
const last = messages[messages.length - 1];
|
|
66924
|
+
if (last && last.role === "assistant") {
|
|
66925
|
+
const updated = [...messages];
|
|
66926
|
+
updated[updated.length - 1] = { ...last, content: accumulated };
|
|
66927
|
+
return updated;
|
|
66928
|
+
}
|
|
66929
|
+
return [
|
|
66930
|
+
...messages,
|
|
66931
|
+
{ role: "assistant", content: accumulated, createdAt: new Date }
|
|
66932
|
+
];
|
|
66933
|
+
}
|
|
66934
|
+
function startStreamingToolCall(messages, toolCallId, toolName) {
|
|
66935
|
+
return [
|
|
66936
|
+
...messages,
|
|
66937
|
+
{
|
|
66938
|
+
role: "tool",
|
|
66939
|
+
content: "",
|
|
66940
|
+
createdAt: new Date,
|
|
66941
|
+
toolCallId,
|
|
66942
|
+
toolName,
|
|
66943
|
+
args: {},
|
|
66944
|
+
status: "streaming"
|
|
66945
|
+
}
|
|
66946
|
+
];
|
|
66947
|
+
}
|
|
66948
|
+
function applyToolCallDelta(messages, toolCallId, parsed) {
|
|
66949
|
+
const contentText = extractStreamableContent(parsed);
|
|
66950
|
+
const logs = contentText ? contentText.split(`
|
|
66951
|
+
`) : undefined;
|
|
66952
|
+
const idx = messages.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
66953
|
+
if (idx === -1)
|
|
66954
|
+
return messages;
|
|
66955
|
+
const updated = [...messages];
|
|
66956
|
+
updated[idx] = { ...updated[idx], args: parsed, ...logs && { logs } };
|
|
66957
|
+
return updated;
|
|
66958
|
+
}
|
|
66959
|
+
function applyToolCall(messages, toolCallId, toolName, args) {
|
|
66960
|
+
const idx = messages.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
66961
|
+
if (idx !== -1) {
|
|
66962
|
+
const updated = [...messages];
|
|
66963
|
+
updated[idx] = {
|
|
66964
|
+
...updated[idx],
|
|
66965
|
+
args,
|
|
66966
|
+
logs: undefined,
|
|
66967
|
+
status: "pending"
|
|
66968
|
+
};
|
|
66969
|
+
return updated;
|
|
66970
|
+
}
|
|
66971
|
+
return [
|
|
66972
|
+
...messages,
|
|
66973
|
+
{
|
|
66974
|
+
role: "tool",
|
|
66975
|
+
content: "",
|
|
66976
|
+
createdAt: new Date,
|
|
66977
|
+
toolCallId,
|
|
66978
|
+
toolName,
|
|
66979
|
+
args,
|
|
66980
|
+
status: "pending"
|
|
66981
|
+
}
|
|
66982
|
+
];
|
|
66983
|
+
}
|
|
66984
|
+
function applyToolResult(messages, toolCallId, result) {
|
|
66985
|
+
const idx = messages.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
66986
|
+
if (idx === -1)
|
|
66987
|
+
return messages;
|
|
66988
|
+
const updated = [...messages];
|
|
66989
|
+
updated[idx] = { ...updated[idx], status: "completed", result };
|
|
66990
|
+
return updated;
|
|
66991
|
+
}
|
|
66992
|
+
function mergeCommandOutput(messages, buf) {
|
|
66993
|
+
const idx = messages.findLastIndex((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming"));
|
|
66994
|
+
if (idx === -1)
|
|
66995
|
+
return messages;
|
|
66996
|
+
const msg = messages[idx];
|
|
66997
|
+
const existing = msg.logs ?? [];
|
|
66998
|
+
const incoming = buf.split(`
|
|
66999
|
+
`);
|
|
67000
|
+
let merged;
|
|
67001
|
+
if (existing.length > 0 && !buf.startsWith(`
|
|
67002
|
+
`)) {
|
|
67003
|
+
merged = [...existing];
|
|
67004
|
+
merged[merged.length - 1] += incoming[0];
|
|
67005
|
+
merged.push(...incoming.slice(1));
|
|
67006
|
+
} else {
|
|
67007
|
+
merged = [...existing, ...incoming];
|
|
67008
|
+
}
|
|
67009
|
+
if (merged.length > MAX_LOG_LINES) {
|
|
67010
|
+
merged = merged.slice(-MAX_LOG_LINES);
|
|
67011
|
+
}
|
|
67012
|
+
const updated = [...messages];
|
|
67013
|
+
updated[idx] = { ...msg, logs: merged };
|
|
67014
|
+
return updated;
|
|
67015
|
+
}
|
|
67016
|
+
function markInFlightToolsErrored(messages, result) {
|
|
67017
|
+
return messages.map((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result } : m2);
|
|
67018
|
+
}
|
|
67019
|
+
|
|
66467
67020
|
// src/tui/components/operator-dashboard/logic.ts
|
|
66468
67021
|
var OPERATOR_ALLOWED_COMMANDS = new Set([
|
|
66469
67022
|
"/models",
|
|
@@ -66741,17 +67294,6 @@ ${refinementBlock}`;
|
|
|
66741
67294
|
function resolveInputFocused(status, dialogStackLength, externalDialogOpen) {
|
|
66742
67295
|
return status !== "running" && dialogStackLength === 0 && !externalDialogOpen;
|
|
66743
67296
|
}
|
|
66744
|
-
function accumulateTokenUsage(current, stepInputTokens, stepOutputTokens) {
|
|
66745
|
-
if (stepInputTokens <= 0 && stepOutputTokens <= 0)
|
|
66746
|
-
return null;
|
|
66747
|
-
return {
|
|
66748
|
-
inputTokens: current.inputTokens + stepInputTokens,
|
|
66749
|
-
outputTokens: current.outputTokens + stepOutputTokens,
|
|
66750
|
-
totalTokens: current.totalTokens + stepInputTokens + stepOutputTokens,
|
|
66751
|
-
cachedTokens: current.cachedTokens,
|
|
66752
|
-
cacheWriteTokens: current.cacheWriteTokens
|
|
66753
|
-
};
|
|
66754
|
-
}
|
|
66755
67297
|
|
|
66756
67298
|
// src/tui/components/operator-dashboard/queue.ts
|
|
66757
67299
|
var nextId3 = 0;
|
|
@@ -66841,6 +67383,401 @@ function QueuedMessages({
|
|
|
66841
67383
|
}, undefined, true, undefined, this);
|
|
66842
67384
|
}
|
|
66843
67385
|
|
|
67386
|
+
// src/tui/components/operator-dashboard/workflow-data.ts
|
|
67387
|
+
function isPentestAgent(id) {
|
|
67388
|
+
return id !== undefined && /^pentest-agent-\d+$/.test(id);
|
|
67389
|
+
}
|
|
67390
|
+
function initialWorkflowData() {
|
|
67391
|
+
return {
|
|
67392
|
+
currentPhase: "discovery",
|
|
67393
|
+
discovery: { label: "", status: "pending", logs: [] },
|
|
67394
|
+
pentesting: { label: "", status: "idle", subagents: {} },
|
|
67395
|
+
reporting: { label: "", status: "idle" }
|
|
67396
|
+
};
|
|
67397
|
+
}
|
|
67398
|
+
function updateWorkflowDataMessage(messages, updater) {
|
|
67399
|
+
const idx = messages.findLastIndex((m2) => isToolMessage(m2) && m2.toolName === "run_pentest_workflow" && (m2.status === "pending" || m2.status === "streaming"));
|
|
67400
|
+
if (idx === -1)
|
|
67401
|
+
return messages;
|
|
67402
|
+
const msg = messages[idx];
|
|
67403
|
+
const wd = msg.workflowData ?? initialWorkflowData();
|
|
67404
|
+
const updated = [...messages];
|
|
67405
|
+
updated[idx] = { ...msg, workflowData: updater(wd) };
|
|
67406
|
+
return updated;
|
|
67407
|
+
}
|
|
67408
|
+
function applyWorkflowSubagentSpawn(wd, subagentId, name) {
|
|
67409
|
+
return {
|
|
67410
|
+
...wd,
|
|
67411
|
+
pentesting: {
|
|
67412
|
+
...wd.pentesting,
|
|
67413
|
+
subagents: {
|
|
67414
|
+
...wd.pentesting.subagents,
|
|
67415
|
+
[subagentId]: { name, status: "pending", logs: [] }
|
|
67416
|
+
}
|
|
67417
|
+
}
|
|
67418
|
+
};
|
|
67419
|
+
}
|
|
67420
|
+
function applyWorkflowSubagentComplete(wd, subagentId, status) {
|
|
67421
|
+
const entry = wd.pentesting.subagents[subagentId];
|
|
67422
|
+
if (!entry)
|
|
67423
|
+
return wd;
|
|
67424
|
+
return {
|
|
67425
|
+
...wd,
|
|
67426
|
+
pentesting: {
|
|
67427
|
+
...wd.pentesting,
|
|
67428
|
+
subagents: {
|
|
67429
|
+
...wd.pentesting.subagents,
|
|
67430
|
+
[subagentId]: { ...entry, status }
|
|
67431
|
+
}
|
|
67432
|
+
}
|
|
67433
|
+
};
|
|
67434
|
+
}
|
|
67435
|
+
function applyWorkflowPhaseStart(wd, phase, label) {
|
|
67436
|
+
const next = { ...wd, currentPhase: phase };
|
|
67437
|
+
if (phase === "discovery") {
|
|
67438
|
+
next.discovery = { ...wd.discovery, label, status: "pending", logs: [] };
|
|
67439
|
+
} else if (phase === "pentesting") {
|
|
67440
|
+
next.pentesting = { ...wd.pentesting, label, status: "pending" };
|
|
67441
|
+
} else if (phase === "reporting") {
|
|
67442
|
+
next.reporting = { ...wd.reporting, label, status: "pending" };
|
|
67443
|
+
}
|
|
67444
|
+
return next;
|
|
67445
|
+
}
|
|
67446
|
+
function applyWorkflowPhaseComplete(wd, phase, summary) {
|
|
67447
|
+
const next = { ...wd };
|
|
67448
|
+
if (phase === "discovery") {
|
|
67449
|
+
const targets = summary.targets ?? [];
|
|
67450
|
+
next.discovery = {
|
|
67451
|
+
...wd.discovery,
|
|
67452
|
+
status: "complete",
|
|
67453
|
+
targets,
|
|
67454
|
+
cached: summary.cached
|
|
67455
|
+
};
|
|
67456
|
+
} else if (phase === "pentesting") {
|
|
67457
|
+
next.pentesting = { ...wd.pentesting, status: "complete" };
|
|
67458
|
+
} else if (phase === "reporting") {
|
|
67459
|
+
next.reporting = {
|
|
67460
|
+
...wd.reporting,
|
|
67461
|
+
status: "complete",
|
|
67462
|
+
findingsCount: summary.findingsCount,
|
|
67463
|
+
findingsBySeverity: summary.findingsBySeverity,
|
|
67464
|
+
reportPath: summary.reportPath
|
|
67465
|
+
};
|
|
67466
|
+
next.currentPhase = "complete";
|
|
67467
|
+
}
|
|
67468
|
+
return next;
|
|
67469
|
+
}
|
|
67470
|
+
|
|
67471
|
+
// src/tui/components/operator-dashboard/run-events.ts
|
|
67472
|
+
function bindOperatorRunEvents(bus, options) {
|
|
67473
|
+
const { isCurrent, handlers } = options;
|
|
67474
|
+
const offs = [];
|
|
67475
|
+
let boundError = false;
|
|
67476
|
+
const bind = (event, handler) => {
|
|
67477
|
+
if (!handler)
|
|
67478
|
+
return;
|
|
67479
|
+
if (event === "error")
|
|
67480
|
+
boundError = true;
|
|
67481
|
+
const wrapped = (e) => {
|
|
67482
|
+
if (!isCurrent())
|
|
67483
|
+
return;
|
|
67484
|
+
try {
|
|
67485
|
+
handler(e);
|
|
67486
|
+
} catch (err) {
|
|
67487
|
+
console.error(`[operator] ${event} handler failed:`, err);
|
|
67488
|
+
}
|
|
67489
|
+
};
|
|
67490
|
+
bus.on(event, wrapped);
|
|
67491
|
+
offs.push(() => bus.off(event, wrapped));
|
|
67492
|
+
};
|
|
67493
|
+
bind("text-delta", handlers.onTextDelta);
|
|
67494
|
+
bind("tool-call-start", handlers.onToolCallStart);
|
|
67495
|
+
bind("tool-call-delta", handlers.onToolCallDelta);
|
|
67496
|
+
bind("tool-call-complete", handlers.onToolCallComplete);
|
|
67497
|
+
bind("tool-result", handlers.onToolResult);
|
|
67498
|
+
bind("command-output", handlers.onCommandOutput);
|
|
67499
|
+
bind("error", handlers.onError);
|
|
67500
|
+
bind("subagent-spawn", handlers.onSubagentSpawn);
|
|
67501
|
+
bind("subagent-complete", handlers.onSubagentComplete);
|
|
67502
|
+
bind("workflow-phase-start", handlers.onWorkflowPhaseStart);
|
|
67503
|
+
bind("workflow-phase-complete", handlers.onWorkflowPhaseComplete);
|
|
67504
|
+
let unbound = false;
|
|
67505
|
+
return () => {
|
|
67506
|
+
if (unbound)
|
|
67507
|
+
return;
|
|
67508
|
+
unbound = true;
|
|
67509
|
+
for (const off of offs)
|
|
67510
|
+
off();
|
|
67511
|
+
offs.length = 0;
|
|
67512
|
+
if (boundError)
|
|
67513
|
+
bus.on("error", () => {});
|
|
67514
|
+
};
|
|
67515
|
+
}
|
|
67516
|
+
var COMMAND_OUTPUT_FLUSH_MS = 150;
|
|
67517
|
+
function createDisplayEventHandlers(sink) {
|
|
67518
|
+
let partialText = "";
|
|
67519
|
+
const toolArgsDeltas = new Map;
|
|
67520
|
+
let commandOutputBuf = "";
|
|
67521
|
+
let flushTimer = null;
|
|
67522
|
+
const flushCommandOutput = () => {
|
|
67523
|
+
if (!commandOutputBuf)
|
|
67524
|
+
return;
|
|
67525
|
+
const buf = commandOutputBuf;
|
|
67526
|
+
commandOutputBuf = "";
|
|
67527
|
+
sink.updateMessages((messages) => mergeCommandOutput(messages, buf));
|
|
67528
|
+
};
|
|
67529
|
+
const stopCommandOutputFlush = () => {
|
|
67530
|
+
if (flushTimer) {
|
|
67531
|
+
clearInterval(flushTimer);
|
|
67532
|
+
flushTimer = null;
|
|
67533
|
+
}
|
|
67534
|
+
};
|
|
67535
|
+
return {
|
|
67536
|
+
onTextDelta(e) {
|
|
67537
|
+
sink.setThinking(false);
|
|
67538
|
+
partialText += e.text;
|
|
67539
|
+
const accumulated = partialText;
|
|
67540
|
+
sink.updateMessages((messages) => appendStreamedText(messages, accumulated));
|
|
67541
|
+
},
|
|
67542
|
+
onToolCallStart(e) {
|
|
67543
|
+
sink.setThinking(false);
|
|
67544
|
+
partialText = "";
|
|
67545
|
+
toolArgsDeltas.set(e.toolCallId, { accumulated: "" });
|
|
67546
|
+
sink.updateMessages((messages) => startStreamingToolCall(messages, e.toolCallId, e.toolName));
|
|
67547
|
+
},
|
|
67548
|
+
onToolCallDelta(e) {
|
|
67549
|
+
const entry = toolArgsDeltas.get(e.toolCallId);
|
|
67550
|
+
const accumulated = (entry?.accumulated ?? "") + e.argsTextDelta;
|
|
67551
|
+
toolArgsDeltas.set(e.toolCallId, { accumulated });
|
|
67552
|
+
const parsed = tryParsePartialJson(accumulated);
|
|
67553
|
+
if (!parsed)
|
|
67554
|
+
return;
|
|
67555
|
+
sink.updateMessages((messages) => applyToolCallDelta(messages, e.toolCallId, parsed));
|
|
67556
|
+
},
|
|
67557
|
+
onToolCallComplete(e) {
|
|
67558
|
+
sink.setThinking(false);
|
|
67559
|
+
partialText = "";
|
|
67560
|
+
toolArgsDeltas.delete(e.toolCallId);
|
|
67561
|
+
const args = e.args && typeof e.args === "object" && !Array.isArray(e.args) && e.args !== null ? e.args : undefined;
|
|
67562
|
+
sink.updateMessages((messages) => applyToolCall(messages, e.toolCallId, e.toolName, args));
|
|
67563
|
+
},
|
|
67564
|
+
onToolResult(e) {
|
|
67565
|
+
flushCommandOutput();
|
|
67566
|
+
stopCommandOutputFlush();
|
|
67567
|
+
sink.setThinking(true);
|
|
67568
|
+
partialText = "";
|
|
67569
|
+
sink.updateMessages((messages) => applyToolResult(messages, e.toolCallId, e.result));
|
|
67570
|
+
},
|
|
67571
|
+
onCommandOutput(e) {
|
|
67572
|
+
commandOutputBuf += e.data;
|
|
67573
|
+
if (!flushTimer) {
|
|
67574
|
+
flushTimer = setInterval(flushCommandOutput, COMMAND_OUTPUT_FLUSH_MS);
|
|
67575
|
+
}
|
|
67576
|
+
},
|
|
67577
|
+
onError(e) {
|
|
67578
|
+
console.error("Agent error:", e.error);
|
|
67579
|
+
const errorMessage = e.error instanceof Error ? e.error.message : "Unknown error";
|
|
67580
|
+
sink.setError(errorMessage);
|
|
67581
|
+
sink.updateMessages((messages) => markInFlightToolsErrored(messages, errorMessage));
|
|
67582
|
+
},
|
|
67583
|
+
getPartialText() {
|
|
67584
|
+
return partialText;
|
|
67585
|
+
},
|
|
67586
|
+
resetPartialText() {
|
|
67587
|
+
partialText = "";
|
|
67588
|
+
},
|
|
67589
|
+
flushCommandOutput,
|
|
67590
|
+
stopCommandOutputFlush,
|
|
67591
|
+
dispose: stopCommandOutputFlush
|
|
67592
|
+
};
|
|
67593
|
+
}
|
|
67594
|
+
function toRecordArgs(args) {
|
|
67595
|
+
return args && typeof args === "object" && !Array.isArray(args) && args !== null ? args : undefined;
|
|
67596
|
+
}
|
|
67597
|
+
function createRunEventProjections(deps) {
|
|
67598
|
+
const { display, subagents, updateWorkflowData } = deps;
|
|
67599
|
+
return {
|
|
67600
|
+
handlers: {
|
|
67601
|
+
onTextDelta: (d2) => {
|
|
67602
|
+
if (d2.subagentId) {
|
|
67603
|
+
subagents.appendText(d2.subagentId, d2.text);
|
|
67604
|
+
return;
|
|
67605
|
+
}
|
|
67606
|
+
display.onTextDelta(d2);
|
|
67607
|
+
},
|
|
67608
|
+
onToolCallStart: (d2) => {
|
|
67609
|
+
if (d2.subagentId) {
|
|
67610
|
+
subagents.addStreamingToolCall(d2.subagentId, d2.toolCallId, d2.toolName);
|
|
67611
|
+
return;
|
|
67612
|
+
}
|
|
67613
|
+
display.onToolCallStart(d2);
|
|
67614
|
+
},
|
|
67615
|
+
onToolCallDelta: (d2) => {
|
|
67616
|
+
if (d2.subagentId) {
|
|
67617
|
+
subagents.appendToolCallDelta(d2.subagentId, d2.toolCallId, d2.argsTextDelta);
|
|
67618
|
+
return;
|
|
67619
|
+
}
|
|
67620
|
+
display.onToolCallDelta(d2);
|
|
67621
|
+
},
|
|
67622
|
+
onToolCallComplete: (d2) => {
|
|
67623
|
+
if (d2.subagentId) {
|
|
67624
|
+
subagents.addToolCall(d2.subagentId, d2.toolCallId, d2.toolName, toRecordArgs(d2.args) ?? {});
|
|
67625
|
+
return;
|
|
67626
|
+
}
|
|
67627
|
+
display.onToolCallComplete(d2);
|
|
67628
|
+
deps.onRootToolCallStarted?.();
|
|
67629
|
+
if (d2.toolName === ASK_USER_QUESTIONS_TOOL_NAME) {
|
|
67630
|
+
const rawQuestions = toRecordArgs(d2.args)?.questions;
|
|
67631
|
+
if (Array.isArray(rawQuestions) && rawQuestions.length > 0) {
|
|
67632
|
+
deps.questions.onAsked(d2.toolCallId, rawQuestions);
|
|
67633
|
+
}
|
|
67634
|
+
}
|
|
67635
|
+
},
|
|
67636
|
+
onToolResult: (d2) => {
|
|
67637
|
+
if (d2.subagentId) {
|
|
67638
|
+
subagents.updateToolResult(d2.subagentId, d2.toolCallId, d2.result);
|
|
67639
|
+
return;
|
|
67640
|
+
}
|
|
67641
|
+
display.onToolResult(d2);
|
|
67642
|
+
if (d2.toolName === "submit_plan" && d2.result?.success === true) {
|
|
67643
|
+
deps.onPlanSubmitted?.();
|
|
67644
|
+
}
|
|
67645
|
+
},
|
|
67646
|
+
onCommandOutput: (d2) => {
|
|
67647
|
+
if (d2.subagentId)
|
|
67648
|
+
return;
|
|
67649
|
+
display.onCommandOutput(d2);
|
|
67650
|
+
},
|
|
67651
|
+
onError: (d2) => {
|
|
67652
|
+
if (d2.subagentId) {
|
|
67653
|
+
const errMsg = d2.error instanceof Error ? d2.error.message : "Unknown error";
|
|
67654
|
+
subagents.appendText(d2.subagentId, `
|
|
67655
|
+
Error: ${errMsg}
|
|
67656
|
+
`);
|
|
67657
|
+
return;
|
|
67658
|
+
}
|
|
67659
|
+
display.onError(d2);
|
|
67660
|
+
deps.questions.onCleared();
|
|
67661
|
+
},
|
|
67662
|
+
onSubagentSpawn: ({ subagentId, name }) => {
|
|
67663
|
+
if (subagentId.startsWith("app:"))
|
|
67664
|
+
return;
|
|
67665
|
+
subagents.spawnSession(subagentId, name);
|
|
67666
|
+
if (!isPentestAgent(subagentId))
|
|
67667
|
+
return;
|
|
67668
|
+
updateWorkflowData((wd) => applyWorkflowSubagentSpawn(wd, subagentId, name));
|
|
67669
|
+
},
|
|
67670
|
+
onSubagentComplete: ({ subagentId, status }) => {
|
|
67671
|
+
if (subagentId.startsWith("app:"))
|
|
67672
|
+
return;
|
|
67673
|
+
subagents.completeSession(subagentId, status);
|
|
67674
|
+
if (!isPentestAgent(subagentId))
|
|
67675
|
+
return;
|
|
67676
|
+
updateWorkflowData((wd) => applyWorkflowSubagentComplete(wd, subagentId, status));
|
|
67677
|
+
},
|
|
67678
|
+
onWorkflowPhaseStart: (d2) => {
|
|
67679
|
+
display.resetPartialText();
|
|
67680
|
+
if (d2.phase === "discovery") {
|
|
67681
|
+
deps.clearSubagentSessions();
|
|
67682
|
+
}
|
|
67683
|
+
updateWorkflowData((wd) => applyWorkflowPhaseStart(wd, d2.phase, d2.label));
|
|
67684
|
+
},
|
|
67685
|
+
onWorkflowPhaseComplete: (d2) => {
|
|
67686
|
+
display.resetPartialText();
|
|
67687
|
+
updateWorkflowData((wd) => applyWorkflowPhaseComplete(wd, d2.phase, d2.summary));
|
|
67688
|
+
}
|
|
67689
|
+
}
|
|
67690
|
+
};
|
|
67691
|
+
}
|
|
67692
|
+
|
|
67693
|
+
// src/core/integrations/wandb/upload.ts
|
|
67694
|
+
async function createWandbUploader(session, opts) {
|
|
67695
|
+
const resolved = resolveConfig(opts);
|
|
67696
|
+
if (!resolved.available)
|
|
67697
|
+
return null;
|
|
67698
|
+
const tracer = await createWeaveTracer(resolved.config);
|
|
67699
|
+
if (!tracer)
|
|
67700
|
+
return null;
|
|
67701
|
+
return {
|
|
67702
|
+
onRecord: (record) => tracer.logRecord(record, session.id),
|
|
67703
|
+
finalize: () => tracer.finish()
|
|
67704
|
+
};
|
|
67705
|
+
}
|
|
67706
|
+
async function attachWandbToEventBus(session, eventBus, opts) {
|
|
67707
|
+
const uploader = await createWandbUploader(session, opts);
|
|
67708
|
+
if (!uploader)
|
|
67709
|
+
return null;
|
|
67710
|
+
const handler = (e) => {
|
|
67711
|
+
uploader.onRecord(e.record);
|
|
67712
|
+
};
|
|
67713
|
+
eventBus.on("trace-record", handler);
|
|
67714
|
+
return async () => {
|
|
67715
|
+
eventBus.off("trace-record", handler);
|
|
67716
|
+
await uploader.finalize();
|
|
67717
|
+
};
|
|
67718
|
+
}
|
|
67719
|
+
|
|
67720
|
+
// src/tui/components/operator-dashboard/run-tracing.ts
|
|
67721
|
+
class RunTraceSession {
|
|
67722
|
+
eventBus;
|
|
67723
|
+
options;
|
|
67724
|
+
cleanup = null;
|
|
67725
|
+
earlyBuffer = [];
|
|
67726
|
+
countedSubagentSteps = new Set;
|
|
67727
|
+
earlyBufferHandler = (e) => {
|
|
67728
|
+
this.earlyBuffer?.push(e);
|
|
67729
|
+
};
|
|
67730
|
+
constructor(eventBus, options) {
|
|
67731
|
+
this.eventBus = eventBus;
|
|
67732
|
+
this.options = options;
|
|
67733
|
+
eventBus.on("trace-record", this.earlyBufferHandler);
|
|
67734
|
+
eventBus.on("trace-record", this.countSubagentStep);
|
|
67735
|
+
}
|
|
67736
|
+
async tryAttach(session) {
|
|
67737
|
+
if (this.cleanup)
|
|
67738
|
+
return;
|
|
67739
|
+
const attach = this.options.attach ?? attachWandbToEventBus;
|
|
67740
|
+
const cleanup = await attach(session, this.eventBus).catch((e) => {
|
|
67741
|
+
console.error("[wandb] Attach failed:", e);
|
|
67742
|
+
return null;
|
|
67743
|
+
});
|
|
67744
|
+
const buffered = this.earlyBuffer;
|
|
67745
|
+
this.stopBuffering();
|
|
67746
|
+
if (cleanup) {
|
|
67747
|
+
this.cleanup = cleanup;
|
|
67748
|
+
if (buffered) {
|
|
67749
|
+
for (const e of buffered)
|
|
67750
|
+
this.eventBus.emit("trace-record", e);
|
|
67751
|
+
}
|
|
67752
|
+
}
|
|
67753
|
+
}
|
|
67754
|
+
async cleanupRun() {
|
|
67755
|
+
this.stopBuffering();
|
|
67756
|
+
this.eventBus.off("trace-record", this.countSubagentStep);
|
|
67757
|
+
if (this.cleanup) {
|
|
67758
|
+
const fn = this.cleanup;
|
|
67759
|
+
this.cleanup = null;
|
|
67760
|
+
await fn().catch((e) => console.error("[wandb] Flush failed:", e));
|
|
67761
|
+
}
|
|
67762
|
+
}
|
|
67763
|
+
stopBuffering() {
|
|
67764
|
+
this.earlyBuffer = null;
|
|
67765
|
+
this.eventBus.off("trace-record", this.earlyBufferHandler);
|
|
67766
|
+
}
|
|
67767
|
+
countSubagentStep = (e) => {
|
|
67768
|
+
if (!this.options.isCurrent())
|
|
67769
|
+
return;
|
|
67770
|
+
const { record, subagentId } = e;
|
|
67771
|
+
if (!subagentId || record.type !== "step")
|
|
67772
|
+
return;
|
|
67773
|
+
const key = `${subagentId}:${record.stepIndex}:${record.timestamp}`;
|
|
67774
|
+
if (this.countedSubagentSteps.has(key))
|
|
67775
|
+
return;
|
|
67776
|
+
this.countedSubagentSteps.add(key);
|
|
67777
|
+
this.options.recordTokenUsage(record.usage.inputTokens, record.usage.outputTokens, record.usage.cacheReadTokens ?? 0, record.usage.cacheWriteTokens ?? 0);
|
|
67778
|
+
};
|
|
67779
|
+
}
|
|
67780
|
+
|
|
66844
67781
|
// src/tui/components/operator-dashboard/subagent-dialog.tsx
|
|
66845
67782
|
import { useKeyboard as useKeyboard25 } from "@opentui/react";
|
|
66846
67783
|
import {
|
|
@@ -66848,7 +67785,7 @@ import {
|
|
|
66848
67785
|
useMemo as useMemo21,
|
|
66849
67786
|
useRef as useRef20,
|
|
66850
67787
|
useState as useState38,
|
|
66851
|
-
useSyncExternalStore
|
|
67788
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
66852
67789
|
} from "react";
|
|
66853
67790
|
|
|
66854
67791
|
// src/tui/components/operator-dashboard/subagent-detail-view.tsx
|
|
@@ -66930,6 +67867,22 @@ function createSubagentStore() {
|
|
|
66930
67867
|
setState
|
|
66931
67868
|
};
|
|
66932
67869
|
}
|
|
67870
|
+
function markSubagentsInterrupted(prev) {
|
|
67871
|
+
let changed = false;
|
|
67872
|
+
const next = new Map(prev);
|
|
67873
|
+
for (const [id, session] of next) {
|
|
67874
|
+
const hasInFlight = session.messages.some((m2) => m2.role === "tool" && (m2.status === "pending" || m2.status === "streaming"));
|
|
67875
|
+
if (!hasInFlight && session.status !== "running")
|
|
67876
|
+
continue;
|
|
67877
|
+
changed = true;
|
|
67878
|
+
next.set(id, {
|
|
67879
|
+
...session,
|
|
67880
|
+
status: session.status === "running" ? "cancelled" : session.status,
|
|
67881
|
+
messages: session.messages.map((m2) => m2.role === "tool" && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result: "Interrupted" } : m2)
|
|
67882
|
+
});
|
|
67883
|
+
}
|
|
67884
|
+
return changed ? next : prev;
|
|
67885
|
+
}
|
|
66933
67886
|
function createSubagentSessionHelpers(setState) {
|
|
66934
67887
|
const toolArgsDeltaBuffers = new Map;
|
|
66935
67888
|
const spawnSession = (id, name, input) => {
|
|
@@ -67340,7 +68293,7 @@ function SubagentDialog({ store }) {
|
|
|
67340
68293
|
const [view, setView] = useState38({ type: "hub" });
|
|
67341
68294
|
const viewRef = useRef20(view);
|
|
67342
68295
|
viewRef.current = view;
|
|
67343
|
-
const sessions2 =
|
|
68296
|
+
const sessions2 = useSyncExternalStore2(store.subscribe, store.getSnapshot);
|
|
67344
68297
|
useEffect24(() => {
|
|
67345
68298
|
setSize(view.type === "detail" ? "xlarge" : "large");
|
|
67346
68299
|
}, [view.type, setSize]);
|
|
@@ -67498,10 +68451,7 @@ var SubagentStatusBar = memo6(function SubagentStatusBar2({
|
|
|
67498
68451
|
});
|
|
67499
68452
|
|
|
67500
68453
|
// src/tui/components/operator-dashboard/index.tsx
|
|
67501
|
-
import { jsxDEV as jsxDEV56, Fragment as
|
|
67502
|
-
function markInFlightToolsErrored(messages, result) {
|
|
67503
|
-
return messages.map((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result } : m2);
|
|
67504
|
-
}
|
|
68454
|
+
import { jsxDEV as jsxDEV56, Fragment as Fragment7 } from "@opentui/react/jsx-dev-runtime";
|
|
67505
68455
|
function OperatorDashboard({
|
|
67506
68456
|
sessionId,
|
|
67507
68457
|
initialMessage,
|
|
@@ -67516,10 +68466,8 @@ function OperatorDashboard({
|
|
|
67516
68466
|
isModelUserSelected,
|
|
67517
68467
|
setThinking,
|
|
67518
68468
|
setIsExecuting,
|
|
67519
|
-
|
|
67520
|
-
|
|
67521
|
-
addCacheUsage,
|
|
67522
|
-
resetTokenUsage,
|
|
68469
|
+
usageStore,
|
|
68470
|
+
markExecuted,
|
|
67523
68471
|
setSessionCwd,
|
|
67524
68472
|
reasoningEnabled,
|
|
67525
68473
|
openAIReasoningEffort
|
|
@@ -67579,7 +68527,7 @@ function OperatorDashboard({
|
|
|
67579
68527
|
});
|
|
67580
68528
|
const commandCancelledRef = useRef21(false);
|
|
67581
68529
|
const subagentStore = useMemo22(() => createSubagentStore(), []);
|
|
67582
|
-
const subagentSessions =
|
|
68530
|
+
const subagentSessions = useSyncExternalStore3(subagentStore.subscribe, subagentStore.getSnapshot);
|
|
67583
68531
|
const subagentHelpers = useMemo22(() => createSubagentSessionHelpers(subagentStore.setState), [subagentStore]);
|
|
67584
68532
|
const messageCountAtSubagentDoneRef = useRef21(null);
|
|
67585
68533
|
const hasRunningSubagent = useMemo22(() => Array.from(subagentSessions.values()).some((s) => s.status === "running"), [subagentSessions]);
|
|
@@ -67592,7 +68540,7 @@ function OperatorDashboard({
|
|
|
67592
68540
|
messageCountAtSubagentDoneRef.current = null;
|
|
67593
68541
|
}
|
|
67594
68542
|
}, [subagentSessions, hasRunningSubagent]);
|
|
67595
|
-
const openSubagentDialog =
|
|
68543
|
+
const openSubagentDialog = useCallback22(() => {
|
|
67596
68544
|
replaceDialog(/* @__PURE__ */ jsxDEV56(SubagentDialog, {
|
|
67597
68545
|
store: subagentStore
|
|
67598
68546
|
}, undefined, false, undefined, this), {
|
|
@@ -67603,7 +68551,6 @@ function OperatorDashboard({
|
|
|
67603
68551
|
const [messages, setMessages] = useState39([]);
|
|
67604
68552
|
const displayMessagesRef = useRef21([]);
|
|
67605
68553
|
displayMessagesRef.current = messages;
|
|
67606
|
-
const textRef = useRef21("");
|
|
67607
68554
|
const conversationRef = useRef21([]);
|
|
67608
68555
|
const [inputValue, setInputValue] = useState39("");
|
|
67609
68556
|
const [queuedMessages, setQueuedMessages] = useState39([]);
|
|
@@ -67644,10 +68591,6 @@ function OperatorDashboard({
|
|
|
67644
68591
|
useEffect25(() => {
|
|
67645
68592
|
approvedPlanRef.current = approvedPlanContent;
|
|
67646
68593
|
}, [approvedPlanContent]);
|
|
67647
|
-
const tokenUsageRef = useRef21(tokenUsage);
|
|
67648
|
-
useEffect25(() => {
|
|
67649
|
-
tokenUsageRef.current = tokenUsage;
|
|
67650
|
-
}, [tokenUsage]);
|
|
67651
68594
|
useEffect25(() => {
|
|
67652
68595
|
const gate = approvalGateRef.current;
|
|
67653
68596
|
const onApprovalNeeded = () => {
|
|
@@ -67766,188 +68709,63 @@ function OperatorDashboard({
|
|
|
67766
68709
|
refocusPrompt();
|
|
67767
68710
|
}
|
|
67768
68711
|
}, [loading, refocusPrompt]);
|
|
68712
|
+
useEffect25(() => {
|
|
68713
|
+
if (sessionId === undefined)
|
|
68714
|
+
usageStore.beginNewSession();
|
|
68715
|
+
}, [sessionId, usageStore]);
|
|
67769
68716
|
useEffect25(() => {
|
|
67770
68717
|
if (!session || !sessionId)
|
|
67771
68718
|
return;
|
|
67772
|
-
resetTokenUsage();
|
|
67773
|
-
tokenUsageRef.current = {
|
|
67774
|
-
inputTokens: 0,
|
|
67775
|
-
outputTokens: 0,
|
|
67776
|
-
totalTokens: 0,
|
|
67777
|
-
cachedTokens: 0,
|
|
67778
|
-
cacheWriteTokens: 0
|
|
67779
|
-
};
|
|
67780
68719
|
const metrics = readExecutionMetrics(session.rootPath);
|
|
67781
|
-
|
|
67782
|
-
|
|
67783
|
-
|
|
67784
|
-
tokenUsageRef.current = {
|
|
67785
|
-
...persisted,
|
|
67786
|
-
cachedTokens: 0,
|
|
67787
|
-
cacheWriteTokens: 0
|
|
67788
|
-
};
|
|
67789
|
-
}
|
|
67790
|
-
try {
|
|
67791
|
-
writeExecutionMetrics({
|
|
67792
|
-
sessionRootPath: session.rootPath,
|
|
67793
|
-
tokenUsage: tokenUsageRef.current
|
|
67794
|
-
});
|
|
67795
|
-
} catch {}
|
|
67796
|
-
}, [session, sessionId, addTokenUsage, resetTokenUsage]);
|
|
67797
|
-
const appendText = useCallback20((text) => {
|
|
67798
|
-
textRef.current += text;
|
|
67799
|
-
const accumulated = textRef.current;
|
|
67800
|
-
setMessages((prev) => {
|
|
67801
|
-
const last = prev[prev.length - 1];
|
|
67802
|
-
if (last && last.role === "assistant") {
|
|
67803
|
-
const updated = [...prev];
|
|
67804
|
-
updated[updated.length - 1] = { ...last, content: accumulated };
|
|
67805
|
-
return updated;
|
|
67806
|
-
}
|
|
67807
|
-
return [
|
|
67808
|
-
...prev,
|
|
67809
|
-
{ role: "assistant", content: accumulated, createdAt: new Date }
|
|
67810
|
-
];
|
|
67811
|
-
});
|
|
67812
|
-
}, []);
|
|
67813
|
-
const toolArgsDeltaRef = useRef21(new Map);
|
|
67814
|
-
const addStreamingToolCall = useCallback20((toolCallId, toolName) => {
|
|
67815
|
-
textRef.current = "";
|
|
67816
|
-
toolArgsDeltaRef.current.set(toolCallId, {
|
|
67817
|
-
toolName,
|
|
67818
|
-
accumulated: ""
|
|
67819
|
-
});
|
|
67820
|
-
setMessages((prev) => [
|
|
67821
|
-
...prev,
|
|
67822
|
-
{
|
|
67823
|
-
role: "tool",
|
|
67824
|
-
content: "",
|
|
67825
|
-
createdAt: new Date,
|
|
67826
|
-
toolCallId,
|
|
67827
|
-
toolName,
|
|
67828
|
-
args: {},
|
|
67829
|
-
status: "streaming"
|
|
67830
|
-
}
|
|
67831
|
-
]);
|
|
67832
|
-
}, []);
|
|
67833
|
-
const appendToolCallDelta = useCallback20((toolCallId, argsTextDelta) => {
|
|
67834
|
-
const entry = toolArgsDeltaRef.current.get(toolCallId);
|
|
67835
|
-
const accumulated = (entry?.accumulated ?? "") + argsTextDelta;
|
|
67836
|
-
toolArgsDeltaRef.current.set(toolCallId, {
|
|
67837
|
-
toolName: entry?.toolName ?? "",
|
|
67838
|
-
accumulated
|
|
67839
|
-
});
|
|
67840
|
-
const parsed = tryParsePartialJson(accumulated);
|
|
67841
|
-
if (!parsed)
|
|
67842
|
-
return;
|
|
67843
|
-
const contentText = extractStreamableContent(parsed);
|
|
67844
|
-
const logs = contentText ? contentText.split(`
|
|
67845
|
-
`) : undefined;
|
|
67846
|
-
setMessages((msgs) => {
|
|
67847
|
-
const idx = msgs.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
67848
|
-
if (idx === -1)
|
|
67849
|
-
return msgs;
|
|
67850
|
-
const updated = [...msgs];
|
|
67851
|
-
updated[idx] = { ...updated[idx], args: parsed, ...logs && { logs } };
|
|
67852
|
-
return updated;
|
|
67853
|
-
});
|
|
67854
|
-
}, []);
|
|
67855
|
-
const addToolCall = useCallback20((toolCallId, toolName, args) => {
|
|
67856
|
-
textRef.current = "";
|
|
67857
|
-
toolArgsDeltaRef.current.delete(toolCallId);
|
|
67858
|
-
setMessages((prev) => {
|
|
67859
|
-
const idx = prev.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
67860
|
-
if (idx !== -1) {
|
|
67861
|
-
const updated = [...prev];
|
|
67862
|
-
updated[idx] = {
|
|
67863
|
-
...updated[idx],
|
|
67864
|
-
args,
|
|
67865
|
-
logs: undefined,
|
|
67866
|
-
status: "pending"
|
|
67867
|
-
};
|
|
67868
|
-
return updated;
|
|
67869
|
-
}
|
|
67870
|
-
return [
|
|
67871
|
-
...prev,
|
|
67872
|
-
{
|
|
67873
|
-
role: "tool",
|
|
67874
|
-
content: "",
|
|
67875
|
-
createdAt: new Date,
|
|
67876
|
-
toolCallId,
|
|
67877
|
-
toolName,
|
|
67878
|
-
args,
|
|
67879
|
-
status: "pending"
|
|
67880
|
-
}
|
|
67881
|
-
];
|
|
68720
|
+
usageStore.enterSession(session.id, {
|
|
68721
|
+
...metrics?.tokenUsage ? { tokenUsage: metrics.tokenUsage } : {},
|
|
68722
|
+
...metrics?.contextUsage ? { contextUsage: metrics.contextUsage } : {}
|
|
67882
68723
|
});
|
|
67883
|
-
}, []);
|
|
67884
|
-
const
|
|
67885
|
-
|
|
67886
|
-
setMessages
|
|
67887
|
-
|
|
67888
|
-
|
|
67889
|
-
|
|
67890
|
-
const updated = [...prev];
|
|
67891
|
-
updated[idx] = { ...updated[idx], status: "completed", result };
|
|
67892
|
-
return updated;
|
|
67893
|
-
});
|
|
67894
|
-
}, []);
|
|
67895
|
-
const cmdOutputBufRef = useRef21("");
|
|
67896
|
-
const cmdFlushTimerRef = useRef21(null);
|
|
67897
|
-
const MAX_LOG_LINES = 200;
|
|
67898
|
-
const flushCommandOutput = useCallback20(() => {
|
|
67899
|
-
const buf = cmdOutputBufRef.current;
|
|
67900
|
-
if (!buf)
|
|
67901
|
-
return;
|
|
67902
|
-
cmdOutputBufRef.current = "";
|
|
67903
|
-
setMessages((prev) => {
|
|
67904
|
-
const idx = prev.findLastIndex((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming"));
|
|
67905
|
-
if (idx === -1)
|
|
67906
|
-
return prev;
|
|
67907
|
-
const msg = prev[idx];
|
|
67908
|
-
const existing = msg.logs ?? [];
|
|
67909
|
-
const incoming = buf.split(`
|
|
67910
|
-
`);
|
|
67911
|
-
let merged;
|
|
67912
|
-
if (existing.length > 0 && !buf.startsWith(`
|
|
67913
|
-
`)) {
|
|
67914
|
-
merged = [...existing];
|
|
67915
|
-
merged[merged.length - 1] += incoming[0];
|
|
67916
|
-
merged.push(...incoming.slice(1));
|
|
67917
|
-
} else {
|
|
67918
|
-
merged = [...existing, ...incoming];
|
|
67919
|
-
}
|
|
67920
|
-
if (merged.length > MAX_LOG_LINES) {
|
|
67921
|
-
merged = merged.slice(-MAX_LOG_LINES);
|
|
67922
|
-
}
|
|
67923
|
-
const updated = [...prev];
|
|
67924
|
-
updated[idx] = { ...msg, logs: merged };
|
|
67925
|
-
return updated;
|
|
67926
|
-
});
|
|
67927
|
-
}, []);
|
|
67928
|
-
const onCommandOutput = useCallback20((data) => {
|
|
67929
|
-
cmdOutputBufRef.current += data;
|
|
67930
|
-
if (!cmdFlushTimerRef.current) {
|
|
67931
|
-
cmdFlushTimerRef.current = setInterval(() => {
|
|
67932
|
-
flushCommandOutput();
|
|
67933
|
-
}, 150);
|
|
67934
|
-
}
|
|
67935
|
-
}, [flushCommandOutput]);
|
|
68724
|
+
}, [session, sessionId, usageStore]);
|
|
68725
|
+
const runSessionIdRef = useRef21(null);
|
|
68726
|
+
const displayEvents = useMemo22(() => createDisplayEventHandlers({
|
|
68727
|
+
updateMessages: setMessages,
|
|
68728
|
+
setThinking,
|
|
68729
|
+
setError
|
|
68730
|
+
}), [setThinking]);
|
|
67936
68731
|
useEffect25(() => {
|
|
67937
68732
|
return () => {
|
|
67938
|
-
|
|
67939
|
-
clearInterval(cmdFlushTimerRef.current);
|
|
67940
|
-
cmdFlushTimerRef.current = null;
|
|
67941
|
-
}
|
|
68733
|
+
displayEvents.dispose();
|
|
67942
68734
|
};
|
|
68735
|
+
}, [displayEvents]);
|
|
68736
|
+
const updateWorkflowData = useCallback22((updater) => {
|
|
68737
|
+
setMessages((prev) => updateWorkflowDataMessage(prev, updater));
|
|
67943
68738
|
}, []);
|
|
67944
|
-
const
|
|
68739
|
+
const runEventProjections = useMemo22(() => createRunEventProjections({
|
|
68740
|
+
display: displayEvents,
|
|
68741
|
+
subagents: subagentHelpers,
|
|
68742
|
+
updateWorkflowData,
|
|
68743
|
+
clearSubagentSessions: () => subagentStore.setState(new Map),
|
|
68744
|
+
questions: {
|
|
68745
|
+
onAsked: (toolCallId, questions) => {
|
|
68746
|
+
pendingToolCallIdRef.current = toolCallId;
|
|
68747
|
+
setPendingQuestions(questions);
|
|
68748
|
+
},
|
|
68749
|
+
onCleared: () => {
|
|
68750
|
+
pendingToolCallIdRef.current = null;
|
|
68751
|
+
setPendingQuestions(null);
|
|
68752
|
+
}
|
|
68753
|
+
},
|
|
68754
|
+
onRootToolCallStarted: () => {
|
|
68755
|
+
commandCancelledRef.current = false;
|
|
68756
|
+
},
|
|
68757
|
+
onPlanSubmitted: () => {
|
|
68758
|
+
planSubmittedRef.current = true;
|
|
68759
|
+
planGateBypassedOnResumeRef.current = false;
|
|
68760
|
+
}
|
|
68761
|
+
}), [displayEvents, subagentHelpers, updateWorkflowData, subagentStore]);
|
|
68762
|
+
const handleApprove = useCallback22(() => {
|
|
67945
68763
|
const pending = approvalGateRef.current.getPendingApprovals();
|
|
67946
68764
|
if (pending.length > 0) {
|
|
67947
68765
|
approvalGateRef.current.approve(pending[0].id);
|
|
67948
68766
|
}
|
|
67949
68767
|
}, []);
|
|
67950
|
-
const handleAutoApprove =
|
|
68768
|
+
const handleAutoApprove = useCallback22(() => {
|
|
67951
68769
|
setOperatorMode("auto");
|
|
67952
68770
|
setOperatorState((prev) => ({
|
|
67953
68771
|
...prev,
|
|
@@ -67960,17 +68778,18 @@ function OperatorDashboard({
|
|
|
67960
68778
|
approvalGateRef.current.approve(p.id);
|
|
67961
68779
|
}
|
|
67962
68780
|
}, []);
|
|
67963
|
-
const runAgent =
|
|
68781
|
+
const runAgent = useCallback22(async (prompt) => {
|
|
67964
68782
|
if (abortControllerRef.current) {
|
|
67965
68783
|
abortControllerRef.current.abort();
|
|
67966
68784
|
abortControllerRef.current = null;
|
|
67967
68785
|
}
|
|
67968
68786
|
const gen = ++generationRef.current;
|
|
68787
|
+
runSessionIdRef.current = sessionRef.current?.id ?? session?.id ?? null;
|
|
67969
68788
|
setStatus("running");
|
|
67970
68789
|
setThinking(true);
|
|
67971
68790
|
setIsExecuting(true);
|
|
67972
68791
|
setError(null);
|
|
67973
|
-
|
|
68792
|
+
displayEvents.resetPartialText();
|
|
67974
68793
|
const controller = new AbortController;
|
|
67975
68794
|
abortControllerRef.current = controller;
|
|
67976
68795
|
const prevMessages = conversationRef.current;
|
|
@@ -67987,259 +68806,58 @@ function OperatorDashboard({
|
|
|
67987
68806
|
conversationRef.current = nextMessages;
|
|
67988
68807
|
if (sessionRef.current) {
|
|
67989
68808
|
try {
|
|
67990
|
-
const mp =
|
|
67991
|
-
|
|
68809
|
+
const mp = join4(sessionRef.current.rootPath, "messages.json");
|
|
68810
|
+
writeFileSync2(mp, JSON.stringify(nextMessages, null, 2));
|
|
67992
68811
|
} catch {}
|
|
67993
68812
|
}
|
|
67994
68813
|
} else {
|
|
67995
68814
|
nextMessages = conversationRef.current;
|
|
67996
68815
|
}
|
|
67997
68816
|
const recordTokenUsage = (inputTokens, outputTokens, cacheReadTokens = 0, cacheWriteTokens = 0) => {
|
|
67998
|
-
|
|
67999
|
-
|
|
68000
|
-
|
|
68001
|
-
|
|
68002
|
-
|
|
68003
|
-
|
|
68004
|
-
|
|
68005
|
-
|
|
68006
|
-
|
|
68007
|
-
|
|
68008
|
-
|
|
68009
|
-
|
|
68817
|
+
if (inputTokens > 0 || outputTokens > 0)
|
|
68818
|
+
markExecuted();
|
|
68819
|
+
const runSessionId = runSessionIdRef.current;
|
|
68820
|
+
usageStore.addSessionTokens(runSessionId, {
|
|
68821
|
+
inputTokens,
|
|
68822
|
+
outputTokens,
|
|
68823
|
+
cacheReadTokens,
|
|
68824
|
+
cacheWriteTokens
|
|
68825
|
+
});
|
|
68826
|
+
const activeSession = sessionRef.current;
|
|
68827
|
+
if (activeSession) {
|
|
68828
|
+
try {
|
|
68829
|
+
const usage = usageStore.getSnapshot(activeSession.id);
|
|
68830
|
+
writeExecutionMetrics({
|
|
68831
|
+
sessionRootPath: activeSession.rootPath,
|
|
68832
|
+
tokenUsage: usage.tokenUsage,
|
|
68833
|
+
...usage.contextUsage ? { contextUsage: usage.contextUsage } : {}
|
|
68834
|
+
});
|
|
68835
|
+
} catch {}
|
|
68010
68836
|
}
|
|
68011
|
-
|
|
68012
|
-
|
|
68837
|
+
};
|
|
68838
|
+
const runModelId = model.id;
|
|
68839
|
+
const recordRootStepUsage = (usage) => {
|
|
68840
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
68841
|
+
if (inputTokens > 0) {
|
|
68842
|
+
usageStore.setRootContext(runSessionIdRef.current, {
|
|
68843
|
+
usedTokens: inputTokens,
|
|
68844
|
+
contextLimit: getContextWindow(runModelId),
|
|
68845
|
+
modelId: runModelId
|
|
68846
|
+
});
|
|
68013
68847
|
}
|
|
68848
|
+
recordTokenUsage(inputTokens, usage.outputTokens ?? 0);
|
|
68014
68849
|
};
|
|
68015
68850
|
const onStepFinish = (event) => {
|
|
68016
|
-
|
|
68851
|
+
recordRootStepUsage(event.usage ?? {});
|
|
68017
68852
|
};
|
|
68018
68853
|
const eventBus = new AgentEventBus;
|
|
68019
|
-
const
|
|
68020
|
-
|
|
68021
|
-
|
|
68022
|
-
const idx = prev.findLastIndex((m2) => isToolMessage(m2) && m2.toolName === "run_pentest_workflow" && (m2.status === "pending" || m2.status === "streaming"));
|
|
68023
|
-
if (idx === -1)
|
|
68024
|
-
return prev;
|
|
68025
|
-
const msg = prev[idx];
|
|
68026
|
-
const wd = msg.workflowData ?? {
|
|
68027
|
-
currentPhase: "discovery",
|
|
68028
|
-
discovery: { label: "", status: "pending", logs: [] },
|
|
68029
|
-
pentesting: {
|
|
68030
|
-
label: "",
|
|
68031
|
-
status: "idle",
|
|
68032
|
-
subagents: {}
|
|
68033
|
-
},
|
|
68034
|
-
reporting: { label: "", status: "idle" }
|
|
68035
|
-
};
|
|
68036
|
-
const updated = [...prev];
|
|
68037
|
-
updated[idx] = { ...msg, workflowData: updater(wd) };
|
|
68038
|
-
return updated;
|
|
68039
|
-
});
|
|
68040
|
-
};
|
|
68041
|
-
eventBus.on("text-delta", (d2) => {
|
|
68042
|
-
if (gen !== generationRef.current)
|
|
68043
|
-
return;
|
|
68044
|
-
if (d2.subagentId) {
|
|
68045
|
-
subagentHelpers.appendText(d2.subagentId, d2.text);
|
|
68046
|
-
return;
|
|
68047
|
-
}
|
|
68048
|
-
setThinking(false);
|
|
68049
|
-
appendText(d2.text);
|
|
68854
|
+
const runTrace = new RunTraceSession(eventBus, {
|
|
68855
|
+
isCurrent: () => gen === generationRef.current,
|
|
68856
|
+
recordTokenUsage
|
|
68050
68857
|
});
|
|
68051
|
-
eventBus
|
|
68052
|
-
|
|
68053
|
-
|
|
68054
|
-
if (d2.subagentId) {
|
|
68055
|
-
subagentHelpers.addStreamingToolCall(d2.subagentId, d2.toolCallId, d2.toolName);
|
|
68056
|
-
return;
|
|
68057
|
-
}
|
|
68058
|
-
setThinking(false);
|
|
68059
|
-
addStreamingToolCall(d2.toolCallId, d2.toolName);
|
|
68060
|
-
});
|
|
68061
|
-
eventBus.on("tool-call-delta", (d2) => {
|
|
68062
|
-
if (gen !== generationRef.current)
|
|
68063
|
-
return;
|
|
68064
|
-
if (d2.subagentId) {
|
|
68065
|
-
subagentHelpers.appendToolCallDelta(d2.subagentId, d2.toolCallId, d2.argsTextDelta);
|
|
68066
|
-
return;
|
|
68067
|
-
}
|
|
68068
|
-
appendToolCallDelta(d2.toolCallId, d2.argsTextDelta);
|
|
68069
|
-
});
|
|
68070
|
-
eventBus.on("tool-call-complete", (d2) => {
|
|
68071
|
-
if (gen !== generationRef.current)
|
|
68072
|
-
return;
|
|
68073
|
-
if (d2.subagentId) {
|
|
68074
|
-
const args2 = d2.args && typeof d2.args === "object" && !Array.isArray(d2.args) && d2.args !== null ? d2.args : {};
|
|
68075
|
-
subagentHelpers.addToolCall(d2.subagentId, d2.toolCallId, d2.toolName, args2);
|
|
68076
|
-
return;
|
|
68077
|
-
}
|
|
68078
|
-
setThinking(false);
|
|
68079
|
-
commandCancelledRef.current = false;
|
|
68080
|
-
const args = d2.args && typeof d2.args === "object" && !Array.isArray(d2.args) && d2.args !== null ? d2.args : undefined;
|
|
68081
|
-
addToolCall(d2.toolCallId, d2.toolName, args);
|
|
68082
|
-
if (d2.toolName === ASK_USER_QUESTIONS_TOOL_NAME && args) {
|
|
68083
|
-
const rawQuestions = args.questions;
|
|
68084
|
-
if (Array.isArray(rawQuestions) && rawQuestions.length > 0) {
|
|
68085
|
-
pendingToolCallIdRef.current = d2.toolCallId;
|
|
68086
|
-
setPendingQuestions(rawQuestions);
|
|
68087
|
-
}
|
|
68088
|
-
}
|
|
68089
|
-
});
|
|
68090
|
-
eventBus.on("tool-result", (d2) => {
|
|
68091
|
-
if (gen !== generationRef.current)
|
|
68092
|
-
return;
|
|
68093
|
-
if (d2.subagentId) {
|
|
68094
|
-
subagentHelpers.updateToolResult(d2.subagentId, d2.toolCallId, d2.result);
|
|
68095
|
-
return;
|
|
68096
|
-
}
|
|
68097
|
-
flushCommandOutput();
|
|
68098
|
-
if (cmdFlushTimerRef.current) {
|
|
68099
|
-
clearInterval(cmdFlushTimerRef.current);
|
|
68100
|
-
cmdFlushTimerRef.current = null;
|
|
68101
|
-
}
|
|
68102
|
-
setThinking(true);
|
|
68103
|
-
updateToolResult(d2.toolCallId, d2.toolName, d2.result);
|
|
68104
|
-
if (d2.toolName === "submit_plan" && d2.result?.success === true) {
|
|
68105
|
-
planSubmittedRef.current = true;
|
|
68106
|
-
planGateBypassedOnResumeRef.current = false;
|
|
68107
|
-
}
|
|
68108
|
-
});
|
|
68109
|
-
eventBus.on("command-output", (d2) => {
|
|
68110
|
-
if (gen !== generationRef.current)
|
|
68111
|
-
return;
|
|
68112
|
-
if (d2.subagentId)
|
|
68113
|
-
return;
|
|
68114
|
-
onCommandOutput(d2.data);
|
|
68115
|
-
});
|
|
68116
|
-
eventBus.on("error", (d2) => {
|
|
68117
|
-
if (gen !== generationRef.current)
|
|
68118
|
-
return;
|
|
68119
|
-
if (d2.subagentId) {
|
|
68120
|
-
const errMsg = d2.error instanceof Error ? d2.error.message : "Unknown error";
|
|
68121
|
-
subagentHelpers.appendText(d2.subagentId, `
|
|
68122
|
-
Error: ${errMsg}
|
|
68123
|
-
`);
|
|
68124
|
-
return;
|
|
68125
|
-
}
|
|
68126
|
-
console.error("Agent error:", d2.error);
|
|
68127
|
-
pendingToolCallIdRef.current = null;
|
|
68128
|
-
setPendingQuestions(null);
|
|
68129
|
-
const errorMessage = d2.error instanceof Error ? d2.error.message : "Unknown error";
|
|
68130
|
-
setError(errorMessage);
|
|
68131
|
-
setMessages((prev) => markInFlightToolsErrored(prev, errorMessage));
|
|
68132
|
-
});
|
|
68133
|
-
eventBus.on("subagent-spawn", ({ subagentId, name }) => {
|
|
68134
|
-
if (gen !== generationRef.current)
|
|
68135
|
-
return;
|
|
68136
|
-
if (subagentId.startsWith("app:"))
|
|
68137
|
-
return;
|
|
68138
|
-
subagentHelpers.spawnSession(subagentId, name);
|
|
68139
|
-
if (!isPentestAgent(subagentId))
|
|
68140
|
-
return;
|
|
68141
|
-
updateWorkflowData((wd) => ({
|
|
68142
|
-
...wd,
|
|
68143
|
-
pentesting: {
|
|
68144
|
-
...wd.pentesting,
|
|
68145
|
-
subagents: {
|
|
68146
|
-
...wd.pentesting.subagents,
|
|
68147
|
-
[subagentId]: {
|
|
68148
|
-
name,
|
|
68149
|
-
status: "pending",
|
|
68150
|
-
logs: []
|
|
68151
|
-
}
|
|
68152
|
-
}
|
|
68153
|
-
}
|
|
68154
|
-
}));
|
|
68155
|
-
});
|
|
68156
|
-
eventBus.on("subagent-complete", ({ subagentId, status: status2 }) => {
|
|
68157
|
-
if (gen !== generationRef.current)
|
|
68158
|
-
return;
|
|
68159
|
-
if (subagentId.startsWith("app:"))
|
|
68160
|
-
return;
|
|
68161
|
-
subagentHelpers.completeSession(subagentId, status2);
|
|
68162
|
-
if (!isPentestAgent(subagentId))
|
|
68163
|
-
return;
|
|
68164
|
-
updateWorkflowData((wd) => {
|
|
68165
|
-
const entry = wd.pentesting.subagents[subagentId];
|
|
68166
|
-
if (!entry)
|
|
68167
|
-
return wd;
|
|
68168
|
-
return {
|
|
68169
|
-
...wd,
|
|
68170
|
-
pentesting: {
|
|
68171
|
-
...wd.pentesting,
|
|
68172
|
-
subagents: {
|
|
68173
|
-
...wd.pentesting.subagents,
|
|
68174
|
-
[subagentId]: { ...entry, status: status2 }
|
|
68175
|
-
}
|
|
68176
|
-
}
|
|
68177
|
-
};
|
|
68178
|
-
});
|
|
68179
|
-
});
|
|
68180
|
-
eventBus.on("workflow-phase-start", (d2) => {
|
|
68181
|
-
if (gen !== generationRef.current)
|
|
68182
|
-
return;
|
|
68183
|
-
textRef.current = "";
|
|
68184
|
-
if (d2.phase === "discovery") {
|
|
68185
|
-
subagentStore.setState(new Map);
|
|
68186
|
-
}
|
|
68187
|
-
updateWorkflowData((wd) => {
|
|
68188
|
-
const next = {
|
|
68189
|
-
...wd,
|
|
68190
|
-
currentPhase: d2.phase
|
|
68191
|
-
};
|
|
68192
|
-
if (d2.phase === "discovery") {
|
|
68193
|
-
next.discovery = {
|
|
68194
|
-
...wd.discovery,
|
|
68195
|
-
label: d2.label,
|
|
68196
|
-
status: "pending",
|
|
68197
|
-
logs: []
|
|
68198
|
-
};
|
|
68199
|
-
} else if (d2.phase === "pentesting") {
|
|
68200
|
-
next.pentesting = {
|
|
68201
|
-
...wd.pentesting,
|
|
68202
|
-
label: d2.label,
|
|
68203
|
-
status: "pending"
|
|
68204
|
-
};
|
|
68205
|
-
} else if (d2.phase === "reporting") {
|
|
68206
|
-
next.reporting = {
|
|
68207
|
-
...wd.reporting,
|
|
68208
|
-
label: d2.label,
|
|
68209
|
-
status: "pending"
|
|
68210
|
-
};
|
|
68211
|
-
}
|
|
68212
|
-
return next;
|
|
68213
|
-
});
|
|
68214
|
-
});
|
|
68215
|
-
eventBus.on("workflow-phase-complete", (d2) => {
|
|
68216
|
-
if (gen !== generationRef.current)
|
|
68217
|
-
return;
|
|
68218
|
-
textRef.current = "";
|
|
68219
|
-
updateWorkflowData((wd) => {
|
|
68220
|
-
const next = { ...wd };
|
|
68221
|
-
if (d2.phase === "discovery") {
|
|
68222
|
-
const targets = d2.summary.targets ?? [];
|
|
68223
|
-
next.discovery = {
|
|
68224
|
-
...wd.discovery,
|
|
68225
|
-
status: "complete",
|
|
68226
|
-
targets,
|
|
68227
|
-
cached: d2.summary.cached
|
|
68228
|
-
};
|
|
68229
|
-
} else if (d2.phase === "pentesting") {
|
|
68230
|
-
next.pentesting = { ...wd.pentesting, status: "complete" };
|
|
68231
|
-
} else if (d2.phase === "reporting") {
|
|
68232
|
-
next.reporting = {
|
|
68233
|
-
...wd.reporting,
|
|
68234
|
-
status: "complete",
|
|
68235
|
-
findingsCount: d2.summary.findingsCount,
|
|
68236
|
-
findingsBySeverity: d2.summary.findingsBySeverity,
|
|
68237
|
-
reportPath: d2.summary.reportPath
|
|
68238
|
-
};
|
|
68239
|
-
next.currentPhase = "complete";
|
|
68240
|
-
}
|
|
68241
|
-
return next;
|
|
68242
|
-
});
|
|
68858
|
+
const unbindRunEvents = bindOperatorRunEvents(eventBus, {
|
|
68859
|
+
isCurrent: () => gen === generationRef.current,
|
|
68860
|
+
handlers: runEventProjections.handlers
|
|
68243
68861
|
});
|
|
68244
68862
|
const skillsCatalog = skillsRegistry.buildCatalog() || undefined;
|
|
68245
68863
|
const commonInput = {
|
|
@@ -68267,59 +68885,24 @@ Error: ${errMsg}
|
|
|
68267
68885
|
promptInjectionLibrarySource: initialConfig?.promptInjectionLibrarySource ?? (route.data.type === "operator" ? route.data.initialSkill?.args?.library : undefined),
|
|
68268
68886
|
onStepFinish,
|
|
68269
68887
|
onCacheMetrics: (metrics) => {
|
|
68270
|
-
|
|
68888
|
+
usageStore.addSessionTokens(runSessionIdRef.current, {
|
|
68889
|
+
cacheReadTokens: metrics.cacheReadInputTokens,
|
|
68890
|
+
cacheWriteTokens: metrics.cacheCreationInputTokens
|
|
68891
|
+
});
|
|
68271
68892
|
},
|
|
68272
68893
|
eventBus,
|
|
68273
68894
|
onSessionReady: (s) => {
|
|
68274
68895
|
setSessionCwd(s.rootPath);
|
|
68275
68896
|
sessionRef.current = s;
|
|
68276
68897
|
setSession((prev) => prev ?? s);
|
|
68277
|
-
|
|
68278
|
-
|
|
68279
|
-
|
|
68280
|
-
let wandbCleanup = null;
|
|
68281
|
-
let earlyBuffer = [];
|
|
68282
|
-
const earlyBufferHandler = (e) => {
|
|
68283
|
-
earlyBuffer?.push(e);
|
|
68284
|
-
};
|
|
68285
|
-
eventBus.on("trace-record", earlyBufferHandler);
|
|
68286
|
-
const countedSubagentSteps = new Set;
|
|
68287
|
-
eventBus.on("trace-record", ({ record, subagentId }) => {
|
|
68288
|
-
if (gen !== generationRef.current)
|
|
68289
|
-
return;
|
|
68290
|
-
if (!subagentId || record.type !== "step")
|
|
68291
|
-
return;
|
|
68292
|
-
const key = `${subagentId}:${record.stepIndex}:${record.timestamp}`;
|
|
68293
|
-
if (countedSubagentSteps.has(key))
|
|
68294
|
-
return;
|
|
68295
|
-
countedSubagentSteps.add(key);
|
|
68296
|
-
recordTokenUsage(record.usage.inputTokens, record.usage.outputTokens, record.usage.cacheReadTokens ?? 0, record.usage.cacheWriteTokens ?? 0);
|
|
68297
|
-
});
|
|
68298
|
-
const tryAttachWandb = async (s) => {
|
|
68299
|
-
if (wandbCleanup)
|
|
68300
|
-
return;
|
|
68301
|
-
const cleanup = await attachWandbToEventBus(s, eventBus).catch((e) => {
|
|
68302
|
-
console.error("[wandb] Attach failed:", e);
|
|
68303
|
-
return null;
|
|
68304
|
-
});
|
|
68305
|
-
if (cleanup) {
|
|
68306
|
-
wandbCleanup = cleanup;
|
|
68307
|
-
const buffered = earlyBuffer;
|
|
68308
|
-
earlyBuffer = null;
|
|
68309
|
-
eventBus.off("trace-record", earlyBufferHandler);
|
|
68310
|
-
if (buffered) {
|
|
68311
|
-
for (const e of buffered) {
|
|
68312
|
-
eventBus.emit("trace-record", e);
|
|
68313
|
-
}
|
|
68314
|
-
}
|
|
68315
|
-
} else {
|
|
68316
|
-
earlyBuffer = null;
|
|
68317
|
-
eventBus.off("trace-record", earlyBufferHandler);
|
|
68898
|
+
runSessionIdRef.current = s.id;
|
|
68899
|
+
usageStore.enterSession(s.id);
|
|
68900
|
+
runTrace.tryAttach(s);
|
|
68318
68901
|
}
|
|
68319
68902
|
};
|
|
68320
68903
|
const wandbSession = session ?? sessionRef.current;
|
|
68321
68904
|
if (wandbSession) {
|
|
68322
|
-
await
|
|
68905
|
+
await runTrace.tryAttach(wandbSession);
|
|
68323
68906
|
}
|
|
68324
68907
|
try {
|
|
68325
68908
|
let agentResult;
|
|
@@ -68374,9 +68957,9 @@ Error: ${errMsg}
|
|
|
68374
68957
|
if (gen === generationRef.current) {
|
|
68375
68958
|
try {
|
|
68376
68959
|
const rootPath = agentResult.session.rootPath;
|
|
68377
|
-
const mp =
|
|
68378
|
-
if (
|
|
68379
|
-
const raw = JSON.parse(
|
|
68960
|
+
const mp = join4(rootPath, "messages.json");
|
|
68961
|
+
if (existsSync4(mp)) {
|
|
68962
|
+
const raw = JSON.parse(readFileSync4(mp, "utf-8"));
|
|
68380
68963
|
if (Array.isArray(raw) && raw.length > 0) {
|
|
68381
68964
|
conversationRef.current = normalizeMessages(sessions.getResumeMessages(raw));
|
|
68382
68965
|
}
|
|
@@ -68402,8 +68985,8 @@ Error: ${errMsg}
|
|
|
68402
68985
|
setPendingQuestions(null);
|
|
68403
68986
|
if (sessionRef.current) {
|
|
68404
68987
|
try {
|
|
68405
|
-
const mp =
|
|
68406
|
-
|
|
68988
|
+
const mp = join4(sessionRef.current.rootPath, "messages.json");
|
|
68989
|
+
writeFileSync2(mp, JSON.stringify(prevMessages, null, 2));
|
|
68407
68990
|
} catch {}
|
|
68408
68991
|
}
|
|
68409
68992
|
const errorMsg = e instanceof Error ? e.message : "Agent failed";
|
|
@@ -68418,12 +69001,8 @@ Error: ${errMsg}
|
|
|
68418
69001
|
]);
|
|
68419
69002
|
}
|
|
68420
69003
|
} finally {
|
|
68421
|
-
|
|
68422
|
-
|
|
68423
|
-
if (wandbCleanup) {
|
|
68424
|
-
const fn = wandbCleanup;
|
|
68425
|
-
await fn().catch((e) => console.error("[wandb] Flush failed:", e));
|
|
68426
|
-
}
|
|
69004
|
+
unbindRunEvents();
|
|
69005
|
+
await runTrace.cleanupRun();
|
|
68427
69006
|
if (gen === generationRef.current) {
|
|
68428
69007
|
setStatus(pendingToolCallIdRef.current ? "waiting" : "idle");
|
|
68429
69008
|
setThinking(false);
|
|
@@ -68442,18 +69021,10 @@ Error: ${errMsg}
|
|
|
68442
69021
|
operatorState,
|
|
68443
69022
|
operatorMode,
|
|
68444
69023
|
agentMode,
|
|
68445
|
-
|
|
68446
|
-
|
|
68447
|
-
addStreamingToolCall,
|
|
68448
|
-
appendToolCallDelta,
|
|
68449
|
-
addToolCall,
|
|
68450
|
-
updateToolResult,
|
|
68451
|
-
flushCommandOutput,
|
|
68452
|
-
onCommandOutput,
|
|
68453
|
-
subagentHelpers,
|
|
69024
|
+
displayEvents,
|
|
69025
|
+
runEventProjections,
|
|
68454
69026
|
setThinking,
|
|
68455
69027
|
setIsExecuting,
|
|
68456
|
-
addCacheUsage,
|
|
68457
69028
|
initialConfig?.sandbox,
|
|
68458
69029
|
initialConfig?.taskDriven,
|
|
68459
69030
|
initialConfig?.target,
|
|
@@ -68462,14 +69033,15 @@ Error: ${errMsg}
|
|
|
68462
69033
|
strikeMode,
|
|
68463
69034
|
route.data,
|
|
68464
69035
|
setSessionCwd,
|
|
68465
|
-
subagentStore.setState,
|
|
68466
69036
|
skillsRegistry.buildCatalog,
|
|
68467
69037
|
requireApproval,
|
|
68468
69038
|
skillsRegistry,
|
|
68469
69039
|
reasoningEnabled,
|
|
68470
|
-
openAIReasoningEffort
|
|
69040
|
+
openAIReasoningEffort,
|
|
69041
|
+
usageStore,
|
|
69042
|
+
markExecuted
|
|
68471
69043
|
]);
|
|
68472
|
-
const handleSubmit =
|
|
69044
|
+
const handleSubmit = useCallback22((value) => {
|
|
68473
69045
|
const pending = approvalGateRef.current.getPendingApprovals();
|
|
68474
69046
|
const result = resolveSubmit(value, status, pending.length > 0);
|
|
68475
69047
|
if (result.denyPending) {
|
|
@@ -68607,16 +69179,16 @@ ${content}
|
|
|
68607
69179
|
planApprovedPendingRunRef.current = false;
|
|
68608
69180
|
runAgentRef.current("Proceed with the approved plan.");
|
|
68609
69181
|
}, [operatorMode]);
|
|
68610
|
-
const addSystemMessage =
|
|
69182
|
+
const addSystemMessage = useCallback22((content) => {
|
|
68611
69183
|
setMessages((prev) => [
|
|
68612
69184
|
...prev,
|
|
68613
69185
|
{ role: "system", content, createdAt: new Date }
|
|
68614
69186
|
]);
|
|
68615
69187
|
}, []);
|
|
68616
|
-
const showModelPicker =
|
|
69188
|
+
const showModelPicker = useCallback22(() => {
|
|
68617
69189
|
executeCommand("/models");
|
|
68618
69190
|
}, [executeCommand]);
|
|
68619
|
-
const handleHeadersSlash =
|
|
69191
|
+
const handleHeadersSlash = useCallback22(async (op) => {
|
|
68620
69192
|
const active = sessionRef.current;
|
|
68621
69193
|
if (!active) {
|
|
68622
69194
|
addSystemMessage("No active session — cannot manage headers yet.");
|
|
@@ -68687,7 +69259,7 @@ ${formatParseError(parsed.error)}`);
|
|
|
68687
69259
|
}
|
|
68688
69260
|
}
|
|
68689
69261
|
}, [addSystemMessage]);
|
|
68690
|
-
const handleCommandExecute =
|
|
69262
|
+
const handleCommandExecute = useCallback22(async (command) => {
|
|
68691
69263
|
const action = routeCommand(command, resolveSkillContent);
|
|
68692
69264
|
switch (action.type) {
|
|
68693
69265
|
case "show-models":
|
|
@@ -68761,7 +69333,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68761
69333
|
handleHeadersSlash,
|
|
68762
69334
|
strikeMode
|
|
68763
69335
|
]);
|
|
68764
|
-
const handleAbort =
|
|
69336
|
+
const handleAbort = useCallback22(() => {
|
|
68765
69337
|
if (!abortControllerRef.current)
|
|
68766
69338
|
return;
|
|
68767
69339
|
const action = resolveAbortAction(commandCancelledRef.current, () => cancelHandleRef.current.cancel());
|
|
@@ -68789,77 +69361,15 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68789
69361
|
setThinking(false);
|
|
68790
69362
|
setIsExecuting(false);
|
|
68791
69363
|
setMessages((prev) => markInFlightToolsErrored(prev, "Interrupted"));
|
|
68792
|
-
subagentStore.setState(
|
|
68793
|
-
let changed = false;
|
|
68794
|
-
const next = new Map(prev);
|
|
68795
|
-
for (const [id, session2] of next) {
|
|
68796
|
-
const hasInFlight = session2.messages.some((m2) => m2.role === "tool" && (m2.status === "pending" || m2.status === "streaming"));
|
|
68797
|
-
if (hasInFlight || session2.status === "running") {
|
|
68798
|
-
changed = true;
|
|
68799
|
-
next.set(id, {
|
|
68800
|
-
...session2,
|
|
68801
|
-
status: session2.status === "running" ? "cancelled" : session2.status,
|
|
68802
|
-
messages: session2.messages.map((m2) => m2.role === "tool" && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result: "Interrupted" } : m2)
|
|
68803
|
-
});
|
|
68804
|
-
}
|
|
68805
|
-
}
|
|
68806
|
-
return changed ? next : prev;
|
|
68807
|
-
});
|
|
69364
|
+
subagentStore.setState(markSubagentsInterrupted);
|
|
68808
69365
|
const activeSession = sessionRef.current;
|
|
68809
69366
|
if (activeSession) {
|
|
68810
|
-
|
|
68811
|
-
|
|
68812
|
-
|
|
68813
|
-
|
|
68814
|
-
|
|
68815
|
-
|
|
68816
|
-
}
|
|
68817
|
-
}
|
|
68818
|
-
const last = conversationRef.current[conversationRef.current.length - 1];
|
|
68819
|
-
if (last?.role === "user") {
|
|
68820
|
-
const partial = textRef.current.trim();
|
|
68821
|
-
const pendingTools = displayMessagesRef.current.filter((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming"));
|
|
68822
|
-
const assistantContent = [
|
|
68823
|
-
{
|
|
68824
|
-
type: "text",
|
|
68825
|
-
text: partial || "[Response interrupted by user.]"
|
|
68826
|
-
}
|
|
68827
|
-
];
|
|
68828
|
-
for (const t of pendingTools) {
|
|
68829
|
-
assistantContent.push({
|
|
68830
|
-
type: "tool-call",
|
|
68831
|
-
toolCallId: t.toolCallId,
|
|
68832
|
-
toolName: t.toolName,
|
|
68833
|
-
input: t.args ?? {}
|
|
68834
|
-
});
|
|
68835
|
-
}
|
|
68836
|
-
conversationRef.current = [
|
|
68837
|
-
...conversationRef.current,
|
|
68838
|
-
{
|
|
68839
|
-
role: "assistant",
|
|
68840
|
-
content: assistantContent
|
|
68841
|
-
}
|
|
68842
|
-
];
|
|
68843
|
-
if (pendingTools.length > 0) {
|
|
68844
|
-
conversationRef.current = [
|
|
68845
|
-
...conversationRef.current,
|
|
68846
|
-
{
|
|
68847
|
-
role: "tool",
|
|
68848
|
-
content: pendingTools.map((t) => ({
|
|
68849
|
-
type: "tool-result",
|
|
68850
|
-
toolCallId: t.toolCallId,
|
|
68851
|
-
toolName: t.toolName ?? "unknown",
|
|
68852
|
-
output: {
|
|
68853
|
-
type: "text",
|
|
68854
|
-
value: "Cancelled by user."
|
|
68855
|
-
}
|
|
68856
|
-
}))
|
|
68857
|
-
}
|
|
68858
|
-
];
|
|
68859
|
-
}
|
|
68860
|
-
writeFileSync(join3(activeSession.rootPath, "messages.json"), JSON.stringify(conversationRef.current, null, 2));
|
|
68861
|
-
}
|
|
68862
|
-
} catch {}
|
|
69367
|
+
conversationRef.current = recoverAbortedTranscript({
|
|
69368
|
+
rootPath: activeSession.rootPath,
|
|
69369
|
+
conversation: conversationRef.current,
|
|
69370
|
+
partialText: displayEvents.getPartialText(),
|
|
69371
|
+
displayMessages: displayMessagesRef.current
|
|
69372
|
+
});
|
|
68863
69373
|
}
|
|
68864
69374
|
setMessages((prev) => {
|
|
68865
69375
|
const updated = prev.map((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result: "Cancelled by user" } : m2);
|
|
@@ -68872,51 +69382,30 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68872
69382
|
}
|
|
68873
69383
|
];
|
|
68874
69384
|
});
|
|
68875
|
-
}, [setThinking, setIsExecuting, subagentStore.setState]);
|
|
68876
|
-
const resumeWithQuestionResult =
|
|
69385
|
+
}, [setThinking, setIsExecuting, subagentStore.setState, displayEvents]);
|
|
69386
|
+
const resumeWithQuestionResult = useCallback22((result) => {
|
|
68877
69387
|
const toolCallId = pendingToolCallIdRef.current;
|
|
68878
69388
|
if (!toolCallId)
|
|
68879
69389
|
return;
|
|
68880
|
-
const
|
|
68881
|
-
type: "json",
|
|
68882
|
-
value: result
|
|
68883
|
-
};
|
|
68884
|
-
const updated = conversationRef.current.map((msg) => {
|
|
68885
|
-
if (msg.role !== "tool")
|
|
68886
|
-
return msg;
|
|
68887
|
-
if (!Array.isArray(msg.content))
|
|
68888
|
-
return msg;
|
|
68889
|
-
let mutated = false;
|
|
68890
|
-
const nextContent = msg.content.map((part) => {
|
|
68891
|
-
if (part && typeof part === "object" && "type" in part && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
68892
|
-
mutated = true;
|
|
68893
|
-
return {
|
|
68894
|
-
...part,
|
|
68895
|
-
output: wrappedOutput
|
|
68896
|
-
};
|
|
68897
|
-
}
|
|
68898
|
-
return part;
|
|
68899
|
-
});
|
|
68900
|
-
return mutated ? { ...msg, content: nextContent } : msg;
|
|
68901
|
-
});
|
|
69390
|
+
const updated = rewriteToolResultOutput(conversationRef.current, toolCallId, result);
|
|
68902
69391
|
conversationRef.current = updated;
|
|
68903
69392
|
const activeSession = sessionRef.current;
|
|
68904
69393
|
if (activeSession) {
|
|
68905
69394
|
try {
|
|
68906
|
-
|
|
69395
|
+
writeFileSync2(join4(activeSession.rootPath, "messages.json"), JSON.stringify(updated, null, 2));
|
|
68907
69396
|
} catch {}
|
|
68908
69397
|
}
|
|
68909
69398
|
pendingToolCallIdRef.current = null;
|
|
68910
69399
|
setPendingQuestions(null);
|
|
68911
69400
|
runAgentRef.current(null);
|
|
68912
69401
|
}, []);
|
|
68913
|
-
const handleQuestionsSubmit =
|
|
69402
|
+
const handleQuestionsSubmit = useCallback22((answers) => {
|
|
68914
69403
|
resumeWithQuestionResult({ answers, skipped: false });
|
|
68915
69404
|
}, [resumeWithQuestionResult]);
|
|
68916
|
-
const handleQuestionsSkip =
|
|
69405
|
+
const handleQuestionsSkip = useCallback22(() => {
|
|
68917
69406
|
resumeWithQuestionResult({ answers: [], skipped: true });
|
|
68918
69407
|
}, [resumeWithQuestionResult]);
|
|
68919
|
-
const transitionToMode =
|
|
69408
|
+
const transitionToMode = useCallback22((next) => {
|
|
68920
69409
|
approvalGateRef.current.updateConfig({
|
|
68921
69410
|
requireApproval: next === "manual"
|
|
68922
69411
|
});
|
|
@@ -68931,7 +69420,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68931
69420
|
sessions.updateOperatorSettings(sid, { initialMode: next }).catch((e) => console.error("[operator] Failed to persist mode:", e));
|
|
68932
69421
|
}
|
|
68933
69422
|
}, []);
|
|
68934
|
-
const cycleMode =
|
|
69423
|
+
const cycleMode = useCallback22(() => {
|
|
68935
69424
|
const current = operatorModeRef.current;
|
|
68936
69425
|
const idx = OPERATOR_MODE_CYCLE.indexOf(current);
|
|
68937
69426
|
const next = OPERATOR_MODE_CYCLE[(idx + 1) % OPERATOR_MODE_CYCLE.length];
|
|
@@ -68972,11 +69461,8 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68972
69461
|
const removeIdx = selectedQueueIndex;
|
|
68973
69462
|
setQueuedMessages((prev) => prev.filter((_2, i) => i !== removeIdx));
|
|
68974
69463
|
setSelectedQueueIndex(-1);
|
|
68975
|
-
flushCommandOutput();
|
|
68976
|
-
|
|
68977
|
-
clearInterval(cmdFlushTimerRef.current);
|
|
68978
|
-
cmdFlushTimerRef.current = null;
|
|
68979
|
-
}
|
|
69464
|
+
displayEvents.flushCommandOutput();
|
|
69465
|
+
displayEvents.stopCommandOutputFlush();
|
|
68980
69466
|
setMessages((prev) => prev.map((m2) => isToolMessage(m2) && m2.status === "pending" ? { ...m2, status: "error", result: "Interrupted" } : m2));
|
|
68981
69467
|
runAgentRef.current(msg);
|
|
68982
69468
|
return;
|
|
@@ -69021,34 +69507,15 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
69021
69507
|
key.preventDefault?.();
|
|
69022
69508
|
const toolCallId = pendingToolCallIdRef.current;
|
|
69023
69509
|
if (toolCallId) {
|
|
69024
|
-
|
|
69025
|
-
|
|
69026
|
-
|
|
69027
|
-
|
|
69028
|
-
skipped: true,
|
|
69029
|
-
aborted: true
|
|
69030
|
-
}
|
|
69031
|
-
};
|
|
69032
|
-
conversationRef.current = conversationRef.current.map((msg) => {
|
|
69033
|
-
if (msg.role !== "tool" || !Array.isArray(msg.content))
|
|
69034
|
-
return msg;
|
|
69035
|
-
let mutated = false;
|
|
69036
|
-
const nextContent = msg.content.map((part) => {
|
|
69037
|
-
if (part && typeof part === "object" && "type" in part && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
69038
|
-
mutated = true;
|
|
69039
|
-
return {
|
|
69040
|
-
...part,
|
|
69041
|
-
output: abortedResult
|
|
69042
|
-
};
|
|
69043
|
-
}
|
|
69044
|
-
return part;
|
|
69045
|
-
});
|
|
69046
|
-
return mutated ? { ...msg, content: nextContent } : msg;
|
|
69510
|
+
conversationRef.current = rewriteToolResultOutput(conversationRef.current, toolCallId, {
|
|
69511
|
+
answers: [],
|
|
69512
|
+
skipped: true,
|
|
69513
|
+
aborted: true
|
|
69047
69514
|
});
|
|
69048
69515
|
const activeSession = sessionRef.current;
|
|
69049
69516
|
if (activeSession) {
|
|
69050
69517
|
try {
|
|
69051
|
-
|
|
69518
|
+
writeFileSync2(join4(activeSession.rootPath, "messages.json"), JSON.stringify(conversationRef.current, null, 2));
|
|
69052
69519
|
} catch {}
|
|
69053
69520
|
}
|
|
69054
69521
|
}
|
|
@@ -69197,7 +69664,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
69197
69664
|
fg: colors2.warning,
|
|
69198
69665
|
children: "STRIKE"
|
|
69199
69666
|
}, undefined, false, undefined, this),
|
|
69200
|
-
(session?.targets[0] || initialConfig?.target) && /* @__PURE__ */ jsxDEV56(
|
|
69667
|
+
(session?.targets[0] || initialConfig?.target) && /* @__PURE__ */ jsxDEV56(Fragment7, {
|
|
69201
69668
|
children: [
|
|
69202
69669
|
/* @__PURE__ */ jsxDEV56("text", {
|
|
69203
69670
|
fg: colors2.textMuted,
|
|
@@ -69240,7 +69707,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
69240
69707
|
questions: pendingQuestions,
|
|
69241
69708
|
onSubmit: handleQuestionsSubmit,
|
|
69242
69709
|
onSkip: handleQuestionsSkip
|
|
69243
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV56(
|
|
69710
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV56(Fragment7, {
|
|
69244
69711
|
children: [
|
|
69245
69712
|
/* @__PURE__ */ jsxDEV56(QueuedMessages, {
|
|
69246
69713
|
messages: queuedMessages,
|
|
@@ -69368,19 +69835,19 @@ function ResponsibleUseDisclosure({
|
|
|
69368
69835
|
|
|
69369
69836
|
// src/tui/components/switch.tsx
|
|
69370
69837
|
import React2 from "react";
|
|
69371
|
-
import { jsxDEV as jsxDEV58, Fragment as
|
|
69838
|
+
import { jsxDEV as jsxDEV58, Fragment as Fragment8 } from "@opentui/react/jsx-dev-runtime";
|
|
69372
69839
|
var CaseSymbol = Symbol("Switch.Case");
|
|
69373
69840
|
var DefaultSymbol = Symbol("Switch.Default");
|
|
69374
69841
|
function CaseComponent({
|
|
69375
69842
|
children
|
|
69376
69843
|
}) {
|
|
69377
|
-
return /* @__PURE__ */ jsxDEV58(
|
|
69844
|
+
return /* @__PURE__ */ jsxDEV58(Fragment8, {
|
|
69378
69845
|
children
|
|
69379
69846
|
}, undefined, false, undefined, this);
|
|
69380
69847
|
}
|
|
69381
69848
|
CaseComponent[CaseSymbol] = true;
|
|
69382
69849
|
function DefaultComponent({ children }) {
|
|
69383
|
-
return /* @__PURE__ */ jsxDEV58(
|
|
69850
|
+
return /* @__PURE__ */ jsxDEV58(Fragment8, {
|
|
69384
69851
|
children
|
|
69385
69852
|
}, undefined, false, undefined, this);
|
|
69386
69853
|
}
|
|
@@ -69403,7 +69870,7 @@ function SwitchComponent({
|
|
|
69403
69870
|
}
|
|
69404
69871
|
}
|
|
69405
69872
|
});
|
|
69406
|
-
return /* @__PURE__ */ jsxDEV58(
|
|
69873
|
+
return /* @__PURE__ */ jsxDEV58(Fragment8, {
|
|
69407
69874
|
children: matchedChild || defaultChild
|
|
69408
69875
|
}, undefined, false, undefined, this);
|
|
69409
69876
|
}
|
|
@@ -69616,6 +70083,7 @@ function createKeybindings(deps) {
|
|
|
69616
70083
|
setExternalDialogOpen,
|
|
69617
70084
|
setFocusIndex,
|
|
69618
70085
|
navigableItems,
|
|
70086
|
+
onExit,
|
|
69619
70087
|
setShowToolsPanel
|
|
69620
70088
|
} = deps;
|
|
69621
70089
|
const route = useRoute();
|
|
@@ -69631,9 +70099,7 @@ function createKeybindings(deps) {
|
|
|
69631
70099
|
const now = Date.now();
|
|
69632
70100
|
const lastPress = ctrlCPressTime;
|
|
69633
70101
|
if (lastPress && now - lastPress < 1000) {
|
|
69634
|
-
|
|
69635
|
-
renderer.destroy();
|
|
69636
|
-
process.exit(0);
|
|
70102
|
+
await onExit();
|
|
69637
70103
|
} else {
|
|
69638
70104
|
setInputKey((prev) => prev + 1);
|
|
69639
70105
|
setCtrlCPressTime(now);
|
|
@@ -69829,7 +70295,7 @@ import { jsxDEV as jsxDEV61 } from "@opentui/react/jsx-dev-runtime";
|
|
|
69829
70295
|
installObfuscationTextPatch();
|
|
69830
70296
|
extend({ frameBuffer: FrameBufferRenderable });
|
|
69831
70297
|
extend({ frameBuffer: FrameBufferRenderable });
|
|
69832
|
-
function App({ appConfig }) {
|
|
70298
|
+
function App({ appConfig, onExit }) {
|
|
69833
70299
|
const [focusIndex, setFocusIndex] = useState40(0);
|
|
69834
70300
|
const [cwd, setCwd] = useState40(process.cwd());
|
|
69835
70301
|
const [ctrlCPressTime, setCtrlCPressTime] = useState40(null);
|
|
@@ -69885,7 +70351,8 @@ function App({ appConfig }) {
|
|
|
69885
70351
|
setShowSessionsDialog,
|
|
69886
70352
|
setShowShortcutsDialog,
|
|
69887
70353
|
setFocusIndex,
|
|
69888
|
-
navigableItems
|
|
70354
|
+
navigableItems,
|
|
70355
|
+
onExit
|
|
69889
70356
|
},
|
|
69890
70357
|
children: /* @__PURE__ */ jsxDEV61(AppContent, {
|
|
69891
70358
|
focusIndex,
|
|
@@ -69982,7 +70449,7 @@ function AppContent({
|
|
|
69982
70449
|
toast(`Update available: v${currentVersion} → v${latestVersion}. Run: pensar upgrade`, "warn", 8000);
|
|
69983
70450
|
});
|
|
69984
70451
|
const checkAuthToken = async () => {
|
|
69985
|
-
const { isTokenExpired, isConnected: isConnected2 } = await import("./index-
|
|
70452
|
+
const { isTokenExpired, isConnected: isConnected2 } = await import("./index-vvkvwmyr.js");
|
|
69986
70453
|
if (isConnected2(config2.data) && config2.data.accessToken && isTokenExpired(config2.data.accessToken, 60) && !config2.data.refreshToken && !config2.data.pensarAPIKey) {
|
|
69987
70454
|
toast("Your Pensar Console session has expired. Run /login to refresh.", "warn", 8000);
|
|
69988
70455
|
}
|
|
@@ -70317,6 +70784,7 @@ async function main() {
|
|
|
70317
70784
|
const transparent = appConfig.transparentBackground ?? false;
|
|
70318
70785
|
const themeColors = resolveThemeColors(getTheme(themeName), mode, transparent);
|
|
70319
70786
|
overlayThemeRef.current = themeColors;
|
|
70787
|
+
const observabilityRuntime = startObservabilityRuntime();
|
|
70320
70788
|
const renderer = await createCliRenderer({
|
|
70321
70789
|
exitOnCtrlC: false,
|
|
70322
70790
|
consoleOptions: buildConsoleOptions(themeColors),
|
|
@@ -70324,10 +70792,17 @@ async function main() {
|
|
|
70324
70792
|
});
|
|
70325
70793
|
const { copyToClipboard } = createClipboardManager(renderer);
|
|
70326
70794
|
setupAutoCopy(renderer, copyToClipboard);
|
|
70795
|
+
let cleanupPromise = null;
|
|
70327
70796
|
const cleanup = () => {
|
|
70328
|
-
|
|
70329
|
-
|
|
70330
|
-
|
|
70797
|
+
if (!cleanupPromise) {
|
|
70798
|
+
cleanupPromise = (async () => {
|
|
70799
|
+
cleanupTerminalFocusMode();
|
|
70800
|
+
renderer.destroy();
|
|
70801
|
+
await observabilityRuntime.shutdown().catch(() => {});
|
|
70802
|
+
process.exit(0);
|
|
70803
|
+
})();
|
|
70804
|
+
}
|
|
70805
|
+
return cleanupPromise;
|
|
70331
70806
|
};
|
|
70332
70807
|
process.on("SIGINT", cleanup);
|
|
70333
70808
|
process.on("SIGTERM", cleanup);
|
|
@@ -70359,7 +70834,8 @@ async function main() {
|
|
|
70359
70834
|
children: [
|
|
70360
70835
|
/* @__PURE__ */ jsxDEV61(ErrorBoundary, {
|
|
70361
70836
|
children: /* @__PURE__ */ jsxDEV61(App, {
|
|
70362
|
-
appConfig
|
|
70837
|
+
appConfig,
|
|
70838
|
+
onExit: cleanup
|
|
70363
70839
|
}, undefined, false, undefined, this)
|
|
70364
70840
|
}, undefined, false, undefined, this),
|
|
70365
70841
|
/* @__PURE__ */ jsxDEV61(ToastContainer, {}, undefined, false, undefined, this)
|