prior-cli 1.6.4 → 1.6.6
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/bin/prior.js +8 -0
- package/lib/agent.js +19 -0
- package/lib/tools.js +21 -0
- package/package.json +1 -1
package/bin/prior.js
CHANGED
|
@@ -49,6 +49,14 @@ let _spinLabel = '';
|
|
|
49
49
|
// Detects keywords in user input and prepends a hard directive so
|
|
50
50
|
// the model can't second-guess which tool to use.
|
|
51
51
|
const TOOL_HINTS = [
|
|
52
|
+
{
|
|
53
|
+
tool: 'get_time',
|
|
54
|
+
patterns: [
|
|
55
|
+
/\bwhat time\b/i, /\bwhat('s| is) the time\b/i, /\bcurrent time\b/i,
|
|
56
|
+
/\btime (is it|now|right now)\b/i,
|
|
57
|
+
],
|
|
58
|
+
hint: '[TOOL DIRECTIVE: You MUST call get_time — do NOT guess the time]',
|
|
59
|
+
},
|
|
52
60
|
{
|
|
53
61
|
tool: 'ssl_check',
|
|
54
62
|
patterns: [
|
package/lib/agent.js
CHANGED
|
@@ -77,6 +77,21 @@ function parseToolCalls(text) {
|
|
|
77
77
|
} catch { /* skip */ }
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// Fallback: unclosed <tool>{...} (no closing </tool> — some models omit it)
|
|
81
|
+
const reUnclosed = /<tool>(\{[\s\S]*?\})\s*(?=$|\n|<)/g;
|
|
82
|
+
while ((m = reUnclosed.exec(text)) !== null) {
|
|
83
|
+
const alreadyCaptured = calls.some(c => m.index >= c.offset && m.index < c.offset + c.raw.length);
|
|
84
|
+
if (alreadyCaptured) continue;
|
|
85
|
+
try {
|
|
86
|
+
const fixed = fixJsonLiterals(m[1].trim());
|
|
87
|
+
const parsed = JSON.parse(fixed);
|
|
88
|
+
if (parsed && typeof parsed.name === 'string') {
|
|
89
|
+
const { name, args, ...rest } = parsed;
|
|
90
|
+
calls.push({ raw: m[0], offset: m.index, name, args: args || (Object.keys(rest).length > 0 ? rest : {}) });
|
|
91
|
+
}
|
|
92
|
+
} catch { /* skip */ }
|
|
93
|
+
}
|
|
94
|
+
|
|
80
95
|
// Primary variant: <tool name="X">{"args"}</tool> (name as attribute — used by some models)
|
|
81
96
|
const reAttr = /<tool\s+name="([^"]+)"[^>]*>([\s\S]*?)<\/tool>/g;
|
|
82
97
|
while ((m = reAttr.exec(text)) !== null) {
|
|
@@ -188,6 +203,10 @@ function truncateAtFakeTurn(text) {
|
|
|
188
203
|
function stripToolTags(text) {
|
|
189
204
|
// <tool>...</tool>
|
|
190
205
|
let out = text.replace(/<tool>[\s\S]*?<\/tool>/gi, '');
|
|
206
|
+
// Unclosed <tool>{...} (no closing tag)
|
|
207
|
+
out = out.replace(/<tool>\{[\s\S]*?\}\s*/gi, '');
|
|
208
|
+
// Bare <tool> with no content following
|
|
209
|
+
out = out.replace(/<\/?tool>/gi, '');
|
|
191
210
|
const namesPattern = TOOL_NAMES.join('|');
|
|
192
211
|
// <tool_name ...>...</tool_name> (with or without attributes/JSON)
|
|
193
212
|
out = out.replace(new RegExp(`<(?:${namesPattern})[^>]*>[\\s\\S]*?<\\/(?:${namesPattern})>`, 'gi'), '');
|
package/lib/tools.js
CHANGED
|
@@ -417,6 +417,27 @@ const TOOLS = {
|
|
|
417
417
|
return { output: data.output || JSON.stringify(data), summary: data.summary || `spider started for ${url}` };
|
|
418
418
|
},
|
|
419
419
|
|
|
420
|
+
async get_time({}, {}) {
|
|
421
|
+
const now = new Date();
|
|
422
|
+
const iso = now.toISOString();
|
|
423
|
+
const local = now.toLocaleString('en-PH', {
|
|
424
|
+
timeZone: 'Asia/Manila',
|
|
425
|
+
weekday: 'long',
|
|
426
|
+
year: 'numeric',
|
|
427
|
+
month: 'long',
|
|
428
|
+
day: 'numeric',
|
|
429
|
+
hour: '2-digit',
|
|
430
|
+
minute: '2-digit',
|
|
431
|
+
second: '2-digit',
|
|
432
|
+
hour12: true,
|
|
433
|
+
});
|
|
434
|
+
const utc = now.toUTCString();
|
|
435
|
+
return {
|
|
436
|
+
output: `Local (PHT/GMT+8) : ${local}\nUTC : ${utc}\nISO 8601 : ${iso}`,
|
|
437
|
+
summary: local,
|
|
438
|
+
};
|
|
439
|
+
},
|
|
440
|
+
|
|
420
441
|
async ip_lookup({ target }, {}) {
|
|
421
442
|
if (!target) throw new Error('"target" is required — provide an IP address or domain');
|
|
422
443
|
const encoded = encodeURIComponent(target.trim());
|