@livx.cc/agentx 0.98.1 → 0.99.1
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 +2 -2
- package/dist/cli.js +72 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +30 -5
- package/dist/index.js +64 -6
- package/dist/index.js.map +1 -1
- package/dist/tools.shell.js +54 -3
- package/dist/tools.shell.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -467,14 +467,27 @@ interface WebFetchOptions {
|
|
|
467
467
|
declare function makeWebFetchTool(options?: WebFetchOptions): AgentTool;
|
|
468
468
|
interface WebSearchOptions {
|
|
469
469
|
fetch?: typeof globalThis.fetch;
|
|
470
|
-
/** Provider: 'auto' (default)
|
|
471
|
-
|
|
470
|
+
/** Provider: 'auto' (default) prefers Firecrawl, then Tavily (by key presence), else keyless DuckDuckGo.
|
|
471
|
+
* 'anthropic' delegates to a cheap model with Anthropic's native server-side web_search. */
|
|
472
|
+
provider?: 'auto' | 'tavily' | 'duckduckgo' | 'anthropic' | 'firecrawl';
|
|
472
473
|
/** API key for Tavily (default: process.env.TAVILY_API_KEY). */
|
|
473
474
|
apiKey?: string;
|
|
474
475
|
/** Tavily endpoint override. */
|
|
475
476
|
endpoint?: string;
|
|
477
|
+
/** API key for Firecrawl (default: process.env.FIRECRAWL_API_KEY). */
|
|
478
|
+
firecrawlApiKey?: string;
|
|
479
|
+
/** Firecrawl search endpoint override. */
|
|
480
|
+
firecrawlEndpoint?: string;
|
|
476
481
|
maxResults?: number;
|
|
477
482
|
timeoutMs?: number;
|
|
483
|
+
/** Tool name (default 'WebSearch'). Set to register a provider-pinned variant, e.g. 'WebSearchAnthropic'. */
|
|
484
|
+
name?: string;
|
|
485
|
+
/** Tool description override (default: the generic ranked-results blurb). */
|
|
486
|
+
description?: string;
|
|
487
|
+
/** Anthropic key for provider 'anthropic' (default: process.env.ANTHROPIC_API_KEY). */
|
|
488
|
+
anthropicApiKey?: string;
|
|
489
|
+
/** Model for provider 'anthropic' (default 'claude-haiku-4-5'). */
|
|
490
|
+
model?: string;
|
|
478
491
|
}
|
|
479
492
|
interface SearchHit {
|
|
480
493
|
title: string;
|
|
@@ -486,13 +499,24 @@ declare function decodeDdgUrl(href: string): string;
|
|
|
486
499
|
/** Parse DuckDuckGo's HTML results page into hits (title/url/snippet) — dependency-free, zips anchors to snippets in order. */
|
|
487
500
|
declare function parseDdgHtml(html: string, max: number): SearchHit[];
|
|
488
501
|
/**
|
|
489
|
-
* Build a WebSearch tool. Keyless by default (DuckDuckGo HTML) so it works in any deployment with
|
|
490
|
-
*
|
|
502
|
+
* Build a WebSearch tool. Keyless by default (DuckDuckGo HTML) so it works in any deployment with no
|
|
503
|
+
* setup; on provider 'auto' it upgrades to an agent-oriented API by key presence — Firecrawl
|
|
504
|
+
* (FIRECRAWL_API_KEY) preferred, then Tavily (TAVILY_API_KEY). Provider 'anthropic' is a separate path
|
|
505
|
+
* (native search via a cheap model) exposed as the WebSearchAnthropic tool.
|
|
491
506
|
*/
|
|
492
507
|
declare function makeWebSearchTool(options?: WebSearchOptions): AgentTool;
|
|
493
508
|
/** Default instances (registered in the tool registry; opt-in by name). */
|
|
494
509
|
declare const webFetchTool: AgentTool;
|
|
495
510
|
declare const webSearchTool: AgentTool;
|
|
511
|
+
/** Anthropic-native search as a provider-pinned WebSearch variant. The credential is API-key billing
|
|
512
|
+
* (x-api-key); pass `anthropicApiKey` to inject a resolved key, else it falls back to ANTHROPIC_API_KEY. */
|
|
513
|
+
declare function makeWebSearchAnthropicTool(opts?: {
|
|
514
|
+
anthropicApiKey?: string;
|
|
515
|
+
model?: string;
|
|
516
|
+
}): AgentTool;
|
|
517
|
+
/** Env-keyed singleton: registered in the tool registry so 'WebSearchAnthropic' resolves by name. The
|
|
518
|
+
* CLI default-on path builds its own instance with a config-resolved key (see cli/core.ts). */
|
|
519
|
+
declare const webSearchAnthropicTool: AgentTool;
|
|
496
520
|
|
|
497
521
|
/**
|
|
498
522
|
* Scratch — keep large tool/subagent outputs OUT of the main context, but queryable AS FILES.
|
|
@@ -952,6 +976,7 @@ declare class DuplexAgent {
|
|
|
952
976
|
private turnDispatched;
|
|
953
977
|
private turnBriefs;
|
|
954
978
|
private spokeThisTurn;
|
|
979
|
+
private heldThisTurn;
|
|
955
980
|
private nudging;
|
|
956
981
|
private reflexBuf;
|
|
957
982
|
private reflexForwarded;
|
|
@@ -1498,4 +1523,4 @@ declare function exitWorktree(): {
|
|
|
1498
1523
|
reason?: string;
|
|
1499
1524
|
} | null;
|
|
1500
1525
|
|
|
1501
|
-
export { Agent, type AgentDef, AgentOptions, AgentTool, type AskOptions, type Attempt, type AudioSink, type AudioSource, type AuthProvider, BodDbFilesystem, CartesiaTTS, CartesiaTTSOptions, ChatLike, ChatOptions, ChatResponse, type CommandInfo, ConsoleHostBridge, DEFAULT_DENY, DuplexAgent, DuplexAgentOptions, type DuplexTaskStatus, FakeAIClient, Hooks, HostBridge, JailOptions, JailedFilesystem, type LessonOptions, LessonOptionsDefaults, type LoadMemoryOpts, MEMORY_PROMPT, MessageContent, type Mount, MountFilesystem, NodeDiskFilesystem, OverlayFilesystem, type ReflectOptions, RunResult, SCRATCH_DIR, STT_SAMPLE_RATE, type ScheduledJob, type ScheduledJobSnapshot, Scheduler, type SchedulerOptions, Scratch, type ScratchOptions, ScriptedHostBridge, type SiblingResolver, type SkillInfo, SonioxSTT, SonioxSTTOptions, type SttLike, TTS_SAMPLE_RATE, type TaskRecord, type TaskToolOptions, ToolCall, type ToolSpec, type Trigger, type TriggerCron, type TriggerInterval, type TriggerOneOff, type TtsLike, UserQuestion, VOICE_MEMORY_PROMPT, VOICE_SYSTEM_PROMPT, VoiceEngine, VoiceEngineOptions, type VoiceState, type WebFetchOptions, type WebSearchOptions, type WorkerTier, type WorktreeInfo, type WorktreeSession, applyEditsTool, askUserQuestionTool, checkpointTool, checkpointTools, cleanupWorktree, compileSynthesizedTool, cronMatches, decodeDdgUrl, diskAgentOptions, enterWorktree, exitWorktree, expandCommand, expandEntry, expandTemplate, findGitRoot, forComponent, fullAgentOptions, getOrCreateWorktree, getWorktreeSession, globTool, grepTool, htmlToText, idfWeights, lessonCapture, loadAgents, loadCommands, loadInstructions, loadMemory, loadSkills, makeAskTool, makeScheduleTools, makeTaskBatchTool, makeTaskTool, makeWebFetchTool, makeWebSearchTool, mkdirp, multiEditTool, nextCronAfter, parseCron, parseDdgHtml, raceAttempts, reflectOnRun, relevanceScore, repoIndex, repoMapTool, resolveAuth, rollbackTool, sandboxAgentOptions, scanCommands, scanSkills, slugify, tokenize, toolCall, topByRelevance, validateToolCode, validateWorktreeSlug, webFetchTool, webSearchTool, worktreeBranchName, writeFact, writeTool };
|
|
1526
|
+
export { Agent, type AgentDef, AgentOptions, AgentTool, type AskOptions, type Attempt, type AudioSink, type AudioSource, type AuthProvider, BodDbFilesystem, CartesiaTTS, CartesiaTTSOptions, ChatLike, ChatOptions, ChatResponse, type CommandInfo, ConsoleHostBridge, DEFAULT_DENY, DuplexAgent, DuplexAgentOptions, type DuplexTaskStatus, FakeAIClient, Hooks, HostBridge, JailOptions, JailedFilesystem, type LessonOptions, LessonOptionsDefaults, type LoadMemoryOpts, MEMORY_PROMPT, MessageContent, type Mount, MountFilesystem, NodeDiskFilesystem, OverlayFilesystem, type ReflectOptions, RunResult, SCRATCH_DIR, STT_SAMPLE_RATE, type ScheduledJob, type ScheduledJobSnapshot, Scheduler, type SchedulerOptions, Scratch, type ScratchOptions, ScriptedHostBridge, type SiblingResolver, type SkillInfo, SonioxSTT, SonioxSTTOptions, type SttLike, TTS_SAMPLE_RATE, type TaskRecord, type TaskToolOptions, ToolCall, type ToolSpec, type Trigger, type TriggerCron, type TriggerInterval, type TriggerOneOff, type TtsLike, UserQuestion, VOICE_MEMORY_PROMPT, VOICE_SYSTEM_PROMPT, VoiceEngine, VoiceEngineOptions, type VoiceState, type WebFetchOptions, type WebSearchOptions, type WorkerTier, type WorktreeInfo, type WorktreeSession, applyEditsTool, askUserQuestionTool, checkpointTool, checkpointTools, cleanupWorktree, compileSynthesizedTool, cronMatches, decodeDdgUrl, diskAgentOptions, enterWorktree, exitWorktree, expandCommand, expandEntry, expandTemplate, findGitRoot, forComponent, fullAgentOptions, getOrCreateWorktree, getWorktreeSession, globTool, grepTool, htmlToText, idfWeights, lessonCapture, loadAgents, loadCommands, loadInstructions, loadMemory, loadSkills, makeAskTool, makeScheduleTools, makeTaskBatchTool, makeTaskTool, makeWebFetchTool, makeWebSearchAnthropicTool, makeWebSearchTool, mkdirp, multiEditTool, nextCronAfter, parseCron, parseDdgHtml, raceAttempts, reflectOnRun, relevanceScore, repoIndex, repoMapTool, resolveAuth, rollbackTool, sandboxAgentOptions, scanCommands, scanSkills, slugify, tokenize, toolCall, topByRelevance, validateToolCode, validateWorktreeSlug, webFetchTool, webSearchAnthropicTool, webSearchTool, worktreeBranchName, writeFact, writeTool };
|
package/dist/index.js
CHANGED
|
@@ -644,13 +644,48 @@ function formatHits(hits) {
|
|
|
644
644
|
${r.url}
|
|
645
645
|
${r.snippet.replace(/\s+/g, " ").slice(0, 240)}`).join("\n\n");
|
|
646
646
|
}
|
|
647
|
+
async function firecrawlSearch(q, opts) {
|
|
648
|
+
const res = await opts.fetch(opts.endpoint, {
|
|
649
|
+
method: "POST",
|
|
650
|
+
signal: opts.signal,
|
|
651
|
+
headers: { authorization: `Bearer ${opts.key}`, "content-type": "application/json" },
|
|
652
|
+
body: JSON.stringify({ query: q, limit: opts.maxResults })
|
|
653
|
+
});
|
|
654
|
+
if (!res.ok) return `Error: Firecrawl search returned ${res.status} ${res.statusText}`;
|
|
655
|
+
const data = await res.json();
|
|
656
|
+
const results = Array.isArray(data?.data) ? data.data.slice(0, opts.maxResults) : [];
|
|
657
|
+
return formatHits(results.map((r) => ({ title: r.title ?? "(untitled)", url: r.url ?? "", snippet: String(r.description ?? r.markdown ?? "") })));
|
|
658
|
+
}
|
|
659
|
+
async function anthropicSearch(q, opts) {
|
|
660
|
+
const res = await opts.fetch("https://api.anthropic.com/v1/messages", {
|
|
661
|
+
method: "POST",
|
|
662
|
+
signal: opts.signal,
|
|
663
|
+
headers: { "x-api-key": opts.key, "anthropic-version": "2023-06-01", "content-type": "application/json" },
|
|
664
|
+
body: JSON.stringify({
|
|
665
|
+
model: opts.model,
|
|
666
|
+
max_tokens: 1024,
|
|
667
|
+
// Basic variant: Haiku-tier doesn't support the _20260209 dynamic-filtering variant (Opus 4.6+/Sonnet 4.6 only).
|
|
668
|
+
tools: [{ type: "web_search_20250305", name: "web_search", max_uses: 5 }],
|
|
669
|
+
messages: [{ role: "user", content: `Search the web for: ${q}
|
|
670
|
+
|
|
671
|
+
Return only the relevant findings as concise bullet points, each with its source URL in parentheses. Do not add a preamble, conclusion, opinion, or commentary. If sources conflict, list each claim with its source rather than resolving it.` }]
|
|
672
|
+
})
|
|
673
|
+
});
|
|
674
|
+
if (!res.ok) return `Error: Anthropic search returned ${res.status} ${res.statusText}`;
|
|
675
|
+
const data = await res.json();
|
|
676
|
+
if (data?.stop_reason === "refusal") return "Error: Anthropic search refused the query";
|
|
677
|
+
let text = "";
|
|
678
|
+
for (const block of data?.content ?? []) if (block?.type === "text") text += block.text;
|
|
679
|
+
return text.trim() || "(no results)";
|
|
680
|
+
}
|
|
647
681
|
function makeWebSearchTool(options = {}) {
|
|
648
682
|
const tavilyEndpoint = options.endpoint ?? "https://api.tavily.com/search";
|
|
683
|
+
const firecrawlEndpoint = options.firecrawlEndpoint ?? "https://api.firecrawl.dev/v1/search";
|
|
649
684
|
const maxResults = options.maxResults ?? 5;
|
|
650
685
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
651
686
|
return {
|
|
652
|
-
name: "WebSearch",
|
|
653
|
-
description: "Search the web by query; returns ranked results (title, URL, snippet). Use to look things up, find pages, or research a topic \u2014 then WebFetch a result URL to read it in full.",
|
|
687
|
+
name: options.name ?? "WebSearch",
|
|
688
|
+
description: options.description ?? "Search the web by query; returns ranked results (title, URL, snippet). Use to look things up, find pages, or research a topic \u2014 then WebFetch a result URL to read it in full.",
|
|
654
689
|
parameters: { type: "object", required: ["query"], properties: { query: { type: "string" } } },
|
|
655
690
|
async run({ query }) {
|
|
656
691
|
const doFetch = options.fetch ?? globalThis.fetch;
|
|
@@ -658,11 +693,22 @@ function makeWebSearchTool(options = {}) {
|
|
|
658
693
|
const q = String(query ?? "").trim();
|
|
659
694
|
if (!q) return "Error: empty query";
|
|
660
695
|
const key = options.apiKey ?? process.env.TAVILY_API_KEY;
|
|
696
|
+
const fcKey = options.firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY;
|
|
661
697
|
const provider = options.provider ?? "auto";
|
|
662
|
-
const
|
|
698
|
+
const useFirecrawl = provider === "firecrawl" || provider === "auto" && !!fcKey;
|
|
699
|
+
const useTavily = provider === "tavily" || provider === "auto" && !useFirecrawl && !!key;
|
|
663
700
|
const ctl = new AbortController();
|
|
664
701
|
const timer = setTimeout(() => ctl.abort(), timeoutMs);
|
|
665
702
|
try {
|
|
703
|
+
if (provider === "anthropic") {
|
|
704
|
+
const akey = options.anthropicApiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
705
|
+
if (!akey) return "Error: WebSearchAnthropic requires ANTHROPIC_API_KEY (set in env)";
|
|
706
|
+
return await anthropicSearch(q, { key: akey, model: options.model ?? "claude-haiku-4-5", fetch: doFetch, signal: ctl.signal });
|
|
707
|
+
}
|
|
708
|
+
if (useFirecrawl) {
|
|
709
|
+
if (!fcKey) return "Error: Firecrawl provider selected but FIRECRAWL_API_KEY is not set";
|
|
710
|
+
return await firecrawlSearch(q, { key: fcKey, endpoint: firecrawlEndpoint, maxResults, fetch: doFetch, signal: ctl.signal });
|
|
711
|
+
}
|
|
666
712
|
if (useTavily) {
|
|
667
713
|
if (!key) return "Error: Tavily provider selected but TAVILY_API_KEY is not set";
|
|
668
714
|
const res2 = await doFetch(tavilyEndpoint, {
|
|
@@ -691,7 +737,10 @@ function makeWebSearchTool(options = {}) {
|
|
|
691
737
|
}
|
|
692
738
|
};
|
|
693
739
|
}
|
|
694
|
-
|
|
740
|
+
function makeWebSearchAnthropicTool(opts = {}) {
|
|
741
|
+
return makeWebSearchTool({ provider: "anthropic", name: "WebSearchAnthropic", description: ANTHROPIC_SEARCH_DESC, anthropicApiKey: opts.anthropicApiKey, model: opts.model });
|
|
742
|
+
}
|
|
743
|
+
var log2, _dnsLookup, webFetchTool, webSearchTool, ANTHROPIC_SEARCH_DESC, webSearchAnthropicTool;
|
|
695
744
|
var init_tools_web = __esm({
|
|
696
745
|
"src/tools.web.ts"() {
|
|
697
746
|
"use strict";
|
|
@@ -699,6 +748,8 @@ var init_tools_web = __esm({
|
|
|
699
748
|
log2 = forComponent("web");
|
|
700
749
|
webFetchTool = makeWebFetchTool();
|
|
701
750
|
webSearchTool = makeWebSearchTool();
|
|
751
|
+
ANTHROPIC_SEARCH_DESC = "High-quality web search via Anthropic's native search index. Returns concise, sourced findings \u2014 one claim per line, each with its source URL. Prefer this over WebSearch when accuracy and citations matter; it is slower (~3\u20138s) and bills the Anthropic API account per call (one cheap-model turn + search fee).";
|
|
752
|
+
webSearchAnthropicTool = makeWebSearchAnthropicTool();
|
|
702
753
|
}
|
|
703
754
|
});
|
|
704
755
|
|
|
@@ -924,7 +975,7 @@ function defaultTools() {
|
|
|
924
975
|
return [bashTool, readTool, editTool];
|
|
925
976
|
}
|
|
926
977
|
function toolRegistry() {
|
|
927
|
-
const all = [bashTool, readTool, editTool, grepTool, globTool, writeTool, multiEditTool, applyEditsTool, repoMapTool, reviewTool(), todoWriteTool, webFetchTool, webSearchTool];
|
|
978
|
+
const all = [bashTool, readTool, editTool, grepTool, globTool, writeTool, multiEditTool, applyEditsTool, repoMapTool, reviewTool(), todoWriteTool, webFetchTool, webSearchTool, webSearchAnthropicTool];
|
|
928
979
|
return Object.fromEntries(all.map((t) => [t.name, t]));
|
|
929
980
|
}
|
|
930
981
|
function toolsByName(names) {
|
|
@@ -4983,6 +5034,8 @@ var DuplexAgent = class _DuplexAgent {
|
|
|
4983
5034
|
// briefs dispatched this turn (detect identical re-dispatch)
|
|
4984
5035
|
spokeThisTurn = false;
|
|
4985
5036
|
// any non-empty text_delta streamed this turn
|
|
5037
|
+
heldThisTurn = false;
|
|
5038
|
+
// Hold called this turn → turn is INTENTIONALLY silent (suppress reflex text + no dead-air ack)
|
|
4986
5039
|
nudging = false;
|
|
4987
5040
|
// re-ack pass in flight: block ALL tools, prevent recursion
|
|
4988
5041
|
reflexBuf = "";
|
|
@@ -5045,6 +5098,7 @@ Today's date: ${(/* @__PURE__ */ new Date()).toDateString()}.`;
|
|
|
5045
5098
|
confirm: host.confirm ? (p, m) => host.confirm(p, m) : void 0,
|
|
5046
5099
|
notify: (ev) => {
|
|
5047
5100
|
if (ev?.kind === "text_delta" && typeof ev.message === "string") {
|
|
5101
|
+
if (this.heldThisTurn) return;
|
|
5048
5102
|
if (this.fabricationCut) return;
|
|
5049
5103
|
const msg = ev.message;
|
|
5050
5104
|
this.reflexBuf += msg;
|
|
@@ -5114,6 +5168,7 @@ Today's date: ${(/* @__PURE__ */ new Date()).toDateString()}.`;
|
|
|
5114
5168
|
this.turnDispatched = false;
|
|
5115
5169
|
this.turnBriefs.clear();
|
|
5116
5170
|
this.spokeThisTurn = false;
|
|
5171
|
+
this.heldThisTurn = false;
|
|
5117
5172
|
this.reflexBuf = "";
|
|
5118
5173
|
this.reflexForwarded = 0;
|
|
5119
5174
|
this.fabricationCut = false;
|
|
@@ -5142,7 +5197,7 @@ Today's date: ${(/* @__PURE__ */ new Date()).toDateString()}.`;
|
|
|
5142
5197
|
* voice) and emits an empty `final`, so no text_delta ever streams. Both ship silence; both repair.
|
|
5143
5198
|
* Requires a host: without one there's no stream to detect speech on (and no one to speak to). */
|
|
5144
5199
|
get silentTurn() {
|
|
5145
|
-
return !!this.options.host && !this.spokeThisTurn;
|
|
5200
|
+
return !!this.options.host && !this.spokeThisTurn && !this.heldThisTurn;
|
|
5146
5201
|
}
|
|
5147
5202
|
/** A turn that voiced nothing is dead air. Re-prompt the reflex ONCE so the LLM itself voices a short
|
|
5148
5203
|
* line (no template). If it STILL says nothing, fall back to a minimal line so silence never ships.
|
|
@@ -5703,6 +5758,7 @@ Another agent just implemented the above. Independently check the CURRENT state
|
|
|
5703
5758
|
}
|
|
5704
5759
|
},
|
|
5705
5760
|
run: async ({ filler }) => {
|
|
5761
|
+
this.heldThisTurn = true;
|
|
5706
5762
|
if (filler) this.notify("hold_filler", String(filler));
|
|
5707
5763
|
return "Holding \u2014 listening for the rest of the user's thought. Do not respond further this turn.";
|
|
5708
5764
|
}
|
|
@@ -6812,6 +6868,7 @@ export {
|
|
|
6812
6868
|
makeTaskBatchTool,
|
|
6813
6869
|
makeTaskTool,
|
|
6814
6870
|
makeWebFetchTool,
|
|
6871
|
+
makeWebSearchAnthropicTool,
|
|
6815
6872
|
makeWebSearchTool,
|
|
6816
6873
|
mcpToolToAgentTool,
|
|
6817
6874
|
mcpToolsToAgentTools,
|
|
@@ -6845,6 +6902,7 @@ export {
|
|
|
6845
6902
|
validateToolCode,
|
|
6846
6903
|
validateWorktreeSlug,
|
|
6847
6904
|
webFetchTool,
|
|
6905
|
+
webSearchAnthropicTool,
|
|
6848
6906
|
webSearchTool,
|
|
6849
6907
|
worktreeBranchName,
|
|
6850
6908
|
writeFact,
|