neko-harness 0.4.3 → 0.4.4
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/client/assets/index-BjLs6qQU.css +2 -0
- package/dist/client/assets/index-BqLuRtzq.js +391 -0
- package/dist/client/index.html +2 -2
- package/dist/gateway.js +182 -1
- package/dist/neko.js +425 -51
- package/package.json +1 -1
- package/dist/client/assets/index-CAwqBiZ6.css +0 -2
- package/dist/client/assets/index-DLyLR2Bn.js +0 -391
package/dist/neko.js
CHANGED
|
@@ -80,7 +80,7 @@ function updateAction(input) {
|
|
|
80
80
|
return "install";
|
|
81
81
|
return "none";
|
|
82
82
|
}
|
|
83
|
-
var RUNNING_VERSION = "0.4.
|
|
83
|
+
var RUNNING_VERSION = "0.4.4", APPLICATION_PROTOCOL = 6, ApplicationProtocolError;
|
|
84
84
|
var init_application_version = __esm(() => {
|
|
85
85
|
ApplicationProtocolError = class ApplicationProtocolError extends Error {
|
|
86
86
|
constructor() {
|
|
@@ -1060,6 +1060,52 @@ var init_input = __esm(() => {
|
|
|
1060
1060
|
NekoInput = defineEntry("app.neko.input");
|
|
1061
1061
|
});
|
|
1062
1062
|
|
|
1063
|
+
// packages/core/src/queued.ts
|
|
1064
|
+
function queuedUserInput(raw) {
|
|
1065
|
+
const item = raw;
|
|
1066
|
+
if (item.mode !== "steer" && item.mode !== "followUp")
|
|
1067
|
+
return;
|
|
1068
|
+
if (item.entry?.kind !== NekoInput.kind)
|
|
1069
|
+
return;
|
|
1070
|
+
const data = item.entry.data;
|
|
1071
|
+
if (!data || data.jobReport || data.subagentRoundId)
|
|
1072
|
+
return;
|
|
1073
|
+
const defaultPrompt = Array.isArray(item.content) ? savedDefaultImagePrompt(item.content, data.defaultImagePrompt) : undefined;
|
|
1074
|
+
const content = defaultPrompt && Array.isArray(item.content) ? item.content.slice(1) : item.content;
|
|
1075
|
+
const skill = data.skill ? { name: data.skill.name, args: data.skill.args } : undefined;
|
|
1076
|
+
return {
|
|
1077
|
+
id: item.id,
|
|
1078
|
+
mode: item.mode,
|
|
1079
|
+
text: skill ? `/skill:${skill.name}${skill.args ? ` ${skill.args}` : ""}` : textOf(content),
|
|
1080
|
+
images: data.images?.length ?? 0,
|
|
1081
|
+
...skill ? { skill } : {}
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
function projectQueued(view) {
|
|
1085
|
+
const items = view.docs["pi.inbox"]?.items ?? [];
|
|
1086
|
+
return items.flatMap((raw) => {
|
|
1087
|
+
const input = queuedUserInput(raw);
|
|
1088
|
+
if (!input)
|
|
1089
|
+
return [];
|
|
1090
|
+
const { text, ...rest } = input;
|
|
1091
|
+
return [{ ...rest, preview: clip(text) }];
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
var QUEUED_PREVIEW_CHARS = 300, textOf = (content) => {
|
|
1095
|
+
if (typeof content === "string")
|
|
1096
|
+
return content;
|
|
1097
|
+
if (!Array.isArray(content))
|
|
1098
|
+
return "";
|
|
1099
|
+
return content.flatMap((b) => b && b.type === "text" && typeof b.text === "string" ? [b.text] : []).join("");
|
|
1100
|
+
}, clip = (text) => {
|
|
1101
|
+
const chars = [...text.replace(/\s+/g, " ").trim()];
|
|
1102
|
+
return chars.length > QUEUED_PREVIEW_CHARS ? `${chars.slice(0, QUEUED_PREVIEW_CHARS - 1).join("")}\u2026` : chars.join("");
|
|
1103
|
+
};
|
|
1104
|
+
var init_queued = __esm(() => {
|
|
1105
|
+
init_image_prompt();
|
|
1106
|
+
init_input();
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1063
1109
|
// packages/core/src/workspace.ts
|
|
1064
1110
|
import { accessSync, constants, realpathSync, statSync } from "fs";
|
|
1065
1111
|
import { isAbsolute, resolve as resolve2 } from "path";
|
|
@@ -1379,6 +1425,7 @@ function projectChatView(view, modelLabel, options = {}) {
|
|
|
1379
1425
|
},
|
|
1380
1426
|
cwd: savedWorkspace(agent?.cwd),
|
|
1381
1427
|
busy: live.run !== undefined,
|
|
1428
|
+
queued: projectQueued(view),
|
|
1382
1429
|
status,
|
|
1383
1430
|
usage: {
|
|
1384
1431
|
input: usage.input,
|
|
@@ -1491,6 +1538,7 @@ var WRITE_DIFF_MAX_LINES = 2000, WRITE_DIFF_MAX_BYTES;
|
|
|
1491
1538
|
var init_projection = __esm(() => {
|
|
1492
1539
|
init_image_prompt();
|
|
1493
1540
|
init_input();
|
|
1541
|
+
init_queued();
|
|
1494
1542
|
init_workspace();
|
|
1495
1543
|
WRITE_DIFF_MAX_BYTES = 64 * 1024;
|
|
1496
1544
|
});
|
|
@@ -3207,6 +3255,14 @@ var createResourceSnapshots = (load, submission) => {
|
|
|
3207
3255
|
discard(id, requestId) {
|
|
3208
3256
|
conversations.get(id)?.pending.delete(requestId);
|
|
3209
3257
|
},
|
|
3258
|
+
move(id, from, to) {
|
|
3259
|
+
const pending = conversations.get(id)?.pending;
|
|
3260
|
+
const snapshot = pending?.get(from);
|
|
3261
|
+
if (!pending || !snapshot)
|
|
3262
|
+
return;
|
|
3263
|
+
pending.delete(from);
|
|
3264
|
+
pending.set(to, snapshot);
|
|
3265
|
+
},
|
|
3210
3266
|
forget(id) {
|
|
3211
3267
|
conversations.delete(id);
|
|
3212
3268
|
}
|
|
@@ -4495,6 +4551,7 @@ import {
|
|
|
4495
4551
|
createRegistry,
|
|
4496
4552
|
defineDoc as defineDoc5,
|
|
4497
4553
|
Harness,
|
|
4554
|
+
InboxDoc as InboxDoc2,
|
|
4498
4555
|
LiveDoc as importLiveDoc,
|
|
4499
4556
|
MemoryStorage,
|
|
4500
4557
|
UsageDoc as UsageDoc2,
|
|
@@ -4843,6 +4900,57 @@ async function createNekoRuntime(options = {}) {
|
|
|
4843
4900
|
},
|
|
4844
4901
|
abort() {
|
|
4845
4902
|
return target.abort(context);
|
|
4903
|
+
},
|
|
4904
|
+
async withdraw(submissionId) {
|
|
4905
|
+
const id = submissionId;
|
|
4906
|
+
const inbox = await harness.snapshot(InboxDoc2, target.id, context);
|
|
4907
|
+
const item = inbox?.items.find((i) => i.id === id);
|
|
4908
|
+
const input = item ? queuedUserInput(item) : undefined;
|
|
4909
|
+
if (item && !input)
|
|
4910
|
+
return { result: "unknown" };
|
|
4911
|
+
const requestId = (await (await harness.submission(id, context))?.status(context))?.requestId;
|
|
4912
|
+
const outcome = await harness.abortSubmission(id, context, target.id);
|
|
4913
|
+
if (outcome !== "aborted") {
|
|
4914
|
+
return { result: outcome === "already_placed" ? "placed" : outcome === "settled" ? "settled" : "unknown" };
|
|
4915
|
+
}
|
|
4916
|
+
if (requestId !== undefined)
|
|
4917
|
+
resourceSnapshots.discard(target.id, requestId);
|
|
4918
|
+
await metadata.reconcile(target.id);
|
|
4919
|
+
return { result: "withdrawn", ...input ? { text: input.text, images: input.images } : {} };
|
|
4920
|
+
},
|
|
4921
|
+
async steer(submissionId) {
|
|
4922
|
+
const id = submissionId;
|
|
4923
|
+
const inbox = await harness.snapshot(InboxDoc2, target.id, context);
|
|
4924
|
+
const item = inbox?.items.find((i) => i.id === id);
|
|
4925
|
+
const input = item ? queuedUserInput(item) : undefined;
|
|
4926
|
+
if (item && (!input || item.mode === "write"))
|
|
4927
|
+
return { result: "unknown" };
|
|
4928
|
+
if (item && input?.mode === "steer")
|
|
4929
|
+
return { result: "steered", id: submissionId };
|
|
4930
|
+
const requestId = (await (await harness.submission(id, context))?.status(context))?.requestId;
|
|
4931
|
+
const outcome = await harness.abortSubmission(id, context, target.id);
|
|
4932
|
+
if (outcome !== "aborted" || !item || !input) {
|
|
4933
|
+
return { result: outcome === "already_placed" ? "placed" : outcome === "settled" ? "settled" : "unknown" };
|
|
4934
|
+
}
|
|
4935
|
+
const steerRequestId = requestId !== undefined ? `steer:${requestId}` : crypto.randomUUID();
|
|
4936
|
+
try {
|
|
4937
|
+
const next = await target.submit({
|
|
4938
|
+
type: "input",
|
|
4939
|
+
content: item.content,
|
|
4940
|
+
...item.entry ? { entry: item.entry } : {},
|
|
4941
|
+
requestId: steerRequestId,
|
|
4942
|
+
whenBusy: "steer"
|
|
4943
|
+
}, context);
|
|
4944
|
+
if (requestId !== undefined)
|
|
4945
|
+
resourceSnapshots.move(target.id, requestId, steerRequestId);
|
|
4946
|
+
await metadata.reconcile(target.id);
|
|
4947
|
+
return { result: "steered", id: next.id };
|
|
4948
|
+
} catch {
|
|
4949
|
+
if (requestId !== undefined)
|
|
4950
|
+
resourceSnapshots.discard(target.id, requestId);
|
|
4951
|
+
await metadata.reconcile(target.id);
|
|
4952
|
+
return { result: "withdrawn", text: input.text, images: input.images };
|
|
4953
|
+
}
|
|
4846
4954
|
}
|
|
4847
4955
|
});
|
|
4848
4956
|
const rootSession = makeSession(conversation);
|
|
@@ -5163,6 +5271,7 @@ var init_runtime = __esm(() => {
|
|
|
5163
5271
|
init_invoke();
|
|
5164
5272
|
init_prompt();
|
|
5165
5273
|
init_resources();
|
|
5274
|
+
init_queued();
|
|
5166
5275
|
init_search_providers();
|
|
5167
5276
|
init_session_metadata();
|
|
5168
5277
|
init_subagent_usage();
|
|
@@ -5238,6 +5347,7 @@ var init_src = __esm(() => {
|
|
|
5238
5347
|
init_jobs();
|
|
5239
5348
|
init_projection();
|
|
5240
5349
|
init_frontmatter();
|
|
5350
|
+
init_queued();
|
|
5241
5351
|
init_runtime();
|
|
5242
5352
|
init_search_providers();
|
|
5243
5353
|
init_session_metadata();
|
|
@@ -5368,7 +5478,7 @@ function contract(name, def) {
|
|
|
5368
5478
|
]));
|
|
5369
5479
|
return remote(name, { ...def, host: hostNamed(GATEWAY_HOST), variants });
|
|
5370
5480
|
}
|
|
5371
|
-
var GATEWAY_HOST = "neko", rpc = (args, result) => [args, result], str, num, bool, nil, integer, nullableString, phase, level, thinking, model, change, usage, image, skill, call, DelegationSchema, SubagentSummarySchema, jobStatus, JobSummarySchema, JobOutputSchema, ChatViewSchema, SessionSummarySchema, DirectoryStateSchema, WorkspaceSummarySchema, WorkspaceStateSchema, credentialStatus, CredentialStateSchema, AttachmentSchema, chatInput, NekoSessionDirectory, NekoSessionManagement, resize, inputLimits, modelInfo, NekoModels, imageChunk, NekoSubagent, NekoChat, browse, page, NekoWorkspaces, provider, NekoCredentials, SearchSettingsStateSchema, NekoSearchSettings, contextSource, ContextSettingsStateSchema, nullable = (schema) => Type5.Union([schema, nil]), ContextSettingsPatchSchema, NekoContextSettings, FileCandidatesSchema, NekoWorkspaceFiles, marketSkill, preview, scope, installResult, NekoSkillMarket, ApplicationInfoSchema, NekoApplicationInfo;
|
|
5481
|
+
var GATEWAY_HOST = "neko", rpc = (args, result) => [args, result], str, num, bool, nil, integer, nullableString, phase, level, thinking, model, change, usage, image, skill, call, DelegationSchema, SubagentSummarySchema, jobStatus, JobSummarySchema, JobOutputSchema, QueuedInputSchema, WithdrawResultSchema, SteerResultSchema, ChatViewSchema, SessionSummarySchema, DirectoryStateSchema, WorkspaceSummarySchema, WorkspaceStateSchema, credentialStatus, CredentialStateSchema, AttachmentSchema, chatInput, NekoSessionDirectory, NekoSessionManagement, resize, inputLimits, modelInfo, NekoModels, imageChunk, NekoSubagent, NekoChat, browse, page, NekoWorkspaces, provider, NekoCredentials, SearchSettingsStateSchema, NekoSearchSettings, contextSource, ContextSettingsStateSchema, nullable = (schema) => Type5.Union([schema, nil]), ContextSettingsPatchSchema, NekoContextSettings, FileCandidatesSchema, NekoWorkspaceFiles, marketSkill, preview, scope, installResult, NekoSkillMarket, ApplicationInfoSchema, NekoApplicationInfo;
|
|
5372
5482
|
var init_contract = __esm(() => {
|
|
5373
5483
|
str = Type5.String();
|
|
5374
5484
|
num = Type5.Number();
|
|
@@ -5464,10 +5574,29 @@ var init_contract = __esm(() => {
|
|
|
5464
5574
|
truncated: bool,
|
|
5465
5575
|
dropped: integer
|
|
5466
5576
|
});
|
|
5577
|
+
QueuedInputSchema = Type5.Object({
|
|
5578
|
+
id: integer,
|
|
5579
|
+
mode: Type5.Enum(["steer", "followUp"]),
|
|
5580
|
+
preview: str,
|
|
5581
|
+
images: integer,
|
|
5582
|
+
skill: Type5.Optional(Type5.Object({ name: str, args: str }))
|
|
5583
|
+
});
|
|
5584
|
+
WithdrawResultSchema = Type5.Object({
|
|
5585
|
+
result: Type5.Enum(["withdrawn", "placed", "settled", "unknown"]),
|
|
5586
|
+
text: Type5.Optional(str),
|
|
5587
|
+
images: Type5.Optional(integer)
|
|
5588
|
+
});
|
|
5589
|
+
SteerResultSchema = Type5.Object({
|
|
5590
|
+
result: Type5.Enum(["steered", "withdrawn", "placed", "settled", "unknown"]),
|
|
5591
|
+
id: Type5.Optional(integer),
|
|
5592
|
+
text: Type5.Optional(str),
|
|
5593
|
+
images: Type5.Optional(integer)
|
|
5594
|
+
});
|
|
5467
5595
|
ChatViewSchema = Type5.Object({
|
|
5468
5596
|
historyBefore: Type5.Optional(Type5.Union([integer, nil])),
|
|
5469
5597
|
agents: Type5.Optional(Type5.Array(SubagentSummarySchema)),
|
|
5470
5598
|
jobs: Type5.Optional(Type5.Array(JobSummarySchema)),
|
|
5599
|
+
queued: Type5.Optional(Type5.Array(QueuedInputSchema)),
|
|
5471
5600
|
rounds: Type5.Optional(Type5.Array(DelegationSchema)),
|
|
5472
5601
|
subagents: Type5.Optional(Type5.Array(DelegationSchema)),
|
|
5473
5602
|
taskUsage: Type5.Optional(usage),
|
|
@@ -5672,6 +5801,8 @@ var init_contract = __esm(() => {
|
|
|
5672
5801
|
whenBusy: Type5.Optional(Type5.Enum(["steer", "followUp"]))
|
|
5673
5802
|
}, { additionalProperties: false }), nil),
|
|
5674
5803
|
abort: rpc(nil, nil),
|
|
5804
|
+
withdraw: rpc(Type5.Object({ id: integer }, { additionalProperties: false }), WithdrawResultSchema),
|
|
5805
|
+
steer: rpc(Type5.Object({ id: integer }, { additionalProperties: false }), SteerResultSchema),
|
|
5675
5806
|
usage: rpc(nil, usage),
|
|
5676
5807
|
skills: rpc(nil, Type5.Array(Type5.Object({ name: str, description: str, location: str, level }))),
|
|
5677
5808
|
jobOutput: rpc(Type5.Object({ jobId: str, since: Type5.Optional(integer) }, { additionalProperties: false }), JobOutputSchema),
|
|
@@ -6168,6 +6299,25 @@ function jobsClient(chat) {
|
|
|
6168
6299
|
}
|
|
6169
6300
|
};
|
|
6170
6301
|
}
|
|
6302
|
+
function queueClient(chat) {
|
|
6303
|
+
const supported = () => chat.view.value?.queued !== undefined;
|
|
6304
|
+
return {
|
|
6305
|
+
get supported() {
|
|
6306
|
+
return supported();
|
|
6307
|
+
},
|
|
6308
|
+
list: () => chat.view.value?.queued ?? [],
|
|
6309
|
+
async steer(id) {
|
|
6310
|
+
if (!supported())
|
|
6311
|
+
throw new Error(QUEUE_UNSUPPORTED);
|
|
6312
|
+
return chat.steer({ id });
|
|
6313
|
+
},
|
|
6314
|
+
async withdraw(id) {
|
|
6315
|
+
if (!supported())
|
|
6316
|
+
throw new Error(QUEUE_UNSUPPORTED);
|
|
6317
|
+
return chat.withdraw({ id });
|
|
6318
|
+
}
|
|
6319
|
+
};
|
|
6320
|
+
}
|
|
6171
6321
|
function createGatewayConnection(link, serverId) {
|
|
6172
6322
|
let protocolMismatch = false;
|
|
6173
6323
|
const linkClosed = new AbortController;
|
|
@@ -6364,7 +6514,7 @@ function deadline(work, signal) {
|
|
|
6364
6514
|
signal?.removeEventListener("abort", abort);
|
|
6365
6515
|
});
|
|
6366
6516
|
}
|
|
6367
|
-
var GatewayIdentityError, JOBS_UNSUPPORTED = "This gateway does not support background jobs. Restart the gateway to enable them.";
|
|
6517
|
+
var GatewayIdentityError, JOBS_UNSUPPORTED = "This gateway does not support background jobs. Restart the gateway to enable them.", QUEUE_UNSUPPORTED = "This gateway does not support queued message controls. Restart the gateway to enable them.";
|
|
6368
6518
|
var init_client_session = __esm(() => {
|
|
6369
6519
|
init_application_version();
|
|
6370
6520
|
init_contract();
|
|
@@ -18578,9 +18728,9 @@ var init_labels = __esm(() => {
|
|
|
18578
18728
|
return shortcutHints(["\u2191\u2193", "Select"], ["Enter", "Open"], ["Esc", "Close"]);
|
|
18579
18729
|
},
|
|
18580
18730
|
idleHints: "Enter Send \xB7 /help Keys",
|
|
18581
|
-
busyHints: "Enter
|
|
18731
|
+
busyHints: "Enter Queue \xB7 Esc Stop",
|
|
18582
18732
|
idleCompact: "Enter Send \xB7 /help Keys",
|
|
18583
|
-
busyCompact: "Enter
|
|
18733
|
+
busyCompact: "Enter Queue \xB7 Esc Stop"
|
|
18584
18734
|
};
|
|
18585
18735
|
});
|
|
18586
18736
|
|
|
@@ -21294,7 +21444,7 @@ function buildHelloResultSchema() {
|
|
|
21294
21444
|
})
|
|
21295
21445
|
});
|
|
21296
21446
|
}
|
|
21297
|
-
var MOBILE_LIMITS, MOBILE_API_VERSIONS, MOBILE_CAPABILITIES, MOBILE_CLOSE_REVOKED = 4401, MOBILE_CLOSE_INCOMPATIBLE = 4402, MOBILE_CLOSE_SLOW_CONSUMER = 4408, MobileHelloParams, opt, str2, int, nullable2 = (schema) => Type7.Union([schema, Type7.Null()]), MobileContentRefSchema, MobileImageRefSchema, MobileToolItemSchema, MobileChatItemSchema, MobileStreamingSchema, MobileUsageSchema, MobileSubagentRoundSchema, MobileAgentSchema, MobileChatStatusSchema, MobileChatSnapshotSchema, MobileWorkspaceSchema, MobileSessionSummarySchema, MobileApprovalSchema, sessionListParams, sessionListResult, subscription, pageResult, pageParams, chunkResult, MOBILE_API_V1_METHODS, patchBody, MOBILE_API_V1_NOTIFICATIONS;
|
|
21447
|
+
var MOBILE_LIMITS, MOBILE_API_VERSIONS, MOBILE_CAPABILITIES, MOBILE_CLOSE_REVOKED = 4401, MOBILE_CLOSE_INCOMPATIBLE = 4402, MOBILE_CLOSE_SLOW_CONSUMER = 4408, MobileHelloParams, opt, str2, int, nullable2 = (schema) => Type7.Union([schema, Type7.Null()]), MobileContentRefSchema, MobileImageRefSchema, MobileToolItemSchema, MobileChatItemSchema, MobileStreamingSchema, MobileUsageSchema, MobileSubagentRoundSchema, MobileAgentSchema, MobileQueuedSchema, MobileChatStatusSchema, MobileChatSnapshotSchema, MobileWorkspaceSchema, MobileSessionSummarySchema, MobileApprovalSchema, sessionListParams, sessionListResult, subscription, pageResult, pageParams, chunkResult, MOBILE_API_V1_METHODS, patchBody, MOBILE_API_V1_NOTIFICATIONS;
|
|
21298
21448
|
var init_protocol = __esm(() => {
|
|
21299
21449
|
init_application_version();
|
|
21300
21450
|
MOBILE_LIMITS = {
|
|
@@ -21426,8 +21576,15 @@ var init_protocol = __esm(() => {
|
|
|
21426
21576
|
roundCount: int,
|
|
21427
21577
|
approvalCount: int
|
|
21428
21578
|
});
|
|
21579
|
+
MobileQueuedSchema = Type7.Object({
|
|
21580
|
+
id: int,
|
|
21581
|
+
mode: Type7.Union([Type7.Literal("steer"), Type7.Literal("followUp")]),
|
|
21582
|
+
preview: Type7.String(),
|
|
21583
|
+
images: int
|
|
21584
|
+
});
|
|
21429
21585
|
MobileChatStatusSchema = Type7.Object({
|
|
21430
21586
|
busy: Type7.Boolean(),
|
|
21587
|
+
queued: opt(Type7.Array(MobileQueuedSchema)),
|
|
21431
21588
|
status: nullable2(str2),
|
|
21432
21589
|
usage: MobileUsageSchema,
|
|
21433
21590
|
taskUsage: opt(MobileUsageSchema),
|
|
@@ -21511,6 +21668,34 @@ var init_protocol = __esm(() => {
|
|
|
21511
21668
|
params: Type7.Object({ ...subscription, requestId: Type7.String({ minLength: 1, maxLength: 128 }) }),
|
|
21512
21669
|
result: Type7.Object({ status: Type7.Union([Type7.Literal("accepted"), Type7.Literal("unknown")]) })
|
|
21513
21670
|
},
|
|
21671
|
+
"chat.steer": {
|
|
21672
|
+
params: Type7.Object({ ...subscription, id: int }),
|
|
21673
|
+
result: Type7.Object({
|
|
21674
|
+
result: Type7.Union([
|
|
21675
|
+
Type7.Literal("steered"),
|
|
21676
|
+
Type7.Literal("withdrawn"),
|
|
21677
|
+
Type7.Literal("placed"),
|
|
21678
|
+
Type7.Literal("settled"),
|
|
21679
|
+
Type7.Literal("unknown")
|
|
21680
|
+
]),
|
|
21681
|
+
id: opt(int),
|
|
21682
|
+
text: opt(Type7.String()),
|
|
21683
|
+
images: opt(int)
|
|
21684
|
+
})
|
|
21685
|
+
},
|
|
21686
|
+
"chat.withdraw": {
|
|
21687
|
+
params: Type7.Object({ ...subscription, id: int }),
|
|
21688
|
+
result: Type7.Object({
|
|
21689
|
+
result: Type7.Union([
|
|
21690
|
+
Type7.Literal("withdrawn"),
|
|
21691
|
+
Type7.Literal("placed"),
|
|
21692
|
+
Type7.Literal("settled"),
|
|
21693
|
+
Type7.Literal("unknown")
|
|
21694
|
+
]),
|
|
21695
|
+
text: opt(Type7.String()),
|
|
21696
|
+
images: opt(int)
|
|
21697
|
+
})
|
|
21698
|
+
},
|
|
21514
21699
|
"chat.abort": { params: Type7.Object(subscription), result: Type7.Object({ accepted: Type7.Boolean() }) },
|
|
21515
21700
|
"subagents.open": {
|
|
21516
21701
|
params: Type7.Object({ ...subscription, agentId: opt(Type7.String({ minLength: 1 })), taskId: opt(int) }),
|
|
@@ -21770,6 +21955,9 @@ function mapStatus(view, options = {}) {
|
|
|
21770
21955
|
const latest = view.compaction?.latest;
|
|
21771
21956
|
return {
|
|
21772
21957
|
busy: view.busy,
|
|
21958
|
+
...view.queued === undefined ? {} : {
|
|
21959
|
+
queued: view.queued.map(({ id, mode, preview, images }) => ({ id, mode, preview, images }))
|
|
21960
|
+
},
|
|
21773
21961
|
status: view.status,
|
|
21774
21962
|
usage: mapUsage(view.usage),
|
|
21775
21963
|
...view.taskUsage === undefined ? {} : { taskUsage: mapUsage(view.taskUsage) },
|
|
@@ -22258,6 +22446,10 @@ class MobileAdapter {
|
|
|
22258
22446
|
return this.chatSubmit(params);
|
|
22259
22447
|
case "chat.submissionStatus":
|
|
22260
22448
|
return this.chatSubmissionStatus(params);
|
|
22449
|
+
case "chat.steer":
|
|
22450
|
+
return this.chatSteer(params);
|
|
22451
|
+
case "chat.withdraw":
|
|
22452
|
+
return this.chatWithdraw(params);
|
|
22261
22453
|
case "chat.abort":
|
|
22262
22454
|
return this.chatAbort(params);
|
|
22263
22455
|
case "subagents.open":
|
|
@@ -22487,6 +22679,16 @@ class MobileAdapter {
|
|
|
22487
22679
|
const accepted = await this.runtime.submissionAccepted(state.sessionId, params.requestId);
|
|
22488
22680
|
return { status: accepted ? "accepted" : "unknown" };
|
|
22489
22681
|
}
|
|
22682
|
+
async chatSteer(params) {
|
|
22683
|
+
const state = this.requireChat(params);
|
|
22684
|
+
this.assertAuthorized();
|
|
22685
|
+
return remote2(() => state.chat.steer({ id: params.id }), "rejected");
|
|
22686
|
+
}
|
|
22687
|
+
async chatWithdraw(params) {
|
|
22688
|
+
const state = this.requireChat(params);
|
|
22689
|
+
this.assertAuthorized();
|
|
22690
|
+
return remote2(() => state.chat.withdraw({ id: params.id }), "rejected");
|
|
22691
|
+
}
|
|
22490
22692
|
async chatAbort(params) {
|
|
22491
22693
|
const state = this.requireChat(params);
|
|
22492
22694
|
this.assertAuthorized();
|
|
@@ -41339,6 +41541,8 @@ function serveSessions(host, runtime, context) {
|
|
|
41339
41541
|
await projection.value.session.abort();
|
|
41340
41542
|
return null;
|
|
41341
41543
|
},
|
|
41544
|
+
withdraw: ({ id }) => projection.value.session.withdraw(id),
|
|
41545
|
+
steer: ({ id }) => projection.value.session.steer(id),
|
|
41342
41546
|
skills: () => runtime.listSkills(projection.value.session.id),
|
|
41343
41547
|
jobOutput: async ({ jobId, since }) => {
|
|
41344
41548
|
try {
|
|
@@ -41416,6 +41620,7 @@ var init_session_host = __esm(() => {
|
|
|
41416
41620
|
agent: { model: null, thinkingLevel: null },
|
|
41417
41621
|
cwd: "",
|
|
41418
41622
|
busy: false,
|
|
41623
|
+
queued: [],
|
|
41419
41624
|
status: null,
|
|
41420
41625
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 },
|
|
41421
41626
|
items: [],
|
|
@@ -42939,8 +43144,7 @@ function helpLines(platform = process.platform) {
|
|
|
42939
43144
|
rows.push(theme.accent(title), ...hints.map(([key, description]) => shortcutHints([key, description])), "");
|
|
42940
43145
|
};
|
|
42941
43146
|
section("Chat", [
|
|
42942
|
-
["Enter", "Send;
|
|
42943
|
-
["Alt+Enter", "Queue while running"],
|
|
43147
|
+
["Enter", "Send; queue while running"],
|
|
42944
43148
|
["Esc", "Stop a running task or blocking compaction"],
|
|
42945
43149
|
["Esc Esc", "Clear draft when idle (press twice quickly)"],
|
|
42946
43150
|
["Up / Down", "Browse previous inputs in this session"],
|
|
@@ -42977,6 +43181,12 @@ function helpLines(platform = process.platform) {
|
|
|
42977
43181
|
["End", "Jump to the newest output"],
|
|
42978
43182
|
["\u2190", "Back"]
|
|
42979
43183
|
]);
|
|
43184
|
+
section("Queue", [
|
|
43185
|
+
["Alt+\u2191", "Select queued messages above the editor"],
|
|
43186
|
+
["\u2191 / \u2193", "Move between queued messages"],
|
|
43187
|
+
["Enter", "Steer the selected message (joins the run after the current tool round)"],
|
|
43188
|
+
["Esc", "Withdraw the selected message into the editor; the run keeps going"]
|
|
43189
|
+
]);
|
|
42980
43190
|
section("Web search", [
|
|
42981
43191
|
["/search", "Choose the web search provider"],
|
|
42982
43192
|
["Enter", "Apply the highlighted provider"]
|
|
@@ -43180,7 +43390,7 @@ function createAppLayout(parts) {
|
|
|
43180
43390
|
parts.approval.height = Math.min(10, Math.max(7, Math.floor(v.height / 2)));
|
|
43181
43391
|
parts.footer.panelOpen = parts.panelOpen();
|
|
43182
43392
|
parts.editor.maxRows = parts.panelOpen() ? 3 : v.height >= 24 ? 7 : 5;
|
|
43183
|
-
parts.panel.height = Math.max(1, v.height - (parts.approvalVisible?.() ? parts.approval?.height ?? 0 : 0) - Math.min(7, Math.max(3, parts.editor.render(v.width).length)) - 2 - Math.min(1, parts.notices.render(v.width).length) - (parts.busyVisible?.() ? Math.min(2, parts.busy?.render(v.width).length ?? 0) : 0));
|
|
43393
|
+
parts.panel.height = Math.max(1, v.height - (parts.approvalVisible?.() ? parts.approval?.height ?? 0 : 0) - Math.min(7, Math.max(3, parts.editor.render(v.width).length)) - 2 - Math.min(1, parts.notices.render(v.width).length) - (parts.busyVisible?.() ? Math.min(2, parts.busy?.render(v.width).length ?? 0) : 0) - (parts.queueVisible?.() ? Math.min(3, parts.queue?.render(v.width).length ?? 0) : 0));
|
|
43184
43394
|
return usableSize(v.width, v.height);
|
|
43185
43395
|
};
|
|
43186
43396
|
return new VStack([
|
|
@@ -43198,6 +43408,12 @@ function createAppLayout(parts) {
|
|
|
43198
43408
|
shrink: 0,
|
|
43199
43409
|
visible: (v) => normal(v) && (parts.busyVisible?.() ?? false)
|
|
43200
43410
|
},
|
|
43411
|
+
{
|
|
43412
|
+
component: parts.queue ?? new Text8("", 0, 0),
|
|
43413
|
+
maxSize: 3,
|
|
43414
|
+
shrink: 0,
|
|
43415
|
+
visible: (v) => normal(v) && (parts.queueVisible?.() ?? false)
|
|
43416
|
+
},
|
|
43201
43417
|
{
|
|
43202
43418
|
component: parts.approval ?? new Text8("", 0, 0),
|
|
43203
43419
|
shrink: 0,
|
|
@@ -43210,6 +43426,105 @@ function createAppLayout(parts) {
|
|
|
43210
43426
|
var usableSize = (width, height) => width >= 40 && height >= 10;
|
|
43211
43427
|
var init_layout = () => {};
|
|
43212
43428
|
|
|
43429
|
+
// packages/tui/src/queue-ui.ts
|
|
43430
|
+
import { matchesKey as matchesKey10, truncateToWidth as truncateToWidth6 } from "@earendil-works/pi-tui";
|
|
43431
|
+
|
|
43432
|
+
class QueueRow {
|
|
43433
|
+
#items = [];
|
|
43434
|
+
#selected;
|
|
43435
|
+
setItems(items) {
|
|
43436
|
+
this.#items = items;
|
|
43437
|
+
if (items.length === 0)
|
|
43438
|
+
this.#selected = undefined;
|
|
43439
|
+
else if (this.#selected !== undefined)
|
|
43440
|
+
this.#selected = Math.min(this.#selected, items.length - 1);
|
|
43441
|
+
}
|
|
43442
|
+
get visible() {
|
|
43443
|
+
return this.#items.length > 0;
|
|
43444
|
+
}
|
|
43445
|
+
get selecting() {
|
|
43446
|
+
return this.#selected !== undefined;
|
|
43447
|
+
}
|
|
43448
|
+
get current() {
|
|
43449
|
+
return this.#selected === undefined ? undefined : this.#items[this.#selected];
|
|
43450
|
+
}
|
|
43451
|
+
select() {
|
|
43452
|
+
if (this.#items.length === 0)
|
|
43453
|
+
return false;
|
|
43454
|
+
this.#selected = this.#items.length - 1;
|
|
43455
|
+
return true;
|
|
43456
|
+
}
|
|
43457
|
+
clear() {
|
|
43458
|
+
this.#selected = undefined;
|
|
43459
|
+
}
|
|
43460
|
+
move(delta) {
|
|
43461
|
+
if (this.#selected === undefined)
|
|
43462
|
+
return;
|
|
43463
|
+
const next = this.#selected + delta;
|
|
43464
|
+
if (next >= this.#items.length)
|
|
43465
|
+
this.#selected = undefined;
|
|
43466
|
+
else
|
|
43467
|
+
this.#selected = Math.max(0, next);
|
|
43468
|
+
}
|
|
43469
|
+
render(width) {
|
|
43470
|
+
const total = this.#items.length;
|
|
43471
|
+
if (total === 0)
|
|
43472
|
+
return [];
|
|
43473
|
+
const end = this.#selected === undefined ? total : Math.max(this.#selected + 1, Math.min(total, QUEUE_ROWS));
|
|
43474
|
+
const start = Math.max(0, end - QUEUE_ROWS);
|
|
43475
|
+
const rows = this.#items.slice(start, end).map((item, offset) => {
|
|
43476
|
+
const picked = start + offset === this.#selected;
|
|
43477
|
+
const text = `${modeLabel(item.mode)} \xB7 ${content2(item)}`;
|
|
43478
|
+
return truncateToWidth6(picked ? ` ${theme.accent(`\u203A ${text}`)}` : ` ${theme.muted(text)}`, width);
|
|
43479
|
+
});
|
|
43480
|
+
const earlier = start > 0 ? `${start} earlier \xB7 ` : "";
|
|
43481
|
+
const later = end < total ? `${total - end} newer \xB7 ` : "";
|
|
43482
|
+
const hint = this.#selected === undefined ? shortcutHints(["Alt+\u2191", "Select queued"]) : shortcutHints(["Enter", "Steer"], ["Esc", "Withdraw"], ["\u2191/\u2193", "Move"]);
|
|
43483
|
+
rows.push(truncateToWidth6(theme.dim(` ${earlier}${later}${hint}`), width));
|
|
43484
|
+
return rows;
|
|
43485
|
+
}
|
|
43486
|
+
invalidate() {}
|
|
43487
|
+
}
|
|
43488
|
+
function queueKeyAction(row, data, autocompleteOpen) {
|
|
43489
|
+
if (!row.selecting)
|
|
43490
|
+
return matchesKey10(data, "alt+up") && row.visible && !autocompleteOpen ? "select" : undefined;
|
|
43491
|
+
if (matchesKey10(data, "up"))
|
|
43492
|
+
return "up";
|
|
43493
|
+
if (matchesKey10(data, "down"))
|
|
43494
|
+
return "down";
|
|
43495
|
+
if (matchesKey10(data, "enter"))
|
|
43496
|
+
return "steer";
|
|
43497
|
+
if (matchesKey10(data, "escape"))
|
|
43498
|
+
return "withdraw";
|
|
43499
|
+
return "leave";
|
|
43500
|
+
}
|
|
43501
|
+
function restoreText(existing, text) {
|
|
43502
|
+
return existing.trim() ? `${existing}
|
|
43503
|
+
${text}` : text;
|
|
43504
|
+
}
|
|
43505
|
+
function steerNotice(outcome) {
|
|
43506
|
+
if (outcome.result === "steered")
|
|
43507
|
+
return { message: "Message will steer the current run.", level: "info" };
|
|
43508
|
+
if (outcome.result === "withdrawn")
|
|
43509
|
+
return { message: "Could not steer; the message was withdrawn into the editor.", level: "warning" };
|
|
43510
|
+
if (outcome.result === "unknown")
|
|
43511
|
+
return { message: "That message is no longer queued.", level: "warning" };
|
|
43512
|
+
return { message: "That message was already sent and cannot be steered.", level: "warning" };
|
|
43513
|
+
}
|
|
43514
|
+
function withdrawNotice(outcome) {
|
|
43515
|
+
if (outcome.result === "withdrawn")
|
|
43516
|
+
return outcome.images ? { message: "Message withdrawn into the editor. Images are not restored; attach them again.", level: "warning" } : { message: "Message withdrawn into the editor.", level: "info" };
|
|
43517
|
+
if (outcome.result === "unknown")
|
|
43518
|
+
return { message: "That message is no longer queued.", level: "warning" };
|
|
43519
|
+
return { message: "That message was already sent and cannot be withdrawn.", level: "warning" };
|
|
43520
|
+
}
|
|
43521
|
+
var QUEUE_ROWS = 2, QUEUE_BLOCK_LINES, modeLabel = (mode) => mode === "steer" ? "Steer" : "Queued", oneLine3 = (text) => text.replace(/\s+/g, " ").trim(), content2 = (item) => oneLine3(item.preview) || (item.images > 0 ? `[${item.images} image${item.images > 1 ? "s" : ""}]` : "");
|
|
43522
|
+
var init_queue_ui = __esm(() => {
|
|
43523
|
+
init_shortcut_hints();
|
|
43524
|
+
init_theme();
|
|
43525
|
+
QUEUE_BLOCK_LINES = QUEUE_ROWS + 1;
|
|
43526
|
+
});
|
|
43527
|
+
|
|
43213
43528
|
// packages/tui/src/search-ui.ts
|
|
43214
43529
|
function searchItems(settings, credentials) {
|
|
43215
43530
|
if (!settings)
|
|
@@ -43258,7 +43573,7 @@ var init_search_ui = __esm(() => {
|
|
|
43258
43573
|
|
|
43259
43574
|
// packages/tui/src/skill-market-ui.ts
|
|
43260
43575
|
import { ChordError as ChordError6 } from "@earendil-works/chord";
|
|
43261
|
-
import { Markdown as Markdown3, matchesKey as
|
|
43576
|
+
import { Markdown as Markdown3, matchesKey as matchesKey11, wrapTextWithAnsi as wrapTextWithAnsi5 } from "@earendil-works/pi-tui";
|
|
43262
43577
|
|
|
43263
43578
|
class SkillDetailView {
|
|
43264
43579
|
#skill = null;
|
|
@@ -43297,11 +43612,11 @@ class SkillDetailView {
|
|
|
43297
43612
|
}
|
|
43298
43613
|
handleKey(data) {
|
|
43299
43614
|
if (this.#confirm) {
|
|
43300
|
-
if (
|
|
43615
|
+
if (matchesKey11(data, "y")) {
|
|
43301
43616
|
const pending = this.#confirm;
|
|
43302
43617
|
this.#confirm = null;
|
|
43303
43618
|
this.run(pending.run);
|
|
43304
|
-
} else if (
|
|
43619
|
+
} else if (matchesKey11(data, "n")) {
|
|
43305
43620
|
this.#confirm = null;
|
|
43306
43621
|
}
|
|
43307
43622
|
return true;
|
|
@@ -43310,17 +43625,17 @@ class SkillDetailView {
|
|
|
43310
43625
|
return true;
|
|
43311
43626
|
const skill = this.#skill;
|
|
43312
43627
|
const builtinOnly = skill.installed.builtin && !skill.installed.user && !skill.installed.project;
|
|
43313
|
-
if (
|
|
43628
|
+
if (matchesKey11(data, "v")) {
|
|
43314
43629
|
this.#openPreview(this.#name);
|
|
43315
43630
|
return true;
|
|
43316
43631
|
}
|
|
43317
43632
|
if (builtinOnly)
|
|
43318
43633
|
return true;
|
|
43319
|
-
if (
|
|
43634
|
+
if (matchesKey11(data, "u"))
|
|
43320
43635
|
this.askInstall("user", skill);
|
|
43321
|
-
else if (
|
|
43636
|
+
else if (matchesKey11(data, "p"))
|
|
43322
43637
|
this.askInstall("project", skill);
|
|
43323
|
-
else if (
|
|
43638
|
+
else if (matchesKey11(data, "d"))
|
|
43324
43639
|
this.askUninstall(skill);
|
|
43325
43640
|
else
|
|
43326
43641
|
return false;
|
|
@@ -43445,13 +43760,13 @@ class SkillPreviewView {
|
|
|
43445
43760
|
this.#offset = Math.max(0, Math.min(this.#maxOffset, this.#offset + delta));
|
|
43446
43761
|
}
|
|
43447
43762
|
handleKey(data) {
|
|
43448
|
-
if (
|
|
43763
|
+
if (matchesKey11(data, "up"))
|
|
43449
43764
|
this.scroll(-1);
|
|
43450
|
-
else if (
|
|
43765
|
+
else if (matchesKey11(data, "down"))
|
|
43451
43766
|
this.scroll(1);
|
|
43452
|
-
else if (
|
|
43767
|
+
else if (matchesKey11(data, "pageUp"))
|
|
43453
43768
|
this.scroll(-this.#pageSize);
|
|
43454
|
-
else if (
|
|
43769
|
+
else if (matchesKey11(data, "pageDown"))
|
|
43455
43770
|
this.scroll(this.#pageSize);
|
|
43456
43771
|
else
|
|
43457
43772
|
return false;
|
|
@@ -43503,7 +43818,7 @@ var init_skill_market_ui = __esm(() => {
|
|
|
43503
43818
|
});
|
|
43504
43819
|
|
|
43505
43820
|
// packages/tui/src/subagents-ui.ts
|
|
43506
|
-
import { matchesKey as
|
|
43821
|
+
import { matchesKey as matchesKey12 } from "@earendil-works/pi-tui";
|
|
43507
43822
|
|
|
43508
43823
|
class SubagentDetail {
|
|
43509
43824
|
get help() {
|
|
@@ -43623,13 +43938,13 @@ class SubagentDetail {
|
|
|
43623
43938
|
this.history();
|
|
43624
43939
|
}
|
|
43625
43940
|
handleKey(data) {
|
|
43626
|
-
if (
|
|
43941
|
+
if (matchesKey12(data, "up")) {
|
|
43627
43942
|
this.scroll(-1);
|
|
43628
|
-
} else if (
|
|
43943
|
+
} else if (matchesKey12(data, "down")) {
|
|
43629
43944
|
this.scroll(1);
|
|
43630
|
-
} else if (
|
|
43945
|
+
} else if (matchesKey12(data, "pageUp")) {
|
|
43631
43946
|
this.scroll(-this.#pageSize);
|
|
43632
|
-
} else if (
|
|
43947
|
+
} else if (matchesKey12(data, "pageDown")) {
|
|
43633
43948
|
this.scroll(this.#pageSize);
|
|
43634
43949
|
} else if (data.toLowerCase() === "e") {
|
|
43635
43950
|
this.#expanded = !this.#expanded;
|
|
@@ -43645,7 +43960,7 @@ class SubagentDetail {
|
|
|
43645
43960
|
help: shortcutHints(["Enter", "Stop"], ["Esc", "Back"]),
|
|
43646
43961
|
lines: () => [theme.warning("Stop this task? Existing changes will be kept.")],
|
|
43647
43962
|
handleKey: (key) => {
|
|
43648
|
-
if (!
|
|
43963
|
+
if (!matchesKey12(key, "enter"))
|
|
43649
43964
|
return false;
|
|
43650
43965
|
this.#service.stop(stopTaskId === undefined ? null : { taskId: stopTaskId }).catch((e) => {
|
|
43651
43966
|
this.#error = String(e);
|
|
@@ -43776,7 +44091,7 @@ var init_subagents_ui = __esm(() => {
|
|
|
43776
44091
|
});
|
|
43777
44092
|
|
|
43778
44093
|
// packages/tui/src/version-ui.ts
|
|
43779
|
-
import { matchesKey as
|
|
44094
|
+
import { matchesKey as matchesKey13, Text as Text9 } from "@earendil-works/pi-tui";
|
|
43780
44095
|
function actionFor(state, installed, runningVersion) {
|
|
43781
44096
|
const action = updateAction({ gateway: state, frontend: runningVersion, installed });
|
|
43782
44097
|
return action === "install" && !newer(state?.latestVersion, runningVersion) ? "none" : action;
|
|
@@ -43854,9 +44169,9 @@ class VersionDetail {
|
|
|
43854
44169
|
return lines.slice(this.#offset, this.#offset + height);
|
|
43855
44170
|
}
|
|
43856
44171
|
handleKey(data) {
|
|
43857
|
-
if (
|
|
44172
|
+
if (matchesKey13(data, "up"))
|
|
43858
44173
|
this.#offset = Math.max(0, this.#offset - 1);
|
|
43859
|
-
else if (
|
|
44174
|
+
else if (matchesKey13(data, "down"))
|
|
43860
44175
|
this.#offset++;
|
|
43861
44176
|
else
|
|
43862
44177
|
return false;
|
|
@@ -43921,7 +44236,7 @@ import {
|
|
|
43921
44236
|
Container as Container6,
|
|
43922
44237
|
isKeyRelease as isKeyRelease5,
|
|
43923
44238
|
Loader,
|
|
43924
|
-
matchesKey as
|
|
44239
|
+
matchesKey as matchesKey14,
|
|
43925
44240
|
ProcessTerminal,
|
|
43926
44241
|
ScrollView,
|
|
43927
44242
|
TuiAltScreen
|
|
@@ -43957,6 +44272,8 @@ class NekoTuiApp {
|
|
|
43957
44272
|
#chat;
|
|
43958
44273
|
#agentsPanel = false;
|
|
43959
44274
|
#jobsPanel = false;
|
|
44275
|
+
#queueBusy = false;
|
|
44276
|
+
#queueRow = new QueueRow;
|
|
43960
44277
|
#searchStop;
|
|
43961
44278
|
#contextStop;
|
|
43962
44279
|
#agentDetails = new Map;
|
|
@@ -44064,10 +44381,10 @@ class NekoTuiApp {
|
|
|
44064
44381
|
this.#ui.addInputListener((data) => {
|
|
44065
44382
|
if (isKeyRelease5(data))
|
|
44066
44383
|
return { consume: true };
|
|
44067
|
-
if (!
|
|
44384
|
+
if (!matchesKey14(data, "escape") || this.#panel.open || this.#login.open || this.#busyText !== undefined || this.#lastView?.compaction?.active.length)
|
|
44068
44385
|
this.#editor.resetEscapeSequence();
|
|
44069
44386
|
if (!usableSize(this.#terminal.columns, this.#terminal.rows)) {
|
|
44070
|
-
if (
|
|
44387
|
+
if (matchesKey14(data, "ctrl+c"))
|
|
44071
44388
|
this.exit();
|
|
44072
44389
|
return { consume: true };
|
|
44073
44390
|
}
|
|
@@ -44078,11 +44395,14 @@ class NekoTuiApp {
|
|
|
44078
44395
|
}
|
|
44079
44396
|
if (this.#sessionOperation)
|
|
44080
44397
|
return { consume: true };
|
|
44081
|
-
|
|
44398
|
+
const queueKey = this.#queueKey(data);
|
|
44399
|
+
if (queueKey)
|
|
44400
|
+
return queueKey;
|
|
44401
|
+
if (matchesKey14(data, "right") && this.#lastView?.subagents?.length && this.#editor.getText() === "" && !this.#editor.isShowingAutocomplete()) {
|
|
44082
44402
|
this.#showAgents();
|
|
44083
44403
|
return { consume: true };
|
|
44084
44404
|
}
|
|
44085
|
-
if (
|
|
44405
|
+
if (matchesKey14(data, process.platform === "win32" ? "alt+v" : "ctrl+v")) {
|
|
44086
44406
|
if (isClipboardShortcut(data))
|
|
44087
44407
|
this.pasteClipboard();
|
|
44088
44408
|
return { consume: true };
|
|
@@ -44099,29 +44419,25 @@ class NekoTuiApp {
|
|
|
44099
44419
|
return { consume: true };
|
|
44100
44420
|
}
|
|
44101
44421
|
}
|
|
44102
|
-
if (
|
|
44422
|
+
if (matchesKey14(data, "escape") && this.#editor.isShowingAutocomplete()) {
|
|
44103
44423
|
this.#editor.resetEscapeSequence();
|
|
44104
44424
|
return;
|
|
44105
44425
|
}
|
|
44106
|
-
if (
|
|
44426
|
+
if (matchesKey14(data, "ctrl+c")) {
|
|
44107
44427
|
if (this.#busyText !== undefined)
|
|
44108
44428
|
this.abort();
|
|
44109
44429
|
else
|
|
44110
44430
|
this.exit();
|
|
44111
44431
|
return { consume: true };
|
|
44112
44432
|
}
|
|
44113
|
-
if (
|
|
44433
|
+
if (matchesKey14(data, "escape") && (this.#busyText !== undefined || this.#lastView?.compaction?.active.some((c) => c.reason === "manual" || c.blocking))) {
|
|
44114
44434
|
this.abort();
|
|
44115
44435
|
return { consume: true };
|
|
44116
44436
|
}
|
|
44117
|
-
if (
|
|
44437
|
+
if (matchesKey14(data, "ctrl+s")) {
|
|
44118
44438
|
this.openSessionsOverlay();
|
|
44119
44439
|
return { consume: true };
|
|
44120
44440
|
}
|
|
44121
|
-
if (this.#busyText !== undefined && matchesKey13(data, "alt+enter")) {
|
|
44122
|
-
this.submitFollowUp();
|
|
44123
|
-
return { consume: true };
|
|
44124
|
-
}
|
|
44125
44441
|
return;
|
|
44126
44442
|
});
|
|
44127
44443
|
}
|
|
@@ -44165,6 +44481,8 @@ class NekoTuiApp {
|
|
|
44165
44481
|
notices,
|
|
44166
44482
|
busy: this.#busyLoader,
|
|
44167
44483
|
busyVisible: () => this.#busyText !== undefined,
|
|
44484
|
+
queue: this.#queueRow,
|
|
44485
|
+
queueVisible: () => this.#queueRow.visible,
|
|
44168
44486
|
panelOpen: () => this.#panel.open || this.#login.open
|
|
44169
44487
|
}));
|
|
44170
44488
|
this.#ui.setFocus(this.#editor);
|
|
@@ -44323,12 +44641,7 @@ class NekoTuiApp {
|
|
|
44323
44641
|
this.addNotice("Configure DeepSeek with /login before sending.", "warning");
|
|
44324
44642
|
return;
|
|
44325
44643
|
}
|
|
44326
|
-
this.sendImages(text
|
|
44327
|
-
}
|
|
44328
|
-
submitFollowUp() {
|
|
44329
|
-
const text = this.#editor.getText();
|
|
44330
|
-
if (text.trim())
|
|
44331
|
-
this.sendImages(text, "followUp");
|
|
44644
|
+
this.sendImages(text);
|
|
44332
44645
|
}
|
|
44333
44646
|
async addImagePaths(paths) {
|
|
44334
44647
|
return paths.map((path) => this.addImage(readImageFile(path, this.#options.cwd ?? process.cwd()), path.split(/[\\/]/).at(-1) ?? "Image")).join(" ");
|
|
@@ -44363,7 +44676,7 @@ class NekoTuiApp {
|
|
|
44363
44676
|
this.#clipboardPending = false;
|
|
44364
44677
|
}
|
|
44365
44678
|
}
|
|
44366
|
-
async sendImages(text
|
|
44679
|
+
async sendImages(text) {
|
|
44367
44680
|
const chat = this.#chat;
|
|
44368
44681
|
const session = this.#sessionId;
|
|
44369
44682
|
if (!chat || this.#sending.has(session))
|
|
@@ -44395,7 +44708,7 @@ class NekoTuiApp {
|
|
|
44395
44708
|
}));
|
|
44396
44709
|
content = content.replaceAll(ref, "");
|
|
44397
44710
|
}
|
|
44398
|
-
await chat.submit({ content: content.trim(), images: ids, requestId
|
|
44711
|
+
await chat.submit({ content: content.trim(), images: ids, requestId });
|
|
44399
44712
|
if (session === this.#sessionId && this.#editor.getText() === before)
|
|
44400
44713
|
this.#editor.setText("");
|
|
44401
44714
|
if (this.#texts.get(session) === before)
|
|
@@ -44471,6 +44784,7 @@ class NekoTuiApp {
|
|
|
44471
44784
|
async switchSession(id) {
|
|
44472
44785
|
this.#approval.close();
|
|
44473
44786
|
this.#chat = undefined;
|
|
44787
|
+
this.#queueRow.setItems([]);
|
|
44474
44788
|
if (this.#jobsPanel && this.#panel.open)
|
|
44475
44789
|
this.#panel.close();
|
|
44476
44790
|
if (this.#sessionId)
|
|
@@ -44675,7 +44989,7 @@ class NekoTuiApp {
|
|
|
44675
44989
|
this.#panel.pointerSelection = true;
|
|
44676
44990
|
this.#panel.emptyText = JOBS_EMPTY;
|
|
44677
44991
|
this.#panel.listKey = (data, value) => {
|
|
44678
|
-
if (
|
|
44992
|
+
if (matchesKey14(data, "left")) {
|
|
44679
44993
|
this.#panel.close();
|
|
44680
44994
|
return true;
|
|
44681
44995
|
}
|
|
@@ -44689,6 +45003,64 @@ class NekoTuiApp {
|
|
|
44689
45003
|
this.#panel.show("Jobs", async () => jobItems(jobs.list()), async (value) => new JobDetail(jobs, value, this.#panel, changed).open());
|
|
44690
45004
|
this.#ui.setFocus(this.#panel);
|
|
44691
45005
|
}
|
|
45006
|
+
#queueKey(data) {
|
|
45007
|
+
const row = this.#queueRow;
|
|
45008
|
+
if (this.#queueBusy && row.selecting)
|
|
45009
|
+
return { consume: true };
|
|
45010
|
+
const action = queueKeyAction(row, data, this.#editor.isShowingAutocomplete());
|
|
45011
|
+
if (action === undefined)
|
|
45012
|
+
return;
|
|
45013
|
+
if (action === "steer" || action === "withdraw")
|
|
45014
|
+
return this.#queueAct(action);
|
|
45015
|
+
if (action === "select")
|
|
45016
|
+
row.select();
|
|
45017
|
+
else if (action === "up")
|
|
45018
|
+
row.move(-1);
|
|
45019
|
+
else if (action === "down")
|
|
45020
|
+
row.move(1);
|
|
45021
|
+
else {
|
|
45022
|
+
row.clear();
|
|
45023
|
+
this.#ui.requestRender();
|
|
45024
|
+
return;
|
|
45025
|
+
}
|
|
45026
|
+
this.#ui.requestRender();
|
|
45027
|
+
return { consume: true };
|
|
45028
|
+
}
|
|
45029
|
+
#queueAct(action) {
|
|
45030
|
+
const chat = this.#chat;
|
|
45031
|
+
const item = this.#queueRow.current;
|
|
45032
|
+
if (!chat || !item)
|
|
45033
|
+
return { consume: true };
|
|
45034
|
+
if (action === "steer" && item.mode === "steer") {
|
|
45035
|
+
this.addNotice("That message already steers the current run.", "info");
|
|
45036
|
+
return { consume: true };
|
|
45037
|
+
}
|
|
45038
|
+
const queue = queueClient(chat);
|
|
45039
|
+
const session = this.#sessionId;
|
|
45040
|
+
this.#queueBusy = true;
|
|
45041
|
+
const restore = (outcome) => {
|
|
45042
|
+
if (outcome.result === "withdrawn")
|
|
45043
|
+
this.#editor.setText(restoreText(this.#editor.getText(), outcome.text ?? ""));
|
|
45044
|
+
};
|
|
45045
|
+
const run = action === "steer" ? queue.steer(item.id).then((outcome) => {
|
|
45046
|
+
if (session !== this.#sessionId)
|
|
45047
|
+
return;
|
|
45048
|
+
restore(outcome);
|
|
45049
|
+
const notice = steerNotice(outcome);
|
|
45050
|
+
this.addNotice(notice.message, notice.level);
|
|
45051
|
+
}) : queue.withdraw(item.id).then((outcome) => {
|
|
45052
|
+
if (session !== this.#sessionId)
|
|
45053
|
+
return;
|
|
45054
|
+
restore(outcome);
|
|
45055
|
+
const notice = withdrawNotice(outcome);
|
|
45056
|
+
this.addNotice(notice.message, notice.level);
|
|
45057
|
+
});
|
|
45058
|
+
run.catch((error) => this.addNotice(messageOf(error), "error")).finally(() => {
|
|
45059
|
+
this.#queueBusy = false;
|
|
45060
|
+
this.#ui.requestRender();
|
|
45061
|
+
});
|
|
45062
|
+
return { consume: true };
|
|
45063
|
+
}
|
|
44692
45064
|
#showSearch() {
|
|
44693
45065
|
if (this.#exitStarted || this.#panel.open || this.#login.open)
|
|
44694
45066
|
return;
|
|
@@ -44767,6 +45139,7 @@ class NekoTuiApp {
|
|
|
44767
45139
|
this.#panel.update(subagentItems(view.subagents ?? [], view.agents));
|
|
44768
45140
|
if (this.#jobsPanel)
|
|
44769
45141
|
this.#panel.update(jobItems(view.jobs ?? []));
|
|
45142
|
+
this.#queueRow.setItems(view.queued ?? []);
|
|
44770
45143
|
for (const identity of view.agents ?? []) {
|
|
44771
45144
|
const detail = this.#agentDetails.get(identity.agentId);
|
|
44772
45145
|
if (detail) {
|
|
@@ -45122,6 +45495,7 @@ var init_tui = __esm(() => {
|
|
|
45122
45495
|
init_jobs_ui();
|
|
45123
45496
|
init_labels();
|
|
45124
45497
|
init_layout();
|
|
45498
|
+
init_queue_ui();
|
|
45125
45499
|
init_search_ui();
|
|
45126
45500
|
init_skill_market_ui();
|
|
45127
45501
|
init_subagents_ui();
|