open-agents-ai 0.103.75 → 0.103.77
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/index.js +185 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19173,7 +19173,8 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
19173
19173
|
"skill_build",
|
|
19174
19174
|
"skill_execute",
|
|
19175
19175
|
"sub_agent",
|
|
19176
|
-
"priority_delegate"
|
|
19176
|
+
"priority_delegate",
|
|
19177
|
+
"ask_user"
|
|
19177
19178
|
].includes(tc.name);
|
|
19178
19179
|
const cachedResult = recentToolResults.get(toolFingerprint);
|
|
19179
19180
|
if (isReadLike && cachedResult !== void 0) {
|
|
@@ -19447,7 +19448,7 @@ Take a DIFFERENT action now.`
|
|
|
19447
19448
|
});
|
|
19448
19449
|
break;
|
|
19449
19450
|
}
|
|
19450
|
-
const narratedToolPattern = /(?:```(?:bash|json|sh)?\s*\n?)?\b(file_read|file_write|file_edit|shell|skill_execute|skill_list|skill_build|grep_search|find_files|web_search|web_fetch|task_complete|memory_read|memory_write|list_directory)\b[\s(=\-]/;
|
|
19451
|
+
const narratedToolPattern = /(?:```(?:bash|json|sh)?\s*\n?)?\b(file_read|file_write|file_edit|shell|skill_execute|skill_list|skill_build|grep_search|find_files|web_search|web_fetch|task_complete|memory_read|memory_write|list_directory|ask_user)\b[\s(=\-]/;
|
|
19451
19452
|
const narratedMatch = content.match(narratedToolPattern);
|
|
19452
19453
|
if (narratedMatch) {
|
|
19453
19454
|
narratedToolCallCount++;
|
|
@@ -27119,6 +27120,12 @@ function formatToolArgs(toolName, args, verbose) {
|
|
|
27119
27120
|
return `${args["path"] ?? ""}${args["model"] ? ` (${args["model"]})` : ""}`;
|
|
27120
27121
|
case "transcribe_url":
|
|
27121
27122
|
return truncStr(String(args["url"] ?? ""), maxArg);
|
|
27123
|
+
case "ask_user": {
|
|
27124
|
+
const q = truncStr(String(args["question"] ?? ""), maxArg - 10);
|
|
27125
|
+
const opts = args["options"];
|
|
27126
|
+
const count = opts ? ` (${opts.length} options)` : "";
|
|
27127
|
+
return `${q}${c2.dim(count)}`;
|
|
27128
|
+
}
|
|
27122
27129
|
default:
|
|
27123
27130
|
return Object.entries(args).map(([k, v]) => `${k}=${truncStr(String(v), Math.max(30, maxArg / 3))}`).join(", ");
|
|
27124
27131
|
}
|
|
@@ -27221,7 +27228,9 @@ var init_render = __esm({
|
|
|
27221
27228
|
ocr: "\u{1F441}\uFE0F",
|
|
27222
27229
|
// Transcription tools
|
|
27223
27230
|
transcribe_file: "\u{1F399}\uFE0F",
|
|
27224
|
-
transcribe_url: "\u{1F399}\uFE0F"
|
|
27231
|
+
transcribe_url: "\u{1F399}\uFE0F",
|
|
27232
|
+
// User interaction
|
|
27233
|
+
ask_user: "\u2753"
|
|
27225
27234
|
};
|
|
27226
27235
|
TOOL_LABELS = {
|
|
27227
27236
|
file_read: "Read",
|
|
@@ -27255,7 +27264,9 @@ var init_render = __esm({
|
|
|
27255
27264
|
ocr: "OCR",
|
|
27256
27265
|
// Transcription tools
|
|
27257
27266
|
transcribe_file: "Transcribe",
|
|
27258
|
-
transcribe_url: "Transcribe URL"
|
|
27267
|
+
transcribe_url: "Transcribe URL",
|
|
27268
|
+
// User interaction
|
|
27269
|
+
ask_user: "Ask user"
|
|
27259
27270
|
};
|
|
27260
27271
|
TOOL_COLORS = {
|
|
27261
27272
|
file_read: pastel.sky,
|
|
@@ -27286,7 +27297,8 @@ var init_render = __esm({
|
|
|
27286
27297
|
screenshot: pastel.pink,
|
|
27287
27298
|
ocr: pastel.pink,
|
|
27288
27299
|
transcribe_file: pastel.peach,
|
|
27289
|
-
transcribe_url: pastel.peach
|
|
27300
|
+
transcribe_url: pastel.peach,
|
|
27301
|
+
ask_user: pastel.sky
|
|
27290
27302
|
};
|
|
27291
27303
|
_contentWriteHook = null;
|
|
27292
27304
|
HINTS = [
|
|
@@ -27337,6 +27349,7 @@ var init_render = __esm({
|
|
|
27337
27349
|
"aiwg_workflow",
|
|
27338
27350
|
"create_tool",
|
|
27339
27351
|
"manage_tools",
|
|
27352
|
+
"ask_user",
|
|
27340
27353
|
"task_complete"
|
|
27341
27354
|
];
|
|
27342
27355
|
COMMAND_NAMES = [
|
|
@@ -30654,13 +30667,43 @@ async function fetchOllamaModels(baseUrl) {
|
|
|
30654
30667
|
}
|
|
30655
30668
|
const data = await resp.json();
|
|
30656
30669
|
const models = data.models ?? [];
|
|
30657
|
-
|
|
30670
|
+
const result = models.map((m) => ({
|
|
30658
30671
|
name: m.name,
|
|
30659
30672
|
size: formatBytes(m.size),
|
|
30660
30673
|
sizeBytes: m.size,
|
|
30661
30674
|
modified: formatRelativeTime(m.modified_at),
|
|
30662
|
-
parameterSize: m.details?.parameter_size
|
|
30675
|
+
parameterSize: m.details?.parameter_size,
|
|
30676
|
+
contextLength: void 0
|
|
30663
30677
|
})).sort((a, b) => b.sizeBytes - a.sizeBytes);
|
|
30678
|
+
const normalized = normalizeBaseUrl(baseUrl);
|
|
30679
|
+
const showResults = await Promise.allSettled(result.map((m) => fetch(`${normalized}/api/show`, {
|
|
30680
|
+
method: "POST",
|
|
30681
|
+
headers: { "Content-Type": "application/json" },
|
|
30682
|
+
body: JSON.stringify({ name: m.name }),
|
|
30683
|
+
signal: AbortSignal.timeout(5e3)
|
|
30684
|
+
}).then((r) => r.ok ? r.json() : null)));
|
|
30685
|
+
for (let i = 0; i < result.length; i++) {
|
|
30686
|
+
const sr = showResults[i];
|
|
30687
|
+
if (sr?.status !== "fulfilled" || !sr.value)
|
|
30688
|
+
continue;
|
|
30689
|
+
const show = sr.value;
|
|
30690
|
+
if (show.parameters) {
|
|
30691
|
+
const match = show.parameters.match(/num_ctx\s+(\d+)/);
|
|
30692
|
+
if (match) {
|
|
30693
|
+
result[i].contextLength = parseInt(match[1], 10);
|
|
30694
|
+
continue;
|
|
30695
|
+
}
|
|
30696
|
+
}
|
|
30697
|
+
if (show.model_info) {
|
|
30698
|
+
for (const [key, value] of Object.entries(show.model_info)) {
|
|
30699
|
+
if (key.endsWith(".context_length") && typeof value === "number") {
|
|
30700
|
+
result[i].contextLength = value;
|
|
30701
|
+
break;
|
|
30702
|
+
}
|
|
30703
|
+
}
|
|
30704
|
+
}
|
|
30705
|
+
}
|
|
30706
|
+
return result;
|
|
30664
30707
|
}
|
|
30665
30708
|
async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
30666
30709
|
const normalized = normalizeBaseUrl(baseUrl);
|
|
@@ -30680,10 +30723,11 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
30680
30723
|
const models = data.data ?? [];
|
|
30681
30724
|
return models.map((m) => ({
|
|
30682
30725
|
name: m.id,
|
|
30683
|
-
size:
|
|
30726
|
+
size: "",
|
|
30684
30727
|
sizeBytes: 0,
|
|
30685
30728
|
modified: m.created ? formatRelativeTime(new Date(m.created * 1e3).toISOString()) : "",
|
|
30686
|
-
parameterSize: m.owned_by ?? void 0
|
|
30729
|
+
parameterSize: m.owned_by ?? void 0,
|
|
30730
|
+
contextLength: m.context_length ?? m.max_model_len ?? void 0
|
|
30687
30731
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
30688
30732
|
}
|
|
30689
30733
|
async function fetchPeerModels(peerId, authKey) {
|
|
@@ -31023,6 +31067,13 @@ function formatBytes(bytes) {
|
|
|
31023
31067
|
}
|
|
31024
31068
|
return `${size.toFixed(1)} ${units[i] ?? "B"}`;
|
|
31025
31069
|
}
|
|
31070
|
+
function formatContextLength(tokens) {
|
|
31071
|
+
if (tokens >= 1e6)
|
|
31072
|
+
return `${(tokens / 1e6).toFixed(1)}M ctx`;
|
|
31073
|
+
if (tokens >= 1024)
|
|
31074
|
+
return `${Math.round(tokens / 1024)}K ctx`;
|
|
31075
|
+
return `${tokens} ctx`;
|
|
31076
|
+
}
|
|
31026
31077
|
function formatRelativeTime(iso) {
|
|
31027
31078
|
const now = Date.now();
|
|
31028
31079
|
const then = new Date(iso).getTime();
|
|
@@ -35148,15 +35199,18 @@ async function showModelPicker(ctx, local = false) {
|
|
|
35148
35199
|
const items = [];
|
|
35149
35200
|
const history = loadUsageHistory("model", ctx.repoRoot);
|
|
35150
35201
|
const liveModelNames = new Set(models.map((m) => m.name));
|
|
35202
|
+
const modelMap = new Map(models.map((m) => [m.name, m]));
|
|
35151
35203
|
if (history.length > 0) {
|
|
35152
35204
|
items.push({ key: "__header_recent__", label: c2.dim("\u2500\u2500 Recent \u2500\u2500"), detail: "" });
|
|
35153
35205
|
for (const h of history.slice(0, 8)) {
|
|
35154
35206
|
const uses = h.localUses > 0 ? `${h.useCount} uses (${h.localUses} local)` : `${h.useCount} uses`;
|
|
35155
35207
|
const available = liveModelNames.has(h.value) ? "" : c2.yellow(" [offline]");
|
|
35208
|
+
const meta = modelMap.get(h.value);
|
|
35209
|
+
const ctx2 = meta?.contextLength ? ` ${formatContextLength(meta.contextLength)}` : "";
|
|
35156
35210
|
items.push({
|
|
35157
35211
|
key: h.value,
|
|
35158
35212
|
label: h.value,
|
|
35159
|
-
detail: `${uses}${available}`
|
|
35213
|
+
detail: `${uses}${ctx2}${available}`
|
|
35160
35214
|
});
|
|
35161
35215
|
}
|
|
35162
35216
|
items.push({ key: "__header_available__", label: c2.dim("\u2500\u2500 Available \u2500\u2500"), detail: "" });
|
|
@@ -35165,10 +35219,11 @@ async function showModelPicker(ctx, local = false) {
|
|
|
35165
35219
|
for (const m of models) {
|
|
35166
35220
|
if (history.length > 0 && historyKeys.has(m.name))
|
|
35167
35221
|
continue;
|
|
35222
|
+
const ctx2 = m.contextLength ? formatContextLength(m.contextLength) : "";
|
|
35168
35223
|
items.push({
|
|
35169
35224
|
key: m.name,
|
|
35170
35225
|
label: m.name,
|
|
35171
|
-
detail: [m.parameterSize, m.size, m.modified].filter(Boolean).join(" ")
|
|
35226
|
+
detail: [m.parameterSize, ctx2, m.size, m.modified].filter(Boolean).join(" ")
|
|
35172
35227
|
});
|
|
35173
35228
|
}
|
|
35174
35229
|
const result = await tuiSelect({
|
|
@@ -46653,7 +46708,7 @@ function formatDMNToolArgs(toolName, args) {
|
|
|
46653
46708
|
return "";
|
|
46654
46709
|
}
|
|
46655
46710
|
}
|
|
46656
|
-
function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler, thinkingEnabled) {
|
|
46711
|
+
function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler, thinkingEnabled, askUserCallback) {
|
|
46657
46712
|
const voiceStyleMap = {
|
|
46658
46713
|
concise: 1,
|
|
46659
46714
|
balanced: 3,
|
|
@@ -46924,6 +46979,62 @@ ${entry.fullContent}`
|
|
|
46924
46979
|
}
|
|
46925
46980
|
});
|
|
46926
46981
|
}
|
|
46982
|
+
if (askUserCallback) {
|
|
46983
|
+
runner.registerTool({
|
|
46984
|
+
name: "ask_user",
|
|
46985
|
+
description: `Present a decision point to the user with selectable options via an interactive TUI picker. Use this when you need user input to proceed \u2014 choosing between approaches, confirming destructive actions, selecting from a list of alternatives, or any situation where the user's preference matters. For yes/no questions, pass options: ["Yes", "No"]. For multi-choice, pass all available options. The user navigates with arrow keys and selects with Enter. The tool blocks until the user responds.`,
|
|
46986
|
+
parameters: {
|
|
46987
|
+
type: "object",
|
|
46988
|
+
properties: {
|
|
46989
|
+
question: {
|
|
46990
|
+
type: "string",
|
|
46991
|
+
description: "The question or decision to present to the user. Be clear and concise."
|
|
46992
|
+
},
|
|
46993
|
+
options: {
|
|
46994
|
+
type: "array",
|
|
46995
|
+
items: { type: "string" },
|
|
46996
|
+
description: 'Array of selectable options. For binary: ["Yes", "No"]. For multi-choice: ["Option A", "Option B", ...].'
|
|
46997
|
+
},
|
|
46998
|
+
allow_multiple: {
|
|
46999
|
+
type: "boolean",
|
|
47000
|
+
description: "If true, user can select multiple options (space to toggle, Enter to confirm). Default: false."
|
|
47001
|
+
}
|
|
47002
|
+
},
|
|
47003
|
+
required: ["question", "options"]
|
|
47004
|
+
},
|
|
47005
|
+
async execute(args) {
|
|
47006
|
+
const question = String(args.question ?? "");
|
|
47007
|
+
const rawOptions = args.options;
|
|
47008
|
+
const allowMultiple = Boolean(args.allow_multiple);
|
|
47009
|
+
if (!question) {
|
|
47010
|
+
return { success: false, output: "", error: "question is required" };
|
|
47011
|
+
}
|
|
47012
|
+
if (!Array.isArray(rawOptions) || rawOptions.length === 0) {
|
|
47013
|
+
return { success: false, output: "", error: "options must be a non-empty array of strings" };
|
|
47014
|
+
}
|
|
47015
|
+
const options = rawOptions.map((o) => String(o));
|
|
47016
|
+
if (options.length > 20) {
|
|
47017
|
+
return { success: false, output: "", error: "Too many options (max 20). Reduce the choices." };
|
|
47018
|
+
}
|
|
47019
|
+
try {
|
|
47020
|
+
const selected = await askUserCallback(question, options, allowMultiple);
|
|
47021
|
+
if (selected.length === 0) {
|
|
47022
|
+
return { success: true, output: "User cancelled the selection (pressed Escape)." };
|
|
47023
|
+
}
|
|
47024
|
+
return {
|
|
47025
|
+
success: true,
|
|
47026
|
+
output: allowMultiple ? `User selected: ${selected.join(", ")}` : `User selected: ${selected[0]}`
|
|
47027
|
+
};
|
|
47028
|
+
} catch (err) {
|
|
47029
|
+
return {
|
|
47030
|
+
success: false,
|
|
47031
|
+
output: "",
|
|
47032
|
+
error: `Ask user failed: ${err instanceof Error ? err.message : String(err)}`
|
|
47033
|
+
};
|
|
47034
|
+
}
|
|
47035
|
+
}
|
|
47036
|
+
});
|
|
47037
|
+
}
|
|
46927
47038
|
const filesTouched = /* @__PURE__ */ new Set();
|
|
46928
47039
|
const toolSequence = [];
|
|
46929
47040
|
const editSessionId = `task-${Date.now()}`;
|
|
@@ -47807,6 +47918,65 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
47807
47918
|
const sudoPromptStr = ` ${c2.bold(c2.yellow("\u{1F511} Password:"))} `;
|
|
47808
47919
|
process.stdout.write(sudoPromptStr);
|
|
47809
47920
|
}
|
|
47921
|
+
async function handleAskUser(question, options, allowMultiple) {
|
|
47922
|
+
if (statusBar?.isActive)
|
|
47923
|
+
statusBar.beginContentWrite();
|
|
47924
|
+
writeContent(() => {
|
|
47925
|
+
process.stdout.write(`
|
|
47926
|
+
${c2.bold(c2.cyan("?"))} ${c2.bold(question)}
|
|
47927
|
+
`);
|
|
47928
|
+
});
|
|
47929
|
+
const items = options.map((opt, i) => ({
|
|
47930
|
+
key: String(i),
|
|
47931
|
+
label: opt
|
|
47932
|
+
}));
|
|
47933
|
+
if (allowMultiple) {
|
|
47934
|
+
const selected = /* @__PURE__ */ new Set();
|
|
47935
|
+
const result = await tuiSelect({
|
|
47936
|
+
items,
|
|
47937
|
+
title: "Select one or more (Space to toggle, Enter to confirm)",
|
|
47938
|
+
rl,
|
|
47939
|
+
renderRow: (item, focused, _isActive) => {
|
|
47940
|
+
const isSelected = selected.has(item.key);
|
|
47941
|
+
const marker = isSelected ? c2.green("\u2611") : focused ? c2.cyan("\u2610") : c2.dim("\u2610");
|
|
47942
|
+
const label = focused ? c2.bold(c2.cyan(item.label)) : isSelected ? c2.green(item.label) : item.label;
|
|
47943
|
+
return ` ${marker} ${label}`;
|
|
47944
|
+
},
|
|
47945
|
+
onAction: (item, action) => {
|
|
47946
|
+
if (action === "space") {
|
|
47947
|
+
if (selected.has(item.key)) {
|
|
47948
|
+
selected.delete(item.key);
|
|
47949
|
+
} else {
|
|
47950
|
+
selected.add(item.key);
|
|
47951
|
+
}
|
|
47952
|
+
return true;
|
|
47953
|
+
}
|
|
47954
|
+
return false;
|
|
47955
|
+
}
|
|
47956
|
+
});
|
|
47957
|
+
if (statusBar?.isActive)
|
|
47958
|
+
statusBar.endContentWrite();
|
|
47959
|
+
if (!result.confirmed)
|
|
47960
|
+
return [];
|
|
47961
|
+
if (selected.size === 0 && result.key !== null) {
|
|
47962
|
+
const idx = parseInt(result.key, 10);
|
|
47963
|
+
return [options[idx]];
|
|
47964
|
+
}
|
|
47965
|
+
return Array.from(selected).map((k) => options[parseInt(k, 10)]);
|
|
47966
|
+
} else {
|
|
47967
|
+
const result = await tuiSelect({
|
|
47968
|
+
items,
|
|
47969
|
+
title: "Select one option",
|
|
47970
|
+
rl
|
|
47971
|
+
});
|
|
47972
|
+
if (statusBar?.isActive)
|
|
47973
|
+
statusBar.endContentWrite();
|
|
47974
|
+
if (!result.confirmed || result.key === null)
|
|
47975
|
+
return [];
|
|
47976
|
+
const idx = parseInt(result.key, 10);
|
|
47977
|
+
return [options[idx]];
|
|
47978
|
+
}
|
|
47979
|
+
}
|
|
47810
47980
|
const evalBackend = {
|
|
47811
47981
|
async evaluate(prompt) {
|
|
47812
47982
|
const backend = new OllamaAgenticBackend(currentConfig.backendUrl, currentConfig.model, currentConfig.apiKey);
|
|
@@ -49072,7 +49242,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
49072
49242
|
}, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
|
|
49073
49243
|
lastCompletedSummary = summary;
|
|
49074
49244
|
lastTaskMeta = meta ?? null;
|
|
49075
|
-
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled);
|
|
49245
|
+
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled, handleAskUser);
|
|
49076
49246
|
activeTask = task;
|
|
49077
49247
|
showPrompt();
|
|
49078
49248
|
await task.promise;
|
|
@@ -49304,7 +49474,7 @@ NEW TASK: ${fullInput}`;
|
|
|
49304
49474
|
}, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
|
|
49305
49475
|
lastCompletedSummary = summary;
|
|
49306
49476
|
lastTaskMeta = meta ?? null;
|
|
49307
|
-
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled);
|
|
49477
|
+
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled, handleAskUser);
|
|
49308
49478
|
activeTask = task;
|
|
49309
49479
|
showPrompt();
|
|
49310
49480
|
await task.promise;
|
|
@@ -49574,6 +49744,7 @@ var init_interactive = __esm({
|
|
|
49574
49744
|
init_carousel_descriptors();
|
|
49575
49745
|
init_voice();
|
|
49576
49746
|
init_stream_renderer();
|
|
49747
|
+
init_tui_select();
|
|
49577
49748
|
init_edit_history();
|
|
49578
49749
|
init_dream_engine();
|
|
49579
49750
|
init_bless_engine();
|
package/package.json
CHANGED