@jini-ai/daemon 0.5.4 → 0.6.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/dist/agent-executor/contracts.d.ts +37 -5
- package/dist/agent-executor/event-translation.js +4 -0
- package/dist/agent-executor/events.d.ts +17 -2
- package/dist/agent-executor/events.js +245 -8
- package/dist/agent-executor/index.d.ts +2 -2
- package/dist/agent-executor/index.js +1 -1
- package/dist/agent-executor/launch.d.ts +11 -2
- package/dist/agent-executor/launch.js +62 -15
- package/dist/agent-executor/mcp-bridge.js +19 -6
- package/dist/agent-executor.d.ts +1 -1
- package/dist/agent-executor.js +1 -1
- package/dist/http/index.d.ts +5 -4
- package/dist/http/index.js +3 -2
- package/dist/http/research-tavily.adapter.d.ts +6 -0
- package/dist/http/research-tavily.adapter.js +109 -0
- package/dist/http/research.d.ts +20 -2
- package/dist/http/research.js +64 -149
- package/dist/http/route-manifest.js +2 -2
- package/dist/http/runs.d.ts +27 -2
- package/dist/http/runs.js +36 -1
- package/package.json +13 -13
|
@@ -2,7 +2,7 @@ import { spawn as nodeSpawn, } from 'node:child_process';
|
|
|
2
2
|
import { promises as fsPromises, } from 'node:fs';
|
|
3
3
|
import { tmpdir, } from 'node:os';
|
|
4
4
|
import { join, } from 'node:path';
|
|
5
|
-
import { agentCapabilities, applyAgentLaunchEnv, ensureAgentCapabilities, resolveModelForLaunch, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, checkPromptArgvBudget, checkWindowsCmdShimCommandLineBudget, checkWindowsDirectExeCommandLineBudget, prepareAgentLogFile, preparePromptFileForAgent, } from '@jini-ai/agent-runtime';
|
|
5
|
+
import { agentCapabilities, bindRuntimeAgentDef, defaultRuntimeState, getRuntimeModelDiscoveryDeps, userToolchainBinDirs, applyAgentLaunchEnv, ensureAgentCapabilities, resolveModelForLaunch, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, checkPromptArgvBudget, checkWindowsCmdShimCommandLineBudget, checkWindowsDirectExeCommandLineBudget, prepareAgentLogFile, preparePromptFileForAgent, } from '@jini-ai/agent-runtime';
|
|
6
6
|
import { collectProcessTreePids, createCommandInvocation, listProcessSnapshots, stopProcesses, } from '@jini-ai/platform';
|
|
7
7
|
import { applyImagePromptDelivery, } from '../image-prompt-delivery.js';
|
|
8
8
|
import { SUPPORTED_STREAM_FORMATS, AgentExecutorError, } from './contracts.js';
|
|
@@ -131,6 +131,22 @@ function buildAgentEnv(hostEnv, credentialEnv) {
|
|
|
131
131
|
}
|
|
132
132
|
return result;
|
|
133
133
|
}
|
|
134
|
+
/** Snapshot only host configuration used by spawn and config staging; credentials stay per-run.
|
|
135
|
+
* Returns an independent allowlisted record. @complexity O(1), fixed key list. */
|
|
136
|
+
export function selectAgentExecutorHostEnv({ env }, { runtimeState } = {}) {
|
|
137
|
+
const selected = buildAgentEnv(env, undefined);
|
|
138
|
+
for (const key of ['CODEX_HOME', 'CLAUDE_CONFIG_DIR', 'VELA_OPENCODE_BIN', 'AGENT_RUNTIME_HOME', 'AGENT_RUNTIME_RESOURCE_ROOT', 'VP_HOME', 'NPM_CONFIG_PREFIX', 'npm_config_prefix', 'APPDATA', 'LOCALAPPDATA', 'MISE_DATA_DIR', 'FNM_DIR']) {
|
|
139
|
+
if (typeof env[key] === 'string')
|
|
140
|
+
selected[key] = env[key];
|
|
141
|
+
}
|
|
142
|
+
// Host-configured resolution names are explicit configuration, never a scan of the env bag.
|
|
143
|
+
const state = runtimeState ?? defaultRuntimeState;
|
|
144
|
+
for (const key of Object.values(state.executable.envNames)) {
|
|
145
|
+
if (typeof env[key] === 'string')
|
|
146
|
+
selected[key] = env[key];
|
|
147
|
+
}
|
|
148
|
+
return selected;
|
|
149
|
+
}
|
|
134
150
|
/**
|
|
135
151
|
* Resolves once `child` emits `'spawn'`, or rejects on `'error'`. Replicates
|
|
136
152
|
* `@jini-ai/platform`'s own internal (non-exported) `waitForChildSpawn` race
|
|
@@ -156,11 +172,17 @@ function waitForSpawnOrError(child) {
|
|
|
156
172
|
* hiding which options belong together. Pure.
|
|
157
173
|
*/
|
|
158
174
|
function resolveAgentRuntimeDeps(options) {
|
|
175
|
+
const runtimeOptions = options.runtimeState ? { state: options.runtimeState } : {};
|
|
176
|
+
const envOptions = options.hostEnv ? { env: options.hostEnv } : {};
|
|
177
|
+
const lookupDef = options.getAgentDef ?? getAgentDef;
|
|
159
178
|
return {
|
|
160
|
-
getAgentDef:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
179
|
+
getAgentDef: (input) => {
|
|
180
|
+
const def = lookupDef(input);
|
|
181
|
+
return def && options.runtimeState ? bindRuntimeAgentDef({ def, state: options.runtimeState }) : def;
|
|
182
|
+
},
|
|
183
|
+
resolveAgentLaunch: options.resolveAgentLaunch ?? ((input, optional = {}) => resolveAgentLaunch(input, { ...optional, ...runtimeOptions, ...envOptions })),
|
|
184
|
+
ensureAgentCapabilities: options.ensureAgentCapabilities ?? ((input) => ensureAgentCapabilities(input, runtimeOptions)),
|
|
185
|
+
applyAgentLaunchEnv: options.applyAgentLaunchEnv ?? ((input, optional = {}) => applyAgentLaunchEnv(input, { appendPathDirs: userToolchainBinDirs({}, { ...runtimeOptions, ...envOptions }), ...optional })),
|
|
164
186
|
attachAcpSession: options.attachAcpSession ?? attachAcpSession,
|
|
165
187
|
attachPiRpcSession: options.attachPiRpcSession ?? attachPiRpcSession,
|
|
166
188
|
preparePromptFileForAgent: options.preparePromptFileForAgent ?? preparePromptFileForAgent,
|
|
@@ -397,7 +419,7 @@ export function buildAgentBuildArgsOptions({ input, systemPromptOverlay }) {
|
|
|
397
419
|
* @complexity O(n) in the overlay/prompt lengths — string concatenation only, no I/O.
|
|
398
420
|
* @overallScore 100/100
|
|
399
421
|
*/
|
|
400
|
-
export function resolveSystemPromptOverlayDelivery(input) {
|
|
422
|
+
export function resolveSystemPromptOverlayDelivery(input, { state } = {}) {
|
|
401
423
|
const { defId, systemPromptDelivery, resumesSessionViaCli, resumesSessionViaAcpLoad, overlay, prompt, resumeSessionId } = input;
|
|
402
424
|
if (typeof overlay !== 'string' || overlay.length === 0) {
|
|
403
425
|
return { promptPrefix: '', prompt, extraArgs: [], envOverrides: {} };
|
|
@@ -410,7 +432,7 @@ export function resolveSystemPromptOverlayDelivery(input) {
|
|
|
410
432
|
// `--help` probe ran and did not find the flag) withholds it. `capabilityKey === undefined`
|
|
411
433
|
// (e.g. `pi`'s existing `--append-system-prompt`, trusted unconditionally) always passes, same
|
|
412
434
|
// as an absent key.
|
|
413
|
-
const capabilityOk = capabilityKey === undefined || agentCapabilities.get(defId)?.[capabilityKey] !== false;
|
|
435
|
+
const capabilityOk = capabilityKey === undefined || (state?.capabilities ?? agentCapabilities).get(defId)?.[capabilityKey] !== false;
|
|
414
436
|
return { promptPrefix: '', prompt, extraArgs: capabilityOk ? [systemPromptDelivery.flag, overlay] : [], envOverrides: {} };
|
|
415
437
|
}
|
|
416
438
|
if (systemPromptDelivery?.strategy === 'env-var') {
|
|
@@ -607,7 +629,8 @@ export async function confirmChildSpawned({ input, deps }) {
|
|
|
607
629
|
export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
608
630
|
const options = { ...requiredArgs, ...optionalArgs };
|
|
609
631
|
const lifecycle = options.lifecycle;
|
|
610
|
-
const {
|
|
632
|
+
const hostEnv = selectAgentExecutorHostEnv({ env: options.hostEnv ?? process.env }, options.runtimeState ? { runtimeState: options.runtimeState } : {});
|
|
633
|
+
const { getAgentDef: getAgentDefFn, resolveAgentLaunch: resolveAgentLaunchFn, ensureAgentCapabilities: ensureAgentCapabilitiesFn, applyAgentLaunchEnv: applyAgentLaunchEnvFn, attachAcpSession: attachAcpSessionFn, attachPiRpcSession: attachPiRpcSessionFn, preparePromptFileForAgent: preparePromptFileForAgentFn, prepareAgentLogFile: prepareAgentLogFileFn, } = resolveAgentRuntimeDeps({ ...options, hostEnv });
|
|
611
634
|
const { createCommandInvocation: createCommandInvocationFn, spawn: spawnFn, listProcessSnapshots: listProcessSnapshotsFn, collectProcessTreePids: collectProcessTreePidsFn, stopProcesses: stopProcessesFn, } = resolveProcessDeps(options);
|
|
612
635
|
const { onCleanupFailure: onCleanupFailureFn, bufferedStdoutMaxBytes } = resolveMiscExecutorDeps(options);
|
|
613
636
|
const journal = options.journal;
|
|
@@ -640,6 +663,18 @@ export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
|
640
663
|
await lifecycle.finish({ runId, status: 'failed', code: null, signal: null, resumable: false });
|
|
641
664
|
throw new AgentExecutorError({ code: code, message: message });
|
|
642
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* Every run with a live child, keyed by run id, mapped to how a mid-run message reaches it — the
|
|
668
|
+
* stdin handle's `sendUserMessage` for a stdin-driven run, a constant `'unsupported'` for an
|
|
669
|
+
* ACP/pi run (whose RPC takes one prompt per turn). Removed on the child's `'close'`, so a
|
|
670
|
+
* finished or unknown run reads as `'not-running'`. Bounded by the number of live children.
|
|
671
|
+
*/
|
|
672
|
+
const liveRunInputs = new Map();
|
|
673
|
+
/** `AgentExecutor.sendUserMessage()` — see that interface method's own doc. @complexity O(1). */
|
|
674
|
+
async function sendUserMessage({ runId, text }) {
|
|
675
|
+
const deliver = liveRunInputs.get(runId);
|
|
676
|
+
return deliver ? deliver(text) : 'not-running';
|
|
677
|
+
}
|
|
643
678
|
/**
|
|
644
679
|
* `AgentExecutor.run()` — see that interface method's own doc for the
|
|
645
680
|
* public contract. Implementation note on shape: every guard below
|
|
@@ -699,18 +734,19 @@ export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
|
699
734
|
overlay: systemPromptOverlay,
|
|
700
735
|
prompt: imageDelivery.prompt,
|
|
701
736
|
resumeSessionId: preStagingRuntimeContext?.resumeSessionId,
|
|
702
|
-
});
|
|
737
|
+
}, options.runtimeState ? { state: options.runtimeState } : {});
|
|
703
738
|
// The def's own declared env (e.g. claude's `ENABLE_TOOL_SEARCH=false`) is a default the run's
|
|
704
739
|
// env can override. Detection already spawns with it (`detection.ts`); without this the run
|
|
705
740
|
// spawn silently dropped it. Declared by the def itself, so it never widens SEC-001's allowlist.
|
|
706
|
-
const resolvedEnv = { ...(def.env ?? {}), ...resolveRunEnv({ input: input, hostEnv
|
|
741
|
+
const resolvedEnv = { ...(def.env ?? {}), ...resolveRunEnv({ input: input, hostEnv }) };
|
|
707
742
|
const launch = await resolveLaunch({ input: { runId: input.runId, def, resolvedEnv }, deps: { resolveAgentLaunch: resolveAgentLaunchFn, failBeforeSpawn } });
|
|
708
743
|
const spawnEnv = applyAgentLaunchEnvFn({ env: { ...resolvedEnv }, launch });
|
|
709
744
|
// Resolve from the launch environment before staging or sending any prompt. Pin the same
|
|
710
745
|
// concrete ID that the picker displays; an opaque native route cannot silently start a run.
|
|
711
746
|
let modelCatalog;
|
|
712
747
|
try {
|
|
713
|
-
const
|
|
748
|
+
const selectModel = options.resolveModelForLaunch ?? ((input) => resolveModelForLaunch(input, options.runtimeState ? { deps: getRuntimeModelDiscoveryDeps({ state: options.runtimeState }) } : {}));
|
|
749
|
+
const selection = await selectModel({ def, context: {
|
|
714
750
|
executable: launch.launchPath, cwd: input.cwd, env: spawnEnv,
|
|
715
751
|
...(input.model && input.model !== 'default' ? { model: input.model } : {}),
|
|
716
752
|
...(input.resumeSessionId ? { resumeSessionId: input.resumeSessionId } : {}),
|
|
@@ -856,7 +892,7 @@ export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
|
856
892
|
// `codex.ts`'s `buildArgs` needs no argv change for this (CODEX_HOME is an env var, not a flag),
|
|
857
893
|
// so — unlike the `.mcp.json` staging above — this can run after `buildArgs` with no ordering
|
|
858
894
|
// constraint of its own; it is placed here only to keep the two staging steps adjacent.
|
|
859
|
-
preparedCodexHome = await prepareCodexHomeIfNeeded({ input: { runId: input.runId, def, mcpBridge }, deps: { mcpJsonInjection, hostEnv
|
|
895
|
+
preparedCodexHome = await prepareCodexHomeIfNeeded({ input: { runId: input.runId, def, mcpBridge }, deps: { mcpJsonInjection, hostEnv, releaseStagedResources, failBeforeSpawn } });
|
|
860
896
|
// Finding 1 of SEC-assistant-env-isolation-2026-09-07's one effect — stage this run's scratch
|
|
861
897
|
// `CLAUDE_CONFIG_DIR` directory. Unconditional for a `claude`-id run (unlike CODEX_HOME above,
|
|
862
898
|
// this does not depend on `mcpJsonInjection` being configured at all — see
|
|
@@ -866,7 +902,7 @@ export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
|
866
902
|
preparedClaudeConfigDir = await prepareClaudeConfigDirIfNeeded({ input: { runId: input.runId, def }, deps: {
|
|
867
903
|
enabled: claudeConfigDirIsolationEnabled,
|
|
868
904
|
claudeConfigDirIsolation,
|
|
869
|
-
hostEnv
|
|
905
|
+
hostEnv,
|
|
870
906
|
releaseStagedResources,
|
|
871
907
|
failBeforeSpawn,
|
|
872
908
|
} });
|
|
@@ -934,7 +970,18 @@ export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
|
934
970
|
expectsJiniBridge: writtenMcpJsonPath !== undefined,
|
|
935
971
|
})
|
|
936
972
|
: null;
|
|
937
|
-
|
|
973
|
+
// Registered with the lifecycle wiring above, before the spawn-confirmation await, so a child
|
|
974
|
+
// that closes immediately never leaves a stale entry behind.
|
|
975
|
+
const runId = input.runId;
|
|
976
|
+
liveRunInputs.set(runId, stdinHandle ? stdinHandle.sendUserMessage : async () => 'unsupported');
|
|
977
|
+
child.once('close', () => liveRunInputs.delete(runId));
|
|
978
|
+
try {
|
|
979
|
+
await confirmChildSpawned({ input: { runId: input.runId, def, child }, deps: { releaseStagedResources, failBeforeSpawn } });
|
|
980
|
+
}
|
|
981
|
+
catch (error) {
|
|
982
|
+
liveRunInputs.delete(runId);
|
|
983
|
+
throw error;
|
|
984
|
+
}
|
|
938
985
|
// Now — and only now — is there a live process that could consume the locked side effect, so
|
|
939
986
|
// this is where a def's handoff watcher starts. Deliberately not awaited: the whole point is to
|
|
940
987
|
// release the lock as soon as the child confirms the handoff, in parallel with this run
|
|
@@ -1019,6 +1066,6 @@ export function createAgentExecutor(requiredArgs, optionalArgs = {}) {
|
|
|
1019
1066
|
stdinHandle.imageContents = input.imageContents;
|
|
1020
1067
|
writePromptToStdin(def, child, stdinPrompt, stdinHandle);
|
|
1021
1068
|
}
|
|
1022
|
-
return { run };
|
|
1069
|
+
return { run, sendUserMessage };
|
|
1023
1070
|
}
|
|
1024
1071
|
//# sourceMappingURL=launch.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promises as fsPromises, } from 'node:fs';
|
|
2
2
|
import { homedir, tmpdir, } from 'node:os';
|
|
3
|
-
import { join, } from 'node:path';
|
|
3
|
+
import { join, resolve, } from 'node:path';
|
|
4
4
|
import { isRecord, errorMessage, } from './values.js';
|
|
5
5
|
const JINI_MCP_SERVER_KEY = 'jini';
|
|
6
6
|
/** The run-error code a run gets when its CLI reports the injected `jini` bridge as anything but connected. */
|
|
@@ -552,12 +552,23 @@ function defaultMkdtempCodexHome({ prefix }) {
|
|
|
552
552
|
function defaultRemoveCodexHomeDir({ path }) {
|
|
553
553
|
return fsPromises.rm(path, { recursive: true, force: true });
|
|
554
554
|
}
|
|
555
|
+
/** Config credentials stay run-scoped, but rollouts must survive both completion and cancellation.
|
|
556
|
+
* Native directory links keep Codex as the sole writer of its own persisted session format.
|
|
557
|
+
* Cleanup removes the links themselves, never their targets. Two fixed directories, O(1) I/O. */
|
|
558
|
+
async function defaultLinkCodexSessionStore({ runHome, sourceHome }, _optional = {}) {
|
|
559
|
+
for (const name of ['sessions', 'archived_sessions']) {
|
|
560
|
+
const target = resolve(sourceHome, name);
|
|
561
|
+
await fsPromises.mkdir(target, { recursive: true, mode: 0o700 });
|
|
562
|
+
await fsPromises.symlink(target, join(runHome, name), 'junction');
|
|
563
|
+
}
|
|
564
|
+
}
|
|
555
565
|
function resolveCodexHomeSeams(options) {
|
|
556
566
|
return {
|
|
557
567
|
mkdtemp: options.mkdtemp ?? defaultMkdtempCodexHome,
|
|
558
568
|
readFile: options.readFile ?? defaultReadMcpJsonFile,
|
|
559
569
|
writeFile: options.writeFile ?? defaultWriteMcpJsonFile,
|
|
560
570
|
removeDir: options.removeDir ?? defaultRemoveCodexHomeDir,
|
|
571
|
+
linkSessionStore: options.linkSessionStore ?? defaultLinkCodexSessionStore,
|
|
561
572
|
};
|
|
562
573
|
}
|
|
563
574
|
/**
|
|
@@ -573,8 +584,9 @@ function resolveCodexHomeSeams(options) {
|
|
|
573
584
|
* 0.151.0) to fail fast with a structured `401 Unauthorized` stream event, never an interactive
|
|
574
585
|
* login prompt or a hang — see `defs/codex.ts`'s module doc for the full transcript summary.
|
|
575
586
|
*
|
|
576
|
-
* **Never
|
|
577
|
-
*
|
|
587
|
+
* **Never changes the real config or credentials.** Those source files stay read-only. Only the
|
|
588
|
+
* native rollout directories are shared: deleting a run's scratch home must not erase the thread
|
|
589
|
+
* whose id the host already persisted. No copied login or run-bound MCP credential is retained.
|
|
578
590
|
*
|
|
579
591
|
* A failure after the directory is created (a rejecting `writeFile`, most plausibly) does not leak
|
|
580
592
|
* it: the directory may already hold a partial `config.toml` or a copied credential, so the
|
|
@@ -584,9 +596,9 @@ function resolveCodexHomeSeams(options) {
|
|
|
584
596
|
* `@jini-ai/agent-runtime`'s `prepareAgentLogFile`'s `label` is.
|
|
585
597
|
* @param entry - The shared bridge entry.
|
|
586
598
|
* @param sourceCodexHomeDir - Where to read the real install's `config.toml`/`auth.json` from — see {@link resolveSourceCodexHomeDir}.
|
|
587
|
-
* @param seams - Injectable mkdtemp/readFile/writeFile/removeDir, real filesystem by default.
|
|
588
|
-
* @throws Whatever
|
|
589
|
-
* @complexity O(1)
|
|
599
|
+
* @param seams - Injectable mkdtemp/readFile/writeFile/removeDir/linkSessionStore, real filesystem by default.
|
|
600
|
+
* @throws Whatever staging rejects with — the caller ({@link prepareCodexHomeIfNeeded}) turns that into a pre-spawn `AGENT_SPAWN_FAILED` failure, matching {@link writeMcpJsonForRun}'s own contract.
|
|
601
|
+
* @complexity O(1): fixed directory links and up to two best-effort file read/write round trips.
|
|
590
602
|
* @overallScore 100/100
|
|
591
603
|
*/
|
|
592
604
|
async function prepareCodexHomeForRun(runId, entry, sourceCodexHomeDir, seams) {
|
|
@@ -616,6 +628,7 @@ async function prepareCodexHomeForRun(runId, entry, sourceCodexHomeDir, seams) {
|
|
|
616
628
|
// No stored login (or unreadable) — the spawned CLI runs unauthenticated. Confirmed above:
|
|
617
629
|
// this fails the run fast and observably, never as a hang.
|
|
618
630
|
}
|
|
631
|
+
await seams.linkSessionStore({ runHome: dir, sourceHome: sourceCodexHomeDir }, {});
|
|
619
632
|
}
|
|
620
633
|
catch (err) {
|
|
621
634
|
await seams.removeDir({ path: dir }).catch(() => {
|
package/dist/agent-executor.d.ts
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* wrappers or a second implementation would let tested and shipped behavior drift.
|
|
7
7
|
* See agent-executor/index.ts for the driver contracts and invariants.
|
|
8
8
|
*/
|
|
9
|
-
export { type SupportedStreamFormat, isSupportedStreamFormat, type AgentExecutorCompatibility, assessAgentExecutorCompatibility, isAgentExecutorSupported, type AgentRuntimeEventTranslation, extractUsageTokens, translateStatusEvent, translateToolResultEvent, translateErrorEvent, translateTurnEndEvent, translateAgentRuntimeEvent, type AgentExecutorErrorCode, AgentExecutorError, type AgentExecutorRunInput, type AgentExecutor, type CollectProcessTreePidsPort, type StopProcessesPort, type AgentCleanupFailurePhase, type AgentCleanupFailureContext, type ContinuationOptions, type McpJsonInjectionOptions, MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, buildMcpJsonServerEntry, mergeMcpJsonContent, buildAcpMcpBridgeServers, mergeEnvContentMcpConfig, mergeEnvContentInstructions, buildCodexMcpServerToml, buildCodexHomeConfigToml, resolveSourceCodexHomeDir, type McpBridgeDelivery, buildMcpBridgeDelivery, type PreparedCodexHome, type PreparedClaudeConfigDir, type ClaudeConfigDirSeams, type ClaudeConfigDirIsolationOptions, resolveSourceClaudeConfigDir, type FailureClassificationContext, type ClassifyFailure, DEFAULT_BUFFERED_STDOUT_MAX_BYTES, applyAgentTranslationSideEffects, type CreateAgentExecutorOptions, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, resolveLaunch, stagePromptFile, stageLogFile, resolveMcpBridgeForRun, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, type SystemPromptOverlayDelivery, resolveSystemPromptOverlayDelivery, buildRunArgs, writeMcpJsonIfNeeded, type PreparedSystemPromptOverlayFile, prepareSystemPromptOverlayFileIfNeeded, prepareCodexHomeIfNeeded, prepareClaudeConfigDirIfNeeded, guardWindowsCommandLineBudget, type SpawnAgentChildProcessResult, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, armHandoffWatcher, runAcpDispatch, runPiRpcDispatch, createAgentExecutor, } from './agent-executor/index.js';
|
|
9
|
+
export { type SupportedStreamFormat, isSupportedStreamFormat, type AgentExecutorCompatibility, assessAgentExecutorCompatibility, isAgentExecutorSupported, type AgentRuntimeEventTranslation, extractUsageTokens, translateStatusEvent, translateToolResultEvent, translateErrorEvent, translateTurnEndEvent, translateAgentRuntimeEvent, type AgentExecutorErrorCode, AgentExecutorError, type AgentExecutorRunInput, type AgentExecutor, type UserMessageDelivery, type CollectProcessTreePidsPort, type StopProcessesPort, type AgentCleanupFailurePhase, type AgentCleanupFailureContext, type ContinuationOptions, type McpJsonInjectionOptions, MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, buildMcpJsonServerEntry, mergeMcpJsonContent, buildAcpMcpBridgeServers, mergeEnvContentMcpConfig, mergeEnvContentInstructions, buildCodexMcpServerToml, buildCodexHomeConfigToml, resolveSourceCodexHomeDir, type McpBridgeDelivery, buildMcpBridgeDelivery, type PreparedCodexHome, type PreparedClaudeConfigDir, type ClaudeConfigDirSeams, type ClaudeConfigDirIsolationOptions, resolveSourceClaudeConfigDir, type FailureClassificationContext, type ClassifyFailure, DEFAULT_BUFFERED_STDOUT_MAX_BYTES, applyAgentTranslationSideEffects, type CreateAgentExecutorOptions, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, selectAgentExecutorHostEnv, resolveLaunch, stagePromptFile, stageLogFile, resolveMcpBridgeForRun, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, type SystemPromptOverlayDelivery, resolveSystemPromptOverlayDelivery, buildRunArgs, writeMcpJsonIfNeeded, type PreparedSystemPromptOverlayFile, prepareSystemPromptOverlayFileIfNeeded, prepareCodexHomeIfNeeded, prepareClaudeConfigDirIfNeeded, guardWindowsCommandLineBudget, type SpawnAgentChildProcessResult, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, armHandoffWatcher, runAcpDispatch, runPiRpcDispatch, createAgentExecutor, } from './agent-executor/index.js';
|
|
10
10
|
//# sourceMappingURL=agent-executor.d.ts.map
|
package/dist/agent-executor.js
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* wrappers or a second implementation would let tested and shipped behavior drift.
|
|
7
7
|
* See agent-executor/index.ts for the driver contracts and invariants.
|
|
8
8
|
*/
|
|
9
|
-
export { isSupportedStreamFormat, assessAgentExecutorCompatibility, isAgentExecutorSupported, extractUsageTokens, translateStatusEvent, translateToolResultEvent, translateErrorEvent, translateTurnEndEvent, translateAgentRuntimeEvent, AgentExecutorError, MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, buildMcpJsonServerEntry, mergeMcpJsonContent, buildAcpMcpBridgeServers, mergeEnvContentMcpConfig, mergeEnvContentInstructions, buildCodexMcpServerToml, buildCodexHomeConfigToml, resolveSourceCodexHomeDir, buildMcpBridgeDelivery, resolveSourceClaudeConfigDir, DEFAULT_BUFFERED_STDOUT_MAX_BYTES, applyAgentTranslationSideEffects, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, resolveLaunch, stagePromptFile, stageLogFile, resolveMcpBridgeForRun, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, resolveSystemPromptOverlayDelivery, buildRunArgs, writeMcpJsonIfNeeded, prepareSystemPromptOverlayFileIfNeeded, prepareCodexHomeIfNeeded, prepareClaudeConfigDirIfNeeded, guardWindowsCommandLineBudget, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, armHandoffWatcher, runAcpDispatch, runPiRpcDispatch, createAgentExecutor, } from './agent-executor/index.js';
|
|
9
|
+
export { isSupportedStreamFormat, assessAgentExecutorCompatibility, isAgentExecutorSupported, extractUsageTokens, translateStatusEvent, translateToolResultEvent, translateErrorEvent, translateTurnEndEvent, translateAgentRuntimeEvent, AgentExecutorError, MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, buildMcpJsonServerEntry, mergeMcpJsonContent, buildAcpMcpBridgeServers, mergeEnvContentMcpConfig, mergeEnvContentInstructions, buildCodexMcpServerToml, buildCodexHomeConfigToml, resolveSourceCodexHomeDir, buildMcpBridgeDelivery, resolveSourceClaudeConfigDir, DEFAULT_BUFFERED_STDOUT_MAX_BYTES, applyAgentTranslationSideEffects, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, selectAgentExecutorHostEnv, resolveLaunch, stagePromptFile, stageLogFile, resolveMcpBridgeForRun, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, resolveSystemPromptOverlayDelivery, buildRunArgs, writeMcpJsonIfNeeded, prepareSystemPromptOverlayFileIfNeeded, prepareCodexHomeIfNeeded, prepareClaudeConfigDirIfNeeded, guardWindowsCommandLineBudget, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, armHandoffWatcher, runAcpDispatch, runPiRpcDispatch, createAgentExecutor, } from './agent-executor/index.js';
|
|
10
10
|
//# sourceMappingURL=agent-executor.js.map
|
package/dist/http/index.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export type { CatalogueEntry, HostEditor, HostEditorsResponse, HostToolLaunchPla
|
|
|
9
9
|
export { applicableForPlatform, CATALOGUE, currentPlatform, defaultProbeEnv, hostEditorsRoute, launchHostTool, listAvailableEditors, pathDirs, probeCommandOnPath, probeMacBundle, registerHostToolsRoutes, resolveEntry, resolveHostToolLaunchPlan, } from './host-tools.js';
|
|
10
10
|
export type { DaemonShutdownResponse, DaemonStatusDeps, DaemonStatusResponse, } from './daemon-status.js';
|
|
11
11
|
export { daemonShutdownRoute, daemonStatusRoute, registerDaemonStatusRoutes } from './daemon-status.js';
|
|
12
|
-
export type { RunCancelResponse, RunCreateRequest, RunHttpDeps, RunInternalErrorContext, RunListResponse, RunStartContext, RunStartHandler, RunStartResponse, RunStatusResponse, } from './runs.js';
|
|
13
|
-
export { registerRunEventStream, registerRunRoutes, RUN_EVENTS_ROUTE_PATH, runCancelRoute, runListRoute, runStartRoute, runStatusRoute, } from './runs.js';
|
|
12
|
+
export type { RunCancelResponse, RunCreateRequest, RunHttpDeps, RunInternalErrorContext, RunListResponse, RunStartContext, RunMessageRequest, RunMessageResponse, RunStartHandler, RunStartResponse, RunStatusResponse, } from './runs.js';
|
|
13
|
+
export { registerRunEventStream, registerRunRoutes, RUN_EVENTS_ROUTE_PATH, runCancelRoute, runListRoute, runMessageRoute, RUN_MESSAGE_MAX_CHARS, runStartRoute, runStatusRoute, } from './runs.js';
|
|
14
14
|
export { JINI_ROUTE_MANIFEST, manifestRoutesForFamilies, routeFamilyManifest } from './route-manifest.js';
|
|
15
15
|
export type { AgentListResponse, AgentModelSummary, AgentsHttpDeps, AgentSummary } from './agents.js';
|
|
16
16
|
export { agentListRoute, agentRescanRoute, registerAgentRoutes } from './agents.js';
|
|
@@ -40,8 +40,8 @@ export type { HealthHttpDeps, HealthReadinessResult, LivenessResponse, Readiness
|
|
|
40
40
|
export { apiHealthRoute, apiReadyRoute, apiVersionInfoRoute, healthRoute, readyRoute, registerHealthRoutes, versionInfoRoute, } from './health.js';
|
|
41
41
|
export type { AuthCredentials, AuthProvider, AuthSession, AuthUser, Charge, ChargeInput, ChargeStatus, ConnectorsAuthSessionResponse, ConnectorsAuthUserResponse, ConnectorsAuthVerifyResponse, ConnectorsChargeResponse, ConnectorsDbQueryResponse, ConnectorsDbRecordResponse, ConnectorsHttpDeps, ConnectorsInternalErrorContext, ConnectorsOkResponse, ConnectorsStorageGetResponse, ConnectorsStorageListResponse, ConnectorsStorageMetaResponse, DbProvider, DbQuery, DbRecord, PaymentsProvider, RealtimeProvider, StorageObjectMeta, StorageProvider, StoragePutOptions, } from './connectors.js';
|
|
42
42
|
export { connectorsAuthSessionRoute, connectorsAuthSignInRoute, connectorsAuthSignOutRoute, connectorsAuthSignUpRoute, connectorsDbDeleteRoute, connectorsDbGetRoute, connectorsDbInsertRoute, connectorsDbQueryRoute, connectorsDbUpdateRoute, connectorsPaymentsChargeRoute, connectorsPaymentsGetRoute, connectorsPaymentsRefundRoute, connectorsRealtimePublishRoute, connectorsStorageDeleteRoute, connectorsStorageGetRoute, connectorsStorageListRoute, connectorsStoragePutRoute, registerConnectorsRoutes, } from './connectors.js';
|
|
43
|
-
export type { ResearchHttpDeps, ResearchInternalErrorContext, ResearchProviderCredentials, ResearchSearchResponse, ResearchSource, } from './research.js';
|
|
44
|
-
export { registerResearchRoutes, researchSearchRoute } from './research.js';
|
|
43
|
+
export type { ResearchProvider, ResearchSearchRequest, ResearchHttpDeps, ResearchInternalErrorContext, ResearchProviderCredentials, ResearchSearchResponse, ResearchSource, } from './research.js';
|
|
44
|
+
export { createResearchSearchRoute, registerResearchRoutes, researchSearchRoute } from './research.js';
|
|
45
45
|
export type { MediaGenerateResponse, MediaHttpDeps, MediaInternalErrorContext, MediaTaskDeleteResponse, MediaTaskListResponse, MediaTaskResponse, } from './media.js';
|
|
46
46
|
export { mediaGenerateRoute, mediaTaskDeleteRoute, mediaTaskGetRoute, mediaTaskListRoute, registerMediaRoutes, } from './media.js';
|
|
47
47
|
export type { AttachmentClaim, AttachmentRejectionReason, AttachmentsHttpDeps, AttachmentsInternalErrorContext, AttachmentStore, AttachmentUploadResponse, CreateDiskAttachmentStoreOptions, ObservedAttachmentIdentity, PendingAttachmentSummary, RecordedAttachmentIdentity, StoredAttachment, } from './attachments.js';
|
|
@@ -49,4 +49,5 @@ export { ATTACHMENTS_ROUTE_PATH, AttachmentRejectedError, createDiskAttachmentSt
|
|
|
49
49
|
export type { XaiAuthStatusResponse, XaiHttpDeps, XaiInternalErrorContext, XaiOauthStartResponse, XaiOkResponse, XaiSearchResponse, } from './xai.js';
|
|
50
50
|
export { registerXaiRoutes, xaiAuthStatusRoute, xaiOauthCancelRoute, xaiOauthCompleteRoute, xaiOauthDisconnectRoute, xaiOauthStartRoute, xaiSearchRoute, } from './xai.js';
|
|
51
51
|
export * from './run-credentials.js';
|
|
52
|
+
export { createTavilyResearchProvider } from './research-tavily.adapter.js';
|
|
52
53
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/http/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { cancelRunsOwnedBy } from './cancel-owned-runs.js';
|
|
|
3
3
|
export { ACTIVE_CONTEXT_TTL_MS, getActiveRoute, registerActiveContextRoutes, setActiveRoute, } from './active-context.js';
|
|
4
4
|
export { applicableForPlatform, CATALOGUE, currentPlatform, defaultProbeEnv, hostEditorsRoute, launchHostTool, listAvailableEditors, pathDirs, probeCommandOnPath, probeMacBundle, registerHostToolsRoutes, resolveEntry, resolveHostToolLaunchPlan, } from './host-tools.js';
|
|
5
5
|
export { daemonShutdownRoute, daemonStatusRoute, registerDaemonStatusRoutes } from './daemon-status.js';
|
|
6
|
-
export { registerRunEventStream, registerRunRoutes, RUN_EVENTS_ROUTE_PATH, runCancelRoute, runListRoute, runStartRoute, runStatusRoute, } from './runs.js';
|
|
6
|
+
export { registerRunEventStream, registerRunRoutes, RUN_EVENTS_ROUTE_PATH, runCancelRoute, runListRoute, runMessageRoute, RUN_MESSAGE_MAX_CHARS, runStartRoute, runStatusRoute, } from './runs.js';
|
|
7
7
|
export { JINI_ROUTE_MANIFEST, manifestRoutesForFamilies, routeFamilyManifest } from './route-manifest.js';
|
|
8
8
|
export { agentListRoute, agentRescanRoute, registerAgentRoutes } from './agents.js';
|
|
9
9
|
export { memoryClearExtractionsRoute, memoryClearVerificationsRoute, memoryCreateEntryRoute, memoryDeleteEntryRoute, memoryListExtractionsRoute, memoryListVerificationsRoute, memoryOverviewRoute, memoryReadEntryRoute, memoryRemoveExtractionRoute, memoryRemoveVerificationRoute, memoryTreeRoute, memoryUpdateEntryRoute, memoryUpdateTreeNodeRoute, memoryWriteConfigRoute, memoryWriteIndexRoute, registerMemoryEventStream, registerMemoryRoutes, } from './memory.js';
|
|
@@ -19,9 +19,10 @@ export { registerTerminalEventStream, registerTerminalRoutes, terminalCreateRout
|
|
|
19
19
|
export { registerModelProxyRoutes } from './model-proxy.js';
|
|
20
20
|
export { apiHealthRoute, apiReadyRoute, apiVersionInfoRoute, healthRoute, readyRoute, registerHealthRoutes, versionInfoRoute, } from './health.js';
|
|
21
21
|
export { connectorsAuthSessionRoute, connectorsAuthSignInRoute, connectorsAuthSignOutRoute, connectorsAuthSignUpRoute, connectorsDbDeleteRoute, connectorsDbGetRoute, connectorsDbInsertRoute, connectorsDbQueryRoute, connectorsDbUpdateRoute, connectorsPaymentsChargeRoute, connectorsPaymentsGetRoute, connectorsPaymentsRefundRoute, connectorsRealtimePublishRoute, connectorsStorageDeleteRoute, connectorsStorageGetRoute, connectorsStorageListRoute, connectorsStoragePutRoute, registerConnectorsRoutes, } from './connectors.js';
|
|
22
|
-
export { registerResearchRoutes, researchSearchRoute } from './research.js';
|
|
22
|
+
export { createResearchSearchRoute, registerResearchRoutes, researchSearchRoute } from './research.js';
|
|
23
23
|
export { mediaGenerateRoute, mediaTaskDeleteRoute, mediaTaskGetRoute, mediaTaskListRoute, registerMediaRoutes, } from './media.js';
|
|
24
24
|
export { ATTACHMENTS_ROUTE_PATH, AttachmentRejectedError, createDiskAttachmentStore, detectAttachmentKind, handleAttachmentCleanup, handleAttachmentUpload, isUnchangedAttachment, registerAttachmentRoutes, sanitizeAttachmentName, writeBoundedAttachmentBody, } from './attachments.js';
|
|
25
25
|
export { registerXaiRoutes, xaiAuthStatusRoute, xaiOauthCancelRoute, xaiOauthCompleteRoute, xaiOauthDisconnectRoute, xaiOauthStartRoute, xaiSearchRoute, } from './xai.js';
|
|
26
26
|
export * from './run-credentials.js';
|
|
27
|
+
export { createTavilyResearchProvider } from './research-tavily.adapter.js';
|
|
27
28
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ResearchProvider } from './research.js';
|
|
2
|
+
/** Creates today's transport with a host-owned fetch port. */
|
|
3
|
+
export declare function createTavilyResearchProvider(_required: Record<string, never>, options?: {
|
|
4
|
+
fetch?: typeof globalThis.fetch;
|
|
5
|
+
}): ResearchProvider;
|
|
6
|
+
//# sourceMappingURL=research-tavily.adapter.d.ts.map
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** Tavily default adapter. Request limits, timeout and secret-redaction policy remain here. */
|
|
2
|
+
import { validateBaseUrl } from '@jini-ai/agent-runtime';
|
|
3
|
+
import { redactSecrets } from '@jini-ai/core';
|
|
4
|
+
const DEFAULT_TAVILY_BASE_URL = 'https://api.tavily.com';
|
|
5
|
+
/** Tavily's own documented cap on `max_results` (see OD's `tavily.ts#TAVILY_MAX_RESULTS_LIMIT`). */
|
|
6
|
+
const TAVILY_MAX_RESULTS_LIMIT = 20;
|
|
7
|
+
const DEFAULT_MAX_SOURCES = 5;
|
|
8
|
+
/** Matches OD's own `tavily.ts` timeout — see research.ts's module doc. */
|
|
9
|
+
const DEFAULT_TAVILY_TIMEOUT_MS = 30_000;
|
|
10
|
+
/**
|
|
11
|
+
* Calls Tavily's real `POST /search` endpoint directly — see research.ts's module doc for the port's exact
|
|
12
|
+
* scope/provenance. Throws (never a `Result`) on any failure; the route handler in research.ts is the one
|
|
13
|
+
* place that converts a thrown error into the package's SEC-005 response shape.
|
|
14
|
+
*
|
|
15
|
+
* `apiKey` is a separate, non-optional parameter rather than being read off `credentials`, so the
|
|
16
|
+
* "credential is present" invariant is carried by the type system instead of by a runtime guard.
|
|
17
|
+
* This function used to take only `credentials` and re-check `credentials.apiKey` itself, but the
|
|
18
|
+
* route caller in research.ts already returns `NOT_CONFIGURED` before it ever gets here — the check was
|
|
19
|
+
* unreachable by construction, so it is now expressed as a required argument instead of dead code.
|
|
20
|
+
* `credentials` is still passed for its optional transport config (`baseUrl`).
|
|
21
|
+
*/
|
|
22
|
+
async function tavilySearch({ apiKey, credentials, request }, { fetch: fetchImpl = globalThis.fetch } = {}) {
|
|
23
|
+
const baseUrl = credentials.baseUrl ?? DEFAULT_TAVILY_BASE_URL;
|
|
24
|
+
const baseUrlCheck = validateBaseUrl({ baseUrl });
|
|
25
|
+
if (baseUrlCheck.error) {
|
|
26
|
+
throw new Error(baseUrlCheck.error);
|
|
27
|
+
}
|
|
28
|
+
const base = baseUrl.replace(/\/+$/, '');
|
|
29
|
+
// Floor before clamping, matching OD's real `clampMaxSources` — see research.ts's module doc. Without the
|
|
30
|
+
// floor, a fractional `maxSources` (e.g. `2.7`, or `0.5` before the `Math.max(1, ...)` floor
|
|
31
|
+
// below) would forward a non-integer `max_results` straight to Tavily's real API.
|
|
32
|
+
const maxResults = Math.max(1, Math.min(Math.floor(request.maxSources ?? DEFAULT_MAX_SOURCES), TAVILY_MAX_RESULTS_LIMIT));
|
|
33
|
+
const body = {
|
|
34
|
+
query: request.query,
|
|
35
|
+
search_depth: 'basic',
|
|
36
|
+
max_results: maxResults,
|
|
37
|
+
include_answer: true,
|
|
38
|
+
include_raw_content: false,
|
|
39
|
+
};
|
|
40
|
+
// The timeout must stay armed for the full operation, not just until `fetch` resolves —
|
|
41
|
+
// `fetch` resolves as soon as response headers arrive, before the body is read. A round-2
|
|
42
|
+
// external audit caught (and locally reproduced) an earlier version of this fix that cleared
|
|
43
|
+
// the timer right after `fetch` resolved, leaving `response.text()`/`response.json()` below
|
|
44
|
+
// completely unbounded against a server that sends headers promptly and then stalls the body.
|
|
45
|
+
//
|
|
46
|
+
// `TavilyHttpError` marks an error already redacted and formatted by the `!response.ok` branch
|
|
47
|
+
// below, so the outer catch can rethrow it verbatim instead of wrapping it a second time (which
|
|
48
|
+
// would otherwise produce a "Tavily request failed: Tavily 429: ..." double-prefixed message).
|
|
49
|
+
class TavilyHttpError extends Error {
|
|
50
|
+
}
|
|
51
|
+
const timeoutController = new AbortController();
|
|
52
|
+
const timeoutHandle = setTimeout(() => timeoutController.abort(), DEFAULT_TAVILY_TIMEOUT_MS);
|
|
53
|
+
// Assigned in the `try` and returned *after* the `finally`, rather than returned from inside the
|
|
54
|
+
// `try`. Both forms behave identically, but a return-through-`finally` compiles to three copies of
|
|
55
|
+
// the `finally` body (normal completion, return, throw) and one of those is unreachable here — the
|
|
56
|
+
// `try` cannot fall off its end and the `catch` always throws. Falling through to a single return
|
|
57
|
+
// keeps the cleanup path honestly measurable instead of permanently one-third uncovered.
|
|
58
|
+
let output;
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetchImpl(`${base}/search`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: { 'content-type': 'application/json', authorization: `Bearer ${apiKey}` },
|
|
63
|
+
body: JSON.stringify(body),
|
|
64
|
+
signal: timeoutController.signal,
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const text = await response.text().catch(() => '');
|
|
68
|
+
throw new TavilyHttpError(redactSecrets({ input: `Tavily ${response.status}: ${text.slice(0, 200) || 'no body'}` }, { exactSecrets: [apiKey] }));
|
|
69
|
+
}
|
|
70
|
+
const json = (await response.json());
|
|
71
|
+
const answer = typeof json.answer === 'string' ? json.answer : '';
|
|
72
|
+
const rawResults = Array.isArray(json.results) ? json.results : [];
|
|
73
|
+
const sources = [];
|
|
74
|
+
for (const raw of rawResults) {
|
|
75
|
+
const url = typeof raw.url === 'string' ? raw.url : '';
|
|
76
|
+
if (!url)
|
|
77
|
+
continue;
|
|
78
|
+
const publishedAt = typeof raw.published_date === 'string' && raw.published_date.trim() ? raw.published_date.trim() : undefined;
|
|
79
|
+
sources.push({
|
|
80
|
+
title: typeof raw.title === 'string' && raw.title.trim() ? raw.title.trim() : url,
|
|
81
|
+
url,
|
|
82
|
+
snippet: typeof raw.content === 'string' ? raw.content.trim().slice(0, 800) : '',
|
|
83
|
+
provider: 'tavily',
|
|
84
|
+
...(publishedAt ? { publishedAt } : {}),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
output = { answer, sources };
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (!timeoutController.signal.aborted && error instanceof TavilyHttpError) {
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
+
throw new Error(redactSecrets({
|
|
95
|
+
input: timeoutController.signal.aborted
|
|
96
|
+
? `Tavily request timed out after ${DEFAULT_TAVILY_TIMEOUT_MS}ms`
|
|
97
|
+
: `Tavily request failed: ${message}`,
|
|
98
|
+
}, { exactSecrets: [apiKey] }));
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
clearTimeout(timeoutHandle);
|
|
102
|
+
}
|
|
103
|
+
return output;
|
|
104
|
+
}
|
|
105
|
+
/** Creates today's transport with a host-owned fetch port. */
|
|
106
|
+
export function createTavilyResearchProvider(_required, options = {}) {
|
|
107
|
+
return { id: 'tavily', search: (input) => tavilySearch(input, options) };
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=research-tavily.adapter.js.map
|
package/dist/http/research.d.ts
CHANGED
|
@@ -25,7 +25,22 @@ export interface ResearchProviderCredentials {
|
|
|
25
25
|
readonly baseUrl?: string;
|
|
26
26
|
readonly model?: string;
|
|
27
27
|
}
|
|
28
|
+
/** Research transport contract: the route owns validation/HTTP errors; adapters own vendor I/O. */
|
|
29
|
+
export interface ResearchProvider {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
search(required: {
|
|
32
|
+
apiKey: string;
|
|
33
|
+
credentials: ResearchProviderCredentials;
|
|
34
|
+
request: ResearchSearchRequest;
|
|
35
|
+
}, optional: Record<string, never>): Promise<{
|
|
36
|
+
readonly answer: string;
|
|
37
|
+
readonly sources: readonly ResearchSource[];
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
28
40
|
export interface ResearchHttpDeps {
|
|
41
|
+
readonly provider?: ResearchProvider;
|
|
42
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
43
|
+
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
29
44
|
/** Resolves per-provider credentials. Defaults to `TAVILY_API_KEY` for the built-in Tavily transport. */
|
|
30
45
|
readonly resolveCredentials?: ({ providerId }: {
|
|
31
46
|
providerId: string;
|
|
@@ -33,10 +48,14 @@ export interface ResearchHttpDeps {
|
|
|
33
48
|
/** Host-owned sink for the real exception behind a generic `INTERNAL_ERROR` response (SEC-005). Defaults to `console.error`. */
|
|
34
49
|
readonly onInternalError?: (context: ResearchInternalErrorContext) => void;
|
|
35
50
|
}
|
|
36
|
-
interface ResearchSearchRequest {
|
|
51
|
+
export interface ResearchSearchRequest {
|
|
37
52
|
readonly query: string;
|
|
38
53
|
readonly maxSources?: number;
|
|
39
54
|
}
|
|
55
|
+
/** Builds one route over a host-selected provider, preserving the default Tavily validation contract. */
|
|
56
|
+
export declare function createResearchSearchRoute({ provider }: {
|
|
57
|
+
provider?: ResearchProvider;
|
|
58
|
+
}, _optional?: Record<string, never>): import("@jini-ai/http-kit").JsonRouteSpec<ResearchSearchRequest, ResearchSearchResponse, ResearchHttpDeps, undefined>;
|
|
40
59
|
export declare const researchSearchRoute: import("@jini-ai/http-kit").JsonRouteSpec<ResearchSearchRequest, ResearchSearchResponse, ResearchHttpDeps, undefined>;
|
|
41
60
|
/** Mounts `POST /api/research/search` on `app`. A pack's `http(app, services)` calls this directly. */
|
|
42
61
|
export declare function registerResearchRoutes({ app, deps, adapter }: {
|
|
@@ -44,5 +63,4 @@ export declare function registerResearchRoutes({ app, deps, adapter }: {
|
|
|
44
63
|
readonly deps: ResearchHttpDeps;
|
|
45
64
|
readonly adapter: AdapterContext;
|
|
46
65
|
}, _optional?: Record<string, never>): void;
|
|
47
|
-
export {};
|
|
48
66
|
//# sourceMappingURL=research.d.ts.map
|