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/client/index.html
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='26' fill='%23ffb7c5'/%3E%3Ctext x='50' y='70' font-size='58' text-anchor='middle' fill='%23ffffff' font-family='sans-serif' font-weight='bold'%3En%3C/text%3E%3C/svg%3E"
|
|
10
10
|
/>
|
|
11
11
|
<title>neko harness</title>
|
|
12
|
-
<script type="module" crossorigin src="/assets/index-
|
|
13
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
12
|
+
<script type="module" crossorigin src="/assets/index-BqLuRtzq.js"></script>
|
|
13
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BjLs6qQU.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<div id="root"></div>
|
package/dist/gateway.js
CHANGED
|
@@ -17256,6 +17256,50 @@ function savedDefaultImagePrompt(content, value) {
|
|
|
17256
17256
|
import { defineEntry } from "@earendil-works/pi-durable";
|
|
17257
17257
|
var NekoInput = defineEntry("app.neko.input");
|
|
17258
17258
|
|
|
17259
|
+
// packages/core/src/queued.ts
|
|
17260
|
+
var QUEUED_PREVIEW_CHARS = 300;
|
|
17261
|
+
var textOf = (content) => {
|
|
17262
|
+
if (typeof content === "string")
|
|
17263
|
+
return content;
|
|
17264
|
+
if (!Array.isArray(content))
|
|
17265
|
+
return "";
|
|
17266
|
+
return content.flatMap((b) => b && b.type === "text" && typeof b.text === "string" ? [b.text] : []).join("");
|
|
17267
|
+
};
|
|
17268
|
+
var clip = (text) => {
|
|
17269
|
+
const chars = [...text.replace(/\s+/g, " ").trim()];
|
|
17270
|
+
return chars.length > QUEUED_PREVIEW_CHARS ? `${chars.slice(0, QUEUED_PREVIEW_CHARS - 1).join("")}\u2026` : chars.join("");
|
|
17271
|
+
};
|
|
17272
|
+
function queuedUserInput(raw) {
|
|
17273
|
+
const item = raw;
|
|
17274
|
+
if (item.mode !== "steer" && item.mode !== "followUp")
|
|
17275
|
+
return;
|
|
17276
|
+
if (item.entry?.kind !== NekoInput.kind)
|
|
17277
|
+
return;
|
|
17278
|
+
const data = item.entry.data;
|
|
17279
|
+
if (!data || data.jobReport || data.subagentRoundId)
|
|
17280
|
+
return;
|
|
17281
|
+
const defaultPrompt = Array.isArray(item.content) ? savedDefaultImagePrompt(item.content, data.defaultImagePrompt) : undefined;
|
|
17282
|
+
const content = defaultPrompt && Array.isArray(item.content) ? item.content.slice(1) : item.content;
|
|
17283
|
+
const skill = data.skill ? { name: data.skill.name, args: data.skill.args } : undefined;
|
|
17284
|
+
return {
|
|
17285
|
+
id: item.id,
|
|
17286
|
+
mode: item.mode,
|
|
17287
|
+
text: skill ? `/skill:${skill.name}${skill.args ? ` ${skill.args}` : ""}` : textOf(content),
|
|
17288
|
+
images: data.images?.length ?? 0,
|
|
17289
|
+
...skill ? { skill } : {}
|
|
17290
|
+
};
|
|
17291
|
+
}
|
|
17292
|
+
function projectQueued(view) {
|
|
17293
|
+
const items = view.docs["pi.inbox"]?.items ?? [];
|
|
17294
|
+
return items.flatMap((raw) => {
|
|
17295
|
+
const input = queuedUserInput(raw);
|
|
17296
|
+
if (!input)
|
|
17297
|
+
return [];
|
|
17298
|
+
const { text, ...rest } = input;
|
|
17299
|
+
return [{ ...rest, preview: clip(text) }];
|
|
17300
|
+
});
|
|
17301
|
+
}
|
|
17302
|
+
|
|
17259
17303
|
// packages/core/src/workspace.ts
|
|
17260
17304
|
import { accessSync, constants, realpathSync, statSync } from "fs";
|
|
17261
17305
|
import { isAbsolute, resolve as resolve2 } from "path";
|
|
@@ -17576,6 +17620,7 @@ function projectChatView(view, modelLabel, options = {}) {
|
|
|
17576
17620
|
},
|
|
17577
17621
|
cwd: savedWorkspace(agent?.cwd),
|
|
17578
17622
|
busy: live.run !== undefined,
|
|
17623
|
+
queued: projectQueued(view),
|
|
17579
17624
|
status,
|
|
17580
17625
|
usage: {
|
|
17581
17626
|
input: usage.input,
|
|
@@ -17721,6 +17766,7 @@ import {
|
|
|
17721
17766
|
createRegistry,
|
|
17722
17767
|
defineDoc as defineDoc5,
|
|
17723
17768
|
Harness,
|
|
17769
|
+
InboxDoc as InboxDoc2,
|
|
17724
17770
|
LiveDoc as importLiveDoc,
|
|
17725
17771
|
MemoryStorage,
|
|
17726
17772
|
UsageDoc as UsageDoc2,
|
|
@@ -19415,6 +19461,14 @@ var createResourceSnapshots = (load, submission) => {
|
|
|
19415
19461
|
discard(id, requestId) {
|
|
19416
19462
|
conversations.get(id)?.pending.delete(requestId);
|
|
19417
19463
|
},
|
|
19464
|
+
move(id, from, to) {
|
|
19465
|
+
const pending = conversations.get(id)?.pending;
|
|
19466
|
+
const snapshot = pending?.get(from);
|
|
19467
|
+
if (!pending || !snapshot)
|
|
19468
|
+
return;
|
|
19469
|
+
pending.delete(from);
|
|
19470
|
+
pending.set(to, snapshot);
|
|
19471
|
+
},
|
|
19418
19472
|
forget(id) {
|
|
19419
19473
|
conversations.delete(id);
|
|
19420
19474
|
}
|
|
@@ -21065,6 +21119,57 @@ async function createNekoRuntime(options = {}) {
|
|
|
21065
21119
|
},
|
|
21066
21120
|
abort() {
|
|
21067
21121
|
return target.abort(context);
|
|
21122
|
+
},
|
|
21123
|
+
async withdraw(submissionId) {
|
|
21124
|
+
const id = submissionId;
|
|
21125
|
+
const inbox = await harness.snapshot(InboxDoc2, target.id, context);
|
|
21126
|
+
const item = inbox?.items.find((i) => i.id === id);
|
|
21127
|
+
const input = item ? queuedUserInput(item) : undefined;
|
|
21128
|
+
if (item && !input)
|
|
21129
|
+
return { result: "unknown" };
|
|
21130
|
+
const requestId = (await (await harness.submission(id, context))?.status(context))?.requestId;
|
|
21131
|
+
const outcome = await harness.abortSubmission(id, context, target.id);
|
|
21132
|
+
if (outcome !== "aborted") {
|
|
21133
|
+
return { result: outcome === "already_placed" ? "placed" : outcome === "settled" ? "settled" : "unknown" };
|
|
21134
|
+
}
|
|
21135
|
+
if (requestId !== undefined)
|
|
21136
|
+
resourceSnapshots.discard(target.id, requestId);
|
|
21137
|
+
await metadata.reconcile(target.id);
|
|
21138
|
+
return { result: "withdrawn", ...input ? { text: input.text, images: input.images } : {} };
|
|
21139
|
+
},
|
|
21140
|
+
async steer(submissionId) {
|
|
21141
|
+
const id = submissionId;
|
|
21142
|
+
const inbox = await harness.snapshot(InboxDoc2, target.id, context);
|
|
21143
|
+
const item = inbox?.items.find((i) => i.id === id);
|
|
21144
|
+
const input = item ? queuedUserInput(item) : undefined;
|
|
21145
|
+
if (item && (!input || item.mode === "write"))
|
|
21146
|
+
return { result: "unknown" };
|
|
21147
|
+
if (item && input?.mode === "steer")
|
|
21148
|
+
return { result: "steered", id: submissionId };
|
|
21149
|
+
const requestId = (await (await harness.submission(id, context))?.status(context))?.requestId;
|
|
21150
|
+
const outcome = await harness.abortSubmission(id, context, target.id);
|
|
21151
|
+
if (outcome !== "aborted" || !item || !input) {
|
|
21152
|
+
return { result: outcome === "already_placed" ? "placed" : outcome === "settled" ? "settled" : "unknown" };
|
|
21153
|
+
}
|
|
21154
|
+
const steerRequestId = requestId !== undefined ? `steer:${requestId}` : crypto.randomUUID();
|
|
21155
|
+
try {
|
|
21156
|
+
const next = await target.submit({
|
|
21157
|
+
type: "input",
|
|
21158
|
+
content: item.content,
|
|
21159
|
+
...item.entry ? { entry: item.entry } : {},
|
|
21160
|
+
requestId: steerRequestId,
|
|
21161
|
+
whenBusy: "steer"
|
|
21162
|
+
}, context);
|
|
21163
|
+
if (requestId !== undefined)
|
|
21164
|
+
resourceSnapshots.move(target.id, requestId, steerRequestId);
|
|
21165
|
+
await metadata.reconcile(target.id);
|
|
21166
|
+
return { result: "steered", id: next.id };
|
|
21167
|
+
} catch {
|
|
21168
|
+
if (requestId !== undefined)
|
|
21169
|
+
resourceSnapshots.discard(target.id, requestId);
|
|
21170
|
+
await metadata.reconcile(target.id);
|
|
21171
|
+
return { result: "withdrawn", text: input.text, images: input.images };
|
|
21172
|
+
}
|
|
21068
21173
|
}
|
|
21069
21174
|
});
|
|
21070
21175
|
const rootSession = makeSession(conversation);
|
|
@@ -21477,10 +21582,29 @@ var JobOutputSchema = Type5.Object({
|
|
|
21477
21582
|
truncated: bool,
|
|
21478
21583
|
dropped: integer
|
|
21479
21584
|
});
|
|
21585
|
+
var QueuedInputSchema = Type5.Object({
|
|
21586
|
+
id: integer,
|
|
21587
|
+
mode: Type5.Enum(["steer", "followUp"]),
|
|
21588
|
+
preview: str,
|
|
21589
|
+
images: integer,
|
|
21590
|
+
skill: Type5.Optional(Type5.Object({ name: str, args: str }))
|
|
21591
|
+
});
|
|
21592
|
+
var WithdrawResultSchema = Type5.Object({
|
|
21593
|
+
result: Type5.Enum(["withdrawn", "placed", "settled", "unknown"]),
|
|
21594
|
+
text: Type5.Optional(str),
|
|
21595
|
+
images: Type5.Optional(integer)
|
|
21596
|
+
});
|
|
21597
|
+
var SteerResultSchema = Type5.Object({
|
|
21598
|
+
result: Type5.Enum(["steered", "withdrawn", "placed", "settled", "unknown"]),
|
|
21599
|
+
id: Type5.Optional(integer),
|
|
21600
|
+
text: Type5.Optional(str),
|
|
21601
|
+
images: Type5.Optional(integer)
|
|
21602
|
+
});
|
|
21480
21603
|
var ChatViewSchema = Type5.Object({
|
|
21481
21604
|
historyBefore: Type5.Optional(Type5.Union([integer, nil])),
|
|
21482
21605
|
agents: Type5.Optional(Type5.Array(SubagentSummarySchema)),
|
|
21483
21606
|
jobs: Type5.Optional(Type5.Array(JobSummarySchema)),
|
|
21607
|
+
queued: Type5.Optional(Type5.Array(QueuedInputSchema)),
|
|
21484
21608
|
rounds: Type5.Optional(Type5.Array(DelegationSchema)),
|
|
21485
21609
|
subagents: Type5.Optional(Type5.Array(DelegationSchema)),
|
|
21486
21610
|
taskUsage: Type5.Optional(usage),
|
|
@@ -21685,6 +21809,8 @@ var NekoChat = contract("neko.chat", {
|
|
|
21685
21809
|
whenBusy: Type5.Optional(Type5.Enum(["steer", "followUp"]))
|
|
21686
21810
|
}, { additionalProperties: false }), nil),
|
|
21687
21811
|
abort: rpc(nil, nil),
|
|
21812
|
+
withdraw: rpc(Type5.Object({ id: integer }, { additionalProperties: false }), WithdrawResultSchema),
|
|
21813
|
+
steer: rpc(Type5.Object({ id: integer }, { additionalProperties: false }), SteerResultSchema),
|
|
21688
21814
|
usage: rpc(nil, usage),
|
|
21689
21815
|
skills: rpc(nil, Type5.Array(Type5.Object({ name: str, description: str, location: str, level }))),
|
|
21690
21816
|
jobOutput: rpc(Type5.Object({ jobId: str, since: Type5.Optional(integer) }, { additionalProperties: false }), JobOutputSchema),
|
|
@@ -22586,7 +22712,7 @@ function subagentClient(connect) {
|
|
|
22586
22712
|
import { createHash as createHash2 } from "crypto";
|
|
22587
22713
|
|
|
22588
22714
|
// packages/core/src/application-version.ts
|
|
22589
|
-
var RUNNING_VERSION = "0.4.
|
|
22715
|
+
var RUNNING_VERSION = "0.4.4";
|
|
22590
22716
|
var APPLICATION_PROTOCOL = 6;
|
|
22591
22717
|
function stableVersion(value) {
|
|
22592
22718
|
return typeof value === "string" && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(value) && value.split(".").every((n) => Number.isSafeInteger(Number(n)));
|
|
@@ -22765,8 +22891,15 @@ var MobileAgentSchema = Type7.Object({
|
|
|
22765
22891
|
roundCount: int,
|
|
22766
22892
|
approvalCount: int
|
|
22767
22893
|
});
|
|
22894
|
+
var MobileQueuedSchema = Type7.Object({
|
|
22895
|
+
id: int,
|
|
22896
|
+
mode: Type7.Union([Type7.Literal("steer"), Type7.Literal("followUp")]),
|
|
22897
|
+
preview: Type7.String(),
|
|
22898
|
+
images: int
|
|
22899
|
+
});
|
|
22768
22900
|
var MobileChatStatusSchema = Type7.Object({
|
|
22769
22901
|
busy: Type7.Boolean(),
|
|
22902
|
+
queued: opt(Type7.Array(MobileQueuedSchema)),
|
|
22770
22903
|
status: nullable2(str2),
|
|
22771
22904
|
usage: MobileUsageSchema,
|
|
22772
22905
|
taskUsage: opt(MobileUsageSchema),
|
|
@@ -22850,6 +22983,34 @@ var MOBILE_API_V1_METHODS = {
|
|
|
22850
22983
|
params: Type7.Object({ ...subscription, requestId: Type7.String({ minLength: 1, maxLength: 128 }) }),
|
|
22851
22984
|
result: Type7.Object({ status: Type7.Union([Type7.Literal("accepted"), Type7.Literal("unknown")]) })
|
|
22852
22985
|
},
|
|
22986
|
+
"chat.steer": {
|
|
22987
|
+
params: Type7.Object({ ...subscription, id: int }),
|
|
22988
|
+
result: Type7.Object({
|
|
22989
|
+
result: Type7.Union([
|
|
22990
|
+
Type7.Literal("steered"),
|
|
22991
|
+
Type7.Literal("withdrawn"),
|
|
22992
|
+
Type7.Literal("placed"),
|
|
22993
|
+
Type7.Literal("settled"),
|
|
22994
|
+
Type7.Literal("unknown")
|
|
22995
|
+
]),
|
|
22996
|
+
id: opt(int),
|
|
22997
|
+
text: opt(Type7.String()),
|
|
22998
|
+
images: opt(int)
|
|
22999
|
+
})
|
|
23000
|
+
},
|
|
23001
|
+
"chat.withdraw": {
|
|
23002
|
+
params: Type7.Object({ ...subscription, id: int }),
|
|
23003
|
+
result: Type7.Object({
|
|
23004
|
+
result: Type7.Union([
|
|
23005
|
+
Type7.Literal("withdrawn"),
|
|
23006
|
+
Type7.Literal("placed"),
|
|
23007
|
+
Type7.Literal("settled"),
|
|
23008
|
+
Type7.Literal("unknown")
|
|
23009
|
+
]),
|
|
23010
|
+
text: opt(Type7.String()),
|
|
23011
|
+
images: opt(int)
|
|
23012
|
+
})
|
|
23013
|
+
},
|
|
22853
23014
|
"chat.abort": { params: Type7.Object(subscription), result: Type7.Object({ accepted: Type7.Boolean() }) },
|
|
22854
23015
|
"subagents.open": {
|
|
22855
23016
|
params: Type7.Object({ ...subscription, agentId: opt(Type7.String({ minLength: 1 })), taskId: opt(int) }),
|
|
@@ -23137,6 +23298,9 @@ function mapStatus(view, options = {}) {
|
|
|
23137
23298
|
const latest = view.compaction?.latest;
|
|
23138
23299
|
return {
|
|
23139
23300
|
busy: view.busy,
|
|
23301
|
+
...view.queued === undefined ? {} : {
|
|
23302
|
+
queued: view.queued.map(({ id, mode, preview, images }) => ({ id, mode, preview, images }))
|
|
23303
|
+
},
|
|
23140
23304
|
status: view.status,
|
|
23141
23305
|
usage: mapUsage(view.usage),
|
|
23142
23306
|
...view.taskUsage === undefined ? {} : { taskUsage: mapUsage(view.taskUsage) },
|
|
@@ -23623,6 +23787,10 @@ class MobileAdapter {
|
|
|
23623
23787
|
return this.chatSubmit(params);
|
|
23624
23788
|
case "chat.submissionStatus":
|
|
23625
23789
|
return this.chatSubmissionStatus(params);
|
|
23790
|
+
case "chat.steer":
|
|
23791
|
+
return this.chatSteer(params);
|
|
23792
|
+
case "chat.withdraw":
|
|
23793
|
+
return this.chatWithdraw(params);
|
|
23626
23794
|
case "chat.abort":
|
|
23627
23795
|
return this.chatAbort(params);
|
|
23628
23796
|
case "subagents.open":
|
|
@@ -23852,6 +24020,16 @@ class MobileAdapter {
|
|
|
23852
24020
|
const accepted = await this.runtime.submissionAccepted(state.sessionId, params.requestId);
|
|
23853
24021
|
return { status: accepted ? "accepted" : "unknown" };
|
|
23854
24022
|
}
|
|
24023
|
+
async chatSteer(params) {
|
|
24024
|
+
const state = this.requireChat(params);
|
|
24025
|
+
this.assertAuthorized();
|
|
24026
|
+
return remote2(() => state.chat.steer({ id: params.id }), "rejected");
|
|
24027
|
+
}
|
|
24028
|
+
async chatWithdraw(params) {
|
|
24029
|
+
const state = this.requireChat(params);
|
|
24030
|
+
this.assertAuthorized();
|
|
24031
|
+
return remote2(() => state.chat.withdraw({ id: params.id }), "rejected");
|
|
24032
|
+
}
|
|
23855
24033
|
async chatAbort(params) {
|
|
23856
24034
|
const state = this.requireChat(params);
|
|
23857
24035
|
this.assertAuthorized();
|
|
@@ -26109,6 +26287,7 @@ var emptyView = {
|
|
|
26109
26287
|
agent: { model: null, thinkingLevel: null },
|
|
26110
26288
|
cwd: "",
|
|
26111
26289
|
busy: false,
|
|
26290
|
+
queued: [],
|
|
26112
26291
|
status: null,
|
|
26113
26292
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 },
|
|
26114
26293
|
items: [],
|
|
@@ -26376,6 +26555,8 @@ function serveSessions(host, runtime, context) {
|
|
|
26376
26555
|
await projection.value.session.abort();
|
|
26377
26556
|
return null;
|
|
26378
26557
|
},
|
|
26558
|
+
withdraw: ({ id }) => projection.value.session.withdraw(id),
|
|
26559
|
+
steer: ({ id }) => projection.value.session.steer(id),
|
|
26379
26560
|
skills: () => runtime.listSkills(projection.value.session.id),
|
|
26380
26561
|
jobOutput: async ({ jobId, since }) => {
|
|
26381
26562
|
try {
|