neko-harness 0.5.2 → 0.5.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/README.md +10 -2
- package/dist/client/assets/index-39DLU7oz.js +396 -0
- package/dist/client/assets/index-BK4Jb8sP.css +2 -0
- package/dist/client/index.html +2 -2
- package/dist/gateway.js +1949 -1280
- package/dist/neko.js +2296 -1301
- package/package.json +8 -7
- package/dist/client/assets/index-DCZeTvcw.css +0 -2
- package/dist/client/assets/index-PcV-h5ox.js +0 -396
package/dist/gateway.js
CHANGED
|
@@ -16604,6 +16604,47 @@ import { basename as basename4, dirname as dirname9, join as join13 } from "path
|
|
|
16604
16604
|
import { createHost as createHost2 } from "@earendil-works/chord";
|
|
16605
16605
|
import { BACKGROUND_CONTEXT as BACKGROUND_CONTEXT4 } from "@earendil-works/chord/context";
|
|
16606
16606
|
|
|
16607
|
+
// packages/core/src/codemode-mode.ts
|
|
16608
|
+
var CODEMODE_NAME = "codemode";
|
|
16609
|
+
var CODEMODE_MODES = ["off", "on", "only"];
|
|
16610
|
+
var DEFAULT_CODEMODE_MODE = "off";
|
|
16611
|
+
var isCodemodeMode = (value) => typeof value === "string" && CODEMODE_MODES.includes(value);
|
|
16612
|
+
var CODEMODE_LIMITS = {
|
|
16613
|
+
memoryLimitBytes: 256 * 1024 * 1024,
|
|
16614
|
+
maxWorkers: 2,
|
|
16615
|
+
waitMs: 60000
|
|
16616
|
+
};
|
|
16617
|
+
var CODEMODE_VIEW_LIMITS = {
|
|
16618
|
+
maxCalls: 100,
|
|
16619
|
+
argsChars: 200,
|
|
16620
|
+
errorChars: 200
|
|
16621
|
+
};
|
|
16622
|
+
function parseCodemodeMode(value, field = "codemode.mode") {
|
|
16623
|
+
if (!isCodemodeMode(value))
|
|
16624
|
+
throw new Error(`"${field}" must be one of ${CODEMODE_MODES.join(", ")}.`);
|
|
16625
|
+
return value;
|
|
16626
|
+
}
|
|
16627
|
+
function parseCodemodeSettings(value, prefix = "codemode") {
|
|
16628
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
16629
|
+
throw new Error(`"${prefix}" must be an object.`);
|
|
16630
|
+
const { mode, ...rest } = value;
|
|
16631
|
+
const unknown = Object.keys(rest)[0];
|
|
16632
|
+
if (unknown !== undefined)
|
|
16633
|
+
throw new Error(`"${prefix}.${unknown}" is not a known setting.`);
|
|
16634
|
+
return mode === undefined ? {} : { mode: parseCodemodeMode(mode, `${prefix}.mode`) };
|
|
16635
|
+
}
|
|
16636
|
+
function resolveCodemodeSettings(config, saved) {
|
|
16637
|
+
if (isCodemodeMode(saved))
|
|
16638
|
+
return { effective: { mode: saved }, source: "saved" };
|
|
16639
|
+
if (config?.mode !== undefined)
|
|
16640
|
+
return { effective: { mode: config.mode }, source: "config" };
|
|
16641
|
+
return { effective: { mode: DEFAULT_CODEMODE_MODE }, source: "default" };
|
|
16642
|
+
}
|
|
16643
|
+
// packages/core/src/commits.ts
|
|
16644
|
+
function onCommits(session, listener) {
|
|
16645
|
+
const observation = session.observeCommits({ advance: (publication) => listener(publication), end: () => {} });
|
|
16646
|
+
return () => observation.detach();
|
|
16647
|
+
}
|
|
16607
16648
|
// packages/core/src/config.ts
|
|
16608
16649
|
import { existsSync, readFileSync } from "fs";
|
|
16609
16650
|
import { homedir } from "os";
|
|
@@ -16873,6 +16914,10 @@ function validate(config, source) {
|
|
|
16873
16914
|
if (level !== undefined && typeof level !== "string") {
|
|
16874
16915
|
throw new Error(`neko config: ${source}: "thinkingLevel" must be a string.`);
|
|
16875
16916
|
}
|
|
16917
|
+
const maxTurns = config.maxTurns;
|
|
16918
|
+
if (maxTurns !== undefined && !(Number.isSafeInteger(maxTurns) && maxTurns >= 1)) {
|
|
16919
|
+
throw new Error(`neko config: ${source}: "maxTurns" must be an integer of 1 or more.`);
|
|
16920
|
+
}
|
|
16876
16921
|
const storagePath = config.storagePath;
|
|
16877
16922
|
if (storagePath !== undefined && typeof storagePath !== "string") {
|
|
16878
16923
|
throw new Error(`neko config: ${source}: "storagePath" must be a string.`);
|
|
@@ -16934,6 +16979,73 @@ function validate(config, source) {
|
|
|
16934
16979
|
throw new Error(`neko config: ${source}: ${error instanceof Error ? error.message : String(error)}`);
|
|
16935
16980
|
}
|
|
16936
16981
|
}
|
|
16982
|
+
if (config.codemode !== undefined) {
|
|
16983
|
+
try {
|
|
16984
|
+
parseCodemodeSettings(config.codemode);
|
|
16985
|
+
} catch (error) {
|
|
16986
|
+
throw new Error(`neko config: ${source}: ${error instanceof Error ? error.message : String(error)}`);
|
|
16987
|
+
}
|
|
16988
|
+
}
|
|
16989
|
+
}
|
|
16990
|
+
// packages/core/src/conversation-follow.ts
|
|
16991
|
+
import {
|
|
16992
|
+
ConversationTranscript
|
|
16993
|
+
} from "@earendil-works/pi-durable";
|
|
16994
|
+
var PAGE_SIZE = 200;
|
|
16995
|
+
async function followConversation(conversation, context) {
|
|
16996
|
+
const transcript = new ConversationTranscript((query, limit, ctx) => conversation.entries(query, limit, undefined, ctx), { pageSize: PAGE_SIZE });
|
|
16997
|
+
const watch = await conversation.watch(context);
|
|
16998
|
+
const listeners = new Set;
|
|
16999
|
+
let byId;
|
|
17000
|
+
let value;
|
|
17001
|
+
const complete = async (view) => {
|
|
17002
|
+
while (view.items[0]?.kind === "earlier") {
|
|
17003
|
+
const before = view.items;
|
|
17004
|
+
view = await transcript.loadEarlier(context);
|
|
17005
|
+
if (view.items === before)
|
|
17006
|
+
break;
|
|
17007
|
+
}
|
|
17008
|
+
for (let gap = view.items.find((item) => item.kind === "gap");gap; ) {
|
|
17009
|
+
const before = view.items;
|
|
17010
|
+
view = await transcript.fillGap(gap, context);
|
|
17011
|
+
if (view.items === before)
|
|
17012
|
+
break;
|
|
17013
|
+
gap = view.items.find((item) => item.kind === "gap");
|
|
17014
|
+
}
|
|
17015
|
+
const { items, ...rest } = view;
|
|
17016
|
+
byId = undefined;
|
|
17017
|
+
return { ...rest, entries: items.flatMap((item) => item.kind === "entry" ? [item.entry] : []) };
|
|
17018
|
+
};
|
|
17019
|
+
try {
|
|
17020
|
+
value = await complete(transcript.merge(watch.value));
|
|
17021
|
+
} catch (error) {
|
|
17022
|
+
await watch.stop();
|
|
17023
|
+
throw error;
|
|
17024
|
+
}
|
|
17025
|
+
watch.start(async (call) => {
|
|
17026
|
+
if (call.kind !== "value")
|
|
17027
|
+
return;
|
|
17028
|
+
value = await complete(transcript.merge(call.value));
|
|
17029
|
+
for (const listener of listeners)
|
|
17030
|
+
listener(value);
|
|
17031
|
+
});
|
|
17032
|
+
return {
|
|
17033
|
+
get value() {
|
|
17034
|
+
return value;
|
|
17035
|
+
},
|
|
17036
|
+
subscribe(listener) {
|
|
17037
|
+
listeners.add(listener);
|
|
17038
|
+
return () => listeners.delete(listener);
|
|
17039
|
+
},
|
|
17040
|
+
entry(id) {
|
|
17041
|
+
byId ??= new Map(value.entries.map((entry) => [entry.id, entry]));
|
|
17042
|
+
return byId.get(id);
|
|
17043
|
+
},
|
|
17044
|
+
dispose() {
|
|
17045
|
+
listeners.clear();
|
|
17046
|
+
watch.stop();
|
|
17047
|
+
}
|
|
17048
|
+
};
|
|
16937
17049
|
}
|
|
16938
17050
|
// packages/core/src/credentials.ts
|
|
16939
17051
|
import { chmod, mkdir, open, readFile, stat, unlink } from "fs/promises";
|
|
@@ -17146,6 +17258,36 @@ class FileCredentialStore {
|
|
|
17146
17258
|
// packages/core/src/file-changes.ts
|
|
17147
17259
|
import { isAbsolute as isAbsolute2, relative, resolve as resolve3, sep } from "path";
|
|
17148
17260
|
|
|
17261
|
+
// packages/core/src/change-limits.ts
|
|
17262
|
+
var CHANGE_LIMITS = {
|
|
17263
|
+
files: 500,
|
|
17264
|
+
opsPerFile: 50,
|
|
17265
|
+
diffBytes: 2 * 1024 * 1024,
|
|
17266
|
+
opDiffBytes: 64 * 1024,
|
|
17267
|
+
conversations: 64,
|
|
17268
|
+
nestedRecords: 1000
|
|
17269
|
+
};
|
|
17270
|
+
function clipDiff(diff) {
|
|
17271
|
+
if (Buffer.byteLength(diff, "utf8") <= CHANGE_LIMITS.opDiffBytes)
|
|
17272
|
+
return { diff, truncated: false };
|
|
17273
|
+
const lines = diff.split(`
|
|
17274
|
+
`);
|
|
17275
|
+
const kept = [];
|
|
17276
|
+
let bytes = 0;
|
|
17277
|
+
for (const line of lines) {
|
|
17278
|
+
bytes += Buffer.byteLength(line, "utf8") + 1;
|
|
17279
|
+
if (bytes > CHANGE_LIMITS.opDiffBytes)
|
|
17280
|
+
break;
|
|
17281
|
+
kept.push(line);
|
|
17282
|
+
}
|
|
17283
|
+
return { diff: kept.join(`
|
|
17284
|
+
`), truncated: true };
|
|
17285
|
+
}
|
|
17286
|
+
|
|
17287
|
+
// packages/core/src/nested-changes.ts
|
|
17288
|
+
import { defineDoc, wrapTool } from "@earendil-works/pi-durable";
|
|
17289
|
+
import { createEditTool, createWriteTool } from "@earendil-works/pi-durable/tools";
|
|
17290
|
+
|
|
17149
17291
|
// packages/core/src/image-prompt.ts
|
|
17150
17292
|
var DEFAULT_IMAGE_PROMPT = {
|
|
17151
17293
|
version: 2,
|
|
@@ -17310,6 +17452,47 @@ var interactionField = (name, details) => {
|
|
|
17310
17452
|
const interaction = toolInteraction(name, details);
|
|
17311
17453
|
return interaction ? { interaction } : {};
|
|
17312
17454
|
};
|
|
17455
|
+
var clip2 = (text, max) => text.length <= max ? text : `${text.slice(0, max - 1)}\u2026`;
|
|
17456
|
+
function codemodeView(calls, fullOutputPath) {
|
|
17457
|
+
const limit = CODEMODE_VIEW_LIMITS.maxCalls;
|
|
17458
|
+
return { calls: calls.slice(0, limit), omitted: Math.max(0, calls.length - limit), fullOutputPath };
|
|
17459
|
+
}
|
|
17460
|
+
function liveCodemodeView(live, callId) {
|
|
17461
|
+
const slots = (live.nestedTools ?? []).filter((slot) => slot.parentCallId === callId);
|
|
17462
|
+
return codemodeView(slots.map((slot, index) => {
|
|
17463
|
+
const key = /\/c(\d+)$/.exec(slot.callId)?.[1];
|
|
17464
|
+
const summary = slot.summary;
|
|
17465
|
+
return {
|
|
17466
|
+
id: key === undefined ? index + 1 : Number(key),
|
|
17467
|
+
name: slot.name,
|
|
17468
|
+
args: clip2(JSON.stringify(slot.arguments) ?? "", CODEMODE_VIEW_LIMITS.argsChars),
|
|
17469
|
+
status: slot.status !== "done" ? "running" : summary === undefined ? "cancelled" : summary.isError ? "error" : "ok",
|
|
17470
|
+
durationMs: summary?.durationMs ?? null,
|
|
17471
|
+
error: summary?.error === undefined ? null : clip2(summary.error, CODEMODE_VIEW_LIMITS.errorChars)
|
|
17472
|
+
};
|
|
17473
|
+
}), null);
|
|
17474
|
+
}
|
|
17475
|
+
function codemodeResultView(details) {
|
|
17476
|
+
if (!isRecord(details) || !Array.isArray(details.calls))
|
|
17477
|
+
return;
|
|
17478
|
+
const calls = details.calls.flatMap((call) => {
|
|
17479
|
+
if (!isRecord(call) || typeof call.name !== "string")
|
|
17480
|
+
return [];
|
|
17481
|
+
const { id, args, status, durationMs, error } = call;
|
|
17482
|
+
return [
|
|
17483
|
+
{
|
|
17484
|
+
id: typeof id === "number" ? id : 0,
|
|
17485
|
+
name: call.name,
|
|
17486
|
+
args: typeof args === "string" ? clip2(args, CODEMODE_VIEW_LIMITS.argsChars) : "",
|
|
17487
|
+
status: status === "ok" || status === "error" || status === "cancelled" ? status : "running",
|
|
17488
|
+
durationMs: typeof durationMs === "number" ? durationMs : null,
|
|
17489
|
+
error: typeof error === "string" ? clip2(error, CODEMODE_VIEW_LIMITS.errorChars) : null
|
|
17490
|
+
}
|
|
17491
|
+
];
|
|
17492
|
+
});
|
|
17493
|
+
return codemodeView(calls, typeof details.fullOutputPath === "string" ? details.fullOutputPath : null);
|
|
17494
|
+
}
|
|
17495
|
+
var codemodeField = (name, view) => name === CODEMODE_NAME && view ? { codemode: view } : {};
|
|
17313
17496
|
function summarizeToolCall(name, args) {
|
|
17314
17497
|
const record = args ?? {};
|
|
17315
17498
|
switch (name) {
|
|
@@ -17342,6 +17525,12 @@ function summarizeToolCall(name, args) {
|
|
|
17342
17525
|
`)
|
|
17343
17526
|
};
|
|
17344
17527
|
}
|
|
17528
|
+
case "codemode": {
|
|
17529
|
+
const code = typeof record.code === "string" ? record.code : "";
|
|
17530
|
+
const first = code.split(`
|
|
17531
|
+
`).find((line) => line.trim() !== "" && !line.trim().startsWith("// @options")) ?? "";
|
|
17532
|
+
return { args: truncateMiddle(first.trim(), 100), detail: code };
|
|
17533
|
+
}
|
|
17345
17534
|
case "subagent":
|
|
17346
17535
|
return {
|
|
17347
17536
|
args: record.action === "list" ? "List agents" : `${record.agentId ?? record.type}: ${record.title}`,
|
|
@@ -17452,13 +17641,14 @@ function totalUsage(state) {
|
|
|
17452
17641
|
}
|
|
17453
17642
|
return total;
|
|
17454
17643
|
}
|
|
17644
|
+
var RUN_FAILURE_DETAIL_CHARS = 500;
|
|
17455
17645
|
function projectChatView(view, modelLabel, options = {}) {
|
|
17456
17646
|
const live = view.docs["pi.live"] ?? {};
|
|
17457
17647
|
const usage = totalUsage(view.docs["pi.usage"] ?? { models: {}, tools: {} });
|
|
17458
17648
|
const agent = view.docs["pi.agent"];
|
|
17459
17649
|
const agentModel = agent?.model ?? null;
|
|
17460
17650
|
const contextWindow = options.models?.find((m) => `${m.provider}/${m.modelId}` === (agentModel ? `${agentModel.provider}/${agentModel.modelId}` : modelLabel))?.contextWindow ?? 0;
|
|
17461
|
-
const tokens = contextTokens(
|
|
17651
|
+
const tokens = contextTokens(view.entries);
|
|
17462
17652
|
const results = new Map;
|
|
17463
17653
|
for (const entry of view.entries) {
|
|
17464
17654
|
for (const message of entry.model ?? []) {
|
|
@@ -17487,7 +17677,8 @@ function projectChatView(view, modelLabel, options = {}) {
|
|
|
17487
17677
|
diff,
|
|
17488
17678
|
diffAdded: counts?.added ?? null,
|
|
17489
17679
|
diffRemoved: counts?.removed ?? null,
|
|
17490
|
-
...interactionField(message.toolName, message.details)
|
|
17680
|
+
...interactionField(message.toolName, message.details),
|
|
17681
|
+
...codemodeField(message.toolName, codemodeResultView(message.details))
|
|
17491
17682
|
});
|
|
17492
17683
|
}
|
|
17493
17684
|
}
|
|
@@ -17585,7 +17776,8 @@ function projectChatView(view, modelLabel, options = {}) {
|
|
|
17585
17776
|
diffAdded: synthesized?.added ?? null,
|
|
17586
17777
|
diffRemoved: synthesized?.removed ?? null,
|
|
17587
17778
|
diffTruncated: synthesized?.truncated ?? false,
|
|
17588
|
-
...interactionField(block.name, slot?.details)
|
|
17779
|
+
...interactionField(block.name, slot?.details),
|
|
17780
|
+
...codemodeField(block.name, slot?.status === "running" ? liveCodemodeView(live, block.id) : undefined)
|
|
17589
17781
|
});
|
|
17590
17782
|
}
|
|
17591
17783
|
}
|
|
@@ -17608,10 +17800,18 @@ function projectChatView(view, modelLabel, options = {}) {
|
|
|
17608
17800
|
percent: tokens !== null && contextWindow > 0 ? tokens / contextWindow * 100 : null
|
|
17609
17801
|
},
|
|
17610
17802
|
compaction: {
|
|
17611
|
-
active:
|
|
17803
|
+
active: (live.compactions ?? []).map(({ trigger, ...status }) => ({ ...status, reason: trigger })),
|
|
17612
17804
|
latest: options.compaction ?? null,
|
|
17613
|
-
...live.compactionFailure ? {
|
|
17805
|
+
...live.compactionFailure ? {
|
|
17806
|
+
failure: {
|
|
17807
|
+
taskId: live.compactionFailure.taskId,
|
|
17808
|
+
reason: live.compactionFailure.trigger,
|
|
17809
|
+
error: live.compactionFailure.error
|
|
17810
|
+
}
|
|
17811
|
+
} : {}
|
|
17614
17812
|
},
|
|
17813
|
+
...live.run === undefined && live.runFailure ? { runFailure: runFailureView(live.runFailure) } : {},
|
|
17814
|
+
continuable: true,
|
|
17615
17815
|
model: agentModel !== null ? `${agentModel.provider}/${agentModel.modelId}` : modelLabel,
|
|
17616
17816
|
agent: {
|
|
17617
17817
|
model: agentModel,
|
|
@@ -17632,6 +17832,13 @@ function projectChatView(view, modelLabel, options = {}) {
|
|
|
17632
17832
|
streaming: projectStreaming(live)
|
|
17633
17833
|
};
|
|
17634
17834
|
}
|
|
17835
|
+
function runFailureView(failure) {
|
|
17836
|
+
const detail = failure.detail?.replace(/\p{Cc}/gu, " ").trim();
|
|
17837
|
+
return {
|
|
17838
|
+
reason: failure.reason,
|
|
17839
|
+
...detail ? { detail: detail.length > RUN_FAILURE_DETAIL_CHARS ? `${detail.slice(0, RUN_FAILURE_DETAIL_CHARS)}\u2026` : detail } : {}
|
|
17840
|
+
};
|
|
17841
|
+
}
|
|
17635
17842
|
function withArgs(item, name, args) {
|
|
17636
17843
|
const summary = summarizeToolCall(name, args);
|
|
17637
17844
|
const synthesized = name === "write" ? synthesizedWriteDiff(args) : null;
|
|
@@ -17708,14 +17915,15 @@ ${block.text}`;
|
|
|
17708
17915
|
diff: synthesized?.diff ?? null,
|
|
17709
17916
|
diffAdded: synthesized?.added ?? null,
|
|
17710
17917
|
diffRemoved: synthesized?.removed ?? null,
|
|
17711
|
-
diffTruncated: synthesized?.truncated ?? false
|
|
17918
|
+
diffTruncated: synthesized?.truncated ?? false,
|
|
17919
|
+
...codemodeField(block.name, slot?.status === "running" ? liveCodemodeView(live, block.id) : undefined)
|
|
17712
17920
|
});
|
|
17713
17921
|
}
|
|
17714
17922
|
}
|
|
17715
17923
|
return { thinking, text, toolCalls };
|
|
17716
17924
|
}
|
|
17717
17925
|
function contextTokens(entries) {
|
|
17718
|
-
const compacted = entries.reduce((id, entry) => entry.kind === "pi.compaction" ? Math.max(id, entry.id) : id, 0);
|
|
17926
|
+
const compacted = entries.reduce((id, entry) => entry.kind === "pi.compaction" || entry.kind === "pi.reset" ? Math.max(id, entry.id) : id, 0);
|
|
17719
17927
|
for (let i = entries.length - 1;i >= 0; i--) {
|
|
17720
17928
|
const entry = entries[i];
|
|
17721
17929
|
const message = entry.model?.[0];
|
|
@@ -17729,24 +17937,87 @@ function contextTokens(entries) {
|
|
|
17729
17937
|
return null;
|
|
17730
17938
|
}
|
|
17731
17939
|
|
|
17940
|
+
// packages/core/src/nested-changes.ts
|
|
17941
|
+
var NestedChangesDoc = defineDoc({
|
|
17942
|
+
kind: "app.neko.nested-changes",
|
|
17943
|
+
checkpointWhen: () => false,
|
|
17944
|
+
version: 1,
|
|
17945
|
+
scope: "conversation",
|
|
17946
|
+
history: "rewindable",
|
|
17947
|
+
fork: "asOf",
|
|
17948
|
+
initial: () => ({ total: 0, dropped: false, items: [] })
|
|
17949
|
+
});
|
|
17950
|
+
var bytesOf = (items) => items.reduce((sum, item) => sum + Buffer.byteLength(item.diff, "utf8"), 0);
|
|
17951
|
+
function addNestedChange(state, change) {
|
|
17952
|
+
const existing = state.items.findIndex((item) => item.id === change.id);
|
|
17953
|
+
if (existing !== -1)
|
|
17954
|
+
state.items.splice(existing, 1);
|
|
17955
|
+
else
|
|
17956
|
+
state.total += 1;
|
|
17957
|
+
state.items.push(change);
|
|
17958
|
+
let bytes = bytesOf(state.items);
|
|
17959
|
+
while (state.items.length > 1 && (state.items.length > CHANGE_LIMITS.nestedRecords || bytes > CHANGE_LIMITS.diffBytes)) {
|
|
17960
|
+
const evicted = state.items.shift();
|
|
17961
|
+
bytes -= Buffer.byteLength(evicted.diff, "utf8");
|
|
17962
|
+
state.dropped = true;
|
|
17963
|
+
}
|
|
17964
|
+
}
|
|
17965
|
+
function describe2(tool, args, details) {
|
|
17966
|
+
if (tool === "edit") {
|
|
17967
|
+
const raw = editResultDiff(details);
|
|
17968
|
+
if (raw === null)
|
|
17969
|
+
return { diff: "", added: 0, removed: 0, truncated: false };
|
|
17970
|
+
return { ...clipDiff(raw), ...countDiffLines(raw) };
|
|
17971
|
+
}
|
|
17972
|
+
return synthesizedWriteDiff(args) ?? { diff: "", added: 0, removed: 0, truncated: false };
|
|
17973
|
+
}
|
|
17974
|
+
function nestedChangeWraps() {
|
|
17975
|
+
const wrap = (reference, tool) => wrapTool(reference, (inner) => ({
|
|
17976
|
+
...inner,
|
|
17977
|
+
execute: async (args, api, context) => {
|
|
17978
|
+
const result = await inner.execute(args, api, context);
|
|
17979
|
+
const path = args?.path;
|
|
17980
|
+
if (result.isError || typeof path !== "string" || path === "")
|
|
17981
|
+
return result;
|
|
17982
|
+
const task = await api.getTask(api.taskId, context);
|
|
17983
|
+
const input = task?.input;
|
|
17984
|
+
if (input?.kind !== "nested" || typeof input.parentCallId !== "string")
|
|
17985
|
+
return result;
|
|
17986
|
+
const parentCallId = input.parentCallId;
|
|
17987
|
+
const change = {
|
|
17988
|
+
id: api.callId,
|
|
17989
|
+
parentCallId,
|
|
17990
|
+
tool,
|
|
17991
|
+
path,
|
|
17992
|
+
...describe2(tool, args, result.details)
|
|
17993
|
+
};
|
|
17994
|
+
await api.commit(async (tx) => {
|
|
17995
|
+
addNestedChange(await tx.doc(NestedChangesDoc, api.conversationId), change);
|
|
17996
|
+
}, context);
|
|
17997
|
+
return result;
|
|
17998
|
+
}
|
|
17999
|
+
}));
|
|
18000
|
+
return [wrap(createEditTool(), "edit"), wrap(createWriteTool(), "write")];
|
|
18001
|
+
}
|
|
18002
|
+
|
|
17732
18003
|
// packages/core/src/subagents.ts
|
|
18004
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
17733
18005
|
import {
|
|
17734
18006
|
AssistantEntry,
|
|
17735
18007
|
configure,
|
|
17736
|
-
defineDoc as
|
|
18008
|
+
defineDoc as defineDoc4,
|
|
17737
18009
|
defineExtension,
|
|
17738
18010
|
defineTask,
|
|
17739
18011
|
defineTool,
|
|
17740
18012
|
LiveDoc,
|
|
17741
18013
|
UsageDoc
|
|
17742
18014
|
} from "@earendil-works/pi-durable";
|
|
17743
|
-
import {
|
|
17744
|
-
import { Value } from "typebox/value";
|
|
18015
|
+
import { arr, compile, int, lit, nul, num, obj, oneOf, opt, str, union } from "@earendil-works/pi-schema";
|
|
17745
18016
|
|
|
17746
18017
|
// packages/core/src/plan-doc.ts
|
|
17747
|
-
import { defineDoc } from "@earendil-works/pi-durable";
|
|
18018
|
+
import { defineDoc as defineDoc2 } from "@earendil-works/pi-durable";
|
|
17748
18019
|
var PLAN_HISTORY = 5;
|
|
17749
|
-
var PlanDoc =
|
|
18020
|
+
var PlanDoc = defineDoc2({
|
|
17750
18021
|
kind: "app.neko.plan",
|
|
17751
18022
|
checkpointWhen: () => false,
|
|
17752
18023
|
version: 1,
|
|
@@ -17756,6 +18027,198 @@ var PlanDoc = defineDoc({
|
|
|
17756
18027
|
initial: () => ({ mode: "normal", revision: 0, items: [] })
|
|
17757
18028
|
});
|
|
17758
18029
|
var PLAN_CODER_BLOCKED = "Plan mode is read-only: the coder subagent is unavailable. Use explore or plan subagents, or finish the plan first.";
|
|
18030
|
+
var PLAN_REMOVED_TOOLS = ["edit", "write", "job"];
|
|
18031
|
+
var PLAN_INSTRUCTIONS = [
|
|
18032
|
+
"You are in plan mode: research and plan only, and change nothing.",
|
|
18033
|
+
"- Allowed: read, find_files, search_text, web_search, web_extract, todo, ask_user, read-only subagents (explore, plan) and bash limited to read-only commands (listing, searching, git log/diff/status, version checks). Other commands are rejected.",
|
|
18034
|
+
"- Not available: edit, write, job and any command that modifies files, installs packages or starts processes. Do not try to work around this.",
|
|
18035
|
+
"- When you understand the task, call submit_plan once, alone in its turn, with a short title, ordered concrete steps and an optional note (risks, assumptions, verification). The user then approves it or asks for changes.",
|
|
18036
|
+
"- After submit_plan do nothing else. If the user asks for changes, research what is needed and submit a revised plan.",
|
|
18037
|
+
"- Use ask_user only for decisions you cannot settle by reading the code."
|
|
18038
|
+
].join(`
|
|
18039
|
+
`);
|
|
18040
|
+
|
|
18041
|
+
// packages/core/src/agent-change.ts
|
|
18042
|
+
var ONLY_MODE_MAIN_TOOLS = ["todo", "ask_user", "subagent"];
|
|
18043
|
+
var named = (name) => ({ name });
|
|
18044
|
+
function onlyModeTools(plan, role) {
|
|
18045
|
+
return [
|
|
18046
|
+
CODEMODE_NAME,
|
|
18047
|
+
...role === "main" ? [...ONLY_MODE_MAIN_TOOLS, ...plan === "plan" ? ["submit_plan"] : []] : []
|
|
18048
|
+
];
|
|
18049
|
+
}
|
|
18050
|
+
function agentChangeFor({ plan, codemode, role }) {
|
|
18051
|
+
const planning = plan === "plan";
|
|
18052
|
+
return {
|
|
18053
|
+
tools: planning ? { remove: PLAN_REMOVED_TOOLS.map(named) } : null,
|
|
18054
|
+
modelTools: codemode === "only" ? onlyModeTools(plan, role).map(named) : planning ? { add: [named("submit_plan")] } : null,
|
|
18055
|
+
extensions: codemode === "off" ? { remove: [{ name: CODEMODE_NAME }] } : { add: [{ name: CODEMODE_NAME }] },
|
|
18056
|
+
instructions: planning ? PLAN_INSTRUCTIONS : null
|
|
18057
|
+
};
|
|
18058
|
+
}
|
|
18059
|
+
function enabledTools(agent) {
|
|
18060
|
+
const offered = new Set(agent.tools.map((tool) => tool.name));
|
|
18061
|
+
return [...agent.tools, ...agent.callable.filter((tool) => !offered.has(tool.name))];
|
|
18062
|
+
}
|
|
18063
|
+
var agentInPlanMode = (agent) => agent.instructions === PLAN_INSTRUCTIONS;
|
|
18064
|
+
function agentSyncChange(agent, state) {
|
|
18065
|
+
const desired = agentChangeFor(state);
|
|
18066
|
+
const planMismatch = agentInPlanMode(agent) !== (state.plan === "plan");
|
|
18067
|
+
const hasExtension = agent.extensions.some((extension) => extension.name === CODEMODE_NAME);
|
|
18068
|
+
const callable = new Set(agent.callable.map((tool) => tool.name));
|
|
18069
|
+
const offered = agent.tools.map((tool) => tool.name);
|
|
18070
|
+
let codemodeMismatch;
|
|
18071
|
+
if (state.codemode === "off")
|
|
18072
|
+
codemodeMismatch = hasExtension || callable.has(CODEMODE_NAME);
|
|
18073
|
+
else {
|
|
18074
|
+
codemodeMismatch = !hasExtension || !offered.includes(CODEMODE_NAME);
|
|
18075
|
+
if (state.codemode === "only") {
|
|
18076
|
+
const allowed = new Set(onlyModeTools(state.plan, state.role));
|
|
18077
|
+
codemodeMismatch ||= offered.some((name) => !allowed.has(name));
|
|
18078
|
+
}
|
|
18079
|
+
}
|
|
18080
|
+
if (!planMismatch && !codemodeMismatch)
|
|
18081
|
+
return;
|
|
18082
|
+
return {
|
|
18083
|
+
...planMismatch ? { tools: desired.tools, instructions: desired.instructions } : {},
|
|
18084
|
+
modelTools: desired.modelTools,
|
|
18085
|
+
...codemodeMismatch ? { extensions: desired.extensions } : {}
|
|
18086
|
+
};
|
|
18087
|
+
}
|
|
18088
|
+
|
|
18089
|
+
// packages/core/src/codemode.ts
|
|
18090
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
18091
|
+
import { CodemodeSandbox } from "@earendil-works/pi-codemode";
|
|
18092
|
+
import { defineDoc as defineDoc3, wrapTool as wrapTool2 } from "@earendil-works/pi-durable";
|
|
18093
|
+
import { createCodemodeExtension, createCodemodeTool } from "@earendil-works/pi-durable/codemode";
|
|
18094
|
+
var CodemodeSettingsDoc = defineDoc3({
|
|
18095
|
+
kind: "app.neko.codemode-settings",
|
|
18096
|
+
checkpointWhen: () => false,
|
|
18097
|
+
version: 1,
|
|
18098
|
+
scope: "conversation",
|
|
18099
|
+
history: "latest",
|
|
18100
|
+
fork: "initial",
|
|
18101
|
+
initial: () => ({ mode: null })
|
|
18102
|
+
});
|
|
18103
|
+
var CodemodeDoc = defineDoc3({
|
|
18104
|
+
kind: "app.neko.codemode",
|
|
18105
|
+
checkpointWhen: () => false,
|
|
18106
|
+
version: 1,
|
|
18107
|
+
scope: "conversation",
|
|
18108
|
+
history: "rewindable",
|
|
18109
|
+
fork: "asOf",
|
|
18110
|
+
initial: () => ({ mode: "off" })
|
|
18111
|
+
});
|
|
18112
|
+
var SANDBOX_BUSY = "Codemode sandbox is busy: too many scripts are running. Try again shortly.";
|
|
18113
|
+
|
|
18114
|
+
class WorkerLimiter {
|
|
18115
|
+
#max;
|
|
18116
|
+
#waitMs;
|
|
18117
|
+
#tickets = new AsyncLocalStorage;
|
|
18118
|
+
#waiters = [];
|
|
18119
|
+
#running = 0;
|
|
18120
|
+
#reserved = 0;
|
|
18121
|
+
constructor(limits = CODEMODE_LIMITS) {
|
|
18122
|
+
this.#max = limits.maxWorkers;
|
|
18123
|
+
this.#waitMs = limits.waitMs;
|
|
18124
|
+
}
|
|
18125
|
+
get running() {
|
|
18126
|
+
return this.#running;
|
|
18127
|
+
}
|
|
18128
|
+
get waiting() {
|
|
18129
|
+
return this.#waiters.length;
|
|
18130
|
+
}
|
|
18131
|
+
#free() {
|
|
18132
|
+
return this.#running + this.#reserved < this.#max;
|
|
18133
|
+
}
|
|
18134
|
+
#wake() {
|
|
18135
|
+
while (this.#waiters.length > 0 && this.#free()) {
|
|
18136
|
+
this.#reserved += 1;
|
|
18137
|
+
this.#waiters.shift()?.();
|
|
18138
|
+
}
|
|
18139
|
+
}
|
|
18140
|
+
acquireWorker = () => {
|
|
18141
|
+
const ticket = this.#tickets.getStore();
|
|
18142
|
+
if (ticket && !ticket.claimed) {
|
|
18143
|
+
ticket.claimed = true;
|
|
18144
|
+
this.#reserved -= 1;
|
|
18145
|
+
} else if (!this.#free())
|
|
18146
|
+
throw new Error(SANDBOX_BUSY);
|
|
18147
|
+
this.#running += 1;
|
|
18148
|
+
let released = false;
|
|
18149
|
+
return () => {
|
|
18150
|
+
if (released)
|
|
18151
|
+
return;
|
|
18152
|
+
released = true;
|
|
18153
|
+
this.#running -= 1;
|
|
18154
|
+
this.#wake();
|
|
18155
|
+
};
|
|
18156
|
+
};
|
|
18157
|
+
async#admit(signal) {
|
|
18158
|
+
signal?.throwIfAborted();
|
|
18159
|
+
if (this.#waiters.length === 0 && this.#free()) {
|
|
18160
|
+
this.#reserved += 1;
|
|
18161
|
+
return;
|
|
18162
|
+
}
|
|
18163
|
+
await new Promise((resolve, reject) => {
|
|
18164
|
+
let timer;
|
|
18165
|
+
const leave = () => {
|
|
18166
|
+
clearTimeout(timer);
|
|
18167
|
+
signal?.removeEventListener("abort", onAbort);
|
|
18168
|
+
};
|
|
18169
|
+
const grant = () => {
|
|
18170
|
+
leave();
|
|
18171
|
+
resolve();
|
|
18172
|
+
};
|
|
18173
|
+
const drop = (error) => {
|
|
18174
|
+
const index = this.#waiters.indexOf(grant);
|
|
18175
|
+
if (index === -1)
|
|
18176
|
+
return;
|
|
18177
|
+
this.#waiters.splice(index, 1);
|
|
18178
|
+
leave();
|
|
18179
|
+
reject(error);
|
|
18180
|
+
};
|
|
18181
|
+
const onAbort = () => drop(signal?.reason instanceof Error ? signal.reason : new Error("Aborted"));
|
|
18182
|
+
this.#waiters.push(grant);
|
|
18183
|
+
timer = setTimeout(() => drop(new Error(SANDBOX_BUSY)), this.#waitMs);
|
|
18184
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
18185
|
+
});
|
|
18186
|
+
}
|
|
18187
|
+
async run(signal, work) {
|
|
18188
|
+
await this.#admit(signal);
|
|
18189
|
+
const ticket = { claimed: false };
|
|
18190
|
+
try {
|
|
18191
|
+
return await this.#tickets.run(ticket, work);
|
|
18192
|
+
} finally {
|
|
18193
|
+
if (!ticket.claimed) {
|
|
18194
|
+
this.#reserved -= 1;
|
|
18195
|
+
this.#wake();
|
|
18196
|
+
}
|
|
18197
|
+
}
|
|
18198
|
+
}
|
|
18199
|
+
}
|
|
18200
|
+
function createCodemodeRuntime(limits = CODEMODE_LIMITS) {
|
|
18201
|
+
const limiter = new WorkerLimiter(limits);
|
|
18202
|
+
const sandbox = new CodemodeSandbox({
|
|
18203
|
+
memoryLimitBytes: CODEMODE_LIMITS.memoryLimitBytes,
|
|
18204
|
+
acquireWorker: limiter.acquireWorker
|
|
18205
|
+
});
|
|
18206
|
+
const options = { sandbox, models: false };
|
|
18207
|
+
const base = createCodemodeExtension(options);
|
|
18208
|
+
const reference = createCodemodeTool(options);
|
|
18209
|
+
const extension = {
|
|
18210
|
+
...base,
|
|
18211
|
+
wraps: [
|
|
18212
|
+
...base.wraps ?? [],
|
|
18213
|
+
...nestedChangeWraps(),
|
|
18214
|
+
wrapTool2(reference, (tool) => ({
|
|
18215
|
+
...tool,
|
|
18216
|
+
execute: (args, api, context) => limiter.run(context.abortSignal, () => tool.execute(args, api, context))
|
|
18217
|
+
}))
|
|
18218
|
+
]
|
|
18219
|
+
};
|
|
18220
|
+
return { extension, limiter, close: () => sandbox.close() };
|
|
18221
|
+
}
|
|
17759
18222
|
|
|
17760
18223
|
// packages/core/src/subagent-usage.ts
|
|
17761
18224
|
var emptySubagentUsage = () => ({ models: {}, tools: {} });
|
|
@@ -17801,7 +18264,7 @@ function subagentUsageTotals(state) {
|
|
|
17801
18264
|
|
|
17802
18265
|
// packages/core/src/subagents.ts
|
|
17803
18266
|
var agentIdFor = (childId) => `agent-${childId}`;
|
|
17804
|
-
var DelegationsDoc =
|
|
18267
|
+
var DelegationsDoc = defineDoc4({
|
|
17805
18268
|
kind: "app.neko.delegations",
|
|
17806
18269
|
checkpointWhen: () => false,
|
|
17807
18270
|
version: 1,
|
|
@@ -17810,7 +18273,7 @@ var DelegationsDoc = defineDoc2({
|
|
|
17810
18273
|
fork: "initial",
|
|
17811
18274
|
initial: () => ({ items: [] })
|
|
17812
18275
|
});
|
|
17813
|
-
var SubagentsDoc =
|
|
18276
|
+
var SubagentsDoc = defineDoc4({
|
|
17814
18277
|
kind: "app.neko.subagents",
|
|
17815
18278
|
checkpointWhen: () => false,
|
|
17816
18279
|
version: 1,
|
|
@@ -17819,7 +18282,7 @@ var SubagentsDoc = defineDoc2({
|
|
|
17819
18282
|
fork: "initial",
|
|
17820
18283
|
initial: () => ({ items: [] })
|
|
17821
18284
|
});
|
|
17822
|
-
var SubagentDoc =
|
|
18285
|
+
var SubagentDoc = defineDoc4({
|
|
17823
18286
|
kind: "app.neko.subagent",
|
|
17824
18287
|
checkpointWhen: () => false,
|
|
17825
18288
|
version: 1,
|
|
@@ -17828,7 +18291,7 @@ var SubagentDoc = defineDoc2({
|
|
|
17828
18291
|
fork: "initial",
|
|
17829
18292
|
initial: () => ({ role: null, parentId: null })
|
|
17830
18293
|
});
|
|
17831
|
-
var SlotsDoc =
|
|
18294
|
+
var SlotsDoc = defineDoc4({
|
|
17832
18295
|
kind: "app.neko.subagent-slots",
|
|
17833
18296
|
checkpointWhen: () => false,
|
|
17834
18297
|
version: 1,
|
|
@@ -17843,7 +18306,7 @@ var ROLE_PROMPTS = {
|
|
|
17843
18306
|
var SUBAGENT_DELIVERY = " Work from the assigned task, your own prior conversation context and project resources; you cannot see the main conversation. Do not delegate or ask the user directly. Your final message must be a self-contained delivery to the main agent, including evidence, results and limitations. Skills never expand your allowed tools.";
|
|
17844
18307
|
var MAIN_ONLY_TOOLS = new Set(["todo", "ask_user", "submit_plan"]);
|
|
17845
18308
|
var MAIN_ONLY_EXTENSIONS = new Set(["neko-todos", "neko-questions", "neko-plan"]);
|
|
17846
|
-
var READ_TOOLS = new Set(["read", "find_files", "search_text", "web_search", "web_extract"]);
|
|
18309
|
+
var READ_TOOLS = new Set(["read", "find_files", "search_text", "web_search", "web_extract", CODEMODE_NAME]);
|
|
17847
18310
|
async function refreshDelegations(tx, id) {
|
|
17848
18311
|
const doc = await tx.doc(DelegationsDoc, id);
|
|
17849
18312
|
const identities = await tx.doc(SubagentsDoc, id);
|
|
@@ -17935,59 +18398,60 @@ async function acquireSlot(tx, round, cwd) {
|
|
|
17935
18398
|
slots.items.push({ taskId: round.taskId, parentId: round.parentId, cwd, coder: round.role === "coder" });
|
|
17936
18399
|
return true;
|
|
17937
18400
|
}
|
|
17938
|
-
var actionParameters =
|
|
17939
|
-
|
|
17940
|
-
action:
|
|
17941
|
-
type:
|
|
17942
|
-
title:
|
|
17943
|
-
task:
|
|
17944
|
-
}
|
|
17945
|
-
|
|
17946
|
-
action:
|
|
17947
|
-
agentId:
|
|
17948
|
-
title:
|
|
17949
|
-
task:
|
|
17950
|
-
}
|
|
17951
|
-
|
|
17952
|
-
action:
|
|
17953
|
-
cursor:
|
|
17954
|
-
limit:
|
|
17955
|
-
}
|
|
18401
|
+
var actionParameters = union([
|
|
18402
|
+
obj({
|
|
18403
|
+
action: opt(lit("create")),
|
|
18404
|
+
type: oneOf(["explore", "plan", "coder"]),
|
|
18405
|
+
title: str({ minLength: 1, maxLength: 80 }),
|
|
18406
|
+
task: str({ minLength: 1, maxLength: 32768 })
|
|
18407
|
+
}),
|
|
18408
|
+
obj({
|
|
18409
|
+
action: lit("continue"),
|
|
18410
|
+
agentId: str(),
|
|
18411
|
+
title: str({ minLength: 1, maxLength: 80 }),
|
|
18412
|
+
task: str({ minLength: 1, maxLength: 32768 })
|
|
18413
|
+
}),
|
|
18414
|
+
obj({
|
|
18415
|
+
action: lit("list"),
|
|
18416
|
+
cursor: opt(int({ minimum: 0 })),
|
|
18417
|
+
limit: opt(int({ minimum: 1, maximum: 100 }))
|
|
18418
|
+
})
|
|
17956
18419
|
]);
|
|
17957
|
-
var
|
|
17958
|
-
|
|
17959
|
-
|
|
17960
|
-
|
|
17961
|
-
|
|
17962
|
-
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17974
|
-
|
|
17975
|
-
|
|
17976
|
-
|
|
17977
|
-
|
|
17978
|
-
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
18420
|
+
var isActionParameters = compile(actionParameters).check;
|
|
18421
|
+
var parameters = obj({
|
|
18422
|
+
action: opt(StringEnum(["create", "continue", "list"], { description: "Defaults to create." })),
|
|
18423
|
+
type: opt(StringEnum(["explore", "plan", "coder"], { description: "Required for create only." })),
|
|
18424
|
+
agentId: opt(str({ description: "Required for continue only; use an ID returned by create/list." })),
|
|
18425
|
+
title: opt(str({ minLength: 1, maxLength: 80, description: "Required for create/continue." })),
|
|
18426
|
+
task: opt(str({ minLength: 1, maxLength: 32768, description: "Required for create/continue." })),
|
|
18427
|
+
cursor: opt(int({ minimum: 0, description: "List pagination cursor only." })),
|
|
18428
|
+
limit: opt(int({ minimum: 1, maximum: 100, description: "List page size only." }))
|
|
18429
|
+
});
|
|
18430
|
+
var structuredOutputSchema = union([
|
|
18431
|
+
obj({
|
|
18432
|
+
agentId: str(),
|
|
18433
|
+
roundId: int(),
|
|
18434
|
+
status: oneOf(["completed", "failed", "cancelled"]),
|
|
18435
|
+
report: str()
|
|
18436
|
+
}),
|
|
18437
|
+
obj({
|
|
18438
|
+
items: arr(obj({
|
|
18439
|
+
agentId: str(),
|
|
18440
|
+
parentId: int(),
|
|
18441
|
+
childId: int(),
|
|
18442
|
+
role: oneOf(["explore", "plan", "coder"]),
|
|
18443
|
+
title: str(),
|
|
18444
|
+
status: oneOf(["idle", "queued", "running"]),
|
|
18445
|
+
activeRoundId: union([int(), nul()]),
|
|
18446
|
+
lastRoundId: int(),
|
|
18447
|
+
lastReport: opt(union([str(), nul()])),
|
|
18448
|
+
roundCount: int(),
|
|
18449
|
+
taskTitle: str(),
|
|
18450
|
+
approvalCount: int(),
|
|
18451
|
+
createdAt: num()
|
|
18452
|
+
})),
|
|
18453
|
+
next: union([int(), nul()])
|
|
18454
|
+
})
|
|
17991
18455
|
]);
|
|
17992
18456
|
var ADMISSION_POLL_MS = 100;
|
|
17993
18457
|
function pause(runtime, ms) {
|
|
@@ -18131,8 +18595,9 @@ function createSubagentExtension(prepare, discard, guard) {
|
|
|
18131
18595
|
parameters,
|
|
18132
18596
|
structuredOutputSchema,
|
|
18133
18597
|
replay: "safe",
|
|
18598
|
+
callers: ["model"],
|
|
18134
18599
|
execute: async (input, api, context) => {
|
|
18135
|
-
if (!
|
|
18600
|
+
if (!isActionParameters(input))
|
|
18136
18601
|
throw new Error("Invalid subagent arguments. create requires type/title/task; continue requires agentId/title/task; list accepts only cursor/limit. Do not mix fields from different actions.");
|
|
18137
18602
|
const args = input;
|
|
18138
18603
|
if ((await api.snapshot(SubagentDoc, api.conversationId, context))?.role)
|
|
@@ -18181,12 +18646,17 @@ function createSubagentExtension(prepare, discard, guard) {
|
|
|
18181
18646
|
if (!identity) {
|
|
18182
18647
|
const created = child ?? await tx.createConversation({ ownership: { kind: "task", taskId: api.taskId } });
|
|
18183
18648
|
const role = args.action === "continue" ? "explore" : args.type;
|
|
18649
|
+
const codemode = (await tx.doc(CodemodeDoc, api.conversationId)).mode;
|
|
18650
|
+
(await tx.doc(CodemodeDoc, created.id)).mode = codemode;
|
|
18651
|
+
const enabled = enabledTools(agent);
|
|
18184
18652
|
await configure(tx, created.id, {
|
|
18185
18653
|
model: agent.model,
|
|
18186
18654
|
thinkingLevel: agent.thinkingLevel,
|
|
18187
18655
|
cwd: agent.cwd,
|
|
18656
|
+
maxTurns: agent.maxTurns ?? null,
|
|
18188
18657
|
extensions: agent.extensions.filter((e) => e.name !== extension.name && !MAIN_ONLY_EXTENSIONS.has(e.name)),
|
|
18189
|
-
|
|
18658
|
+
modelTools: agentChangeFor({ plan: "normal", codemode, role: "subagent" }).modelTools,
|
|
18659
|
+
tools: enabled.filter((t) => t.name !== "subagent" && t.name !== "job" && !MAIN_ONLY_TOOLS.has(t.name) && (role === "coder" || READ_TOOLS.has(t.name) || role === "explore" && t.name === "bash"))
|
|
18190
18660
|
});
|
|
18191
18661
|
Object.assign(await tx.doc(SubagentDoc, created.id), { role, parentId: api.conversationId });
|
|
18192
18662
|
identity = {
|
|
@@ -18289,9 +18759,10 @@ async function removeMainOnlyTools(harness, ids, context) {
|
|
|
18289
18759
|
if (!(await harness.snapshot(SubagentDoc, id, context))?.role)
|
|
18290
18760
|
continue;
|
|
18291
18761
|
const agent = await (await harness.conversation(id, context)).agent(context);
|
|
18292
|
-
|
|
18762
|
+
const enabled = enabledTools(agent);
|
|
18763
|
+
if (!enabled.some((t) => MAIN_ONLY_TOOLS.has(t.name)))
|
|
18293
18764
|
continue;
|
|
18294
|
-
await harness.commit((tx) => configure(tx, id, { tools:
|
|
18765
|
+
await harness.commit((tx) => configure(tx, id, { tools: enabled.filter((t) => !MAIN_ONLY_TOOLS.has(t.name)) }), context);
|
|
18295
18766
|
}
|
|
18296
18767
|
}
|
|
18297
18768
|
async function installSubagentCoordinator(harness, parents, context) {
|
|
@@ -18327,7 +18798,7 @@ async function installSubagentCoordinator(harness, parents, context) {
|
|
|
18327
18798
|
}, context);
|
|
18328
18799
|
}
|
|
18329
18800
|
}
|
|
18330
|
-
const stop = harness
|
|
18801
|
+
const stop = onCommits(harness, ({ changes }) => {
|
|
18331
18802
|
for (const c of changes)
|
|
18332
18803
|
if (c.type === "document" && c.record.kind === "app.neko.delegations" && c.conversationId !== undefined)
|
|
18333
18804
|
known.add(c.conversationId);
|
|
@@ -18338,13 +18809,6 @@ async function installSubagentCoordinator(harness, parents, context) {
|
|
|
18338
18809
|
}
|
|
18339
18810
|
|
|
18340
18811
|
// packages/core/src/file-changes.ts
|
|
18341
|
-
var CHANGE_LIMITS = {
|
|
18342
|
-
files: 500,
|
|
18343
|
-
opsPerFile: 50,
|
|
18344
|
-
diffBytes: 2 * 1024 * 1024,
|
|
18345
|
-
opDiffBytes: 64 * 1024,
|
|
18346
|
-
conversations: 64
|
|
18347
|
-
};
|
|
18348
18812
|
var MAIN_AGENT = "main";
|
|
18349
18813
|
function normalizeChangePath(raw, cwd, workspace) {
|
|
18350
18814
|
const resolved = raw.startsWith("~") ? raw : resolve3(cwd, raw);
|
|
@@ -18355,22 +18819,6 @@ function normalizeChangePath(raw, cwd, workspace) {
|
|
|
18355
18819
|
}
|
|
18356
18820
|
return { path: resolved.split(sep).join("/"), outside: true };
|
|
18357
18821
|
}
|
|
18358
|
-
function clipDiff(diff) {
|
|
18359
|
-
if (Buffer.byteLength(diff, "utf8") <= CHANGE_LIMITS.opDiffBytes)
|
|
18360
|
-
return { diff, truncated: false };
|
|
18361
|
-
const lines = diff.split(`
|
|
18362
|
-
`);
|
|
18363
|
-
const kept = [];
|
|
18364
|
-
let bytes = 0;
|
|
18365
|
-
for (const line of lines) {
|
|
18366
|
-
bytes += Buffer.byteLength(line, "utf8") + 1;
|
|
18367
|
-
if (bytes > CHANGE_LIMITS.opDiffBytes)
|
|
18368
|
-
break;
|
|
18369
|
-
kept.push(line);
|
|
18370
|
-
}
|
|
18371
|
-
return { diff: kept.join(`
|
|
18372
|
-
`), truncated: true };
|
|
18373
|
-
}
|
|
18374
18822
|
|
|
18375
18823
|
class ConversationChanges {
|
|
18376
18824
|
last = 0;
|
|
@@ -18378,6 +18826,7 @@ class ConversationChanges {
|
|
|
18378
18826
|
truncated = false;
|
|
18379
18827
|
bytes = 0;
|
|
18380
18828
|
files = new Map;
|
|
18829
|
+
#scripts = new Map;
|
|
18381
18830
|
#pending = new Map;
|
|
18382
18831
|
#agent;
|
|
18383
18832
|
#cwd;
|
|
@@ -18391,6 +18840,8 @@ class ConversationChanges {
|
|
|
18391
18840
|
for (const message of entry.model ?? []) {
|
|
18392
18841
|
if (message.role === "assistant") {
|
|
18393
18842
|
for (const block of message.content) {
|
|
18843
|
+
if (block.type === "toolCall" && block.name === CODEMODE_NAME)
|
|
18844
|
+
this.#scripts.set(block.id, entry.id);
|
|
18394
18845
|
if (block.type !== "toolCall" || block.name !== "edit" && block.name !== "write")
|
|
18395
18846
|
continue;
|
|
18396
18847
|
const path = block.arguments?.path;
|
|
@@ -18398,6 +18849,8 @@ class ConversationChanges {
|
|
|
18398
18849
|
this.#pending.set(block.id, { tool: block.name, path, args: block.arguments });
|
|
18399
18850
|
}
|
|
18400
18851
|
} else if (message.role === "toolResult") {
|
|
18852
|
+
if (this.#scripts.has(message.toolCallId))
|
|
18853
|
+
this.#scripts.set(message.toolCallId, entry.id);
|
|
18401
18854
|
const call = this.#pending.get(message.toolCallId);
|
|
18402
18855
|
if (!call)
|
|
18403
18856
|
continue;
|
|
@@ -18409,8 +18862,20 @@ class ConversationChanges {
|
|
|
18409
18862
|
}
|
|
18410
18863
|
this.last = entry.id;
|
|
18411
18864
|
}
|
|
18865
|
+
withNested(nested) {
|
|
18866
|
+
const visible = nested.items.filter((item) => this.#scripts.has(item.parentCallId));
|
|
18867
|
+
const copy = new ConversationChanges(this.#agent, this.#cwd, this.#workspace);
|
|
18868
|
+
copy.last = this.last;
|
|
18869
|
+
copy.total = this.total;
|
|
18870
|
+
copy.truncated = this.truncated || nested.dropped && visible.length > 0;
|
|
18871
|
+
copy.bytes = this.bytes;
|
|
18872
|
+
for (const [path, file] of this.files)
|
|
18873
|
+
copy.files.set(path, { ...file, agents: new Set(file.agents), items: file.items.map((item) => ({ ...item })) });
|
|
18874
|
+
for (const item of visible)
|
|
18875
|
+
copy.#record({ tool: item.tool, path: item.path }, { diff: item.diff, added: item.added, removed: item.removed, truncated: item.truncated }, this.#scripts.get(item.parentCallId));
|
|
18876
|
+
return copy;
|
|
18877
|
+
}
|
|
18412
18878
|
#add(call, details, seq) {
|
|
18413
|
-
const { path, outside } = normalizeChangePath(call.path, this.#cwd, this.#workspace);
|
|
18414
18879
|
let diff = "";
|
|
18415
18880
|
let added = 0;
|
|
18416
18881
|
let removed = 0;
|
|
@@ -18430,6 +18895,11 @@ class ConversationChanges {
|
|
|
18430
18895
|
({ diff, added, removed, truncated } = synthesized);
|
|
18431
18896
|
}
|
|
18432
18897
|
}
|
|
18898
|
+
this.#record(call, { diff, added, removed, truncated }, seq);
|
|
18899
|
+
}
|
|
18900
|
+
#record(call, shown, seq) {
|
|
18901
|
+
const { path, outside } = normalizeChangePath(call.path, this.#cwd, this.#workspace);
|
|
18902
|
+
const { diff, added, removed, truncated } = shown;
|
|
18433
18903
|
this.total++;
|
|
18434
18904
|
let file = this.files.get(path);
|
|
18435
18905
|
if (!file) {
|
|
@@ -18450,7 +18920,7 @@ class ConversationChanges {
|
|
|
18450
18920
|
file.added += added;
|
|
18451
18921
|
file.removed += removed;
|
|
18452
18922
|
file.agents.add(this.#agent);
|
|
18453
|
-
file.lastSeq = seq;
|
|
18923
|
+
file.lastSeq = Math.max(file.lastSeq, seq);
|
|
18454
18924
|
file.items.push({ seq, agent: this.#agent, tool: call.tool, diff, added, removed, truncated });
|
|
18455
18925
|
this.bytes += Buffer.byteLength(diff, "utf8");
|
|
18456
18926
|
if (file.items.length > CHANGE_LIMITS.opsPerFile) {
|
|
@@ -18552,10 +19022,12 @@ class ChangeTracker {
|
|
|
18552
19022
|
let revision = 0;
|
|
18553
19023
|
let truncated = false;
|
|
18554
19024
|
for (const member of await this.#members(rootId)) {
|
|
18555
|
-
const
|
|
18556
|
-
if (!
|
|
19025
|
+
const synced = await this.#sync(member, workspace);
|
|
19026
|
+
if (!synced)
|
|
18557
19027
|
continue;
|
|
18558
|
-
|
|
19028
|
+
const nested = await this.#harness.snapshot(NestedChangesDoc, member.id, this.#context);
|
|
19029
|
+
const state = nested && nested.items.length > 0 ? synced.withNested(nested) : synced;
|
|
19030
|
+
revision += synced.total + (nested?.total ?? 0);
|
|
18559
19031
|
truncated ||= state.truncated;
|
|
18560
19032
|
for (const file of state.files.values()) {
|
|
18561
19033
|
const existing = merged.get(file.path);
|
|
@@ -18960,7 +19432,7 @@ function validatePlanDecision(input) {
|
|
|
18960
19432
|
return { kind: "revise", feedback: text(input.feedback, "feedback", PLAN_LIMITS.feedbackChars) };
|
|
18961
19433
|
}
|
|
18962
19434
|
// packages/core/src/jobs.ts
|
|
18963
|
-
import { defineDoc as
|
|
19435
|
+
import { defineDoc as defineDoc5 } from "@earendil-works/pi-durable";
|
|
18964
19436
|
var JOB_LIMITS = {
|
|
18965
19437
|
maxRunning: 4,
|
|
18966
19438
|
keepTerminal: 20,
|
|
@@ -18974,7 +19446,7 @@ var JOB_LIMITS = {
|
|
|
18974
19446
|
commandBytes: 32 * 1024,
|
|
18975
19447
|
maxTimeoutSeconds: 7 * 24 * 3600
|
|
18976
19448
|
};
|
|
18977
|
-
var JobsDoc =
|
|
19449
|
+
var JobsDoc = defineDoc5({
|
|
18978
19450
|
kind: "app.neko.jobs",
|
|
18979
19451
|
checkpointWhen: () => false,
|
|
18980
19452
|
version: 1,
|
|
@@ -19105,6 +19577,9 @@ var parseFrontmatter = (content) => {
|
|
|
19105
19577
|
return { frontmatter: parsed ?? {}, body };
|
|
19106
19578
|
};
|
|
19107
19579
|
var stripFrontmatter = (content) => extractFrontmatter(content).body;
|
|
19580
|
+
// packages/core/src/run-failure.ts
|
|
19581
|
+
var CONTINUE_BUSY = "CONTINUE_BUSY: The session is running; wait for it to finish.";
|
|
19582
|
+
var CONTINUE_UNAVAILABLE = "CONTINUE_UNAVAILABLE: The last run was answered; there is nothing to continue.";
|
|
19108
19583
|
// packages/core/src/runtime.ts
|
|
19109
19584
|
import { homedir as homedir4 } from "os";
|
|
19110
19585
|
import { join as join5 } from "path";
|
|
@@ -19114,14 +19589,15 @@ import { builtinProviders } from "@earendil-works/pi-ai/providers/all";
|
|
|
19114
19589
|
import { PI_ATTRIBUTION } from "@earendil-works/pi-ai/utils/identity";
|
|
19115
19590
|
import {
|
|
19116
19591
|
AssistantEntry as AssistantEntry2,
|
|
19592
|
+
ConversationBusy,
|
|
19593
|
+
configure as configure3,
|
|
19117
19594
|
createRegistry,
|
|
19118
|
-
defineDoc as
|
|
19595
|
+
defineDoc as defineDoc10,
|
|
19119
19596
|
Harness,
|
|
19120
19597
|
InboxDoc as InboxDoc3,
|
|
19121
19598
|
LiveDoc as importLiveDoc,
|
|
19122
19599
|
MemoryStorage,
|
|
19123
|
-
UsageDoc as UsageDoc2
|
|
19124
|
-
watchEvents
|
|
19600
|
+
UsageDoc as UsageDoc2
|
|
19125
19601
|
} from "@earendil-works/pi-durable";
|
|
19126
19602
|
import { createNodePhotonImages } from "@earendil-works/pi-durable/images/node";
|
|
19127
19603
|
import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
|
|
@@ -19131,7 +19607,7 @@ import { createCodingTools } from "@earendil-works/pi-durable/tools";
|
|
|
19131
19607
|
import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/context";
|
|
19132
19608
|
import { defineExtension as defineExtension2, defineTool as defineTool2 } from "@earendil-works/pi-durable";
|
|
19133
19609
|
import { getOrThrow } from "@earendil-works/pi-durable/env";
|
|
19134
|
-
import {
|
|
19610
|
+
import { bool, int as int2, obj as obj2, opt as opt2, str as str2 } from "@earendil-works/pi-schema";
|
|
19135
19611
|
var SEARCH_LIMITS = {
|
|
19136
19612
|
entries: 1e4,
|
|
19137
19613
|
fileBytes: 2 * 1024 * 1024,
|
|
@@ -19139,8 +19615,8 @@ var SEARCH_LIMITS = {
|
|
|
19139
19615
|
outputBytes: 32 * 1024,
|
|
19140
19616
|
timeoutMs: 1e4
|
|
19141
19617
|
};
|
|
19142
|
-
var path =
|
|
19143
|
-
var limit =
|
|
19618
|
+
var path = opt2(str2({ description: "Directory relative to this conversation's cwd, or absolute path." }));
|
|
19619
|
+
var limit = opt2(int2({ minimum: 1, maximum: 500, description: "Maximum results (default 100)." }));
|
|
19144
19620
|
var text2 = (value) => ({ type: "text", text: value });
|
|
19145
19621
|
async function search(api, context, run) {
|
|
19146
19622
|
if (!api.env)
|
|
@@ -19180,7 +19656,7 @@ ${status}${skipped ? ` Skipped/unreadable files: ${skipped}.` : ""}`)],
|
|
|
19180
19656
|
var FindFiles = defineTool2({
|
|
19181
19657
|
name: "find_files",
|
|
19182
19658
|
description: "Discover files and directories without a shell. query is a literal path/name substring (not a glob). Respects gitignore; returns absolute paths usable by read. A partial result is not a complete absence of matches.",
|
|
19183
|
-
parameters:
|
|
19659
|
+
parameters: obj2({ path, query: opt2(str2()), limit }, { open: true }),
|
|
19184
19660
|
replay: "safe",
|
|
19185
19661
|
execute: (args, api, context) => search(api, context, async (env, ctx) => {
|
|
19186
19662
|
const files = await listing(env, args.path ?? ".", ctx);
|
|
@@ -19206,14 +19682,14 @@ var FindFiles = defineTool2({
|
|
|
19206
19682
|
var SearchText = defineTool2({
|
|
19207
19683
|
name: "search_text",
|
|
19208
19684
|
description: "Search UTF-8 file contents without a shell. pattern and filePattern are literal substrings, not regex/globs. Returns absolute paths, 1-based line numbers and context for read. Binary/large/unreadable files and exhausted budgets are explicitly reported as partial results.",
|
|
19209
|
-
parameters:
|
|
19210
|
-
pattern:
|
|
19685
|
+
parameters: obj2({
|
|
19686
|
+
pattern: str2({ minLength: 1, maxLength: 4096 }),
|
|
19211
19687
|
path,
|
|
19212
|
-
filePattern:
|
|
19213
|
-
caseSensitive:
|
|
19214
|
-
contextLines:
|
|
19688
|
+
filePattern: opt2(str2()),
|
|
19689
|
+
caseSensitive: opt2(bool()),
|
|
19690
|
+
contextLines: opt2(int2({ minimum: 0, maximum: 5 })),
|
|
19215
19691
|
limit
|
|
19216
|
-
}),
|
|
19692
|
+
}, { open: true }),
|
|
19217
19693
|
replay: "safe",
|
|
19218
19694
|
execute: (args, api, context) => search(api, context, async (env, ctx) => {
|
|
19219
19695
|
const files = await listing(env, args.path ?? ".", ctx);
|
|
@@ -19382,7 +19858,7 @@ class ContextPruner {
|
|
|
19382
19858
|
#closed = false;
|
|
19383
19859
|
constructor(options) {
|
|
19384
19860
|
this.#options = options;
|
|
19385
|
-
this.#unsubscribe = options.harness
|
|
19861
|
+
this.#unsubscribe = onCommits(options.harness, ({ changes }) => {
|
|
19386
19862
|
if (!options.settings().enabled)
|
|
19387
19863
|
return;
|
|
19388
19864
|
for (const change of changes) {
|
|
@@ -19490,7 +19966,7 @@ import {
|
|
|
19490
19966
|
defineTask as defineTask2,
|
|
19491
19967
|
defineTool as defineTool3
|
|
19492
19968
|
} from "@earendil-works/pi-durable";
|
|
19493
|
-
import {
|
|
19969
|
+
import { int as int3, lit as lit2, num as num2, obj as obj3, opt as opt3, str as str3, union as union2 } from "@earendil-works/pi-schema";
|
|
19494
19970
|
var plain = (value) => JSON.parse(JSON.stringify(value));
|
|
19495
19971
|
|
|
19496
19972
|
class JobEntry {
|
|
@@ -19547,7 +20023,7 @@ var statusWord = {
|
|
|
19547
20023
|
stopped: "stopped",
|
|
19548
20024
|
lost: "lost"
|
|
19549
20025
|
};
|
|
19550
|
-
var
|
|
20026
|
+
var describe3 = (job) => {
|
|
19551
20027
|
const parts = [statusWord[job.status]];
|
|
19552
20028
|
if (job.exitCode !== null)
|
|
19553
20029
|
parts.push(`exit code ${job.exitCode}`);
|
|
@@ -19562,7 +20038,7 @@ var describe2 = (job) => {
|
|
|
19562
20038
|
function reportText(job, tail) {
|
|
19563
20039
|
const body = reportTail(tail);
|
|
19564
20040
|
return [
|
|
19565
|
-
`[Background job ${job.jobId} "${job.title}" ${
|
|
20041
|
+
`[Background job ${job.jobId} "${job.title}" ${describe3(job)}]`,
|
|
19566
20042
|
`Command: ${job.command}`,
|
|
19567
20043
|
body ? `Last output (use the job tool's output action with jobId "${job.jobId}" for more):
|
|
19568
20044
|
${body}` : "It produced no output."
|
|
@@ -19631,15 +20107,15 @@ var delay = (ms, signal) => new Promise((resolve) => {
|
|
|
19631
20107
|
else
|
|
19632
20108
|
signal?.addEventListener("abort", done, { once: true });
|
|
19633
20109
|
});
|
|
19634
|
-
var action =
|
|
19635
|
-
var parameters2 =
|
|
20110
|
+
var action = union2([lit2("start"), lit2("output"), lit2("stop"), lit2("list")]);
|
|
20111
|
+
var parameters2 = obj3({
|
|
19636
20112
|
action,
|
|
19637
|
-
command:
|
|
19638
|
-
title:
|
|
19639
|
-
timeout:
|
|
19640
|
-
jobId:
|
|
19641
|
-
since:
|
|
19642
|
-
});
|
|
20113
|
+
command: opt3(str3({ description: "start: shell command to run in the session's working directory." })),
|
|
20114
|
+
title: opt3(str3({ description: "start: short label shown in the job list." })),
|
|
20115
|
+
timeout: opt3(num2({ description: "start: optional timeout in seconds; no default timeout." })),
|
|
20116
|
+
jobId: opt3(str3({ description: "output/stop: the job id returned by start or list." })),
|
|
20117
|
+
since: opt3(int3({ description: "output: resume after this offset, as returned by the previous output call." }))
|
|
20118
|
+
}, { open: true });
|
|
19643
20119
|
var stringField = (value, name) => {
|
|
19644
20120
|
if (typeof value !== "string" || !value.trim())
|
|
19645
20121
|
throw new Error(`Invalid job arguments: ${name} must be a nonempty string.`);
|
|
@@ -19772,7 +20248,7 @@ class JobManager {
|
|
|
19772
20248
|
if (kind === "stop") {
|
|
19773
20249
|
const jobId = stringField(args.jobId, "jobId");
|
|
19774
20250
|
const job = await this.stop(io, api.conversationId, jobId, "model", context);
|
|
19775
|
-
return this.#text(`Job ${job.jobId} ${
|
|
20251
|
+
return this.#text(`Job ${job.jobId} ${describe3(job)}.`);
|
|
19776
20252
|
}
|
|
19777
20253
|
if (kind !== "start")
|
|
19778
20254
|
throw new Error("Invalid job arguments: action must be start, output, stop or list.");
|
|
@@ -19800,7 +20276,7 @@ class JobManager {
|
|
|
19800
20276
|
#listText(items) {
|
|
19801
20277
|
if (!items.length)
|
|
19802
20278
|
return "No jobs.";
|
|
19803
|
-
return items.map((job) => `${job.jobId} [${
|
|
20279
|
+
return items.map((job) => `${job.jobId} [${describe3(job)}] "${job.title}" \u2014 ${job.command}`).join(`
|
|
19804
20280
|
`);
|
|
19805
20281
|
}
|
|
19806
20282
|
async start(io, conversationId, cwd, args, context) {
|
|
@@ -19852,7 +20328,7 @@ class JobManager {
|
|
|
19852
20328
|
return this.#render(job, read.text, read.offset, read.dropped);
|
|
19853
20329
|
}
|
|
19854
20330
|
#render(job, text, offset, dropped) {
|
|
19855
|
-
const lines = [`Job ${job.jobId} ${
|
|
20331
|
+
const lines = [`Job ${job.jobId} ${describe3(job)}.`, `Title: ${job.title}`, `Command: ${job.command}`];
|
|
19856
20332
|
if (dropped > 0)
|
|
19857
20333
|
lines.push(`(${dropped} bytes of earlier output were dropped)`);
|
|
19858
20334
|
lines.push(text ? `Output (next offset ${offset}):
|
|
@@ -19926,10 +20402,10 @@ import {
|
|
|
19926
20402
|
hook as hook2,
|
|
19927
20403
|
InboxDoc,
|
|
19928
20404
|
ToolTask as ToolTask2,
|
|
19929
|
-
wrapTool
|
|
20405
|
+
wrapTool as wrapTool3
|
|
19930
20406
|
} from "@earendil-works/pi-durable";
|
|
19931
20407
|
import { createBashTool } from "@earendil-works/pi-durable/tools";
|
|
19932
|
-
import {
|
|
20408
|
+
import { arr as arr3, obj as obj5, opt as opt5, str as str5 } from "@earendil-works/pi-schema";
|
|
19933
20409
|
|
|
19934
20410
|
// packages/core/src/plan-bash.ts
|
|
19935
20411
|
var SAFE_PATTERNS = [
|
|
@@ -20038,13 +20514,14 @@ function isSafeCommand(command) {
|
|
|
20038
20514
|
|
|
20039
20515
|
// packages/core/src/user-questions.ts
|
|
20040
20516
|
import { randomUUID } from "crypto";
|
|
20517
|
+
import { StringEnum as StringEnum2 } from "@earendil-works/pi-ai";
|
|
20041
20518
|
import {
|
|
20042
|
-
defineDoc as
|
|
20519
|
+
defineDoc as defineDoc6,
|
|
20043
20520
|
defineDocFamily,
|
|
20044
20521
|
defineExtension as defineExtension5,
|
|
20045
20522
|
defineTool as defineTool4
|
|
20046
20523
|
} from "@earendil-works/pi-durable";
|
|
20047
|
-
import {
|
|
20524
|
+
import { arr as arr2, bool as bool2, nul as nul2, obj as obj4, opt as opt4, str as str4, union as union3 } from "@earendil-works/pi-schema";
|
|
20048
20525
|
var QuestionDoc = defineDocFamily({
|
|
20049
20526
|
kind: "app.neko.question",
|
|
20050
20527
|
checkpointWhen: () => false,
|
|
@@ -20055,7 +20532,7 @@ var QuestionDoc = defineDocFamily({
|
|
|
20055
20532
|
family: true,
|
|
20056
20533
|
initial: (seed) => seed
|
|
20057
20534
|
});
|
|
20058
|
-
var QuestionsDoc =
|
|
20535
|
+
var QuestionsDoc = defineDoc6({
|
|
20059
20536
|
kind: "app.neko.questions",
|
|
20060
20537
|
checkpointWhen: () => false,
|
|
20061
20538
|
version: 1,
|
|
@@ -20108,7 +20585,7 @@ class UserQuestions {
|
|
|
20108
20585
|
constructor(harness, context) {
|
|
20109
20586
|
this.harness = harness;
|
|
20110
20587
|
this.#context = context;
|
|
20111
|
-
const stop = harness
|
|
20588
|
+
const stop = onCommits(harness, ({ changes }) => {
|
|
20112
20589
|
if (!changes.some((c) => c.type === "task" && (c.value.abortRequested || c.value.state.status === "terminal")))
|
|
20113
20590
|
return;
|
|
20114
20591
|
this.reconcileAll();
|
|
@@ -20214,13 +20691,16 @@ class UserQuestions {
|
|
|
20214
20691
|
if (signal?.aborted)
|
|
20215
20692
|
return onAbort();
|
|
20216
20693
|
watch.closed.then((end) => {
|
|
20217
|
-
if (end.
|
|
20694
|
+
if (end.kind === "stopped")
|
|
20218
20695
|
return;
|
|
20219
|
-
finish(() => reject(signal?.aborted ? signal.reason : end.
|
|
20696
|
+
finish(() => reject(signal?.aborted ? signal.reason : end.kind === "listener_error" || end.kind === "failed" ? end.error : new Error(`Question watch ended: ${end.kind}`)));
|
|
20220
20697
|
});
|
|
20221
20698
|
check(watch.value);
|
|
20222
20699
|
if (!done)
|
|
20223
|
-
watch.start(async (
|
|
20700
|
+
watch.start(async (call) => {
|
|
20701
|
+
if (call.kind === "value")
|
|
20702
|
+
check(call.value);
|
|
20703
|
+
});
|
|
20224
20704
|
});
|
|
20225
20705
|
} finally {
|
|
20226
20706
|
signal?.removeEventListener("abort", onAbort);
|
|
@@ -20274,31 +20754,31 @@ class UserQuestions {
|
|
|
20274
20754
|
}, context);
|
|
20275
20755
|
}
|
|
20276
20756
|
}
|
|
20277
|
-
var optionSchema =
|
|
20278
|
-
id:
|
|
20757
|
+
var optionSchema = obj4({
|
|
20758
|
+
id: str4({
|
|
20279
20759
|
minLength: 1,
|
|
20280
20760
|
maxLength: QUESTION_LIMITS.optionIdChars,
|
|
20281
20761
|
description: "Unique within the question."
|
|
20282
20762
|
}),
|
|
20283
|
-
label:
|
|
20763
|
+
label: str4({
|
|
20284
20764
|
minLength: 1,
|
|
20285
20765
|
maxLength: QUESTION_LIMITS.labelChars,
|
|
20286
20766
|
description: "Short, unique, readable alone."
|
|
20287
20767
|
}),
|
|
20288
|
-
description:
|
|
20289
|
-
recommended:
|
|
20290
|
-
}
|
|
20291
|
-
var parameters3 =
|
|
20292
|
-
question:
|
|
20293
|
-
multiple:
|
|
20294
|
-
options:
|
|
20295
|
-
}
|
|
20296
|
-
var structuredOutputSchema2 =
|
|
20297
|
-
status:
|
|
20298
|
-
optionIds:
|
|
20299
|
-
labels:
|
|
20300
|
-
text:
|
|
20301
|
-
}
|
|
20768
|
+
description: opt4(str4({ maxLength: QUESTION_LIMITS.descriptionChars })),
|
|
20769
|
+
recommended: opt4(bool2({ description: "Your suggested choice; shown as a hint, never preselected." }))
|
|
20770
|
+
});
|
|
20771
|
+
var parameters3 = obj4({
|
|
20772
|
+
question: str4({ minLength: 1, maxLength: QUESTION_LIMITS.questionChars }),
|
|
20773
|
+
multiple: opt4(bool2({ description: "Let the user pick several options; needs at least 2 options. Default false." })),
|
|
20774
|
+
options: opt4(arr2(optionSchema, { maxItems: QUESTION_LIMITS.maxOptions }))
|
|
20775
|
+
});
|
|
20776
|
+
var structuredOutputSchema2 = obj4({
|
|
20777
|
+
status: StringEnum2(["answered", "skipped", "cancelled"]),
|
|
20778
|
+
optionIds: opt4(arr2(str4())),
|
|
20779
|
+
labels: opt4(arr2(str4())),
|
|
20780
|
+
text: opt4(union3([str4(), nul2()]))
|
|
20781
|
+
});
|
|
20302
20782
|
function questionOutput(record) {
|
|
20303
20783
|
if (record.status === "answered" && record.answer) {
|
|
20304
20784
|
const labels = answerLabels(record, record.answer);
|
|
@@ -20377,28 +20857,7 @@ function createAskUserTool(service) {
|
|
|
20377
20857
|
var createQuestionExtension = (service) => defineExtension5({ name: "neko-questions", tools: [createAskUserTool(service)] });
|
|
20378
20858
|
|
|
20379
20859
|
// packages/core/src/plan.ts
|
|
20380
|
-
var PLAN_REMOVED_TOOLS = ["edit", "write", "job"];
|
|
20381
|
-
var PLAN_INSTRUCTIONS = [
|
|
20382
|
-
"You are in plan mode: research and plan only, and change nothing.",
|
|
20383
|
-
"- Allowed: read, find_files, search_text, web_search, web_extract, todo, ask_user, read-only subagents (explore, plan) and bash limited to read-only commands (listing, searching, git log/diff/status, version checks). Other commands are rejected.",
|
|
20384
|
-
"- Not available: edit, write, job and any command that modifies files, installs packages or starts processes. Do not try to work around this.",
|
|
20385
|
-
"- When you understand the task, call submit_plan once, alone in its turn, with a short title, ordered concrete steps and an optional note (risks, assumptions, verification). The user then approves it or asks for changes.",
|
|
20386
|
-
"- After submit_plan do nothing else. If the user asks for changes, research what is needed and submit a revised plan.",
|
|
20387
|
-
"- Use ask_user only for decisions you cannot settle by reading the code."
|
|
20388
|
-
].join(`
|
|
20389
|
-
`);
|
|
20390
20860
|
var PLAN_BUSY = "PLAN_BUSY: Wait for the current run to finish or stop it first.";
|
|
20391
|
-
function planAgentChange(mode) {
|
|
20392
|
-
if (mode === "normal")
|
|
20393
|
-
return { tools: null, modelTools: null, instructions: null };
|
|
20394
|
-
const named = (name) => ({ name });
|
|
20395
|
-
return {
|
|
20396
|
-
tools: { remove: PLAN_REMOVED_TOOLS.map(named) },
|
|
20397
|
-
modelTools: { add: [named("submit_plan")] },
|
|
20398
|
-
instructions: PLAN_INSTRUCTIONS
|
|
20399
|
-
};
|
|
20400
|
-
}
|
|
20401
|
-
var agentInPlanMode = (agent) => agent.instructions === PLAN_INSTRUCTIONS;
|
|
20402
20861
|
var clone2 = (value) => JSON.parse(JSON.stringify(value));
|
|
20403
20862
|
var toRecord = ({ taskId: _taskId, dispatched: _dispatched, ...record }) => clone2(record);
|
|
20404
20863
|
function settle2(state, item, status) {
|
|
@@ -20491,22 +20950,24 @@ class PlanService {
|
|
|
20491
20950
|
return toRecord(item);
|
|
20492
20951
|
}, context);
|
|
20493
20952
|
}
|
|
20494
|
-
async
|
|
20953
|
+
async decideWith(id, version, decision, act) {
|
|
20495
20954
|
return this.harness.commit(async (tx) => {
|
|
20496
20955
|
const state = await tx.doc(PlanDoc, id);
|
|
20497
20956
|
const item = state.items.find((i) => i.version === version);
|
|
20498
20957
|
if (!item)
|
|
20499
20958
|
throw new Error("Plan not found.");
|
|
20500
|
-
if (item.status
|
|
20501
|
-
|
|
20502
|
-
|
|
20503
|
-
|
|
20504
|
-
|
|
20505
|
-
|
|
20506
|
-
|
|
20507
|
-
|
|
20959
|
+
if (item.status !== "awaiting_approval")
|
|
20960
|
+
return toRecord(item);
|
|
20961
|
+
await act(tx);
|
|
20962
|
+
if (decision.kind === "approve") {
|
|
20963
|
+
settle2(state, item, "approved");
|
|
20964
|
+
state.mode = "normal";
|
|
20965
|
+
} else {
|
|
20966
|
+
settle2(state, item, "revision_requested");
|
|
20967
|
+
item.feedback = decision.feedback;
|
|
20508
20968
|
}
|
|
20509
|
-
|
|
20969
|
+
item.dispatched = true;
|
|
20970
|
+
return toRecord(item);
|
|
20510
20971
|
}, this.#context);
|
|
20511
20972
|
}
|
|
20512
20973
|
async supersedePending(id) {
|
|
@@ -20557,15 +21018,15 @@ function planRevisionPrompt(plan, feedback) {
|
|
|
20557
21018
|
].join(`
|
|
20558
21019
|
`);
|
|
20559
21020
|
}
|
|
20560
|
-
var parameters4 =
|
|
20561
|
-
title:
|
|
20562
|
-
steps:
|
|
21021
|
+
var parameters4 = obj5({
|
|
21022
|
+
title: str5({ minLength: 1, maxLength: PLAN_LIMITS.titleChars, description: "Short name of the plan." }),
|
|
21023
|
+
steps: arr3(str5({ minLength: 1, maxLength: PLAN_LIMITS.stepChars }), {
|
|
20563
21024
|
minItems: 1,
|
|
20564
21025
|
maxItems: PLAN_LIMITS.maxSteps,
|
|
20565
21026
|
description: "Ordered, concrete implementation steps."
|
|
20566
21027
|
}),
|
|
20567
|
-
note:
|
|
20568
|
-
}
|
|
21028
|
+
note: opt5(str5({ maxLength: PLAN_LIMITS.noteChars, description: "Risks, assumptions and how to verify." }))
|
|
21029
|
+
});
|
|
20569
21030
|
function submitPlanTool(service) {
|
|
20570
21031
|
return defineTool5({
|
|
20571
21032
|
name: "submit_plan",
|
|
@@ -20634,7 +21095,7 @@ var createPlanExtension = (service) => defineExtension6({
|
|
|
20634
21095
|
})
|
|
20635
21096
|
],
|
|
20636
21097
|
wraps: [
|
|
20637
|
-
|
|
21098
|
+
wrapTool3(createBashTool(), (bash) => ({
|
|
20638
21099
|
...bash,
|
|
20639
21100
|
execute: async (args, api, context) => {
|
|
20640
21101
|
if ((await api.snapshot(PlanDoc, api.conversationId, context))?.mode === "plan" && !isSafeCommand(args.command))
|
|
@@ -20786,6 +21247,9 @@ import { defineExtension as defineExtension7, section } from "@earendil-works/pi
|
|
|
20786
21247
|
var KEYS = ["preamble", "rules", "project_context", "skills", "cwd"];
|
|
20787
21248
|
var PREAMBLE = "You are an expert coding assistant operating inside neko, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.";
|
|
20788
21249
|
var TOOL_GUIDELINES = {
|
|
21250
|
+
codemode: [
|
|
21251
|
+
"Use codemode to batch independent tool calls (Promise.allSettled), chain them, or filter large output, instead of many separate calls."
|
|
21252
|
+
],
|
|
20789
21253
|
subagent: [
|
|
20790
21254
|
"Delegate only independent, sufficiently scoped work when isolation or parallelism helps. Handle simple tasks directly. Pass necessary context and user constraints; research-only requests must not become coding tasks. For related follow-up work, list and continue a suitable idle subagent using its stable agentId; busy means no task was accepted. Do not change its role. Verify and integrate reports. Do not modify files concurrently with a coder assigned those files."
|
|
20791
21255
|
],
|
|
@@ -20850,7 +21314,7 @@ var createNekoPrompt = (loadResources, platform = process.platform) => {
|
|
|
20850
21314
|
const resources = cwd ? await loadResources(input.conversationId, cwd) : { contextFiles: [], skills: [] };
|
|
20851
21315
|
const sections = {
|
|
20852
21316
|
preamble: role ? ROLE_PROMPTS[role] + SUBAGENT_DELIVERY : PREAMBLE,
|
|
20853
|
-
rules: buildRules(input.agent.
|
|
21317
|
+
rules: buildRules(enabledTools(input.agent).map((tool) => tool.name), platform),
|
|
20854
21318
|
project_context: renderProjectContext(resources.contextFiles),
|
|
20855
21319
|
skills: formatSkillsForPrompt(resources.skills) || undefined,
|
|
20856
21320
|
cwd: cwd?.replace(/\\/g, "/")
|
|
@@ -21017,13 +21481,13 @@ var createResourceSnapshots = (load, submission) => {
|
|
|
21017
21481
|
import { stripVTControlCharacters } from "util";
|
|
21018
21482
|
import { getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
21019
21483
|
import {
|
|
21020
|
-
defineDoc as
|
|
21484
|
+
defineDoc as defineDoc7,
|
|
21021
21485
|
defineExtension as defineExtension8,
|
|
21022
21486
|
defineTask as defineTask3,
|
|
21023
21487
|
InboxDoc as InboxDoc2,
|
|
21024
21488
|
LiveDoc as LiveDoc2
|
|
21025
21489
|
} from "@earendil-works/pi-durable";
|
|
21026
|
-
var SessionMetadataDoc =
|
|
21490
|
+
var SessionMetadataDoc = defineDoc7({
|
|
21027
21491
|
kind: "app.neko.session-metadata",
|
|
21028
21492
|
checkpointWhen: () => false,
|
|
21029
21493
|
version: 1,
|
|
@@ -21215,7 +21679,7 @@ class SessionMetadataManager {
|
|
|
21215
21679
|
this.context = context;
|
|
21216
21680
|
this.report = report;
|
|
21217
21681
|
registry.install(defineExtension8({ name: "neko-naming", tasks: [this.task] }));
|
|
21218
|
-
this.#unsubscribe = harness
|
|
21682
|
+
this.#unsubscribe = onCommits(harness, ({ changes }) => {
|
|
21219
21683
|
const ids = new Set;
|
|
21220
21684
|
const submissions = new Map;
|
|
21221
21685
|
let notice = false;
|
|
@@ -21230,7 +21694,7 @@ class SessionMetadataManager {
|
|
|
21230
21694
|
if (c.record.kind === "pi.agent" || c.record.kind === QuestionsDoc.definition.kind || c.record.kind === PlanDoc.definition.kind)
|
|
21231
21695
|
ids.add(c.conversationId);
|
|
21232
21696
|
if (c.record.kind === "pi.live") {
|
|
21233
|
-
const running = c.value
|
|
21697
|
+
const running = c.kind === "change" && c.value.run !== undefined;
|
|
21234
21698
|
if (this.#live.get(c.conversationId) !== running) {
|
|
21235
21699
|
this.#live.set(c.conversationId, running);
|
|
21236
21700
|
ids.add(c.conversationId);
|
|
@@ -21360,9 +21824,10 @@ class SessionMetadataManager {
|
|
|
21360
21824
|
}
|
|
21361
21825
|
|
|
21362
21826
|
// packages/core/src/todos.ts
|
|
21363
|
-
import {
|
|
21364
|
-
import {
|
|
21365
|
-
|
|
21827
|
+
import { StringEnum as StringEnum3 } from "@earendil-works/pi-ai";
|
|
21828
|
+
import { defineDoc as defineDoc8, defineExtension as defineExtension9, defineTool as defineTool6 } from "@earendil-works/pi-durable";
|
|
21829
|
+
import { arr as arr4, int as int4, obj as obj6, opt as opt6, str as str6 } from "@earendil-works/pi-schema";
|
|
21830
|
+
var TodosDoc = defineDoc8({
|
|
21366
21831
|
kind: "app.neko.todos",
|
|
21367
21832
|
checkpointWhen: () => false,
|
|
21368
21833
|
version: 1,
|
|
@@ -21371,30 +21836,30 @@ var TodosDoc = defineDoc6({
|
|
|
21371
21836
|
fork: "asOf",
|
|
21372
21837
|
initial: () => ({ revision: 0, items: [] })
|
|
21373
21838
|
});
|
|
21374
|
-
var TodoReceiptDoc =
|
|
21839
|
+
var TodoReceiptDoc = defineDoc8({
|
|
21375
21840
|
kind: "app.neko.todo-receipt",
|
|
21376
21841
|
checkpointWhen: () => false,
|
|
21377
21842
|
version: 1,
|
|
21378
21843
|
scope: "task",
|
|
21379
21844
|
initial: () => ({ applied: false, revision: 0, items: [] })
|
|
21380
21845
|
});
|
|
21381
|
-
var itemSchema =
|
|
21382
|
-
id:
|
|
21846
|
+
var itemSchema = obj6({
|
|
21847
|
+
id: str6({
|
|
21383
21848
|
minLength: 1,
|
|
21384
21849
|
maxLength: TODO_LIMITS.idChars,
|
|
21385
21850
|
description: "Stable id; keep it when you update the same task."
|
|
21386
21851
|
}),
|
|
21387
|
-
text:
|
|
21388
|
-
status:
|
|
21389
|
-
}
|
|
21390
|
-
var parameters5 =
|
|
21391
|
-
action:
|
|
21392
|
-
items:
|
|
21852
|
+
text: str6({ minLength: 1, maxLength: TODO_LIMITS.textChars }),
|
|
21853
|
+
status: StringEnum3([...TODO_STATUSES])
|
|
21854
|
+
});
|
|
21855
|
+
var parameters5 = obj6({
|
|
21856
|
+
action: StringEnum3(["list", "replace"], { description: "list reads the list; replace overwrites it." }),
|
|
21857
|
+
items: opt6(arr4(itemSchema, {
|
|
21393
21858
|
maxItems: TODO_LIMITS.maxItems,
|
|
21394
21859
|
description: "Required for replace only: the complete ordered list; [] clears it."
|
|
21395
21860
|
}))
|
|
21396
|
-
}
|
|
21397
|
-
var structuredOutputSchema3 =
|
|
21861
|
+
});
|
|
21862
|
+
var structuredOutputSchema3 = obj6({ revision: int4({ minimum: 0 }), items: arr4(itemSchema) });
|
|
21398
21863
|
var clone3 = (value) => JSON.parse(JSON.stringify(value));
|
|
21399
21864
|
function renderTodos(list) {
|
|
21400
21865
|
const { completed, total } = todoProgress(list.items);
|
|
@@ -21463,14 +21928,14 @@ import { randomUUID as randomUUID3 } from "crypto";
|
|
|
21463
21928
|
import { realpath } from "fs/promises";
|
|
21464
21929
|
import {
|
|
21465
21930
|
configure as configure2,
|
|
21466
|
-
defineDoc as
|
|
21931
|
+
defineDoc as defineDoc9,
|
|
21467
21932
|
defineExtension as defineExtension10,
|
|
21468
21933
|
hook as hook3,
|
|
21469
21934
|
ToolTask as ToolTask3,
|
|
21470
|
-
wrapTool as
|
|
21935
|
+
wrapTool as wrapTool4
|
|
21471
21936
|
} from "@earendil-works/pi-durable";
|
|
21472
21937
|
import { createBashTool as createBashTool2 } from "@earendil-works/pi-durable/tools";
|
|
21473
|
-
var ApprovalsDoc =
|
|
21938
|
+
var ApprovalsDoc = defineDoc9({
|
|
21474
21939
|
kind: "app.neko.approvals",
|
|
21475
21940
|
checkpointWhen: () => false,
|
|
21476
21941
|
version: 1,
|
|
@@ -21489,7 +21954,7 @@ class ToolApprovals {
|
|
|
21489
21954
|
#parents = new Set;
|
|
21490
21955
|
constructor(harness, context) {
|
|
21491
21956
|
this.harness = harness;
|
|
21492
|
-
const stop = harness
|
|
21957
|
+
const stop = onCommits(harness, ({ changes }) => {
|
|
21493
21958
|
if (!changes.some((c) => c.type === "task" && (c.value.abortRequested || c.value.state.status === "terminal")))
|
|
21494
21959
|
return;
|
|
21495
21960
|
for (const parent of this.#parents)
|
|
@@ -21524,14 +21989,12 @@ class ToolApprovals {
|
|
|
21524
21989
|
}, context);
|
|
21525
21990
|
}
|
|
21526
21991
|
async wait(parent, id, context) {
|
|
21527
|
-
const
|
|
21528
|
-
if (!
|
|
21992
|
+
const watch = await this.harness.watchDoc(ApprovalsDoc, parent, context);
|
|
21993
|
+
if (!watch)
|
|
21529
21994
|
throw new Error("Approval unavailable");
|
|
21530
21995
|
try {
|
|
21531
21996
|
return await new Promise((resolve, reject) => {
|
|
21532
|
-
let stop = () => {};
|
|
21533
21997
|
const cleanup = () => {
|
|
21534
|
-
stop();
|
|
21535
21998
|
context.abortSignal?.removeEventListener("abort", abort);
|
|
21536
21999
|
};
|
|
21537
22000
|
const abort = () => {
|
|
@@ -21539,13 +22002,16 @@ class ToolApprovals {
|
|
|
21539
22002
|
reject(context.abortSignal?.reason ?? new Error("Cancelled"));
|
|
21540
22003
|
};
|
|
21541
22004
|
const check = () => {
|
|
21542
|
-
const item =
|
|
22005
|
+
const item = watch.value.items.find((a) => a.id === id);
|
|
21543
22006
|
if (item && item.status !== "pending") {
|
|
21544
22007
|
cleanup();
|
|
21545
22008
|
resolve(structuredClone(item));
|
|
21546
22009
|
}
|
|
21547
22010
|
};
|
|
21548
|
-
|
|
22011
|
+
watch.start(async (call) => {
|
|
22012
|
+
if (call.kind === "value")
|
|
22013
|
+
check();
|
|
22014
|
+
});
|
|
21549
22015
|
context.abortSignal?.addEventListener("abort", abort, { once: true });
|
|
21550
22016
|
if (context.abortSignal?.aborted)
|
|
21551
22017
|
abort();
|
|
@@ -21553,7 +22019,7 @@ class ToolApprovals {
|
|
|
21553
22019
|
check();
|
|
21554
22020
|
});
|
|
21555
22021
|
} finally {
|
|
21556
|
-
|
|
22022
|
+
await watch.stop();
|
|
21557
22023
|
}
|
|
21558
22024
|
}
|
|
21559
22025
|
async ensure(parent, candidate, context) {
|
|
@@ -21612,7 +22078,7 @@ function createApprovalExtension(service) {
|
|
|
21612
22078
|
})
|
|
21613
22079
|
],
|
|
21614
22080
|
wraps: [
|
|
21615
|
-
|
|
22081
|
+
wrapTool4(createBashTool2(), (bash) => ({
|
|
21616
22082
|
...bash,
|
|
21617
22083
|
execute: async (args, api, context) => {
|
|
21618
22084
|
const role = await api.snapshot(SubagentDoc, api.conversationId, context);
|
|
@@ -21636,7 +22102,7 @@ async function prepareApprovalConversations(harness, ids, extension, context) {
|
|
|
21636
22102
|
const child = await harness.conversation(id, context);
|
|
21637
22103
|
const agent = await child.agent(context);
|
|
21638
22104
|
await harness.commit((tx) => configure2(tx, id, {
|
|
21639
|
-
tools: [...agent.
|
|
22105
|
+
tools: [...enabledTools(agent).filter((t) => t.name !== "bash"), createBashTool2()],
|
|
21640
22106
|
extensions: { add: [extension] }
|
|
21641
22107
|
}), context);
|
|
21642
22108
|
}
|
|
@@ -21863,8 +22329,8 @@ function createDeepseekProvider(resolveKey, fetchImpl = fetch, options = {}) {
|
|
|
21863
22329
|
}
|
|
21864
22330
|
|
|
21865
22331
|
// packages/core/src/web-search/index.ts
|
|
21866
|
-
import { Type as Type7 } from "@earendil-works/pi-ai";
|
|
21867
22332
|
import { defineExtension as defineExtension11, defineTool as defineTool7 } from "@earendil-works/pi-durable";
|
|
22333
|
+
import { arr as arr5, num as num3, obj as obj7, opt as opt7, str as str7 } from "@earendil-works/pi-schema";
|
|
21868
22334
|
var MAX_URLS = 20;
|
|
21869
22335
|
var MAX_RESULTS = 10;
|
|
21870
22336
|
var DEFAULT_RESULTS = 5;
|
|
@@ -21888,10 +22354,10 @@ function createWebSearchTools(resolveProvider) {
|
|
|
21888
22354
|
defineTool7({
|
|
21889
22355
|
name: "web_search",
|
|
21890
22356
|
description: "Search the live web for current or unknown information. Returns ranked sources (title, URL, bounded excerpts). Keep the query short and focused (ideally under 128 characters). Use only when up-to-date or external information is needed; use web_extract to read a known URL.",
|
|
21891
|
-
parameters:
|
|
21892
|
-
query:
|
|
21893
|
-
maxResults:
|
|
21894
|
-
}),
|
|
22357
|
+
parameters: obj7({
|
|
22358
|
+
query: str7({ minLength: 1, maxLength: 4096, description: "The search query" }),
|
|
22359
|
+
maxResults: opt7(num3({ description: `Maximum number of results (1-${MAX_RESULTS}, default ${DEFAULT_RESULTS})` }))
|
|
22360
|
+
}, { open: true }),
|
|
21895
22361
|
async execute({ query, maxResults }, _api, context) {
|
|
21896
22362
|
try {
|
|
21897
22363
|
if (!query.trim() || query.length > 4096)
|
|
@@ -21919,13 +22385,13 @@ ${item.date ? `Published: ${item.date}
|
|
|
21919
22385
|
defineTool7({
|
|
21920
22386
|
name: "web_extract",
|
|
21921
22387
|
description: "Extract bounded markdown excerpts from web pages by URL. Every requested URL has a result or failure entry; long content is truncated.",
|
|
21922
|
-
parameters:
|
|
21923
|
-
urls:
|
|
22388
|
+
parameters: obj7({
|
|
22389
|
+
urls: arr5(str7({ maxLength: 2048, description: "http(s) URL" }), {
|
|
21924
22390
|
minItems: 1,
|
|
21925
22391
|
maxItems: MAX_URLS,
|
|
21926
22392
|
description: `URLs to extract (1-${MAX_URLS})`
|
|
21927
22393
|
})
|
|
21928
|
-
}),
|
|
22394
|
+
}, { open: true }),
|
|
21929
22395
|
async execute({ urls }, _api, context) {
|
|
21930
22396
|
try {
|
|
21931
22397
|
if (!urls.length || urls.length > MAX_URLS)
|
|
@@ -22323,7 +22789,7 @@ class WorkspaceFiles {
|
|
|
22323
22789
|
}
|
|
22324
22790
|
#disposeWatch(watch) {
|
|
22325
22791
|
watch.controller.abort();
|
|
22326
|
-
const closing = watch.work.catch(() => {}).then(() => watch.watcher?.
|
|
22792
|
+
const closing = watch.work.catch(() => {}).then(() => watch.watcher?.stop(BACKGROUND_CONTEXT2)).then(() => {}).catch(() => {}).finally(() => this.#disposing.delete(closing));
|
|
22327
22793
|
this.#disposing.add(closing);
|
|
22328
22794
|
}
|
|
22329
22795
|
#closeWatcher(item) {
|
|
@@ -22364,7 +22830,7 @@ class WorkspaceFiles {
|
|
|
22364
22830
|
user.generation++;
|
|
22365
22831
|
user.loaded = 0;
|
|
22366
22832
|
}
|
|
22367
|
-
if ("
|
|
22833
|
+
if (change.kind === "failed") {
|
|
22368
22834
|
if (this.#watches.get(item.root) === current)
|
|
22369
22835
|
this.#watches.delete(item.root);
|
|
22370
22836
|
for (const user of [...current.users])
|
|
@@ -22374,7 +22840,7 @@ class WorkspaceFiles {
|
|
|
22374
22840
|
if (result.ok) {
|
|
22375
22841
|
current.watcher = result.value;
|
|
22376
22842
|
if (current.controller.signal.aborted)
|
|
22377
|
-
await result.value.
|
|
22843
|
+
await result.value.stop(BACKGROUND_CONTEXT2);
|
|
22378
22844
|
} else {
|
|
22379
22845
|
forget();
|
|
22380
22846
|
}
|
|
@@ -22645,7 +23111,7 @@ function cancellable(work, signal) {
|
|
|
22645
23111
|
var DEFAULT_MODEL = { provider: "deepseek", modelId: "deepseek-flash" };
|
|
22646
23112
|
var DEFAULT_STORAGE_PATH = join5(homedir4(), ".neko", "neko.sqlite");
|
|
22647
23113
|
var neverAborted = () => new AbortController().signal;
|
|
22648
|
-
var ArchivedDoc =
|
|
23114
|
+
var ArchivedDoc = defineDoc10({
|
|
22649
23115
|
kind: "app.neko.conversation",
|
|
22650
23116
|
checkpointWhen: () => false,
|
|
22651
23117
|
version: 1,
|
|
@@ -22654,7 +23120,7 @@ var ArchivedDoc = defineDoc8({
|
|
|
22654
23120
|
fork: "initial",
|
|
22655
23121
|
initial: () => ({ archived: false })
|
|
22656
23122
|
});
|
|
22657
|
-
var WorkspacesDoc =
|
|
23123
|
+
var WorkspacesDoc = defineDoc10({
|
|
22658
23124
|
kind: "app.neko.workspaces",
|
|
22659
23125
|
checkpointWhen: () => false,
|
|
22660
23126
|
version: 1,
|
|
@@ -22663,7 +23129,7 @@ var WorkspacesDoc = defineDoc8({
|
|
|
22663
23129
|
fork: "initial",
|
|
22664
23130
|
initial: () => ({ items: [] })
|
|
22665
23131
|
});
|
|
22666
|
-
var RemovedWorkspacesDoc =
|
|
23132
|
+
var RemovedWorkspacesDoc = defineDoc10({
|
|
22667
23133
|
kind: "app.neko.workspaces-removed",
|
|
22668
23134
|
checkpointWhen: () => false,
|
|
22669
23135
|
version: 1,
|
|
@@ -22672,7 +23138,7 @@ var RemovedWorkspacesDoc = defineDoc8({
|
|
|
22672
23138
|
fork: "initial",
|
|
22673
23139
|
initial: () => ({ paths: [] })
|
|
22674
23140
|
});
|
|
22675
|
-
var SearchSettingsDoc =
|
|
23141
|
+
var SearchSettingsDoc = defineDoc10({
|
|
22676
23142
|
kind: "app.neko.search-settings",
|
|
22677
23143
|
checkpointWhen: () => false,
|
|
22678
23144
|
version: 1,
|
|
@@ -22681,7 +23147,7 @@ var SearchSettingsDoc = defineDoc8({
|
|
|
22681
23147
|
fork: "initial",
|
|
22682
23148
|
initial: () => ({ provider: null })
|
|
22683
23149
|
});
|
|
22684
|
-
var ProviderSettingsDoc =
|
|
23150
|
+
var ProviderSettingsDoc = defineDoc10({
|
|
22685
23151
|
kind: "app.neko.provider-settings",
|
|
22686
23152
|
checkpointWhen: () => false,
|
|
22687
23153
|
version: 1,
|
|
@@ -22690,7 +23156,7 @@ var ProviderSettingsDoc = defineDoc8({
|
|
|
22690
23156
|
fork: "initial",
|
|
22691
23157
|
initial: () => ({ enabled: null })
|
|
22692
23158
|
});
|
|
22693
|
-
var DefaultModelDoc =
|
|
23159
|
+
var DefaultModelDoc = defineDoc10({
|
|
22694
23160
|
kind: "app.neko.default-model",
|
|
22695
23161
|
checkpointWhen: () => false,
|
|
22696
23162
|
version: 1,
|
|
@@ -22699,7 +23165,7 @@ var DefaultModelDoc = defineDoc8({
|
|
|
22699
23165
|
fork: "initial",
|
|
22700
23166
|
initial: () => ({ model: null })
|
|
22701
23167
|
});
|
|
22702
|
-
var ContextSettingsDoc =
|
|
23168
|
+
var ContextSettingsDoc = defineDoc10({
|
|
22703
23169
|
kind: "app.neko.context-settings",
|
|
22704
23170
|
checkpointWhen: () => false,
|
|
22705
23171
|
version: 1,
|
|
@@ -22708,7 +23174,7 @@ var ContextSettingsDoc = defineDoc8({
|
|
|
22708
23174
|
fork: "initial",
|
|
22709
23175
|
initial: emptySavedContextSettings
|
|
22710
23176
|
});
|
|
22711
|
-
var ActivityDoc =
|
|
23177
|
+
var ActivityDoc = defineDoc10({
|
|
22712
23178
|
kind: "app.neko.activity",
|
|
22713
23179
|
checkpointWhen: () => false,
|
|
22714
23180
|
version: 1,
|
|
@@ -22719,6 +23185,9 @@ var ActivityDoc = defineDoc8({
|
|
|
22719
23185
|
});
|
|
22720
23186
|
async function createNekoRuntime(options = {}) {
|
|
22721
23187
|
const context = options.context ?? BACKGROUND_CONTEXT3;
|
|
23188
|
+
if (options.maxTurns !== undefined && !(Number.isSafeInteger(options.maxTurns) && options.maxTurns >= 1))
|
|
23189
|
+
throw new RangeError(`maxTurns must be an integer of 1 or more, got ${options.maxTurns}`);
|
|
23190
|
+
const turnLimit = options.maxTurns === undefined ? {} : { maxTurns: options.maxTurns };
|
|
22722
23191
|
const defaultCwd = normalizeWorkspace(options.cwd);
|
|
22723
23192
|
const model = options.model ?? DEFAULT_MODEL;
|
|
22724
23193
|
const modelOverride = options.modelOverride;
|
|
@@ -22815,6 +23284,11 @@ async function createNekoRuntime(options = {}) {
|
|
|
22815
23284
|
registry.install(createQuestionExtension(() => questions));
|
|
22816
23285
|
let plans;
|
|
22817
23286
|
registry.install(createPlanExtension(() => plans));
|
|
23287
|
+
const codemode = createCodemodeRuntime({
|
|
23288
|
+
maxWorkers: options.codemodeLimits?.maxWorkers ?? CODEMODE_LIMITS.maxWorkers,
|
|
23289
|
+
waitMs: options.codemodeLimits?.waitMs ?? CODEMODE_LIMITS.waitMs
|
|
23290
|
+
});
|
|
23291
|
+
registry.install(codemode.extension);
|
|
22818
23292
|
for (const extension of options.extensions ?? [])
|
|
22819
23293
|
registry.install(extension);
|
|
22820
23294
|
let approvals;
|
|
@@ -22833,7 +23307,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
22833
23307
|
return compactionFor(contextState);
|
|
22834
23308
|
}
|
|
22835
23309
|
},
|
|
22836
|
-
onReport: options.onReport,
|
|
23310
|
+
onReport: (report) => options.onReport?.(report.error, report),
|
|
22837
23311
|
conversationCreated: async (tx, record) => {
|
|
22838
23312
|
(await tx.doc(SessionMetadataDoc, record.id)).createdAt = Date.now();
|
|
22839
23313
|
},
|
|
@@ -22868,6 +23342,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
22868
23342
|
}
|
|
22869
23343
|
}
|
|
22870
23344
|
} catch (error) {
|
|
23345
|
+
await codemode.close();
|
|
22871
23346
|
await workspaceFiles.close();
|
|
22872
23347
|
await harness.close(context);
|
|
22873
23348
|
throw error;
|
|
@@ -22878,10 +23353,18 @@ async function createNekoRuntime(options = {}) {
|
|
|
22878
23353
|
agent: {
|
|
22879
23354
|
model: rootModel,
|
|
22880
23355
|
thinkingLevel: resolveLevel(rootModel, options.thinkingLevel ?? "high"),
|
|
22881
|
-
cwd: defaultCwd
|
|
23356
|
+
cwd: defaultCwd,
|
|
23357
|
+
...turnLimit
|
|
22882
23358
|
}
|
|
22883
23359
|
});
|
|
22884
23360
|
enabled = new Set(normalizeEnabledProviders((await harness.snapshot(ProviderSettingsDoc, conversation.id, context))?.enabled));
|
|
23361
|
+
const codemodeState = async () => resolveCodemodeSettings(options.codemodeSettings, (await harness.snapshot(CodemodeSettingsDoc, conversation.id, context))?.mode);
|
|
23362
|
+
if (existing.length === 0) {
|
|
23363
|
+
const initial = (await codemodeState()).effective.mode;
|
|
23364
|
+
await harness.commit(async (tx) => {
|
|
23365
|
+
(await tx.doc(CodemodeDoc, conversation.id)).mode = initial;
|
|
23366
|
+
}, context);
|
|
23367
|
+
}
|
|
22885
23368
|
const savedSearch = (await harness.snapshot(SearchSettingsDoc, conversation.id, context))?.provider;
|
|
22886
23369
|
if (isSearchProvider(savedSearch))
|
|
22887
23370
|
searchProvider = savedSearch;
|
|
@@ -23008,14 +23491,16 @@ async function createNekoRuntime(options = {}) {
|
|
|
23008
23491
|
admissions.delete(id);
|
|
23009
23492
|
}
|
|
23010
23493
|
};
|
|
23011
|
-
const
|
|
23012
|
-
const
|
|
23013
|
-
|
|
23014
|
-
await
|
|
23494
|
+
const syncAgent = async (target) => {
|
|
23495
|
+
const change = agentSyncChange(await target.agent(context), {
|
|
23496
|
+
plan: await plans.mode(target.id),
|
|
23497
|
+
codemode: (await harness.snapshot(CodemodeDoc, target.id, context))?.mode ?? "off",
|
|
23498
|
+
role: "main"
|
|
23499
|
+
});
|
|
23500
|
+
if (change)
|
|
23501
|
+
await target.configure(change, context);
|
|
23015
23502
|
};
|
|
23016
|
-
const
|
|
23017
|
-
await syncPlanAgent(target);
|
|
23018
|
-
const agent = await target.agent(context);
|
|
23503
|
+
const prepareSubmission = async (target, agent, content, submitOptions, extra) => {
|
|
23019
23504
|
const workspace = executionWorkspace(agent.cwd);
|
|
23020
23505
|
const duplicate = submitOptions?.requestId !== undefined && await storage.submissionByRequest(target.id, submitOptions.requestId, context);
|
|
23021
23506
|
const data = { at: Date.now(), prompt: "", images: [], ...extra };
|
|
@@ -23069,15 +23554,23 @@ async function createNekoRuntime(options = {}) {
|
|
|
23069
23554
|
}
|
|
23070
23555
|
if (prepared)
|
|
23071
23556
|
resourceSnapshots.stage(target.id, requestId, workspace, prepared);
|
|
23072
|
-
|
|
23073
|
-
|
|
23074
|
-
result = await target.submit({
|
|
23557
|
+
return {
|
|
23558
|
+
draft: {
|
|
23075
23559
|
type: "input",
|
|
23076
23560
|
content,
|
|
23077
23561
|
entry: { kind: NekoInput.kind, data },
|
|
23078
23562
|
requestId,
|
|
23079
23563
|
...submitOptions?.whenBusy !== undefined ? { whenBusy: submitOptions.whenBusy } : {}
|
|
23080
|
-
},
|
|
23564
|
+
},
|
|
23565
|
+
requestId
|
|
23566
|
+
};
|
|
23567
|
+
};
|
|
23568
|
+
const submitNow = async (target, content, submitOptions, extra) => {
|
|
23569
|
+
await syncAgent(target);
|
|
23570
|
+
const { draft, requestId } = await prepareSubmission(target, await target.agent(context), content, submitOptions, extra);
|
|
23571
|
+
let result;
|
|
23572
|
+
try {
|
|
23573
|
+
result = await target.submit(draft, context);
|
|
23081
23574
|
} catch (error) {
|
|
23082
23575
|
resourceSnapshots.discard(target.id, requestId);
|
|
23083
23576
|
throw error;
|
|
@@ -23087,10 +23580,11 @@ async function createNekoRuntime(options = {}) {
|
|
|
23087
23580
|
await touchConversation(target.id);
|
|
23088
23581
|
await metadata.reconcile(target.id);
|
|
23089
23582
|
return result;
|
|
23090
|
-
}
|
|
23091
|
-
const
|
|
23583
|
+
};
|
|
23584
|
+
const submitTo = (target, ...args) => admit(target.id, () => submitNow(target, ...args));
|
|
23585
|
+
const dispatchPlan = async (target, item, submit = submitTo) => {
|
|
23092
23586
|
const approve = item.status === "approved";
|
|
23093
|
-
await
|
|
23587
|
+
await submit(target, approve ? approvedPlanPrompt(item) : planRevisionPrompt(item, item.feedback ?? ""), { requestId: `${approve ? "plan-exec" : "plan-revise"}:${item.version}`, whenBusy: "followUp" }, {
|
|
23094
23588
|
planDecision: {
|
|
23095
23589
|
version: item.version,
|
|
23096
23590
|
kind: approve ? "approve" : "revise",
|
|
@@ -23127,15 +23621,12 @@ async function createNekoRuntime(options = {}) {
|
|
|
23127
23621
|
waitAnswer(submission) {
|
|
23128
23622
|
return waitAnswerOf(target, submission);
|
|
23129
23623
|
},
|
|
23130
|
-
|
|
23131
|
-
return target
|
|
23624
|
+
follow() {
|
|
23625
|
+
return followConversation(target, context);
|
|
23132
23626
|
},
|
|
23133
23627
|
watch() {
|
|
23134
23628
|
return target.watch(context);
|
|
23135
23629
|
},
|
|
23136
|
-
events() {
|
|
23137
|
-
return watchEvents(harness, target.id, context);
|
|
23138
|
-
},
|
|
23139
23630
|
async usage() {
|
|
23140
23631
|
return mergeUsage(await harness.snapshot(UsageDoc2, target.id, context) ?? { models: {}, tools: {} }, (await harness.snapshot(SessionMetadataDoc, target.id, context))?.namingUsage ?? { models: {}, tools: {} });
|
|
23141
23632
|
},
|
|
@@ -23178,24 +23669,55 @@ async function createNekoRuntime(options = {}) {
|
|
|
23178
23669
|
if (await isRunning(target.id))
|
|
23179
23670
|
throw new Error(PLAN_BUSY);
|
|
23180
23671
|
await plans.setMode(target.id, mode);
|
|
23181
|
-
await
|
|
23672
|
+
await syncAgent(target);
|
|
23182
23673
|
return plans.view(target.id);
|
|
23183
23674
|
});
|
|
23184
23675
|
},
|
|
23185
23676
|
async respondPlan(version, decision) {
|
|
23186
23677
|
const parsed = validatePlanDecision(decision);
|
|
23187
|
-
|
|
23188
|
-
|
|
23189
|
-
|
|
23190
|
-
|
|
23678
|
+
return admit(target.id, async () => {
|
|
23679
|
+
const known = await plans.get(target.id, version);
|
|
23680
|
+
if (!known)
|
|
23681
|
+
throw new Error("Plan not found.");
|
|
23682
|
+
if (known.status !== "awaiting_approval") {
|
|
23683
|
+
const legacy = await plans.undispatched(target.id);
|
|
23684
|
+
if (legacy?.version === version)
|
|
23685
|
+
await dispatchPlan(target, legacy, submitNow);
|
|
23686
|
+
return known;
|
|
23687
|
+
}
|
|
23191
23688
|
if (await isRunning(target.id))
|
|
23192
23689
|
throw new Error(PLAN_BUSY);
|
|
23193
|
-
await
|
|
23194
|
-
|
|
23195
|
-
|
|
23196
|
-
|
|
23197
|
-
await
|
|
23198
|
-
|
|
23690
|
+
await syncAgent(target);
|
|
23691
|
+
const agent = await target.agent(context);
|
|
23692
|
+
const approve = parsed.kind === "approve";
|
|
23693
|
+
const feedback = parsed.kind === "revise" ? parsed.feedback : "";
|
|
23694
|
+
const { draft, requestId } = await prepareSubmission(target, agent, approve ? approvedPlanPrompt(known) : planRevisionPrompt(known, feedback), { requestId: `${approve ? "plan-exec" : "plan-revise"}:${version}`, whenBusy: "followUp" }, {
|
|
23695
|
+
planDecision: {
|
|
23696
|
+
version,
|
|
23697
|
+
kind: approve ? "approve" : "revise",
|
|
23698
|
+
title: known.title,
|
|
23699
|
+
...!approve && feedback ? { feedback } : {}
|
|
23700
|
+
}
|
|
23701
|
+
});
|
|
23702
|
+
const codemode = (await harness.snapshot(CodemodeDoc, target.id, context))?.mode ?? "off";
|
|
23703
|
+
const leave = approve ? agentSyncChange(agent, { plan: "normal", codemode, role: "main" }) : undefined;
|
|
23704
|
+
let record;
|
|
23705
|
+
try {
|
|
23706
|
+
record = await plans.decideWith(target.id, version, parsed, async (tx) => {
|
|
23707
|
+
await target.submit(tx, draft);
|
|
23708
|
+
if (leave)
|
|
23709
|
+
await configure3(tx, target.id, leave);
|
|
23710
|
+
});
|
|
23711
|
+
} catch (error) {
|
|
23712
|
+
resourceSnapshots.discard(target.id, requestId);
|
|
23713
|
+
throw error;
|
|
23714
|
+
}
|
|
23715
|
+
if (record.status !== "approved" && record.status !== "revision_requested")
|
|
23716
|
+
resourceSnapshots.discard(target.id, requestId);
|
|
23717
|
+
await touchConversation(target.id);
|
|
23718
|
+
await metadata.reconcile(target.id);
|
|
23719
|
+
return record;
|
|
23720
|
+
});
|
|
23199
23721
|
},
|
|
23200
23722
|
async workspaceDir(path, signal) {
|
|
23201
23723
|
return workspaceFiles.children(savedWorkspace((await target.agent(context)).cwd), path, signal ?? neverAborted());
|
|
@@ -23226,6 +23748,26 @@ async function createNekoRuntime(options = {}) {
|
|
|
23226
23748
|
await target.abort(context);
|
|
23227
23749
|
await plans.cancelPending(target.id);
|
|
23228
23750
|
},
|
|
23751
|
+
continueRun() {
|
|
23752
|
+
return admit(target.id, async () => {
|
|
23753
|
+
await syncAgent(target);
|
|
23754
|
+
await guardProvider((await target.agent(context)).model);
|
|
23755
|
+
const live = await harness.snapshot(importLiveDoc, target.id, context);
|
|
23756
|
+
if (live?.run !== undefined)
|
|
23757
|
+
throw new Error(CONTINUE_BUSY);
|
|
23758
|
+
if (live?.runFailure === undefined)
|
|
23759
|
+
throw new Error(CONTINUE_UNAVAILABLE);
|
|
23760
|
+
try {
|
|
23761
|
+
await target.submit({ type: "continue" }, context);
|
|
23762
|
+
} catch (error) {
|
|
23763
|
+
if (error instanceof ConversationBusy)
|
|
23764
|
+
throw new Error(CONTINUE_BUSY);
|
|
23765
|
+
throw error;
|
|
23766
|
+
}
|
|
23767
|
+
await touchConversation(target.id);
|
|
23768
|
+
await metadata.reconcile(target.id);
|
|
23769
|
+
});
|
|
23770
|
+
},
|
|
23229
23771
|
async withdraw(submissionId) {
|
|
23230
23772
|
const id = submissionId;
|
|
23231
23773
|
const inbox = await harness.snapshot(InboxDoc3, target.id, context);
|
|
@@ -23300,7 +23842,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
23300
23842
|
const session = await getConversation(id);
|
|
23301
23843
|
if (!session)
|
|
23302
23844
|
continue;
|
|
23303
|
-
await admit(id, () =>
|
|
23845
|
+
await admit(id, () => syncAgent(session.conversation));
|
|
23304
23846
|
const pending = await plans.undispatched(id);
|
|
23305
23847
|
if (pending)
|
|
23306
23848
|
await dispatchPlan(session.conversation, pending);
|
|
@@ -23386,6 +23928,8 @@ async function createNekoRuntime(options = {}) {
|
|
|
23386
23928
|
}
|
|
23387
23929
|
const child = at === undefined ? await tx.createConversation({ ownership: { kind: "ownerless" } }) : await tx.forkConversation(id, at, { ownership: { kind: "ownerless" } });
|
|
23388
23930
|
(await tx.doc(DelegationsDoc, child.id)).items = inherited;
|
|
23931
|
+
if (at === undefined)
|
|
23932
|
+
(await tx.doc(CodemodeDoc, child.id)).mode = (await tx.doc(CodemodeDoc, id)).mode;
|
|
23389
23933
|
if (sourceMetadata) {
|
|
23390
23934
|
const doc = await tx.doc(SessionMetadataDoc, child.id);
|
|
23391
23935
|
doc.title = sourceMetadata.title || sourceMetadata.firstPromptPreview;
|
|
@@ -23413,15 +23957,12 @@ async function createNekoRuntime(options = {}) {
|
|
|
23413
23957
|
root: rootSession,
|
|
23414
23958
|
submit: rootSession.submit,
|
|
23415
23959
|
waitAnswer: rootSession.waitAnswer,
|
|
23416
|
-
async
|
|
23417
|
-
return (await sessionFor(id)).
|
|
23960
|
+
async follow(id) {
|
|
23961
|
+
return (await sessionFor(id)).follow();
|
|
23418
23962
|
},
|
|
23419
23963
|
async watch(id) {
|
|
23420
23964
|
return (await sessionFor(id)).watch();
|
|
23421
23965
|
},
|
|
23422
|
-
async events(id) {
|
|
23423
|
-
return (await sessionFor(id)).events();
|
|
23424
|
-
},
|
|
23425
23966
|
async usage(id) {
|
|
23426
23967
|
return (await sessionFor(id)).usage();
|
|
23427
23968
|
},
|
|
@@ -23466,12 +24007,18 @@ async function createNekoRuntime(options = {}) {
|
|
|
23466
24007
|
const workspace = await addWorkspace(createOptions?.cwd ?? defaultCwd);
|
|
23467
24008
|
const savedDefault = (await harness.snapshot(DefaultModelDoc, conversation.id, context))?.model ?? null;
|
|
23468
24009
|
const effective = createOptions?.model ?? modelOverride ?? savedDefault ?? model;
|
|
24010
|
+
const mode = (await codemodeState()).effective.mode;
|
|
23469
24011
|
const created = await harness.createConversation({
|
|
23470
24012
|
ownership: { kind: "ownerless" },
|
|
23471
24013
|
agent: {
|
|
23472
24014
|
model: effective,
|
|
23473
24015
|
thinkingLevel: resolveLevel(effective, createOptions?.thinkingLevel ?? options.thinkingLevel ?? "high"),
|
|
23474
|
-
cwd: workspace.path
|
|
24016
|
+
cwd: workspace.path,
|
|
24017
|
+
...turnLimit,
|
|
24018
|
+
...agentChangeFor({ plan: "normal", codemode: mode, role: "main" })
|
|
24019
|
+
},
|
|
24020
|
+
init: async (tx, id) => {
|
|
24021
|
+
(await tx.doc(CodemodeDoc, id)).mode = mode;
|
|
23475
24022
|
}
|
|
23476
24023
|
}, context);
|
|
23477
24024
|
await metadata.initialize(created.id);
|
|
@@ -23526,6 +24073,20 @@ async function createNekoRuntime(options = {}) {
|
|
|
23526
24073
|
async resetContextSettings() {
|
|
23527
24074
|
return persistContext(emptySavedContextSettings());
|
|
23528
24075
|
},
|
|
24076
|
+
codemodeSettings: codemodeState,
|
|
24077
|
+
async setCodemodeMode(mode) {
|
|
24078
|
+
const parsed = parseCodemodeMode(mode);
|
|
24079
|
+
await harness.commit(async (tx) => {
|
|
24080
|
+
(await tx.doc(CodemodeSettingsDoc, conversation.id)).mode = parsed;
|
|
24081
|
+
}, context);
|
|
24082
|
+
return codemodeState();
|
|
24083
|
+
},
|
|
24084
|
+
async resetCodemodeMode() {
|
|
24085
|
+
await harness.commit(async (tx) => {
|
|
24086
|
+
(await tx.doc(CodemodeSettingsDoc, conversation.id)).mode = null;
|
|
24087
|
+
}, context);
|
|
24088
|
+
return codemodeState();
|
|
24089
|
+
},
|
|
23529
24090
|
async searchSettings() {
|
|
23530
24091
|
return { selected: searchProvider };
|
|
23531
24092
|
},
|
|
@@ -23647,6 +24208,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
23647
24208
|
registry.install(extension);
|
|
23648
24209
|
},
|
|
23649
24210
|
async close() {
|
|
24211
|
+
await codemode.close();
|
|
23650
24212
|
await cleanup();
|
|
23651
24213
|
return harness.close(context);
|
|
23652
24214
|
}
|
|
@@ -23654,7 +24216,20 @@ async function createNekoRuntime(options = {}) {
|
|
|
23654
24216
|
}
|
|
23655
24217
|
// packages/gateway/src/contract.ts
|
|
23656
24218
|
import { hostNamed, method, remote } from "@earendil-works/chord";
|
|
23657
|
-
import {
|
|
24219
|
+
import {
|
|
24220
|
+
arr as arr6,
|
|
24221
|
+
bool as bool3,
|
|
24222
|
+
int as int5,
|
|
24223
|
+
lit as lit3,
|
|
24224
|
+
map,
|
|
24225
|
+
nul as nul3,
|
|
24226
|
+
num as num4,
|
|
24227
|
+
obj as obj8,
|
|
24228
|
+
oneOf as oneOf2,
|
|
24229
|
+
opt as opt8,
|
|
24230
|
+
str as str8,
|
|
24231
|
+
union as union4
|
|
24232
|
+
} from "@earendil-works/pi-schema";
|
|
23658
24233
|
var GATEWAY_HOST = "neko";
|
|
23659
24234
|
var rpc = (args, result) => [args, result];
|
|
23660
24235
|
function contract(name, def) {
|
|
@@ -23667,433 +24242,458 @@ function contract(name, def) {
|
|
|
23667
24242
|
]));
|
|
23668
24243
|
return remote(name, { ...def, host: hostNamed(GATEWAY_HOST), variants });
|
|
23669
24244
|
}
|
|
23670
|
-
var
|
|
23671
|
-
var
|
|
23672
|
-
var
|
|
23673
|
-
var nil =
|
|
23674
|
-
var integer =
|
|
23675
|
-
var nullableString =
|
|
23676
|
-
var phase =
|
|
23677
|
-
var level =
|
|
23678
|
-
var thinking =
|
|
23679
|
-
var model2 =
|
|
23680
|
-
var
|
|
23681
|
-
var
|
|
23682
|
-
var
|
|
23683
|
-
|
|
23684
|
-
|
|
24245
|
+
var text3 = str8();
|
|
24246
|
+
var number = num4();
|
|
24247
|
+
var boolean = bool3();
|
|
24248
|
+
var nil = nul3();
|
|
24249
|
+
var integer = int5({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER });
|
|
24250
|
+
var nullableString = union4([text3, nil]);
|
|
24251
|
+
var phase = oneOf2(["pending", "running", "done"]);
|
|
24252
|
+
var level = oneOf2(["project", "user", "builtin"]);
|
|
24253
|
+
var thinking = oneOf2(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
24254
|
+
var model2 = obj8({ provider: text3, modelId: text3 }, { open: true });
|
|
24255
|
+
var changeProperties = { model: opt8(model2), thinkingLevel: opt8(thinking) };
|
|
24256
|
+
var change = obj8(changeProperties);
|
|
24257
|
+
var usage = obj8({ input: number, output: number, cacheRead: number, cacheWrite: number, cost: number }, { open: true });
|
|
24258
|
+
var image = obj8({
|
|
24259
|
+
name: text3,
|
|
24260
|
+
mimeType: text3,
|
|
23685
24261
|
width: integer,
|
|
23686
24262
|
height: integer,
|
|
23687
24263
|
bytes: integer,
|
|
23688
24264
|
entryId: integer,
|
|
23689
24265
|
contentIndex: integer
|
|
23690
|
-
});
|
|
23691
|
-
var skill =
|
|
23692
|
-
var
|
|
23693
|
-
|
|
23694
|
-
|
|
23695
|
-
|
|
24266
|
+
}, { open: true });
|
|
24267
|
+
var skill = obj8({ name: text3, location: text3, body: text3, args: text3 }, { open: true });
|
|
24268
|
+
var CodemodeViewSchema = obj8({
|
|
24269
|
+
calls: arr6(obj8({
|
|
24270
|
+
id: integer,
|
|
24271
|
+
name: text3,
|
|
24272
|
+
args: text3,
|
|
24273
|
+
status: oneOf2(["running", "ok", "error", "cancelled"]),
|
|
24274
|
+
durationMs: union4([number, nil]),
|
|
24275
|
+
error: nullableString
|
|
24276
|
+
}, { open: true })),
|
|
24277
|
+
omitted: integer,
|
|
24278
|
+
fullOutputPath: nullableString
|
|
24279
|
+
}, { open: true });
|
|
24280
|
+
var call = obj8({
|
|
24281
|
+
callId: text3,
|
|
24282
|
+
name: text3,
|
|
24283
|
+
summary: text3,
|
|
23696
24284
|
detail: nullableString,
|
|
23697
24285
|
phase,
|
|
23698
24286
|
output: nullableString,
|
|
23699
24287
|
diff: nullableString,
|
|
23700
|
-
diffAdded:
|
|
23701
|
-
diffRemoved:
|
|
23702
|
-
diffTruncated:
|
|
23703
|
-
|
|
23704
|
-
|
|
24288
|
+
diffAdded: union4([number, nil]),
|
|
24289
|
+
diffRemoved: union4([number, nil]),
|
|
24290
|
+
diffTruncated: opt8(boolean),
|
|
24291
|
+
codemode: opt8(CodemodeViewSchema)
|
|
24292
|
+
}, { open: true });
|
|
24293
|
+
var DelegationSchema = obj8({
|
|
23705
24294
|
parentId: integer,
|
|
23706
|
-
agentId:
|
|
23707
|
-
round:
|
|
23708
|
-
runnerId:
|
|
23709
|
-
inputEntryId:
|
|
23710
|
-
answerEntryId:
|
|
23711
|
-
roundUsage:
|
|
24295
|
+
agentId: opt8(text3),
|
|
24296
|
+
round: opt8(integer),
|
|
24297
|
+
runnerId: opt8(integer),
|
|
24298
|
+
inputEntryId: opt8(integer),
|
|
24299
|
+
answerEntryId: opt8(integer),
|
|
24300
|
+
roundUsage: opt8(union4([usage, nil])),
|
|
23712
24301
|
taskId: integer,
|
|
23713
|
-
callId:
|
|
24302
|
+
callId: text3,
|
|
23714
24303
|
childId: integer,
|
|
23715
|
-
role:
|
|
23716
|
-
title:
|
|
23717
|
-
createdAt:
|
|
23718
|
-
startedAt:
|
|
23719
|
-
endedAt:
|
|
23720
|
-
status:
|
|
24304
|
+
role: oneOf2(["explore", "plan", "coder"]),
|
|
24305
|
+
title: text3,
|
|
24306
|
+
createdAt: number,
|
|
24307
|
+
startedAt: union4([number, nil]),
|
|
24308
|
+
endedAt: union4([number, nil]),
|
|
24309
|
+
status: oneOf2(["queued", "running", "completed", "failed", "cancelled"]),
|
|
23721
24310
|
report: nullableString,
|
|
23722
|
-
approvalCount:
|
|
23723
|
-
historyThrough:
|
|
23724
|
-
historyUsage:
|
|
23725
|
-
});
|
|
23726
|
-
var SubagentSummarySchema =
|
|
23727
|
-
agentId:
|
|
24311
|
+
approvalCount: opt8(integer),
|
|
24312
|
+
historyThrough: opt8(integer),
|
|
24313
|
+
historyUsage: opt8(usage)
|
|
24314
|
+
}, { open: true });
|
|
24315
|
+
var SubagentSummarySchema = obj8({
|
|
24316
|
+
agentId: text3,
|
|
23728
24317
|
parentId: integer,
|
|
23729
24318
|
childId: integer,
|
|
23730
|
-
role:
|
|
23731
|
-
title:
|
|
23732
|
-
status:
|
|
23733
|
-
activeRoundId:
|
|
24319
|
+
role: oneOf2(["explore", "plan", "coder"]),
|
|
24320
|
+
title: text3,
|
|
24321
|
+
status: oneOf2(["idle", "queued", "running"]),
|
|
24322
|
+
activeRoundId: union4([integer, nil]),
|
|
23734
24323
|
lastRoundId: integer,
|
|
23735
|
-
lastReport:
|
|
24324
|
+
lastReport: opt8(nullableString),
|
|
23736
24325
|
roundCount: integer,
|
|
23737
|
-
taskTitle:
|
|
24326
|
+
taskTitle: text3,
|
|
23738
24327
|
approvalCount: integer,
|
|
23739
|
-
createdAt:
|
|
23740
|
-
historyThrough:
|
|
23741
|
-
historyUsage:
|
|
23742
|
-
});
|
|
23743
|
-
var jobStatus =
|
|
23744
|
-
var JobSummarySchema =
|
|
23745
|
-
jobId:
|
|
23746
|
-
title:
|
|
23747
|
-
command:
|
|
23748
|
-
cwd:
|
|
24328
|
+
createdAt: number,
|
|
24329
|
+
historyThrough: opt8(integer),
|
|
24330
|
+
historyUsage: opt8(usage)
|
|
24331
|
+
}, { open: true });
|
|
24332
|
+
var jobStatus = oneOf2(["running", "exited", "failed", "stopped", "lost"]);
|
|
24333
|
+
var JobSummarySchema = obj8({
|
|
24334
|
+
jobId: text3,
|
|
24335
|
+
title: text3,
|
|
24336
|
+
command: text3,
|
|
24337
|
+
cwd: text3,
|
|
23749
24338
|
status: jobStatus,
|
|
23750
|
-
startedAt:
|
|
23751
|
-
endedAt:
|
|
23752
|
-
exitCode:
|
|
23753
|
-
reason:
|
|
23754
|
-
timeoutSeconds:
|
|
24339
|
+
startedAt: number,
|
|
24340
|
+
endedAt: union4([number, nil]),
|
|
24341
|
+
exitCode: union4([number, nil]),
|
|
24342
|
+
reason: opt8(oneOf2(["timeout", "spawn-error", "restart", "aborted"])),
|
|
24343
|
+
timeoutSeconds: opt8(number),
|
|
23755
24344
|
outputBytes: integer
|
|
23756
|
-
});
|
|
23757
|
-
var JobOutputSchema =
|
|
24345
|
+
}, { open: true });
|
|
24346
|
+
var JobOutputSchema = obj8({
|
|
23758
24347
|
job: JobSummarySchema,
|
|
23759
|
-
text:
|
|
24348
|
+
text: text3,
|
|
23760
24349
|
offset: integer,
|
|
23761
|
-
truncated:
|
|
24350
|
+
truncated: boolean,
|
|
23762
24351
|
dropped: integer
|
|
23763
|
-
});
|
|
23764
|
-
var QueuedInputSchema =
|
|
24352
|
+
}, { open: true });
|
|
24353
|
+
var QueuedInputSchema = obj8({
|
|
23765
24354
|
id: integer,
|
|
23766
|
-
mode:
|
|
23767
|
-
preview:
|
|
24355
|
+
mode: oneOf2(["steer", "followUp"]),
|
|
24356
|
+
preview: text3,
|
|
23768
24357
|
images: integer,
|
|
23769
|
-
skill:
|
|
23770
|
-
});
|
|
23771
|
-
var WithdrawResultSchema =
|
|
23772
|
-
result:
|
|
23773
|
-
text:
|
|
23774
|
-
images:
|
|
23775
|
-
});
|
|
23776
|
-
var SteerResultSchema =
|
|
23777
|
-
result:
|
|
23778
|
-
id:
|
|
23779
|
-
text:
|
|
23780
|
-
images:
|
|
24358
|
+
skill: opt8(obj8({ name: text3, args: text3 }, { open: true }))
|
|
24359
|
+
}, { open: true });
|
|
24360
|
+
var WithdrawResultSchema = obj8({
|
|
24361
|
+
result: oneOf2(["withdrawn", "placed", "settled", "unknown"]),
|
|
24362
|
+
text: opt8(text3),
|
|
24363
|
+
images: opt8(integer)
|
|
24364
|
+
}, { open: true });
|
|
24365
|
+
var SteerResultSchema = obj8({
|
|
24366
|
+
result: oneOf2(["steered", "withdrawn", "placed", "settled", "unknown"]),
|
|
24367
|
+
id: opt8(integer),
|
|
24368
|
+
text: opt8(text3),
|
|
24369
|
+
images: opt8(integer)
|
|
24370
|
+
}, { open: true });
|
|
24371
|
+
var TodoItemSchema = obj8({
|
|
24372
|
+
id: str8({ minLength: 1, maxLength: TODO_LIMITS.idChars }),
|
|
24373
|
+
text: str8({ minLength: 1, maxLength: TODO_LIMITS.textChars }),
|
|
24374
|
+
status: oneOf2(["pending", "in_progress", "completed"])
|
|
23781
24375
|
});
|
|
23782
|
-
var
|
|
23783
|
-
id: Type8.String({ minLength: 1, maxLength: TODO_LIMITS.idChars }),
|
|
23784
|
-
text: Type8.String({ minLength: 1, maxLength: TODO_LIMITS.textChars }),
|
|
23785
|
-
status: Type8.Enum(["pending", "in_progress", "completed"])
|
|
23786
|
-
}, { additionalProperties: false });
|
|
23787
|
-
var TodoListSchema = Type8.Object({
|
|
24376
|
+
var TodoListSchema = obj8({
|
|
23788
24377
|
revision: integer,
|
|
23789
|
-
items:
|
|
24378
|
+
items: arr6(TodoItemSchema, { maxItems: TODO_LIMITS.maxItems })
|
|
24379
|
+
}, { open: true });
|
|
24380
|
+
var QuestionOptionSchema = obj8({
|
|
24381
|
+
id: str8({ minLength: 1, maxLength: QUESTION_LIMITS.optionIdChars }),
|
|
24382
|
+
label: str8({ minLength: 1, maxLength: QUESTION_LIMITS.labelChars }),
|
|
24383
|
+
description: opt8(str8({ maxLength: QUESTION_LIMITS.descriptionChars })),
|
|
24384
|
+
recommended: opt8(boolean)
|
|
23790
24385
|
});
|
|
23791
|
-
var
|
|
23792
|
-
|
|
23793
|
-
label: Type8.String({ minLength: 1, maxLength: QUESTION_LIMITS.labelChars }),
|
|
23794
|
-
description: Type8.Optional(Type8.String({ maxLength: QUESTION_LIMITS.descriptionChars })),
|
|
23795
|
-
recommended: Type8.Optional(bool)
|
|
23796
|
-
}, { additionalProperties: false });
|
|
23797
|
-
var questionStatus = Type8.Enum(["pending", "answered", "skipped", "cancelled"]);
|
|
23798
|
-
var QuestionSummarySchema = Type8.Object({
|
|
24386
|
+
var questionStatus = oneOf2(["pending", "answered", "skipped", "cancelled"]);
|
|
24387
|
+
var QuestionSummarySchema = obj8({
|
|
23799
24388
|
id: integer,
|
|
23800
|
-
version:
|
|
23801
|
-
preview:
|
|
23802
|
-
multiple:
|
|
24389
|
+
version: text3,
|
|
24390
|
+
preview: str8({ maxLength: QUESTION_LIMITS.previewChars }),
|
|
24391
|
+
multiple: boolean,
|
|
23803
24392
|
optionCount: integer,
|
|
23804
|
-
createdAt:
|
|
24393
|
+
createdAt: number
|
|
24394
|
+
}, { open: true });
|
|
24395
|
+
var WorkspaceEntrySchema = obj8({
|
|
24396
|
+
name: text3,
|
|
24397
|
+
path: text3,
|
|
24398
|
+
kind: oneOf2(["file", "directory", "symlink"]),
|
|
24399
|
+
protected: opt8(lit3(true))
|
|
23805
24400
|
});
|
|
23806
|
-
var
|
|
23807
|
-
|
|
23808
|
-
|
|
23809
|
-
|
|
23810
|
-
|
|
23811
|
-
}, {
|
|
23812
|
-
var
|
|
23813
|
-
path:
|
|
23814
|
-
|
|
23815
|
-
|
|
23816
|
-
|
|
23817
|
-
|
|
23818
|
-
|
|
23819
|
-
|
|
23820
|
-
|
|
23821
|
-
|
|
23822
|
-
|
|
23823
|
-
|
|
23824
|
-
truncated: bool
|
|
23825
|
-
});
|
|
23826
|
-
var ChangeSummarySchema = Type8.Object({ revision: integer, files: integer, added: integer, removed: integer });
|
|
23827
|
-
var ChangedFileSchema = Type8.Object({
|
|
23828
|
-
path: str,
|
|
23829
|
-
outside: Type8.Optional(Type8.Literal(true)),
|
|
24401
|
+
var WorkspaceDirSchema = obj8({
|
|
24402
|
+
path: text3,
|
|
24403
|
+
entries: arr6(WorkspaceEntrySchema, { maxItems: 1000 }),
|
|
24404
|
+
limited: boolean,
|
|
24405
|
+
incomplete: boolean
|
|
24406
|
+
}, { open: true });
|
|
24407
|
+
var WorkspaceFileSchema = obj8({
|
|
24408
|
+
path: text3,
|
|
24409
|
+
size: number,
|
|
24410
|
+
mtimeMs: number,
|
|
24411
|
+
kind: oneOf2(["text", "binary", "protected"]),
|
|
24412
|
+
content: opt8(text3),
|
|
24413
|
+
truncated: boolean
|
|
24414
|
+
}, { open: true });
|
|
24415
|
+
var ChangeSummarySchema = obj8({ revision: integer, files: integer, added: integer, removed: integer }, { open: true });
|
|
24416
|
+
var ChangedFileSchema = obj8({
|
|
24417
|
+
path: text3,
|
|
24418
|
+
outside: opt8(lit3(true)),
|
|
23830
24419
|
ops: integer,
|
|
23831
24420
|
added: integer,
|
|
23832
24421
|
removed: integer,
|
|
23833
|
-
agents:
|
|
24422
|
+
agents: arr6(text3, { maxItems: 64 }),
|
|
23834
24423
|
lastSeq: integer
|
|
23835
|
-
}, { additionalProperties: false });
|
|
23836
|
-
var ChangeListSchema = Type8.Object({
|
|
23837
|
-
revision: integer,
|
|
23838
|
-
files: Type8.Array(ChangedFileSchema, { maxItems: 500 }),
|
|
23839
|
-
truncated: bool
|
|
23840
24424
|
});
|
|
23841
|
-
var
|
|
24425
|
+
var ChangeListSchema = obj8({
|
|
24426
|
+
revision: integer,
|
|
24427
|
+
files: arr6(ChangedFileSchema, { maxItems: 500 }),
|
|
24428
|
+
truncated: boolean
|
|
24429
|
+
}, { open: true });
|
|
24430
|
+
var ChangeOpSchema = obj8({
|
|
23842
24431
|
seq: integer,
|
|
23843
|
-
agent:
|
|
23844
|
-
tool:
|
|
23845
|
-
diff:
|
|
24432
|
+
agent: text3,
|
|
24433
|
+
tool: oneOf2(["edit", "write"]),
|
|
24434
|
+
diff: text3,
|
|
23846
24435
|
added: integer,
|
|
23847
24436
|
removed: integer,
|
|
23848
|
-
truncated:
|
|
23849
|
-
}, { additionalProperties: false });
|
|
23850
|
-
var ChangeDetailSchema = Type8.Object({
|
|
23851
|
-
path: str,
|
|
23852
|
-
outside: Type8.Optional(Type8.Literal(true)),
|
|
23853
|
-
ops: Type8.Array(ChangeOpSchema, { maxItems: 50 }),
|
|
23854
|
-
truncated: bool
|
|
24437
|
+
truncated: boolean
|
|
23855
24438
|
});
|
|
23856
|
-
var
|
|
24439
|
+
var ChangeDetailSchema = obj8({
|
|
24440
|
+
path: text3,
|
|
24441
|
+
outside: opt8(lit3(true)),
|
|
24442
|
+
ops: arr6(ChangeOpSchema, { maxItems: 50 }),
|
|
24443
|
+
truncated: boolean
|
|
24444
|
+
}, { open: true });
|
|
24445
|
+
var QuestionListSchema = obj8({
|
|
23857
24446
|
revision: integer,
|
|
23858
|
-
pending:
|
|
23859
|
-
});
|
|
23860
|
-
var QuestionRecordSchema =
|
|
24447
|
+
pending: arr6(QuestionSummarySchema, { maxItems: QUESTION_LIMITS.maxPending })
|
|
24448
|
+
}, { open: true });
|
|
24449
|
+
var QuestionRecordSchema = obj8({
|
|
23861
24450
|
id: integer,
|
|
23862
|
-
callId:
|
|
23863
|
-
version:
|
|
23864
|
-
question:
|
|
23865
|
-
multiple:
|
|
23866
|
-
options:
|
|
24451
|
+
callId: text3,
|
|
24452
|
+
version: text3,
|
|
24453
|
+
question: str8({ maxLength: QUESTION_LIMITS.questionChars }),
|
|
24454
|
+
multiple: boolean,
|
|
24455
|
+
options: arr6(QuestionOptionSchema, { maxItems: QUESTION_LIMITS.maxOptions }),
|
|
23867
24456
|
status: questionStatus,
|
|
23868
|
-
answer:
|
|
23869
|
-
|
|
23870
|
-
optionIds:
|
|
23871
|
-
text:
|
|
23872
|
-
}),
|
|
24457
|
+
answer: union4([
|
|
24458
|
+
obj8({
|
|
24459
|
+
optionIds: arr6(str8(), { maxItems: QUESTION_LIMITS.maxOptions }),
|
|
24460
|
+
text: union4([str8({ maxLength: QUESTION_LIMITS.textChars }), nil])
|
|
24461
|
+
}, { open: true }),
|
|
23873
24462
|
nil
|
|
23874
24463
|
]),
|
|
23875
|
-
createdAt:
|
|
23876
|
-
settledAt:
|
|
23877
|
-
});
|
|
23878
|
-
var QuestionResponseSchema =
|
|
23879
|
-
|
|
23880
|
-
kind:
|
|
23881
|
-
optionIds:
|
|
23882
|
-
text:
|
|
23883
|
-
}
|
|
23884
|
-
|
|
24464
|
+
createdAt: number,
|
|
24465
|
+
settledAt: union4([number, nil])
|
|
24466
|
+
}, { open: true });
|
|
24467
|
+
var QuestionResponseSchema = union4([
|
|
24468
|
+
obj8({
|
|
24469
|
+
kind: lit3("answer"),
|
|
24470
|
+
optionIds: opt8(arr6(str8(), { maxItems: QUESTION_LIMITS.maxOptions })),
|
|
24471
|
+
text: opt8(str8({ maxLength: QUESTION_LIMITS.textChars }))
|
|
24472
|
+
}),
|
|
24473
|
+
obj8({ kind: lit3("skip") })
|
|
23885
24474
|
]);
|
|
23886
|
-
var PlanRecordSchema =
|
|
23887
|
-
version:
|
|
23888
|
-
title:
|
|
23889
|
-
steps:
|
|
23890
|
-
note:
|
|
23891
|
-
status:
|
|
23892
|
-
feedback:
|
|
23893
|
-
createdAt:
|
|
23894
|
-
settledAt:
|
|
23895
|
-
});
|
|
23896
|
-
var PlanViewSchema =
|
|
23897
|
-
mode:
|
|
24475
|
+
var PlanRecordSchema = obj8({
|
|
24476
|
+
version: text3,
|
|
24477
|
+
title: str8({ maxLength: PLAN_LIMITS.titleChars }),
|
|
24478
|
+
steps: arr6(str8({ maxLength: PLAN_LIMITS.stepChars }), { maxItems: PLAN_LIMITS.maxSteps }),
|
|
24479
|
+
note: str8({ maxLength: PLAN_LIMITS.noteChars }),
|
|
24480
|
+
status: oneOf2(["awaiting_approval", "approved", "revision_requested", "superseded", "cancelled"]),
|
|
24481
|
+
feedback: union4([str8({ maxLength: PLAN_LIMITS.feedbackChars }), nil]),
|
|
24482
|
+
createdAt: number,
|
|
24483
|
+
settledAt: union4([number, nil])
|
|
24484
|
+
}, { open: true });
|
|
24485
|
+
var PlanViewSchema = obj8({
|
|
24486
|
+
mode: oneOf2(["normal", "plan"]),
|
|
23898
24487
|
revision: integer,
|
|
23899
|
-
current:
|
|
23900
|
-
});
|
|
23901
|
-
var PlanDecisionSchema =
|
|
23902
|
-
|
|
23903
|
-
|
|
24488
|
+
current: union4([PlanRecordSchema, nil])
|
|
24489
|
+
}, { open: true });
|
|
24490
|
+
var PlanDecisionSchema = union4([
|
|
24491
|
+
obj8({ kind: lit3("approve") }),
|
|
24492
|
+
obj8({ kind: lit3("revise"), feedback: str8({ minLength: 1, maxLength: PLAN_LIMITS.feedbackChars }) })
|
|
23904
24493
|
]);
|
|
23905
|
-
var ToolInteractionSchema =
|
|
23906
|
-
|
|
23907
|
-
kind:
|
|
24494
|
+
var ToolInteractionSchema = union4([
|
|
24495
|
+
obj8({
|
|
24496
|
+
kind: lit3("ask_user"),
|
|
23908
24497
|
id: integer,
|
|
23909
|
-
question:
|
|
23910
|
-
multiple:
|
|
23911
|
-
options:
|
|
24498
|
+
question: text3,
|
|
24499
|
+
multiple: boolean,
|
|
24500
|
+
options: arr6(obj8({ id: text3, label: text3, recommended: opt8(boolean) }, { open: true })),
|
|
23912
24501
|
status: questionStatus,
|
|
23913
|
-
optionIds:
|
|
23914
|
-
labels:
|
|
23915
|
-
text:
|
|
23916
|
-
}),
|
|
23917
|
-
|
|
23918
|
-
kind:
|
|
23919
|
-
action:
|
|
24502
|
+
optionIds: opt8(arr6(text3)),
|
|
24503
|
+
labels: opt8(arr6(text3)),
|
|
24504
|
+
text: opt8(union4([text3, nil]))
|
|
24505
|
+
}, { open: true }),
|
|
24506
|
+
obj8({
|
|
24507
|
+
kind: lit3("todo"),
|
|
24508
|
+
action: oneOf2(["list", "replace"]),
|
|
23920
24509
|
revision: integer,
|
|
23921
24510
|
completed: integer,
|
|
23922
24511
|
total: integer
|
|
23923
|
-
}),
|
|
23924
|
-
|
|
23925
|
-
kind:
|
|
23926
|
-
version:
|
|
23927
|
-
title:
|
|
23928
|
-
steps:
|
|
23929
|
-
note:
|
|
23930
|
-
})
|
|
24512
|
+
}, { open: true }),
|
|
24513
|
+
obj8({
|
|
24514
|
+
kind: lit3("submit_plan"),
|
|
24515
|
+
version: text3,
|
|
24516
|
+
title: text3,
|
|
24517
|
+
steps: arr6(text3),
|
|
24518
|
+
note: text3
|
|
24519
|
+
}, { open: true })
|
|
23931
24520
|
]);
|
|
23932
|
-
var ChatViewSchema =
|
|
23933
|
-
historyBefore:
|
|
23934
|
-
agents:
|
|
23935
|
-
jobs:
|
|
23936
|
-
queued:
|
|
23937
|
-
todos:
|
|
23938
|
-
questions:
|
|
23939
|
-
plan:
|
|
23940
|
-
changes:
|
|
23941
|
-
rounds:
|
|
23942
|
-
subagents:
|
|
23943
|
-
taskUsage:
|
|
23944
|
-
model:
|
|
23945
|
-
agent:
|
|
23946
|
-
cwd:
|
|
23947
|
-
busy:
|
|
24521
|
+
var ChatViewSchema = obj8({
|
|
24522
|
+
historyBefore: opt8(union4([integer, nil])),
|
|
24523
|
+
agents: opt8(arr6(SubagentSummarySchema)),
|
|
24524
|
+
jobs: opt8(arr6(JobSummarySchema)),
|
|
24525
|
+
queued: opt8(arr6(QueuedInputSchema)),
|
|
24526
|
+
todos: opt8(TodoListSchema),
|
|
24527
|
+
questions: opt8(QuestionListSchema),
|
|
24528
|
+
plan: opt8(PlanViewSchema),
|
|
24529
|
+
changes: opt8(ChangeSummarySchema),
|
|
24530
|
+
rounds: opt8(arr6(DelegationSchema)),
|
|
24531
|
+
subagents: opt8(arr6(DelegationSchema)),
|
|
24532
|
+
taskUsage: opt8(usage),
|
|
24533
|
+
model: text3,
|
|
24534
|
+
agent: obj8({ model: union4([model2, nil]), thinkingLevel: union4([thinking, nil]) }, { open: true }),
|
|
24535
|
+
cwd: text3,
|
|
24536
|
+
busy: boolean,
|
|
23948
24537
|
status: nullableString,
|
|
23949
24538
|
usage,
|
|
23950
|
-
contextUsage:
|
|
23951
|
-
compaction:
|
|
23952
|
-
failure:
|
|
23953
|
-
active:
|
|
24539
|
+
contextUsage: opt8(obj8({ tokens: union4([number, nil]), window: number, percent: union4([number, nil]) }, { open: true })),
|
|
24540
|
+
compaction: opt8(obj8({
|
|
24541
|
+
failure: opt8(obj8({ taskId: integer, reason: oneOf2(["manual", "threshold", "overflow"]), error: text3 }, { open: true })),
|
|
24542
|
+
active: arr6(obj8({
|
|
23954
24543
|
taskId: integer,
|
|
23955
|
-
reason:
|
|
23956
|
-
blocking:
|
|
24544
|
+
reason: oneOf2(["manual", "threshold", "overflow"]),
|
|
24545
|
+
blocking: boolean,
|
|
23957
24546
|
attempt: integer,
|
|
23958
|
-
retry:
|
|
23959
|
-
})),
|
|
23960
|
-
latest:
|
|
24547
|
+
retry: opt8(obj8({ at: number, error: text3 }, { open: true }))
|
|
24548
|
+
}, { open: true })),
|
|
24549
|
+
latest: union4([
|
|
23961
24550
|
nil,
|
|
23962
|
-
|
|
24551
|
+
obj8({
|
|
23963
24552
|
taskId: integer,
|
|
23964
|
-
phase:
|
|
23965
|
-
|
|
23966
|
-
|
|
24553
|
+
phase: oneOf2([
|
|
24554
|
+
"summarizing",
|
|
24555
|
+
"waiting-to-apply",
|
|
24556
|
+
"applied",
|
|
24557
|
+
"nothing",
|
|
24558
|
+
"skipped",
|
|
24559
|
+
"cancelled",
|
|
24560
|
+
"failed"
|
|
24561
|
+
]),
|
|
24562
|
+
at: number
|
|
24563
|
+
}, { open: true })
|
|
23967
24564
|
])
|
|
23968
|
-
})),
|
|
23969
|
-
|
|
23970
|
-
|
|
23971
|
-
|
|
23972
|
-
|
|
23973
|
-
|
|
24565
|
+
}, { open: true })),
|
|
24566
|
+
runFailure: opt8(obj8({ reason: text3, detail: opt8(text3) }, { open: true })),
|
|
24567
|
+
continuable: opt8(lit3(true)),
|
|
24568
|
+
items: arr6(union4([
|
|
24569
|
+
obj8({
|
|
24570
|
+
type: lit3("user"),
|
|
24571
|
+
order: opt8(number),
|
|
24572
|
+
key: text3,
|
|
23974
24573
|
id: integer,
|
|
23975
|
-
text:
|
|
23976
|
-
images:
|
|
23977
|
-
skill:
|
|
23978
|
-
defaultImagePrompt:
|
|
23979
|
-
}),
|
|
23980
|
-
|
|
23981
|
-
type:
|
|
23982
|
-
order:
|
|
23983
|
-
key:
|
|
24574
|
+
text: text3,
|
|
24575
|
+
images: opt8(arr6(image)),
|
|
24576
|
+
skill: opt8(skill),
|
|
24577
|
+
defaultImagePrompt: opt8(obj8({ version: int5({ minimum: 1 }), text: text3 }, { open: true }))
|
|
24578
|
+
}, { open: true }),
|
|
24579
|
+
obj8({
|
|
24580
|
+
type: lit3("assistant"),
|
|
24581
|
+
order: opt8(number),
|
|
24582
|
+
key: text3,
|
|
23984
24583
|
id: integer,
|
|
23985
|
-
thinking:
|
|
23986
|
-
text:
|
|
24584
|
+
thinking: text3,
|
|
24585
|
+
text: text3,
|
|
23987
24586
|
stopReason: nullableString,
|
|
23988
24587
|
errorMessage: nullableString,
|
|
23989
24588
|
note: nullableString
|
|
23990
|
-
}),
|
|
23991
|
-
|
|
23992
|
-
type:
|
|
23993
|
-
order:
|
|
23994
|
-
key:
|
|
23995
|
-
images:
|
|
23996
|
-
callId:
|
|
23997
|
-
name:
|
|
23998
|
-
summary:
|
|
24589
|
+
}, { open: true }),
|
|
24590
|
+
obj8({
|
|
24591
|
+
type: lit3("tool"),
|
|
24592
|
+
order: opt8(number),
|
|
24593
|
+
key: text3,
|
|
24594
|
+
images: opt8(arr6(image)),
|
|
24595
|
+
callId: text3,
|
|
24596
|
+
name: text3,
|
|
24597
|
+
summary: text3,
|
|
23999
24598
|
detail: nullableString,
|
|
24000
24599
|
phase,
|
|
24001
|
-
isError:
|
|
24600
|
+
isError: boolean,
|
|
24002
24601
|
output: nullableString,
|
|
24003
24602
|
result: nullableString,
|
|
24004
|
-
durationMs:
|
|
24603
|
+
durationMs: union4([number, nil]),
|
|
24005
24604
|
note: nullableString,
|
|
24006
24605
|
diff: nullableString,
|
|
24007
|
-
diffAdded:
|
|
24008
|
-
diffRemoved:
|
|
24009
|
-
diffTruncated:
|
|
24010
|
-
interaction:
|
|
24011
|
-
|
|
24012
|
-
|
|
24013
|
-
|
|
24014
|
-
|
|
24015
|
-
|
|
24606
|
+
diffAdded: union4([number, nil]),
|
|
24607
|
+
diffRemoved: union4([number, nil]),
|
|
24608
|
+
diffTruncated: opt8(boolean),
|
|
24609
|
+
interaction: opt8(ToolInteractionSchema),
|
|
24610
|
+
codemode: opt8(CodemodeViewSchema)
|
|
24611
|
+
}, { open: true }),
|
|
24612
|
+
obj8({
|
|
24613
|
+
type: lit3("system"),
|
|
24614
|
+
order: opt8(number),
|
|
24615
|
+
key: text3,
|
|
24016
24616
|
id: integer,
|
|
24017
|
-
text:
|
|
24018
|
-
jobId:
|
|
24019
|
-
planDecision:
|
|
24020
|
-
})
|
|
24617
|
+
text: text3,
|
|
24618
|
+
jobId: opt8(text3),
|
|
24619
|
+
planDecision: opt8(obj8({ version: text3, kind: oneOf2(["approve", "revise"]) }))
|
|
24620
|
+
}, { open: true })
|
|
24021
24621
|
])),
|
|
24022
|
-
streaming:
|
|
24023
|
-
});
|
|
24024
|
-
var SessionSummarySchema =
|
|
24025
|
-
workspaceRoot:
|
|
24026
|
-
lastUsedAt:
|
|
24027
|
-
title:
|
|
24028
|
-
firstPromptPreview:
|
|
24029
|
-
createdAt:
|
|
24030
|
-
lastMessageAt:
|
|
24031
|
-
model:
|
|
24032
|
-
status:
|
|
24033
|
-
awaitingAnswer:
|
|
24034
|
-
awaitingPlan:
|
|
24035
|
-
id:
|
|
24036
|
-
});
|
|
24037
|
-
var DirectoryStateSchema =
|
|
24038
|
-
var WorkspaceSummarySchema =
|
|
24039
|
-
var WorkspaceStateSchema =
|
|
24040
|
-
var credentialStatus =
|
|
24041
|
-
savedConfigured:
|
|
24042
|
-
environmentConfigured:
|
|
24043
|
-
source:
|
|
24044
|
-
enabled:
|
|
24045
|
-
});
|
|
24046
|
-
var CredentialStateSchema =
|
|
24622
|
+
streaming: union4([nil, obj8({ thinking: text3, text: text3, toolCalls: arr6(call) }, { open: true })])
|
|
24623
|
+
}, { open: true });
|
|
24624
|
+
var SessionSummarySchema = obj8({
|
|
24625
|
+
workspaceRoot: text3,
|
|
24626
|
+
lastUsedAt: number,
|
|
24627
|
+
title: text3,
|
|
24628
|
+
firstPromptPreview: text3,
|
|
24629
|
+
createdAt: number,
|
|
24630
|
+
lastMessageAt: union4([number, nil]),
|
|
24631
|
+
model: union4([model2, nil]),
|
|
24632
|
+
status: oneOf2(["idle", "running", "error"]),
|
|
24633
|
+
awaitingAnswer: opt8(boolean),
|
|
24634
|
+
awaitingPlan: opt8(boolean),
|
|
24635
|
+
id: text3
|
|
24636
|
+
}, { open: true });
|
|
24637
|
+
var DirectoryStateSchema = obj8({ revision: integer, sessions: arr6(SessionSummarySchema) }, { open: true });
|
|
24638
|
+
var WorkspaceSummarySchema = obj8({ path: text3, createdAt: number }, { open: true });
|
|
24639
|
+
var WorkspaceStateSchema = obj8({ revision: integer, workspaces: arr6(WorkspaceSummarySchema) }, { open: true });
|
|
24640
|
+
var credentialStatus = obj8({
|
|
24641
|
+
savedConfigured: boolean,
|
|
24642
|
+
environmentConfigured: boolean,
|
|
24643
|
+
source: oneOf2(["saved", "environment", "runtime", "keyless", "none"]),
|
|
24644
|
+
enabled: opt8(boolean)
|
|
24645
|
+
}, { open: true });
|
|
24646
|
+
var CredentialStateSchema = obj8({
|
|
24047
24647
|
revision: integer,
|
|
24048
|
-
statuses:
|
|
24049
|
-
});
|
|
24050
|
-
var AttachmentSchema =
|
|
24051
|
-
var chatInput =
|
|
24648
|
+
statuses: map(credentialStatus)
|
|
24649
|
+
}, { open: true });
|
|
24650
|
+
var AttachmentSchema = obj8({ sessionId: text3, attachmentId: text3 }, { open: true });
|
|
24651
|
+
var chatInput = obj8({ sessionId: text3, attachmentId: text3 });
|
|
24052
24652
|
var NekoSessionDirectory = contract("neko.session-directory", {
|
|
24053
24653
|
version: 1,
|
|
24054
|
-
input:
|
|
24654
|
+
input: obj8({}),
|
|
24055
24655
|
variants: { ready: { state: { state: DirectoryStateSchema } } }
|
|
24056
24656
|
});
|
|
24057
24657
|
var NekoSessionManagement = contract("neko.session-management", {
|
|
24058
24658
|
version: 1,
|
|
24059
|
-
input:
|
|
24659
|
+
input: obj8({}),
|
|
24060
24660
|
variants: {
|
|
24061
24661
|
ready: {
|
|
24062
24662
|
methods: {
|
|
24063
|
-
create: rpc(
|
|
24064
|
-
archive: rpc(
|
|
24065
|
-
attach: rpc(
|
|
24663
|
+
create: rpc(obj8({ ...changeProperties, cwd: opt8(text3) }), SessionSummarySchema),
|
|
24664
|
+
archive: rpc(text3, nil),
|
|
24665
|
+
attach: rpc(text3, AttachmentSchema),
|
|
24066
24666
|
detach: rpc(nil, nil),
|
|
24067
|
-
fork: rpc(
|
|
24667
|
+
fork: rpc(text3, SessionSummarySchema)
|
|
24068
24668
|
}
|
|
24069
24669
|
}
|
|
24070
24670
|
}
|
|
24071
24671
|
});
|
|
24072
|
-
var resize =
|
|
24073
|
-
maxWidth:
|
|
24074
|
-
maxHeight:
|
|
24075
|
-
maxBytes:
|
|
24076
|
-
jpegQuality:
|
|
24077
|
-
});
|
|
24078
|
-
var inputLimits =
|
|
24079
|
-
maxRequestBytes:
|
|
24080
|
-
images:
|
|
24081
|
-
resize:
|
|
24082
|
-
maxPerMessage:
|
|
24083
|
-
maxPerRequest:
|
|
24084
|
-
}))
|
|
24085
|
-
});
|
|
24086
|
-
var modelInfo =
|
|
24087
|
-
provider:
|
|
24088
|
-
modelId:
|
|
24089
|
-
name:
|
|
24090
|
-
available:
|
|
24091
|
-
contextWindow:
|
|
24092
|
-
input:
|
|
24093
|
-
inputLimits:
|
|
24094
|
-
reasoning:
|
|
24095
|
-
supportedThinkingLevels:
|
|
24096
|
-
thinkingLevelAdjustments:
|
|
24672
|
+
var resize = obj8({
|
|
24673
|
+
maxWidth: opt8(integer),
|
|
24674
|
+
maxHeight: opt8(integer),
|
|
24675
|
+
maxBytes: opt8(integer),
|
|
24676
|
+
jpegQuality: opt8(integer)
|
|
24677
|
+
}, { open: true });
|
|
24678
|
+
var inputLimits = obj8({
|
|
24679
|
+
maxRequestBytes: opt8(integer),
|
|
24680
|
+
images: opt8(obj8({
|
|
24681
|
+
resize: opt8(resize),
|
|
24682
|
+
maxPerMessage: opt8(integer),
|
|
24683
|
+
maxPerRequest: opt8(integer)
|
|
24684
|
+
}, { open: true }))
|
|
24685
|
+
}, { open: true });
|
|
24686
|
+
var modelInfo = obj8({
|
|
24687
|
+
provider: text3,
|
|
24688
|
+
modelId: text3,
|
|
24689
|
+
name: text3,
|
|
24690
|
+
available: boolean,
|
|
24691
|
+
contextWindow: number,
|
|
24692
|
+
input: arr6(text3),
|
|
24693
|
+
inputLimits: opt8(inputLimits),
|
|
24694
|
+
reasoning: boolean,
|
|
24695
|
+
supportedThinkingLevels: arr6(thinking),
|
|
24696
|
+
thinkingLevelAdjustments: obj8({
|
|
24097
24697
|
off: thinking,
|
|
24098
24698
|
minimal: thinking,
|
|
24099
24699
|
low: thinking,
|
|
@@ -24101,35 +24701,35 @@ var modelInfo = Type8.Object({
|
|
|
24101
24701
|
high: thinking,
|
|
24102
24702
|
xhigh: thinking,
|
|
24103
24703
|
max: thinking
|
|
24104
|
-
})
|
|
24105
|
-
});
|
|
24704
|
+
}, { open: true })
|
|
24705
|
+
}, { open: true });
|
|
24106
24706
|
var NekoModels = contract("neko.models", {
|
|
24107
24707
|
version: 1,
|
|
24108
|
-
input:
|
|
24109
|
-
variants: { ready: { methods: { list: rpc(nil,
|
|
24708
|
+
input: obj8({}),
|
|
24709
|
+
variants: { ready: { methods: { list: rpc(nil, arr6(modelInfo)) } } }
|
|
24110
24710
|
});
|
|
24111
|
-
var imageChunk =
|
|
24711
|
+
var imageChunk = obj8({ data: text3, total: integer, mimeType: text3 }, { open: true });
|
|
24112
24712
|
var NekoSubagent = contract("neko.subagent", {
|
|
24113
24713
|
version: 1,
|
|
24114
|
-
input:
|
|
24115
|
-
sessionId:
|
|
24116
|
-
attachmentId:
|
|
24117
|
-
taskId:
|
|
24118
|
-
agentId:
|
|
24119
|
-
}),
|
|
24714
|
+
input: obj8({
|
|
24715
|
+
sessionId: text3,
|
|
24716
|
+
attachmentId: text3,
|
|
24717
|
+
taskId: opt8(integer),
|
|
24718
|
+
agentId: opt8(text3)
|
|
24719
|
+
}, { open: true }),
|
|
24120
24720
|
variants: {
|
|
24121
24721
|
ready: {
|
|
24122
24722
|
state: { revision: integer },
|
|
24123
24723
|
methods: {
|
|
24124
|
-
chunk: rpc(
|
|
24125
|
-
kind:
|
|
24126
|
-
before:
|
|
24127
|
-
token:
|
|
24724
|
+
chunk: rpc(obj8({
|
|
24725
|
+
kind: oneOf2(["view", "history"]),
|
|
24726
|
+
before: opt8(integer),
|
|
24727
|
+
token: opt8(integer),
|
|
24128
24728
|
offset: integer
|
|
24129
|
-
}),
|
|
24130
|
-
getImage: rpc(
|
|
24131
|
-
decideApproval: rpc(
|
|
24132
|
-
stop: rpc(
|
|
24729
|
+
}, { open: true }), obj8({ token: integer, data: text3, next: union4([integer, nil]) }, { open: true })),
|
|
24730
|
+
getImage: rpc(obj8({ entryId: integer, contentIndex: integer, offset: integer }, { open: true }), imageChunk),
|
|
24731
|
+
decideApproval: rpc(obj8({ id: integer, version: text3, decision: oneOf2(["allowed", "denied"]) }, { open: true }), oneOf2(["pending", "allowed", "denied", "cancelled"])),
|
|
24732
|
+
stop: rpc(union4([nil, obj8({ taskId: integer }, { open: true })]), nil)
|
|
24133
24733
|
}
|
|
24134
24734
|
}
|
|
24135
24735
|
}
|
|
@@ -24141,157 +24741,176 @@ var NekoChat = contract("neko.chat", {
|
|
|
24141
24741
|
ready: {
|
|
24142
24742
|
state: { view: ChatViewSchema },
|
|
24143
24743
|
methods: {
|
|
24144
|
-
submit: rpc(
|
|
24145
|
-
content:
|
|
24146
|
-
images:
|
|
24147
|
-
requestId:
|
|
24148
|
-
whenBusy:
|
|
24149
|
-
}
|
|
24744
|
+
submit: rpc(obj8({
|
|
24745
|
+
content: text3,
|
|
24746
|
+
images: opt8(arr6(text3, { maxItems: 4 })),
|
|
24747
|
+
requestId: opt8(text3),
|
|
24748
|
+
whenBusy: opt8(oneOf2(["steer", "followUp"]))
|
|
24749
|
+
}), nil),
|
|
24150
24750
|
abort: rpc(nil, nil),
|
|
24151
|
-
|
|
24152
|
-
|
|
24153
|
-
|
|
24154
|
-
|
|
24155
|
-
|
|
24156
|
-
|
|
24157
|
-
|
|
24751
|
+
continueRun: rpc(nil, nil),
|
|
24752
|
+
withdraw: rpc(obj8({ id: integer }), WithdrawResultSchema),
|
|
24753
|
+
steer: rpc(obj8({ id: integer }), SteerResultSchema),
|
|
24754
|
+
questionGet: rpc(obj8({ id: integer }), union4([QuestionRecordSchema, nil])),
|
|
24755
|
+
questionRespond: rpc(obj8({ id: integer, version: text3, response: QuestionResponseSchema }), QuestionRecordSchema),
|
|
24756
|
+
planGet: rpc(obj8({ version: text3 }), union4([PlanRecordSchema, nil])),
|
|
24757
|
+
planRespond: rpc(obj8({ version: text3, decision: PlanDecisionSchema }), PlanRecordSchema),
|
|
24758
|
+
planMode: rpc(obj8({ mode: oneOf2(["normal", "plan"]) }), PlanViewSchema),
|
|
24158
24759
|
usage: rpc(nil, usage),
|
|
24159
|
-
workspaceDir: rpc(
|
|
24160
|
-
workspaceFile: rpc(
|
|
24760
|
+
workspaceDir: rpc(obj8({ path: text3 }), WorkspaceDirSchema),
|
|
24761
|
+
workspaceFile: rpc(obj8({ path: text3 }), WorkspaceFileSchema),
|
|
24161
24762
|
changesList: rpc(nil, ChangeListSchema),
|
|
24162
|
-
changeGet: rpc(
|
|
24163
|
-
skills: rpc(nil,
|
|
24164
|
-
jobOutput: rpc(
|
|
24165
|
-
jobStop: rpc(
|
|
24763
|
+
changeGet: rpc(obj8({ path: text3 }), union4([ChangeDetailSchema, nil])),
|
|
24764
|
+
skills: rpc(nil, arr6(obj8({ name: text3, description: text3, location: text3, level }, { open: true }))),
|
|
24765
|
+
jobOutput: rpc(obj8({ jobId: text3, since: opt8(integer) }), JobOutputSchema),
|
|
24766
|
+
jobStop: rpc(obj8({ jobId: text3 }), JobSummarySchema),
|
|
24166
24767
|
configure: rpc(change, nil),
|
|
24167
|
-
compact: rpc(
|
|
24168
|
-
importImage: rpc(
|
|
24169
|
-
draftImage: rpc(
|
|
24170
|
-
beginImage: rpc(
|
|
24171
|
-
appendImage: rpc(
|
|
24172
|
-
finishImage: rpc(
|
|
24173
|
-
releaseImage: rpc(
|
|
24174
|
-
getImage: rpc(
|
|
24768
|
+
compact: rpc(obj8({ instructions: opt8(text3) }), nil),
|
|
24769
|
+
importImage: rpc(text3, obj8({ id: text3, name: text3 }, { open: true })),
|
|
24770
|
+
draftImage: rpc(obj8({ id: text3, offset: integer }), imageChunk),
|
|
24771
|
+
beginImage: rpc(obj8({ name: text3, mimeType: text3, size: int5({ minimum: 1, maximum: 20971520 }) }), text3),
|
|
24772
|
+
appendImage: rpc(obj8({ id: text3, offset: integer, data: str8({ maxLength: 350000 }) }), nil),
|
|
24773
|
+
finishImage: rpc(text3, nil),
|
|
24774
|
+
releaseImage: rpc(text3, nil),
|
|
24775
|
+
getImage: rpc(obj8({ entryId: integer, contentIndex: integer, offset: integer }), imageChunk)
|
|
24175
24776
|
}
|
|
24176
24777
|
}
|
|
24177
24778
|
}
|
|
24178
24779
|
});
|
|
24179
|
-
var browse =
|
|
24180
|
-
var page =
|
|
24181
|
-
path:
|
|
24780
|
+
var browse = obj8({ path: text3, query: opt8(text3), showHidden: opt8(boolean), cursor: opt8(text3) });
|
|
24781
|
+
var page = obj8({
|
|
24782
|
+
path: text3,
|
|
24182
24783
|
parent: nullableString,
|
|
24183
|
-
entries:
|
|
24784
|
+
entries: arr6(obj8({ name: text3, path: text3, error: opt8(text3) }, { open: true })),
|
|
24184
24785
|
next: nullableString
|
|
24185
|
-
});
|
|
24786
|
+
}, { open: true });
|
|
24186
24787
|
var NekoWorkspaces = contract("neko.workspaces", {
|
|
24187
24788
|
version: 2,
|
|
24188
|
-
input:
|
|
24789
|
+
input: obj8({}),
|
|
24189
24790
|
variants: {
|
|
24190
24791
|
ready: {
|
|
24191
24792
|
state: { state: WorkspaceStateSchema },
|
|
24192
24793
|
methods: {
|
|
24193
|
-
add: rpc(
|
|
24194
|
-
remove: rpc(
|
|
24794
|
+
add: rpc(obj8({ path: text3 }), WorkspaceSummarySchema),
|
|
24795
|
+
remove: rpc(obj8({ path: text3 }), nul3()),
|
|
24195
24796
|
browse: rpc(browse, page)
|
|
24196
24797
|
}
|
|
24197
24798
|
}
|
|
24198
24799
|
}
|
|
24199
24800
|
});
|
|
24200
|
-
var provider =
|
|
24801
|
+
var provider = str8({ minLength: 1, maxLength: 64 });
|
|
24201
24802
|
var NekoCredentials = contract("neko.credentials", {
|
|
24202
24803
|
version: 2,
|
|
24203
|
-
input:
|
|
24804
|
+
input: obj8({}),
|
|
24204
24805
|
variants: {
|
|
24205
24806
|
ready: {
|
|
24206
24807
|
state: { state: CredentialStateSchema },
|
|
24207
24808
|
methods: {
|
|
24208
|
-
save: rpc(
|
|
24209
|
-
remove: rpc(
|
|
24210
|
-
setEnabled: rpc(
|
|
24809
|
+
save: rpc(obj8({ provider, key: str8({ minLength: 1, maxLength: 8192 }) }), nil),
|
|
24810
|
+
remove: rpc(obj8({ provider }), nil),
|
|
24811
|
+
setEnabled: rpc(obj8({ provider, enabled: boolean }), nil)
|
|
24211
24812
|
}
|
|
24212
24813
|
}
|
|
24213
24814
|
}
|
|
24214
24815
|
});
|
|
24215
|
-
var SearchSettingsStateSchema =
|
|
24816
|
+
var SearchSettingsStateSchema = obj8({
|
|
24216
24817
|
revision: integer,
|
|
24217
|
-
selected:
|
|
24218
|
-
});
|
|
24818
|
+
selected: oneOf2(["tavily", "deepseek"])
|
|
24819
|
+
}, { open: true });
|
|
24219
24820
|
var NekoSearchSettings = contract("neko.search-settings", {
|
|
24220
24821
|
version: 1,
|
|
24221
|
-
input:
|
|
24822
|
+
input: obj8({}),
|
|
24222
24823
|
variants: {
|
|
24223
24824
|
ready: {
|
|
24224
24825
|
state: { state: SearchSettingsStateSchema },
|
|
24225
24826
|
methods: {
|
|
24226
|
-
set: rpc(
|
|
24827
|
+
set: rpc(obj8({ provider: oneOf2(["tavily", "deepseek"]) }), nil)
|
|
24227
24828
|
}
|
|
24228
24829
|
}
|
|
24229
24830
|
}
|
|
24230
24831
|
});
|
|
24231
|
-
var contextSource =
|
|
24232
|
-
var ContextSettingsStateSchema =
|
|
24832
|
+
var contextSource = oneOf2(["default", "config", "saved"]);
|
|
24833
|
+
var ContextSettingsStateSchema = obj8({
|
|
24233
24834
|
revision: integer,
|
|
24234
|
-
effective:
|
|
24235
|
-
compaction:
|
|
24236
|
-
enabled:
|
|
24237
|
-
triggerPercent:
|
|
24835
|
+
effective: obj8({
|
|
24836
|
+
compaction: obj8({
|
|
24837
|
+
enabled: boolean,
|
|
24838
|
+
triggerPercent: union4([integer, nil]),
|
|
24238
24839
|
keepRecentTokens: integer
|
|
24239
|
-
}),
|
|
24240
|
-
pruning:
|
|
24241
|
-
enabled:
|
|
24840
|
+
}, { open: true }),
|
|
24841
|
+
pruning: obj8({
|
|
24842
|
+
enabled: boolean,
|
|
24242
24843
|
triggerPercent: integer,
|
|
24243
24844
|
keepRecent: integer,
|
|
24244
24845
|
minChars: integer,
|
|
24245
24846
|
minSavePercent: integer
|
|
24246
|
-
})
|
|
24247
|
-
}),
|
|
24248
|
-
sources:
|
|
24249
|
-
compaction:
|
|
24250
|
-
pruning:
|
|
24847
|
+
}, { open: true })
|
|
24848
|
+
}, { open: true }),
|
|
24849
|
+
sources: obj8({
|
|
24850
|
+
compaction: obj8({ enabled: contextSource, triggerPercent: contextSource, keepRecentTokens: contextSource }, { open: true }),
|
|
24851
|
+
pruning: obj8({
|
|
24251
24852
|
enabled: contextSource,
|
|
24252
24853
|
triggerPercent: contextSource,
|
|
24253
24854
|
keepRecent: contextSource,
|
|
24254
24855
|
minChars: contextSource,
|
|
24255
24856
|
minSavePercent: contextSource
|
|
24256
|
-
})
|
|
24257
|
-
})
|
|
24857
|
+
}, { open: true })
|
|
24858
|
+
}, { open: true })
|
|
24859
|
+
}, { open: true });
|
|
24860
|
+
var nullable = (schema) => union4([schema, nil]);
|
|
24861
|
+
var ContextSettingsPatchSchema = obj8({
|
|
24862
|
+
compaction: opt8(obj8({
|
|
24863
|
+
enabled: opt8(nullable(boolean)),
|
|
24864
|
+
triggerPercent: opt8(nullable(integer)),
|
|
24865
|
+
keepRecentTokens: opt8(nullable(integer))
|
|
24866
|
+
})),
|
|
24867
|
+
pruning: opt8(obj8({
|
|
24868
|
+
enabled: opt8(nullable(boolean)),
|
|
24869
|
+
triggerPercent: opt8(nullable(integer)),
|
|
24870
|
+
keepRecent: opt8(nullable(integer)),
|
|
24871
|
+
minChars: opt8(nullable(integer)),
|
|
24872
|
+
minSavePercent: opt8(nullable(integer))
|
|
24873
|
+
}))
|
|
24258
24874
|
});
|
|
24259
|
-
var nullable = (schema) => Type8.Union([schema, nil]);
|
|
24260
|
-
var ContextSettingsPatchSchema = Type8.Object({
|
|
24261
|
-
compaction: Type8.Optional(Type8.Object({
|
|
24262
|
-
enabled: Type8.Optional(nullable(bool)),
|
|
24263
|
-
triggerPercent: Type8.Optional(nullable(integer)),
|
|
24264
|
-
keepRecentTokens: Type8.Optional(nullable(integer))
|
|
24265
|
-
}, { additionalProperties: false })),
|
|
24266
|
-
pruning: Type8.Optional(Type8.Object({
|
|
24267
|
-
enabled: Type8.Optional(nullable(bool)),
|
|
24268
|
-
triggerPercent: Type8.Optional(nullable(integer)),
|
|
24269
|
-
keepRecent: Type8.Optional(nullable(integer)),
|
|
24270
|
-
minChars: Type8.Optional(nullable(integer)),
|
|
24271
|
-
minSavePercent: Type8.Optional(nullable(integer))
|
|
24272
|
-
}, { additionalProperties: false }))
|
|
24273
|
-
}, { additionalProperties: false });
|
|
24274
24875
|
var NekoContextSettings = contract("neko.context-settings", {
|
|
24275
24876
|
version: 1,
|
|
24276
|
-
input:
|
|
24877
|
+
input: obj8({}),
|
|
24277
24878
|
variants: {
|
|
24278
24879
|
ready: {
|
|
24279
24880
|
state: { state: ContextSettingsStateSchema },
|
|
24280
24881
|
methods: {
|
|
24281
24882
|
set: rpc(ContextSettingsPatchSchema, nil),
|
|
24282
|
-
reset: rpc(
|
|
24883
|
+
reset: rpc(obj8({}), nil)
|
|
24884
|
+
}
|
|
24885
|
+
}
|
|
24886
|
+
}
|
|
24887
|
+
});
|
|
24888
|
+
var CodemodeSettingsStateSchema = obj8({
|
|
24889
|
+
revision: integer,
|
|
24890
|
+
effective: obj8({ mode: oneOf2([...CODEMODE_MODES]) }, { open: true }),
|
|
24891
|
+
source: oneOf2(["default", "config", "saved"])
|
|
24892
|
+
}, { open: true });
|
|
24893
|
+
var NekoCodemodeSettings = contract("neko.codemode-settings", {
|
|
24894
|
+
version: 1,
|
|
24895
|
+
input: obj8({}),
|
|
24896
|
+
variants: {
|
|
24897
|
+
ready: {
|
|
24898
|
+
state: { state: CodemodeSettingsStateSchema },
|
|
24899
|
+
methods: {
|
|
24900
|
+
set: rpc(obj8({ mode: oneOf2([...CODEMODE_MODES]) }), nil),
|
|
24901
|
+
reset: rpc(obj8({}), nil)
|
|
24283
24902
|
}
|
|
24284
24903
|
}
|
|
24285
24904
|
}
|
|
24286
24905
|
});
|
|
24287
|
-
var defaultModelSource =
|
|
24288
|
-
var DefaultModelStateSchema =
|
|
24906
|
+
var defaultModelSource = oneOf2(["cli", "saved", "config", "default"]);
|
|
24907
|
+
var DefaultModelStateSchema = obj8({
|
|
24289
24908
|
effective: model2,
|
|
24290
24909
|
source: defaultModelSource
|
|
24291
|
-
});
|
|
24910
|
+
}, { open: true });
|
|
24292
24911
|
var NekoDefaultModel = contract("neko.default-model", {
|
|
24293
24912
|
version: 1,
|
|
24294
|
-
input:
|
|
24913
|
+
input: obj8({}),
|
|
24295
24914
|
variants: {
|
|
24296
24915
|
ready: {
|
|
24297
24916
|
state: { state: DefaultModelStateSchema },
|
|
@@ -24302,74 +24921,76 @@ var NekoDefaultModel = contract("neko.default-model", {
|
|
|
24302
24921
|
}
|
|
24303
24922
|
}
|
|
24304
24923
|
});
|
|
24305
|
-
var FileCandidatesSchema =
|
|
24306
|
-
entries:
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
|
|
24924
|
+
var FileCandidatesSchema = obj8({
|
|
24925
|
+
entries: arr6(obj8({ name: text3, path: text3, kind: oneOf2(["file", "directory"]) }, { open: true }), {
|
|
24926
|
+
maxItems: 100
|
|
24927
|
+
}),
|
|
24928
|
+
limited: boolean,
|
|
24929
|
+
incomplete: boolean
|
|
24930
|
+
}, { open: true });
|
|
24310
24931
|
var NekoWorkspaceFiles = contract("neko.workspace-files", {
|
|
24311
24932
|
version: 1,
|
|
24312
|
-
input:
|
|
24933
|
+
input: obj8({}),
|
|
24313
24934
|
variants: {
|
|
24314
24935
|
ready: {
|
|
24315
24936
|
methods: {
|
|
24316
|
-
search: rpc(
|
|
24937
|
+
search: rpc(obj8({ workspaceRoot: text3, query: text3 }), FileCandidatesSchema)
|
|
24317
24938
|
}
|
|
24318
24939
|
}
|
|
24319
24940
|
}
|
|
24320
24941
|
});
|
|
24321
|
-
var marketSkill =
|
|
24322
|
-
name:
|
|
24323
|
-
description:
|
|
24324
|
-
category:
|
|
24325
|
-
source:
|
|
24326
|
-
license:
|
|
24327
|
-
version:
|
|
24328
|
-
sha256:
|
|
24942
|
+
var marketSkill = obj8({
|
|
24943
|
+
name: text3,
|
|
24944
|
+
description: text3,
|
|
24945
|
+
category: text3,
|
|
24946
|
+
source: text3,
|
|
24947
|
+
license: text3,
|
|
24948
|
+
version: text3,
|
|
24949
|
+
sha256: text3,
|
|
24329
24950
|
sizeBytes: integer,
|
|
24330
|
-
uploadedAt:
|
|
24331
|
-
installed:
|
|
24332
|
-
activeLevel:
|
|
24333
|
-
});
|
|
24334
|
-
var preview =
|
|
24335
|
-
var scope =
|
|
24336
|
-
var installResult =
|
|
24951
|
+
uploadedAt: text3,
|
|
24952
|
+
installed: obj8({ project: boolean, user: boolean, builtin: boolean }, { open: true }),
|
|
24953
|
+
activeLevel: union4([level, nil])
|
|
24954
|
+
}, { open: true });
|
|
24955
|
+
var preview = obj8({ body: text3, files: arr6(text3) }, { open: true });
|
|
24956
|
+
var scope = oneOf2(["user", "project"]);
|
|
24957
|
+
var installResult = obj8({ name: text3, scope, path: text3, shadowedBy: opt8(scope) }, { open: true });
|
|
24337
24958
|
var NekoSkillMarket = contract("neko.skill-market", {
|
|
24338
24959
|
version: 1,
|
|
24339
|
-
input:
|
|
24960
|
+
input: obj8({}),
|
|
24340
24961
|
variants: {
|
|
24341
24962
|
ready: {
|
|
24342
24963
|
methods: {
|
|
24343
|
-
list: rpc(
|
|
24344
|
-
detail: rpc(
|
|
24345
|
-
preview: rpc(
|
|
24346
|
-
install: rpc(
|
|
24347
|
-
uninstall: rpc(
|
|
24964
|
+
list: rpc(obj8({ query: opt8(text3), workspaceRoot: opt8(text3) }), arr6(marketSkill)),
|
|
24965
|
+
detail: rpc(obj8({ name: text3, workspaceRoot: opt8(text3) }), marketSkill),
|
|
24966
|
+
preview: rpc(obj8({ name: text3 }), preview),
|
|
24967
|
+
install: rpc(obj8({ name: text3, scope, workspaceRoot: opt8(text3), overwrite: opt8(boolean) }), installResult),
|
|
24968
|
+
uninstall: rpc(obj8({ name: text3, scope, workspaceRoot: opt8(text3) }), nil)
|
|
24348
24969
|
}
|
|
24349
24970
|
}
|
|
24350
24971
|
}
|
|
24351
24972
|
});
|
|
24352
|
-
var ShellStatusSchema =
|
|
24353
|
-
|
|
24354
|
-
|
|
24355
|
-
status:
|
|
24356
|
-
reason:
|
|
24357
|
-
detail:
|
|
24358
|
-
})
|
|
24973
|
+
var ShellStatusSchema = union4([
|
|
24974
|
+
obj8({ status: lit3("ready"), path: text3, source: oneOf2(["config", "auto"]) }, { open: true }),
|
|
24975
|
+
obj8({
|
|
24976
|
+
status: lit3("missing"),
|
|
24977
|
+
reason: oneOf2(["not_found", "invalid_config"]),
|
|
24978
|
+
detail: opt8(text3)
|
|
24979
|
+
}, { open: true })
|
|
24359
24980
|
]);
|
|
24360
|
-
var ApplicationInfoSchema =
|
|
24361
|
-
runningVersion:
|
|
24981
|
+
var ApplicationInfoSchema = obj8({
|
|
24982
|
+
runningVersion: text3,
|
|
24362
24983
|
installedVersion: nullableString,
|
|
24363
|
-
protocolVersion:
|
|
24984
|
+
protocolVersion: int5({ minimum: 1 }),
|
|
24364
24985
|
latestVersion: nullableString,
|
|
24365
|
-
checkedAt:
|
|
24366
|
-
checkState:
|
|
24367
|
-
serverId:
|
|
24368
|
-
shell:
|
|
24369
|
-
});
|
|
24986
|
+
checkedAt: union4([integer, nil]),
|
|
24987
|
+
checkState: oneOf2(["unknown", "checking", "ok", "failed", "development"]),
|
|
24988
|
+
serverId: text3,
|
|
24989
|
+
shell: opt8(ShellStatusSchema)
|
|
24990
|
+
}, { open: true });
|
|
24370
24991
|
var NekoApplicationInfo = contract("neko.application-info", {
|
|
24371
24992
|
version: 1,
|
|
24372
|
-
input:
|
|
24993
|
+
input: obj8({}, { open: true }),
|
|
24373
24994
|
variants: {
|
|
24374
24995
|
ready: { state: { info: ApplicationInfoSchema }, methods: { check: rpc(nil, ApplicationInfoSchema) } }
|
|
24375
24996
|
}
|
|
@@ -24383,7 +25004,7 @@ function isServerId(value) {
|
|
|
24383
25004
|
// packages/gateway/src/mobile/admin.ts
|
|
24384
25005
|
import { createHash, timingSafeEqual } from "crypto";
|
|
24385
25006
|
import { ChordError } from "@earendil-works/chord";
|
|
24386
|
-
import {
|
|
25007
|
+
import { arr as arr7, bool as bool4, int as int6, lit as lit4, nul as nul4, obj as obj9, opt as opt9, str as str9, union as union5 } from "@earendil-works/pi-schema";
|
|
24387
25008
|
|
|
24388
25009
|
// packages/gateway/src/principal.ts
|
|
24389
25010
|
var HOST_PRINCIPAL = { kind: "host" };
|
|
@@ -24712,62 +25333,56 @@ class MobileStore {
|
|
|
24712
25333
|
}
|
|
24713
25334
|
|
|
24714
25335
|
// packages/gateway/src/mobile/admin.ts
|
|
24715
|
-
var listenerStateSchema =
|
|
24716
|
-
|
|
24717
|
-
|
|
24718
|
-
|
|
24719
|
-
status:
|
|
24720
|
-
address:
|
|
24721
|
-
port:
|
|
24722
|
-
bindAddress:
|
|
24723
|
-
mode:
|
|
24724
|
-
}),
|
|
24725
|
-
|
|
24726
|
-
|
|
25336
|
+
var listenerStateSchema = union5([
|
|
25337
|
+
obj9({ status: lit4("disabled") }, { open: true }),
|
|
25338
|
+
obj9({ status: lit4("starting") }, { open: true }),
|
|
25339
|
+
obj9({
|
|
25340
|
+
status: lit4("listening"),
|
|
25341
|
+
address: str9(),
|
|
25342
|
+
port: int6({ minimum: 1, maximum: 65535 }),
|
|
25343
|
+
bindAddress: opt9(str9()),
|
|
25344
|
+
mode: opt9(union5([lit4("direct"), lit4("wsl-relay")]))
|
|
25345
|
+
}, { open: true }),
|
|
25346
|
+
obj9({ status: lit4("error"), error: str9() }, { open: true }),
|
|
25347
|
+
obj9({ status: lit4("stopping") }, { open: true })
|
|
24727
25348
|
]);
|
|
24728
|
-
var adminDeviceSchema =
|
|
24729
|
-
deviceId:
|
|
24730
|
-
name:
|
|
24731
|
-
pairedAt:
|
|
24732
|
-
lastSeenAt:
|
|
24733
|
-
online:
|
|
24734
|
-
});
|
|
25349
|
+
var adminDeviceSchema = obj9({
|
|
25350
|
+
deviceId: str9(),
|
|
25351
|
+
name: str9(),
|
|
25352
|
+
pairedAt: int6(),
|
|
25353
|
+
lastSeenAt: int6(),
|
|
25354
|
+
online: bool4()
|
|
25355
|
+
}, { open: true });
|
|
24735
25356
|
var NekoMobileAdmin = contract("neko.mobile-admin", {
|
|
24736
25357
|
version: 1,
|
|
24737
|
-
input:
|
|
25358
|
+
input: obj9({ token: str9() }, { open: true }),
|
|
24738
25359
|
variants: {
|
|
24739
25360
|
admin: {
|
|
24740
25361
|
methods: {
|
|
24741
|
-
state: rpc(
|
|
25362
|
+
state: rpc(nul4(), obj9({
|
|
24742
25363
|
state: listenerStateSchema,
|
|
24743
|
-
candidates:
|
|
24744
|
-
port:
|
|
24745
|
-
certificate:
|
|
24746
|
-
|
|
24747
|
-
|
|
24748
|
-
]),
|
|
24749
|
-
|
|
24750
|
-
|
|
24751
|
-
|
|
24752
|
-
|
|
24753
|
-
|
|
24754
|
-
|
|
24755
|
-
|
|
24756
|
-
|
|
24757
|
-
|
|
24758
|
-
|
|
24759
|
-
}
|
|
24760
|
-
|
|
24761
|
-
|
|
24762
|
-
|
|
24763
|
-
|
|
24764
|
-
|
|
24765
|
-
})),
|
|
24766
|
-
disable: rpc(Type9.Null(), listenerStateSchema),
|
|
24767
|
-
createPairing: rpc(Type9.Null(), Type9.Object({ pairingText: Type9.String(), expiresAt: Type9.Integer() })),
|
|
24768
|
-
cancelPairing: rpc(Type9.Null(), Type9.Null()),
|
|
24769
|
-
revoke: rpc(Type9.Object({ deviceId: Type9.String({ minLength: 1 }) }), Type9.Object({ revoked: Type9.Boolean() })),
|
|
24770
|
-
regenerateCertificate: rpc(Type9.Null(), Type9.Object({ fingerprint: Type9.String(), expiresAt: Type9.Integer() }))
|
|
25364
|
+
candidates: arr7(str9()),
|
|
25365
|
+
port: int6({ minimum: 1, maximum: 65535 }),
|
|
25366
|
+
certificate: union5([obj9({ fingerprint: str9(), expiresAt: int6() }, { open: true }), nul4()]),
|
|
25367
|
+
devices: arr7(adminDeviceSchema),
|
|
25368
|
+
lastConnectedAddress: union5([str9(), nul4()]),
|
|
25369
|
+
wsl: opt9(union5([obj9({ interop: bool4(), error: union5([str9(), nul4()]) }, { open: true }), nul4()]))
|
|
25370
|
+
}, { open: true })),
|
|
25371
|
+
enable: rpc(obj9({
|
|
25372
|
+
address: str9(),
|
|
25373
|
+
port: opt9(int6({ minimum: 1, maximum: 65535 }))
|
|
25374
|
+
}, { open: true }), obj9({
|
|
25375
|
+
status: lit4("listening"),
|
|
25376
|
+
address: str9(),
|
|
25377
|
+
port: int6({ minimum: 1, maximum: 65535 }),
|
|
25378
|
+
bindAddress: opt9(str9()),
|
|
25379
|
+
mode: opt9(union5([lit4("direct"), lit4("wsl-relay")]))
|
|
25380
|
+
}, { open: true })),
|
|
25381
|
+
disable: rpc(nul4(), listenerStateSchema),
|
|
25382
|
+
createPairing: rpc(nul4(), obj9({ pairingText: str9(), expiresAt: int6() }, { open: true })),
|
|
25383
|
+
cancelPairing: rpc(nul4(), nul4()),
|
|
25384
|
+
revoke: rpc(obj9({ deviceId: str9({ minLength: 1 }) }, { open: true }), obj9({ revoked: bool4() }, { open: true })),
|
|
25385
|
+
regenerateCertificate: rpc(nul4(), obj9({ fingerprint: str9(), expiresAt: int6() }, { open: true }))
|
|
24771
25386
|
}
|
|
24772
25387
|
}
|
|
24773
25388
|
}
|
|
@@ -24943,9 +25558,6 @@ import { ChordError as ChordError2 } from "@earendil-works/chord";
|
|
|
24943
25558
|
var messageTime = (session) => session.lastMessageAt ?? session.createdAt;
|
|
24944
25559
|
var byMessage = (a, b) => messageTime(b) - messageTime(a) || Number(b.id) - Number(a.id);
|
|
24945
25560
|
|
|
24946
|
-
// packages/gateway/src/mobile/adapter.ts
|
|
24947
|
-
import { Check as Check2 } from "typebox/value";
|
|
24948
|
-
|
|
24949
25561
|
// packages/gateway/src/subagent-client.ts
|
|
24950
25562
|
function subagentClient(connect) {
|
|
24951
25563
|
let value;
|
|
@@ -25089,16 +25701,29 @@ function subagentClient(connect) {
|
|
|
25089
25701
|
// packages/gateway/src/mobile/projection.ts
|
|
25090
25702
|
import { createHash as createHash2 } from "crypto";
|
|
25091
25703
|
|
|
25704
|
+
// packages/gateway/src/mobile/protocol.ts
|
|
25705
|
+
import {
|
|
25706
|
+
arr as arr8,
|
|
25707
|
+
bool as bool5,
|
|
25708
|
+
compile as compile2,
|
|
25709
|
+
int as int7,
|
|
25710
|
+
lit as lit5,
|
|
25711
|
+
nul as nul5,
|
|
25712
|
+
num as num5,
|
|
25713
|
+
obj as obj10,
|
|
25714
|
+
opt as opt10,
|
|
25715
|
+
str as str10,
|
|
25716
|
+
union as union6
|
|
25717
|
+
} from "@earendil-works/pi-schema";
|
|
25718
|
+
|
|
25092
25719
|
// packages/core/src/application-version.ts
|
|
25093
|
-
var RUNNING_VERSION = "0.5.
|
|
25094
|
-
var APPLICATION_PROTOCOL =
|
|
25720
|
+
var RUNNING_VERSION = "0.5.4";
|
|
25721
|
+
var APPLICATION_PROTOCOL = 10;
|
|
25095
25722
|
function stableVersion(value) {
|
|
25096
25723
|
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)));
|
|
25097
25724
|
}
|
|
25098
25725
|
|
|
25099
25726
|
// packages/gateway/src/mobile/protocol.ts
|
|
25100
|
-
import { Type as Type10 } from "typebox";
|
|
25101
|
-
import { Check } from "typebox/value";
|
|
25102
25727
|
var MOBILE_LIMITS = {
|
|
25103
25728
|
maxFrameBytes: 262144,
|
|
25104
25729
|
maxPayloadBytes: 131072,
|
|
@@ -25122,14 +25747,14 @@ var MOBILE_CAPABILITIES = [
|
|
|
25122
25747
|
var MOBILE_CLOSE_REVOKED = 4401;
|
|
25123
25748
|
var MOBILE_CLOSE_INCOMPATIBLE = 4402;
|
|
25124
25749
|
var MOBILE_CLOSE_SLOW_CONSUMER = 4408;
|
|
25125
|
-
var MobileHelloParams =
|
|
25126
|
-
apiVersions:
|
|
25127
|
-
app:
|
|
25128
|
-
version:
|
|
25129
|
-
platform:
|
|
25130
|
-
build:
|
|
25131
|
-
})
|
|
25132
|
-
});
|
|
25750
|
+
var MobileHelloParams = obj10({
|
|
25751
|
+
apiVersions: arr8(int7(), { minItems: 1 }),
|
|
25752
|
+
app: obj10({
|
|
25753
|
+
version: str10({ minLength: 1, maxLength: 64 }),
|
|
25754
|
+
platform: str10({ minLength: 1, maxLength: 64 }),
|
|
25755
|
+
build: str10({ maxLength: 128 })
|
|
25756
|
+
}, { open: true })
|
|
25757
|
+
}, { open: true });
|
|
25133
25758
|
function asJsonRpcRequest(value) {
|
|
25134
25759
|
if (typeof value !== "object" || value === null)
|
|
25135
25760
|
return;
|
|
@@ -25142,8 +25767,18 @@ function asJsonRpcRequest(value) {
|
|
|
25142
25767
|
return;
|
|
25143
25768
|
return { jsonrpc: "2.0", id: record.id, method: record.method, params: record.params };
|
|
25144
25769
|
}
|
|
25770
|
+
var validators = new WeakMap;
|
|
25771
|
+
function checkSchema(schema, value) {
|
|
25772
|
+
let validator = validators.get(schema);
|
|
25773
|
+
if (!validator) {
|
|
25774
|
+
validator = compile2(schema);
|
|
25775
|
+
validators.set(schema, validator);
|
|
25776
|
+
}
|
|
25777
|
+
return validator.check(value);
|
|
25778
|
+
}
|
|
25779
|
+
var helloParams = compile2(MobileHelloParams);
|
|
25145
25780
|
function isMobileHelloParams(value) {
|
|
25146
|
-
return
|
|
25781
|
+
return helloParams.check(value);
|
|
25147
25782
|
}
|
|
25148
25783
|
function negotiateApiVersion(clientVersions) {
|
|
25149
25784
|
let best;
|
|
@@ -25167,462 +25802,444 @@ function buildHelloResult(serverId, serverName, apiVersion) {
|
|
|
25167
25802
|
limits: MOBILE_LIMITS
|
|
25168
25803
|
};
|
|
25169
25804
|
}
|
|
25170
|
-
var
|
|
25171
|
-
var
|
|
25172
|
-
var
|
|
25173
|
-
var
|
|
25174
|
-
|
|
25175
|
-
|
|
25176
|
-
|
|
25177
|
-
|
|
25178
|
-
|
|
25179
|
-
|
|
25180
|
-
|
|
25181
|
-
|
|
25182
|
-
|
|
25183
|
-
|
|
25184
|
-
|
|
25185
|
-
|
|
25186
|
-
|
|
25187
|
-
|
|
25188
|
-
|
|
25189
|
-
|
|
25190
|
-
|
|
25191
|
-
|
|
25192
|
-
|
|
25193
|
-
|
|
25194
|
-
|
|
25195
|
-
|
|
25196
|
-
Type10.Literal("cancelled")
|
|
25805
|
+
var text4 = str10();
|
|
25806
|
+
var count = int7({ minimum: 0 });
|
|
25807
|
+
var nullable2 = (schema) => union6([schema, nul5()]);
|
|
25808
|
+
var MobileContentRefSchema = obj10({
|
|
25809
|
+
sessionId: text4,
|
|
25810
|
+
agentId: opt10(text4),
|
|
25811
|
+
key: text4,
|
|
25812
|
+
field: text4,
|
|
25813
|
+
digest: text4,
|
|
25814
|
+
bytes: count
|
|
25815
|
+
}, { open: true });
|
|
25816
|
+
var MobileImageRefSchema = obj10({
|
|
25817
|
+
name: text4,
|
|
25818
|
+
mimeType: text4,
|
|
25819
|
+
width: count,
|
|
25820
|
+
height: count,
|
|
25821
|
+
bytes: count,
|
|
25822
|
+
entryId: count,
|
|
25823
|
+
contentIndex: count
|
|
25824
|
+
}, { open: true });
|
|
25825
|
+
var planStatus = union6([
|
|
25826
|
+
lit5("awaiting_approval"),
|
|
25827
|
+
lit5("approved"),
|
|
25828
|
+
lit5("revision_requested"),
|
|
25829
|
+
lit5("superseded"),
|
|
25830
|
+
lit5("cancelled")
|
|
25197
25831
|
]);
|
|
25198
|
-
var questionStatus2 =
|
|
25199
|
-
|
|
25200
|
-
|
|
25201
|
-
|
|
25202
|
-
|
|
25203
|
-
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
kind: Type10.Literal("ask_user"),
|
|
25207
|
-
id: int,
|
|
25208
|
-
question: str2,
|
|
25209
|
-
multiple: Type10.Boolean(),
|
|
25210
|
-
options: Type10.Array(Type10.Object({ id: str2, label: str2, recommended: opt(Type10.Boolean()) })),
|
|
25832
|
+
var questionStatus2 = union6([lit5("pending"), lit5("answered"), lit5("skipped"), lit5("cancelled")]);
|
|
25833
|
+
var MobileToolInteractionSchema = union6([
|
|
25834
|
+
obj10({
|
|
25835
|
+
kind: lit5("ask_user"),
|
|
25836
|
+
id: count,
|
|
25837
|
+
question: text4,
|
|
25838
|
+
multiple: bool5(),
|
|
25839
|
+
options: arr8(obj10({ id: text4, label: text4, recommended: opt10(bool5()) }, { open: true })),
|
|
25211
25840
|
status: questionStatus2,
|
|
25212
|
-
optionIds:
|
|
25213
|
-
labels:
|
|
25214
|
-
text:
|
|
25215
|
-
}),
|
|
25216
|
-
|
|
25217
|
-
kind:
|
|
25218
|
-
action:
|
|
25219
|
-
revision:
|
|
25220
|
-
completed:
|
|
25221
|
-
total:
|
|
25222
|
-
}),
|
|
25223
|
-
|
|
25224
|
-
kind:
|
|
25225
|
-
version:
|
|
25226
|
-
title:
|
|
25227
|
-
steps:
|
|
25228
|
-
note:
|
|
25229
|
-
})
|
|
25841
|
+
optionIds: opt10(arr8(text4)),
|
|
25842
|
+
labels: opt10(arr8(text4)),
|
|
25843
|
+
text: opt10(nullable2(text4))
|
|
25844
|
+
}, { open: true }),
|
|
25845
|
+
obj10({
|
|
25846
|
+
kind: lit5("todo"),
|
|
25847
|
+
action: union6([lit5("list"), lit5("replace")]),
|
|
25848
|
+
revision: count,
|
|
25849
|
+
completed: count,
|
|
25850
|
+
total: count
|
|
25851
|
+
}, { open: true }),
|
|
25852
|
+
obj10({
|
|
25853
|
+
kind: lit5("submit_plan"),
|
|
25854
|
+
version: text4,
|
|
25855
|
+
title: text4,
|
|
25856
|
+
steps: arr8(text4),
|
|
25857
|
+
note: text4
|
|
25858
|
+
}, { open: true })
|
|
25230
25859
|
]);
|
|
25231
|
-
var
|
|
25232
|
-
|
|
25233
|
-
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25238
|
-
|
|
25239
|
-
|
|
25240
|
-
|
|
25241
|
-
|
|
25242
|
-
|
|
25243
|
-
|
|
25244
|
-
|
|
25245
|
-
|
|
25246
|
-
|
|
25247
|
-
|
|
25248
|
-
|
|
25249
|
-
|
|
25250
|
-
|
|
25251
|
-
|
|
25252
|
-
|
|
25253
|
-
|
|
25254
|
-
|
|
25255
|
-
|
|
25256
|
-
|
|
25257
|
-
|
|
25258
|
-
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
25264
|
-
|
|
25265
|
-
|
|
25266
|
-
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25270
|
-
|
|
25271
|
-
|
|
25272
|
-
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
|
|
25276
|
-
|
|
25277
|
-
|
|
25278
|
-
|
|
25279
|
-
|
|
25280
|
-
|
|
25281
|
-
|
|
25282
|
-
|
|
25283
|
-
|
|
25284
|
-
|
|
25285
|
-
|
|
25286
|
-
|
|
25287
|
-
|
|
25288
|
-
|
|
25289
|
-
|
|
25290
|
-
|
|
25291
|
-
|
|
25292
|
-
|
|
25293
|
-
|
|
25294
|
-
|
|
25295
|
-
|
|
25296
|
-
|
|
25297
|
-
|
|
25298
|
-
|
|
25299
|
-
|
|
25300
|
-
|
|
25301
|
-
|
|
25302
|
-
|
|
25303
|
-
|
|
25304
|
-
|
|
25305
|
-
|
|
25306
|
-
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
|
|
25310
|
-
|
|
25311
|
-
|
|
25312
|
-
|
|
25313
|
-
|
|
25314
|
-
|
|
25315
|
-
|
|
25316
|
-
|
|
25317
|
-
|
|
25318
|
-
|
|
25319
|
-
|
|
25320
|
-
|
|
25321
|
-
|
|
25322
|
-
|
|
25323
|
-
|
|
25324
|
-
|
|
25325
|
-
|
|
25326
|
-
|
|
25327
|
-
|
|
25328
|
-
|
|
25860
|
+
var MobileCodemodeSchema = obj10({
|
|
25861
|
+
calls: arr8(obj10({
|
|
25862
|
+
id: count,
|
|
25863
|
+
name: text4,
|
|
25864
|
+
args: str10({ maxLength: CODEMODE_VIEW_LIMITS.argsChars }),
|
|
25865
|
+
status: union6([lit5("running"), lit5("ok"), lit5("error"), lit5("cancelled")]),
|
|
25866
|
+
durationMs: opt10(num5()),
|
|
25867
|
+
error: opt10(str10({ maxLength: CODEMODE_VIEW_LIMITS.errorChars }))
|
|
25868
|
+
}, { open: true }), { maxItems: CODEMODE_VIEW_LIMITS.maxCalls }),
|
|
25869
|
+
omitted: count,
|
|
25870
|
+
fullOutputPath: opt10(text4)
|
|
25871
|
+
}, { open: true });
|
|
25872
|
+
var MobileToolItemSchema = obj10({
|
|
25873
|
+
callId: text4,
|
|
25874
|
+
name: text4,
|
|
25875
|
+
summary: text4,
|
|
25876
|
+
status: union6([lit5("running"), lit5("done"), lit5("error")]),
|
|
25877
|
+
detail: opt10(text4),
|
|
25878
|
+
output: opt10(text4),
|
|
25879
|
+
result: opt10(text4),
|
|
25880
|
+
diff: opt10(text4),
|
|
25881
|
+
diffAdded: opt10(num5()),
|
|
25882
|
+
diffRemoved: opt10(num5()),
|
|
25883
|
+
diffTruncated: opt10(bool5()),
|
|
25884
|
+
durationMs: opt10(num5()),
|
|
25885
|
+
note: opt10(text4),
|
|
25886
|
+
interaction: opt10(MobileToolInteractionSchema),
|
|
25887
|
+
codemode: opt10(MobileCodemodeSchema)
|
|
25888
|
+
}, { open: true });
|
|
25889
|
+
var MobileChatItemSchema = obj10({
|
|
25890
|
+
key: text4,
|
|
25891
|
+
type: union6([lit5("user"), lit5("assistant"), lit5("tool"), lit5("error"), lit5("system")]),
|
|
25892
|
+
text: opt10(text4),
|
|
25893
|
+
thinking: opt10(text4),
|
|
25894
|
+
note: opt10(text4),
|
|
25895
|
+
error: opt10(text4),
|
|
25896
|
+
skill: opt10(text4),
|
|
25897
|
+
jobId: opt10(text4),
|
|
25898
|
+
tool: opt10(MobileToolItemSchema),
|
|
25899
|
+
images: opt10(arr8(MobileImageRefSchema)),
|
|
25900
|
+
refs: opt10(arr8(MobileContentRefSchema))
|
|
25901
|
+
}, { open: true });
|
|
25902
|
+
var MobileStreamingSchema = obj10({
|
|
25903
|
+
text: text4,
|
|
25904
|
+
thinking: text4,
|
|
25905
|
+
textOmitted: count,
|
|
25906
|
+
thinkingOmitted: count,
|
|
25907
|
+
toolCalls: arr8(obj10({
|
|
25908
|
+
callId: text4,
|
|
25909
|
+
name: text4,
|
|
25910
|
+
summary: text4,
|
|
25911
|
+
status: union6([lit5("running"), lit5("done")])
|
|
25912
|
+
}, { open: true }))
|
|
25913
|
+
}, { open: true });
|
|
25914
|
+
var MobileUsageSchema = obj10({
|
|
25915
|
+
input: count,
|
|
25916
|
+
output: count,
|
|
25917
|
+
cacheRead: count,
|
|
25918
|
+
cacheWrite: count,
|
|
25919
|
+
totalTokens: count,
|
|
25920
|
+
cost: num5({ minimum: 0 })
|
|
25921
|
+
}, { open: true });
|
|
25922
|
+
var MobileSubagentRoundSchema = obj10({
|
|
25923
|
+
taskId: count,
|
|
25924
|
+
callId: text4,
|
|
25925
|
+
agentId: text4,
|
|
25926
|
+
round: opt10(count),
|
|
25927
|
+
role: text4,
|
|
25928
|
+
title: text4,
|
|
25929
|
+
status: union6([lit5("queued"), lit5("running"), lit5("completed"), lit5("failed"), lit5("cancelled")]),
|
|
25930
|
+
approvalCount: count,
|
|
25931
|
+
readonly: bool5(),
|
|
25932
|
+
createdAt: num5(),
|
|
25933
|
+
endedAt: nullable2(num5()),
|
|
25934
|
+
usage: opt10(MobileUsageSchema)
|
|
25935
|
+
}, { open: true });
|
|
25936
|
+
var MobileAgentSchema = obj10({
|
|
25937
|
+
agentId: text4,
|
|
25938
|
+
role: text4,
|
|
25939
|
+
title: text4,
|
|
25940
|
+
status: union6([lit5("idle"), lit5("queued"), lit5("running")]),
|
|
25941
|
+
activeRoundId: nullable2(count),
|
|
25942
|
+
lastRoundId: count,
|
|
25943
|
+
roundCount: count,
|
|
25944
|
+
approvalCount: count
|
|
25945
|
+
}, { open: true });
|
|
25946
|
+
var MobileQueuedSchema = obj10({
|
|
25947
|
+
id: count,
|
|
25948
|
+
mode: union6([lit5("steer"), lit5("followUp")]),
|
|
25949
|
+
preview: str10(),
|
|
25950
|
+
images: count
|
|
25951
|
+
}, { open: true });
|
|
25952
|
+
var mobileChatStatusProperties = {
|
|
25953
|
+
busy: bool5(),
|
|
25954
|
+
queued: opt10(arr8(MobileQueuedSchema)),
|
|
25955
|
+
todos: opt10(obj10({ revision: count, count, completed: count }, { open: true })),
|
|
25956
|
+
questions: opt10(obj10({ revision: count, pendingCount: count }, { open: true })),
|
|
25957
|
+
plan: opt10(obj10({ revision: count, pending: bool5(), version: opt10(str10({ minLength: 1 })) }, { open: true })),
|
|
25958
|
+
status: nullable2(text4),
|
|
25329
25959
|
usage: MobileUsageSchema,
|
|
25330
|
-
taskUsage:
|
|
25331
|
-
contextUsage:
|
|
25332
|
-
agent:
|
|
25333
|
-
subagents:
|
|
25334
|
-
agents:
|
|
25335
|
-
approvalCount:
|
|
25336
|
-
compaction:
|
|
25337
|
-
|
|
25338
|
-
|
|
25339
|
-
|
|
25340
|
-
|
|
25341
|
-
|
|
25342
|
-
|
|
25960
|
+
taskUsage: opt10(MobileUsageSchema),
|
|
25961
|
+
contextUsage: opt10(obj10({ tokens: nullable2(num5()), window: num5(), percent: nullable2(num5()) }, { open: true })),
|
|
25962
|
+
agent: obj10({ model: nullable2(text4), thinkingLevel: nullable2(text4) }, { open: true }),
|
|
25963
|
+
subagents: arr8(MobileSubagentRoundSchema),
|
|
25964
|
+
agents: arr8(MobileAgentSchema),
|
|
25965
|
+
approvalCount: count,
|
|
25966
|
+
compaction: opt10(obj10({ phase: text4, at: num5() }, { open: true })),
|
|
25967
|
+
runFailure: opt10(obj10({ reason: text4, detail: opt10(text4) }, { open: true })),
|
|
25968
|
+
readonly: opt10(bool5())
|
|
25969
|
+
};
|
|
25970
|
+
var MobileChatStatusSchema = obj10(mobileChatStatusProperties, { open: true });
|
|
25971
|
+
var MobileChatSnapshotSchema = obj10({
|
|
25972
|
+
...mobileChatStatusProperties,
|
|
25973
|
+
items: arr8(MobileChatItemSchema),
|
|
25974
|
+
historyBefore: nullable2(text4),
|
|
25343
25975
|
streaming: nullable2(MobileStreamingSchema)
|
|
25344
|
-
});
|
|
25345
|
-
var MobileWorkspaceSchema =
|
|
25346
|
-
var MobileSessionSummarySchema =
|
|
25347
|
-
id:
|
|
25348
|
-
workspace:
|
|
25349
|
-
title:
|
|
25350
|
-
preview:
|
|
25351
|
-
lastUsedAt:
|
|
25352
|
-
lastMessageAt:
|
|
25353
|
-
archived:
|
|
25354
|
-
awaitingAnswer:
|
|
25355
|
-
awaitingPlan:
|
|
25356
|
-
});
|
|
25357
|
-
var MobileApprovalSchema =
|
|
25358
|
-
id:
|
|
25359
|
-
version:
|
|
25360
|
-
taskId:
|
|
25361
|
-
agentId:
|
|
25362
|
-
title:
|
|
25363
|
-
command:
|
|
25364
|
-
cwd:
|
|
25365
|
-
timeoutSeconds:
|
|
25366
|
-
requestedAt:
|
|
25367
|
-
});
|
|
25368
|
-
var MobileTodoItemSchema =
|
|
25369
|
-
id:
|
|
25370
|
-
text:
|
|
25371
|
-
status:
|
|
25372
|
-
});
|
|
25373
|
-
var MobileTodoListSchema =
|
|
25374
|
-
revision:
|
|
25375
|
-
items:
|
|
25376
|
-
});
|
|
25377
|
-
var MobileQuestionOptionSchema =
|
|
25378
|
-
id:
|
|
25379
|
-
label:
|
|
25380
|
-
description:
|
|
25381
|
-
recommended:
|
|
25382
|
-
});
|
|
25383
|
-
var MobileQuestionSummarySchema =
|
|
25384
|
-
id:
|
|
25385
|
-
version:
|
|
25386
|
-
preview:
|
|
25387
|
-
multiple:
|
|
25388
|
-
optionCount:
|
|
25389
|
-
createdAt:
|
|
25390
|
-
});
|
|
25391
|
-
var MobileQuestionListSchema =
|
|
25392
|
-
revision:
|
|
25393
|
-
pending:
|
|
25394
|
-
});
|
|
25395
|
-
var MobileQuestionSchema =
|
|
25396
|
-
id:
|
|
25397
|
-
callId:
|
|
25398
|
-
version:
|
|
25399
|
-
question:
|
|
25400
|
-
multiple:
|
|
25401
|
-
options:
|
|
25976
|
+
}, { open: true });
|
|
25977
|
+
var MobileWorkspaceSchema = obj10({ root: text4, name: text4 }, { open: true });
|
|
25978
|
+
var MobileSessionSummarySchema = obj10({
|
|
25979
|
+
id: text4,
|
|
25980
|
+
workspace: text4,
|
|
25981
|
+
title: text4,
|
|
25982
|
+
preview: text4,
|
|
25983
|
+
lastUsedAt: int7(),
|
|
25984
|
+
lastMessageAt: int7(),
|
|
25985
|
+
archived: bool5(),
|
|
25986
|
+
awaitingAnswer: opt10(bool5()),
|
|
25987
|
+
awaitingPlan: opt10(bool5())
|
|
25988
|
+
}, { open: true });
|
|
25989
|
+
var MobileApprovalSchema = obj10({
|
|
25990
|
+
id: count,
|
|
25991
|
+
version: text4,
|
|
25992
|
+
taskId: count,
|
|
25993
|
+
agentId: opt10(text4),
|
|
25994
|
+
title: opt10(text4),
|
|
25995
|
+
command: text4,
|
|
25996
|
+
cwd: text4,
|
|
25997
|
+
timeoutSeconds: opt10(num5({ minimum: 0 })),
|
|
25998
|
+
requestedAt: num5()
|
|
25999
|
+
}, { open: true });
|
|
26000
|
+
var MobileTodoItemSchema = obj10({
|
|
26001
|
+
id: str10({ minLength: 1, maxLength: TODO_LIMITS.idChars }),
|
|
26002
|
+
text: str10({ minLength: 1, maxLength: TODO_LIMITS.textChars }),
|
|
26003
|
+
status: union6([lit5("pending"), lit5("in_progress"), lit5("completed")])
|
|
26004
|
+
}, { open: true });
|
|
26005
|
+
var MobileTodoListSchema = obj10({
|
|
26006
|
+
revision: count,
|
|
26007
|
+
items: arr8(MobileTodoItemSchema, { maxItems: TODO_LIMITS.maxItems })
|
|
26008
|
+
}, { open: true });
|
|
26009
|
+
var MobileQuestionOptionSchema = obj10({
|
|
26010
|
+
id: str10({ minLength: 1, maxLength: QUESTION_LIMITS.optionIdChars }),
|
|
26011
|
+
label: str10({ minLength: 1, maxLength: QUESTION_LIMITS.labelChars }),
|
|
26012
|
+
description: opt10(str10({ maxLength: QUESTION_LIMITS.descriptionChars })),
|
|
26013
|
+
recommended: opt10(bool5())
|
|
26014
|
+
}, { open: true });
|
|
26015
|
+
var MobileQuestionSummarySchema = obj10({
|
|
26016
|
+
id: count,
|
|
26017
|
+
version: text4,
|
|
26018
|
+
preview: str10({ maxLength: QUESTION_LIMITS.previewChars }),
|
|
26019
|
+
multiple: bool5(),
|
|
26020
|
+
optionCount: count,
|
|
26021
|
+
createdAt: num5()
|
|
26022
|
+
}, { open: true });
|
|
26023
|
+
var MobileQuestionListSchema = obj10({
|
|
26024
|
+
revision: count,
|
|
26025
|
+
pending: arr8(MobileQuestionSummarySchema, { maxItems: QUESTION_LIMITS.maxPending })
|
|
26026
|
+
}, { open: true });
|
|
26027
|
+
var MobileQuestionSchema = obj10({
|
|
26028
|
+
id: count,
|
|
26029
|
+
callId: text4,
|
|
26030
|
+
version: text4,
|
|
26031
|
+
question: str10({ maxLength: QUESTION_LIMITS.questionChars }),
|
|
26032
|
+
multiple: bool5(),
|
|
26033
|
+
options: arr8(MobileQuestionOptionSchema, { maxItems: QUESTION_LIMITS.maxOptions }),
|
|
25402
26034
|
status: questionStatus2,
|
|
25403
|
-
answer: nullable2(
|
|
25404
|
-
optionIds:
|
|
25405
|
-
text: nullable2(
|
|
25406
|
-
})),
|
|
25407
|
-
createdAt:
|
|
25408
|
-
settledAt: nullable2(
|
|
25409
|
-
});
|
|
25410
|
-
var MobileQuestionResponseSchema =
|
|
25411
|
-
|
|
25412
|
-
kind:
|
|
25413
|
-
optionIds:
|
|
25414
|
-
text:
|
|
25415
|
-
}
|
|
25416
|
-
|
|
26035
|
+
answer: nullable2(obj10({
|
|
26036
|
+
optionIds: arr8(str10(), { maxItems: QUESTION_LIMITS.maxOptions }),
|
|
26037
|
+
text: nullable2(str10({ maxLength: QUESTION_LIMITS.textChars }))
|
|
26038
|
+
}, { open: true })),
|
|
26039
|
+
createdAt: num5(),
|
|
26040
|
+
settledAt: nullable2(num5())
|
|
26041
|
+
}, { open: true });
|
|
26042
|
+
var MobileQuestionResponseSchema = union6([
|
|
26043
|
+
obj10({
|
|
26044
|
+
kind: lit5("answer"),
|
|
26045
|
+
optionIds: opt10(arr8(str10(), { maxItems: QUESTION_LIMITS.maxOptions })),
|
|
26046
|
+
text: opt10(str10({ maxLength: QUESTION_LIMITS.textChars }))
|
|
26047
|
+
}),
|
|
26048
|
+
obj10({ kind: lit5("skip") })
|
|
25417
26049
|
]);
|
|
25418
|
-
var MobilePlanSchema =
|
|
25419
|
-
version:
|
|
25420
|
-
title:
|
|
25421
|
-
steps:
|
|
25422
|
-
note:
|
|
26050
|
+
var MobilePlanSchema = obj10({
|
|
26051
|
+
version: str10({ minLength: 1 }),
|
|
26052
|
+
title: str10({ maxLength: PLAN_LIMITS.titleChars }),
|
|
26053
|
+
steps: arr8(str10({ maxLength: PLAN_LIMITS.stepChars }), { maxItems: PLAN_LIMITS.maxSteps }),
|
|
26054
|
+
note: str10({ maxLength: PLAN_LIMITS.noteChars }),
|
|
25423
26055
|
status: planStatus,
|
|
25424
|
-
feedback: nullable2(
|
|
25425
|
-
createdAt:
|
|
25426
|
-
settledAt: nullable2(
|
|
25427
|
-
});
|
|
25428
|
-
var MobilePlanDecisionSchema =
|
|
25429
|
-
|
|
25430
|
-
|
|
26056
|
+
feedback: nullable2(str10({ maxLength: PLAN_LIMITS.feedbackChars })),
|
|
26057
|
+
createdAt: num5(),
|
|
26058
|
+
settledAt: nullable2(num5())
|
|
26059
|
+
}, { open: true });
|
|
26060
|
+
var MobilePlanDecisionSchema = union6([
|
|
26061
|
+
obj10({ kind: lit5("approve") }),
|
|
26062
|
+
obj10({ kind: lit5("revise"), feedback: str10({ minLength: 1, maxLength: PLAN_LIMITS.feedbackChars }) })
|
|
25431
26063
|
]);
|
|
25432
|
-
var sessionListParams =
|
|
25433
|
-
workspace:
|
|
25434
|
-
query:
|
|
25435
|
-
cursor:
|
|
25436
|
-
});
|
|
25437
|
-
var sessionListResult =
|
|
25438
|
-
sessions:
|
|
25439
|
-
nextCursor:
|
|
25440
|
-
});
|
|
25441
|
-
var subscription = { subscriptionId:
|
|
25442
|
-
var pageResult =
|
|
25443
|
-
var pageParams =
|
|
26064
|
+
var sessionListParams = obj10({
|
|
26065
|
+
workspace: text4,
|
|
26066
|
+
query: opt10(text4),
|
|
26067
|
+
cursor: opt10(text4)
|
|
26068
|
+
}, { open: true });
|
|
26069
|
+
var sessionListResult = obj10({
|
|
26070
|
+
sessions: arr8(MobileSessionSummarySchema),
|
|
26071
|
+
nextCursor: opt10(text4)
|
|
26072
|
+
}, { open: true });
|
|
26073
|
+
var subscription = { subscriptionId: str10({ minLength: 1 }) };
|
|
26074
|
+
var pageResult = obj10({ items: arr8(MobileChatItemSchema), historyBefore: nullable2(text4) }, { open: true });
|
|
26075
|
+
var pageParams = obj10({
|
|
25444
26076
|
...subscription,
|
|
25445
|
-
before:
|
|
25446
|
-
limit:
|
|
25447
|
-
});
|
|
25448
|
-
var
|
|
26077
|
+
before: str10({ minLength: 1 }),
|
|
26078
|
+
limit: opt10(int7({ minimum: 1, maximum: 50 }))
|
|
26079
|
+
}, { open: true });
|
|
26080
|
+
var chunkResultProperties = { data: text4, nextOffset: count, total: count, done: bool5() };
|
|
26081
|
+
var chunkResult = obj10(chunkResultProperties, { open: true });
|
|
25449
26082
|
var MOBILE_API_V1_METHODS = {
|
|
25450
26083
|
"server.hello": { params: MobileHelloParams, result: buildHelloResultSchema() },
|
|
25451
|
-
"workspaces.list": { params:
|
|
26084
|
+
"workspaces.list": { params: nul5(), result: obj10({ workspaces: arr8(MobileWorkspaceSchema) }, { open: true }) },
|
|
25452
26085
|
"sessions.list": { params: sessionListParams, result: sessionListResult },
|
|
25453
|
-
"sessions.create": { params:
|
|
26086
|
+
"sessions.create": { params: obj10({ workspace: text4 }, { open: true }), result: MobileSessionSummarySchema },
|
|
25454
26087
|
"chat.attach": {
|
|
25455
|
-
params:
|
|
25456
|
-
result:
|
|
26088
|
+
params: obj10({ sessionId: str10({ minLength: 1 }) }, { open: true }),
|
|
26089
|
+
result: obj10({ subscriptionId: text4, sessionId: text4, snapshot: MobileChatSnapshotSchema }, { open: true })
|
|
25457
26090
|
},
|
|
25458
|
-
"chat.detach": { params:
|
|
26091
|
+
"chat.detach": { params: obj10(subscription, { open: true }), result: nul5() },
|
|
25459
26092
|
"chat.history": { params: pageParams, result: pageResult },
|
|
25460
26093
|
"chat.content": {
|
|
25461
|
-
params:
|
|
26094
|
+
params: obj10({ ref: MobileContentRefSchema, offset: count }, { open: true }),
|
|
25462
26095
|
result: chunkResult
|
|
25463
26096
|
},
|
|
25464
26097
|
"chat.submit": {
|
|
25465
|
-
params:
|
|
26098
|
+
params: obj10({
|
|
25466
26099
|
...subscription,
|
|
25467
|
-
requestId:
|
|
25468
|
-
text:
|
|
25469
|
-
mode:
|
|
25470
|
-
}),
|
|
25471
|
-
result:
|
|
26100
|
+
requestId: str10({ minLength: 1, maxLength: 128 }),
|
|
26101
|
+
text: str10({ minLength: 1, maxLength: 65536 }),
|
|
26102
|
+
mode: opt10(lit5("steer"))
|
|
26103
|
+
}, { open: true }),
|
|
26104
|
+
result: obj10({ accepted: lit5(true), queued: bool5() }, { open: true })
|
|
25472
26105
|
},
|
|
25473
26106
|
"chat.submissionStatus": {
|
|
25474
|
-
params:
|
|
25475
|
-
result:
|
|
26107
|
+
params: obj10({ ...subscription, requestId: str10({ minLength: 1, maxLength: 128 }) }, { open: true }),
|
|
26108
|
+
result: obj10({ status: union6([lit5("accepted"), lit5("unknown")]) }, { open: true })
|
|
25476
26109
|
},
|
|
25477
26110
|
"chat.steer": {
|
|
25478
|
-
params:
|
|
25479
|
-
result:
|
|
25480
|
-
result:
|
|
25481
|
-
|
|
25482
|
-
|
|
25483
|
-
|
|
25484
|
-
|
|
25485
|
-
Type10.Literal("unknown")
|
|
25486
|
-
]),
|
|
25487
|
-
id: opt(int),
|
|
25488
|
-
text: opt(Type10.String()),
|
|
25489
|
-
images: opt(int)
|
|
25490
|
-
})
|
|
26111
|
+
params: obj10({ ...subscription, id: count }, { open: true }),
|
|
26112
|
+
result: obj10({
|
|
26113
|
+
result: union6([lit5("steered"), lit5("withdrawn"), lit5("placed"), lit5("settled"), lit5("unknown")]),
|
|
26114
|
+
id: opt10(count),
|
|
26115
|
+
text: opt10(str10()),
|
|
26116
|
+
images: opt10(count)
|
|
26117
|
+
}, { open: true })
|
|
25491
26118
|
},
|
|
25492
26119
|
"chat.withdraw": {
|
|
25493
|
-
params:
|
|
25494
|
-
result:
|
|
25495
|
-
result:
|
|
25496
|
-
|
|
25497
|
-
|
|
25498
|
-
|
|
25499
|
-
Type10.Literal("unknown")
|
|
25500
|
-
]),
|
|
25501
|
-
text: opt(Type10.String()),
|
|
25502
|
-
images: opt(int)
|
|
25503
|
-
})
|
|
26120
|
+
params: obj10({ ...subscription, id: count }, { open: true }),
|
|
26121
|
+
result: obj10({
|
|
26122
|
+
result: union6([lit5("withdrawn"), lit5("placed"), lit5("settled"), lit5("unknown")]),
|
|
26123
|
+
text: opt10(str10()),
|
|
26124
|
+
images: opt10(count)
|
|
26125
|
+
}, { open: true })
|
|
25504
26126
|
},
|
|
25505
|
-
"chat.abort": { params:
|
|
26127
|
+
"chat.abort": { params: obj10(subscription, { open: true }), result: obj10({ accepted: bool5() }, { open: true }) },
|
|
25506
26128
|
"subagents.open": {
|
|
25507
|
-
params:
|
|
25508
|
-
result:
|
|
25509
|
-
subagentSubscriptionId:
|
|
25510
|
-
agentId:
|
|
26129
|
+
params: obj10({ ...subscription, agentId: opt10(str10({ minLength: 1 })), taskId: opt10(count) }, { open: true }),
|
|
26130
|
+
result: obj10({
|
|
26131
|
+
subagentSubscriptionId: text4,
|
|
26132
|
+
agentId: text4,
|
|
25511
26133
|
snapshot: MobileChatSnapshotSchema
|
|
25512
|
-
})
|
|
26134
|
+
}, { open: true })
|
|
25513
26135
|
},
|
|
25514
26136
|
"subagents.history": {
|
|
25515
|
-
params:
|
|
25516
|
-
subagentSubscriptionId:
|
|
25517
|
-
before:
|
|
25518
|
-
limit:
|
|
25519
|
-
}),
|
|
26137
|
+
params: obj10({
|
|
26138
|
+
subagentSubscriptionId: str10({ minLength: 1 }),
|
|
26139
|
+
before: str10({ minLength: 1 }),
|
|
26140
|
+
limit: opt10(int7({ minimum: 1, maximum: 50 }))
|
|
26141
|
+
}, { open: true }),
|
|
25520
26142
|
result: pageResult
|
|
25521
26143
|
},
|
|
25522
26144
|
"subagents.close": {
|
|
25523
|
-
params:
|
|
25524
|
-
result:
|
|
26145
|
+
params: obj10({ subagentSubscriptionId: str10({ minLength: 1 }) }, { open: true }),
|
|
26146
|
+
result: nul5()
|
|
25525
26147
|
},
|
|
25526
26148
|
"subagents.stop": {
|
|
25527
|
-
params:
|
|
25528
|
-
result:
|
|
26149
|
+
params: obj10({ ...subscription, taskId: count }, { open: true }),
|
|
26150
|
+
result: obj10({ stopped: bool5() }, { open: true })
|
|
25529
26151
|
},
|
|
25530
26152
|
"approvals.list": {
|
|
25531
|
-
params:
|
|
25532
|
-
result:
|
|
26153
|
+
params: obj10(subscription, { open: true }),
|
|
26154
|
+
result: obj10({ approvals: arr8(MobileApprovalSchema) }, { open: true })
|
|
25533
26155
|
},
|
|
25534
|
-
"approvals.get": { params:
|
|
26156
|
+
"approvals.get": { params: obj10({ ...subscription, id: count }, { open: true }), result: MobileApprovalSchema },
|
|
25535
26157
|
"approvals.decide": {
|
|
25536
|
-
params:
|
|
26158
|
+
params: obj10({
|
|
25537
26159
|
...subscription,
|
|
25538
|
-
taskId:
|
|
25539
|
-
id:
|
|
25540
|
-
version:
|
|
25541
|
-
decision:
|
|
25542
|
-
}),
|
|
25543
|
-
result:
|
|
25544
|
-
status:
|
|
25545
|
-
|
|
25546
|
-
Type10.Literal("allowed"),
|
|
25547
|
-
Type10.Literal("denied"),
|
|
25548
|
-
Type10.Literal("cancelled")
|
|
25549
|
-
])
|
|
25550
|
-
})
|
|
26160
|
+
taskId: count,
|
|
26161
|
+
id: count,
|
|
26162
|
+
version: str10({ minLength: 1 }),
|
|
26163
|
+
decision: union6([lit5("allow"), lit5("deny")])
|
|
26164
|
+
}, { open: true }),
|
|
26165
|
+
result: obj10({
|
|
26166
|
+
status: union6([lit5("pending"), lit5("allowed"), lit5("denied"), lit5("cancelled")])
|
|
26167
|
+
}, { open: true })
|
|
25551
26168
|
},
|
|
25552
|
-
"todos.get": { params:
|
|
25553
|
-
"questions.list": { params:
|
|
25554
|
-
"questions.get": { params:
|
|
26169
|
+
"todos.get": { params: obj10(subscription, { open: true }), result: MobileTodoListSchema },
|
|
26170
|
+
"questions.list": { params: obj10(subscription, { open: true }), result: MobileQuestionListSchema },
|
|
26171
|
+
"questions.get": { params: obj10({ ...subscription, id: count }, { open: true }), result: MobileQuestionSchema },
|
|
25555
26172
|
"questions.respond": {
|
|
25556
|
-
params:
|
|
26173
|
+
params: obj10({
|
|
25557
26174
|
...subscription,
|
|
25558
|
-
id:
|
|
25559
|
-
version:
|
|
26175
|
+
id: count,
|
|
26176
|
+
version: str10({ minLength: 1 }),
|
|
25560
26177
|
response: MobileQuestionResponseSchema
|
|
25561
|
-
}),
|
|
26178
|
+
}, { open: true }),
|
|
25562
26179
|
result: MobileQuestionSchema
|
|
25563
26180
|
},
|
|
25564
26181
|
"plan.get": {
|
|
25565
|
-
params:
|
|
26182
|
+
params: obj10({ ...subscription, version: str10({ minLength: 1 }) }, { open: true }),
|
|
25566
26183
|
result: MobilePlanSchema
|
|
25567
26184
|
},
|
|
25568
26185
|
"plan.respond": {
|
|
25569
|
-
params:
|
|
26186
|
+
params: obj10({
|
|
25570
26187
|
...subscription,
|
|
25571
|
-
version:
|
|
26188
|
+
version: str10({ minLength: 1 }),
|
|
25572
26189
|
decision: MobilePlanDecisionSchema
|
|
25573
|
-
}),
|
|
26190
|
+
}, { open: true }),
|
|
25574
26191
|
result: MobilePlanSchema
|
|
25575
26192
|
},
|
|
25576
26193
|
"plan.exit": {
|
|
25577
|
-
params:
|
|
25578
|
-
result:
|
|
26194
|
+
params: obj10(subscription, { open: true }),
|
|
26195
|
+
result: obj10({ mode: lit5("normal"), revision: count }, { open: true })
|
|
25579
26196
|
},
|
|
25580
26197
|
"media.read": {
|
|
25581
|
-
params:
|
|
26198
|
+
params: obj10({
|
|
25582
26199
|
...subscription,
|
|
25583
|
-
agentId:
|
|
25584
|
-
entryId:
|
|
25585
|
-
contentIndex:
|
|
25586
|
-
offset:
|
|
25587
|
-
}),
|
|
25588
|
-
result:
|
|
26200
|
+
agentId: opt10(str10({ minLength: 1 })),
|
|
26201
|
+
entryId: count,
|
|
26202
|
+
contentIndex: count,
|
|
26203
|
+
offset: count
|
|
26204
|
+
}, { open: true }),
|
|
26205
|
+
result: obj10({ ...chunkResultProperties, mimeType: text4 }, { open: true })
|
|
25589
26206
|
}
|
|
25590
26207
|
};
|
|
25591
26208
|
function buildHelloResultSchema() {
|
|
25592
|
-
return
|
|
25593
|
-
apiVersion:
|
|
25594
|
-
serverId:
|
|
25595
|
-
serverName:
|
|
25596
|
-
gatewayVersion:
|
|
25597
|
-
capabilities:
|
|
25598
|
-
limits:
|
|
25599
|
-
maxFrameBytes:
|
|
25600
|
-
maxPayloadBytes:
|
|
25601
|
-
pageItems:
|
|
25602
|
-
chunkBytes:
|
|
25603
|
-
maxConcurrentRequests:
|
|
25604
|
-
maxSendBufferBytes:
|
|
25605
|
-
})
|
|
25606
|
-
});
|
|
26209
|
+
return obj10({
|
|
26210
|
+
apiVersion: int7({ minimum: 1 }),
|
|
26211
|
+
serverId: text4,
|
|
26212
|
+
serverName: text4,
|
|
26213
|
+
gatewayVersion: text4,
|
|
26214
|
+
capabilities: arr8(text4),
|
|
26215
|
+
limits: obj10({
|
|
26216
|
+
maxFrameBytes: int7(),
|
|
26217
|
+
maxPayloadBytes: int7(),
|
|
26218
|
+
pageItems: int7(),
|
|
26219
|
+
chunkBytes: int7(),
|
|
26220
|
+
maxConcurrentRequests: int7(),
|
|
26221
|
+
maxSendBufferBytes: int7()
|
|
26222
|
+
}, { open: true })
|
|
26223
|
+
}, { open: true });
|
|
25607
26224
|
}
|
|
25608
26225
|
var patchBody = {
|
|
25609
|
-
seq:
|
|
25610
|
-
upserts:
|
|
25611
|
-
status:
|
|
25612
|
-
streaming:
|
|
25613
|
-
streamingAppend:
|
|
26226
|
+
seq: int7({ minimum: 1 }),
|
|
26227
|
+
upserts: arr8(MobileChatItemSchema),
|
|
26228
|
+
status: opt10(MobileChatStatusSchema),
|
|
26229
|
+
streaming: opt10(nullable2(MobileStreamingSchema)),
|
|
26230
|
+
streamingAppend: opt10(obj10({ text: opt10(text4), thinking: opt10(text4) }, { open: true }))
|
|
25614
26231
|
};
|
|
25615
26232
|
var MOBILE_API_V1_NOTIFICATIONS = {
|
|
25616
|
-
"workspaces.changed":
|
|
25617
|
-
"sessions.changed":
|
|
25618
|
-
"chat.patch":
|
|
25619
|
-
"chat.reset":
|
|
25620
|
-
"subagents.patch":
|
|
25621
|
-
"subagents.reset":
|
|
25622
|
-
"approvals.changed":
|
|
25623
|
-
"todos.changed":
|
|
25624
|
-
"questions.changed":
|
|
25625
|
-
"plan.changed":
|
|
26233
|
+
"workspaces.changed": obj10({ revision: int7({ minimum: 1 }) }, { open: true }),
|
|
26234
|
+
"sessions.changed": obj10({ revision: int7({ minimum: 1 }) }, { open: true }),
|
|
26235
|
+
"chat.patch": obj10({ subscriptionId: text4, ...patchBody }, { open: true }),
|
|
26236
|
+
"chat.reset": obj10({ subscriptionId: text4, seq: int7({ minimum: 1 }) }, { open: true }),
|
|
26237
|
+
"subagents.patch": obj10({ subagentSubscriptionId: text4, ...patchBody }, { open: true }),
|
|
26238
|
+
"subagents.reset": obj10({ subagentSubscriptionId: text4, seq: int7({ minimum: 1 }) }, { open: true }),
|
|
26239
|
+
"approvals.changed": obj10({ subscriptionId: text4, revision: int7({ minimum: 1 }) }, { open: true }),
|
|
26240
|
+
"todos.changed": obj10({ subscriptionId: text4, revision: int7({ minimum: 1 }) }, { open: true }),
|
|
26241
|
+
"questions.changed": obj10({ subscriptionId: text4, revision: int7({ minimum: 1 }) }, { open: true }),
|
|
26242
|
+
"plan.changed": obj10({ subscriptionId: text4, revision: int7({ minimum: 1 }) }, { open: true })
|
|
25626
26243
|
};
|
|
25627
26244
|
|
|
25628
26245
|
// packages/gateway/src/mobile/projection.ts
|
|
@@ -25664,12 +26281,12 @@ function utf8Prefix(value, maxBytes) {
|
|
|
25664
26281
|
function jsonBytes2(value) {
|
|
25665
26282
|
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
25666
26283
|
}
|
|
25667
|
-
var
|
|
26284
|
+
var count2 = (value) => Math.max(0, Math.round(value ?? 0));
|
|
25668
26285
|
function mapUsage(usage) {
|
|
25669
|
-
const input =
|
|
25670
|
-
const output =
|
|
25671
|
-
const cacheRead =
|
|
25672
|
-
const cacheWrite =
|
|
26286
|
+
const input = count2(usage.input);
|
|
26287
|
+
const output = count2(usage.output);
|
|
26288
|
+
const cacheRead = count2(usage.cacheRead);
|
|
26289
|
+
const cacheWrite = count2(usage.cacheWrite);
|
|
25673
26290
|
return {
|
|
25674
26291
|
input,
|
|
25675
26292
|
output,
|
|
@@ -25721,9 +26338,9 @@ function mapChatItem(raw, owner) {
|
|
|
25721
26338
|
images: list.map((image) => ({
|
|
25722
26339
|
name: image.name,
|
|
25723
26340
|
mimeType: image.mimeType,
|
|
25724
|
-
width:
|
|
25725
|
-
height:
|
|
25726
|
-
bytes:
|
|
26341
|
+
width: count2(image.width),
|
|
26342
|
+
height: count2(image.height),
|
|
26343
|
+
bytes: count2(image.bytes),
|
|
25727
26344
|
entryId: image.entryId,
|
|
25728
26345
|
contentIndex: image.contentIndex
|
|
25729
26346
|
}))
|
|
@@ -25773,6 +26390,17 @@ function mapChatItem(raw, owner) {
|
|
|
25773
26390
|
tool.note = raw.note;
|
|
25774
26391
|
if (raw.interaction !== undefined)
|
|
25775
26392
|
tool.interaction = raw.interaction;
|
|
26393
|
+
if (raw.codemode !== undefined) {
|
|
26394
|
+
tool.codemode = {
|
|
26395
|
+
calls: raw.codemode.calls.map(({ durationMs, error, ...call }) => ({
|
|
26396
|
+
...call,
|
|
26397
|
+
...durationMs === null ? {} : { durationMs },
|
|
26398
|
+
...error === null ? {} : { error }
|
|
26399
|
+
})),
|
|
26400
|
+
omitted: raw.codemode.omitted,
|
|
26401
|
+
...raw.codemode.fullOutputPath === null ? {} : { fullOutputPath: raw.codemode.fullOutputPath }
|
|
26402
|
+
};
|
|
26403
|
+
}
|
|
25776
26404
|
item = { key: raw.key, type: "tool", tool, ...images(raw.images) };
|
|
25777
26405
|
break;
|
|
25778
26406
|
}
|
|
@@ -25799,7 +26427,7 @@ function mapRound(round, readonlyRound) {
|
|
|
25799
26427
|
role: round.role,
|
|
25800
26428
|
title: round.title,
|
|
25801
26429
|
status: round.status,
|
|
25802
|
-
approvalCount:
|
|
26430
|
+
approvalCount: count2(round.approvalCount),
|
|
25803
26431
|
readonly: readonlyRound || round.historyThrough !== undefined,
|
|
25804
26432
|
createdAt: round.createdAt,
|
|
25805
26433
|
endedAt: round.endedAt,
|
|
@@ -25816,7 +26444,7 @@ function mapStatus(view, options = {}) {
|
|
|
25816
26444
|
activeRoundId: agent.activeRoundId,
|
|
25817
26445
|
lastRoundId: agent.lastRoundId,
|
|
25818
26446
|
roundCount: agent.roundCount,
|
|
25819
|
-
approvalCount:
|
|
26447
|
+
approvalCount: count2(agent.approvalCount)
|
|
25820
26448
|
}));
|
|
25821
26449
|
const approvalCount = view.approvals !== undefined ? view.approvals.filter((approval) => approval.status === "pending").length : rounds.reduce((sum, round) => sum + round.approvalCount, 0);
|
|
25822
26450
|
const latest = view.compaction?.latest;
|
|
@@ -25852,6 +26480,12 @@ function mapStatus(view, options = {}) {
|
|
|
25852
26480
|
agents,
|
|
25853
26481
|
approvalCount,
|
|
25854
26482
|
...latest ? { compaction: { phase: latest.phase, at: latest.at } } : {},
|
|
26483
|
+
...view.runFailure === undefined ? {} : {
|
|
26484
|
+
runFailure: {
|
|
26485
|
+
reason: view.runFailure.reason,
|
|
26486
|
+
...view.runFailure.detail === undefined ? {} : { detail: view.runFailure.detail }
|
|
26487
|
+
}
|
|
26488
|
+
},
|
|
25855
26489
|
...options.readonly === undefined ? {} : { readonly: options.readonly }
|
|
25856
26490
|
};
|
|
25857
26491
|
}
|
|
@@ -26294,12 +26928,12 @@ class MobileAdapter {
|
|
|
26294
26928
|
this.sendError(id, -32601, "method not found", { code: "not_found" });
|
|
26295
26929
|
return;
|
|
26296
26930
|
}
|
|
26297
|
-
if (!
|
|
26931
|
+
if (!checkSchema(spec.params, params)) {
|
|
26298
26932
|
this.sendError(id, -32602, "invalid params", { code: "invalid_params" });
|
|
26299
26933
|
return;
|
|
26300
26934
|
}
|
|
26301
26935
|
const result = await this.invoke(method, params);
|
|
26302
|
-
if (!
|
|
26936
|
+
if (!checkSchema(spec.result, result)) {
|
|
26303
26937
|
this.onError?.(new Error(`mobile result for ${method} does not match its schema`));
|
|
26304
26938
|
this.sendError(id, -32603, "internal result mismatch", { code: "internal" });
|
|
26305
26939
|
return;
|
|
@@ -28430,6 +29064,7 @@ async function removeGatewayPortFile(nekoDir, serverId) {
|
|
|
28430
29064
|
// packages/gateway/src/server-services.ts
|
|
28431
29065
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
28432
29066
|
import { ChordError as ChordError5, local as local3, method as method2 } from "@earendil-works/chord";
|
|
29067
|
+
import { nul as nul6, obj as obj13 } from "@earendil-works/pi-schema";
|
|
28433
29068
|
|
|
28434
29069
|
// packages/core/src/application-updates.ts
|
|
28435
29070
|
import { mkdir as mkdir3, readFile as readFile6, rm as rm3, writeFile as writeFile3 } from "fs/promises";
|
|
@@ -28578,9 +29213,6 @@ class UpdateChecker {
|
|
|
28578
29213
|
}
|
|
28579
29214
|
}
|
|
28580
29215
|
|
|
28581
|
-
// packages/gateway/src/server-services.ts
|
|
28582
|
-
import { Type as Type13 } from "typebox";
|
|
28583
|
-
|
|
28584
29216
|
// packages/gateway/src/session-host.ts
|
|
28585
29217
|
import { open as open3 } from "fs/promises";
|
|
28586
29218
|
import { basename as basename3, extname } from "path";
|
|
@@ -28591,7 +29223,7 @@ import {
|
|
|
28591
29223
|
} from "@earendil-works/chord";
|
|
28592
29224
|
import { withAbortSignal as withAbortSignal4 } from "@earendil-works/chord/context";
|
|
28593
29225
|
import { UsageDoc as UsageDoc4 } from "@earendil-works/pi-durable";
|
|
28594
|
-
import {
|
|
29226
|
+
import { obj as obj12, str as str12 } from "@earendil-works/pi-schema";
|
|
28595
29227
|
|
|
28596
29228
|
// packages/gateway/src/image-uploads.ts
|
|
28597
29229
|
var IMAGE_CHUNK_BYTES = 256 * 1024;
|
|
@@ -28690,18 +29322,23 @@ class ImageUploads {
|
|
|
28690
29322
|
// packages/gateway/src/subagent-host.ts
|
|
28691
29323
|
import { ChordError as ChordError3, local, opaque } from "@earendil-works/chord";
|
|
28692
29324
|
import { UsageDoc as UsageDoc3 } from "@earendil-works/pi-durable";
|
|
28693
|
-
import {
|
|
29325
|
+
import { int as int8, obj as obj11, str as str11 } from "@earendil-works/pi-schema";
|
|
28694
29326
|
async function openReader(runtime, childId, parentId, context, through, historyUsage) {
|
|
28695
29327
|
const child = await runtime.harness.conversation(childId, context);
|
|
28696
29328
|
if (!child)
|
|
28697
29329
|
throw new ChordError3("gone", "Subagent unavailable");
|
|
28698
|
-
const native = await child.
|
|
29330
|
+
const native = await child.watch(context);
|
|
29331
|
+
const listeners = new Set;
|
|
28699
29332
|
if (through !== undefined)
|
|
28700
|
-
native.
|
|
29333
|
+
await native.stop();
|
|
29334
|
+
else
|
|
29335
|
+
native.start(async () => {
|
|
29336
|
+
for (const listener of listeners)
|
|
29337
|
+
listener();
|
|
29338
|
+
});
|
|
28701
29339
|
const project = (entries, streaming = true) => {
|
|
28702
29340
|
const result = projectChatView({ ...native.value, entries: [...entries].sort((a, b) => a.id - b.id) }, "", {
|
|
28703
|
-
models: runtime.listModels()
|
|
28704
|
-
contextEntries: native.value.entries
|
|
29341
|
+
models: runtime.listModels()
|
|
28705
29342
|
});
|
|
28706
29343
|
if (!streaming || through !== undefined) {
|
|
28707
29344
|
result.streaming = null;
|
|
@@ -28750,8 +29387,10 @@ async function openReader(runtime, childId, parentId, context, through, historyU
|
|
|
28750
29387
|
subscribe: (fn) => {
|
|
28751
29388
|
if (through !== undefined)
|
|
28752
29389
|
return () => {};
|
|
28753
|
-
const
|
|
28754
|
-
|
|
29390
|
+
const listener = () => fn(null);
|
|
29391
|
+
listeners.add(listener);
|
|
29392
|
+
const stop = () => listeners.delete(listener);
|
|
29393
|
+
const stopApprovals = onCommits(runtime.harness, ({ changes }) => {
|
|
28755
29394
|
if (changes.some((c) => c.type === "document" && ["app.neko.approvals", "app.neko.delegations", "app.neko.subagents"].includes(c.record.kind) && c.conversationId === parentId))
|
|
28756
29395
|
fn(null);
|
|
28757
29396
|
});
|
|
@@ -28810,20 +29449,23 @@ async function openReader(runtime, childId, parentId, context, through, historyU
|
|
|
28810
29449
|
mimeType: image.mimeType
|
|
28811
29450
|
};
|
|
28812
29451
|
},
|
|
28813
|
-
close: () =>
|
|
29452
|
+
close: () => {
|
|
29453
|
+
listeners.clear();
|
|
29454
|
+
native.stop();
|
|
29455
|
+
}
|
|
28814
29456
|
};
|
|
28815
29457
|
}
|
|
28816
29458
|
var ChildProjection = local("neko.subagent-projection", {
|
|
28817
29459
|
version: 1,
|
|
28818
|
-
input:
|
|
29460
|
+
input: obj11({ parentId: int8(), agentId: str11() }, { open: true }),
|
|
28819
29461
|
members: {
|
|
28820
|
-
revision:
|
|
29462
|
+
revision: int8(),
|
|
28821
29463
|
reader: opaque("neko.subagent-reader@1")
|
|
28822
29464
|
}
|
|
28823
29465
|
});
|
|
28824
29466
|
function installSubagentHost(host, runtime, context) {
|
|
28825
29467
|
host.serve(ChildProjection, (input, _principal, self2) => {
|
|
28826
|
-
const revision = self2.state("revision",
|
|
29468
|
+
const revision = self2.state("revision", int8(), 0);
|
|
28827
29469
|
const reader = self2.resource("reader", {
|
|
28828
29470
|
version: 1,
|
|
28829
29471
|
async open() {
|
|
@@ -28864,7 +29506,7 @@ function installSubagentHost(host, runtime, context) {
|
|
|
28864
29506
|
parentId: Number(input.sessionId),
|
|
28865
29507
|
agentId: input.agentId ?? `round-${input.taskId}`
|
|
28866
29508
|
});
|
|
28867
|
-
const authorizedRevision = self2.state("authorizedRevision",
|
|
29509
|
+
const authorizedRevision = self2.state("authorizedRevision", int8(), 0);
|
|
28868
29510
|
self2.on("authorizedView", shared.revision, async (value, ctx) => {
|
|
28869
29511
|
try {
|
|
28870
29512
|
target.value;
|
|
@@ -28917,7 +29559,7 @@ function installSubagentHost(host, runtime, context) {
|
|
|
28917
29559
|
}
|
|
28918
29560
|
|
|
28919
29561
|
// packages/gateway/src/session-host.ts
|
|
28920
|
-
var OwnerInput =
|
|
29562
|
+
var OwnerInput = obj12({}, { open: true });
|
|
28921
29563
|
var Owner = local2("neko.attachment-owner", {
|
|
28922
29564
|
version: 1,
|
|
28923
29565
|
input: OwnerInput,
|
|
@@ -28925,7 +29567,7 @@ var Owner = local2("neko.attachment-owner", {
|
|
|
28925
29567
|
});
|
|
28926
29568
|
var Projection = local2("neko.projection", {
|
|
28927
29569
|
version: 1,
|
|
28928
|
-
input:
|
|
29570
|
+
input: obj12({ id: str12() }, { open: true }),
|
|
28929
29571
|
members: {
|
|
28930
29572
|
view: ChatViewSchema,
|
|
28931
29573
|
reader: opaque2("neko.projection-reader@1")
|
|
@@ -28945,20 +29587,12 @@ var emptyView = {
|
|
|
28945
29587
|
var JOB_COMMAND_PREVIEW_CHARS = 1000;
|
|
28946
29588
|
var clipJob = (job) => job.command.length > JOB_COMMAND_PREVIEW_CHARS ? { ...job, command: `${job.command.slice(0, JOB_COMMAND_PREVIEW_CHARS)}\u2026` } : job;
|
|
28947
29589
|
async function openProjection(runtime, session, context) {
|
|
28948
|
-
const view = await session.
|
|
28949
|
-
const history = new Map;
|
|
28950
|
-
let cursor;
|
|
28951
|
-
do {
|
|
28952
|
-
const page = await session.conversation.entries({ order: "ascending" }, 100, cursor, context);
|
|
28953
|
-
for (const entry of page.items)
|
|
28954
|
-
history.set(entry.id, entry);
|
|
28955
|
-
cursor = page.next;
|
|
28956
|
-
} while (cursor);
|
|
29590
|
+
const view = await session.follow();
|
|
28957
29591
|
let changed;
|
|
28958
29592
|
const stop = view.subscribe(() => changed?.(null));
|
|
28959
29593
|
const stopMetadata = runtime.onDirectoryChange(() => changed?.(null));
|
|
28960
29594
|
let childIds = new Set;
|
|
28961
|
-
const stopChildren = runtime.harness
|
|
29595
|
+
const stopChildren = onCommits(runtime.harness, ({ changes }) => {
|
|
28962
29596
|
if (changes.some((change) => change.type === "entry" && change.value.kind === "pi.tool-result" && childIds.has(change.value.conversationId) || change.type === "document" && ([
|
|
28963
29597
|
"app.neko.delegations",
|
|
28964
29598
|
"app.neko.approvals",
|
|
@@ -28979,12 +29613,9 @@ async function openProjection(runtime, session, context) {
|
|
|
28979
29613
|
};
|
|
28980
29614
|
},
|
|
28981
29615
|
async project() {
|
|
28982
|
-
for (const entry of view.value.entries)
|
|
28983
|
-
history.set(entry.id, entry);
|
|
28984
29616
|
const [naming, compaction] = await Promise.all([runtime.namingUsage(session.id), session.compactionRecord()]);
|
|
28985
29617
|
const projected = projectChatView({
|
|
28986
29618
|
...view.value,
|
|
28987
|
-
entries: [...history.values()].sort((a, b) => a.id - b.id),
|
|
28988
29619
|
docs: {
|
|
28989
29620
|
...view.value.docs,
|
|
28990
29621
|
"pi.usage": mergeUsage(view.value.docs["pi.usage"] ?? {
|
|
@@ -28992,7 +29623,7 @@ async function openProjection(runtime, session, context) {
|
|
|
28992
29623
|
tools: {}
|
|
28993
29624
|
}, naming)
|
|
28994
29625
|
}
|
|
28995
|
-
}, "", { models: runtime.listModels(),
|
|
29626
|
+
}, "", { models: runtime.listModels(), compaction });
|
|
28996
29627
|
const jobs = (await session.jobs()).map(clipJob);
|
|
28997
29628
|
const [todos, questions, plan] = await Promise.all([session.todos(), session.questions(), session.plan()]);
|
|
28998
29629
|
const changes = await session.changeSummary().catch(() => {
|
|
@@ -29033,16 +29664,13 @@ async function openProjection(runtime, session, context) {
|
|
|
29033
29664
|
},
|
|
29034
29665
|
async entry(id, ctx) {
|
|
29035
29666
|
ctx.abortSignal?.throwIfAborted();
|
|
29036
|
-
|
|
29037
|
-
history.set(entry.id, entry);
|
|
29038
|
-
return history.get(id);
|
|
29667
|
+
return view.entry(id);
|
|
29039
29668
|
},
|
|
29040
29669
|
close() {
|
|
29041
29670
|
stop();
|
|
29042
29671
|
stopMetadata();
|
|
29043
29672
|
stopChildren();
|
|
29044
29673
|
view.dispose();
|
|
29045
|
-
history.clear();
|
|
29046
29674
|
}
|
|
29047
29675
|
};
|
|
29048
29676
|
}
|
|
@@ -29218,6 +29846,14 @@ function serveSessions(host, runtime, context) {
|
|
|
29218
29846
|
await projection.value.session.abort();
|
|
29219
29847
|
return null;
|
|
29220
29848
|
},
|
|
29849
|
+
continueRun: async () => {
|
|
29850
|
+
try {
|
|
29851
|
+
await projection.value.session.continueRun();
|
|
29852
|
+
return null;
|
|
29853
|
+
} catch (error) {
|
|
29854
|
+
throw new ChordError4("invalid", error instanceof Error ? error.message : "Cannot continue");
|
|
29855
|
+
}
|
|
29856
|
+
},
|
|
29221
29857
|
withdraw: ({ id }) => projection.value.session.withdraw(id),
|
|
29222
29858
|
steer: ({ id }) => projection.value.session.steer(id),
|
|
29223
29859
|
questionGet: async ({ id }) => await projection.value.session.question(id) ?? null,
|
|
@@ -30037,18 +30673,20 @@ async function listDrives() {
|
|
|
30037
30673
|
// packages/gateway/src/server-services.ts
|
|
30038
30674
|
var ServerState = local3("neko.server-state", {
|
|
30039
30675
|
version: 1,
|
|
30040
|
-
input:
|
|
30676
|
+
input: obj13({}, { open: true }),
|
|
30041
30677
|
members: {
|
|
30042
30678
|
directory: DirectoryStateSchema,
|
|
30043
30679
|
workspaces: WorkspaceStateSchema,
|
|
30044
30680
|
credentials: CredentialStateSchema,
|
|
30045
30681
|
searchSettings: SearchSettingsStateSchema,
|
|
30046
30682
|
contextSettings: ContextSettingsStateSchema,
|
|
30683
|
+
codemodeSettings: CodemodeSettingsStateSchema,
|
|
30047
30684
|
defaultModel: DefaultModelStateSchema,
|
|
30048
|
-
refreshCredentials: method2(
|
|
30049
|
-
refreshSearchSettings: method2(
|
|
30050
|
-
refreshContextSettings: method2(
|
|
30051
|
-
|
|
30685
|
+
refreshCredentials: method2(nul6(), nul6()),
|
|
30686
|
+
refreshSearchSettings: method2(nul6(), nul6()),
|
|
30687
|
+
refreshContextSettings: method2(nul6(), nul6()),
|
|
30688
|
+
refreshCodemodeSettings: method2(nul6(), nul6()),
|
|
30689
|
+
refreshDefaultModel: method2(nul6(), nul6())
|
|
30052
30690
|
}
|
|
30053
30691
|
});
|
|
30054
30692
|
async function createNekoServerServices(options) {
|
|
@@ -30138,12 +30776,13 @@ async function createNekoServerServices(options) {
|
|
|
30138
30776
|
return [spec.id, spec.kind === "model" ? { ...status, enabled: enabled.has(spec.id) } : status];
|
|
30139
30777
|
})));
|
|
30140
30778
|
};
|
|
30141
|
-
const [sessions, workspaces, statuses, search, contextSettings0, defaultModel0] = await Promise.all([
|
|
30779
|
+
const [sessions, workspaces, statuses, search, contextSettings0, codemodeSettings0, defaultModel0] = await Promise.all([
|
|
30142
30780
|
list(),
|
|
30143
30781
|
runtime.listWorkspaces(),
|
|
30144
30782
|
readStatuses(),
|
|
30145
30783
|
runtime.searchSettings(),
|
|
30146
30784
|
runtime.contextSettings(),
|
|
30785
|
+
runtime.codemodeSettings(),
|
|
30147
30786
|
runtime.defaultModel()
|
|
30148
30787
|
]);
|
|
30149
30788
|
let mutationTail = Promise.resolve();
|
|
@@ -30161,6 +30800,10 @@ async function createNekoServerServices(options) {
|
|
|
30161
30800
|
revision: 1,
|
|
30162
30801
|
...contextSettings0
|
|
30163
30802
|
});
|
|
30803
|
+
const codemodeSettings = self2.state("codemodeSettings", CodemodeSettingsStateSchema, {
|
|
30804
|
+
revision: 1,
|
|
30805
|
+
...codemodeSettings0
|
|
30806
|
+
});
|
|
30164
30807
|
const defaultModel = self2.state("defaultModel", DefaultModelStateSchema, defaultModel0);
|
|
30165
30808
|
const refreshContextSettings = async (_input, ctx) => {
|
|
30166
30809
|
const next = await runtime.contextSettings();
|
|
@@ -30169,6 +30812,13 @@ async function createNekoServerServices(options) {
|
|
|
30169
30812
|
contextSettings.replace(ctx, { revision: revision + 1, ...next });
|
|
30170
30813
|
return null;
|
|
30171
30814
|
};
|
|
30815
|
+
const refreshCodemodeSettings = async (_input, ctx) => {
|
|
30816
|
+
const next = await runtime.codemodeSettings();
|
|
30817
|
+
const { revision, ...current } = codemodeSettings.value;
|
|
30818
|
+
if (JSON.stringify(next) !== JSON.stringify(current))
|
|
30819
|
+
codemodeSettings.replace(ctx, { revision: revision + 1, ...next });
|
|
30820
|
+
return null;
|
|
30821
|
+
};
|
|
30172
30822
|
const refreshDefaultModel = async (_input, ctx) => {
|
|
30173
30823
|
const next = await runtime.defaultModel();
|
|
30174
30824
|
if (JSON.stringify(next) !== JSON.stringify(defaultModel.value))
|
|
@@ -30182,7 +30832,7 @@ async function createNekoServerServices(options) {
|
|
|
30182
30832
|
searchSettings.replace(ctx, { revision: current.revision + 1, ...next });
|
|
30183
30833
|
return null;
|
|
30184
30834
|
};
|
|
30185
|
-
self2.on("directory", { subscribe:
|
|
30835
|
+
self2.on("directory", { subscribe: (listener) => onCommits(runtime.harness, listener) }, async (event, ctx) => {
|
|
30186
30836
|
if (!event.changes.some((change) => change.type === "conversation" || change.type === "document" && [
|
|
30187
30837
|
"app.neko.session-metadata",
|
|
30188
30838
|
"app.neko.activity",
|
|
@@ -30204,6 +30854,7 @@ async function createNekoServerServices(options) {
|
|
|
30204
30854
|
credentials,
|
|
30205
30855
|
searchSettings,
|
|
30206
30856
|
contextSettings,
|
|
30857
|
+
codemodeSettings,
|
|
30207
30858
|
defaultModel,
|
|
30208
30859
|
async refreshCredentials(_input, ctx) {
|
|
30209
30860
|
credentials.replace(ctx, {
|
|
@@ -30214,6 +30865,7 @@ async function createNekoServerServices(options) {
|
|
|
30214
30865
|
},
|
|
30215
30866
|
refreshSearchSettings,
|
|
30216
30867
|
refreshContextSettings,
|
|
30868
|
+
refreshCodemodeSettings,
|
|
30217
30869
|
refreshDefaultModel
|
|
30218
30870
|
};
|
|
30219
30871
|
}, { lifetime: "host" });
|
|
@@ -30280,6 +30932,21 @@ async function createNekoServerServices(options) {
|
|
|
30280
30932
|
})
|
|
30281
30933
|
};
|
|
30282
30934
|
});
|
|
30935
|
+
host.serve(NekoCodemodeSettings, (_input, _principal, self2) => {
|
|
30936
|
+
const hub = shared(self2);
|
|
30937
|
+
return {
|
|
30938
|
+
variant: "ready",
|
|
30939
|
+
state: hub.codemodeSettings,
|
|
30940
|
+
set: (input, ctx) => serialize(async () => {
|
|
30941
|
+
await runtime.setCodemodeMode(input.mode);
|
|
30942
|
+
return hub.refreshCodemodeSettings(null, ctx);
|
|
30943
|
+
}),
|
|
30944
|
+
reset: (_input, ctx) => serialize(async () => {
|
|
30945
|
+
await runtime.resetCodemodeMode();
|
|
30946
|
+
return hub.refreshCodemodeSettings(null, ctx);
|
|
30947
|
+
})
|
|
30948
|
+
};
|
|
30949
|
+
});
|
|
30283
30950
|
host.serve(NekoDefaultModel, (_input, _principal, self2) => {
|
|
30284
30951
|
const hub = shared(self2);
|
|
30285
30952
|
return {
|
|
@@ -30608,6 +31275,8 @@ async function startGateway(options = {}) {
|
|
|
30608
31275
|
...options.apiKey !== undefined ? { apiKey: options.apiKey } : {},
|
|
30609
31276
|
...searchProvider !== undefined ? { searchProvider } : {},
|
|
30610
31277
|
...fileConfig.context !== undefined ? { contextSettings: fileConfig.context } : {},
|
|
31278
|
+
...fileConfig.codemode !== undefined ? { codemodeSettings: fileConfig.codemode } : {},
|
|
31279
|
+
...fileConfig.maxTurns !== undefined ? { maxTurns: fileConfig.maxTurns } : {},
|
|
30611
31280
|
...fileConfig.defaultModel !== undefined ? { model: fileConfig.defaultModel } : {},
|
|
30612
31281
|
...options.model !== undefined ? { modelOverride: options.model } : {},
|
|
30613
31282
|
thinkingLevel: options.thinkingLevel ?? fileConfig.thinkingLevel ?? "high",
|
|
@@ -30733,7 +31402,7 @@ async function bindGateway(runtime, options) {
|
|
|
30733
31402
|
}
|
|
30734
31403
|
};
|
|
30735
31404
|
runtime.closed.then(async (result) => {
|
|
30736
|
-
if (result.
|
|
31405
|
+
if (result.kind === "failed") {
|
|
30737
31406
|
options.onError?.(new Error("Gateway storage failed"));
|
|
30738
31407
|
await gateway.close();
|
|
30739
31408
|
}
|