@pensar/apex 2.4.0 → 2.5.0-canary.2bbb0f6f
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-20hb6mg7.js +20 -0
- package/build/{agent-5ejt5vpz.js → agent-71sn1cjn.js} +9 -8
- package/build/{agent-nhs1w5w0.js → agent-xnrz4bhp.js} +11 -10
- package/build/{apps-17wvz1d7.js → apps-ghf7kp1s.js} +72 -31
- package/build/{auth-z3h9859n.js → auth-p1nrv7re.js} +25 -20
- package/build/authentication-m1vj2f0s.js +20 -0
- package/build/blackboxAgent-hjfzgk93.js +20 -0
- package/build/blackboxPentest-9snp9gvp.js +70 -0
- package/build/{cli-0n4r54hq.js → cli-08fcc6d8.js} +1 -1
- package/build/{cli-gq40s5b3.js → cli-14j00zfh.js} +5 -3
- package/build/{cli-vnynf0js.js → cli-3bmqdcfh.js} +10 -4
- package/build/{cli-mavved45.js → cli-3ew5fs3f.js} +46 -25
- package/build/{cli-xshasbwe.js → cli-4mgj070h.js} +30 -4
- package/build/{cli-repbyhkk.js → cli-4vwnsyep.js} +1141 -525
- package/build/cli-53rm0rrz.js +15 -0
- package/build/cli-68260ckj.js +12136 -0
- package/build/cli-7q3ae3ft.js +6 -0
- package/build/{cli-5k33webc.js → cli-7sqb16dd.js} +45 -43
- package/build/{cli-9rhzhgx2.js → cli-8pk8znhw.js} +1 -1
- package/build/cli-9pbk8m32.js +32 -0
- package/build/{cli-72cvcqhg.js → cli-9ya3yktn.js} +1 -1
- package/build/{cli-vq52kp7j.js → cli-a8n64cef.js} +23 -5
- package/build/{cli-qqt4gj1w.js → cli-a9vq54sx.js} +5 -3
- package/build/{cli-swpbx60z.js → cli-avmhkjtv.js} +1 -1481
- package/build/{cli-tkc598ey.js → cli-f47dgye3.js} +411 -280
- package/build/{cli-k8kc47pq.js → cli-fw7sp0fp.js} +3 -3
- package/build/{cli-32z0017y.js → cli-g3cb8pj5.js} +2 -2
- package/build/{cli-tznv8pf1.js → cli-gbch9xmy.js} +1 -1
- package/build/cli-knd276ed.js +1485 -0
- package/build/{cli-2cbwdk78.js → cli-t7rhyqx5.js} +1 -1
- package/build/{cli-b1adytsy.js → cli-yge44bmk.js} +28 -5
- package/build/cli.js +641 -95
- package/build/{config-f1mj4nhd.js → config-cqw98n5y.js} +18 -15
- package/build/{doctor-ekneewa3.js → doctor-vzh1wmfa.js} +8 -7
- package/build/{fastStrike-8zka43xs.js → fastStrike-f441e9nr.js} +13 -10
- package/build/{fixes-b89s5haw.js → fixes-xxz52cf2.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-ghwf5z3v.js → index-23jj0234.js} +3 -3
- package/build/{index-6d22pyxt.js → index-3gavwzay.js} +1756 -1213
- package/build/{index-4ad3sdwk.js → index-4v5jc2td.js} +4 -4
- package/build/{index-mtq7kmxz.js → index-5wh7gq37.js} +4 -2
- package/build/{index-sf16jm0m.js → index-e7kq5rrd.js} +9 -7
- package/build/{index-rbzhk712.js → index-fxx38nc9.js} +11 -10
- package/build/{index-hqjdg6fg.js → index-j3dc7dks.js} +17 -9
- package/build/{index-y5w6n3tb.js → index-yc1dnj3n.js} +2 -2
- package/build/{issues-xx5bs4md.js → issues-zdag9ayw.js} +82 -26
- package/build/{logs-qtxe51w2.js → logs-f492cjgt.js} +25 -20
- package/build/{offesecAgent-b9e2xm6v.js → offesecAgent-pr0cmrqb.js} +10 -9
- package/build/pentest-1g3fzah5.js +30 -0
- package/build/{pentests-6ks3szc4.js → pentests-vstpzh9j.js} +26 -21
- package/build/{targetedPentest-s1ptvq8e.js → targetedPentest-wj3ae355.js} +11 -10
- package/build/{targets-sxygyj87.js → targets-806zxf1n.js} +27 -22
- package/build/threatModel-dc4jbhkf.js +29 -0
- package/build/{uninstall-tvsh81v8.js → uninstall-58ak2e2v.js} +6 -3
- package/build/{upload-7wdyyqmr.js → upload-kkktzh83.js} +8 -7
- package/build/{utils-7fwdkqk6.js → utils-1sawtwbj.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-a8n64cef.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-7sqb16dd.js";
|
|
22
|
+
import"./cli-fw7sp0fp.js";
|
|
23
|
+
import"./cli-14j00zfh.js";
|
|
24
|
+
import"./cli-3ew5fs3f.js";
|
|
18
25
|
import {
|
|
19
26
|
REPORT_FILENAME_MD
|
|
20
|
-
} from "./cli-
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
} from "./cli-yge44bmk.js";
|
|
28
|
+
import {
|
|
29
|
+
createWeaveTracer,
|
|
30
|
+
resolveConfig
|
|
31
|
+
} from "./cli-t7rhyqx5.js";
|
|
32
|
+
import {
|
|
33
|
+
AVAILABLE_PROVIDERS,
|
|
34
|
+
init_types
|
|
35
|
+
} from "./cli-ee3axgts.js";
|
|
36
|
+
import"./cli-4mgj070h.js";
|
|
37
|
+
import"./cli-g3cb8pj5.js";
|
|
25
38
|
import"./cli-9fsre5pt.js";
|
|
26
|
-
import"./cli-
|
|
39
|
+
import"./cli-a9vq54sx.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-4vwnsyep.js";
|
|
43
56
|
import {
|
|
44
57
|
detectOSAndEnhancePrompt
|
|
45
|
-
} from "./cli-
|
|
58
|
+
} from "./cli-gbch9xmy.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,20 +77,18 @@ 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
|
+
endAllActiveRootSpans,
|
|
86
|
+
getContextWindow,
|
|
70
87
|
getOpenAIReasoningEfforts,
|
|
88
|
+
getRecentModels,
|
|
89
|
+
getResumeMessages,
|
|
71
90
|
hasToolCall,
|
|
91
|
+
init_active_root_spans,
|
|
72
92
|
init_ai,
|
|
73
93
|
init_dist,
|
|
74
94
|
init_logger,
|
|
@@ -85,7 +105,7 @@ import {
|
|
|
85
105
|
stepCountIs,
|
|
86
106
|
write,
|
|
87
107
|
writeErrorLog
|
|
88
|
-
} from "./cli-
|
|
108
|
+
} from "./cli-f47dgye3.js";
|
|
89
109
|
import {
|
|
90
110
|
disconnect,
|
|
91
111
|
ensureValidToken,
|
|
@@ -100,21 +120,23 @@ import {
|
|
|
100
120
|
selectWorkspace,
|
|
101
121
|
startDeviceFlow,
|
|
102
122
|
validateGateway
|
|
103
|
-
} from "./cli-
|
|
104
|
-
import"./cli-
|
|
123
|
+
} from "./cli-08fcc6d8.js";
|
|
124
|
+
import"./cli-avmhkjtv.js";
|
|
105
125
|
import"./cli-j54qa6tm.js";
|
|
106
126
|
import {
|
|
107
127
|
config,
|
|
108
|
-
init_config
|
|
109
|
-
} from "./cli-
|
|
110
|
-
import
|
|
111
|
-
init_config,
|
|
112
|
-
update
|
|
113
|
-
} from "./cli-9rhzhgx2.js";
|
|
128
|
+
init_config
|
|
129
|
+
} from "./cli-9ya3yktn.js";
|
|
130
|
+
import"./cli-8pk8znhw.js";
|
|
114
131
|
import {
|
|
115
132
|
checkForUpdate,
|
|
116
|
-
init_installation
|
|
117
|
-
|
|
133
|
+
init_installation,
|
|
134
|
+
init_package,
|
|
135
|
+
version
|
|
136
|
+
} from "./cli-3bmqdcfh.js";
|
|
137
|
+
import {
|
|
138
|
+
require_src
|
|
139
|
+
} from "./cli-knd276ed.js";
|
|
118
140
|
import {
|
|
119
141
|
__commonJS,
|
|
120
142
|
__esm,
|
|
@@ -752,11 +774,11 @@ var require_core = __commonJS(function(exports, module) {
|
|
|
752
774
|
var warn = (message, ...args) => {
|
|
753
775
|
console.log(`WARN: ${message}`, ...args);
|
|
754
776
|
};
|
|
755
|
-
var deprecated = (
|
|
756
|
-
if (seenDeprecations[`${
|
|
777
|
+
var deprecated = (version3, message) => {
|
|
778
|
+
if (seenDeprecations[`${version3}/${message}`])
|
|
757
779
|
return;
|
|
758
|
-
console.log(`Deprecated as of ${
|
|
759
|
-
seenDeprecations[`${
|
|
780
|
+
console.log(`Deprecated as of ${version3}. ${message}`);
|
|
781
|
+
seenDeprecations[`${version3}/${message}`] = true;
|
|
760
782
|
};
|
|
761
783
|
var MultiClassError = new Error;
|
|
762
784
|
function remapScopeNames(mode, regexes, { key }) {
|
|
@@ -1006,7 +1028,7 @@ var require_core = __commonJS(function(exports, module) {
|
|
|
1006
1028
|
}
|
|
1007
1029
|
return mode;
|
|
1008
1030
|
}
|
|
1009
|
-
var
|
|
1031
|
+
var version2 = "11.11.1";
|
|
1010
1032
|
|
|
1011
1033
|
class HTMLInjectionError extends Error {
|
|
1012
1034
|
constructor(reason, html) {
|
|
@@ -1070,13 +1092,13 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
|
|
|
1070
1092
|
if (ignoreIllegals === undefined) {
|
|
1071
1093
|
ignoreIllegals = true;
|
|
1072
1094
|
}
|
|
1073
|
-
const
|
|
1095
|
+
const context2 = {
|
|
1074
1096
|
code,
|
|
1075
1097
|
language: languageName
|
|
1076
1098
|
};
|
|
1077
|
-
fire("before:highlight",
|
|
1078
|
-
const result =
|
|
1079
|
-
result.code =
|
|
1099
|
+
fire("before:highlight", context2);
|
|
1100
|
+
const result = context2.result ? context2.result : _highlight(context2.language, context2.code, ignoreIllegals);
|
|
1101
|
+
result.code = context2.code;
|
|
1080
1102
|
fire("after:highlight", result);
|
|
1081
1103
|
return result;
|
|
1082
1104
|
}
|
|
@@ -1628,7 +1650,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
|
|
|
1628
1650
|
hljs.safeMode = function() {
|
|
1629
1651
|
SAFE_MODE = true;
|
|
1630
1652
|
};
|
|
1631
|
-
hljs.versionString =
|
|
1653
|
+
hljs.versionString = version2;
|
|
1632
1654
|
hljs.regex = {
|
|
1633
1655
|
concat,
|
|
1634
1656
|
lookahead,
|
|
@@ -49370,13 +49392,186 @@ var require_lib = __commonJS(function(exports, module) {
|
|
|
49370
49392
|
});
|
|
49371
49393
|
|
|
49372
49394
|
// src/tui/index.tsx
|
|
49373
|
-
|
|
49395
|
+
init_config();
|
|
49374
49396
|
init_installation();
|
|
49375
49397
|
init_logger();
|
|
49376
49398
|
import { createCliRenderer, FrameBufferRenderable, RGBA as RGBA25 } from "@opentui/core";
|
|
49377
49399
|
import { createRoot, extend } from "@opentui/react";
|
|
49378
49400
|
import { useEffect as useEffect27, useState as useState40 } from "react";
|
|
49379
49401
|
|
|
49402
|
+
// src/core/observability/runtime.ts
|
|
49403
|
+
init_package();
|
|
49404
|
+
init_active_root_spans();
|
|
49405
|
+
var import_api = __toESM(require_src(), 1);
|
|
49406
|
+
var import_context_async_hooks = __toESM(require_src2(), 1);
|
|
49407
|
+
var import_exporter_trace_otlp_http = __toESM(require_src6(), 1);
|
|
49408
|
+
var import_otlp_exporter_base = __toESM(require_src3(), 1);
|
|
49409
|
+
var import_node_http = __toESM(require_index_node_http(), 1);
|
|
49410
|
+
var import_otlp_transformer = __toESM(require_src5(), 1);
|
|
49411
|
+
var import_resources = __toESM(require_src4(), 1);
|
|
49412
|
+
var import_sdk_trace_base = __toESM(require_index_shim(), 1);
|
|
49413
|
+
import { randomUUID } from "node:crypto";
|
|
49414
|
+
var DEFAULT_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
49415
|
+
function withTimeout(promise, timeoutMs) {
|
|
49416
|
+
return new Promise((resolve) => {
|
|
49417
|
+
let settled = false;
|
|
49418
|
+
const settle = (result) => {
|
|
49419
|
+
if (settled)
|
|
49420
|
+
return;
|
|
49421
|
+
settled = true;
|
|
49422
|
+
clearTimeout(timer);
|
|
49423
|
+
resolve(result);
|
|
49424
|
+
};
|
|
49425
|
+
const timer = setTimeout(() => settle("timed-out"), timeoutMs);
|
|
49426
|
+
promise.then(() => settle("completed"), () => settle("completed"));
|
|
49427
|
+
});
|
|
49428
|
+
}
|
|
49429
|
+
var NOOP_RUNTIME = {
|
|
49430
|
+
async forceFlush() {},
|
|
49431
|
+
async shutdown() {
|
|
49432
|
+
return "completed";
|
|
49433
|
+
}
|
|
49434
|
+
};
|
|
49435
|
+
function isOtelSdkDisabled(env) {
|
|
49436
|
+
return env.OTEL_SDK_DISABLED === "true";
|
|
49437
|
+
}
|
|
49438
|
+
function resolveTracesEndpoint(env) {
|
|
49439
|
+
const specific = env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT?.trim();
|
|
49440
|
+
if (specific)
|
|
49441
|
+
return specific;
|
|
49442
|
+
const generic = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim();
|
|
49443
|
+
if (!generic)
|
|
49444
|
+
return null;
|
|
49445
|
+
return `${generic.endsWith("/") ? generic : `${generic}/`}v1/traces`;
|
|
49446
|
+
}
|
|
49447
|
+
function resolveTracesProtocol(env) {
|
|
49448
|
+
const raw = (env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ?? env.OTEL_EXPORTER_OTLP_PROTOCOL ?? "").trim();
|
|
49449
|
+
return raw === "http/protobuf" ? "http/protobuf" : "http/json";
|
|
49450
|
+
}
|
|
49451
|
+
function parseResourceAttributes(env) {
|
|
49452
|
+
const raw = env.OTEL_RESOURCE_ATTRIBUTES;
|
|
49453
|
+
if (!raw)
|
|
49454
|
+
return {};
|
|
49455
|
+
const attrs = {};
|
|
49456
|
+
for (const pair of raw.split(",")) {
|
|
49457
|
+
const eq = pair.indexOf("=");
|
|
49458
|
+
if (eq <= 0)
|
|
49459
|
+
continue;
|
|
49460
|
+
const key = pair.slice(0, eq).trim();
|
|
49461
|
+
const value = pair.slice(eq + 1).trim();
|
|
49462
|
+
if (key && value)
|
|
49463
|
+
attrs[key] = value;
|
|
49464
|
+
}
|
|
49465
|
+
return attrs;
|
|
49466
|
+
}
|
|
49467
|
+
function buildResource(env) {
|
|
49468
|
+
const resourceAttributes = parseResourceAttributes(env);
|
|
49469
|
+
return import_resources.resourceFromAttributes({
|
|
49470
|
+
"service.version": version,
|
|
49471
|
+
"service.instance.id": randomUUID(),
|
|
49472
|
+
...resourceAttributes,
|
|
49473
|
+
"service.name": env.OTEL_SERVICE_NAME?.trim() || resourceAttributes["service.name"] || "apex"
|
|
49474
|
+
});
|
|
49475
|
+
}
|
|
49476
|
+
function createTraceExporter(protocol) {
|
|
49477
|
+
if (protocol === "http/json") {
|
|
49478
|
+
return new import_exporter_trace_otlp_http.OTLPTraceExporter;
|
|
49479
|
+
}
|
|
49480
|
+
return new import_otlp_exporter_base.OTLPExporterBase(import_node_http.createOtlpHttpExportDelegate(import_node_http.convertLegacyHttpOptions({}, "TRACES", "v1/traces", {
|
|
49481
|
+
"Content-Type": "application/x-protobuf"
|
|
49482
|
+
}), import_otlp_transformer.ProtobufTraceSerializer, "otlp_http_span_exporter", import_otlp_transformer.TraceExporterMetricsHelper, undefined));
|
|
49483
|
+
}
|
|
49484
|
+
var activeRuntime = null;
|
|
49485
|
+
function startObservabilityRuntime(env = process.env, opts) {
|
|
49486
|
+
if (activeRuntime)
|
|
49487
|
+
return activeRuntime;
|
|
49488
|
+
if (isOtelSdkDisabled(env))
|
|
49489
|
+
return NOOP_RUNTIME;
|
|
49490
|
+
if (!resolveTracesEndpoint(env))
|
|
49491
|
+
return NOOP_RUNTIME;
|
|
49492
|
+
const shutdownTimeoutMs = opts?.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
|
|
49493
|
+
const exporter = createTraceExporter(resolveTracesProtocol(env));
|
|
49494
|
+
const provider = new import_sdk_trace_base.BasicTracerProvider({
|
|
49495
|
+
resource: buildResource(env),
|
|
49496
|
+
spanProcessors: opts?.spanProcessors ?? [new import_sdk_trace_base.BatchSpanProcessor(exporter)]
|
|
49497
|
+
});
|
|
49498
|
+
const contextManager = new import_context_async_hooks.AsyncLocalStorageContextManager;
|
|
49499
|
+
contextManager.enable();
|
|
49500
|
+
import_api.trace.setGlobalTracerProvider(provider);
|
|
49501
|
+
import_api.context.setGlobalContextManager(contextManager);
|
|
49502
|
+
let shutdownPromise = null;
|
|
49503
|
+
const runtime = {
|
|
49504
|
+
async forceFlush() {
|
|
49505
|
+
await provider.forceFlush();
|
|
49506
|
+
},
|
|
49507
|
+
shutdown() {
|
|
49508
|
+
if (!shutdownPromise) {
|
|
49509
|
+
const shutdownWork = (async () => {
|
|
49510
|
+
endAllActiveRootSpans();
|
|
49511
|
+
try {
|
|
49512
|
+
await provider.forceFlush();
|
|
49513
|
+
} finally {
|
|
49514
|
+
await provider.shutdown();
|
|
49515
|
+
}
|
|
49516
|
+
})();
|
|
49517
|
+
shutdownPromise = withTimeout(shutdownWork, shutdownTimeoutMs).then((result) => {
|
|
49518
|
+
contextManager.disable();
|
|
49519
|
+
import_api.trace.disable();
|
|
49520
|
+
import_api.context.disable();
|
|
49521
|
+
return result;
|
|
49522
|
+
}).finally(() => {
|
|
49523
|
+
activeRuntime = null;
|
|
49524
|
+
});
|
|
49525
|
+
}
|
|
49526
|
+
return shutdownPromise;
|
|
49527
|
+
}
|
|
49528
|
+
};
|
|
49529
|
+
activeRuntime = runtime;
|
|
49530
|
+
return runtime;
|
|
49531
|
+
}
|
|
49532
|
+
function installObservabilityExitHandlers(runtime, opts) {
|
|
49533
|
+
let exitPromise = null;
|
|
49534
|
+
let exitCode = 0;
|
|
49535
|
+
let fatalSeen = false;
|
|
49536
|
+
const reportError = (error, source) => {
|
|
49537
|
+
try {
|
|
49538
|
+
opts?.onError?.(error, source);
|
|
49539
|
+
} catch {}
|
|
49540
|
+
};
|
|
49541
|
+
const exitWith = (code, error, source) => {
|
|
49542
|
+
let pendingReport = null;
|
|
49543
|
+
if (error !== undefined && !fatalSeen) {
|
|
49544
|
+
fatalSeen = true;
|
|
49545
|
+
exitCode = 1;
|
|
49546
|
+
const fatalSource = source ?? "uncaughtException";
|
|
49547
|
+
pendingReport = () => reportError(error, fatalSource);
|
|
49548
|
+
} else if (!fatalSeen && exitCode === 0) {
|
|
49549
|
+
exitCode = code;
|
|
49550
|
+
}
|
|
49551
|
+
if (exitPromise) {
|
|
49552
|
+
pendingReport?.();
|
|
49553
|
+
return exitPromise;
|
|
49554
|
+
}
|
|
49555
|
+
try {
|
|
49556
|
+
opts?.cleanup?.(code);
|
|
49557
|
+
} catch (cleanupError) {
|
|
49558
|
+
if (!fatalSeen) {
|
|
49559
|
+
fatalSeen = true;
|
|
49560
|
+
exitCode = 1;
|
|
49561
|
+
pendingReport = () => reportError(cleanupError, "uncaughtException");
|
|
49562
|
+
}
|
|
49563
|
+
}
|
|
49564
|
+
pendingReport?.();
|
|
49565
|
+
exitPromise = runtime.shutdown().catch(() => {}).then(() => process.exit(exitCode));
|
|
49566
|
+
return exitPromise;
|
|
49567
|
+
};
|
|
49568
|
+
process.on("SIGINT", () => void exitWith(130));
|
|
49569
|
+
process.on("SIGTERM", () => void exitWith(143));
|
|
49570
|
+
process.on("uncaughtException", (error) => void exitWith(1, error, "uncaughtException"));
|
|
49571
|
+
process.on("unhandledRejection", (reason) => void exitWith(1, reason, "unhandledRejection"));
|
|
49572
|
+
return exitWith;
|
|
49573
|
+
}
|
|
49574
|
+
|
|
49380
49575
|
// src/core/providers/index.ts
|
|
49381
49576
|
init_types();
|
|
49382
49577
|
init_utils();
|
|
@@ -52796,16 +52991,15 @@ function createClipboardManager(renderer) {
|
|
|
52796
52991
|
|
|
52797
52992
|
// src/tui/components/chat/index.tsx
|
|
52798
52993
|
init_session();
|
|
52799
|
-
import { useCallback as
|
|
52994
|
+
import { useCallback as useCallback14, useEffect as useEffect12, useState as useState19 } from "react";
|
|
52800
52995
|
|
|
52801
52996
|
// src/tui/context/agent.tsx
|
|
52802
52997
|
init_ai();
|
|
52803
|
-
init_config();
|
|
52804
52998
|
init_logger();
|
|
52805
52999
|
init_utils();
|
|
52806
53000
|
import {
|
|
52807
53001
|
createContext as createContext3,
|
|
52808
|
-
useCallback as
|
|
53002
|
+
useCallback as useCallback4,
|
|
52809
53003
|
useContext as useContext3,
|
|
52810
53004
|
useEffect as useEffect2,
|
|
52811
53005
|
useMemo as useMemo3,
|
|
@@ -52814,9 +53008,10 @@ import {
|
|
|
52814
53008
|
} from "react";
|
|
52815
53009
|
|
|
52816
53010
|
// src/tui/context/config.tsx
|
|
52817
|
-
|
|
53011
|
+
init_config();
|
|
52818
53012
|
import {
|
|
52819
53013
|
createContext as createContext2,
|
|
53014
|
+
useCallback as useCallback2,
|
|
52820
53015
|
useContext as useContext2,
|
|
52821
53016
|
useMemo as useMemo2,
|
|
52822
53017
|
useState as useState2
|
|
@@ -52825,20 +53020,22 @@ import { jsxDEV as jsxDEV2 } from "@opentui/react/jsx-dev-runtime";
|
|
|
52825
53020
|
var ctx = createContext2(null);
|
|
52826
53021
|
function ConfigProvider({ children, config: config2 }) {
|
|
52827
53022
|
const [appConfig, setAppConfig] = useState2(config2);
|
|
53023
|
+
const update = useCallback2(async (newConfig) => {
|
|
53024
|
+
await config.update(newConfig);
|
|
53025
|
+
setAppConfig((current) => ({
|
|
53026
|
+
...current,
|
|
53027
|
+
...newConfig
|
|
53028
|
+
}));
|
|
53029
|
+
}, []);
|
|
53030
|
+
const reload = useCallback2(async () => {
|
|
53031
|
+
const freshConfig = await config.get();
|
|
53032
|
+
setAppConfig(freshConfig);
|
|
53033
|
+
}, []);
|
|
52828
53034
|
const value = useMemo2(() => ({
|
|
52829
53035
|
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]);
|
|
53036
|
+
update,
|
|
53037
|
+
reload
|
|
53038
|
+
}), [appConfig, reload, update]);
|
|
52842
53039
|
return /* @__PURE__ */ jsxDEV2(ctx.Provider, {
|
|
52843
53040
|
value,
|
|
52844
53041
|
children
|
|
@@ -52852,15 +53049,133 @@ var useConfig = () => {
|
|
|
52852
53049
|
return config2;
|
|
52853
53050
|
};
|
|
52854
53051
|
|
|
53052
|
+
// src/tui/context/session-usage.ts
|
|
53053
|
+
import { useCallback as useCallback3, useSyncExternalStore } from "react";
|
|
53054
|
+
var EMPTY_STATE = {
|
|
53055
|
+
tokenUsage: EMPTY_SESSION_TOKEN_USAGE,
|
|
53056
|
+
contextUsage: null
|
|
53057
|
+
};
|
|
53058
|
+
|
|
53059
|
+
class SessionUsageStore {
|
|
53060
|
+
sessions = new Map;
|
|
53061
|
+
listeners = new Map;
|
|
53062
|
+
activeListeners = new Set;
|
|
53063
|
+
activeId = null;
|
|
53064
|
+
provisionalState = EMPTY_STATE;
|
|
53065
|
+
get activeSessionId() {
|
|
53066
|
+
return this.activeId;
|
|
53067
|
+
}
|
|
53068
|
+
beginNewSession() {
|
|
53069
|
+
const changed = this.activeId !== null || this.provisionalState !== EMPTY_STATE;
|
|
53070
|
+
this.activeId = null;
|
|
53071
|
+
this.provisionalState = EMPTY_STATE;
|
|
53072
|
+
if (changed)
|
|
53073
|
+
this.emitActive();
|
|
53074
|
+
}
|
|
53075
|
+
enterSession(sessionId, seed) {
|
|
53076
|
+
if (!this.sessions.has(sessionId)) {
|
|
53077
|
+
this.sessions.set(sessionId, {
|
|
53078
|
+
tokenUsage: seed?.tokenUsage ?? this.provisionalState.tokenUsage,
|
|
53079
|
+
contextUsage: seed?.contextUsage ?? null
|
|
53080
|
+
});
|
|
53081
|
+
this.provisionalState = EMPTY_STATE;
|
|
53082
|
+
}
|
|
53083
|
+
if (this.activeId !== sessionId) {
|
|
53084
|
+
this.activeId = sessionId;
|
|
53085
|
+
this.emit(sessionId);
|
|
53086
|
+
}
|
|
53087
|
+
}
|
|
53088
|
+
forgetSession(sessionId) {
|
|
53089
|
+
this.sessions.delete(sessionId);
|
|
53090
|
+
this.listeners.delete(sessionId);
|
|
53091
|
+
if (this.activeId === sessionId)
|
|
53092
|
+
this.activeId = null;
|
|
53093
|
+
}
|
|
53094
|
+
getSnapshot(sessionId) {
|
|
53095
|
+
if (sessionId === null)
|
|
53096
|
+
return EMPTY_STATE;
|
|
53097
|
+
return this.sessions.get(sessionId) ?? EMPTY_STATE;
|
|
53098
|
+
}
|
|
53099
|
+
subscribe(sessionId, listener) {
|
|
53100
|
+
let set = this.listeners.get(sessionId);
|
|
53101
|
+
if (!set) {
|
|
53102
|
+
set = new Set;
|
|
53103
|
+
this.listeners.set(sessionId, set);
|
|
53104
|
+
}
|
|
53105
|
+
set.add(listener);
|
|
53106
|
+
return () => {
|
|
53107
|
+
set.delete(listener);
|
|
53108
|
+
};
|
|
53109
|
+
}
|
|
53110
|
+
addSessionTokens(sessionId, step) {
|
|
53111
|
+
if (sessionId === null) {
|
|
53112
|
+
const next = accumulateSessionTokens(this.provisionalState.tokenUsage, step);
|
|
53113
|
+
if (next !== this.provisionalState.tokenUsage) {
|
|
53114
|
+
this.provisionalState = { tokenUsage: next, contextUsage: null };
|
|
53115
|
+
if (this.activeId === null)
|
|
53116
|
+
this.emitActive();
|
|
53117
|
+
}
|
|
53118
|
+
return;
|
|
53119
|
+
}
|
|
53120
|
+
this.update(sessionId, (state) => ({
|
|
53121
|
+
...state,
|
|
53122
|
+
tokenUsage: accumulateSessionTokens(state.tokenUsage, step)
|
|
53123
|
+
}));
|
|
53124
|
+
}
|
|
53125
|
+
setRootContext(sessionId, sample) {
|
|
53126
|
+
if (sessionId === null)
|
|
53127
|
+
return;
|
|
53128
|
+
this.update(sessionId, (state) => ({
|
|
53129
|
+
...state,
|
|
53130
|
+
contextUsage: sample
|
|
53131
|
+
}));
|
|
53132
|
+
}
|
|
53133
|
+
update(sessionId, updater) {
|
|
53134
|
+
const current = this.sessions.get(sessionId);
|
|
53135
|
+
if (!current)
|
|
53136
|
+
return;
|
|
53137
|
+
const next = updater(current);
|
|
53138
|
+
if (next === current || next.tokenUsage === current.tokenUsage && next.contextUsage === current.contextUsage) {
|
|
53139
|
+
return;
|
|
53140
|
+
}
|
|
53141
|
+
this.sessions.set(sessionId, next);
|
|
53142
|
+
this.emit(sessionId);
|
|
53143
|
+
}
|
|
53144
|
+
getActiveSnapshot() {
|
|
53145
|
+
return this.activeId === null ? this.provisionalState : this.getSnapshot(this.activeId);
|
|
53146
|
+
}
|
|
53147
|
+
subscribeActive(listener) {
|
|
53148
|
+
this.activeListeners.add(listener);
|
|
53149
|
+
return () => {
|
|
53150
|
+
this.activeListeners.delete(listener);
|
|
53151
|
+
};
|
|
53152
|
+
}
|
|
53153
|
+
emit(sessionId) {
|
|
53154
|
+
for (const listener of this.listeners.get(sessionId) ?? [])
|
|
53155
|
+
listener();
|
|
53156
|
+
if (sessionId === this.activeId)
|
|
53157
|
+
this.emitActive();
|
|
53158
|
+
}
|
|
53159
|
+
emitActive() {
|
|
53160
|
+
for (const listener of this.activeListeners)
|
|
53161
|
+
listener();
|
|
53162
|
+
}
|
|
53163
|
+
}
|
|
53164
|
+
function useActiveSessionUsage(store) {
|
|
53165
|
+
const subscribe = useCallback3((listener) => store.subscribeActive(listener), [store]);
|
|
53166
|
+
const getSnapshot = useCallback3(() => store.getActiveSnapshot(), [store]);
|
|
53167
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
53168
|
+
}
|
|
53169
|
+
|
|
52855
53170
|
// src/tui/context/agent.tsx
|
|
52856
53171
|
import { jsxDEV as jsxDEV3 } from "@opentui/react/jsx-dev-runtime";
|
|
52857
53172
|
var AgentContext = createContext3(null);
|
|
52858
53173
|
function useAgent() {
|
|
52859
|
-
const
|
|
52860
|
-
if (!
|
|
53174
|
+
const context2 = useContext3(AgentContext);
|
|
53175
|
+
if (!context2) {
|
|
52861
53176
|
throw new Error("useAgent must be used within AgentProvider");
|
|
52862
53177
|
}
|
|
52863
|
-
return
|
|
53178
|
+
return context2;
|
|
52864
53179
|
}
|
|
52865
53180
|
function AgentProvider({ children }) {
|
|
52866
53181
|
const appConfig = useConfig();
|
|
@@ -52868,13 +53183,7 @@ function AgentProvider({ children }) {
|
|
|
52868
53183
|
return getDefaultModelForConfig(appConfig.data) ?? AVAILABLE_MODELS[0];
|
|
52869
53184
|
});
|
|
52870
53185
|
const [isModelUserSelected, setIsModelUserSelected] = useState3(false);
|
|
52871
|
-
const
|
|
52872
|
-
inputTokens: 0,
|
|
52873
|
-
outputTokens: 0,
|
|
52874
|
-
totalTokens: 0,
|
|
52875
|
-
cachedTokens: 0,
|
|
52876
|
-
cacheWriteTokens: 0
|
|
52877
|
-
});
|
|
53186
|
+
const usageStore = useMemo3(() => new SessionUsageStore, []);
|
|
52878
53187
|
const [hasExecuted, setHasExecuted] = useState3(false);
|
|
52879
53188
|
const [thinking, setThinking] = useState3(false);
|
|
52880
53189
|
const [reasoningEnabled, setReasoningEnabledInternal] = useState3(() => appConfig.data?.reasoningEnabled ?? false);
|
|
@@ -52885,12 +53194,17 @@ function AgentProvider({ children }) {
|
|
|
52885
53194
|
reasoningEnabledRef.current = reasoningEnabled;
|
|
52886
53195
|
const openAIReasoningEffortRef = useRef(openAIReasoningEffort);
|
|
52887
53196
|
openAIReasoningEffortRef.current = openAIReasoningEffort;
|
|
52888
|
-
const
|
|
53197
|
+
const recentModelIdsRef = useRef(appConfig.data.recentModelIds ?? []);
|
|
53198
|
+
const updateConfig = appConfig.update;
|
|
53199
|
+
const setModel = useCallback4((newModel, persist = true) => {
|
|
52889
53200
|
setModelInternal(newModel);
|
|
52890
53201
|
if (persist) {
|
|
52891
53202
|
setIsModelUserSelected(true);
|
|
53203
|
+
const nextRecentModelIds = addRecentModelId(recentModelIdsRef.current, newModel.id);
|
|
53204
|
+
recentModelIdsRef.current = nextRecentModelIds;
|
|
52892
53205
|
const configUpdate = {
|
|
52893
|
-
selectedModelId: newModel.id
|
|
53206
|
+
selectedModelId: newModel.id,
|
|
53207
|
+
recentModelIds: nextRecentModelIds
|
|
52894
53208
|
};
|
|
52895
53209
|
if (reasoningEnabledRef.current && !modelSupportsThinking(newModel.id)) {
|
|
52896
53210
|
configUpdate.reasoningEnabled = false;
|
|
@@ -52901,23 +53215,26 @@ function AgentProvider({ children }) {
|
|
|
52901
53215
|
configUpdate.openAIReasoningEffort = DEFAULT_OPENAI_REASONING_EFFORT;
|
|
52902
53216
|
setOpenAIReasoningEffortInternal(DEFAULT_OPENAI_REASONING_EFFORT);
|
|
52903
53217
|
}
|
|
52904
|
-
|
|
53218
|
+
updateConfig(configUpdate).catch((err) => {
|
|
52905
53219
|
writeErrorLog(err, "AGENT_CONTEXT");
|
|
52906
53220
|
});
|
|
52907
53221
|
}
|
|
52908
|
-
}, []);
|
|
52909
|
-
const setReasoningEnabled =
|
|
53222
|
+
}, [updateConfig]);
|
|
53223
|
+
const setReasoningEnabled = useCallback4((enabled) => {
|
|
52910
53224
|
setReasoningEnabledInternal(enabled);
|
|
52911
|
-
|
|
53225
|
+
updateConfig({ reasoningEnabled: enabled }).catch((err) => {
|
|
52912
53226
|
writeErrorLog(err, "AGENT_CONTEXT");
|
|
52913
53227
|
});
|
|
52914
|
-
}, []);
|
|
52915
|
-
const setOpenAIReasoningEffort =
|
|
53228
|
+
}, [updateConfig]);
|
|
53229
|
+
const setOpenAIReasoningEffort = useCallback4((effort) => {
|
|
52916
53230
|
setOpenAIReasoningEffortInternal(effort);
|
|
52917
|
-
|
|
53231
|
+
updateConfig({ openAIReasoningEffort: effort }).catch((err) => {
|
|
52918
53232
|
writeErrorLog(err, "AGENT_CONTEXT");
|
|
52919
53233
|
});
|
|
52920
|
-
}, []);
|
|
53234
|
+
}, [updateConfig]);
|
|
53235
|
+
useEffect2(() => {
|
|
53236
|
+
recentModelIdsRef.current = appConfig.data.recentModelIds ?? [];
|
|
53237
|
+
}, [appConfig.data.recentModelIds]);
|
|
52921
53238
|
useEffect2(() => {
|
|
52922
53239
|
if (appConfig.data?.reasoningEnabled != null) {
|
|
52923
53240
|
setReasoningEnabledInternal(appConfig.data.reasoningEnabled);
|
|
@@ -52948,40 +53265,13 @@ function AgentProvider({ children }) {
|
|
|
52948
53265
|
setModelInternal(defaultModel);
|
|
52949
53266
|
}
|
|
52950
53267
|
}, [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
|
-
}, []);
|
|
53268
|
+
const markExecuted = useCallback4(() => setHasExecuted(true), []);
|
|
52977
53269
|
const contextValue = useMemo3(() => ({
|
|
52978
53270
|
model,
|
|
52979
53271
|
setModel,
|
|
52980
53272
|
isModelUserSelected,
|
|
52981
|
-
|
|
52982
|
-
|
|
52983
|
-
addCacheUsage,
|
|
52984
|
-
resetTokenUsage,
|
|
53273
|
+
usageStore,
|
|
53274
|
+
markExecuted,
|
|
52985
53275
|
hasExecuted,
|
|
52986
53276
|
thinking,
|
|
52987
53277
|
setThinking,
|
|
@@ -52997,7 +53287,6 @@ function AgentProvider({ children }) {
|
|
|
52997
53287
|
model,
|
|
52998
53288
|
setModel,
|
|
52999
53289
|
isModelUserSelected,
|
|
53000
|
-
tokenUsage,
|
|
53001
53290
|
hasExecuted,
|
|
53002
53291
|
thinking,
|
|
53003
53292
|
reasoningEnabled,
|
|
@@ -53005,9 +53294,8 @@ function AgentProvider({ children }) {
|
|
|
53005
53294
|
openAIReasoningEffort,
|
|
53006
53295
|
isExecuting,
|
|
53007
53296
|
sessionCwd,
|
|
53008
|
-
|
|
53009
|
-
|
|
53010
|
-
resetTokenUsage,
|
|
53297
|
+
usageStore,
|
|
53298
|
+
markExecuted,
|
|
53011
53299
|
setOpenAIReasoningEffort
|
|
53012
53300
|
]);
|
|
53013
53301
|
return /* @__PURE__ */ jsxDEV3(AgentContext.Provider, {
|
|
@@ -53019,14 +53307,14 @@ function AgentProvider({ children }) {
|
|
|
53019
53307
|
// src/tui/components/chat/config-view.tsx
|
|
53020
53308
|
init_utils();
|
|
53021
53309
|
import { useKeyboard as useKeyboard2 } from "@opentui/react";
|
|
53022
|
-
import { useCallback as
|
|
53310
|
+
import { useCallback as useCallback6, useEffect as useEffect4, useState as useState5 } from "react";
|
|
53023
53311
|
|
|
53024
53312
|
// src/tui/components/model-picker/ModelPicker.tsx
|
|
53025
53313
|
init_ai();
|
|
53026
53314
|
init_utils();
|
|
53027
53315
|
import { useKeyboard } from "@opentui/react";
|
|
53028
53316
|
import {
|
|
53029
|
-
useCallback as
|
|
53317
|
+
useCallback as useCallback5,
|
|
53030
53318
|
useEffect as useEffect3,
|
|
53031
53319
|
useMemo as useMemo4,
|
|
53032
53320
|
useRef as useRef2,
|
|
@@ -53094,18 +53382,105 @@ function findChildById(scrollBox, id) {
|
|
|
53094
53382
|
return;
|
|
53095
53383
|
}
|
|
53096
53384
|
|
|
53097
|
-
// src/tui/components/model-picker/
|
|
53098
|
-
|
|
53099
|
-
|
|
53100
|
-
|
|
53385
|
+
// src/tui/components/model-picker/model-navigation.ts
|
|
53386
|
+
function findSelectedModelIndex(navigationItems, selectedModelId) {
|
|
53387
|
+
return navigationItems.findIndex((item) => (item.type === "model" || item.type === "recent-model") && item.model?.id === selectedModelId);
|
|
53388
|
+
}
|
|
53389
|
+
function retainAvailableProviders(expandedProviders, availableProviders) {
|
|
53390
|
+
const retainedProviders = new Set([...expandedProviders].filter((provider) => availableProviders.has(provider)));
|
|
53391
|
+
return retainedProviders.size === expandedProviders.size ? expandedProviders : retainedProviders;
|
|
53392
|
+
}
|
|
53393
|
+
function getSelectedModelRevealKey({
|
|
53394
|
+
availableModels,
|
|
53395
|
+
selectedModel,
|
|
53396
|
+
lastRevealedSelectedModelKey
|
|
53397
|
+
}) {
|
|
53398
|
+
const selectedModelKey = `${selectedModel.provider}:${selectedModel.id}`;
|
|
53399
|
+
if (lastRevealedSelectedModelKey === selectedModelKey)
|
|
53400
|
+
return null;
|
|
53401
|
+
const selectedModelIsAvailable = availableModels.some((model) => model.id === selectedModel.id && model.provider === selectedModel.provider);
|
|
53402
|
+
return selectedModelIsAvailable ? selectedModelKey : null;
|
|
53403
|
+
}
|
|
53404
|
+
|
|
53405
|
+
// src/tui/components/model-picker/model-search.ts
|
|
53406
|
+
var PROVIDER_DISPLAY_NAMES = {
|
|
53407
|
+
anthropic: "Anthropic",
|
|
53101
53408
|
openai: "OpenAI",
|
|
53102
|
-
google: "
|
|
53409
|
+
google: "Google",
|
|
53103
53410
|
openrouter: "OpenRouter",
|
|
53104
53411
|
concentrate: "Concentrate",
|
|
53105
|
-
bedrock: "Bedrock",
|
|
53412
|
+
bedrock: "AWS Bedrock",
|
|
53413
|
+
"bedrock-mantle": "Bedrock Mantle",
|
|
53106
53414
|
pensar: "Pensar",
|
|
53415
|
+
inception: "Inception",
|
|
53107
53416
|
local: "Local LLM"
|
|
53108
53417
|
};
|
|
53418
|
+
function getProviderDisplayName(provider) {
|
|
53419
|
+
return PROVIDER_DISPLAY_NAMES[provider];
|
|
53420
|
+
}
|
|
53421
|
+
function normalizeSearchText(value) {
|
|
53422
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
53423
|
+
}
|
|
53424
|
+
function filterModels(models, searchQuery) {
|
|
53425
|
+
const terms = normalizeSearchText(searchQuery).split(/\s+/).filter(Boolean);
|
|
53426
|
+
if (terms.length === 0)
|
|
53427
|
+
return models;
|
|
53428
|
+
return models.filter((model) => {
|
|
53429
|
+
const searchableText = normalizeSearchText(`${model.name} ${model.id} ${model.provider} ${getProviderDisplayName(model.provider)}`);
|
|
53430
|
+
return terms.every((term) => searchableText.includes(term));
|
|
53431
|
+
});
|
|
53432
|
+
}
|
|
53433
|
+
|
|
53434
|
+
// src/tui/components/model-picker/model-visibility.ts
|
|
53435
|
+
var HIDDEN_MODEL_IDS = {
|
|
53436
|
+
anthropic: new Set([
|
|
53437
|
+
"claude-3-haiku-20240307",
|
|
53438
|
+
"claude-opus-4-0",
|
|
53439
|
+
"claude-opus-4-20250514",
|
|
53440
|
+
"claude-opus-4-1",
|
|
53441
|
+
"claude-opus-4-1-20250805",
|
|
53442
|
+
"claude-sonnet-4-0",
|
|
53443
|
+
"claude-sonnet-4-20250514"
|
|
53444
|
+
]),
|
|
53445
|
+
openai: new Set([
|
|
53446
|
+
"gpt-5.3-chat-latest",
|
|
53447
|
+
"gpt-5.2-chat-latest",
|
|
53448
|
+
"gpt-5.2-codex",
|
|
53449
|
+
"gpt-5.1-chat-latest",
|
|
53450
|
+
"gpt-5.1-codex-mini",
|
|
53451
|
+
"gpt-5.1-codex",
|
|
53452
|
+
"gpt-5.1-codex-max",
|
|
53453
|
+
"gpt-5-chat-latest",
|
|
53454
|
+
"gpt-5-codex",
|
|
53455
|
+
"gpt-4.1-nano",
|
|
53456
|
+
"gpt-4.1-nano-2025-04-14",
|
|
53457
|
+
"gpt-4o-2024-05-13",
|
|
53458
|
+
"gpt-3.5-turbo",
|
|
53459
|
+
"gpt-3.5-turbo-0125",
|
|
53460
|
+
"gpt-3.5-turbo-1106",
|
|
53461
|
+
"o4-mini",
|
|
53462
|
+
"o4-mini-2025-04-16",
|
|
53463
|
+
"o3-mini",
|
|
53464
|
+
"o3-mini-2025-01-31",
|
|
53465
|
+
"o1",
|
|
53466
|
+
"o1-2024-12-17"
|
|
53467
|
+
]),
|
|
53468
|
+
google: new Set([
|
|
53469
|
+
"gemini-2.0-flash",
|
|
53470
|
+
"gemini-2.0-flash-001",
|
|
53471
|
+
"gemini-2.0-flash-lite",
|
|
53472
|
+
"gemini-2.0-flash-lite-001",
|
|
53473
|
+
"gemini-3-pro-preview",
|
|
53474
|
+
"gemini-3.1-flash-lite-preview",
|
|
53475
|
+
"gemini-robotics-er-1.5-preview"
|
|
53476
|
+
])
|
|
53477
|
+
};
|
|
53478
|
+
function getVisiblePickerModels(models, selectedModel) {
|
|
53479
|
+
return models.filter((model) => !HIDDEN_MODEL_IDS[model.provider]?.has(model.id) || model.id === selectedModel?.id && model.provider === selectedModel.provider);
|
|
53480
|
+
}
|
|
53481
|
+
|
|
53482
|
+
// src/tui/components/model-picker/ModelPicker.tsx
|
|
53483
|
+
import { jsxDEV as jsxDEV4, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
53109
53484
|
var providerOrder = [
|
|
53110
53485
|
"pensar",
|
|
53111
53486
|
"anthropic",
|
|
@@ -53114,11 +53489,10 @@ var providerOrder = [
|
|
|
53114
53489
|
"openrouter",
|
|
53115
53490
|
"concentrate",
|
|
53116
53491
|
"bedrock",
|
|
53492
|
+
"bedrock-mantle",
|
|
53493
|
+
"inception",
|
|
53117
53494
|
"local"
|
|
53118
53495
|
];
|
|
53119
|
-
function setsAreEqual(a, b) {
|
|
53120
|
-
return a.size === b.size && [...a].every((value) => b.has(value));
|
|
53121
|
-
}
|
|
53122
53496
|
function PickerRow({
|
|
53123
53497
|
children,
|
|
53124
53498
|
id,
|
|
@@ -53145,6 +53519,8 @@ function getNavItemId(item) {
|
|
|
53145
53519
|
return `provider-${item.provider}`;
|
|
53146
53520
|
if (item.type === "model")
|
|
53147
53521
|
return `model-${item.model.id}`;
|
|
53522
|
+
if (item.type === "recent-model")
|
|
53523
|
+
return `recent-model-${item.model.id}`;
|
|
53148
53524
|
if (item.type === "reasoning")
|
|
53149
53525
|
return "reasoning-toggle";
|
|
53150
53526
|
if (item.type === "openai-reasoning")
|
|
@@ -53169,8 +53545,10 @@ function ModelPicker({
|
|
|
53169
53545
|
const scrollBoxRef = useRef2(null);
|
|
53170
53546
|
const [availableModels, setAvailableModels] = useState4([]);
|
|
53171
53547
|
const [searchQuery, setSearchQuery] = useState4("");
|
|
53172
|
-
const [expandedProviders, setExpandedProviders] = useState4(new Set([
|
|
53548
|
+
const [expandedProviders, setExpandedProviders] = useState4(new Set([selectedModel.provider]));
|
|
53173
53549
|
const [focusedIndex, setFocusedIndex] = useState4(0);
|
|
53550
|
+
const lastRevealedSelectedModelRef = useRef2(null);
|
|
53551
|
+
const lastFocusedSelectedModelIdRef = useRef2(null);
|
|
53174
53552
|
const [localUrl, setLocalUrl] = useState4(config2?.localModelUrl ?? "");
|
|
53175
53553
|
const [localModelName, setLocalModelName] = useState4(config2?.localModelName ?? "");
|
|
53176
53554
|
const [editingLocalField, setEditingLocalField] = useState4(null);
|
|
@@ -53183,86 +53561,105 @@ function ModelPicker({
|
|
|
53183
53561
|
setAvailableModels([]);
|
|
53184
53562
|
return;
|
|
53185
53563
|
}
|
|
53186
|
-
setAvailableModels(getAvailableModels(config2)
|
|
53187
|
-
|
|
53564
|
+
setAvailableModels(getVisiblePickerModels(getAvailableModels(config2), {
|
|
53565
|
+
id: selectedModel.id,
|
|
53566
|
+
provider: selectedModel.provider
|
|
53567
|
+
}));
|
|
53568
|
+
}, [config2, selectedModel.id, selectedModel.provider]);
|
|
53188
53569
|
useEffect3(() => {
|
|
53189
53570
|
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]);
|
|
53571
|
+
setExpandedProviders((prev) => retainAvailableProviders(prev, availableProviders));
|
|
53572
|
+
}, [availableModels]);
|
|
53573
|
+
useEffect3(() => {
|
|
53574
|
+
const selectedModelKey = getSelectedModelRevealKey({
|
|
53575
|
+
availableModels,
|
|
53576
|
+
selectedModel: {
|
|
53577
|
+
id: selectedModel.id,
|
|
53578
|
+
provider: selectedModel.provider
|
|
53579
|
+
},
|
|
53580
|
+
lastRevealedSelectedModelKey: lastRevealedSelectedModelRef.current
|
|
53203
53581
|
});
|
|
53204
|
-
|
|
53582
|
+
if (!selectedModelKey)
|
|
53583
|
+
return;
|
|
53584
|
+
lastRevealedSelectedModelRef.current = selectedModelKey;
|
|
53585
|
+
setExpandedProviders((prev) => prev.has(selectedModel.provider) ? prev : new Set([...prev, selectedModel.provider]));
|
|
53586
|
+
}, [availableModels, selectedModel.id, selectedModel.provider]);
|
|
53587
|
+
const filteredModels = useMemo4(() => filterModels(availableModels, searchQuery), [availableModels, searchQuery]);
|
|
53588
|
+
const isSearching = searchQuery.trim().length > 0;
|
|
53589
|
+
const recentModels = useMemo4(() => getRecentModels(availableModels, config2?.recentModelIds ?? []), [availableModels, config2?.recentModelIds]);
|
|
53205
53590
|
const groupedModels = useMemo4(() => {
|
|
53206
53591
|
const groups = {};
|
|
53207
|
-
const query = searchQuery.toLowerCase().trim();
|
|
53208
53592
|
for (const m of availableModels) {
|
|
53209
|
-
if (query && !m.name.toLowerCase().includes(query) && !m.id.toLowerCase().includes(query)) {
|
|
53210
|
-
continue;
|
|
53211
|
-
}
|
|
53212
53593
|
if (!groups[m.provider]) {
|
|
53213
53594
|
groups[m.provider] = [];
|
|
53214
53595
|
}
|
|
53215
53596
|
groups[m.provider].push(m);
|
|
53216
53597
|
}
|
|
53217
53598
|
return groups;
|
|
53218
|
-
}, [availableModels
|
|
53599
|
+
}, [availableModels]);
|
|
53219
53600
|
const navigationItems = useMemo4(() => {
|
|
53220
53601
|
const items = [];
|
|
53221
|
-
|
|
53222
|
-
|
|
53223
|
-
items.push({ type: "
|
|
53224
|
-
|
|
53225
|
-
|
|
53226
|
-
|
|
53227
|
-
|
|
53228
|
-
|
|
53229
|
-
|
|
53230
|
-
|
|
53602
|
+
if (isSearching) {
|
|
53603
|
+
for (const model of filteredModels) {
|
|
53604
|
+
items.push({ type: "model", model });
|
|
53605
|
+
}
|
|
53606
|
+
} else {
|
|
53607
|
+
for (const model of recentModels) {
|
|
53608
|
+
items.push({ type: "recent-model", model });
|
|
53609
|
+
}
|
|
53610
|
+
for (const provider of providerOrder) {
|
|
53611
|
+
if (provider === "local") {
|
|
53612
|
+
items.push({ type: "provider", provider: "local" });
|
|
53613
|
+
if (expandedProviders.has("local")) {
|
|
53614
|
+
items.push({ type: "local-input", field: "url" });
|
|
53615
|
+
items.push({ type: "local-input", field: "model" });
|
|
53616
|
+
const localModels = groupedModels.local;
|
|
53617
|
+
if (localModels) {
|
|
53618
|
+
for (const m of localModels) {
|
|
53619
|
+
items.push({ type: "model", model: m });
|
|
53620
|
+
}
|
|
53231
53621
|
}
|
|
53232
53622
|
}
|
|
53623
|
+
continue;
|
|
53233
53624
|
}
|
|
53234
|
-
|
|
53235
|
-
|
|
53236
|
-
|
|
53237
|
-
|
|
53238
|
-
|
|
53239
|
-
|
|
53240
|
-
|
|
53241
|
-
|
|
53242
|
-
items.push({ type: "model", model: m });
|
|
53625
|
+
const models = groupedModels[provider];
|
|
53626
|
+
if (!models || models.length === 0)
|
|
53627
|
+
continue;
|
|
53628
|
+
items.push({ type: "provider", provider });
|
|
53629
|
+
if (expandedProviders.has(provider)) {
|
|
53630
|
+
for (const m of models) {
|
|
53631
|
+
items.push({ type: "model", model: m });
|
|
53632
|
+
}
|
|
53243
53633
|
}
|
|
53244
53634
|
}
|
|
53245
53635
|
}
|
|
53246
|
-
if (onReasoningToggle && modelSupportsThinking(selectedModel.id)) {
|
|
53636
|
+
if (!isSearching && onReasoningToggle && modelSupportsThinking(selectedModel.id)) {
|
|
53247
53637
|
items.push({ type: "reasoning" });
|
|
53248
53638
|
}
|
|
53249
|
-
if (onOpenAIReasoningEffortChange && modelSupportsOpenAIReasoning(selectedModel.id)) {
|
|
53639
|
+
if (!isSearching && onOpenAIReasoningEffortChange && modelSupportsOpenAIReasoning(selectedModel.id)) {
|
|
53250
53640
|
items.push({ type: "openai-reasoning" });
|
|
53251
53641
|
}
|
|
53252
53642
|
return items;
|
|
53253
53643
|
}, [
|
|
53254
53644
|
groupedModels,
|
|
53645
|
+
filteredModels,
|
|
53646
|
+
recentModels,
|
|
53647
|
+
isSearching,
|
|
53255
53648
|
expandedProviders,
|
|
53256
53649
|
onReasoningToggle,
|
|
53257
53650
|
onOpenAIReasoningEffortChange,
|
|
53258
53651
|
selectedModel.id
|
|
53259
53652
|
]);
|
|
53260
53653
|
useEffect3(() => {
|
|
53261
|
-
|
|
53262
|
-
|
|
53263
|
-
setFocusedIndex(idx);
|
|
53654
|
+
if (isSearching || lastFocusedSelectedModelIdRef.current === selectedModel.id) {
|
|
53655
|
+
return;
|
|
53264
53656
|
}
|
|
53265
|
-
|
|
53657
|
+
const index = findSelectedModelIndex(navigationItems, selectedModel.id);
|
|
53658
|
+
if (index === -1)
|
|
53659
|
+
return;
|
|
53660
|
+
lastFocusedSelectedModelIdRef.current = selectedModel.id;
|
|
53661
|
+
setFocusedIndex(index);
|
|
53662
|
+
}, [isSearching, navigationItems, selectedModel.id]);
|
|
53266
53663
|
useEffect3(() => {
|
|
53267
53664
|
setFocusedIndex((prev) => Math.min(prev, Math.max(0, navigationItems.length - 1)));
|
|
53268
53665
|
}, [navigationItems.length]);
|
|
@@ -53272,16 +53669,16 @@ function ModelPicker({
|
|
|
53272
53669
|
return;
|
|
53273
53670
|
scrollToChild(scrollBoxRef.current, getNavItemId(item));
|
|
53274
53671
|
}, [focusedIndex, navigationItems]);
|
|
53275
|
-
const commitLocalConfig =
|
|
53672
|
+
const commitLocalConfig = useCallback5((url, modelName) => {
|
|
53276
53673
|
if (!onConfigUpdate)
|
|
53277
53674
|
return;
|
|
53278
|
-
const
|
|
53675
|
+
const update = {
|
|
53279
53676
|
localModelUrl: url || null,
|
|
53280
53677
|
localModelName: modelName || null
|
|
53281
53678
|
};
|
|
53282
|
-
onConfigUpdate(
|
|
53679
|
+
onConfigUpdate(update);
|
|
53283
53680
|
}, [onConfigUpdate]);
|
|
53284
|
-
const finishEditing =
|
|
53681
|
+
const finishEditing = useCallback5(() => {
|
|
53285
53682
|
setEditingLocalField(null);
|
|
53286
53683
|
commitLocalConfig(localUrl, localModelName);
|
|
53287
53684
|
}, [localUrl, localModelName, commitLocalConfig]);
|
|
@@ -53290,7 +53687,7 @@ function ModelPicker({
|
|
|
53290
53687
|
const openAIReasoningEfforts = getOpenAIReasoningEfforts(selectedModel.id);
|
|
53291
53688
|
const isReasoningFocused = navigationItems[focusedIndex]?.type === "reasoning";
|
|
53292
53689
|
const isOpenAIReasoningFocused = navigationItems[focusedIndex]?.type === "openai-reasoning";
|
|
53293
|
-
const cycleOpenAIReasoningEffort =
|
|
53690
|
+
const cycleOpenAIReasoningEffort = useCallback5(() => {
|
|
53294
53691
|
if (!onOpenAIReasoningEffortChange || openAIReasoningEfforts.length === 0) {
|
|
53295
53692
|
return;
|
|
53296
53693
|
}
|
|
@@ -53302,7 +53699,7 @@ function ModelPicker({
|
|
|
53302
53699
|
openAIReasoningEffort,
|
|
53303
53700
|
openAIReasoningEfforts
|
|
53304
53701
|
]);
|
|
53305
|
-
const handleKeyboard =
|
|
53702
|
+
const handleKeyboard = useCallback5((key) => {
|
|
53306
53703
|
if (!focused)
|
|
53307
53704
|
return false;
|
|
53308
53705
|
if (editingLocalField) {
|
|
@@ -53312,24 +53709,18 @@ function ModelPicker({
|
|
|
53312
53709
|
}
|
|
53313
53710
|
return false;
|
|
53314
53711
|
}
|
|
53315
|
-
if (navigationItems.length === 0)
|
|
53316
|
-
return false;
|
|
53317
53712
|
if (key.name === "up" || key.name === "down") {
|
|
53318
|
-
|
|
53713
|
+
if (navigationItems.length === 0)
|
|
53714
|
+
return false;
|
|
53715
|
+
const direction = key.name === "up" ? -1 : 1;
|
|
53716
|
+
const newIndex = (focusedIndex + direction + navigationItems.length) % navigationItems.length;
|
|
53319
53717
|
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
53718
|
return true;
|
|
53329
53719
|
}
|
|
53330
53720
|
if (key.name === "escape") {
|
|
53331
53721
|
if (searchQuery) {
|
|
53332
53722
|
setSearchQuery("");
|
|
53723
|
+
setFocusedIndex(0);
|
|
53333
53724
|
return true;
|
|
53334
53725
|
}
|
|
53335
53726
|
if (onCancel) {
|
|
@@ -53338,16 +53729,16 @@ function ModelPicker({
|
|
|
53338
53729
|
}
|
|
53339
53730
|
return false;
|
|
53340
53731
|
}
|
|
53341
|
-
|
|
53732
|
+
const currentItem = navigationItems[focusedIndex];
|
|
53733
|
+
if (key.name === "space" && currentItem?.type === "reasoning" && onReasoningToggle && thinkingSupported) {
|
|
53342
53734
|
onReasoningToggle(!reasoningEnabled);
|
|
53343
53735
|
return true;
|
|
53344
53736
|
}
|
|
53345
|
-
if (key.name === "space" && onOpenAIReasoningEffortChange && openAIReasoningSupported) {
|
|
53737
|
+
if (key.name === "space" && currentItem?.type === "openai-reasoning" && onOpenAIReasoningEffortChange && openAIReasoningSupported) {
|
|
53346
53738
|
cycleOpenAIReasoningEffort();
|
|
53347
53739
|
return true;
|
|
53348
53740
|
}
|
|
53349
53741
|
if (key.name === "return") {
|
|
53350
|
-
const currentItem = navigationItems[focusedIndex];
|
|
53351
53742
|
if (!currentItem)
|
|
53352
53743
|
return false;
|
|
53353
53744
|
if (currentItem.type === "local-input") {
|
|
@@ -53369,17 +53760,20 @@ function ModelPicker({
|
|
|
53369
53760
|
}
|
|
53370
53761
|
return next;
|
|
53371
53762
|
});
|
|
53372
|
-
} else {
|
|
53763
|
+
} else if (currentItem.type === "model" || currentItem.type === "recent-model") {
|
|
53764
|
+
onSelectModel(currentItem.model);
|
|
53373
53765
|
onConfirm?.();
|
|
53374
53766
|
}
|
|
53375
53767
|
return true;
|
|
53376
53768
|
}
|
|
53377
53769
|
if (key.name === "left" || key.name === "right") {
|
|
53378
|
-
|
|
53379
|
-
|
|
53770
|
+
if (isSearching)
|
|
53771
|
+
return false;
|
|
53772
|
+
const currentItem2 = navigationItems[focusedIndex];
|
|
53773
|
+
if (!currentItem2 || currentItem2.type === "recent-model" || currentItem2.type === "reasoning" || currentItem2.type === "openai-reasoning") {
|
|
53380
53774
|
return false;
|
|
53381
53775
|
}
|
|
53382
|
-
const targetProvider =
|
|
53776
|
+
const targetProvider = currentItem2.type === "provider" ? currentItem2.provider : currentItem2.type === "model" ? currentItem2.model.provider : "local";
|
|
53383
53777
|
if (key.name === "left") {
|
|
53384
53778
|
setExpandedProviders((prev) => {
|
|
53385
53779
|
const next = new Set(prev);
|
|
@@ -53395,13 +53789,6 @@ function ModelPicker({
|
|
|
53395
53789
|
}
|
|
53396
53790
|
return true;
|
|
53397
53791
|
}
|
|
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
53792
|
return false;
|
|
53406
53793
|
}, [
|
|
53407
53794
|
focused,
|
|
@@ -53418,7 +53805,8 @@ function ModelPicker({
|
|
|
53418
53805
|
thinkingSupported,
|
|
53419
53806
|
onOpenAIReasoningEffortChange,
|
|
53420
53807
|
openAIReasoningSupported,
|
|
53421
|
-
cycleOpenAIReasoningEffort
|
|
53808
|
+
cycleOpenAIReasoningEffort,
|
|
53809
|
+
isSearching
|
|
53422
53810
|
]);
|
|
53423
53811
|
useKeyboard((key) => {
|
|
53424
53812
|
const handled = handleKeyboard(key);
|
|
@@ -53427,7 +53815,11 @@ function ModelPicker({
|
|
|
53427
53815
|
}
|
|
53428
53816
|
});
|
|
53429
53817
|
const isProviderFocused = (provider) => navigationItems[focusedIndex]?.type === "provider" && navigationItems[focusedIndex].provider === provider;
|
|
53430
|
-
const isModelFocused = (modelId
|
|
53818
|
+
const isModelFocused = (modelId, recent = false) => {
|
|
53819
|
+
const item = navigationItems[focusedIndex];
|
|
53820
|
+
const expectedType = recent ? "recent-model" : "model";
|
|
53821
|
+
return item?.type === expectedType && item.model.id === modelId;
|
|
53822
|
+
};
|
|
53431
53823
|
const isLocalFieldFocused = (field) => navigationItems[focusedIndex]?.type === "local-input" && navigationItems[focusedIndex].field === field;
|
|
53432
53824
|
return /* @__PURE__ */ jsxDEV4("box", {
|
|
53433
53825
|
flexDirection: "column",
|
|
@@ -53438,21 +53830,42 @@ function ModelPicker({
|
|
|
53438
53830
|
children: [
|
|
53439
53831
|
/* @__PURE__ */ jsxDEV4("box", {
|
|
53440
53832
|
flexShrink: 0,
|
|
53441
|
-
|
|
53442
|
-
|
|
53443
|
-
|
|
53833
|
+
marginBottom: 1,
|
|
53834
|
+
children: [
|
|
53835
|
+
/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53444
53836
|
children: [
|
|
53445
|
-
|
|
53446
|
-
|
|
53837
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
53838
|
+
fg: colors2.primary,
|
|
53839
|
+
children: "Search "
|
|
53840
|
+
}, undefined, false, undefined, this),
|
|
53841
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
53842
|
+
flexGrow: 1,
|
|
53843
|
+
value: searchQuery,
|
|
53844
|
+
onInput: (value) => {
|
|
53845
|
+
setSearchQuery(value);
|
|
53846
|
+
setFocusedIndex(0);
|
|
53847
|
+
},
|
|
53848
|
+
focused: focused && editingLocalField === null,
|
|
53849
|
+
placeholder: "family, model name, or provider...",
|
|
53850
|
+
textColor: colors2.text,
|
|
53851
|
+
focusedTextColor: colors2.text,
|
|
53852
|
+
backgroundColor: "transparent",
|
|
53853
|
+
cursorColor: colors2.textMuted
|
|
53854
|
+
}, undefined, false, undefined, this)
|
|
53447
53855
|
]
|
|
53448
|
-
}, undefined, true, undefined, this)
|
|
53449
|
-
|
|
53450
|
-
|
|
53451
|
-
|
|
53452
|
-
|
|
53856
|
+
}, undefined, true, undefined, this),
|
|
53857
|
+
isSearching && /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53858
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53859
|
+
fg: colors2.primary,
|
|
53860
|
+
children: [
|
|
53861
|
+
"Results (",
|
|
53862
|
+
filteredModels.length,
|
|
53863
|
+
")"
|
|
53864
|
+
]
|
|
53865
|
+
}, undefined, true, undefined, this)
|
|
53453
53866
|
}, undefined, false, undefined, this)
|
|
53454
|
-
|
|
53455
|
-
}, undefined,
|
|
53867
|
+
]
|
|
53868
|
+
}, undefined, true, undefined, this),
|
|
53456
53869
|
/* @__PURE__ */ jsxDEV4("scrollbox", {
|
|
53457
53870
|
ref: scrollBoxRef,
|
|
53458
53871
|
style: {
|
|
@@ -53460,170 +53873,240 @@ function ModelPicker({
|
|
|
53460
53873
|
flexShrink: 1,
|
|
53461
53874
|
width: "100%",
|
|
53462
53875
|
overflow: "hidden",
|
|
53463
|
-
maxHeight: navigationItems.length
|
|
53876
|
+
maxHeight: Math.max(1, navigationItems.length + (!isSearching && recentModels.length > 0 ? 1 : 0))
|
|
53464
53877
|
},
|
|
53465
53878
|
contentOptions: {
|
|
53466
53879
|
flexDirection: "column"
|
|
53467
53880
|
},
|
|
53468
53881
|
scrollbarOptions: {
|
|
53469
|
-
|
|
53882
|
+
trackOptions: {
|
|
53883
|
+
foregroundColor: colors2.textMuted,
|
|
53884
|
+
backgroundColor: colors2.backgroundElement
|
|
53885
|
+
}
|
|
53470
53886
|
}
|
|
53471
53887
|
},
|
|
53472
53888
|
stickyScroll: false,
|
|
53473
|
-
children:
|
|
53474
|
-
|
|
53475
|
-
|
|
53476
|
-
|
|
53477
|
-
|
|
53478
|
-
|
|
53479
|
-
|
|
53480
|
-
|
|
53481
|
-
|
|
53482
|
-
|
|
53889
|
+
children: [
|
|
53890
|
+
!isSearching && recentModels.length > 0 && /* @__PURE__ */ jsxDEV4(Fragment, {
|
|
53891
|
+
children: [
|
|
53892
|
+
/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53893
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53894
|
+
fg: colors2.primary,
|
|
53895
|
+
children: "Recent"
|
|
53896
|
+
}, undefined, false, undefined, this)
|
|
53897
|
+
}, undefined, false, undefined, this),
|
|
53898
|
+
recentModels.map((model) => {
|
|
53899
|
+
const isSelected = model.id === selectedModel.id;
|
|
53900
|
+
const isFocused = isModelFocused(model.id, true);
|
|
53901
|
+
return /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53902
|
+
id: `recent-model-${model.id}`,
|
|
53903
|
+
backgroundColor: isFocused ? colors2.backgroundSelected : undefined,
|
|
53904
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53905
|
+
children: [
|
|
53906
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53907
|
+
fg: isFocused ? colors2.primary : colors2.text,
|
|
53908
|
+
children: [
|
|
53909
|
+
isSelected ? "●" : "○",
|
|
53910
|
+
" ",
|
|
53911
|
+
model.name
|
|
53912
|
+
]
|
|
53913
|
+
}, undefined, true, undefined, this),
|
|
53914
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53915
|
+
fg: colors2.textMuted,
|
|
53916
|
+
children: ` ${getProviderDisplayName(model.provider)}`
|
|
53917
|
+
}, undefined, false, undefined, this)
|
|
53918
|
+
]
|
|
53919
|
+
}, undefined, true, undefined, this)
|
|
53920
|
+
}, `recent-${model.id}`, false, undefined, this);
|
|
53921
|
+
})
|
|
53922
|
+
]
|
|
53923
|
+
}, undefined, true, undefined, this),
|
|
53924
|
+
isSearching && (filteredModels.length === 0 ? /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53925
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53926
|
+
fg: colors2.textMuted,
|
|
53927
|
+
children: "No matching models"
|
|
53928
|
+
}, undefined, false, undefined, this)
|
|
53929
|
+
}, undefined, false, undefined, this) : filteredModels.map((model) => {
|
|
53930
|
+
const isSelected = model.id === selectedModel.id;
|
|
53931
|
+
const isFocused = isModelFocused(model.id);
|
|
53932
|
+
return /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53933
|
+
id: `model-${model.id}`,
|
|
53934
|
+
backgroundColor: isFocused ? colors2.backgroundSelected : undefined,
|
|
53483
53935
|
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53484
|
-
fg: isFocused ? colors2.primary : isExpanded ? colors2.text : colors2.textMuted,
|
|
53485
53936
|
children: [
|
|
53486
|
-
|
|
53487
|
-
|
|
53488
|
-
|
|
53489
|
-
|
|
53937
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53938
|
+
fg: isFocused ? colors2.primary : colors2.text,
|
|
53939
|
+
children: [
|
|
53940
|
+
isSelected ? "●" : "○",
|
|
53941
|
+
" ",
|
|
53942
|
+
model.name
|
|
53943
|
+
]
|
|
53944
|
+
}, undefined, true, undefined, this),
|
|
53945
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
53946
|
+
fg: colors2.textMuted,
|
|
53947
|
+
children: ` ${getProviderDisplayName(model.provider)}`
|
|
53948
|
+
}, undefined, false, undefined, this)
|
|
53490
53949
|
]
|
|
53491
53950
|
}, undefined, true, undefined, this)
|
|
53492
|
-
},
|
|
53493
|
-
|
|
53494
|
-
|
|
53495
|
-
|
|
53496
|
-
|
|
53497
|
-
|
|
53498
|
-
|
|
53499
|
-
|
|
53951
|
+
}, model.id, false, undefined, this);
|
|
53952
|
+
})),
|
|
53953
|
+
providerOrder.flatMap((provider) => {
|
|
53954
|
+
if (isSearching)
|
|
53955
|
+
return [];
|
|
53956
|
+
const isExpanded = expandedProviders.has(provider);
|
|
53957
|
+
const providerName = getProviderDisplayName(provider);
|
|
53958
|
+
const isFocused = isProviderFocused(provider);
|
|
53959
|
+
if (provider === "local") {
|
|
53960
|
+
const localModels = groupedModels.local;
|
|
53961
|
+
const modelCount = localModels?.length ?? 0;
|
|
53962
|
+
const elements2 = [];
|
|
53963
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53964
|
+
id: "provider-local",
|
|
53965
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53966
|
+
fg: isFocused ? colors2.primary : isExpanded ? colors2.text : colors2.textMuted,
|
|
53500
53967
|
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)
|
|
53968
|
+
isFocused ? "❯" : isExpanded ? "▾" : "▸",
|
|
53969
|
+
" ",
|
|
53970
|
+
providerName,
|
|
53971
|
+
modelCount > 0 ? ` (${modelCount})` : ""
|
|
53517
53972
|
]
|
|
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
|
-
|
|
53973
|
+
}, undefined, true, undefined, this)
|
|
53974
|
+
}, "local", false, undefined, this));
|
|
53975
|
+
if (isExpanded) {
|
|
53976
|
+
const isUrlFocused = isLocalFieldFocused("url");
|
|
53977
|
+
const isUrlEditing = editingLocalField === "url";
|
|
53978
|
+
if (isUrlEditing) {
|
|
53979
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53980
|
+
id: "local-input-url",
|
|
53981
|
+
paddingLeft: 2,
|
|
53982
|
+
children: [
|
|
53983
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
53984
|
+
fg: colors2.primary,
|
|
53985
|
+
children: " URL: "
|
|
53986
|
+
}, undefined, false, undefined, this),
|
|
53987
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
53988
|
+
focused: true,
|
|
53989
|
+
value: localUrl,
|
|
53990
|
+
backgroundColor: "transparent",
|
|
53991
|
+
cursorColor: colors2.textMuted,
|
|
53992
|
+
onInput: (v) => setLocalUrl(typeof v === "string" ? v : ""),
|
|
53993
|
+
onPaste: (event) => {
|
|
53994
|
+
const cleaned = getPasteText(event).replace(/\r?\n/g, "");
|
|
53995
|
+
setLocalUrl((prev) => `${prev}${cleaned}`);
|
|
53996
|
+
},
|
|
53997
|
+
onSubmit: finishEditing
|
|
53998
|
+
}, undefined, false, undefined, this)
|
|
53999
|
+
]
|
|
54000
|
+
}, "local-url", true, undefined, this));
|
|
54001
|
+
} else {
|
|
54002
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
54003
|
+
id: "local-input-url",
|
|
54004
|
+
paddingLeft: 2,
|
|
54005
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
54006
|
+
fg: isUrlFocused ? colors2.primary : colors2.textMuted,
|
|
54007
|
+
children: ` URL: ${localUrl || "(press Enter to set)"}`
|
|
53551
54008
|
}, undefined, false, undefined, this)
|
|
53552
|
-
|
|
53553
|
-
}
|
|
53554
|
-
|
|
53555
|
-
|
|
53556
|
-
|
|
53557
|
-
|
|
53558
|
-
|
|
53559
|
-
|
|
53560
|
-
children:
|
|
53561
|
-
|
|
53562
|
-
|
|
53563
|
-
|
|
53564
|
-
|
|
53565
|
-
|
|
53566
|
-
|
|
53567
|
-
|
|
54009
|
+
}, "local-url", false, undefined, this));
|
|
54010
|
+
}
|
|
54011
|
+
const isModelFieldFocused = isLocalFieldFocused("model");
|
|
54012
|
+
const isModelEditing = editingLocalField === "model";
|
|
54013
|
+
if (isModelEditing) {
|
|
54014
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
54015
|
+
id: "local-input-model",
|
|
54016
|
+
paddingLeft: 2,
|
|
54017
|
+
children: [
|
|
54018
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
54019
|
+
fg: colors2.primary,
|
|
54020
|
+
children: " Model: "
|
|
54021
|
+
}, undefined, false, undefined, this),
|
|
54022
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
54023
|
+
focused: true,
|
|
54024
|
+
value: localModelName,
|
|
54025
|
+
backgroundColor: "transparent",
|
|
54026
|
+
cursorColor: colors2.textMuted,
|
|
54027
|
+
onInput: (v) => setLocalModelName(typeof v === "string" ? v : ""),
|
|
54028
|
+
onPaste: (event) => {
|
|
54029
|
+
const cleaned = getPasteText(event).replace(/\r?\n/g, "");
|
|
54030
|
+
setLocalModelName((prev) => `${prev}${cleaned}`);
|
|
54031
|
+
},
|
|
54032
|
+
onSubmit: finishEditing
|
|
54033
|
+
}, undefined, false, undefined, this)
|
|
54034
|
+
]
|
|
54035
|
+
}, "local-model", true, undefined, this));
|
|
54036
|
+
} else {
|
|
53568
54037
|
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
53569
|
-
id:
|
|
54038
|
+
id: "local-input-model",
|
|
53570
54039
|
paddingLeft: 2,
|
|
53571
54040
|
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
53572
|
-
fg:
|
|
53573
|
-
children:
|
|
53574
|
-
|
|
53575
|
-
|
|
53576
|
-
|
|
53577
|
-
|
|
53578
|
-
|
|
53579
|
-
|
|
54041
|
+
fg: isModelFieldFocused ? colors2.primary : colors2.textMuted,
|
|
54042
|
+
children: ` Model: ${localModelName || "(press Enter to set)"}`
|
|
54043
|
+
}, undefined, false, undefined, this)
|
|
54044
|
+
}, "local-model", false, undefined, this));
|
|
54045
|
+
}
|
|
54046
|
+
if (localModels) {
|
|
54047
|
+
for (const m of localModels) {
|
|
54048
|
+
const isSelected = m.id === selectedModel.id;
|
|
54049
|
+
const isMFocused = isModelFocused(m.id);
|
|
54050
|
+
elements2.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
54051
|
+
id: `model-${m.id}`,
|
|
54052
|
+
paddingLeft: 2,
|
|
54053
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
54054
|
+
fg: isMFocused ? colors2.primary : colors2.textMuted,
|
|
54055
|
+
children: [
|
|
54056
|
+
isSelected ? "●" : "○",
|
|
54057
|
+
" ",
|
|
54058
|
+
m.name
|
|
54059
|
+
]
|
|
54060
|
+
}, undefined, true, undefined, this)
|
|
54061
|
+
}, m.id, false, undefined, this));
|
|
54062
|
+
}
|
|
53580
54063
|
}
|
|
53581
54064
|
}
|
|
54065
|
+
return elements2;
|
|
53582
54066
|
}
|
|
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));
|
|
54067
|
+
const models = groupedModels[provider];
|
|
54068
|
+
if (!models || models.length === 0)
|
|
54069
|
+
return [];
|
|
54070
|
+
const elements = [];
|
|
54071
|
+
elements.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
54072
|
+
id: `provider-${provider}`,
|
|
54073
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
54074
|
+
fg: isFocused ? colors2.primary : isExpanded ? colors2.text : colors2.textMuted,
|
|
54075
|
+
children: [
|
|
54076
|
+
isFocused ? "❯" : isExpanded ? "▾" : "▸",
|
|
54077
|
+
" ",
|
|
54078
|
+
providerName,
|
|
54079
|
+
" (",
|
|
54080
|
+
models.length,
|
|
54081
|
+
")"
|
|
54082
|
+
]
|
|
54083
|
+
}, undefined, true, undefined, this)
|
|
54084
|
+
}, provider, false, undefined, this));
|
|
54085
|
+
if (isExpanded) {
|
|
54086
|
+
for (const m of models) {
|
|
54087
|
+
const isSelected = m.id === selectedModel.id;
|
|
54088
|
+
const isMFocused = isModelFocused(m.id);
|
|
54089
|
+
const isDefault = m.id === "claude-haiku-4-5" || m.id === "gpt-4o-mini";
|
|
54090
|
+
elements.push(/* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
54091
|
+
id: `model-${m.id}`,
|
|
54092
|
+
paddingLeft: 2,
|
|
54093
|
+
children: /* @__PURE__ */ jsxDEV4("text", {
|
|
54094
|
+
fg: isMFocused ? colors2.primary : colors2.textMuted,
|
|
54095
|
+
children: [
|
|
54096
|
+
isSelected ? "●" : "○",
|
|
54097
|
+
" ",
|
|
54098
|
+
m.name,
|
|
54099
|
+
isDefault && !isModelUserSelected && isSelected ? " [default]" : ""
|
|
54100
|
+
]
|
|
54101
|
+
}, undefined, true, undefined, this)
|
|
54102
|
+
}, m.id, false, undefined, this));
|
|
54103
|
+
}
|
|
53621
54104
|
}
|
|
53622
|
-
|
|
53623
|
-
|
|
53624
|
-
|
|
53625
|
-
},
|
|
53626
|
-
onReasoningToggle && thinkingSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
54105
|
+
return elements;
|
|
54106
|
+
})
|
|
54107
|
+
]
|
|
54108
|
+
}, isSearching ? "search-results" : "model-browser", true, undefined, this),
|
|
54109
|
+
!isSearching && onReasoningToggle && thinkingSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
53627
54110
|
flexShrink: 0,
|
|
53628
54111
|
paddingTop: 1,
|
|
53629
54112
|
children: /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
@@ -53637,7 +54120,7 @@ function ModelPicker({
|
|
|
53637
54120
|
}, undefined, true, undefined, this)
|
|
53638
54121
|
}, undefined, false, undefined, this)
|
|
53639
54122
|
}, undefined, false, undefined, this),
|
|
53640
|
-
onOpenAIReasoningEffortChange && openAIReasoningSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
54123
|
+
!isSearching && onOpenAIReasoningEffortChange && openAIReasoningSupported && /* @__PURE__ */ jsxDEV4("box", {
|
|
53641
54124
|
flexShrink: 0,
|
|
53642
54125
|
paddingTop: 1,
|
|
53643
54126
|
children: /* @__PURE__ */ jsxDEV4(PickerRow, {
|
|
@@ -53737,7 +54220,7 @@ function ConfigView({ config: config2, onBack, onStart }) {
|
|
|
53737
54220
|
return;
|
|
53738
54221
|
}
|
|
53739
54222
|
});
|
|
53740
|
-
const handleModelSelect =
|
|
54223
|
+
const handleModelSelect = useCallback6((model) => {
|
|
53741
54224
|
setSelectedModel(model);
|
|
53742
54225
|
setIsModelUserSelected(true);
|
|
53743
54226
|
}, []);
|
|
@@ -53913,7 +54396,7 @@ function isValidUrl(url) {
|
|
|
53913
54396
|
}
|
|
53914
54397
|
|
|
53915
54398
|
// src/tui/components/chat/home-view.tsx
|
|
53916
|
-
import { useCallback as
|
|
54399
|
+
import { useCallback as useCallback13, useEffect as useEffect11, useState as useState18 } from "react";
|
|
53917
54400
|
|
|
53918
54401
|
// src/core/history.ts
|
|
53919
54402
|
init_storage();
|
|
@@ -53970,7 +54453,7 @@ function getEntries() {
|
|
|
53970
54453
|
// src/tui/context/command.tsx
|
|
53971
54454
|
import {
|
|
53972
54455
|
createContext as createContext7,
|
|
53973
|
-
useCallback as
|
|
54456
|
+
useCallback as useCallback8,
|
|
53974
54457
|
useContext as useContext7,
|
|
53975
54458
|
useEffect as useEffect5,
|
|
53976
54459
|
useMemo as useMemo8,
|
|
@@ -54365,7 +54848,7 @@ function deobfuscate(input) {
|
|
|
54365
54848
|
return output;
|
|
54366
54849
|
}
|
|
54367
54850
|
// src/tui/command-registry.ts
|
|
54368
|
-
|
|
54851
|
+
init_config();
|
|
54369
54852
|
|
|
54370
54853
|
// src/tui/utils/command-flags.ts
|
|
54371
54854
|
import { readFileSync } from "node:fs";
|
|
@@ -55023,8 +55506,8 @@ var commands = [
|
|
|
55023
55506
|
aliases: ["quit", "q"],
|
|
55024
55507
|
description: "Exit the application",
|
|
55025
55508
|
category: "General",
|
|
55026
|
-
handler: async () => {
|
|
55027
|
-
|
|
55509
|
+
handler: async (_args, ctx2) => {
|
|
55510
|
+
await ctx2.exitApplication?.();
|
|
55028
55511
|
}
|
|
55029
55512
|
},
|
|
55030
55513
|
{
|
|
@@ -55268,7 +55751,7 @@ var useRoute = () => {
|
|
|
55268
55751
|
// src/tui/context/toast.tsx
|
|
55269
55752
|
import {
|
|
55270
55753
|
createContext as createContext6,
|
|
55271
|
-
useCallback as
|
|
55754
|
+
useCallback as useCallback7,
|
|
55272
55755
|
useContext as useContext6,
|
|
55273
55756
|
useMemo as useMemo7,
|
|
55274
55757
|
useState as useState8
|
|
@@ -55283,10 +55766,10 @@ var DEFAULT_DURATION = {
|
|
|
55283
55766
|
};
|
|
55284
55767
|
function ToastProvider({ children }) {
|
|
55285
55768
|
const [toasts, setToasts] = useState8([]);
|
|
55286
|
-
const dismiss =
|
|
55769
|
+
const dismiss = useCallback7((id) => {
|
|
55287
55770
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
55288
55771
|
}, []);
|
|
55289
|
-
const toast =
|
|
55772
|
+
const toast = useCallback7((message, variant = "default", duration) => {
|
|
55290
55773
|
const id = nextId++;
|
|
55291
55774
|
const ms = duration ?? DEFAULT_DURATION[variant];
|
|
55292
55775
|
setToasts((prev) => [...prev, { id, message, variant, duration: ms }]);
|
|
@@ -55309,11 +55792,11 @@ function useToast() {
|
|
|
55309
55792
|
import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
|
|
55310
55793
|
var CommandContext = createContext7(null);
|
|
55311
55794
|
function useCommand() {
|
|
55312
|
-
const
|
|
55313
|
-
if (!
|
|
55795
|
+
const context2 = useContext7(CommandContext);
|
|
55796
|
+
if (!context2) {
|
|
55314
55797
|
throw new Error("useCommand must be used within CommandProvider");
|
|
55315
55798
|
}
|
|
55316
|
-
return
|
|
55799
|
+
return context2;
|
|
55317
55800
|
}
|
|
55318
55801
|
function CommandProvider({
|
|
55319
55802
|
children,
|
|
@@ -55326,7 +55809,8 @@ function CommandProvider({
|
|
|
55326
55809
|
onOpenHelpDialog,
|
|
55327
55810
|
onOpenAuthDialog,
|
|
55328
55811
|
onOpenPentestDialog,
|
|
55329
|
-
onOpenSkillsDialog
|
|
55812
|
+
onOpenSkillsDialog,
|
|
55813
|
+
onExit
|
|
55330
55814
|
}) {
|
|
55331
55815
|
const route = useRoute();
|
|
55332
55816
|
const obfuscation = useObfuscation();
|
|
@@ -55347,6 +55831,7 @@ function CommandProvider({
|
|
|
55347
55831
|
openAuthDialog: onOpenAuthDialog,
|
|
55348
55832
|
openPentestDialog: onOpenPentestDialog,
|
|
55349
55833
|
openSkillsDialog: onOpenSkillsDialog,
|
|
55834
|
+
exitApplication: onExit,
|
|
55350
55835
|
setObfuscation: (enabled) => {
|
|
55351
55836
|
const current = isObfuscationEnabled();
|
|
55352
55837
|
const next = typeof enabled === "boolean" ? enabled : !current;
|
|
@@ -55369,10 +55854,11 @@ function CommandProvider({
|
|
|
55369
55854
|
onOpenAuthDialog,
|
|
55370
55855
|
onOpenPentestDialog,
|
|
55371
55856
|
onOpenSkillsDialog,
|
|
55857
|
+
onExit,
|
|
55372
55858
|
obfuscation,
|
|
55373
55859
|
toast
|
|
55374
55860
|
]);
|
|
55375
|
-
const refreshSkills =
|
|
55861
|
+
const refreshSkills = useCallback8(async () => {
|
|
55376
55862
|
await registry.refresh();
|
|
55377
55863
|
setRegistryVersion((v) => v + 1);
|
|
55378
55864
|
}, [registry]);
|
|
@@ -55388,7 +55874,7 @@ function CommandProvider({
|
|
|
55388
55874
|
}
|
|
55389
55875
|
return router2;
|
|
55390
55876
|
}, []);
|
|
55391
|
-
const resolveSkillContent =
|
|
55877
|
+
const resolveSkillContent = useCallback8((input) => {
|
|
55392
55878
|
const trimmed = input.trim().replace(/^\/+/, "").toLowerCase();
|
|
55393
55879
|
const entry = registry.get(trimmed);
|
|
55394
55880
|
if (entry) {
|
|
@@ -55458,7 +55944,7 @@ function CommandProvider({
|
|
|
55458
55944
|
}
|
|
55459
55945
|
return names;
|
|
55460
55946
|
}, []);
|
|
55461
|
-
const executeCommand =
|
|
55947
|
+
const executeCommand = useCallback8(async (input) => {
|
|
55462
55948
|
return await router.execute(input, ctx3);
|
|
55463
55949
|
}, [router, ctx3]);
|
|
55464
55950
|
const value = useMemo8(() => ({
|
|
@@ -55493,7 +55979,7 @@ function CommandProvider({
|
|
|
55493
55979
|
import { useKeyboard as useKeyboard3, useRenderer as useRenderer3 } from "@opentui/react";
|
|
55494
55980
|
import {
|
|
55495
55981
|
createContext as createContext9,
|
|
55496
|
-
useCallback as
|
|
55982
|
+
useCallback as useCallback9,
|
|
55497
55983
|
useContext as useContext9,
|
|
55498
55984
|
useRef as useRef4,
|
|
55499
55985
|
useState as useState10
|
|
@@ -55578,7 +56064,7 @@ function DialogProvider({ children }) {
|
|
|
55578
56064
|
const [externalDialogOpen, setExternalDialogOpen] = useState10(false);
|
|
55579
56065
|
const renderer = useRenderer3();
|
|
55580
56066
|
const focusRef = useRef4(null);
|
|
55581
|
-
const refocus =
|
|
56067
|
+
const refocus = useCallback9(() => {
|
|
55582
56068
|
setTimeout(() => {
|
|
55583
56069
|
const focus = focusRef.current;
|
|
55584
56070
|
if (!focus)
|
|
@@ -55600,7 +56086,7 @@ function DialogProvider({ children }) {
|
|
|
55600
56086
|
focus.focus();
|
|
55601
56087
|
}, 1);
|
|
55602
56088
|
}, [renderer]);
|
|
55603
|
-
const clear =
|
|
56089
|
+
const clear = useCallback9(() => {
|
|
55604
56090
|
for (const item of stack) {
|
|
55605
56091
|
if (item.onClose)
|
|
55606
56092
|
item.onClose();
|
|
@@ -55609,7 +56095,7 @@ function DialogProvider({ children }) {
|
|
|
55609
56095
|
setStack([]);
|
|
55610
56096
|
refocus();
|
|
55611
56097
|
}, [stack, refocus]);
|
|
55612
|
-
const replace =
|
|
56098
|
+
const replace = useCallback9((element, options) => {
|
|
55613
56099
|
if (stack.length === 0) {
|
|
55614
56100
|
focusRef.current = renderer.currentFocusedRenderable;
|
|
55615
56101
|
}
|
|
@@ -55673,7 +56159,7 @@ function useDialog() {
|
|
|
55673
56159
|
// src/tui/context/focus.tsx
|
|
55674
56160
|
import {
|
|
55675
56161
|
createContext as createContext10,
|
|
55676
|
-
useCallback as
|
|
56162
|
+
useCallback as useCallback10,
|
|
55677
56163
|
useContext as useContext10,
|
|
55678
56164
|
useRef as useRef5
|
|
55679
56165
|
} from "react";
|
|
@@ -55681,17 +56167,17 @@ import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
|
|
|
55681
56167
|
var FocusContext = createContext10(undefined);
|
|
55682
56168
|
function FocusProvider({ children }) {
|
|
55683
56169
|
const promptRef = useRef5(null);
|
|
55684
|
-
const refocusPrompt =
|
|
56170
|
+
const refocusPrompt = useCallback10(() => {
|
|
55685
56171
|
setTimeout(() => {
|
|
55686
56172
|
promptRef.current?.focus();
|
|
55687
56173
|
}, 1);
|
|
55688
56174
|
}, []);
|
|
55689
|
-
const focusPrompt =
|
|
55690
|
-
const blurPrompt =
|
|
55691
|
-
const resetPrompt =
|
|
55692
|
-
const setPromptValue =
|
|
55693
|
-
const getPromptValue =
|
|
55694
|
-
const registerPromptRef =
|
|
56175
|
+
const focusPrompt = useCallback10(() => promptRef.current?.focus(), []);
|
|
56176
|
+
const blurPrompt = useCallback10(() => promptRef.current?.blur(), []);
|
|
56177
|
+
const resetPrompt = useCallback10(() => promptRef.current?.reset(), []);
|
|
56178
|
+
const setPromptValue = useCallback10((value) => promptRef.current?.setValue(value), []);
|
|
56179
|
+
const getPromptValue = useCallback10(() => promptRef.current?.getValue() ?? "", []);
|
|
56180
|
+
const registerPromptRef = useCallback10((ref) => {
|
|
55695
56181
|
promptRef.current = ref;
|
|
55696
56182
|
}, []);
|
|
55697
56183
|
return /* @__PURE__ */ jsxDEV12(FocusContext.Provider, {
|
|
@@ -55709,17 +56195,17 @@ function FocusProvider({ children }) {
|
|
|
55709
56195
|
}, undefined, false, undefined, this);
|
|
55710
56196
|
}
|
|
55711
56197
|
function useFocus() {
|
|
55712
|
-
const
|
|
55713
|
-
if (!
|
|
56198
|
+
const context2 = useContext10(FocusContext);
|
|
56199
|
+
if (!context2) {
|
|
55714
56200
|
throw new Error("useFocus must be used within FocusProvider");
|
|
55715
56201
|
}
|
|
55716
|
-
return
|
|
56202
|
+
return context2;
|
|
55717
56203
|
}
|
|
55718
56204
|
|
|
55719
56205
|
// src/tui/context/input.tsx
|
|
55720
56206
|
import {
|
|
55721
56207
|
createContext as createContext11,
|
|
55722
|
-
useCallback as
|
|
56208
|
+
useCallback as useCallback11,
|
|
55723
56209
|
useContext as useContext11,
|
|
55724
56210
|
useState as useState11
|
|
55725
56211
|
} from "react";
|
|
@@ -55727,7 +56213,7 @@ import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
|
|
|
55727
56213
|
var InputContext = createContext11(undefined);
|
|
55728
56214
|
function InputProvider({ children }) {
|
|
55729
56215
|
const [inputValue, setInputValue] = useState11("");
|
|
55730
|
-
const clearInput =
|
|
56216
|
+
const clearInput = useCallback11(() => {
|
|
55731
56217
|
setInputValue("");
|
|
55732
56218
|
}, []);
|
|
55733
56219
|
return /* @__PURE__ */ jsxDEV13(InputContext.Provider, {
|
|
@@ -55741,11 +56227,11 @@ function InputProvider({ children }) {
|
|
|
55741
56227
|
}, undefined, false, undefined, this);
|
|
55742
56228
|
}
|
|
55743
56229
|
function useInput() {
|
|
55744
|
-
const
|
|
55745
|
-
if (!
|
|
56230
|
+
const context2 = useContext11(InputContext);
|
|
56231
|
+
if (!context2) {
|
|
55746
56232
|
throw new Error("useInput must be used within InputProvider");
|
|
55747
56233
|
}
|
|
55748
|
-
return
|
|
56234
|
+
return context2;
|
|
55749
56235
|
}
|
|
55750
56236
|
|
|
55751
56237
|
// src/tui/components/shared/tool-registry.ts
|
|
@@ -57371,7 +57857,7 @@ function markdownToStyledText(rawContent, colors2) {
|
|
|
57371
57857
|
import {
|
|
57372
57858
|
SyntaxStyle
|
|
57373
57859
|
} from "@opentui/core";
|
|
57374
|
-
import { useCallback as
|
|
57860
|
+
import { useCallback as useCallback12, useMemo as useMemo9, useRef as useRef6 } from "react";
|
|
57375
57861
|
function useMarkdownSyntaxStyle() {
|
|
57376
57862
|
const { colors: colors2 } = useTheme();
|
|
57377
57863
|
return useMemo9(() => SyntaxStyle.fromStyles({
|
|
@@ -57392,7 +57878,7 @@ function useMarkdownSyntaxStyle() {
|
|
|
57392
57878
|
}
|
|
57393
57879
|
function useMarkdownRenderNode() {
|
|
57394
57880
|
const { colors: colors2 } = useTheme();
|
|
57395
|
-
return
|
|
57881
|
+
return useCallback12((token, ctx3) => {
|
|
57396
57882
|
if (token.type === "code") {
|
|
57397
57883
|
const renderable = ctx3.defaultRender();
|
|
57398
57884
|
if (renderable) {
|
|
@@ -58780,7 +59266,7 @@ function isToolMessage(msg) {
|
|
|
58780
59266
|
}
|
|
58781
59267
|
|
|
58782
59268
|
// src/tui/components/shared/tool-renderer.tsx
|
|
58783
|
-
import { jsxDEV as jsxDEV19, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
59269
|
+
import { jsxDEV as jsxDEV19, Fragment as Fragment2 } from "@opentui/react/jsx-dev-runtime";
|
|
58784
59270
|
var TOOLS_WITH_LOG_WINDOW = new Set([
|
|
58785
59271
|
"execute_command",
|
|
58786
59272
|
"run_attack_surface",
|
|
@@ -58843,7 +59329,7 @@ var ToolRenderer = memo2(function ToolRenderer2({
|
|
|
58843
59329
|
children: isPending ? /* @__PURE__ */ jsxDEV19(ShiningText, {
|
|
58844
59330
|
text: summary,
|
|
58845
59331
|
fg: colors2.warning
|
|
58846
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19(
|
|
59332
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19(Fragment2, {
|
|
58847
59333
|
children: [
|
|
58848
59334
|
/* @__PURE__ */ jsxDEV19("text", {
|
|
58849
59335
|
fg: isError ? colors2.error : colors2.success,
|
|
@@ -59990,7 +60476,7 @@ var PromptInput = forwardRef(function PromptInput2({
|
|
|
59990
60476
|
import { useKeyboard as useKeyboard5 } from "@opentui/react";
|
|
59991
60477
|
import { useEffect as useEffect9, useRef as useRef9, useState as useState16 } from "react";
|
|
59992
60478
|
import { jsxDEV as jsxDEV22 } from "@opentui/react/jsx-dev-runtime";
|
|
59993
|
-
var
|
|
60479
|
+
var PROVIDER_DISPLAY_NAMES2 = {
|
|
59994
60480
|
anthropic: "Anthropic",
|
|
59995
60481
|
openai: "OpenAI",
|
|
59996
60482
|
google: "Google",
|
|
@@ -60001,7 +60487,7 @@ var PROVIDER_DISPLAY_NAMES = {
|
|
|
60001
60487
|
inception: "Inception",
|
|
60002
60488
|
local: "Local"
|
|
60003
60489
|
};
|
|
60004
|
-
var providerDisplayName = (p) =>
|
|
60490
|
+
var providerDisplayName = (p) => PROVIDER_DISPLAY_NAMES2[p] ?? p;
|
|
60005
60491
|
function OperatorModeBar({
|
|
60006
60492
|
operatorMode,
|
|
60007
60493
|
modelName,
|
|
@@ -60582,7 +61068,7 @@ function HomeView({ onNavigate, onStartSession }) {
|
|
|
60582
61068
|
useEffect11(() => {
|
|
60583
61069
|
load().then(setCommandHistory);
|
|
60584
61070
|
}, []);
|
|
60585
|
-
const launchOperator =
|
|
61071
|
+
const launchOperator = useCallback13((message, options) => {
|
|
60586
61072
|
const requireApproval = options?.requireApproval ?? true;
|
|
60587
61073
|
route.navigate({
|
|
60588
61074
|
type: "operator",
|
|
@@ -60593,10 +61079,10 @@ function HomeView({ onNavigate, onStartSession }) {
|
|
|
60593
61079
|
}
|
|
60594
61080
|
});
|
|
60595
61081
|
}, [route]);
|
|
60596
|
-
const pushHistory =
|
|
61082
|
+
const pushHistory = useCallback13((entry) => {
|
|
60597
61083
|
push(entry).then(() => setCommandHistory([...getEntries()]));
|
|
60598
61084
|
}, []);
|
|
60599
|
-
const handleSubmit =
|
|
61085
|
+
const handleSubmit = useCallback13((value) => {
|
|
60600
61086
|
if (!value.trim())
|
|
60601
61087
|
return;
|
|
60602
61088
|
pushHistory(value.trim());
|
|
@@ -60608,7 +61094,7 @@ function HomeView({ onNavigate, onStartSession }) {
|
|
|
60608
61094
|
const timer = setTimeout(() => setHintMessage(null), 3000);
|
|
60609
61095
|
return () => clearTimeout(timer);
|
|
60610
61096
|
}, [hintMessage]);
|
|
60611
|
-
const handleCommandExecute =
|
|
61097
|
+
const handleCommandExecute = useCallback13(async (command) => {
|
|
60612
61098
|
const trimmed = command.trim();
|
|
60613
61099
|
pushHistory(trimmed);
|
|
60614
61100
|
const handled = await executeCommand(command);
|
|
@@ -60805,7 +61291,7 @@ function ChatApp({
|
|
|
60805
61291
|
});
|
|
60806
61292
|
}
|
|
60807
61293
|
}, [initialSessionId]);
|
|
60808
|
-
const handleNavigate =
|
|
61294
|
+
const handleNavigate = useCallback14((view, options) => {
|
|
60809
61295
|
if (view === "chat" && options?.sessionId) {
|
|
60810
61296
|
sessions.get(options.sessionId).then((session) => {
|
|
60811
61297
|
if (session) {
|
|
@@ -60817,7 +61303,7 @@ function ChatApp({
|
|
|
60817
61303
|
setCurrentView(view);
|
|
60818
61304
|
}
|
|
60819
61305
|
}, []);
|
|
60820
|
-
const handleStartSession =
|
|
61306
|
+
const handleStartSession = useCallback14(async (directive) => {
|
|
60821
61307
|
const session = await sessions.create({
|
|
60822
61308
|
name: `exploration-${Date.now()}`,
|
|
60823
61309
|
targets: []
|
|
@@ -60826,7 +61312,7 @@ function ChatApp({
|
|
|
60826
61312
|
setInitialDirective(directive);
|
|
60827
61313
|
setCurrentView("chat");
|
|
60828
61314
|
}, []);
|
|
60829
|
-
const handleConfigSubmit =
|
|
61315
|
+
const handleConfigSubmit = useCallback14(async (configData) => {
|
|
60830
61316
|
const hostname = parseHostFromTarget(configData.targetUrl);
|
|
60831
61317
|
const timestamp = new Date().toISOString().split("T")[0];
|
|
60832
61318
|
const sessionName = `${hostname}-${timestamp}`;
|
|
@@ -60849,12 +61335,12 @@ function ChatApp({
|
|
|
60849
61335
|
setSessionModel(configData.model);
|
|
60850
61336
|
setCurrentView("chat");
|
|
60851
61337
|
}, []);
|
|
60852
|
-
const handleExitChat =
|
|
61338
|
+
const handleExitChat = useCallback14(() => {
|
|
60853
61339
|
setCurrentView("home");
|
|
60854
61340
|
setActiveSession(null);
|
|
60855
61341
|
setInitialDirective(undefined);
|
|
60856
61342
|
}, []);
|
|
60857
|
-
const handleBackFromConfig =
|
|
61343
|
+
const handleBackFromConfig = useCallback14(() => {
|
|
60858
61344
|
setCurrentView("home");
|
|
60859
61345
|
}, []);
|
|
60860
61346
|
return /* @__PURE__ */ jsxDEV25("box", {
|
|
@@ -60887,7 +61373,7 @@ function parseHostFromTarget(target) {
|
|
|
60887
61373
|
|
|
60888
61374
|
// src/tui/components/commands/advanced-settings.tsx
|
|
60889
61375
|
import { useKeyboard as useKeyboard6 } from "@opentui/react";
|
|
60890
|
-
import { useCallback as
|
|
61376
|
+
import { useCallback as useCallback15, useState as useState20 } from "react";
|
|
60891
61377
|
|
|
60892
61378
|
// src/tui/components/dialog-layout.tsx
|
|
60893
61379
|
import { jsxDEV as jsxDEV26 } from "@opentui/react/jsx-dev-runtime";
|
|
@@ -60959,7 +61445,7 @@ function AdvancedSettings({ onClose }) {
|
|
|
60959
61445
|
const [saving, setSaving] = useState20(false);
|
|
60960
61446
|
const [error, setError] = useState20(null);
|
|
60961
61447
|
const [draftStrikeMode, setDraftStrikeMode] = useState20(config2.data.strikeMode ?? false);
|
|
60962
|
-
const saveSettings =
|
|
61448
|
+
const saveSettings = useCallback15(async () => {
|
|
60963
61449
|
if (saving)
|
|
60964
61450
|
return;
|
|
60965
61451
|
setSaving(true);
|
|
@@ -61041,9 +61527,9 @@ function AdvancedSettings({ onClose }) {
|
|
|
61041
61527
|
|
|
61042
61528
|
// src/tui/components/commands/auth-flow.tsx
|
|
61043
61529
|
import { useKeyboard as useKeyboard7 } from "@opentui/react";
|
|
61044
|
-
import { useCallback as
|
|
61530
|
+
import { useCallback as useCallback16, useEffect as useEffect13, useRef as useRef11, useState as useState21 } from "react";
|
|
61045
61531
|
init_auth();
|
|
61046
|
-
|
|
61532
|
+
init_config();
|
|
61047
61533
|
|
|
61048
61534
|
// src/tui/utils/open-url.ts
|
|
61049
61535
|
var OPEN_FAILED_MSG = "Couldn't open browser — visit the URL shown instead";
|
|
@@ -61117,7 +61603,7 @@ function AuthFlow({ onClose, hideEsc }) {
|
|
|
61117
61603
|
const goHome = () => {
|
|
61118
61604
|
onClose();
|
|
61119
61605
|
};
|
|
61120
|
-
const cleanup =
|
|
61606
|
+
const cleanup = useCallback16(() => {
|
|
61121
61607
|
abortRef.current?.abort();
|
|
61122
61608
|
abortRef.current = null;
|
|
61123
61609
|
}, []);
|
|
@@ -61678,9 +62164,9 @@ function AuthFlow({ onClose, hideEsc }) {
|
|
|
61678
62164
|
|
|
61679
62165
|
// src/tui/components/commands/credits-flow.tsx
|
|
61680
62166
|
import { useKeyboard as useKeyboard8 } from "@opentui/react";
|
|
61681
|
-
import { useCallback as
|
|
62167
|
+
import { useCallback as useCallback17, useEffect as useEffect14, useState as useState22 } from "react";
|
|
61682
62168
|
init_auth();
|
|
61683
|
-
import { jsxDEV as jsxDEV29, Fragment as
|
|
62169
|
+
import { jsxDEV as jsxDEV29, Fragment as Fragment3 } from "@opentui/react/jsx-dev-runtime";
|
|
61684
62170
|
function CreditsFlow({
|
|
61685
62171
|
onClose,
|
|
61686
62172
|
onOpenAuthDialog
|
|
@@ -61706,7 +62192,7 @@ function CreditsFlow({
|
|
|
61706
62192
|
});
|
|
61707
62193
|
setStep("browser-opened");
|
|
61708
62194
|
};
|
|
61709
|
-
const fetchBalance =
|
|
62195
|
+
const fetchBalance = useCallback17(async () => {
|
|
61710
62196
|
setStep("loading");
|
|
61711
62197
|
setError(null);
|
|
61712
62198
|
try {
|
|
@@ -61816,7 +62302,7 @@ function CreditsFlow({
|
|
|
61816
62302
|
error
|
|
61817
62303
|
]
|
|
61818
62304
|
}, undefined, true, undefined, this)
|
|
61819
|
-
}, undefined, false, undefined, this) : credits ? /* @__PURE__ */ jsxDEV29(
|
|
62305
|
+
}, undefined, false, undefined, this) : credits ? /* @__PURE__ */ jsxDEV29(Fragment3, {
|
|
61820
62306
|
children: [
|
|
61821
62307
|
/* @__PURE__ */ jsxDEV29("box", {
|
|
61822
62308
|
children: /* @__PURE__ */ jsxDEV29("text", {
|
|
@@ -62109,7 +62595,6 @@ function HelpDialog({ onClose }) {
|
|
|
62109
62595
|
// src/tui/components/commands/models-display.tsx
|
|
62110
62596
|
import { useKeyboard as useKeyboard10 } from "@opentui/react";
|
|
62111
62597
|
// src/tui/components/model-picker/ModelPickerDialog.tsx
|
|
62112
|
-
init_ai();
|
|
62113
62598
|
import { jsxDEV as jsxDEV31 } from "@opentui/react/jsx-dev-runtime";
|
|
62114
62599
|
function ModelPickerDialog({ onClose }) {
|
|
62115
62600
|
const { colors: colors2 } = useTheme();
|
|
@@ -62123,17 +62608,9 @@ function ModelPickerDialog({ onClose }) {
|
|
|
62123
62608
|
openAIReasoningEffort,
|
|
62124
62609
|
setOpenAIReasoningEffort
|
|
62125
62610
|
} = useAgent();
|
|
62126
|
-
const thinkingSupported = modelSupportsThinking(model.id);
|
|
62127
|
-
const openAIReasoningSupported = modelSupportsOpenAIReasoning(model.id);
|
|
62128
62611
|
const footerActions = [
|
|
62129
62612
|
{ key: "Enter", label: "confirm", variant: "primary" }
|
|
62130
62613
|
];
|
|
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
62614
|
const title = /* @__PURE__ */ jsxDEV31("text", {
|
|
62138
62615
|
children: [
|
|
62139
62616
|
/* @__PURE__ */ jsxDEV31("span", {
|
|
@@ -62609,7 +63086,7 @@ function HITLWizard(props) {
|
|
|
62609
63086
|
}
|
|
62610
63087
|
|
|
62611
63088
|
// src/tui/components/commands/provider-manager.tsx
|
|
62612
|
-
|
|
63089
|
+
init_config();
|
|
62613
63090
|
import { useKeyboard as useKeyboard14 } from "@opentui/react";
|
|
62614
63091
|
import { useState as useState27 } from "react";
|
|
62615
63092
|
|
|
@@ -62863,7 +63340,7 @@ function ProviderSelection({
|
|
|
62863
63340
|
}
|
|
62864
63341
|
|
|
62865
63342
|
// src/tui/components/commands/provider-manager.tsx
|
|
62866
|
-
import { jsxDEV as jsxDEV37, Fragment as
|
|
63343
|
+
import { jsxDEV as jsxDEV37, Fragment as Fragment4 } from "@opentui/react/jsx-dev-runtime";
|
|
62867
63344
|
function ProviderManager({
|
|
62868
63345
|
onClose,
|
|
62869
63346
|
onOpenModelDialog
|
|
@@ -62939,7 +63416,7 @@ function ProviderManager({
|
|
|
62939
63416
|
};
|
|
62940
63417
|
const otherProviders = AVAILABLE_PROVIDERS.filter((p) => p.id !== "pensar");
|
|
62941
63418
|
const selectedProviderInfo = AVAILABLE_PROVIDERS.find((p) => p.id === selectedProvider);
|
|
62942
|
-
return /* @__PURE__ */ jsxDEV37(
|
|
63419
|
+
return /* @__PURE__ */ jsxDEV37(Fragment4, {
|
|
62943
63420
|
children: [
|
|
62944
63421
|
flowState === "choosing" && /* @__PURE__ */ jsxDEV37(OnboardingChoice, {
|
|
62945
63422
|
onPensarSelected: () => setFlowState("auth"),
|
|
@@ -63052,13 +63529,13 @@ function OnboardingChoice({
|
|
|
63052
63529
|
|
|
63053
63530
|
// src/tui/components/commands/sessions-display.tsx
|
|
63054
63531
|
import { useKeyboard as useKeyboard16 } from "@opentui/react";
|
|
63055
|
-
import { useCallback as
|
|
63532
|
+
import { useCallback as useCallback19, useEffect as useEffect18, useRef as useRef14, useState as useState29 } from "react";
|
|
63056
63533
|
init_session();
|
|
63057
63534
|
|
|
63058
63535
|
// src/tui/hooks/use-sessions-list.ts
|
|
63059
63536
|
import { existsSync, readdirSync } from "node:fs";
|
|
63060
63537
|
import { join } from "node:path";
|
|
63061
|
-
import { useCallback as
|
|
63538
|
+
import { useCallback as useCallback18, useEffect as useEffect17, useState as useState28 } from "react";
|
|
63062
63539
|
init_session();
|
|
63063
63540
|
function countFindings(findingsPath) {
|
|
63064
63541
|
try {
|
|
@@ -63076,7 +63553,7 @@ function useSessionsList() {
|
|
|
63076
63553
|
const [allSessions, setAllSessions] = useState28([]);
|
|
63077
63554
|
const [loading, setLoading] = useState28(true);
|
|
63078
63555
|
const [searchTerm, setSearchTerm] = useState28("");
|
|
63079
|
-
const loadSessions =
|
|
63556
|
+
const loadSessions = useCallback18(async () => {
|
|
63080
63557
|
try {
|
|
63081
63558
|
const enriched = [];
|
|
63082
63559
|
for await (const session of list()) {
|
|
@@ -63101,7 +63578,7 @@ function useSessionsList() {
|
|
|
63101
63578
|
useEffect17(() => {
|
|
63102
63579
|
loadSessions();
|
|
63103
63580
|
}, [loadSessions]);
|
|
63104
|
-
const deleteSession =
|
|
63581
|
+
const deleteSession = useCallback18(async (id) => {
|
|
63105
63582
|
setAllSessions((prev) => prev.filter((s) => s.id !== id));
|
|
63106
63583
|
await sessions.remove({ sessionId: id });
|
|
63107
63584
|
await loadSessions();
|
|
@@ -63334,7 +63811,7 @@ function SessionsDisplay({ onClose }) {
|
|
|
63334
63811
|
initialOverflowRef.current = estimatedRows > availableListHeight;
|
|
63335
63812
|
}
|
|
63336
63813
|
const listHeight = initialOverflowRef.current ? availableListHeight : undefined;
|
|
63337
|
-
const viewReport =
|
|
63814
|
+
const viewReport = useCallback19(async (sessionId) => {
|
|
63338
63815
|
const session = await sessions.get(sessionId);
|
|
63339
63816
|
const content = readSessionReport(session.rootPath);
|
|
63340
63817
|
if (!content) {
|
|
@@ -63345,7 +63822,7 @@ function SessionsDisplay({ onClose }) {
|
|
|
63345
63822
|
setReportSessionPath(session.rootPath);
|
|
63346
63823
|
setShowReportViewer(true);
|
|
63347
63824
|
}, [toast]);
|
|
63348
|
-
const openReportExternal =
|
|
63825
|
+
const openReportExternal = useCallback19(async () => {
|
|
63349
63826
|
if (!reportSessionPath)
|
|
63350
63827
|
return;
|
|
63351
63828
|
const err = await openSessionReport(reportSessionPath);
|
|
@@ -63971,9 +64448,9 @@ function SkillsDialog({
|
|
|
63971
64448
|
}
|
|
63972
64449
|
|
|
63973
64450
|
// src/tui/components/commands/theme-picker.tsx
|
|
63974
|
-
|
|
64451
|
+
init_config();
|
|
63975
64452
|
import { useKeyboard as useKeyboard19 } from "@opentui/react";
|
|
63976
|
-
import { useCallback as
|
|
64453
|
+
import { useCallback as useCallback20, useRef as useRef16, useState as useState31 } from "react";
|
|
63977
64454
|
import { jsxDEV as jsxDEV42 } from "@opentui/react/jsx-dev-runtime";
|
|
63978
64455
|
function ThemePicker({ onClose }) {
|
|
63979
64456
|
const dimensions = useDimensions();
|
|
@@ -63992,14 +64469,14 @@ function ThemePicker({ onClose }) {
|
|
|
63992
64469
|
const originalThemeRef = useRef16(theme.name);
|
|
63993
64470
|
const originalModeRef = useRef16(mode);
|
|
63994
64471
|
const originalTransparentRef = useRef16(transparent);
|
|
63995
|
-
const handleClose =
|
|
64472
|
+
const handleClose = useCallback20(() => {
|
|
63996
64473
|
setTheme(originalThemeRef.current);
|
|
63997
64474
|
setMode(originalModeRef.current);
|
|
63998
64475
|
if (transparent !== originalTransparentRef.current)
|
|
63999
64476
|
toggleTransparent();
|
|
64000
64477
|
onClose();
|
|
64001
64478
|
}, [setTheme, setMode, transparent, toggleTransparent, onClose]);
|
|
64002
|
-
const handleConfirm =
|
|
64479
|
+
const handleConfirm = useCallback20(async () => {
|
|
64003
64480
|
const currentThemeName = availableThemes[selectedIndex];
|
|
64004
64481
|
if (currentThemeName) {
|
|
64005
64482
|
await config.update({ theme: currentThemeName });
|
|
@@ -64125,7 +64602,7 @@ function ThemePicker({ onClose }) {
|
|
|
64125
64602
|
// src/tui/components/commands/web-wizard.tsx
|
|
64126
64603
|
import { useKeyboard as useKeyboard20 } from "@opentui/react";
|
|
64127
64604
|
import { useEffect as useEffect20, useRef as useRef17, useState as useState32 } from "react";
|
|
64128
|
-
import { jsxDEV as jsxDEV43, Fragment as
|
|
64605
|
+
import { jsxDEV as jsxDEV43, Fragment as Fragment5 } from "@opentui/react/jsx-dev-runtime";
|
|
64129
64606
|
function capitalize(s) {
|
|
64130
64607
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
64131
64608
|
}
|
|
@@ -64611,7 +65088,7 @@ function WebWizard({
|
|
|
64611
65088
|
}, undefined, false, undefined, this)
|
|
64612
65089
|
]
|
|
64613
65090
|
}, undefined, true, undefined, this),
|
|
64614
|
-
advancedExpanded && /* @__PURE__ */ jsxDEV43(
|
|
65091
|
+
advancedExpanded && /* @__PURE__ */ jsxDEV43(Fragment5, {
|
|
64615
65092
|
children: [
|
|
64616
65093
|
/* @__PURE__ */ jsxDEV43("box", {
|
|
64617
65094
|
id: `field-${promptFieldIndex}`,
|
|
@@ -64849,7 +65326,7 @@ function WebWizard({
|
|
|
64849
65326
|
}, undefined, false, undefined, this)
|
|
64850
65327
|
]
|
|
64851
65328
|
}, undefined, true, undefined, this),
|
|
64852
|
-
state.headers.mode === "custom" && /* @__PURE__ */ jsxDEV43(
|
|
65329
|
+
state.headers.mode === "custom" && /* @__PURE__ */ jsxDEV43(Fragment5, {
|
|
64853
65330
|
children: [
|
|
64854
65331
|
/* @__PURE__ */ jsxDEV43("box", {
|
|
64855
65332
|
id: `field-${headersNameIndex}`,
|
|
@@ -64897,7 +65374,7 @@ function WebWizard({
|
|
|
64897
65374
|
|
|
64898
65375
|
// src/tui/components/error-boundary.tsx
|
|
64899
65376
|
init_logger();
|
|
64900
|
-
import React, { useCallback as
|
|
65377
|
+
import React, { useCallback as useCallback21 } from "react";
|
|
64901
65378
|
var MAX_ERRORS = 3;
|
|
64902
65379
|
var ERROR_WINDOW_MS = 5000;
|
|
64903
65380
|
|
|
@@ -64932,7 +65409,7 @@ class ErrorBoundaryInner extends React.Component {
|
|
|
64932
65409
|
}
|
|
64933
65410
|
function ErrorBoundary({ children }) {
|
|
64934
65411
|
const { toast } = useToast();
|
|
64935
|
-
const handleError =
|
|
65412
|
+
const handleError = useCallback21((message) => {
|
|
64936
65413
|
toast(message, "error");
|
|
64937
65414
|
}, [toast]);
|
|
64938
65415
|
return React.createElement(ErrorBoundaryInner, { onError: handleError }, children);
|
|
@@ -64986,19 +65463,52 @@ var useSession = () => {
|
|
|
64986
65463
|
return session;
|
|
64987
65464
|
};
|
|
64988
65465
|
|
|
64989
|
-
// src/tui/components/
|
|
64990
|
-
|
|
65466
|
+
// src/tui/components/usage-labels.ts
|
|
65467
|
+
var WIDE_MIN_WIDTH = 86;
|
|
65468
|
+
var NARROW_MIN_WIDTH = 56;
|
|
64991
65469
|
function formatTokenCount(count) {
|
|
64992
65470
|
if (count >= 1e6) {
|
|
64993
65471
|
const v2 = count / 1e6;
|
|
64994
|
-
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}
|
|
65472
|
+
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}m`;
|
|
64995
65473
|
}
|
|
64996
65474
|
if (count >= 1000) {
|
|
64997
65475
|
const v2 = count / 1000;
|
|
64998
|
-
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}
|
|
65476
|
+
return `${Number.isInteger(v2) ? v2.toFixed(0) : v2.toFixed(1)}k`;
|
|
64999
65477
|
}
|
|
65000
65478
|
return count.toString();
|
|
65001
65479
|
}
|
|
65480
|
+
function buildUsageFooterLabels(input) {
|
|
65481
|
+
const { tokenUsage, contextUsage, width } = input;
|
|
65482
|
+
if (width < NARROW_MIN_WIDTH) {
|
|
65483
|
+
return { tokensLabel: null, contextLabel: null };
|
|
65484
|
+
}
|
|
65485
|
+
if (width >= WIDE_MIN_WIDTH) {
|
|
65486
|
+
let tokensLabel = `in ${formatTokenCount(tokenUsage.inputTokens)} out ${formatTokenCount(tokenUsage.outputTokens)}`;
|
|
65487
|
+
if (tokenUsage.cacheReadTokens > 0) {
|
|
65488
|
+
tokensLabel += ` cached ${formatTokenCount(tokenUsage.cacheReadTokens)}`;
|
|
65489
|
+
}
|
|
65490
|
+
return {
|
|
65491
|
+
tokensLabel,
|
|
65492
|
+
contextLabel: contextLabel(contextUsage, true)
|
|
65493
|
+
};
|
|
65494
|
+
}
|
|
65495
|
+
const total = tokenUsage.inputTokens + tokenUsage.outputTokens;
|
|
65496
|
+
return {
|
|
65497
|
+
tokensLabel: `${formatTokenCount(total)} tokens`,
|
|
65498
|
+
contextLabel: contextLabel(contextUsage, false)
|
|
65499
|
+
};
|
|
65500
|
+
}
|
|
65501
|
+
function contextLabel(context2, wide) {
|
|
65502
|
+
const percentage = contextPercentage(context2);
|
|
65503
|
+
if (percentage === null || !context2)
|
|
65504
|
+
return null;
|
|
65505
|
+
const pct = Math.floor(percentage);
|
|
65506
|
+
const limit = formatTokenCount(context2.contextLimit);
|
|
65507
|
+
return wide ? `context ${pct}% / ${limit}` : `${pct}% / ${limit}`;
|
|
65508
|
+
}
|
|
65509
|
+
|
|
65510
|
+
// src/tui/components/footer.tsx
|
|
65511
|
+
import { jsxDEV as jsxDEV45, Fragment as Fragment6 } from "@opentui/react/jsx-dev-runtime";
|
|
65002
65512
|
function Footer({
|
|
65003
65513
|
cwd = process.cwd(),
|
|
65004
65514
|
showExitWarning = false
|
|
@@ -65077,126 +65587,54 @@ function Footer({
|
|
|
65077
65587
|
}
|
|
65078
65588
|
function AgentStatus() {
|
|
65079
65589
|
const { colors: colors2 } = useTheme();
|
|
65080
|
-
const {
|
|
65590
|
+
const { usageStore } = useAgent();
|
|
65081
65591
|
const { width: termWidth } = useDimensions();
|
|
65082
|
-
const
|
|
65083
|
-
const
|
|
65592
|
+
const usage = useActiveSessionUsage(usageStore);
|
|
65593
|
+
const { tokensLabel, contextLabel: contextLabel2 } = buildUsageFooterLabels({
|
|
65594
|
+
tokenUsage: usage.tokenUsage,
|
|
65595
|
+
contextUsage: usage.contextUsage,
|
|
65596
|
+
width: termWidth
|
|
65597
|
+
});
|
|
65598
|
+
if (!tokensLabel)
|
|
65599
|
+
return null;
|
|
65084
65600
|
return /* @__PURE__ */ jsxDEV45("box", {
|
|
65085
65601
|
flexDirection: "row",
|
|
65086
65602
|
gap: 1,
|
|
65087
65603
|
children: [
|
|
65088
|
-
|
|
65604
|
+
/* @__PURE__ */ jsxDEV45("text", {
|
|
65605
|
+
fg: colors2.text,
|
|
65606
|
+
children: tokensLabel
|
|
65607
|
+
}, undefined, false, undefined, this),
|
|
65608
|
+
contextLabel2 && /* @__PURE__ */ jsxDEV45(Fragment6, {
|
|
65089
65609
|
children: [
|
|
65090
|
-
/* @__PURE__ */ jsxDEV45("
|
|
65091
|
-
|
|
65092
|
-
|
|
65610
|
+
/* @__PURE__ */ jsxDEV45("text", {
|
|
65611
|
+
fg: colors2.textMuted,
|
|
65612
|
+
children: "|"
|
|
65093
65613
|
}, undefined, false, undefined, this),
|
|
65094
65614
|
/* @__PURE__ */ jsxDEV45("text", {
|
|
65095
65615
|
fg: colors2.text,
|
|
65096
|
-
children:
|
|
65097
|
-
}, undefined, false, undefined, this),
|
|
65098
|
-
/* @__PURE__ */ jsxDEV45("box", {
|
|
65099
|
-
border: ["right"],
|
|
65100
|
-
borderColor: colors2.primary
|
|
65616
|
+
children: contextLabel2
|
|
65101
65617
|
}, undefined, false, undefined, this)
|
|
65102
65618
|
]
|
|
65103
|
-
}, undefined, true, undefined, this)
|
|
65104
|
-
/* @__PURE__ */ jsxDEV45(ContextProgress, {
|
|
65105
|
-
width: 16,
|
|
65106
|
-
showPercent: true
|
|
65107
|
-
}, undefined, false, undefined, this)
|
|
65619
|
+
}, undefined, true, undefined, this)
|
|
65108
65620
|
]
|
|
65109
65621
|
}, undefined, true, undefined, this);
|
|
65110
65622
|
}
|
|
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
65623
|
|
|
65157
65624
|
// src/tui/components/operator-dashboard/index.tsx
|
|
65158
65625
|
init_dist();
|
|
65159
|
-
import { existsSync as
|
|
65160
|
-
import { isAbsolute as isAbsolute2, join as
|
|
65626
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
65627
|
+
import { isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "node:path";
|
|
65161
65628
|
import { useKeyboard as useKeyboard26 } from "@opentui/react";
|
|
65162
65629
|
import {
|
|
65163
|
-
useCallback as
|
|
65630
|
+
useCallback as useCallback22,
|
|
65164
65631
|
useEffect as useEffect25,
|
|
65165
65632
|
useMemo as useMemo22,
|
|
65166
65633
|
useRef as useRef21,
|
|
65167
65634
|
useState as useState39,
|
|
65168
|
-
useSyncExternalStore as
|
|
65635
|
+
useSyncExternalStore as useSyncExternalStore3
|
|
65169
65636
|
} from "react";
|
|
65170
65637
|
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
65638
|
init_session();
|
|
65201
65639
|
|
|
65202
65640
|
// src/tui/components/chat/approval-inline.tsx
|
|
@@ -66464,6 +66902,202 @@ function ScreenshotModal({ screenshots, initialIndex, onClose }) {
|
|
|
66464
66902
|
}, undefined, true, undefined, this);
|
|
66465
66903
|
}
|
|
66466
66904
|
|
|
66905
|
+
// src/tui/components/operator-dashboard/conversation.ts
|
|
66906
|
+
init_session();
|
|
66907
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
66908
|
+
import { join as join3 } from "node:path";
|
|
66909
|
+
function recoverAbortedConversation(conversation, partialText, displayMessages) {
|
|
66910
|
+
if (conversation.at(-1)?.role !== "user")
|
|
66911
|
+
return null;
|
|
66912
|
+
const pendingTools = displayMessages.filter((message) => message.role === "tool" && typeof message.toolCallId === "string" && typeof message.toolName === "string" && (message.status === "pending" || message.status === "streaming"));
|
|
66913
|
+
const assistantContent = [
|
|
66914
|
+
{
|
|
66915
|
+
type: "text",
|
|
66916
|
+
text: partialText.trim() || "[Response interrupted by user.]"
|
|
66917
|
+
},
|
|
66918
|
+
...pendingTools.map((tool) => ({
|
|
66919
|
+
type: "tool-call",
|
|
66920
|
+
toolCallId: tool.toolCallId,
|
|
66921
|
+
toolName: tool.toolName,
|
|
66922
|
+
input: tool.args ?? {}
|
|
66923
|
+
}))
|
|
66924
|
+
];
|
|
66925
|
+
const recovered = [
|
|
66926
|
+
...conversation,
|
|
66927
|
+
{
|
|
66928
|
+
role: "assistant",
|
|
66929
|
+
content: assistantContent
|
|
66930
|
+
}
|
|
66931
|
+
];
|
|
66932
|
+
if (pendingTools.length === 0)
|
|
66933
|
+
return recovered;
|
|
66934
|
+
return [
|
|
66935
|
+
...recovered,
|
|
66936
|
+
{
|
|
66937
|
+
role: "tool",
|
|
66938
|
+
content: pendingTools.map((tool) => ({
|
|
66939
|
+
type: "tool-result",
|
|
66940
|
+
toolCallId: tool.toolCallId,
|
|
66941
|
+
toolName: tool.toolName ?? "unknown",
|
|
66942
|
+
output: {
|
|
66943
|
+
type: "text",
|
|
66944
|
+
value: "Cancelled by user."
|
|
66945
|
+
}
|
|
66946
|
+
}))
|
|
66947
|
+
}
|
|
66948
|
+
];
|
|
66949
|
+
}
|
|
66950
|
+
function rewriteToolResultOutput(conversation, toolCallId, value) {
|
|
66951
|
+
const wrappedOutput = {
|
|
66952
|
+
type: "json",
|
|
66953
|
+
value
|
|
66954
|
+
};
|
|
66955
|
+
let changed = false;
|
|
66956
|
+
const next = conversation.map((msg) => {
|
|
66957
|
+
if (msg.role !== "tool")
|
|
66958
|
+
return msg;
|
|
66959
|
+
if (!Array.isArray(msg.content))
|
|
66960
|
+
return msg;
|
|
66961
|
+
let mutated = false;
|
|
66962
|
+
const nextContent = msg.content.map((part) => {
|
|
66963
|
+
if (part && typeof part === "object" && "type" in part && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
66964
|
+
mutated = true;
|
|
66965
|
+
return {
|
|
66966
|
+
...part,
|
|
66967
|
+
output: wrappedOutput
|
|
66968
|
+
};
|
|
66969
|
+
}
|
|
66970
|
+
return part;
|
|
66971
|
+
});
|
|
66972
|
+
if (!mutated)
|
|
66973
|
+
return msg;
|
|
66974
|
+
changed = true;
|
|
66975
|
+
return { ...msg, content: nextContent };
|
|
66976
|
+
});
|
|
66977
|
+
return changed ? next : conversation;
|
|
66978
|
+
}
|
|
66979
|
+
function recoverAbortedTranscript(input) {
|
|
66980
|
+
const messagesPath = join3(input.rootPath, "messages.json");
|
|
66981
|
+
let conversation = input.conversation;
|
|
66982
|
+
let recovered = null;
|
|
66983
|
+
try {
|
|
66984
|
+
if (existsSync3(messagesPath)) {
|
|
66985
|
+
const raw = JSON.parse(readFileSync3(messagesPath, "utf-8"));
|
|
66986
|
+
if (Array.isArray(raw) && raw.length > 0) {
|
|
66987
|
+
conversation = normalizeMessages(getResumeMessages(raw));
|
|
66988
|
+
}
|
|
66989
|
+
}
|
|
66990
|
+
recovered = recoverAbortedConversation(conversation, input.partialText, input.displayMessages);
|
|
66991
|
+
} catch {}
|
|
66992
|
+
if (!recovered)
|
|
66993
|
+
return conversation;
|
|
66994
|
+
conversation = recovered;
|
|
66995
|
+
try {
|
|
66996
|
+
writeFileSync(messagesPath, JSON.stringify(recovered, null, 2));
|
|
66997
|
+
} catch {}
|
|
66998
|
+
return conversation;
|
|
66999
|
+
}
|
|
67000
|
+
|
|
67001
|
+
// src/tui/components/operator-dashboard/display-state.ts
|
|
67002
|
+
var MAX_LOG_LINES = 200;
|
|
67003
|
+
function appendStreamedText(messages, accumulated) {
|
|
67004
|
+
const last = messages[messages.length - 1];
|
|
67005
|
+
if (last && last.role === "assistant") {
|
|
67006
|
+
const updated = [...messages];
|
|
67007
|
+
updated[updated.length - 1] = { ...last, content: accumulated };
|
|
67008
|
+
return updated;
|
|
67009
|
+
}
|
|
67010
|
+
return [
|
|
67011
|
+
...messages,
|
|
67012
|
+
{ role: "assistant", content: accumulated, createdAt: new Date }
|
|
67013
|
+
];
|
|
67014
|
+
}
|
|
67015
|
+
function startStreamingToolCall(messages, toolCallId, toolName) {
|
|
67016
|
+
return [
|
|
67017
|
+
...messages,
|
|
67018
|
+
{
|
|
67019
|
+
role: "tool",
|
|
67020
|
+
content: "",
|
|
67021
|
+
createdAt: new Date,
|
|
67022
|
+
toolCallId,
|
|
67023
|
+
toolName,
|
|
67024
|
+
args: {},
|
|
67025
|
+
status: "streaming"
|
|
67026
|
+
}
|
|
67027
|
+
];
|
|
67028
|
+
}
|
|
67029
|
+
function applyToolCallDelta(messages, toolCallId, parsed) {
|
|
67030
|
+
const contentText = extractStreamableContent(parsed);
|
|
67031
|
+
const logs = contentText ? contentText.split(`
|
|
67032
|
+
`) : undefined;
|
|
67033
|
+
const idx = messages.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
67034
|
+
if (idx === -1)
|
|
67035
|
+
return messages;
|
|
67036
|
+
const updated = [...messages];
|
|
67037
|
+
updated[idx] = { ...updated[idx], args: parsed, ...logs && { logs } };
|
|
67038
|
+
return updated;
|
|
67039
|
+
}
|
|
67040
|
+
function applyToolCall(messages, toolCallId, toolName, args) {
|
|
67041
|
+
const idx = messages.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
67042
|
+
if (idx !== -1) {
|
|
67043
|
+
const updated = [...messages];
|
|
67044
|
+
updated[idx] = {
|
|
67045
|
+
...updated[idx],
|
|
67046
|
+
args,
|
|
67047
|
+
logs: undefined,
|
|
67048
|
+
status: "pending"
|
|
67049
|
+
};
|
|
67050
|
+
return updated;
|
|
67051
|
+
}
|
|
67052
|
+
return [
|
|
67053
|
+
...messages,
|
|
67054
|
+
{
|
|
67055
|
+
role: "tool",
|
|
67056
|
+
content: "",
|
|
67057
|
+
createdAt: new Date,
|
|
67058
|
+
toolCallId,
|
|
67059
|
+
toolName,
|
|
67060
|
+
args,
|
|
67061
|
+
status: "pending"
|
|
67062
|
+
}
|
|
67063
|
+
];
|
|
67064
|
+
}
|
|
67065
|
+
function applyToolResult(messages, toolCallId, result) {
|
|
67066
|
+
const idx = messages.findIndex((m2) => isToolMessage(m2) && m2.toolCallId === toolCallId);
|
|
67067
|
+
if (idx === -1)
|
|
67068
|
+
return messages;
|
|
67069
|
+
const updated = [...messages];
|
|
67070
|
+
updated[idx] = { ...updated[idx], status: "completed", result };
|
|
67071
|
+
return updated;
|
|
67072
|
+
}
|
|
67073
|
+
function mergeCommandOutput(messages, buf) {
|
|
67074
|
+
const idx = messages.findLastIndex((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming"));
|
|
67075
|
+
if (idx === -1)
|
|
67076
|
+
return messages;
|
|
67077
|
+
const msg = messages[idx];
|
|
67078
|
+
const existing = msg.logs ?? [];
|
|
67079
|
+
const incoming = buf.split(`
|
|
67080
|
+
`);
|
|
67081
|
+
let merged;
|
|
67082
|
+
if (existing.length > 0 && !buf.startsWith(`
|
|
67083
|
+
`)) {
|
|
67084
|
+
merged = [...existing];
|
|
67085
|
+
merged[merged.length - 1] += incoming[0];
|
|
67086
|
+
merged.push(...incoming.slice(1));
|
|
67087
|
+
} else {
|
|
67088
|
+
merged = [...existing, ...incoming];
|
|
67089
|
+
}
|
|
67090
|
+
if (merged.length > MAX_LOG_LINES) {
|
|
67091
|
+
merged = merged.slice(-MAX_LOG_LINES);
|
|
67092
|
+
}
|
|
67093
|
+
const updated = [...messages];
|
|
67094
|
+
updated[idx] = { ...msg, logs: merged };
|
|
67095
|
+
return updated;
|
|
67096
|
+
}
|
|
67097
|
+
function markInFlightToolsErrored(messages, result) {
|
|
67098
|
+
return messages.map((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result } : m2);
|
|
67099
|
+
}
|
|
67100
|
+
|
|
66467
67101
|
// src/tui/components/operator-dashboard/logic.ts
|
|
66468
67102
|
var OPERATOR_ALLOWED_COMMANDS = new Set([
|
|
66469
67103
|
"/models",
|
|
@@ -66741,17 +67375,6 @@ ${refinementBlock}`;
|
|
|
66741
67375
|
function resolveInputFocused(status, dialogStackLength, externalDialogOpen) {
|
|
66742
67376
|
return status !== "running" && dialogStackLength === 0 && !externalDialogOpen;
|
|
66743
67377
|
}
|
|
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
67378
|
|
|
66756
67379
|
// src/tui/components/operator-dashboard/queue.ts
|
|
66757
67380
|
var nextId3 = 0;
|
|
@@ -66841,6 +67464,401 @@ function QueuedMessages({
|
|
|
66841
67464
|
}, undefined, true, undefined, this);
|
|
66842
67465
|
}
|
|
66843
67466
|
|
|
67467
|
+
// src/tui/components/operator-dashboard/workflow-data.ts
|
|
67468
|
+
function isPentestAgent(id) {
|
|
67469
|
+
return id !== undefined && /^pentest-agent-\d+$/.test(id);
|
|
67470
|
+
}
|
|
67471
|
+
function initialWorkflowData() {
|
|
67472
|
+
return {
|
|
67473
|
+
currentPhase: "discovery",
|
|
67474
|
+
discovery: { label: "", status: "pending", logs: [] },
|
|
67475
|
+
pentesting: { label: "", status: "idle", subagents: {} },
|
|
67476
|
+
reporting: { label: "", status: "idle" }
|
|
67477
|
+
};
|
|
67478
|
+
}
|
|
67479
|
+
function updateWorkflowDataMessage(messages, updater) {
|
|
67480
|
+
const idx = messages.findLastIndex((m2) => isToolMessage(m2) && m2.toolName === "run_pentest_workflow" && (m2.status === "pending" || m2.status === "streaming"));
|
|
67481
|
+
if (idx === -1)
|
|
67482
|
+
return messages;
|
|
67483
|
+
const msg = messages[idx];
|
|
67484
|
+
const wd = msg.workflowData ?? initialWorkflowData();
|
|
67485
|
+
const updated = [...messages];
|
|
67486
|
+
updated[idx] = { ...msg, workflowData: updater(wd) };
|
|
67487
|
+
return updated;
|
|
67488
|
+
}
|
|
67489
|
+
function applyWorkflowSubagentSpawn(wd, subagentId, name) {
|
|
67490
|
+
return {
|
|
67491
|
+
...wd,
|
|
67492
|
+
pentesting: {
|
|
67493
|
+
...wd.pentesting,
|
|
67494
|
+
subagents: {
|
|
67495
|
+
...wd.pentesting.subagents,
|
|
67496
|
+
[subagentId]: { name, status: "pending", logs: [] }
|
|
67497
|
+
}
|
|
67498
|
+
}
|
|
67499
|
+
};
|
|
67500
|
+
}
|
|
67501
|
+
function applyWorkflowSubagentComplete(wd, subagentId, status) {
|
|
67502
|
+
const entry = wd.pentesting.subagents[subagentId];
|
|
67503
|
+
if (!entry)
|
|
67504
|
+
return wd;
|
|
67505
|
+
return {
|
|
67506
|
+
...wd,
|
|
67507
|
+
pentesting: {
|
|
67508
|
+
...wd.pentesting,
|
|
67509
|
+
subagents: {
|
|
67510
|
+
...wd.pentesting.subagents,
|
|
67511
|
+
[subagentId]: { ...entry, status }
|
|
67512
|
+
}
|
|
67513
|
+
}
|
|
67514
|
+
};
|
|
67515
|
+
}
|
|
67516
|
+
function applyWorkflowPhaseStart(wd, phase, label) {
|
|
67517
|
+
const next = { ...wd, currentPhase: phase };
|
|
67518
|
+
if (phase === "discovery") {
|
|
67519
|
+
next.discovery = { ...wd.discovery, label, status: "pending", logs: [] };
|
|
67520
|
+
} else if (phase === "pentesting") {
|
|
67521
|
+
next.pentesting = { ...wd.pentesting, label, status: "pending" };
|
|
67522
|
+
} else if (phase === "reporting") {
|
|
67523
|
+
next.reporting = { ...wd.reporting, label, status: "pending" };
|
|
67524
|
+
}
|
|
67525
|
+
return next;
|
|
67526
|
+
}
|
|
67527
|
+
function applyWorkflowPhaseComplete(wd, phase, summary) {
|
|
67528
|
+
const next = { ...wd };
|
|
67529
|
+
if (phase === "discovery") {
|
|
67530
|
+
const targets = summary.targets ?? [];
|
|
67531
|
+
next.discovery = {
|
|
67532
|
+
...wd.discovery,
|
|
67533
|
+
status: "complete",
|
|
67534
|
+
targets,
|
|
67535
|
+
cached: summary.cached
|
|
67536
|
+
};
|
|
67537
|
+
} else if (phase === "pentesting") {
|
|
67538
|
+
next.pentesting = { ...wd.pentesting, status: "complete" };
|
|
67539
|
+
} else if (phase === "reporting") {
|
|
67540
|
+
next.reporting = {
|
|
67541
|
+
...wd.reporting,
|
|
67542
|
+
status: "complete",
|
|
67543
|
+
findingsCount: summary.findingsCount,
|
|
67544
|
+
findingsBySeverity: summary.findingsBySeverity,
|
|
67545
|
+
reportPath: summary.reportPath
|
|
67546
|
+
};
|
|
67547
|
+
next.currentPhase = "complete";
|
|
67548
|
+
}
|
|
67549
|
+
return next;
|
|
67550
|
+
}
|
|
67551
|
+
|
|
67552
|
+
// src/tui/components/operator-dashboard/run-events.ts
|
|
67553
|
+
function bindOperatorRunEvents(bus, options) {
|
|
67554
|
+
const { isCurrent, handlers } = options;
|
|
67555
|
+
const offs = [];
|
|
67556
|
+
let boundError = false;
|
|
67557
|
+
const bind = (event, handler) => {
|
|
67558
|
+
if (!handler)
|
|
67559
|
+
return;
|
|
67560
|
+
if (event === "error")
|
|
67561
|
+
boundError = true;
|
|
67562
|
+
const wrapped = (e) => {
|
|
67563
|
+
if (!isCurrent())
|
|
67564
|
+
return;
|
|
67565
|
+
try {
|
|
67566
|
+
handler(e);
|
|
67567
|
+
} catch (err) {
|
|
67568
|
+
console.error(`[operator] ${event} handler failed:`, err);
|
|
67569
|
+
}
|
|
67570
|
+
};
|
|
67571
|
+
bus.on(event, wrapped);
|
|
67572
|
+
offs.push(() => bus.off(event, wrapped));
|
|
67573
|
+
};
|
|
67574
|
+
bind("text-delta", handlers.onTextDelta);
|
|
67575
|
+
bind("tool-call-start", handlers.onToolCallStart);
|
|
67576
|
+
bind("tool-call-delta", handlers.onToolCallDelta);
|
|
67577
|
+
bind("tool-call-complete", handlers.onToolCallComplete);
|
|
67578
|
+
bind("tool-result", handlers.onToolResult);
|
|
67579
|
+
bind("command-output", handlers.onCommandOutput);
|
|
67580
|
+
bind("error", handlers.onError);
|
|
67581
|
+
bind("subagent-spawn", handlers.onSubagentSpawn);
|
|
67582
|
+
bind("subagent-complete", handlers.onSubagentComplete);
|
|
67583
|
+
bind("workflow-phase-start", handlers.onWorkflowPhaseStart);
|
|
67584
|
+
bind("workflow-phase-complete", handlers.onWorkflowPhaseComplete);
|
|
67585
|
+
let unbound = false;
|
|
67586
|
+
return () => {
|
|
67587
|
+
if (unbound)
|
|
67588
|
+
return;
|
|
67589
|
+
unbound = true;
|
|
67590
|
+
for (const off of offs)
|
|
67591
|
+
off();
|
|
67592
|
+
offs.length = 0;
|
|
67593
|
+
if (boundError)
|
|
67594
|
+
bus.on("error", () => {});
|
|
67595
|
+
};
|
|
67596
|
+
}
|
|
67597
|
+
var COMMAND_OUTPUT_FLUSH_MS = 150;
|
|
67598
|
+
function createDisplayEventHandlers(sink) {
|
|
67599
|
+
let partialText = "";
|
|
67600
|
+
const toolArgsDeltas = new Map;
|
|
67601
|
+
let commandOutputBuf = "";
|
|
67602
|
+
let flushTimer = null;
|
|
67603
|
+
const flushCommandOutput = () => {
|
|
67604
|
+
if (!commandOutputBuf)
|
|
67605
|
+
return;
|
|
67606
|
+
const buf = commandOutputBuf;
|
|
67607
|
+
commandOutputBuf = "";
|
|
67608
|
+
sink.updateMessages((messages) => mergeCommandOutput(messages, buf));
|
|
67609
|
+
};
|
|
67610
|
+
const stopCommandOutputFlush = () => {
|
|
67611
|
+
if (flushTimer) {
|
|
67612
|
+
clearInterval(flushTimer);
|
|
67613
|
+
flushTimer = null;
|
|
67614
|
+
}
|
|
67615
|
+
};
|
|
67616
|
+
return {
|
|
67617
|
+
onTextDelta(e) {
|
|
67618
|
+
sink.setThinking(false);
|
|
67619
|
+
partialText += e.text;
|
|
67620
|
+
const accumulated = partialText;
|
|
67621
|
+
sink.updateMessages((messages) => appendStreamedText(messages, accumulated));
|
|
67622
|
+
},
|
|
67623
|
+
onToolCallStart(e) {
|
|
67624
|
+
sink.setThinking(false);
|
|
67625
|
+
partialText = "";
|
|
67626
|
+
toolArgsDeltas.set(e.toolCallId, { accumulated: "" });
|
|
67627
|
+
sink.updateMessages((messages) => startStreamingToolCall(messages, e.toolCallId, e.toolName));
|
|
67628
|
+
},
|
|
67629
|
+
onToolCallDelta(e) {
|
|
67630
|
+
const entry = toolArgsDeltas.get(e.toolCallId);
|
|
67631
|
+
const accumulated = (entry?.accumulated ?? "") + e.argsTextDelta;
|
|
67632
|
+
toolArgsDeltas.set(e.toolCallId, { accumulated });
|
|
67633
|
+
const parsed = tryParsePartialJson(accumulated);
|
|
67634
|
+
if (!parsed)
|
|
67635
|
+
return;
|
|
67636
|
+
sink.updateMessages((messages) => applyToolCallDelta(messages, e.toolCallId, parsed));
|
|
67637
|
+
},
|
|
67638
|
+
onToolCallComplete(e) {
|
|
67639
|
+
sink.setThinking(false);
|
|
67640
|
+
partialText = "";
|
|
67641
|
+
toolArgsDeltas.delete(e.toolCallId);
|
|
67642
|
+
const args = e.args && typeof e.args === "object" && !Array.isArray(e.args) && e.args !== null ? e.args : undefined;
|
|
67643
|
+
sink.updateMessages((messages) => applyToolCall(messages, e.toolCallId, e.toolName, args));
|
|
67644
|
+
},
|
|
67645
|
+
onToolResult(e) {
|
|
67646
|
+
flushCommandOutput();
|
|
67647
|
+
stopCommandOutputFlush();
|
|
67648
|
+
sink.setThinking(true);
|
|
67649
|
+
partialText = "";
|
|
67650
|
+
sink.updateMessages((messages) => applyToolResult(messages, e.toolCallId, e.result));
|
|
67651
|
+
},
|
|
67652
|
+
onCommandOutput(e) {
|
|
67653
|
+
commandOutputBuf += e.data;
|
|
67654
|
+
if (!flushTimer) {
|
|
67655
|
+
flushTimer = setInterval(flushCommandOutput, COMMAND_OUTPUT_FLUSH_MS);
|
|
67656
|
+
}
|
|
67657
|
+
},
|
|
67658
|
+
onError(e) {
|
|
67659
|
+
console.error("Agent error:", e.error);
|
|
67660
|
+
const errorMessage = e.error instanceof Error ? e.error.message : "Unknown error";
|
|
67661
|
+
sink.setError(errorMessage);
|
|
67662
|
+
sink.updateMessages((messages) => markInFlightToolsErrored(messages, errorMessage));
|
|
67663
|
+
},
|
|
67664
|
+
getPartialText() {
|
|
67665
|
+
return partialText;
|
|
67666
|
+
},
|
|
67667
|
+
resetPartialText() {
|
|
67668
|
+
partialText = "";
|
|
67669
|
+
},
|
|
67670
|
+
flushCommandOutput,
|
|
67671
|
+
stopCommandOutputFlush,
|
|
67672
|
+
dispose: stopCommandOutputFlush
|
|
67673
|
+
};
|
|
67674
|
+
}
|
|
67675
|
+
function toRecordArgs(args) {
|
|
67676
|
+
return args && typeof args === "object" && !Array.isArray(args) && args !== null ? args : undefined;
|
|
67677
|
+
}
|
|
67678
|
+
function createRunEventProjections(deps) {
|
|
67679
|
+
const { display, subagents, updateWorkflowData } = deps;
|
|
67680
|
+
return {
|
|
67681
|
+
handlers: {
|
|
67682
|
+
onTextDelta: (d2) => {
|
|
67683
|
+
if (d2.subagentId) {
|
|
67684
|
+
subagents.appendText(d2.subagentId, d2.text);
|
|
67685
|
+
return;
|
|
67686
|
+
}
|
|
67687
|
+
display.onTextDelta(d2);
|
|
67688
|
+
},
|
|
67689
|
+
onToolCallStart: (d2) => {
|
|
67690
|
+
if (d2.subagentId) {
|
|
67691
|
+
subagents.addStreamingToolCall(d2.subagentId, d2.toolCallId, d2.toolName);
|
|
67692
|
+
return;
|
|
67693
|
+
}
|
|
67694
|
+
display.onToolCallStart(d2);
|
|
67695
|
+
},
|
|
67696
|
+
onToolCallDelta: (d2) => {
|
|
67697
|
+
if (d2.subagentId) {
|
|
67698
|
+
subagents.appendToolCallDelta(d2.subagentId, d2.toolCallId, d2.argsTextDelta);
|
|
67699
|
+
return;
|
|
67700
|
+
}
|
|
67701
|
+
display.onToolCallDelta(d2);
|
|
67702
|
+
},
|
|
67703
|
+
onToolCallComplete: (d2) => {
|
|
67704
|
+
if (d2.subagentId) {
|
|
67705
|
+
subagents.addToolCall(d2.subagentId, d2.toolCallId, d2.toolName, toRecordArgs(d2.args) ?? {});
|
|
67706
|
+
return;
|
|
67707
|
+
}
|
|
67708
|
+
display.onToolCallComplete(d2);
|
|
67709
|
+
deps.onRootToolCallStarted?.();
|
|
67710
|
+
if (d2.toolName === ASK_USER_QUESTIONS_TOOL_NAME) {
|
|
67711
|
+
const rawQuestions = toRecordArgs(d2.args)?.questions;
|
|
67712
|
+
if (Array.isArray(rawQuestions) && rawQuestions.length > 0) {
|
|
67713
|
+
deps.questions.onAsked(d2.toolCallId, rawQuestions);
|
|
67714
|
+
}
|
|
67715
|
+
}
|
|
67716
|
+
},
|
|
67717
|
+
onToolResult: (d2) => {
|
|
67718
|
+
if (d2.subagentId) {
|
|
67719
|
+
subagents.updateToolResult(d2.subagentId, d2.toolCallId, d2.result);
|
|
67720
|
+
return;
|
|
67721
|
+
}
|
|
67722
|
+
display.onToolResult(d2);
|
|
67723
|
+
if (d2.toolName === "submit_plan" && d2.result?.success === true) {
|
|
67724
|
+
deps.onPlanSubmitted?.();
|
|
67725
|
+
}
|
|
67726
|
+
},
|
|
67727
|
+
onCommandOutput: (d2) => {
|
|
67728
|
+
if (d2.subagentId)
|
|
67729
|
+
return;
|
|
67730
|
+
display.onCommandOutput(d2);
|
|
67731
|
+
},
|
|
67732
|
+
onError: (d2) => {
|
|
67733
|
+
if (d2.subagentId) {
|
|
67734
|
+
const errMsg = d2.error instanceof Error ? d2.error.message : "Unknown error";
|
|
67735
|
+
subagents.appendText(d2.subagentId, `
|
|
67736
|
+
Error: ${errMsg}
|
|
67737
|
+
`);
|
|
67738
|
+
return;
|
|
67739
|
+
}
|
|
67740
|
+
display.onError(d2);
|
|
67741
|
+
deps.questions.onCleared();
|
|
67742
|
+
},
|
|
67743
|
+
onSubagentSpawn: ({ subagentId, name }) => {
|
|
67744
|
+
if (subagentId.startsWith("app:"))
|
|
67745
|
+
return;
|
|
67746
|
+
subagents.spawnSession(subagentId, name);
|
|
67747
|
+
if (!isPentestAgent(subagentId))
|
|
67748
|
+
return;
|
|
67749
|
+
updateWorkflowData((wd) => applyWorkflowSubagentSpawn(wd, subagentId, name));
|
|
67750
|
+
},
|
|
67751
|
+
onSubagentComplete: ({ subagentId, status }) => {
|
|
67752
|
+
if (subagentId.startsWith("app:"))
|
|
67753
|
+
return;
|
|
67754
|
+
subagents.completeSession(subagentId, status);
|
|
67755
|
+
if (!isPentestAgent(subagentId))
|
|
67756
|
+
return;
|
|
67757
|
+
updateWorkflowData((wd) => applyWorkflowSubagentComplete(wd, subagentId, status));
|
|
67758
|
+
},
|
|
67759
|
+
onWorkflowPhaseStart: (d2) => {
|
|
67760
|
+
display.resetPartialText();
|
|
67761
|
+
if (d2.phase === "discovery") {
|
|
67762
|
+
deps.clearSubagentSessions();
|
|
67763
|
+
}
|
|
67764
|
+
updateWorkflowData((wd) => applyWorkflowPhaseStart(wd, d2.phase, d2.label));
|
|
67765
|
+
},
|
|
67766
|
+
onWorkflowPhaseComplete: (d2) => {
|
|
67767
|
+
display.resetPartialText();
|
|
67768
|
+
updateWorkflowData((wd) => applyWorkflowPhaseComplete(wd, d2.phase, d2.summary));
|
|
67769
|
+
}
|
|
67770
|
+
}
|
|
67771
|
+
};
|
|
67772
|
+
}
|
|
67773
|
+
|
|
67774
|
+
// src/core/integrations/wandb/upload.ts
|
|
67775
|
+
async function createWandbUploader(session, opts) {
|
|
67776
|
+
const resolved = resolveConfig(opts);
|
|
67777
|
+
if (!resolved.available)
|
|
67778
|
+
return null;
|
|
67779
|
+
const tracer = await createWeaveTracer(resolved.config);
|
|
67780
|
+
if (!tracer)
|
|
67781
|
+
return null;
|
|
67782
|
+
return {
|
|
67783
|
+
onRecord: (record) => tracer.logRecord(record, session.id),
|
|
67784
|
+
finalize: () => tracer.finish()
|
|
67785
|
+
};
|
|
67786
|
+
}
|
|
67787
|
+
async function attachWandbToEventBus(session, eventBus, opts) {
|
|
67788
|
+
const uploader = await createWandbUploader(session, opts);
|
|
67789
|
+
if (!uploader)
|
|
67790
|
+
return null;
|
|
67791
|
+
const handler = (e) => {
|
|
67792
|
+
uploader.onRecord(e.record);
|
|
67793
|
+
};
|
|
67794
|
+
eventBus.on("trace-record", handler);
|
|
67795
|
+
return async () => {
|
|
67796
|
+
eventBus.off("trace-record", handler);
|
|
67797
|
+
await uploader.finalize();
|
|
67798
|
+
};
|
|
67799
|
+
}
|
|
67800
|
+
|
|
67801
|
+
// src/tui/components/operator-dashboard/run-tracing.ts
|
|
67802
|
+
class RunTraceSession {
|
|
67803
|
+
eventBus;
|
|
67804
|
+
options;
|
|
67805
|
+
cleanup = null;
|
|
67806
|
+
earlyBuffer = [];
|
|
67807
|
+
countedSubagentSteps = new Set;
|
|
67808
|
+
earlyBufferHandler = (e) => {
|
|
67809
|
+
this.earlyBuffer?.push(e);
|
|
67810
|
+
};
|
|
67811
|
+
constructor(eventBus, options) {
|
|
67812
|
+
this.eventBus = eventBus;
|
|
67813
|
+
this.options = options;
|
|
67814
|
+
eventBus.on("trace-record", this.earlyBufferHandler);
|
|
67815
|
+
eventBus.on("trace-record", this.countSubagentStep);
|
|
67816
|
+
}
|
|
67817
|
+
async tryAttach(session) {
|
|
67818
|
+
if (this.cleanup)
|
|
67819
|
+
return;
|
|
67820
|
+
const attach = this.options.attach ?? attachWandbToEventBus;
|
|
67821
|
+
const cleanup = await attach(session, this.eventBus).catch((e) => {
|
|
67822
|
+
console.error("[wandb] Attach failed:", e);
|
|
67823
|
+
return null;
|
|
67824
|
+
});
|
|
67825
|
+
const buffered = this.earlyBuffer;
|
|
67826
|
+
this.stopBuffering();
|
|
67827
|
+
if (cleanup) {
|
|
67828
|
+
this.cleanup = cleanup;
|
|
67829
|
+
if (buffered) {
|
|
67830
|
+
for (const e of buffered)
|
|
67831
|
+
this.eventBus.emit("trace-record", e);
|
|
67832
|
+
}
|
|
67833
|
+
}
|
|
67834
|
+
}
|
|
67835
|
+
async cleanupRun() {
|
|
67836
|
+
this.stopBuffering();
|
|
67837
|
+
this.eventBus.off("trace-record", this.countSubagentStep);
|
|
67838
|
+
if (this.cleanup) {
|
|
67839
|
+
const fn = this.cleanup;
|
|
67840
|
+
this.cleanup = null;
|
|
67841
|
+
await fn().catch((e) => console.error("[wandb] Flush failed:", e));
|
|
67842
|
+
}
|
|
67843
|
+
}
|
|
67844
|
+
stopBuffering() {
|
|
67845
|
+
this.earlyBuffer = null;
|
|
67846
|
+
this.eventBus.off("trace-record", this.earlyBufferHandler);
|
|
67847
|
+
}
|
|
67848
|
+
countSubagentStep = (e) => {
|
|
67849
|
+
if (!this.options.isCurrent())
|
|
67850
|
+
return;
|
|
67851
|
+
const { record, subagentId } = e;
|
|
67852
|
+
if (!subagentId || record.type !== "step")
|
|
67853
|
+
return;
|
|
67854
|
+
const key = `${subagentId}:${record.stepIndex}:${record.timestamp}`;
|
|
67855
|
+
if (this.countedSubagentSteps.has(key))
|
|
67856
|
+
return;
|
|
67857
|
+
this.countedSubagentSteps.add(key);
|
|
67858
|
+
this.options.recordTokenUsage(record.usage.inputTokens, record.usage.outputTokens, record.usage.cacheReadTokens ?? 0, record.usage.cacheWriteTokens ?? 0);
|
|
67859
|
+
};
|
|
67860
|
+
}
|
|
67861
|
+
|
|
66844
67862
|
// src/tui/components/operator-dashboard/subagent-dialog.tsx
|
|
66845
67863
|
import { useKeyboard as useKeyboard25 } from "@opentui/react";
|
|
66846
67864
|
import {
|
|
@@ -66848,7 +67866,7 @@ import {
|
|
|
66848
67866
|
useMemo as useMemo21,
|
|
66849
67867
|
useRef as useRef20,
|
|
66850
67868
|
useState as useState38,
|
|
66851
|
-
useSyncExternalStore
|
|
67869
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
66852
67870
|
} from "react";
|
|
66853
67871
|
|
|
66854
67872
|
// src/tui/components/operator-dashboard/subagent-detail-view.tsx
|
|
@@ -66930,6 +67948,22 @@ function createSubagentStore() {
|
|
|
66930
67948
|
setState
|
|
66931
67949
|
};
|
|
66932
67950
|
}
|
|
67951
|
+
function markSubagentsInterrupted(prev) {
|
|
67952
|
+
let changed = false;
|
|
67953
|
+
const next = new Map(prev);
|
|
67954
|
+
for (const [id, session] of next) {
|
|
67955
|
+
const hasInFlight = session.messages.some((m2) => m2.role === "tool" && (m2.status === "pending" || m2.status === "streaming"));
|
|
67956
|
+
if (!hasInFlight && session.status !== "running")
|
|
67957
|
+
continue;
|
|
67958
|
+
changed = true;
|
|
67959
|
+
next.set(id, {
|
|
67960
|
+
...session,
|
|
67961
|
+
status: session.status === "running" ? "cancelled" : session.status,
|
|
67962
|
+
messages: session.messages.map((m2) => m2.role === "tool" && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result: "Interrupted" } : m2)
|
|
67963
|
+
});
|
|
67964
|
+
}
|
|
67965
|
+
return changed ? next : prev;
|
|
67966
|
+
}
|
|
66933
67967
|
function createSubagentSessionHelpers(setState) {
|
|
66934
67968
|
const toolArgsDeltaBuffers = new Map;
|
|
66935
67969
|
const spawnSession = (id, name, input) => {
|
|
@@ -67340,7 +68374,7 @@ function SubagentDialog({ store }) {
|
|
|
67340
68374
|
const [view, setView] = useState38({ type: "hub" });
|
|
67341
68375
|
const viewRef = useRef20(view);
|
|
67342
68376
|
viewRef.current = view;
|
|
67343
|
-
const sessions2 =
|
|
68377
|
+
const sessions2 = useSyncExternalStore2(store.subscribe, store.getSnapshot);
|
|
67344
68378
|
useEffect24(() => {
|
|
67345
68379
|
setSize(view.type === "detail" ? "xlarge" : "large");
|
|
67346
68380
|
}, [view.type, setSize]);
|
|
@@ -67498,10 +68532,7 @@ var SubagentStatusBar = memo6(function SubagentStatusBar2({
|
|
|
67498
68532
|
});
|
|
67499
68533
|
|
|
67500
68534
|
// 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
|
-
}
|
|
68535
|
+
import { jsxDEV as jsxDEV56, Fragment as Fragment7 } from "@opentui/react/jsx-dev-runtime";
|
|
67505
68536
|
function OperatorDashboard({
|
|
67506
68537
|
sessionId,
|
|
67507
68538
|
initialMessage,
|
|
@@ -67516,10 +68547,8 @@ function OperatorDashboard({
|
|
|
67516
68547
|
isModelUserSelected,
|
|
67517
68548
|
setThinking,
|
|
67518
68549
|
setIsExecuting,
|
|
67519
|
-
|
|
67520
|
-
|
|
67521
|
-
addCacheUsage,
|
|
67522
|
-
resetTokenUsage,
|
|
68550
|
+
usageStore,
|
|
68551
|
+
markExecuted,
|
|
67523
68552
|
setSessionCwd,
|
|
67524
68553
|
reasoningEnabled,
|
|
67525
68554
|
openAIReasoningEffort
|
|
@@ -67579,7 +68608,7 @@ function OperatorDashboard({
|
|
|
67579
68608
|
});
|
|
67580
68609
|
const commandCancelledRef = useRef21(false);
|
|
67581
68610
|
const subagentStore = useMemo22(() => createSubagentStore(), []);
|
|
67582
|
-
const subagentSessions =
|
|
68611
|
+
const subagentSessions = useSyncExternalStore3(subagentStore.subscribe, subagentStore.getSnapshot);
|
|
67583
68612
|
const subagentHelpers = useMemo22(() => createSubagentSessionHelpers(subagentStore.setState), [subagentStore]);
|
|
67584
68613
|
const messageCountAtSubagentDoneRef = useRef21(null);
|
|
67585
68614
|
const hasRunningSubagent = useMemo22(() => Array.from(subagentSessions.values()).some((s) => s.status === "running"), [subagentSessions]);
|
|
@@ -67592,7 +68621,7 @@ function OperatorDashboard({
|
|
|
67592
68621
|
messageCountAtSubagentDoneRef.current = null;
|
|
67593
68622
|
}
|
|
67594
68623
|
}, [subagentSessions, hasRunningSubagent]);
|
|
67595
|
-
const openSubagentDialog =
|
|
68624
|
+
const openSubagentDialog = useCallback22(() => {
|
|
67596
68625
|
replaceDialog(/* @__PURE__ */ jsxDEV56(SubagentDialog, {
|
|
67597
68626
|
store: subagentStore
|
|
67598
68627
|
}, undefined, false, undefined, this), {
|
|
@@ -67603,7 +68632,6 @@ function OperatorDashboard({
|
|
|
67603
68632
|
const [messages, setMessages] = useState39([]);
|
|
67604
68633
|
const displayMessagesRef = useRef21([]);
|
|
67605
68634
|
displayMessagesRef.current = messages;
|
|
67606
|
-
const textRef = useRef21("");
|
|
67607
68635
|
const conversationRef = useRef21([]);
|
|
67608
68636
|
const [inputValue, setInputValue] = useState39("");
|
|
67609
68637
|
const [queuedMessages, setQueuedMessages] = useState39([]);
|
|
@@ -67644,10 +68672,6 @@ function OperatorDashboard({
|
|
|
67644
68672
|
useEffect25(() => {
|
|
67645
68673
|
approvedPlanRef.current = approvedPlanContent;
|
|
67646
68674
|
}, [approvedPlanContent]);
|
|
67647
|
-
const tokenUsageRef = useRef21(tokenUsage);
|
|
67648
|
-
useEffect25(() => {
|
|
67649
|
-
tokenUsageRef.current = tokenUsage;
|
|
67650
|
-
}, [tokenUsage]);
|
|
67651
68675
|
useEffect25(() => {
|
|
67652
68676
|
const gate = approvalGateRef.current;
|
|
67653
68677
|
const onApprovalNeeded = () => {
|
|
@@ -67766,188 +68790,63 @@ function OperatorDashboard({
|
|
|
67766
68790
|
refocusPrompt();
|
|
67767
68791
|
}
|
|
67768
68792
|
}, [loading, refocusPrompt]);
|
|
68793
|
+
useEffect25(() => {
|
|
68794
|
+
if (sessionId === undefined)
|
|
68795
|
+
usageStore.beginNewSession();
|
|
68796
|
+
}, [sessionId, usageStore]);
|
|
67769
68797
|
useEffect25(() => {
|
|
67770
68798
|
if (!session || !sessionId)
|
|
67771
68799
|
return;
|
|
67772
|
-
resetTokenUsage();
|
|
67773
|
-
tokenUsageRef.current = {
|
|
67774
|
-
inputTokens: 0,
|
|
67775
|
-
outputTokens: 0,
|
|
67776
|
-
totalTokens: 0,
|
|
67777
|
-
cachedTokens: 0,
|
|
67778
|
-
cacheWriteTokens: 0
|
|
67779
|
-
};
|
|
67780
68800
|
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
|
-
];
|
|
68801
|
+
usageStore.enterSession(session.id, {
|
|
68802
|
+
...metrics?.tokenUsage ? { tokenUsage: metrics.tokenUsage } : {},
|
|
68803
|
+
...metrics?.contextUsage ? { contextUsage: metrics.contextUsage } : {}
|
|
67882
68804
|
});
|
|
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]);
|
|
68805
|
+
}, [session, sessionId, usageStore]);
|
|
68806
|
+
const runSessionIdRef = useRef21(null);
|
|
68807
|
+
const displayEvents = useMemo22(() => createDisplayEventHandlers({
|
|
68808
|
+
updateMessages: setMessages,
|
|
68809
|
+
setThinking,
|
|
68810
|
+
setError
|
|
68811
|
+
}), [setThinking]);
|
|
67936
68812
|
useEffect25(() => {
|
|
67937
68813
|
return () => {
|
|
67938
|
-
|
|
67939
|
-
clearInterval(cmdFlushTimerRef.current);
|
|
67940
|
-
cmdFlushTimerRef.current = null;
|
|
67941
|
-
}
|
|
68814
|
+
displayEvents.dispose();
|
|
67942
68815
|
};
|
|
68816
|
+
}, [displayEvents]);
|
|
68817
|
+
const updateWorkflowData = useCallback22((updater) => {
|
|
68818
|
+
setMessages((prev) => updateWorkflowDataMessage(prev, updater));
|
|
67943
68819
|
}, []);
|
|
67944
|
-
const
|
|
68820
|
+
const runEventProjections = useMemo22(() => createRunEventProjections({
|
|
68821
|
+
display: displayEvents,
|
|
68822
|
+
subagents: subagentHelpers,
|
|
68823
|
+
updateWorkflowData,
|
|
68824
|
+
clearSubagentSessions: () => subagentStore.setState(new Map),
|
|
68825
|
+
questions: {
|
|
68826
|
+
onAsked: (toolCallId, questions) => {
|
|
68827
|
+
pendingToolCallIdRef.current = toolCallId;
|
|
68828
|
+
setPendingQuestions(questions);
|
|
68829
|
+
},
|
|
68830
|
+
onCleared: () => {
|
|
68831
|
+
pendingToolCallIdRef.current = null;
|
|
68832
|
+
setPendingQuestions(null);
|
|
68833
|
+
}
|
|
68834
|
+
},
|
|
68835
|
+
onRootToolCallStarted: () => {
|
|
68836
|
+
commandCancelledRef.current = false;
|
|
68837
|
+
},
|
|
68838
|
+
onPlanSubmitted: () => {
|
|
68839
|
+
planSubmittedRef.current = true;
|
|
68840
|
+
planGateBypassedOnResumeRef.current = false;
|
|
68841
|
+
}
|
|
68842
|
+
}), [displayEvents, subagentHelpers, updateWorkflowData, subagentStore]);
|
|
68843
|
+
const handleApprove = useCallback22(() => {
|
|
67945
68844
|
const pending = approvalGateRef.current.getPendingApprovals();
|
|
67946
68845
|
if (pending.length > 0) {
|
|
67947
68846
|
approvalGateRef.current.approve(pending[0].id);
|
|
67948
68847
|
}
|
|
67949
68848
|
}, []);
|
|
67950
|
-
const handleAutoApprove =
|
|
68849
|
+
const handleAutoApprove = useCallback22(() => {
|
|
67951
68850
|
setOperatorMode("auto");
|
|
67952
68851
|
setOperatorState((prev) => ({
|
|
67953
68852
|
...prev,
|
|
@@ -67960,17 +68859,18 @@ function OperatorDashboard({
|
|
|
67960
68859
|
approvalGateRef.current.approve(p.id);
|
|
67961
68860
|
}
|
|
67962
68861
|
}, []);
|
|
67963
|
-
const runAgent =
|
|
68862
|
+
const runAgent = useCallback22(async (prompt) => {
|
|
67964
68863
|
if (abortControllerRef.current) {
|
|
67965
68864
|
abortControllerRef.current.abort();
|
|
67966
68865
|
abortControllerRef.current = null;
|
|
67967
68866
|
}
|
|
67968
68867
|
const gen = ++generationRef.current;
|
|
68868
|
+
runSessionIdRef.current = sessionRef.current?.id ?? session?.id ?? null;
|
|
67969
68869
|
setStatus("running");
|
|
67970
68870
|
setThinking(true);
|
|
67971
68871
|
setIsExecuting(true);
|
|
67972
68872
|
setError(null);
|
|
67973
|
-
|
|
68873
|
+
displayEvents.resetPartialText();
|
|
67974
68874
|
const controller = new AbortController;
|
|
67975
68875
|
abortControllerRef.current = controller;
|
|
67976
68876
|
const prevMessages = conversationRef.current;
|
|
@@ -67987,259 +68887,58 @@ function OperatorDashboard({
|
|
|
67987
68887
|
conversationRef.current = nextMessages;
|
|
67988
68888
|
if (sessionRef.current) {
|
|
67989
68889
|
try {
|
|
67990
|
-
const mp =
|
|
67991
|
-
|
|
68890
|
+
const mp = join4(sessionRef.current.rootPath, "messages.json");
|
|
68891
|
+
writeFileSync2(mp, JSON.stringify(nextMessages, null, 2));
|
|
67992
68892
|
} catch {}
|
|
67993
68893
|
}
|
|
67994
68894
|
} else {
|
|
67995
68895
|
nextMessages = conversationRef.current;
|
|
67996
68896
|
}
|
|
67997
68897
|
const recordTokenUsage = (inputTokens, outputTokens, cacheReadTokens = 0, cacheWriteTokens = 0) => {
|
|
67998
|
-
|
|
67999
|
-
|
|
68000
|
-
|
|
68001
|
-
|
|
68002
|
-
|
|
68003
|
-
|
|
68004
|
-
|
|
68005
|
-
|
|
68006
|
-
|
|
68007
|
-
|
|
68008
|
-
|
|
68009
|
-
|
|
68898
|
+
if (inputTokens > 0 || outputTokens > 0)
|
|
68899
|
+
markExecuted();
|
|
68900
|
+
const runSessionId = runSessionIdRef.current;
|
|
68901
|
+
usageStore.addSessionTokens(runSessionId, {
|
|
68902
|
+
inputTokens,
|
|
68903
|
+
outputTokens,
|
|
68904
|
+
cacheReadTokens,
|
|
68905
|
+
cacheWriteTokens
|
|
68906
|
+
});
|
|
68907
|
+
const activeSession = sessionRef.current;
|
|
68908
|
+
if (activeSession) {
|
|
68909
|
+
try {
|
|
68910
|
+
const usage = usageStore.getSnapshot(activeSession.id);
|
|
68911
|
+
writeExecutionMetrics({
|
|
68912
|
+
sessionRootPath: activeSession.rootPath,
|
|
68913
|
+
tokenUsage: usage.tokenUsage,
|
|
68914
|
+
...usage.contextUsage ? { contextUsage: usage.contextUsage } : {}
|
|
68915
|
+
});
|
|
68916
|
+
} catch {}
|
|
68010
68917
|
}
|
|
68011
|
-
|
|
68012
|
-
|
|
68918
|
+
};
|
|
68919
|
+
const runModelId = model.id;
|
|
68920
|
+
const recordRootStepUsage = (usage) => {
|
|
68921
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
68922
|
+
if (inputTokens > 0) {
|
|
68923
|
+
usageStore.setRootContext(runSessionIdRef.current, {
|
|
68924
|
+
usedTokens: inputTokens,
|
|
68925
|
+
contextLimit: getContextWindow(runModelId),
|
|
68926
|
+
modelId: runModelId
|
|
68927
|
+
});
|
|
68013
68928
|
}
|
|
68929
|
+
recordTokenUsage(inputTokens, usage.outputTokens ?? 0);
|
|
68014
68930
|
};
|
|
68015
68931
|
const onStepFinish = (event) => {
|
|
68016
|
-
|
|
68932
|
+
recordRootStepUsage(event.usage ?? {});
|
|
68017
68933
|
};
|
|
68018
68934
|
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);
|
|
68050
|
-
});
|
|
68051
|
-
eventBus.on("tool-call-start", (d2) => {
|
|
68052
|
-
if (gen !== generationRef.current)
|
|
68053
|
-
return;
|
|
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);
|
|
68935
|
+
const runTrace = new RunTraceSession(eventBus, {
|
|
68936
|
+
isCurrent: () => gen === generationRef.current,
|
|
68937
|
+
recordTokenUsage
|
|
68069
68938
|
});
|
|
68070
|
-
eventBus
|
|
68071
|
-
|
|
68072
|
-
|
|
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
|
-
});
|
|
68939
|
+
const unbindRunEvents = bindOperatorRunEvents(eventBus, {
|
|
68940
|
+
isCurrent: () => gen === generationRef.current,
|
|
68941
|
+
handlers: runEventProjections.handlers
|
|
68243
68942
|
});
|
|
68244
68943
|
const skillsCatalog = skillsRegistry.buildCatalog() || undefined;
|
|
68245
68944
|
const commonInput = {
|
|
@@ -68267,59 +68966,24 @@ Error: ${errMsg}
|
|
|
68267
68966
|
promptInjectionLibrarySource: initialConfig?.promptInjectionLibrarySource ?? (route.data.type === "operator" ? route.data.initialSkill?.args?.library : undefined),
|
|
68268
68967
|
onStepFinish,
|
|
68269
68968
|
onCacheMetrics: (metrics) => {
|
|
68270
|
-
|
|
68969
|
+
usageStore.addSessionTokens(runSessionIdRef.current, {
|
|
68970
|
+
cacheReadTokens: metrics.cacheReadInputTokens,
|
|
68971
|
+
cacheWriteTokens: metrics.cacheCreationInputTokens
|
|
68972
|
+
});
|
|
68271
68973
|
},
|
|
68272
68974
|
eventBus,
|
|
68273
68975
|
onSessionReady: (s) => {
|
|
68274
68976
|
setSessionCwd(s.rootPath);
|
|
68275
68977
|
sessionRef.current = s;
|
|
68276
68978
|
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);
|
|
68979
|
+
runSessionIdRef.current = s.id;
|
|
68980
|
+
usageStore.enterSession(s.id);
|
|
68981
|
+
runTrace.tryAttach(s);
|
|
68318
68982
|
}
|
|
68319
68983
|
};
|
|
68320
68984
|
const wandbSession = session ?? sessionRef.current;
|
|
68321
68985
|
if (wandbSession) {
|
|
68322
|
-
await
|
|
68986
|
+
await runTrace.tryAttach(wandbSession);
|
|
68323
68987
|
}
|
|
68324
68988
|
try {
|
|
68325
68989
|
let agentResult;
|
|
@@ -68374,9 +69038,9 @@ Error: ${errMsg}
|
|
|
68374
69038
|
if (gen === generationRef.current) {
|
|
68375
69039
|
try {
|
|
68376
69040
|
const rootPath = agentResult.session.rootPath;
|
|
68377
|
-
const mp =
|
|
68378
|
-
if (
|
|
68379
|
-
const raw = JSON.parse(
|
|
69041
|
+
const mp = join4(rootPath, "messages.json");
|
|
69042
|
+
if (existsSync4(mp)) {
|
|
69043
|
+
const raw = JSON.parse(readFileSync4(mp, "utf-8"));
|
|
68380
69044
|
if (Array.isArray(raw) && raw.length > 0) {
|
|
68381
69045
|
conversationRef.current = normalizeMessages(sessions.getResumeMessages(raw));
|
|
68382
69046
|
}
|
|
@@ -68402,8 +69066,8 @@ Error: ${errMsg}
|
|
|
68402
69066
|
setPendingQuestions(null);
|
|
68403
69067
|
if (sessionRef.current) {
|
|
68404
69068
|
try {
|
|
68405
|
-
const mp =
|
|
68406
|
-
|
|
69069
|
+
const mp = join4(sessionRef.current.rootPath, "messages.json");
|
|
69070
|
+
writeFileSync2(mp, JSON.stringify(prevMessages, null, 2));
|
|
68407
69071
|
} catch {}
|
|
68408
69072
|
}
|
|
68409
69073
|
const errorMsg = e instanceof Error ? e.message : "Agent failed";
|
|
@@ -68418,12 +69082,8 @@ Error: ${errMsg}
|
|
|
68418
69082
|
]);
|
|
68419
69083
|
}
|
|
68420
69084
|
} finally {
|
|
68421
|
-
|
|
68422
|
-
|
|
68423
|
-
if (wandbCleanup) {
|
|
68424
|
-
const fn = wandbCleanup;
|
|
68425
|
-
await fn().catch((e) => console.error("[wandb] Flush failed:", e));
|
|
68426
|
-
}
|
|
69085
|
+
unbindRunEvents();
|
|
69086
|
+
await runTrace.cleanupRun();
|
|
68427
69087
|
if (gen === generationRef.current) {
|
|
68428
69088
|
setStatus(pendingToolCallIdRef.current ? "waiting" : "idle");
|
|
68429
69089
|
setThinking(false);
|
|
@@ -68442,18 +69102,10 @@ Error: ${errMsg}
|
|
|
68442
69102
|
operatorState,
|
|
68443
69103
|
operatorMode,
|
|
68444
69104
|
agentMode,
|
|
68445
|
-
|
|
68446
|
-
|
|
68447
|
-
addStreamingToolCall,
|
|
68448
|
-
appendToolCallDelta,
|
|
68449
|
-
addToolCall,
|
|
68450
|
-
updateToolResult,
|
|
68451
|
-
flushCommandOutput,
|
|
68452
|
-
onCommandOutput,
|
|
68453
|
-
subagentHelpers,
|
|
69105
|
+
displayEvents,
|
|
69106
|
+
runEventProjections,
|
|
68454
69107
|
setThinking,
|
|
68455
69108
|
setIsExecuting,
|
|
68456
|
-
addCacheUsage,
|
|
68457
69109
|
initialConfig?.sandbox,
|
|
68458
69110
|
initialConfig?.taskDriven,
|
|
68459
69111
|
initialConfig?.target,
|
|
@@ -68462,14 +69114,15 @@ Error: ${errMsg}
|
|
|
68462
69114
|
strikeMode,
|
|
68463
69115
|
route.data,
|
|
68464
69116
|
setSessionCwd,
|
|
68465
|
-
subagentStore.setState,
|
|
68466
69117
|
skillsRegistry.buildCatalog,
|
|
68467
69118
|
requireApproval,
|
|
68468
69119
|
skillsRegistry,
|
|
68469
69120
|
reasoningEnabled,
|
|
68470
|
-
openAIReasoningEffort
|
|
69121
|
+
openAIReasoningEffort,
|
|
69122
|
+
usageStore,
|
|
69123
|
+
markExecuted
|
|
68471
69124
|
]);
|
|
68472
|
-
const handleSubmit =
|
|
69125
|
+
const handleSubmit = useCallback22((value) => {
|
|
68473
69126
|
const pending = approvalGateRef.current.getPendingApprovals();
|
|
68474
69127
|
const result = resolveSubmit(value, status, pending.length > 0);
|
|
68475
69128
|
if (result.denyPending) {
|
|
@@ -68607,16 +69260,16 @@ ${content}
|
|
|
68607
69260
|
planApprovedPendingRunRef.current = false;
|
|
68608
69261
|
runAgentRef.current("Proceed with the approved plan.");
|
|
68609
69262
|
}, [operatorMode]);
|
|
68610
|
-
const addSystemMessage =
|
|
69263
|
+
const addSystemMessage = useCallback22((content) => {
|
|
68611
69264
|
setMessages((prev) => [
|
|
68612
69265
|
...prev,
|
|
68613
69266
|
{ role: "system", content, createdAt: new Date }
|
|
68614
69267
|
]);
|
|
68615
69268
|
}, []);
|
|
68616
|
-
const showModelPicker =
|
|
69269
|
+
const showModelPicker = useCallback22(() => {
|
|
68617
69270
|
executeCommand("/models");
|
|
68618
69271
|
}, [executeCommand]);
|
|
68619
|
-
const handleHeadersSlash =
|
|
69272
|
+
const handleHeadersSlash = useCallback22(async (op) => {
|
|
68620
69273
|
const active = sessionRef.current;
|
|
68621
69274
|
if (!active) {
|
|
68622
69275
|
addSystemMessage("No active session — cannot manage headers yet.");
|
|
@@ -68687,7 +69340,7 @@ ${formatParseError(parsed.error)}`);
|
|
|
68687
69340
|
}
|
|
68688
69341
|
}
|
|
68689
69342
|
}, [addSystemMessage]);
|
|
68690
|
-
const handleCommandExecute =
|
|
69343
|
+
const handleCommandExecute = useCallback22(async (command) => {
|
|
68691
69344
|
const action = routeCommand(command, resolveSkillContent);
|
|
68692
69345
|
switch (action.type) {
|
|
68693
69346
|
case "show-models":
|
|
@@ -68761,7 +69414,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68761
69414
|
handleHeadersSlash,
|
|
68762
69415
|
strikeMode
|
|
68763
69416
|
]);
|
|
68764
|
-
const handleAbort =
|
|
69417
|
+
const handleAbort = useCallback22(() => {
|
|
68765
69418
|
if (!abortControllerRef.current)
|
|
68766
69419
|
return;
|
|
68767
69420
|
const action = resolveAbortAction(commandCancelledRef.current, () => cancelHandleRef.current.cancel());
|
|
@@ -68789,77 +69442,15 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68789
69442
|
setThinking(false);
|
|
68790
69443
|
setIsExecuting(false);
|
|
68791
69444
|
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
|
-
});
|
|
69445
|
+
subagentStore.setState(markSubagentsInterrupted);
|
|
68808
69446
|
const activeSession = sessionRef.current;
|
|
68809
69447
|
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 {}
|
|
69448
|
+
conversationRef.current = recoverAbortedTranscript({
|
|
69449
|
+
rootPath: activeSession.rootPath,
|
|
69450
|
+
conversation: conversationRef.current,
|
|
69451
|
+
partialText: displayEvents.getPartialText(),
|
|
69452
|
+
displayMessages: displayMessagesRef.current
|
|
69453
|
+
});
|
|
68863
69454
|
}
|
|
68864
69455
|
setMessages((prev) => {
|
|
68865
69456
|
const updated = prev.map((m2) => isToolMessage(m2) && (m2.status === "pending" || m2.status === "streaming") ? { ...m2, status: "error", result: "Cancelled by user" } : m2);
|
|
@@ -68872,51 +69463,30 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68872
69463
|
}
|
|
68873
69464
|
];
|
|
68874
69465
|
});
|
|
68875
|
-
}, [setThinking, setIsExecuting, subagentStore.setState]);
|
|
68876
|
-
const resumeWithQuestionResult =
|
|
69466
|
+
}, [setThinking, setIsExecuting, subagentStore.setState, displayEvents]);
|
|
69467
|
+
const resumeWithQuestionResult = useCallback22((result) => {
|
|
68877
69468
|
const toolCallId = pendingToolCallIdRef.current;
|
|
68878
69469
|
if (!toolCallId)
|
|
68879
69470
|
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
|
-
});
|
|
69471
|
+
const updated = rewriteToolResultOutput(conversationRef.current, toolCallId, result);
|
|
68902
69472
|
conversationRef.current = updated;
|
|
68903
69473
|
const activeSession = sessionRef.current;
|
|
68904
69474
|
if (activeSession) {
|
|
68905
69475
|
try {
|
|
68906
|
-
|
|
69476
|
+
writeFileSync2(join4(activeSession.rootPath, "messages.json"), JSON.stringify(updated, null, 2));
|
|
68907
69477
|
} catch {}
|
|
68908
69478
|
}
|
|
68909
69479
|
pendingToolCallIdRef.current = null;
|
|
68910
69480
|
setPendingQuestions(null);
|
|
68911
69481
|
runAgentRef.current(null);
|
|
68912
69482
|
}, []);
|
|
68913
|
-
const handleQuestionsSubmit =
|
|
69483
|
+
const handleQuestionsSubmit = useCallback22((answers) => {
|
|
68914
69484
|
resumeWithQuestionResult({ answers, skipped: false });
|
|
68915
69485
|
}, [resumeWithQuestionResult]);
|
|
68916
|
-
const handleQuestionsSkip =
|
|
69486
|
+
const handleQuestionsSkip = useCallback22(() => {
|
|
68917
69487
|
resumeWithQuestionResult({ answers: [], skipped: true });
|
|
68918
69488
|
}, [resumeWithQuestionResult]);
|
|
68919
|
-
const transitionToMode =
|
|
69489
|
+
const transitionToMode = useCallback22((next) => {
|
|
68920
69490
|
approvalGateRef.current.updateConfig({
|
|
68921
69491
|
requireApproval: next === "manual"
|
|
68922
69492
|
});
|
|
@@ -68931,7 +69501,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68931
69501
|
sessions.updateOperatorSettings(sid, { initialMode: next }).catch((e) => console.error("[operator] Failed to persist mode:", e));
|
|
68932
69502
|
}
|
|
68933
69503
|
}, []);
|
|
68934
|
-
const cycleMode =
|
|
69504
|
+
const cycleMode = useCallback22(() => {
|
|
68935
69505
|
const current = operatorModeRef.current;
|
|
68936
69506
|
const idx = OPERATOR_MODE_CYCLE.indexOf(current);
|
|
68937
69507
|
const next = OPERATOR_MODE_CYCLE[(idx + 1) % OPERATOR_MODE_CYCLE.length];
|
|
@@ -68972,11 +69542,8 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
68972
69542
|
const removeIdx = selectedQueueIndex;
|
|
68973
69543
|
setQueuedMessages((prev) => prev.filter((_2, i) => i !== removeIdx));
|
|
68974
69544
|
setSelectedQueueIndex(-1);
|
|
68975
|
-
flushCommandOutput();
|
|
68976
|
-
|
|
68977
|
-
clearInterval(cmdFlushTimerRef.current);
|
|
68978
|
-
cmdFlushTimerRef.current = null;
|
|
68979
|
-
}
|
|
69545
|
+
displayEvents.flushCommandOutput();
|
|
69546
|
+
displayEvents.stopCommandOutputFlush();
|
|
68980
69547
|
setMessages((prev) => prev.map((m2) => isToolMessage(m2) && m2.status === "pending" ? { ...m2, status: "error", result: "Interrupted" } : m2));
|
|
68981
69548
|
runAgentRef.current(msg);
|
|
68982
69549
|
return;
|
|
@@ -69021,34 +69588,15 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
69021
69588
|
key.preventDefault?.();
|
|
69022
69589
|
const toolCallId = pendingToolCallIdRef.current;
|
|
69023
69590
|
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;
|
|
69591
|
+
conversationRef.current = rewriteToolResultOutput(conversationRef.current, toolCallId, {
|
|
69592
|
+
answers: [],
|
|
69593
|
+
skipped: true,
|
|
69594
|
+
aborted: true
|
|
69047
69595
|
});
|
|
69048
69596
|
const activeSession = sessionRef.current;
|
|
69049
69597
|
if (activeSession) {
|
|
69050
69598
|
try {
|
|
69051
|
-
|
|
69599
|
+
writeFileSync2(join4(activeSession.rootPath, "messages.json"), JSON.stringify(conversationRef.current, null, 2));
|
|
69052
69600
|
} catch {}
|
|
69053
69601
|
}
|
|
69054
69602
|
}
|
|
@@ -69197,7 +69745,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
69197
69745
|
fg: colors2.warning,
|
|
69198
69746
|
children: "STRIKE"
|
|
69199
69747
|
}, undefined, false, undefined, this),
|
|
69200
|
-
(session?.targets[0] || initialConfig?.target) && /* @__PURE__ */ jsxDEV56(
|
|
69748
|
+
(session?.targets[0] || initialConfig?.target) && /* @__PURE__ */ jsxDEV56(Fragment7, {
|
|
69201
69749
|
children: [
|
|
69202
69750
|
/* @__PURE__ */ jsxDEV56("text", {
|
|
69203
69751
|
fg: colors2.textMuted,
|
|
@@ -69240,7 +69788,7 @@ ${planContent}` : "No plan exists yet. Switch to plan mode (Shift+Tab) to create
|
|
|
69240
69788
|
questions: pendingQuestions,
|
|
69241
69789
|
onSubmit: handleQuestionsSubmit,
|
|
69242
69790
|
onSkip: handleQuestionsSkip
|
|
69243
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV56(
|
|
69791
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV56(Fragment7, {
|
|
69244
69792
|
children: [
|
|
69245
69793
|
/* @__PURE__ */ jsxDEV56(QueuedMessages, {
|
|
69246
69794
|
messages: queuedMessages,
|
|
@@ -69368,19 +69916,19 @@ function ResponsibleUseDisclosure({
|
|
|
69368
69916
|
|
|
69369
69917
|
// src/tui/components/switch.tsx
|
|
69370
69918
|
import React2 from "react";
|
|
69371
|
-
import { jsxDEV as jsxDEV58, Fragment as
|
|
69919
|
+
import { jsxDEV as jsxDEV58, Fragment as Fragment8 } from "@opentui/react/jsx-dev-runtime";
|
|
69372
69920
|
var CaseSymbol = Symbol("Switch.Case");
|
|
69373
69921
|
var DefaultSymbol = Symbol("Switch.Default");
|
|
69374
69922
|
function CaseComponent({
|
|
69375
69923
|
children
|
|
69376
69924
|
}) {
|
|
69377
|
-
return /* @__PURE__ */ jsxDEV58(
|
|
69925
|
+
return /* @__PURE__ */ jsxDEV58(Fragment8, {
|
|
69378
69926
|
children
|
|
69379
69927
|
}, undefined, false, undefined, this);
|
|
69380
69928
|
}
|
|
69381
69929
|
CaseComponent[CaseSymbol] = true;
|
|
69382
69930
|
function DefaultComponent({ children }) {
|
|
69383
|
-
return /* @__PURE__ */ jsxDEV58(
|
|
69931
|
+
return /* @__PURE__ */ jsxDEV58(Fragment8, {
|
|
69384
69932
|
children
|
|
69385
69933
|
}, undefined, false, undefined, this);
|
|
69386
69934
|
}
|
|
@@ -69403,7 +69951,7 @@ function SwitchComponent({
|
|
|
69403
69951
|
}
|
|
69404
69952
|
}
|
|
69405
69953
|
});
|
|
69406
|
-
return /* @__PURE__ */ jsxDEV58(
|
|
69954
|
+
return /* @__PURE__ */ jsxDEV58(Fragment8, {
|
|
69407
69955
|
children: matchedChild || defaultChild
|
|
69408
69956
|
}, undefined, false, undefined, this);
|
|
69409
69957
|
}
|
|
@@ -69616,6 +70164,7 @@ function createKeybindings(deps) {
|
|
|
69616
70164
|
setExternalDialogOpen,
|
|
69617
70165
|
setFocusIndex,
|
|
69618
70166
|
navigableItems,
|
|
70167
|
+
onExit,
|
|
69619
70168
|
setShowToolsPanel
|
|
69620
70169
|
} = deps;
|
|
69621
70170
|
const route = useRoute();
|
|
@@ -69631,9 +70180,7 @@ function createKeybindings(deps) {
|
|
|
69631
70180
|
const now = Date.now();
|
|
69632
70181
|
const lastPress = ctrlCPressTime;
|
|
69633
70182
|
if (lastPress && now - lastPress < 1000) {
|
|
69634
|
-
|
|
69635
|
-
renderer.destroy();
|
|
69636
|
-
process.exit(0);
|
|
70183
|
+
await onExit();
|
|
69637
70184
|
} else {
|
|
69638
70185
|
setInputKey((prev) => prev + 1);
|
|
69639
70186
|
setCtrlCPressTime(now);
|
|
@@ -69829,7 +70376,7 @@ import { jsxDEV as jsxDEV61 } from "@opentui/react/jsx-dev-runtime";
|
|
|
69829
70376
|
installObfuscationTextPatch();
|
|
69830
70377
|
extend({ frameBuffer: FrameBufferRenderable });
|
|
69831
70378
|
extend({ frameBuffer: FrameBufferRenderable });
|
|
69832
|
-
function App({ appConfig }) {
|
|
70379
|
+
function App({ appConfig, onExit }) {
|
|
69833
70380
|
const [focusIndex, setFocusIndex] = useState40(0);
|
|
69834
70381
|
const [cwd, setCwd] = useState40(process.cwd());
|
|
69835
70382
|
const [ctrlCPressTime, setCtrlCPressTime] = useState40(null);
|
|
@@ -69860,6 +70407,7 @@ function App({ appConfig }) {
|
|
|
69860
70407
|
children: /* @__PURE__ */ jsxDEV61(DialogProvider, {
|
|
69861
70408
|
children: /* @__PURE__ */ jsxDEV61(AgentProvider, {
|
|
69862
70409
|
children: /* @__PURE__ */ jsxDEV61(CommandProvider, {
|
|
70410
|
+
onExit,
|
|
69863
70411
|
onOpenSessionsDialog: () => setShowSessionsDialog(true),
|
|
69864
70412
|
onOpenThemeDialog: () => setShowThemeDialog(true),
|
|
69865
70413
|
onOpenAdvancedDialog: () => setShowAdvancedDialog(true),
|
|
@@ -69885,7 +70433,8 @@ function App({ appConfig }) {
|
|
|
69885
70433
|
setShowSessionsDialog,
|
|
69886
70434
|
setShowShortcutsDialog,
|
|
69887
70435
|
setFocusIndex,
|
|
69888
|
-
navigableItems
|
|
70436
|
+
navigableItems,
|
|
70437
|
+
onExit
|
|
69889
70438
|
},
|
|
69890
70439
|
children: /* @__PURE__ */ jsxDEV61(AppContent, {
|
|
69891
70440
|
focusIndex,
|
|
@@ -69982,7 +70531,7 @@ function AppContent({
|
|
|
69982
70531
|
toast(`Update available: v${currentVersion} → v${latestVersion}. Run: pensar upgrade`, "warn", 8000);
|
|
69983
70532
|
});
|
|
69984
70533
|
const checkAuthToken = async () => {
|
|
69985
|
-
const { isTokenExpired, isConnected: isConnected2 } = await import("./index-
|
|
70534
|
+
const { isTokenExpired, isConnected: isConnected2 } = await import("./index-4v5jc2td.js");
|
|
69986
70535
|
if (isConnected2(config2.data) && config2.data.accessToken && isTokenExpired(config2.data.accessToken, 60) && !config2.data.refreshToken && !config2.data.pensarAPIKey) {
|
|
69987
70536
|
toast("Your Pensar Console session has expired. Run /login to refresh.", "warn", 8000);
|
|
69988
70537
|
}
|
|
@@ -70317,6 +70866,7 @@ async function main() {
|
|
|
70317
70866
|
const transparent = appConfig.transparentBackground ?? false;
|
|
70318
70867
|
const themeColors = resolveThemeColors(getTheme(themeName), mode, transparent);
|
|
70319
70868
|
overlayThemeRef.current = themeColors;
|
|
70869
|
+
const observabilityRuntime = startObservabilityRuntime();
|
|
70320
70870
|
const renderer = await createCliRenderer({
|
|
70321
70871
|
exitOnCtrlC: false,
|
|
70322
70872
|
consoleOptions: buildConsoleOptions(themeColors),
|
|
@@ -70324,27 +70874,19 @@ async function main() {
|
|
|
70324
70874
|
});
|
|
70325
70875
|
const { copyToClipboard } = createClipboardManager(renderer);
|
|
70326
70876
|
setupAutoCopy(renderer, copyToClipboard);
|
|
70327
|
-
const
|
|
70328
|
-
|
|
70329
|
-
|
|
70330
|
-
|
|
70331
|
-
|
|
70332
|
-
|
|
70333
|
-
|
|
70334
|
-
|
|
70335
|
-
|
|
70336
|
-
|
|
70337
|
-
|
|
70338
|
-
writeErrorLog(err, "UNCAUGHT");
|
|
70339
|
-
process.exit(1);
|
|
70340
|
-
});
|
|
70341
|
-
process.on("unhandledRejection", (reason) => {
|
|
70342
|
-
cleanupTerminalFocusMode();
|
|
70343
|
-
renderer.destroy();
|
|
70344
|
-
console.error("Unhandled rejection:", reason);
|
|
70345
|
-
writeErrorLog(reason, "UNHANDLED_REJECTION");
|
|
70346
|
-
process.exit(1);
|
|
70877
|
+
const exitWith = installObservabilityExitHandlers(observabilityRuntime, {
|
|
70878
|
+
cleanup: () => {
|
|
70879
|
+
cleanupTerminalFocusMode();
|
|
70880
|
+
renderer.destroy();
|
|
70881
|
+
},
|
|
70882
|
+
onError: (error, source) => {
|
|
70883
|
+
const uncaught = source === "uncaughtException";
|
|
70884
|
+
const label = uncaught ? "Uncaught exception:" : "Unhandled rejection:";
|
|
70885
|
+
console.error(label, error);
|
|
70886
|
+
writeErrorLog(error, uncaught ? "UNCAUGHT" : "UNHANDLED_REJECTION");
|
|
70887
|
+
}
|
|
70347
70888
|
});
|
|
70889
|
+
const cleanup = () => exitWith(0);
|
|
70348
70890
|
const obfuscateEnabled = process.env.PENSAR_OBFUSCATE === "1";
|
|
70349
70891
|
createRoot(renderer).render(/* @__PURE__ */ jsxDEV61(ObfuscationProvider, {
|
|
70350
70892
|
initialEnabled: obfuscateEnabled,
|
|
@@ -70359,7 +70901,8 @@ async function main() {
|
|
|
70359
70901
|
children: [
|
|
70360
70902
|
/* @__PURE__ */ jsxDEV61(ErrorBoundary, {
|
|
70361
70903
|
children: /* @__PURE__ */ jsxDEV61(App, {
|
|
70362
|
-
appConfig
|
|
70904
|
+
appConfig,
|
|
70905
|
+
onExit: cleanup
|
|
70363
70906
|
}, undefined, false, undefined, this)
|
|
70364
70907
|
}, undefined, false, undefined, this),
|
|
70365
70908
|
/* @__PURE__ */ jsxDEV61(ToastContainer, {}, undefined, false, undefined, this)
|