@rzx/ohs 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frontend/index.js +181 -155
- package/dist/frontend/index.js.map +4 -4
- package/dist/index.js +37647 -58827
- package/dist/index.js.map +48 -217
- package/package.json +10 -10
package/dist/frontend/index.js
CHANGED
|
@@ -14,8 +14,17 @@ var __export = (target, all) => {
|
|
|
14
14
|
set: __exportSetter.bind(all, name)
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
|
-
var __esm = (fn, res) => () =>
|
|
18
|
-
|
|
17
|
+
var __esm = (fn, res, err) => () => {
|
|
18
|
+
if (fn)
|
|
19
|
+
try {
|
|
20
|
+
res = fn(fn = 0);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
err = [e];
|
|
23
|
+
}
|
|
24
|
+
if (err)
|
|
25
|
+
throw err[0];
|
|
26
|
+
return res;
|
|
27
|
+
};
|
|
19
28
|
|
|
20
29
|
// ../frontend/src/theme/builtinThemes.ts
|
|
21
30
|
function getTheme(name) {
|
|
@@ -692,8 +701,8 @@ function parseServerCapabilities(value) {
|
|
|
692
701
|
if (!isRecord2(value.features))
|
|
693
702
|
throw new Error("features must be an object");
|
|
694
703
|
const features = {};
|
|
695
|
-
for (const [name,
|
|
696
|
-
features[name] = positiveInteger2(
|
|
704
|
+
for (const [name, version] of Object.entries(value.features)) {
|
|
705
|
+
features[name] = positiveInteger2(version, `features.${name}`);
|
|
697
706
|
}
|
|
698
707
|
const attachments = parseAttachmentTransferCapabilities(value.attachments);
|
|
699
708
|
return {
|
|
@@ -815,12 +824,12 @@ class OpenHarnessClient {
|
|
|
815
824
|
auth: false,
|
|
816
825
|
signal: options.signal
|
|
817
826
|
});
|
|
818
|
-
const
|
|
819
|
-
const compatibility = checkProtocolCompatibility(
|
|
827
|
+
const capabilities = parseServerCapabilities(value);
|
|
828
|
+
const compatibility = checkProtocolCompatibility(capabilities, options.support ?? { version: 2 });
|
|
820
829
|
if (!compatibility.compatible) {
|
|
821
|
-
throw new IncompatibleProtocolError(
|
|
830
|
+
throw new IncompatibleProtocolError(capabilities, compatibility.reason ?? "Client and server protocol versions are incompatible");
|
|
822
831
|
}
|
|
823
|
-
return
|
|
832
|
+
return capabilities;
|
|
824
833
|
}
|
|
825
834
|
async uploadAttachment(input) {
|
|
826
835
|
const headers = this.headers();
|
|
@@ -1000,6 +1009,15 @@ class OpenHarnessClient {
|
|
|
1000
1009
|
const response = await this.request(this.path("/context/status", query), { signal });
|
|
1001
1010
|
return response.report;
|
|
1002
1011
|
}
|
|
1012
|
+
async getContextUsage(options) {
|
|
1013
|
+
const { signal, refresh, previousContextWindow, ...rest } = options;
|
|
1014
|
+
const query = {
|
|
1015
|
+
...rest,
|
|
1016
|
+
...refresh !== undefined ? { refresh: refresh ? "true" : "false" } : {},
|
|
1017
|
+
...previousContextWindow !== undefined ? { previousContextWindow: String(previousContextWindow) } : {}
|
|
1018
|
+
};
|
|
1019
|
+
return await this.request(this.path("/context/usage", query), { signal });
|
|
1020
|
+
}
|
|
1003
1021
|
async compactSession(sessionId, options = {}) {
|
|
1004
1022
|
return await this.request(`/sessions/${encodeURIComponent(sessionId)}/compact`, { method: "POST", signal: options.signal });
|
|
1005
1023
|
}
|
|
@@ -1495,9 +1513,9 @@ async function* streamServerSentEvents(open, decode = (value) => value) {
|
|
|
1495
1513
|
const frames = buffer.split(/\r?\n\r?\n/);
|
|
1496
1514
|
buffer = frames.pop() ?? "";
|
|
1497
1515
|
for (const frame of frames) {
|
|
1498
|
-
const
|
|
1499
|
-
if (
|
|
1500
|
-
yield decode(
|
|
1516
|
+
const event = parseSseFrame(frame);
|
|
1517
|
+
if (event !== undefined)
|
|
1518
|
+
yield decode(event);
|
|
1501
1519
|
}
|
|
1502
1520
|
}
|
|
1503
1521
|
buffer += decoder.decode();
|
|
@@ -1535,9 +1553,9 @@ var init_http_client = __esm(() => {
|
|
|
1535
1553
|
};
|
|
1536
1554
|
IncompatibleProtocolError = class IncompatibleProtocolError extends Error {
|
|
1537
1555
|
capabilities;
|
|
1538
|
-
constructor(
|
|
1556
|
+
constructor(capabilities, message) {
|
|
1539
1557
|
super(message);
|
|
1540
|
-
this.capabilities =
|
|
1558
|
+
this.capabilities = capabilities;
|
|
1541
1559
|
this.name = "IncompatibleProtocolError";
|
|
1542
1560
|
}
|
|
1543
1561
|
};
|
|
@@ -1661,17 +1679,17 @@ function readPayloadRecord(event, key) {
|
|
|
1661
1679
|
const value = event.payload[key];
|
|
1662
1680
|
return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
1663
1681
|
}
|
|
1664
|
-
function upsertSession(state,
|
|
1665
|
-
if (!
|
|
1682
|
+
function upsertSession(state, session) {
|
|
1683
|
+
if (!session)
|
|
1666
1684
|
return state;
|
|
1667
|
-
const bucket = cloneBucket(state.buckets[
|
|
1668
|
-
bucket.session =
|
|
1669
|
-
const sessions = { ...state.sessions, [
|
|
1685
|
+
const bucket = cloneBucket(state.buckets[session.id]);
|
|
1686
|
+
bucket.session = session;
|
|
1687
|
+
const sessions = { ...state.sessions, [session.id]: session };
|
|
1670
1688
|
return {
|
|
1671
1689
|
...state,
|
|
1672
1690
|
sessions,
|
|
1673
1691
|
sessionOrder: sortSessionOrder(sessions),
|
|
1674
|
-
buckets: { ...state.buckets, [
|
|
1692
|
+
buckets: { ...state.buckets, [session.id]: bucket }
|
|
1675
1693
|
};
|
|
1676
1694
|
}
|
|
1677
1695
|
function archiveSession(state, event) {
|
|
@@ -1791,34 +1809,34 @@ function upsertRun(state, run) {
|
|
|
1791
1809
|
return state;
|
|
1792
1810
|
const bucket = cloneBucket(state.buckets[run.sessionId]);
|
|
1793
1811
|
bucket.runs = { ...bucket.runs, [run.id]: run };
|
|
1794
|
-
const
|
|
1795
|
-
bucket.session =
|
|
1796
|
-
const sessions =
|
|
1812
|
+
const session = refreshSessionStatusFromRuns(bucket.session, bucket.runs, run.updatedAt);
|
|
1813
|
+
bucket.session = session;
|
|
1814
|
+
const sessions = session ? { ...state.sessions, [run.sessionId]: session } : state.sessions;
|
|
1797
1815
|
return {
|
|
1798
1816
|
...state,
|
|
1799
1817
|
sessions,
|
|
1800
|
-
sessionOrder:
|
|
1818
|
+
sessionOrder: session ? sortSessionOrder(sessions) : state.sessionOrder,
|
|
1801
1819
|
buckets: { ...state.buckets, [run.sessionId]: bucket }
|
|
1802
1820
|
};
|
|
1803
1821
|
}
|
|
1804
1822
|
function upsertRunAttempt(state, attempt) {
|
|
1805
1823
|
if (!attempt)
|
|
1806
1824
|
return state;
|
|
1807
|
-
const run = Object.values(state.buckets).flatMap((
|
|
1825
|
+
const run = Object.values(state.buckets).flatMap((bucket) => Object.values(bucket.runs)).find((candidate) => candidate.id === attempt.runId);
|
|
1808
1826
|
if (!run)
|
|
1809
1827
|
return state;
|
|
1810
1828
|
const bucket = cloneBucket(state.buckets[run.sessionId]);
|
|
1811
1829
|
bucket.attempts = { ...bucket.attempts, [attempt.id]: attempt };
|
|
1812
1830
|
return { ...state, buckets: { ...state.buckets, [run.sessionId]: bucket } };
|
|
1813
1831
|
}
|
|
1814
|
-
function refreshSessionStatusFromRuns(
|
|
1815
|
-
if (!
|
|
1816
|
-
return
|
|
1832
|
+
function refreshSessionStatusFromRuns(session, runs, updatedAt) {
|
|
1833
|
+
if (!session || session.status === "archived" || session.status === "closing")
|
|
1834
|
+
return session;
|
|
1817
1835
|
const running = Object.values(runs).some((candidate) => candidate.status === "pending" || candidate.status === "running");
|
|
1818
1836
|
return {
|
|
1819
|
-
...
|
|
1837
|
+
...session,
|
|
1820
1838
|
status: running ? "running" : "idle",
|
|
1821
|
-
updatedAt: Math.max(
|
|
1839
|
+
updatedAt: Math.max(session.updatedAt, updatedAt)
|
|
1822
1840
|
};
|
|
1823
1841
|
}
|
|
1824
1842
|
function upsertPermission(state, request) {
|
|
@@ -1865,7 +1883,7 @@ function upsertSorted(rows, row, sortKey) {
|
|
|
1865
1883
|
return without.sort((a, b) => sortKey(a) - sortKey(b));
|
|
1866
1884
|
}
|
|
1867
1885
|
function sortSessionOrder(sessions) {
|
|
1868
|
-
return Object.values(sessions).sort((a, b) => b.updatedAt - a.updatedAt || a.id.localeCompare(b.id)).map((
|
|
1886
|
+
return Object.values(sessions).sort((a, b) => b.updatedAt - a.updatedAt || a.id.localeCompare(b.id)).map((session) => session.id);
|
|
1869
1887
|
}
|
|
1870
1888
|
var UnsupportedSessionEventSchemaVersionError;
|
|
1871
1889
|
var init_reducer = __esm(() => {
|
|
@@ -2124,7 +2142,7 @@ function shouldPresentSlashOutput(slash) {
|
|
|
2124
2142
|
}
|
|
2125
2143
|
function formatJobReadResult(result) {
|
|
2126
2144
|
const snapshot = result.snapshot;
|
|
2127
|
-
const
|
|
2145
|
+
const capabilities = [
|
|
2128
2146
|
`read=${snapshot.capabilities.read}`,
|
|
2129
2147
|
`wait=${snapshot.capabilities.wait}`,
|
|
2130
2148
|
`send=${snapshot.capabilities.send}`,
|
|
@@ -2141,7 +2159,7 @@ function formatJobReadResult(result) {
|
|
|
2141
2159
|
` Updated at: ${snapshot.updatedAt}`,
|
|
2142
2160
|
` Finished at: ${snapshot.finishedAt ?? "(n/a)"}`,
|
|
2143
2161
|
` Detail: ${snapshot.detail ?? "(none)"}`,
|
|
2144
|
-
` Capabilities: ${
|
|
2162
|
+
` Capabilities: ${capabilities}`,
|
|
2145
2163
|
` Metadata: ${snapshot.metadata ? JSON.stringify(snapshot.metadata) : "(none)"}`,
|
|
2146
2164
|
` Cursor: ${result.cursor}`,
|
|
2147
2165
|
` Truncated: ${result.truncated}`,
|
|
@@ -2321,7 +2339,7 @@ async function dispatchSessionCommand(slash, host) {
|
|
|
2321
2339
|
return [
|
|
2322
2340
|
`Jobs (${jobs.length}):`,
|
|
2323
2341
|
"",
|
|
2324
|
-
...jobs.map((
|
|
2342
|
+
...jobs.map((job) => ` ${job.id} [${job.status}] ${job.kind}: ${job.label}`)
|
|
2325
2343
|
].join(`
|
|
2326
2344
|
`);
|
|
2327
2345
|
});
|
|
@@ -2468,8 +2486,18 @@ No entries found.`;
|
|
|
2468
2486
|
await readPresentation(`context:${cwd}:status`, "Context", async () => await client.getContextStatus({ cwd }));
|
|
2469
2487
|
return "handled";
|
|
2470
2488
|
}
|
|
2489
|
+
if (action === "usage") {
|
|
2490
|
+
await readPresentation(`context:${cwd}:usage:${sessionId ?? "none"}`, "Context", async () => {
|
|
2491
|
+
const result = await client.getContextUsage({
|
|
2492
|
+
cwd,
|
|
2493
|
+
...sessionId ? { sessionId } : {}
|
|
2494
|
+
});
|
|
2495
|
+
return result.report;
|
|
2496
|
+
});
|
|
2497
|
+
return "handled";
|
|
2498
|
+
}
|
|
2471
2499
|
if (action !== "preview") {
|
|
2472
|
-
emit("Usage: /context [status]");
|
|
2500
|
+
emit("Usage: /context [preview|status|usage]");
|
|
2473
2501
|
return "handled";
|
|
2474
2502
|
}
|
|
2475
2503
|
await readPresentation(`context:${cwd}`, "Context", async () => await client.getContextPreview({ cwd }));
|
|
@@ -2517,7 +2545,7 @@ No entries found.`;
|
|
|
2517
2545
|
emit([
|
|
2518
2546
|
`Agent Jobs (${agents.length}):`,
|
|
2519
2547
|
"",
|
|
2520
|
-
...agents.map((
|
|
2548
|
+
...agents.map((job) => ` ${job.id} [${job.status}] ${job.label}`)
|
|
2521
2549
|
].join(`
|
|
2522
2550
|
`));
|
|
2523
2551
|
return "handled";
|
|
@@ -2903,7 +2931,7 @@ function beginJobList(previous) {
|
|
|
2903
2931
|
return { status: "loading", jobs: [...previous.jobs] };
|
|
2904
2932
|
}
|
|
2905
2933
|
function resolveJobList(jobs, now, previous) {
|
|
2906
|
-
const cachedById = new Map(previous?.jobs.map((
|
|
2934
|
+
const cachedById = new Map(previous?.jobs.map((job) => [job.id, job]) ?? []);
|
|
2907
2935
|
return {
|
|
2908
2936
|
status: "ready",
|
|
2909
2937
|
jobs: jobs.map((snapshot) => preferMonotonicSnapshot(cachedById.get(snapshot.id), snapshot)),
|
|
@@ -2920,8 +2948,8 @@ function rejectJobList(previous, error) {
|
|
|
2920
2948
|
};
|
|
2921
2949
|
}
|
|
2922
2950
|
function mergeJobSnapshot(state, snapshot, now) {
|
|
2923
|
-
const found = state.jobs.some((
|
|
2924
|
-
const jobs = found ? state.jobs.map((
|
|
2951
|
+
const found = state.jobs.some((job) => job.id === snapshot.id);
|
|
2952
|
+
const jobs = found ? state.jobs.map((job) => job.id === snapshot.id ? preferMonotonicSnapshot(job, snapshot) : job) : [snapshot, ...state.jobs];
|
|
2925
2953
|
return { status: "ready", jobs, refreshedAt: now };
|
|
2926
2954
|
}
|
|
2927
2955
|
function preferMonotonicSnapshot(cached, incoming) {
|
|
@@ -2943,8 +2971,8 @@ function isJobSnapshot(value, ownerSession) {
|
|
|
2943
2971
|
if (!isRecord3(value)) {
|
|
2944
2972
|
return false;
|
|
2945
2973
|
}
|
|
2946
|
-
const
|
|
2947
|
-
return typeof value.id === "string" && value.id.trim().length > 0 && value.ownerSession === ownerSession && typeof value.label === "string" && typeof value.cwd === "string" && typeof value.kind === "string" && JOB_KINDS.includes(value.kind) && typeof value.status === "string" && JOB_STATUSES.includes(value.status) && Number.isFinite(value.startedAt) && Number.isFinite(value.updatedAt) && (value.finishedAt === undefined || Number.isFinite(value.finishedAt)) && (value.detail === undefined || typeof value.detail === "string") && (value.metadata === undefined || isRecord3(value.metadata)) && isRecord3(
|
|
2974
|
+
const capabilities = value.capabilities;
|
|
2975
|
+
return typeof value.id === "string" && value.id.trim().length > 0 && value.ownerSession === ownerSession && typeof value.label === "string" && typeof value.cwd === "string" && typeof value.kind === "string" && JOB_KINDS.includes(value.kind) && typeof value.status === "string" && JOB_STATUSES.includes(value.status) && Number.isFinite(value.startedAt) && Number.isFinite(value.updatedAt) && (value.finishedAt === undefined || Number.isFinite(value.finishedAt)) && (value.detail === undefined || typeof value.detail === "string") && (value.metadata === undefined || isRecord3(value.metadata)) && isRecord3(capabilities) && typeof capabilities.read === "boolean" && typeof capabilities.wait === "boolean" && typeof capabilities.send === "boolean" && typeof capabilities.cancel === "boolean";
|
|
2948
2976
|
}
|
|
2949
2977
|
function validateJobSnapshot(value, ownerSession, expectedJobId) {
|
|
2950
2978
|
if (!isRecord3(value)) {
|
|
@@ -3234,7 +3262,7 @@ function archiveClientSession(state, sessionId, archivedAt) {
|
|
|
3234
3262
|
};
|
|
3235
3263
|
}
|
|
3236
3264
|
function listTopLevelSessions(sessions, activeSessionId) {
|
|
3237
|
-
return [...sessions].filter((
|
|
3265
|
+
return [...sessions].filter((session) => !session.parentId && session.status !== "archived").sort((a, b) => {
|
|
3238
3266
|
if (a.id === activeSessionId)
|
|
3239
3267
|
return -1;
|
|
3240
3268
|
if (b.id === activeSessionId)
|
|
@@ -3243,14 +3271,14 @@ function listTopLevelSessions(sessions, activeSessionId) {
|
|
|
3243
3271
|
});
|
|
3244
3272
|
}
|
|
3245
3273
|
function sessionSelectOptions(sessions, activeSessionId) {
|
|
3246
|
-
return listTopLevelSessions(sessions, activeSessionId).map((
|
|
3247
|
-
value:
|
|
3248
|
-
label: `${
|
|
3249
|
-
description: `${
|
|
3274
|
+
return listTopLevelSessions(sessions, activeSessionId).map((session) => ({
|
|
3275
|
+
value: session.id,
|
|
3276
|
+
label: `${session.id === activeSessionId ? "* " : ""}${session.title || session.id}`,
|
|
3277
|
+
description: `${session.model} | ${session.status}`
|
|
3250
3278
|
}));
|
|
3251
3279
|
}
|
|
3252
|
-
function shouldAutoActivateSession(
|
|
3253
|
-
const runtime = readSessionRuntimeConfig(
|
|
3280
|
+
function shouldAutoActivateSession(session, defaultModel, pluginsEnabled) {
|
|
3281
|
+
const runtime = readSessionRuntimeConfig(session);
|
|
3254
3282
|
return runtime.model === defaultModel && (pluginsEnabled == null || (runtime.pluginsEnabled ?? true) === pluginsEnabled);
|
|
3255
3283
|
}
|
|
3256
3284
|
function recoverableInterruptedRuns(bucket) {
|
|
@@ -3602,17 +3630,17 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3602
3630
|
}, LIVE_TEXT_DELTA_FLUSH_MS);
|
|
3603
3631
|
}, [clearPendingClientState]);
|
|
3604
3632
|
useEffect(() => clearPendingClientState, [clearPendingClientState]);
|
|
3605
|
-
const activateSession = useCallback((
|
|
3606
|
-
const runtime = readSessionRuntimeConfig(
|
|
3607
|
-
activeSessionIdRef.current =
|
|
3608
|
-
setActiveSessionId(
|
|
3633
|
+
const activateSession = useCallback((session) => {
|
|
3634
|
+
const runtime = readSessionRuntimeConfig(session, defaultRuntimeRef.current);
|
|
3635
|
+
activeSessionIdRef.current = session.id;
|
|
3636
|
+
setActiveSessionId(session.id);
|
|
3609
3637
|
clearAuxiliaryState();
|
|
3610
3638
|
setStatus((current) => ({
|
|
3611
3639
|
...current,
|
|
3612
3640
|
model: runtime.model,
|
|
3613
3641
|
...runtime.provider ? { provider: runtime.provider } : {},
|
|
3614
|
-
session_id:
|
|
3615
|
-
cwd:
|
|
3642
|
+
session_id: session.id,
|
|
3643
|
+
cwd: session.cwd,
|
|
3616
3644
|
permission_mode: typeof runtime.permissionMode === "string" ? runtime.permissionMode : current.permission_mode,
|
|
3617
3645
|
...typeof runtime.maxTurns === "number" ? { max_turns: runtime.maxTurns } : {},
|
|
3618
3646
|
session_mode: statusSessionMode(runtime.sessionMode)
|
|
@@ -3656,7 +3684,7 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3656
3684
|
try {
|
|
3657
3685
|
await client.health();
|
|
3658
3686
|
const cwd = daemon.cwd ?? process.cwd();
|
|
3659
|
-
const [settings, sessions,
|
|
3687
|
+
const [settings, sessions, commands] = await Promise.all([client.getSettings().catch(() => ({})), client.listSessions({ cwd, limit: 20 }), client.listCommands({ cwd }).catch(() => [])]);
|
|
3660
3688
|
const model = daemon.model ?? stringSetting(settings.model) ?? "default";
|
|
3661
3689
|
const provider = stringSetting(settings.provider);
|
|
3662
3690
|
const baseUrl = stringSetting(settings.baseUrl);
|
|
@@ -3669,8 +3697,8 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3669
3697
|
};
|
|
3670
3698
|
if (cancelled)
|
|
3671
3699
|
return;
|
|
3672
|
-
listedSessionsRef.current = Object.fromEntries(sessions.map((
|
|
3673
|
-
setCommandCatalog(
|
|
3700
|
+
listedSessionsRef.current = Object.fromEntries(sessions.map((session) => [session.id, session]));
|
|
3701
|
+
setCommandCatalog(commands);
|
|
3674
3702
|
setStatus((current) => ({
|
|
3675
3703
|
...current,
|
|
3676
3704
|
model,
|
|
@@ -3680,10 +3708,10 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3680
3708
|
...typeof daemon?.maxTurns === "number" ? { max_turns: daemon.maxTurns } : {},
|
|
3681
3709
|
session_mode: statusSessionMode(daemon?.sessionMode)
|
|
3682
3710
|
}));
|
|
3683
|
-
const
|
|
3684
|
-
if (
|
|
3685
|
-
activateSession(
|
|
3686
|
-
client.getSession(
|
|
3711
|
+
const session = sessions[0];
|
|
3712
|
+
if (session && shouldAutoActivateSession(session, model, daemon?.pluginsEnabled)) {
|
|
3713
|
+
activateSession(session);
|
|
3714
|
+
client.getSession(session.id).catch(() => {});
|
|
3687
3715
|
}
|
|
3688
3716
|
setReady(true);
|
|
3689
3717
|
} catch (error) {
|
|
@@ -3817,18 +3845,18 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3817
3845
|
sessionMode: nextSessionModeRef.current,
|
|
3818
3846
|
pluginsEnabled: daemon?.pluginsEnabled
|
|
3819
3847
|
});
|
|
3820
|
-
const
|
|
3848
|
+
const session = await client.createSession({
|
|
3821
3849
|
cwd,
|
|
3822
3850
|
model,
|
|
3823
3851
|
title: title?.trim() || "TUI",
|
|
3824
3852
|
metadata
|
|
3825
3853
|
});
|
|
3826
|
-
activateSession(
|
|
3854
|
+
activateSession(session);
|
|
3827
3855
|
setSelectRequest(null);
|
|
3828
3856
|
setLocalBusy(false);
|
|
3829
3857
|
setSubmittedRun(null);
|
|
3830
3858
|
pendingNewSessionTitleRef.current = undefined;
|
|
3831
|
-
return
|
|
3859
|
+
return session;
|
|
3832
3860
|
}, [activateSession, daemon?.cwd, daemon?.maxTurns, daemon?.model, daemon?.permissionMode, daemon?.pluginsEnabled, daemon?.sessionMode]);
|
|
3833
3861
|
useEffect(() => {
|
|
3834
3862
|
if (!ready || sentInitialPromptRef.current || !config.initial_prompt)
|
|
@@ -3839,17 +3867,17 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3839
3867
|
return;
|
|
3840
3868
|
setLocalBusy(true);
|
|
3841
3869
|
(async () => {
|
|
3842
|
-
const
|
|
3843
|
-
if (!
|
|
3870
|
+
const session = activeSessionId ? clientState.sessions[activeSessionId] ?? await client.getSession(activeSessionId) : await createAndSwitchSession();
|
|
3871
|
+
if (!session) {
|
|
3844
3872
|
setLocalBusy(false);
|
|
3845
3873
|
return;
|
|
3846
3874
|
}
|
|
3847
|
-
const response = await client.admitPrompt(
|
|
3875
|
+
const response = await client.admitPrompt(session.id, {
|
|
3848
3876
|
id: createPromptRequestId(),
|
|
3849
3877
|
content: config.initial_prompt
|
|
3850
3878
|
});
|
|
3851
3879
|
setLocalBusy(false);
|
|
3852
|
-
setSubmittedRun(response.run ? { sessionId:
|
|
3880
|
+
setSubmittedRun(response.run ? { sessionId: session.id, runId: response.run.id } : null);
|
|
3853
3881
|
})().catch((error) => reportError(error instanceof Error ? error.message : String(error)));
|
|
3854
3882
|
}, [activeSessionId, clientState.sessions, config.initial_prompt, createAndSwitchSession, ready, reportError]);
|
|
3855
3883
|
const sendRequest = useCallback((action) => {
|
|
@@ -3867,13 +3895,13 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3867
3895
|
if (!model)
|
|
3868
3896
|
return;
|
|
3869
3897
|
if (sessionId) {
|
|
3870
|
-
const
|
|
3898
|
+
const session = await client.updateSession(sessionId, {
|
|
3871
3899
|
metadata: patchSessionRuntimeMetadata({}, {
|
|
3872
3900
|
model,
|
|
3873
3901
|
...provider ? { provider } : {}
|
|
3874
3902
|
})
|
|
3875
3903
|
});
|
|
3876
|
-
activateSession(
|
|
3904
|
+
activateSession(session);
|
|
3877
3905
|
} else {
|
|
3878
3906
|
const settingsPatch = { model };
|
|
3879
3907
|
if (provider)
|
|
@@ -3915,8 +3943,8 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3915
3943
|
activateSession(knownSession);
|
|
3916
3944
|
return;
|
|
3917
3945
|
}
|
|
3918
|
-
const
|
|
3919
|
-
activateSession(
|
|
3946
|
+
const session = await client.getSession(target);
|
|
3947
|
+
activateSession(session);
|
|
3920
3948
|
return;
|
|
3921
3949
|
}
|
|
3922
3950
|
if (slash?.name === "/resume") {
|
|
@@ -3948,9 +3976,9 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3948
3976
|
return;
|
|
3949
3977
|
}
|
|
3950
3978
|
setLocalBusy(true);
|
|
3951
|
-
const
|
|
3979
|
+
const response = await client.resumeInterruptedRun(sessionId, runId, { id: createPromptRequestId() });
|
|
3952
3980
|
setLocalBusy(false);
|
|
3953
|
-
setSubmittedRun(
|
|
3981
|
+
setSubmittedRun(response.run ? { sessionId, runId: response.run.id } : null);
|
|
3954
3982
|
setSelectRequest(null);
|
|
3955
3983
|
return;
|
|
3956
3984
|
}
|
|
@@ -3991,7 +4019,7 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
3991
4019
|
return;
|
|
3992
4020
|
setLocalBusy(true);
|
|
3993
4021
|
const commandName = slash.name.replace(/^\//, "");
|
|
3994
|
-
const
|
|
4022
|
+
const response = await client.admitPrompt(sessionId, {
|
|
3995
4023
|
id: createPromptRequestId(),
|
|
3996
4024
|
content: slash.args,
|
|
3997
4025
|
metadata: {
|
|
@@ -4005,17 +4033,17 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
4005
4033
|
}
|
|
4006
4034
|
});
|
|
4007
4035
|
setLocalBusy(false);
|
|
4008
|
-
setSubmittedRun(
|
|
4036
|
+
setSubmittedRun(response.run ? { sessionId, runId: response.run.id } : null);
|
|
4009
4037
|
return;
|
|
4010
4038
|
}
|
|
4011
4039
|
pushSystem(`Unknown command: ${slash.name}`);
|
|
4012
4040
|
return;
|
|
4013
4041
|
}
|
|
4014
4042
|
if (!sessionId) {
|
|
4015
|
-
const
|
|
4016
|
-
if (!
|
|
4043
|
+
const session = await createAndSwitchSession(pendingNewSessionTitleRef.current);
|
|
4044
|
+
if (!session)
|
|
4017
4045
|
return;
|
|
4018
|
-
sessionId =
|
|
4046
|
+
sessionId = session.id;
|
|
4019
4047
|
}
|
|
4020
4048
|
setLocalBusy(true);
|
|
4021
4049
|
const response = await client.admitPrompt(sessionId, {
|
|
@@ -4056,8 +4084,8 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
4056
4084
|
includeArchived: false,
|
|
4057
4085
|
limit: 20
|
|
4058
4086
|
});
|
|
4059
|
-
listedSessionsRef.current = Object.fromEntries(sessions.map((
|
|
4060
|
-
const remoteNext = sessions.find((
|
|
4087
|
+
listedSessionsRef.current = Object.fromEntries(sessions.map((session) => [session.id, session]));
|
|
4088
|
+
const remoteNext = sessions.find((session) => session.id !== target);
|
|
4061
4089
|
if (remoteNext)
|
|
4062
4090
|
activateSession(remoteNext);
|
|
4063
4091
|
else
|
|
@@ -4107,7 +4135,7 @@ Refresh failed: ${message}` : `Failed to load ${request.title}: ${message}`;
|
|
|
4107
4135
|
includeArchived: false,
|
|
4108
4136
|
limit: 20
|
|
4109
4137
|
});
|
|
4110
|
-
listedSessionsRef.current = Object.fromEntries(sessions.map((
|
|
4138
|
+
listedSessionsRef.current = Object.fromEntries(sessions.map((session) => [session.id, session]));
|
|
4111
4139
|
setSelectRequest((current) => current?.submitPrefix === "/sessions open " ? {
|
|
4112
4140
|
title: "Sessions",
|
|
4113
4141
|
submitPrefix: "/sessions open ",
|
|
@@ -4889,9 +4917,9 @@ var init_QuestionDialog = __esm(() => {
|
|
|
4889
4917
|
// ../frontend/src/hooks/useModalWiring.tsx
|
|
4890
4918
|
import { useEffect as useEffect4, useRef as useRef5 } from "react";
|
|
4891
4919
|
import { jsxDEV as jsxDEV7 } from "@opentui/react/jsx-dev-runtime";
|
|
4892
|
-
function useModalWiring(
|
|
4920
|
+
function useModalWiring(session, dialog) {
|
|
4893
4921
|
useEffect4(() => {
|
|
4894
|
-
const modal =
|
|
4922
|
+
const modal = session.modal;
|
|
4895
4923
|
if (!modal)
|
|
4896
4924
|
return;
|
|
4897
4925
|
if (modal.kind === "permission") {
|
|
@@ -4903,25 +4931,25 @@ function useModalWiring(session2, dialog) {
|
|
|
4903
4931
|
if (respondedRef.current)
|
|
4904
4932
|
return;
|
|
4905
4933
|
respondedRef.current = true;
|
|
4906
|
-
|
|
4934
|
+
session.sendRequest({
|
|
4907
4935
|
type: "permission_response",
|
|
4908
4936
|
request_id: requestId,
|
|
4909
4937
|
allowed,
|
|
4910
4938
|
scope
|
|
4911
4939
|
});
|
|
4912
|
-
|
|
4940
|
+
session.setModal(null);
|
|
4913
4941
|
dialog.close();
|
|
4914
4942
|
};
|
|
4915
4943
|
const onClose = () => {
|
|
4916
4944
|
if (!respondedRef.current) {
|
|
4917
4945
|
respondedRef.current = true;
|
|
4918
|
-
|
|
4946
|
+
session.sendRequest({
|
|
4919
4947
|
type: "permission_response",
|
|
4920
4948
|
request_id: requestId,
|
|
4921
4949
|
allowed: false,
|
|
4922
4950
|
scope: "once"
|
|
4923
4951
|
});
|
|
4924
|
-
|
|
4952
|
+
session.setModal(null);
|
|
4925
4953
|
}
|
|
4926
4954
|
};
|
|
4927
4955
|
dialog.replace(/* @__PURE__ */ jsxDEV7(PermissionDialog, {
|
|
@@ -4939,12 +4967,12 @@ function useModalWiring(session2, dialog) {
|
|
|
4939
4967
|
if (respondedRef.current)
|
|
4940
4968
|
return;
|
|
4941
4969
|
respondedRef.current = true;
|
|
4942
|
-
|
|
4970
|
+
session.sendRequest({
|
|
4943
4971
|
type: "question_response",
|
|
4944
4972
|
request_id: requestId,
|
|
4945
4973
|
answer
|
|
4946
4974
|
});
|
|
4947
|
-
|
|
4975
|
+
session.setModal(null);
|
|
4948
4976
|
};
|
|
4949
4977
|
const onClose = () => {
|
|
4950
4978
|
sendAnswer("");
|
|
@@ -4957,19 +4985,19 @@ function useModalWiring(session2, dialog) {
|
|
|
4957
4985
|
}
|
|
4958
4986
|
}, undefined, false, undefined, this), onClose);
|
|
4959
4987
|
}
|
|
4960
|
-
}, [
|
|
4988
|
+
}, [session.modal]);
|
|
4961
4989
|
useEffect4(() => {
|
|
4962
|
-
const req =
|
|
4990
|
+
const req = session.displayRequest;
|
|
4963
4991
|
if (!req)
|
|
4964
4992
|
return;
|
|
4965
4993
|
dialog.replace(/* @__PURE__ */ jsxDEV7(DialogText, {
|
|
4966
4994
|
title: req.title,
|
|
4967
4995
|
content: req.content
|
|
4968
|
-
}, undefined, false, undefined, this), () =>
|
|
4969
|
-
}, [
|
|
4996
|
+
}, undefined, false, undefined, this), () => session.setDisplayRequest(null));
|
|
4997
|
+
}, [session.displayRequest]);
|
|
4970
4998
|
const selectOpenRef = useRef5(false);
|
|
4971
4999
|
useEffect4(() => {
|
|
4972
|
-
const req =
|
|
5000
|
+
const req = session.selectRequest;
|
|
4973
5001
|
if (!req) {
|
|
4974
5002
|
if (selectOpenRef.current) {
|
|
4975
5003
|
selectOpenRef.current = false;
|
|
@@ -4987,15 +5015,15 @@ function useModalWiring(session2, dialog) {
|
|
|
4987
5015
|
})),
|
|
4988
5016
|
onSelect: (value) => {
|
|
4989
5017
|
selectOpenRef.current = false;
|
|
4990
|
-
|
|
5018
|
+
session.sendRequest({
|
|
4991
5019
|
type: "submit_line",
|
|
4992
5020
|
line: `${req.submitPrefix}${value}`
|
|
4993
5021
|
});
|
|
4994
|
-
|
|
5022
|
+
session.setSelectRequest(null);
|
|
4995
5023
|
dialog.close();
|
|
4996
5024
|
},
|
|
4997
5025
|
onDelete: isSessions ? (value) => {
|
|
4998
|
-
|
|
5026
|
+
session.sendRequest({ type: "delete_session", session_id: value });
|
|
4999
5027
|
} : undefined
|
|
5000
5028
|
}, undefined, false, undefined, this);
|
|
5001
5029
|
if (selectOpenRef.current) {
|
|
@@ -5005,9 +5033,9 @@ function useModalWiring(session2, dialog) {
|
|
|
5005
5033
|
selectOpenRef.current = true;
|
|
5006
5034
|
dialog.replace(node, () => {
|
|
5007
5035
|
selectOpenRef.current = false;
|
|
5008
|
-
|
|
5036
|
+
session.setSelectRequest(null);
|
|
5009
5037
|
});
|
|
5010
|
-
}, [
|
|
5038
|
+
}, [session.selectRequest]);
|
|
5011
5039
|
}
|
|
5012
5040
|
var init_useModalWiring = __esm(() => {
|
|
5013
5041
|
init_DialogSelect();
|
|
@@ -7185,7 +7213,7 @@ function JobsPanel({ state, detailState, onRefresh, onSelect, onCancel }) {
|
|
|
7185
7213
|
const c = theme.colors;
|
|
7186
7214
|
const [kindFilter, setKindFilter] = useState12();
|
|
7187
7215
|
const [statusFilter, setStatusFilter] = useState12();
|
|
7188
|
-
const visibleJobs = useMemo6(() => state.jobs.filter((
|
|
7216
|
+
const visibleJobs = useMemo6(() => state.jobs.filter((job) => (!kindFilter || job.kind === kindFilter) && (!statusFilter || job.status === statusFilter)), [kindFilter, state.jobs, statusFilter]);
|
|
7189
7217
|
const { index, setIndex, moveUp, moveDown } = useListNavigation(visibleJobs.length);
|
|
7190
7218
|
const cursorIndex = Math.min(index, Math.max(0, visibleJobs.length - 1));
|
|
7191
7219
|
const selectedJob = visibleJobs[cursorIndex];
|
|
@@ -7247,12 +7275,12 @@ function JobsPanel({ state, detailState, onRefresh, onSelect, onCancel }) {
|
|
|
7247
7275
|
}, undefined, false, undefined, this),
|
|
7248
7276
|
visibleJobs.length > 0 ? /* @__PURE__ */ jsxDEV21("box", {
|
|
7249
7277
|
flexDirection: "column",
|
|
7250
|
-
children: jobWindow.map((
|
|
7278
|
+
children: jobWindow.map((job, visibleIndex) => {
|
|
7251
7279
|
const isCursor = windowStart + visibleIndex === cursorIndex;
|
|
7252
7280
|
return /* @__PURE__ */ jsxDEV21(JobRow, {
|
|
7253
|
-
job
|
|
7281
|
+
job,
|
|
7254
7282
|
selected: isCursor
|
|
7255
|
-
},
|
|
7283
|
+
}, job.id, false, undefined, this);
|
|
7256
7284
|
})
|
|
7257
7285
|
}, undefined, false, undefined, this) : state.status === "ready" || state.status === "idle" ? /* @__PURE__ */ jsxDEV21("text", {
|
|
7258
7286
|
fg: c.muted,
|
|
@@ -7289,22 +7317,22 @@ function ListRemoteState({ state }) {
|
|
|
7289
7317
|
}
|
|
7290
7318
|
return null;
|
|
7291
7319
|
}
|
|
7292
|
-
function JobRow({ job
|
|
7320
|
+
function JobRow({ job, selected }) {
|
|
7293
7321
|
const { theme } = useTheme();
|
|
7294
7322
|
const c = theme.colors;
|
|
7295
|
-
const marker = statusMarker(
|
|
7296
|
-
const foreground = selected ? c.background : statusColor2(
|
|
7323
|
+
const marker = statusMarker(job.status);
|
|
7324
|
+
const foreground = selected ? c.background : statusColor2(job.status, c);
|
|
7297
7325
|
return /* @__PURE__ */ jsxDEV21("box", {
|
|
7298
7326
|
flexDirection: "column",
|
|
7299
7327
|
backgroundColor: selected ? c.accent : undefined,
|
|
7300
7328
|
children: [
|
|
7301
7329
|
/* @__PURE__ */ jsxDEV21("text", {
|
|
7302
7330
|
fg: foreground,
|
|
7303
|
-
children: `${marker} ${
|
|
7331
|
+
children: `${marker} ${job.kind} ${job.status} ${truncate2(job.label, 50)}`
|
|
7304
7332
|
}, undefined, false, undefined, this),
|
|
7305
7333
|
/* @__PURE__ */ jsxDEV21("text", {
|
|
7306
7334
|
fg: selected ? c.background : c.muted,
|
|
7307
|
-
children: ` ${truncate2(
|
|
7335
|
+
children: ` ${truncate2(job.id, 24)} ${truncate2(job.cwd, 44)}`
|
|
7308
7336
|
}, undefined, false, undefined, this)
|
|
7309
7337
|
]
|
|
7310
7338
|
}, undefined, true, undefined, this);
|
|
@@ -7574,9 +7602,7 @@ var init_selection = () => {};
|
|
|
7574
7602
|
// ../frontend/src/App.tsx
|
|
7575
7603
|
var exports_App = {};
|
|
7576
7604
|
__export(exports_App, {
|
|
7577
|
-
App: () => App
|
|
7578
|
-
createJobsPanelCallbacks: () => createJobsPanelCallbacks,
|
|
7579
|
-
shouldOpenJobsPanel: () => shouldOpenJobsPanel
|
|
7605
|
+
App: () => App
|
|
7580
7606
|
});
|
|
7581
7607
|
import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo7, useRef as useRef9, useState as useState13 } from "react";
|
|
7582
7608
|
import { useKeyboard as useKeyboard8, useRenderer, useTerminalDimensions as useTerminalDimensions5 } from "@opentui/react";
|
|
@@ -7612,9 +7638,9 @@ function AppInner({ config }) {
|
|
|
7612
7638
|
renderer.destroy();
|
|
7613
7639
|
}, [renderer]);
|
|
7614
7640
|
const onSessionError = useCallback7((message) => toast(message, "error"), [toast]);
|
|
7615
|
-
const
|
|
7616
|
-
const jobsPanelCallbacks = useMemo7(() => createJobsPanelCallbacks(
|
|
7617
|
-
const activeSessionId = typeof
|
|
7641
|
+
const session = useServerSync(config, onSessionError);
|
|
7642
|
+
const jobsPanelCallbacks = useMemo7(() => createJobsPanelCallbacks(session.sendRequest), [session.sendRequest]);
|
|
7643
|
+
const activeSessionId = typeof session.status.session_id === "string" ? session.status.session_id : undefined;
|
|
7618
7644
|
const previousSessionIdRef = useRef9(undefined);
|
|
7619
7645
|
useEffect10(() => {
|
|
7620
7646
|
const previousSessionId = previousSessionIdRef.current;
|
|
@@ -7627,8 +7653,8 @@ function AppInner({ config }) {
|
|
|
7627
7653
|
}, [activeSessionId, dialog.closeAll]);
|
|
7628
7654
|
const [history, setHistory] = useState13([]);
|
|
7629
7655
|
const [draft, setDraft] = useState13("");
|
|
7630
|
-
const { escHint, handleEscape } = useEscToCancel(
|
|
7631
|
-
|
|
7656
|
+
const { escHint, handleEscape } = useEscToCancel(session.busy, () => {
|
|
7657
|
+
session.sendRequest({ type: "interrupt" });
|
|
7632
7658
|
});
|
|
7633
7659
|
const appendHistory = useCallback7((line) => {
|
|
7634
7660
|
setHistory((prev) => {
|
|
@@ -7637,22 +7663,22 @@ function AppInner({ config }) {
|
|
|
7637
7663
|
});
|
|
7638
7664
|
}, []);
|
|
7639
7665
|
const setPermissionMode = useCallback7((mode) => {
|
|
7640
|
-
|
|
7641
|
-
}, [
|
|
7666
|
+
session.sendRequest({ type: "set_permission_mode", permission_mode: mode });
|
|
7667
|
+
}, [session]);
|
|
7642
7668
|
const openModelPicker = useCallback7(() => {
|
|
7643
|
-
const currentModel = typeof
|
|
7669
|
+
const currentModel = typeof session.status.model === "string" ? session.status.model : config.daemon?.model ?? undefined;
|
|
7644
7670
|
dialog.replace(/* @__PURE__ */ jsxDEV22("box", {
|
|
7645
7671
|
flexDirection: "column",
|
|
7646
7672
|
children: /* @__PURE__ */ jsxDEV22("text", {
|
|
7647
7673
|
children: "Loading models..."
|
|
7648
7674
|
}, undefined, false, undefined, this)
|
|
7649
7675
|
}, undefined, false, undefined, this));
|
|
7650
|
-
|
|
7676
|
+
session.loadModels().then((providers) => {
|
|
7651
7677
|
dialog.replace(/* @__PURE__ */ jsxDEV22(ModelPickerDialog, {
|
|
7652
7678
|
providers,
|
|
7653
7679
|
currentModel,
|
|
7654
7680
|
onSelect: (model) => {
|
|
7655
|
-
|
|
7681
|
+
session.sendRequest({
|
|
7656
7682
|
type: "select_model",
|
|
7657
7683
|
model: model.id,
|
|
7658
7684
|
provider: model.providerName
|
|
@@ -7666,7 +7692,7 @@ function AppInner({ config }) {
|
|
|
7666
7692
|
dialog.close();
|
|
7667
7693
|
toast(`Models: ${message}`, "error");
|
|
7668
7694
|
});
|
|
7669
|
-
}, [config.daemon?.model, dialog,
|
|
7695
|
+
}, [config.daemon?.model, dialog, session, toast]);
|
|
7670
7696
|
const handleCommand = useCallback7((line) => {
|
|
7671
7697
|
const themeSetMatch = line.match(/^\/theme\s+set\s+(\S+)$/);
|
|
7672
7698
|
if (themeSetMatch?.[1]) {
|
|
@@ -7697,7 +7723,7 @@ function AppInner({ config }) {
|
|
|
7697
7723
|
return true;
|
|
7698
7724
|
}
|
|
7699
7725
|
if (line.trim() === "/permissions" || line.trim() === "/permissions show") {
|
|
7700
|
-
const currentMode = String(
|
|
7726
|
+
const currentMode = String(session.status.permission_mode ?? "default");
|
|
7701
7727
|
const currentIndex = PERMISSION_MODES.findIndex((m) => m.value === currentMode);
|
|
7702
7728
|
dialog.replace(/* @__PURE__ */ jsxDEV22(DialogSelect, {
|
|
7703
7729
|
title: "Permission Mode",
|
|
@@ -7717,9 +7743,9 @@ function AppInner({ config }) {
|
|
|
7717
7743
|
return true;
|
|
7718
7744
|
}
|
|
7719
7745
|
if (line.trim() === "/plan") {
|
|
7720
|
-
const currentMode = String(
|
|
7746
|
+
const currentMode = String(session.status.permission_mode ?? "default");
|
|
7721
7747
|
const isPlan = currentMode === "plan";
|
|
7722
|
-
|
|
7748
|
+
session.sendRequest({
|
|
7723
7749
|
type: "submit_line",
|
|
7724
7750
|
line: isPlan ? "/plan off" : "/plan on"
|
|
7725
7751
|
});
|
|
@@ -7727,7 +7753,7 @@ function AppInner({ config }) {
|
|
|
7727
7753
|
}
|
|
7728
7754
|
const coordinatorMatch = line.trim().match(/^\/coordinator(?:\s+(on|off|status))?$/);
|
|
7729
7755
|
if (coordinatorMatch) {
|
|
7730
|
-
const currentMode = String(
|
|
7756
|
+
const currentMode = String(session.status.session_mode ?? "direct");
|
|
7731
7757
|
const action = coordinatorMatch[1] ?? (currentMode === "coordinator" ? "off" : "on");
|
|
7732
7758
|
if (action === "status") {
|
|
7733
7759
|
toast(`Coordinator mode: ${currentMode === "coordinator" ? "on" : "off"}`);
|
|
@@ -7737,7 +7763,7 @@ function AppInner({ config }) {
|
|
|
7737
7763
|
toast("Use /new before changing coordinator mode", "error");
|
|
7738
7764
|
return true;
|
|
7739
7765
|
}
|
|
7740
|
-
|
|
7766
|
+
session.sendRequest({
|
|
7741
7767
|
type: "set_session_mode",
|
|
7742
7768
|
session_mode: action === "on" ? "coordinator" : "direct"
|
|
7743
7769
|
});
|
|
@@ -7745,22 +7771,22 @@ function AppInner({ config }) {
|
|
|
7745
7771
|
return true;
|
|
7746
7772
|
}
|
|
7747
7773
|
if (line.trim() === "/sessions") {
|
|
7748
|
-
|
|
7774
|
+
session.sendRequest({ type: "list_sessions" });
|
|
7749
7775
|
return true;
|
|
7750
7776
|
}
|
|
7751
7777
|
if (shouldOpenJobsPanel(line)) {
|
|
7752
7778
|
setJobsPanelOpen(true);
|
|
7753
|
-
|
|
7779
|
+
session.sendRequest({ type: "job_request", job_action: "open" });
|
|
7754
7780
|
return true;
|
|
7755
7781
|
}
|
|
7756
7782
|
return false;
|
|
7757
|
-
}, [activeSessionId, dialog, openModelPicker,
|
|
7783
|
+
}, [activeSessionId, dialog, openModelPicker, session, setThemeName, theme.name, toast]);
|
|
7758
7784
|
const registryRef = useRef9(null);
|
|
7759
7785
|
const openCommandPalette = useCallback7(() => {
|
|
7760
|
-
const
|
|
7761
|
-
if (!
|
|
7786
|
+
const registry = registryRef.current;
|
|
7787
|
+
if (!registry)
|
|
7762
7788
|
return;
|
|
7763
|
-
const allCmds =
|
|
7789
|
+
const allCmds = registry.all();
|
|
7764
7790
|
dialog.replace(/* @__PURE__ */ jsxDEV22(DialogSelect, {
|
|
7765
7791
|
title: "Commands",
|
|
7766
7792
|
items: allCmds.map((cmd) => ({
|
|
@@ -7771,7 +7797,7 @@ function AppInner({ config }) {
|
|
|
7771
7797
|
})),
|
|
7772
7798
|
onSelect: (id) => {
|
|
7773
7799
|
dialog.close();
|
|
7774
|
-
const cmd =
|
|
7800
|
+
const cmd = registry.get(id);
|
|
7775
7801
|
cmd?.run();
|
|
7776
7802
|
}
|
|
7777
7803
|
}, undefined, false, undefined, this));
|
|
@@ -7781,17 +7807,17 @@ function AppInner({ config }) {
|
|
|
7781
7807
|
appendHistory(line);
|
|
7782
7808
|
return;
|
|
7783
7809
|
}
|
|
7784
|
-
|
|
7810
|
+
session.sendRequest({ type: "submit_line", line });
|
|
7785
7811
|
appendHistory(line);
|
|
7786
|
-
}, [appendHistory, handleCommand,
|
|
7812
|
+
}, [appendHistory, handleCommand, session]);
|
|
7787
7813
|
const onCycleMode = useCallback7(() => {
|
|
7788
|
-
const currentMode = String(
|
|
7814
|
+
const currentMode = String(session.status.permission_mode ?? "default");
|
|
7789
7815
|
const idx = PERMISSION_MODE_ORDER.indexOf(currentMode);
|
|
7790
7816
|
const nextMode = PERMISSION_MODE_ORDER[(idx + 1) % PERMISSION_MODE_ORDER.length] ?? "default";
|
|
7791
7817
|
setPermissionMode(nextMode);
|
|
7792
|
-
}, [
|
|
7818
|
+
}, [session.status.permission_mode, setPermissionMode]);
|
|
7793
7819
|
const registry = useMemo7(() => buildRegistry({
|
|
7794
|
-
backendCommands: (
|
|
7820
|
+
backendCommands: (session.commandDetails.length > 0 ? [...session.commandDetails] : session.commands.map((name) => ({ name }))).sort((a, b) => a.name.localeCompare(b.name)),
|
|
7795
7821
|
local: [
|
|
7796
7822
|
{
|
|
7797
7823
|
id: "app.palette",
|
|
@@ -7834,7 +7860,7 @@ function AppInner({ config }) {
|
|
|
7834
7860
|
title: "Jobs",
|
|
7835
7861
|
run: () => {
|
|
7836
7862
|
setJobsPanelOpen(true);
|
|
7837
|
-
|
|
7863
|
+
session.sendRequest({ type: "job_request", job_action: "open" });
|
|
7838
7864
|
}
|
|
7839
7865
|
},
|
|
7840
7866
|
{
|
|
@@ -7860,11 +7886,11 @@ function AppInner({ config }) {
|
|
|
7860
7886
|
}
|
|
7861
7887
|
],
|
|
7862
7888
|
submitLine: (line) => {
|
|
7863
|
-
|
|
7889
|
+
session.sendRequest({ type: "submit_line", line });
|
|
7864
7890
|
}
|
|
7865
|
-
}), [handleCommand, onSessionExit, openCommandPalette,
|
|
7891
|
+
}), [handleCommand, onSessionExit, openCommandPalette, session]);
|
|
7866
7892
|
registryRef.current = registry;
|
|
7867
|
-
useModalWiring(
|
|
7893
|
+
useModalWiring(session, dialog);
|
|
7868
7894
|
useKeyboard8((key) => {
|
|
7869
7895
|
if (key.ctrl && key.name === "c") {
|
|
7870
7896
|
if (copySelectionToClipboard(renderer, toast)) {
|
|
@@ -7888,7 +7914,7 @@ function AppInner({ config }) {
|
|
|
7888
7914
|
if (key.ctrl && key.name === "b") {
|
|
7889
7915
|
setSidebarOpen((v) => !v);
|
|
7890
7916
|
}
|
|
7891
|
-
if (key.name === "escape" &&
|
|
7917
|
+
if (key.name === "escape" && session.busy && !dialog.isOpen) {
|
|
7892
7918
|
handleEscape();
|
|
7893
7919
|
}
|
|
7894
7920
|
});
|
|
@@ -7897,12 +7923,12 @@ function AppInner({ config }) {
|
|
|
7897
7923
|
return /* @__PURE__ */ jsxDEV22(Fragment3, {
|
|
7898
7924
|
children: [
|
|
7899
7925
|
/* @__PURE__ */ jsxDEV22(AppView, {
|
|
7900
|
-
transcript:
|
|
7901
|
-
assistantBuffer:
|
|
7902
|
-
ready:
|
|
7903
|
-
busy:
|
|
7904
|
-
status:
|
|
7905
|
-
mcpServers:
|
|
7926
|
+
transcript: session.transcript,
|
|
7927
|
+
assistantBuffer: session.assistantBuffer,
|
|
7928
|
+
ready: session.ready,
|
|
7929
|
+
busy: session.busy,
|
|
7930
|
+
status: session.status,
|
|
7931
|
+
mcpServers: session.mcpServers,
|
|
7906
7932
|
version: config.version ?? null,
|
|
7907
7933
|
history,
|
|
7908
7934
|
slashCommands: registry.slashCommands(),
|
|
@@ -7927,8 +7953,8 @@ function AppInner({ config }) {
|
|
|
7927
7953
|
padding: 1,
|
|
7928
7954
|
flexDirection: "column",
|
|
7929
7955
|
children: /* @__PURE__ */ jsxDEV22(JobsPanel, {
|
|
7930
|
-
state:
|
|
7931
|
-
detailState:
|
|
7956
|
+
state: session.jobState,
|
|
7957
|
+
detailState: session.jobDetailState,
|
|
7932
7958
|
...jobsPanelCallbacks
|
|
7933
7959
|
}, undefined, false, undefined, this)
|
|
7934
7960
|
}, undefined, false, undefined, this) : null
|
|
@@ -8012,7 +8038,7 @@ try {
|
|
|
8012
8038
|
}
|
|
8013
8039
|
try {
|
|
8014
8040
|
assertSupportedTuiRuntime();
|
|
8015
|
-
const [{ createCliRenderer }, { createElement, createRoot }, { App
|
|
8041
|
+
const [{ createCliRenderer }, { createElement, createRoot }, { App }] = await Promise.all([
|
|
8016
8042
|
import("@opentui/core"),
|
|
8017
8043
|
import("@opentui/react"),
|
|
8018
8044
|
Promise.resolve().then(() => (init_App(), exports_App))
|
|
@@ -8024,10 +8050,10 @@ try {
|
|
|
8024
8050
|
onDestroy: () => process.exit(process.exitCode ?? 0)
|
|
8025
8051
|
});
|
|
8026
8052
|
renderer.setTerminalTitle("OpenHarness");
|
|
8027
|
-
createRoot(renderer).render(createElement(
|
|
8053
|
+
createRoot(renderer).render(createElement(App, { config }));
|
|
8028
8054
|
} catch (err) {
|
|
8029
8055
|
console.error("[openharness] \u7EC8\u7AEF\u6E32\u67D3\u5668\u521D\u59CB\u5316\u5931\u8D25\uFF08\u9700\u8981 Bun + \u652F\u6301\u7684\u5E73\u53F0\uFF09\uFF1A", err);
|
|
8030
8056
|
process.exit(1);
|
|
8031
8057
|
}
|
|
8032
8058
|
|
|
8033
|
-
//# debugId=
|
|
8059
|
+
//# debugId=5DBCBBC40135AE2E64756E2164756E21
|