neoctl 0.2.12 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/agent-activity.js +11 -1
- package/dist/agents/agent-activity.js.map +1 -1
- package/dist/agents/local-agent-task.d.ts +1 -1
- package/dist/core/image-registry.js +4 -1
- package/dist/core/image-registry.js.map +1 -1
- package/dist/core/message-pipeline.js +16 -2
- package/dist/core/message-pipeline.js.map +1 -1
- package/dist/core/query-engine.d.ts +2 -0
- package/dist/core/query-engine.js +8 -4
- package/dist/core/query-engine.js.map +1 -1
- package/dist/core/query.js +6 -2
- package/dist/core/query.js.map +1 -1
- package/dist/repl/index.js +50 -86
- package/dist/repl/index.js.map +1 -1
- package/dist/session/tool-result-memory.js +58 -0
- package/dist/session/tool-result-memory.js.map +1 -1
- package/dist/tools/builtins/exec-tool.d.ts +1 -0
- package/dist/tools/builtins/exec-tool.js.map +1 -1
- package/dist/tools/builtins/image-generation-tool.d.ts +4 -0
- package/dist/tools/builtins/image-generation-tool.js +179 -52
- package/dist/tools/builtins/image-generation-tool.js.map +1 -1
- package/dist/web/index.d.ts +17 -1
- package/dist/web/index.js +33 -12
- package/dist/web/index.js.map +1 -1
- package/package.json +3 -1
- package/scripts/release-local.mjs +190 -0
package/dist/repl/index.js
CHANGED
|
@@ -260,7 +260,7 @@ async function createRuntime() {
|
|
|
260
260
|
tools.register(createLoadImageTool());
|
|
261
261
|
tools.register(createImageNoteTool());
|
|
262
262
|
if (modelConfig?.provider === "openai")
|
|
263
|
-
tools.register(createOpenAIImageGenerationTool());
|
|
263
|
+
tools.register(createOpenAIImageGenerationTool({ taskStore, foregroundDetachRegistry: foregroundExecDetach }));
|
|
264
264
|
tools.register(planTool);
|
|
265
265
|
for (const tool of createSecretTools())
|
|
266
266
|
tools.register(tool);
|
|
@@ -330,7 +330,7 @@ async function createRuntime() {
|
|
|
330
330
|
function syncImageGenerationTool(runtime, provider) {
|
|
331
331
|
runtime.tools.unregister("image2");
|
|
332
332
|
if (provider === "openai")
|
|
333
|
-
runtime.tools.register(createOpenAIImageGenerationTool());
|
|
333
|
+
runtime.tools.register(createOpenAIImageGenerationTool({ taskStore: runtime.taskStore, foregroundDetachRegistry: runtime.foregroundExecDetach }));
|
|
334
334
|
}
|
|
335
335
|
function formatCreatedEnvNotice(path) {
|
|
336
336
|
return `Created default config file: ${path}\nSet MODEL_PROVIDER and the matching provider section (OPENAI_API_KEY or ANTHROPIC_API_KEY), then restart neo.`;
|
|
@@ -1352,7 +1352,7 @@ function InkRepl({ runtime, initialCommandLine }) {
|
|
|
1352
1352
|
if (key.ctrl && value.toLowerCase() === "b") {
|
|
1353
1353
|
const result = runtime.foregroundExecDetach.detachCurrent();
|
|
1354
1354
|
append(result.ok
|
|
1355
|
-
? systemLine(`Detached foreground
|
|
1355
|
+
? systemLine(`Detached foreground task to background task ${result.taskId ?? "unknown"}.`)
|
|
1356
1356
|
: systemLine(result.message));
|
|
1357
1357
|
return;
|
|
1358
1358
|
}
|
|
@@ -1656,7 +1656,7 @@ function InkRepl({ runtime, initialCommandLine }) {
|
|
|
1656
1656
|
return;
|
|
1657
1657
|
}
|
|
1658
1658
|
});
|
|
1659
|
-
return e(Box, { flexDirection: "column" }, e((Static), { items: staticLines, children: (line, index) => e(MessageBlock, { key: line.id, line, width, blockIndex: index }) }), e(MessageList, { lines: visibleDynamicLines, width, lineIndexOffset: staticLines.length, onMarkdownRenderComplete: markLineRendered }), sessionsBrowser ? e(SessionsBrowser, { state: sessionsBrowser, width }) : null, skillsBrowser ? e(SkillsBrowser, { state: skillsBrowser, width }) : null, secretsBrowser ? e(SecretsBrowser, { state: secretsBrowser, width }) : null, loginForm ? e(LoginFormView, { state: loginForm, width }) : null, e(StatusBar, { status, animationTick, width }), showForegroundExecDetachHint && foregroundExecDetachHandle ? e(ForegroundExecDetachHintLine, { handle: foregroundExecDetachHandle, width }) : null, agentActivities.length > 0 ? e(SubagentLivePanel, { activities: agentActivities, width,
|
|
1659
|
+
return e(Box, { flexDirection: "column" }, e((Static), { items: staticLines, children: (line, index) => e(MessageBlock, { key: line.id, line, width, blockIndex: index }) }), e(MessageList, { lines: visibleDynamicLines, width, lineIndexOffset: staticLines.length, onMarkdownRenderComplete: markLineRendered }), sessionsBrowser ? e(SessionsBrowser, { state: sessionsBrowser, width }) : null, skillsBrowser ? e(SkillsBrowser, { state: skillsBrowser, width }) : null, secretsBrowser ? e(SecretsBrowser, { state: secretsBrowser, width }) : null, loginForm ? e(LoginFormView, { state: loginForm, width }) : null, e(StatusBar, { status, animationTick, width }), showForegroundExecDetachHint && foregroundExecDetachHandle ? e(ForegroundExecDetachHintLine, { handle: foregroundExecDetachHandle, width }) : null, agentActivities.length > 0 ? e(SubagentLivePanel, { activities: agentActivities, width, animationTick }) : null, agentActivities.length === 0 && backgroundTasks.length > 0 ? e(BackgroundTaskStatusLine, { tasks: backgroundTasks, width }) : null, agentActivities.length > 0 && nonAgentBackgroundTasks.length > 0 ? e(BackgroundTaskStatusLine, { tasks: nonAgentBackgroundTasks, width }) : null, pasteStatus ? e(PasteStatusLine, { text: pasteStatus, width }) : null, queuedInput !== undefined ? e(QueuedInputLine, { text: queuedInput, width }) : null, e(PromptLine, { text: promptDisplayText, cursor: promptDisplayCursor, busy, locked: inputLockedByQueue, placeholder: input.length === 0 && promptPlaceholder !== undefined, ghostText: activePlaceholder, width, prompt, slashCompletions, selectedSlashCompletionIndex, attachments }));
|
|
1660
1660
|
}
|
|
1661
1661
|
const MessageList = React.memo(function MessageList({ lines, width, lineIndexOffset = 0, onMarkdownRenderComplete }) {
|
|
1662
1662
|
const contentWidth = messageContentWidth(width);
|
|
@@ -1994,37 +1994,26 @@ function backgroundTaskStatusRenderRows(taskCount) {
|
|
|
1994
1994
|
}
|
|
1995
1995
|
function ForegroundExecDetachHintLine({ handle, width: terminalWidth }) {
|
|
1996
1996
|
const width = statusBarWidth(terminalWidth);
|
|
1997
|
+
const toolName = handle.toolName?.trim() || "exec";
|
|
1997
1998
|
const label = handle.description?.trim() || handle.command;
|
|
1998
|
-
const text = `↳
|
|
1999
|
+
const text = `↳ ${toolName} still running · Ctrl+B to detach · ${truncateMiddle(label, Math.max(12, width - toolName.length - 33))}`;
|
|
1999
2000
|
return e(Text, { color: "yellow" }, fitToWidth(text, width));
|
|
2000
2001
|
}
|
|
2001
|
-
function SubagentLivePanel({ activities, width: terminalWidth,
|
|
2002
|
+
function SubagentLivePanel({ activities, width: terminalWidth, animationTick }) {
|
|
2002
2003
|
const width = statusBarWidth(terminalWidth);
|
|
2003
|
-
const rows = subagentLivePanelRenderRows(activities, terminalRows, compact);
|
|
2004
|
-
if (rows <= 0)
|
|
2005
|
-
return null;
|
|
2006
2004
|
const sorted = sortAgentActivitiesForPanel(activities);
|
|
2007
2005
|
const selected = sorted[0];
|
|
2008
2006
|
if (!selected)
|
|
2009
2007
|
return null;
|
|
2010
2008
|
const activeCount = activities.filter((activity) => activity.status === "running" || activity.status === "pending").length;
|
|
2011
|
-
const
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
}, fitToWidth(line.text, width))));
|
|
2020
|
-
}
|
|
2021
|
-
const SUBAGENT_DETAIL_ROWS = 3;
|
|
2022
|
-
function subagentLivePanelRenderRows(activities, terminalRows, compact = false) {
|
|
2023
|
-
if (activities.length === 0)
|
|
2024
|
-
return 0;
|
|
2025
|
-
if (compact || terminalRows < 22 || activities.length > 1)
|
|
2026
|
-
return 1;
|
|
2027
|
-
return 1 + SUBAGENT_DETAIL_ROWS;
|
|
2009
|
+
const recentCount = Math.max(0, activities.length - activeCount);
|
|
2010
|
+
const countText = activeCount > 1
|
|
2011
|
+
? `${activeCount} active${recentCount ? ` · ${recentCount} recent` : ""}`
|
|
2012
|
+
: recentCount && activeCount === 0
|
|
2013
|
+
? `${recentCount} recent`
|
|
2014
|
+
: "";
|
|
2015
|
+
const text = `↳ subagent ${subagentStatusText(selected.status, animationTick)}${countText ? ` · ${countText}` : ""} · ${compactAgentSummary(selected, width)}`;
|
|
2016
|
+
return e(Text, { color: statusColor(selected.status) }, fitToWidth(text, width));
|
|
2028
2017
|
}
|
|
2029
2018
|
function sortAgentActivitiesForPanel(activities) {
|
|
2030
2019
|
const rank = (status) => {
|
|
@@ -2038,76 +2027,35 @@ function sortAgentActivitiesForPanel(activities) {
|
|
|
2038
2027
|
};
|
|
2039
2028
|
return [...activities].sort((left, right) => rank(left.status) - rank(right.status) || right.updatedAt.localeCompare(left.updatedAt));
|
|
2040
2029
|
}
|
|
2041
|
-
function buildSubagentDetailLines(selected, sorted, animationTick) {
|
|
2042
|
-
const spinner = selected.status === "running" ? spinnerFrame(animationTick) : statusGlyph(selected.status);
|
|
2043
|
-
const elapsed = formatElapsed(Date.now() - new Date(selected.startedAt).getTime());
|
|
2044
|
-
const headerLine = `${spinner} ${selected.description || selected.agentId} · ${elapsed}`;
|
|
2045
|
-
const currentLine = selected.currentTool
|
|
2046
|
-
? `→ ${selected.currentTool.name}${selected.currentTool.inputPreview ? ` · ${selected.currentTool.inputPreview}` : ""}`
|
|
2047
|
-
: selected.error
|
|
2048
|
-
? `✖ ${selected.error}`
|
|
2049
|
-
: selected.resultPreview
|
|
2050
|
-
? `✓ ${selected.resultPreview}`
|
|
2051
|
-
: selected.lastText
|
|
2052
|
-
? `• ${selected.lastText}`
|
|
2053
|
-
: `• ${selected.prompt}`;
|
|
2054
|
-
const recent = selected.timeline.slice(-2).map((entry) => `${timelinePrefix(entry)} ${formatTimelineEntry(entry, 240)}`);
|
|
2055
|
-
const otherRunning = sorted
|
|
2056
|
-
.filter((activity) => activity.agentId !== selected.agentId && (activity.status === "running" || activity.status === "pending"))
|
|
2057
|
-
.slice(0, 2)
|
|
2058
|
-
.map((activity) => compactAgentSummary(activity, 180));
|
|
2059
|
-
const tail = [...recent, ...otherRunning.map((summary) => `· ${summary}`)].find((line) => line.trim()) ?? `tools:${selected.totalToolUseCount}`;
|
|
2060
|
-
return [
|
|
2061
|
-
{ text: headerLine, color: statusColor(selected.status) },
|
|
2062
|
-
{ text: currentLine, color: selected.error ? "red" : selected.currentTool ? "#d4b04c" : "yellow" },
|
|
2063
|
-
{ text: tail, color: "gray" },
|
|
2064
|
-
];
|
|
2065
|
-
}
|
|
2066
2030
|
function compactAgentSummary(activity, maxLength) {
|
|
2067
2031
|
const current = activity.currentTool
|
|
2068
2032
|
? `${activity.currentTool.name}${activity.currentTool.inputPreview ? ` ${activity.currentTool.inputPreview}` : ""}`
|
|
2069
|
-
: activity.
|
|
2033
|
+
: firstSafeSubagentPreview(activity.resultPreview, activity.error, activity.lastText, activity.prompt);
|
|
2070
2034
|
const elapsed = formatElapsed(Date.now() - new Date(activity.startedAt).getTime());
|
|
2071
2035
|
return truncateMiddle(`${activity.description || activity.agentId} · ${elapsed} · tools:${activity.totalToolUseCount} · ${current.replace(/\s+/g, " ")}`, Math.max(8, maxLength));
|
|
2072
2036
|
}
|
|
2073
|
-
function
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
if (entry.kind === "thinking")
|
|
2083
|
-
return "◆";
|
|
2084
|
-
if (entry.kind === "error")
|
|
2085
|
-
return "✖";
|
|
2086
|
-
if (entry.kind === "status")
|
|
2087
|
-
return "•";
|
|
2088
|
-
return "assistant:";
|
|
2089
|
-
}
|
|
2090
|
-
function timelineColor(entry) {
|
|
2091
|
-
if (entry.status === "failed" || entry.kind === "error")
|
|
2092
|
-
return "red";
|
|
2093
|
-
if (entry.kind === "tool_start" || entry.kind === "tool_result")
|
|
2094
|
-
return "#d4b04c";
|
|
2095
|
-
if (entry.kind === "thinking")
|
|
2096
|
-
return THINKING_COLOR;
|
|
2097
|
-
if (entry.kind === "status")
|
|
2098
|
-
return "gray";
|
|
2099
|
-
return "green";
|
|
2037
|
+
function firstSafeSubagentPreview(...values) {
|
|
2038
|
+
return values.find((value) => value && !isInternalContinuationPreview(value)) ?? "working";
|
|
2039
|
+
}
|
|
2040
|
+
function isInternalContinuationPreview(value) {
|
|
2041
|
+
const normalized = value.toLowerCase();
|
|
2042
|
+
return normalized.includes("<compact_state>")
|
|
2043
|
+
|| normalized.includes("internal continuation state")
|
|
2044
|
+
|| normalized.includes("auto compact")
|
|
2045
|
+
|| normalized.includes("conversation summary generated by compact");
|
|
2100
2046
|
}
|
|
2101
|
-
function
|
|
2047
|
+
function subagentStatusText(status, animationTick) {
|
|
2048
|
+
if (status === "running")
|
|
2049
|
+
return `still running ${spinnerFrame(animationTick)}`;
|
|
2050
|
+
if (status === "pending")
|
|
2051
|
+
return "pending";
|
|
2102
2052
|
if (status === "completed")
|
|
2103
|
-
return "
|
|
2053
|
+
return "completed";
|
|
2104
2054
|
if (status === "failed")
|
|
2105
|
-
return "
|
|
2055
|
+
return "failed";
|
|
2106
2056
|
if (status === "killed")
|
|
2107
|
-
return "
|
|
2108
|
-
|
|
2109
|
-
return "…";
|
|
2110
|
-
return "●";
|
|
2057
|
+
return "killed";
|
|
2058
|
+
return status;
|
|
2111
2059
|
}
|
|
2112
2060
|
function statusColor(status) {
|
|
2113
2061
|
if (status === "completed")
|
|
@@ -4036,8 +3984,23 @@ function previewTextLines(text, maxLines, label) {
|
|
|
4036
3984
|
return [...preview, dimAnsi(`showing first ${maxLines} of ${lines.length} ${label} lines`)];
|
|
4037
3985
|
}
|
|
4038
3986
|
function previewGenericString(text) {
|
|
3987
|
+
const persisted = formatPersistedOutputString(text);
|
|
3988
|
+
if (persisted)
|
|
3989
|
+
return persisted;
|
|
4039
3990
|
return previewTextLines(text, FALLBACK_PREVIEW_LINES, "output").join("\n");
|
|
4040
3991
|
}
|
|
3992
|
+
function formatPersistedOutputString(text) {
|
|
3993
|
+
if (!text.startsWith("<persisted-output>"))
|
|
3994
|
+
return undefined;
|
|
3995
|
+
const savedPath = /^Output too large \(([^)]+)\)\. Full output saved to:\s*(.+)$/m.exec(text)?.[2]?.trim();
|
|
3996
|
+
const preview = /Preview \(first \d+ chars\):\n([\s\S]*?)\n(?:\.\.\.\n)?<\/persisted-output>/m.exec(text)?.[1]?.trimEnd();
|
|
3997
|
+
const lines = ["output persisted"];
|
|
3998
|
+
if (savedPath)
|
|
3999
|
+
lines.push(`${dimAnsi("saved to")} ${savedPath}`);
|
|
4000
|
+
if (preview)
|
|
4001
|
+
lines.push("", dimAnsi("preview"), ...previewTextLines(preview, PERSISTED_OUTPUT_PREVIEW_LINES, "preview"));
|
|
4002
|
+
return lines.join("\n");
|
|
4003
|
+
}
|
|
4041
4004
|
function formatCommandPreview(command) {
|
|
4042
4005
|
const normalized = command.replace(/\r\n/g, "\n").trimEnd();
|
|
4043
4006
|
const lines = normalized.split("\n");
|
|
@@ -4728,6 +4691,7 @@ const GREP_MATCH_PREVIEW_COUNT = 20;
|
|
|
4728
4691
|
const GREP_CONTEXT_PREVIEW_LINES = 2;
|
|
4729
4692
|
const LIST_ENTRY_PREVIEW_COUNT = 12;
|
|
4730
4693
|
const FALLBACK_PREVIEW_LINES = 40;
|
|
4694
|
+
const PERSISTED_OUTPUT_PREVIEW_LINES = 24;
|
|
4731
4695
|
const LOW_VALUE_FALLBACK_FIELDS = new Set(["ok", "summary", "metadata", "transportTruncation"]);
|
|
4732
4696
|
function fixed(value, width, align = "right") {
|
|
4733
4697
|
const stripped = stripAnsi(value);
|