agent-accelerator 0.5.9 → 0.6.0
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 +3 -1
- package/examples/prompts/SYSTEM_PROMPT.md +2 -0
- package/examples/prompts/SYSTEM_PROMPT_AGENT.md +4 -0
- package/examples/prompts/SYSTEM_PROMPT_TOOLS.md +1 -0
- package/package.json +4 -1
- package/src/agent/agent.ts +366 -161
- package/src/agent/architecture.md +13 -12
- package/src/agent/config-blocks.ts +39 -12
- package/src/agent/context.ts +8 -3
- package/src/agent/delegation.ts +82 -29
- package/src/agent/loop.ts +444 -365
- package/src/agent/subagent.ts +1 -3
- package/src/agent/subagents-tool.ts +45 -7
- package/src/agent/subagents.md +3 -0
- package/src/agent/turns.ts +3 -1
- package/src/agent/worker.ts +56 -27
- package/src/agent/workers.ts +113 -20
- package/src/architecture.md +16 -15
- package/src/index.ts +34 -10
- package/src/models/architecture.md +4 -3
- package/src/models/catalog-cache.ts +6 -5
- package/src/models/catalog.ts +39 -30
- package/src/providers/architecture.md +10 -8
- package/src/providers/google.ts +147 -59
- package/src/providers/openai-compat.ts +57 -49
- package/src/providers/openai.ts +54 -37
- package/src/providers/openrouter.ts +85 -30
- package/src/providers/registry.ts +6 -21
- package/src/providers/shared.ts +87 -33
- package/src/providers.ts +56 -115
- package/src/scheduler/architecture.md +7 -6
- package/src/scheduler/scheduled-actions.md +4 -0
- package/src/scheduler/scheduler.ts +186 -60
- package/src/scheduler/store.ts +23 -10
- package/src/scheduler/time.ts +17 -3
- package/src/scheduler/tool.ts +33 -7
- package/src/session/architecture.md +7 -6
- package/src/session/journal.ts +38 -12
- package/src/session/store.ts +122 -61
- package/src/session/usage.ts +58 -9
- package/src/streaming/architecture.md +4 -3
- package/src/streaming/event-stream.ts +26 -12
- package/src/telemetry.ts +6 -2
- package/src/tools/architecture.md +8 -7
- package/src/tools/executor.ts +50 -48
- package/src/tools/schema.ts +10 -6
- package/src/tools/subagent-result.ts +6 -1
- package/src/tools/tool.ts +9 -11
- package/src/types/agent.ts +2 -21
- package/src/types/architecture.md +11 -10
- package/src/types/core.ts +1 -9
- package/src/types/errors.ts +26 -4
- package/src/types/model.ts +0 -4
- package/src/types/tool.ts +12 -2
- package/src/update-models.ts +5 -5
- package/src/utils/architecture.md +16 -15
- package/src/utils/cache.ts +1 -3
- package/src/utils/durable.ts +17 -5
- package/src/utils/env.ts +9 -7
- package/src/utils/errors.ts +6 -14
- package/src/utils/headers.ts +3 -10
- package/src/utils/media.ts +23 -8
- package/src/utils/raw-capture.ts +9 -2
- package/src/utils/retry.ts +15 -3
- package/src/utils/safe-io.ts +29 -7
- package/src/utils/serialization.ts +1 -4
- package/src/utils/session.ts +1 -2
package/src/index.ts
CHANGED
|
@@ -37,7 +37,14 @@ export { zodToJsonSchema, cleanJsonSchema } from "./tools/schema.ts";
|
|
|
37
37
|
*/
|
|
38
38
|
export { executeToolCalls } from "./tools/executor.ts";
|
|
39
39
|
|
|
40
|
-
export {
|
|
40
|
+
export {
|
|
41
|
+
assertPathAllowed,
|
|
42
|
+
enforceFileAccess,
|
|
43
|
+
fetchRemoteBytes,
|
|
44
|
+
isPrivateAddress,
|
|
45
|
+
RemoteFetchError,
|
|
46
|
+
MAX_REMOTE_FETCH_BYTES,
|
|
47
|
+
} from "./utils/safe-io.ts";
|
|
41
48
|
|
|
42
49
|
// Multi-Agent Delegation & Tools
|
|
43
50
|
export {
|
|
@@ -126,12 +133,8 @@ export {
|
|
|
126
133
|
GoogleInteractionsProvider,
|
|
127
134
|
clearInteractionChains,
|
|
128
135
|
} from "./providers/google.ts";
|
|
129
|
-
export {
|
|
130
|
-
|
|
131
|
-
} from "./providers/openrouter.ts";
|
|
132
|
-
export {
|
|
133
|
-
OpenAIResponsesProvider,
|
|
134
|
-
} from "./providers/openai.ts";
|
|
136
|
+
export { OpenRouterChatCompletionsProvider } from "./providers/openrouter.ts";
|
|
137
|
+
export { OpenAIResponsesProvider } from "./providers/openai.ts";
|
|
135
138
|
/**
|
|
136
139
|
* @deprecated Internal provider mappers/routing helpers. Prefer the
|
|
137
140
|
* provider-agnostic registry (`resolveModel`/`getProvider`); direct mapper
|
|
@@ -251,14 +254,36 @@ export {
|
|
|
251
254
|
emptyTotals,
|
|
252
255
|
} from "./session/store.ts";
|
|
253
256
|
export type { UsageReport, UsageLine, UsageTotals, AgentUsage, WorkerUsage, CostSource } from "./session/usage.ts";
|
|
254
|
-
export type {
|
|
257
|
+
export type {
|
|
258
|
+
SessionLimits,
|
|
259
|
+
SessionPayloadStatus,
|
|
260
|
+
PersistedAgentSession,
|
|
261
|
+
SessionTotals,
|
|
262
|
+
SessionAgentLike,
|
|
263
|
+
LoadedSessionDir,
|
|
264
|
+
PersistedSubAgentTrace,
|
|
265
|
+
SessionRunMark,
|
|
266
|
+
SessionRunEnd,
|
|
267
|
+
SessionPending,
|
|
268
|
+
SessionPendingPrompt,
|
|
269
|
+
SessionToolRecord,
|
|
270
|
+
} from "./session/store.ts";
|
|
255
271
|
|
|
256
272
|
// Utilities
|
|
257
273
|
/**
|
|
258
274
|
* @deprecated Session-routing internals. Prefer agent-level `sessionId`;
|
|
259
275
|
* direct use moves to the future `/internal` entry.
|
|
260
276
|
*/
|
|
261
|
-
export {
|
|
277
|
+
export {
|
|
278
|
+
createSessionId,
|
|
279
|
+
hashSessionPart,
|
|
280
|
+
createTrackingId,
|
|
281
|
+
nowMs,
|
|
282
|
+
newRunId,
|
|
283
|
+
newTurnId,
|
|
284
|
+
previewPrompt,
|
|
285
|
+
parseModelRef,
|
|
286
|
+
} from "./utils/session.ts";
|
|
262
287
|
export type { ParsedModelRef } from "./utils/session.ts";
|
|
263
288
|
/**
|
|
264
289
|
* @deprecated Raw env access. Prefer explicit `Agent` config (which wins over
|
|
@@ -344,7 +369,6 @@ export type {
|
|
|
344
369
|
RetryPolicyConfig,
|
|
345
370
|
AgentLogger,
|
|
346
371
|
ToolChoiceOption,
|
|
347
|
-
StopOption,
|
|
348
372
|
Budget,
|
|
349
373
|
BudgetState,
|
|
350
374
|
SubAgentRunIds,
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
The model catalog: context limits, prices, modalities and reasoning options come from models.dev, not from code.
|
|
4
4
|
|
|
5
|
-
| File
|
|
6
|
-
|
|
|
5
|
+
| File | What it is |
|
|
6
|
+
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
7
7
|
| `catalog-cache.ts` | Downloads and caches `models.dev/api.json` in `<home>/catalog/` (or `AGENT_CACHE_DIR`). Stale-while-revalidate: an expired catalog is served at once and refreshed in the background (8 s timeout, 10 min backoff after a failure); only a cold start waits. `AGENT_CATALOG_REFRESH=off` stops automatic refreshes. |
|
|
8
|
-
| `catalog.ts`
|
|
8
|
+
| `catalog.ts` | Lookups (`getModelFromCatalog`), `registerModel`, thinking validation (`validateModelThinking`, which throws `ThinkingLevelError`, a one-line `ConfigError`), and the exported `GOOGLE_/OPENAI_/OPENROUTER_MODELS` arrays (rebuilt in place when the catalog changes). |
|
|
9
9
|
|
|
10
10
|
## Invariants
|
|
11
|
+
|
|
11
12
|
- Never hand-edit the cache file; register custom models with `registerModel()`. Verified modality fixes go in `MODALITY_OVERRIDES`.
|
|
12
13
|
- The global bare-id fallback applies to first-class providers and explicit bare-id lookups only. A custom prefix never borrows another provider's price or modalities: unknown stays unknown.
|
|
13
14
|
- A payload that is not a catalog (fewer than 3 providers with models) never overwrites the cache.
|
|
@@ -313,7 +313,7 @@ export async function refreshModelCatalog(options: RefreshCatalogOptions = {}):
|
|
|
313
313
|
fallbackToDiskCache();
|
|
314
314
|
return getCatalogStatus();
|
|
315
315
|
}
|
|
316
|
-
} catch
|
|
316
|
+
} catch {
|
|
317
317
|
clearTimeout(timer);
|
|
318
318
|
// If download fails, retain disk cache if available
|
|
319
319
|
fallbackToDiskCache();
|
|
@@ -356,7 +356,6 @@ export async function refreshModelCatalog(options: RefreshCatalogOptions = {}):
|
|
|
356
356
|
return getCatalogStatus();
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
-
|
|
360
359
|
/** True when `AGENT_CATALOG_REFRESH` is `off`/`0`/`false`: never touch the network automatically. */
|
|
361
360
|
function automaticRefreshDisabled(): boolean {
|
|
362
361
|
const v = getEnv("AGENT_CATALOG_REFRESH")?.trim().toLowerCase();
|
|
@@ -388,9 +387,11 @@ export async function ensureModelCatalogFresh(options: RefreshCatalogOptions = {
|
|
|
388
387
|
const start = (): Promise<CatalogStatus> => {
|
|
389
388
|
if (!inFlightRefresh) {
|
|
390
389
|
const timeoutMs = options.timeoutMs ?? (current.loaded ? BACKGROUND_REFRESH_TIMEOUT_MS : undefined);
|
|
391
|
-
inFlightRefresh = refreshModelCatalog({ ...options, ...(timeoutMs !== undefined ? { timeoutMs } : {}) }).finally(
|
|
392
|
-
|
|
393
|
-
|
|
390
|
+
inFlightRefresh = refreshModelCatalog({ ...options, ...(timeoutMs !== undefined ? { timeoutMs } : {}) }).finally(
|
|
391
|
+
() => {
|
|
392
|
+
inFlightRefresh = null;
|
|
393
|
+
}
|
|
394
|
+
);
|
|
394
395
|
}
|
|
395
396
|
return inFlightRefresh;
|
|
396
397
|
};
|
package/src/models/catalog.ts
CHANGED
|
@@ -5,21 +5,10 @@
|
|
|
5
5
|
* rebuilt in place whenever it changes.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
getActiveCatalog,
|
|
10
|
-
registerCatalogUpdateListener,
|
|
11
|
-
refreshModelCatalog,
|
|
12
|
-
ensureModelCatalogFresh,
|
|
13
|
-
getCatalogStatus,
|
|
14
|
-
setCatalogTTL,
|
|
15
|
-
getCatalogTTL,
|
|
16
|
-
DEFAULT_CATALOG_TTL_MS,
|
|
17
|
-
type CatalogStatus,
|
|
18
|
-
type RefreshCatalogOptions,
|
|
19
|
-
} from "./catalog-cache.ts";
|
|
8
|
+
import { getActiveCatalog, registerCatalogUpdateListener } from "./catalog-cache.ts";
|
|
20
9
|
import type { ModelSpec, ProviderId, ModelLimit, ModelCost, ModelModalities } from "../types/model.ts";
|
|
21
10
|
import type { ThinkingLevel } from "../types/core.ts";
|
|
22
|
-
import { ConfigError } from "../types/errors.ts";
|
|
11
|
+
import { ConfigError, ValidationError } from "../types/errors.ts";
|
|
23
12
|
|
|
24
13
|
// ---------------------------------------------------------------------------
|
|
25
14
|
// Provider aliases — maps our internal ids to models.dev keys
|
|
@@ -49,8 +38,8 @@ function applyModalityOverrides(provider: string, modelId: string, base: ModelMo
|
|
|
49
38
|
MODALITY_OVERRIDES[`${provider}/${normalizeModelIdForLookup(modelId)}`];
|
|
50
39
|
if (!hit) return base;
|
|
51
40
|
return {
|
|
52
|
-
input: (
|
|
53
|
-
output: (
|
|
41
|
+
input: (hit.input ?? base.input) as ModelModalities["input"],
|
|
42
|
+
output: (hit.output ?? base.output) as ModelModalities["output"],
|
|
54
43
|
};
|
|
55
44
|
}
|
|
56
45
|
|
|
@@ -107,7 +96,7 @@ function customRegistryKey(provider: string, modelId: string): string {
|
|
|
107
96
|
*/
|
|
108
97
|
export function registerModel(spec: ModelSpec): void {
|
|
109
98
|
if (!spec || typeof spec.id !== "string" || typeof spec.provider !== "string") {
|
|
110
|
-
throw new
|
|
99
|
+
throw new ValidationError("[Agent Accelerator] registerModel requires spec.id and spec.provider strings");
|
|
111
100
|
}
|
|
112
101
|
customModelRegistry.set(customRegistryKey(String(spec.provider), String(spec.id)), { ...spec });
|
|
113
102
|
// Invalidate derived caches so the custom model is visible immediately.
|
|
@@ -136,30 +125,38 @@ export function getModelSource(provider: string, modelId: string): "catalog" | "
|
|
|
136
125
|
if (customModelRegistry.has(customRegistryKey(p, m)) || customModelRegistry.has(customRegistryKey(p, norm))) {
|
|
137
126
|
return "override";
|
|
138
127
|
}
|
|
139
|
-
if (
|
|
140
|
-
MODALITY_OVERRIDES[`${p}/${m}`] !== undefined ||
|
|
141
|
-
MODALITY_OVERRIDES[`${p}/${norm}`] !== undefined
|
|
142
|
-
) {
|
|
128
|
+
if (MODALITY_OVERRIDES[`${p}/${m}`] !== undefined || MODALITY_OVERRIDES[`${p}/${norm}`] !== undefined) {
|
|
143
129
|
return "override";
|
|
144
130
|
}
|
|
145
131
|
return getModelFromCatalog(provider, modelId) ? "catalog" : "unknown";
|
|
146
132
|
}
|
|
147
133
|
|
|
148
134
|
// Derives capability flags (thinking, caching, tools, structured output, modalities) from a raw catalog entry; in: mapModelSpec, out: ModelCapabilities.
|
|
149
|
-
function mapCapabilities(
|
|
135
|
+
function mapCapabilities(
|
|
136
|
+
raw: any,
|
|
137
|
+
cost: ModelCost,
|
|
138
|
+
reasoning: boolean,
|
|
139
|
+
toolCall: boolean,
|
|
140
|
+
modalities: ModelModalities
|
|
141
|
+
) {
|
|
150
142
|
return {
|
|
151
143
|
supportsThinking: reasoning,
|
|
152
144
|
supportsThinkingLevel: !!raw.reasoning_options,
|
|
153
|
-
supportsThinkingBudget:
|
|
145
|
+
supportsThinkingBudget:
|
|
146
|
+
Array.isArray(raw.reasoning_options) && raw.reasoning_options.some((o: any) => o.type === "budget_tokens"),
|
|
154
147
|
supportsImplicitCaching: cost.cache_read !== undefined || cost.cache_write !== undefined,
|
|
155
148
|
supportsLongCacheRetention: cost.cache_read !== undefined,
|
|
156
149
|
supportsExplicitCaching: cost.cache_read !== undefined,
|
|
157
150
|
supportsParallelToolCalls: toolCall,
|
|
158
151
|
supportsStreaming: true,
|
|
159
152
|
supportsStructuredOutput: raw.structured_output === undefined ? true : !!raw.structured_output,
|
|
160
|
-
supportsReasoningToggle:
|
|
161
|
-
|
|
162
|
-
|
|
153
|
+
supportsReasoningToggle:
|
|
154
|
+
Array.isArray(raw.reasoning_options) && raw.reasoning_options.some((o: any) => o.type === "toggle"),
|
|
155
|
+
supportsReasoningEffort:
|
|
156
|
+
Array.isArray(raw.reasoning_options) && raw.reasoning_options.some((o: any) => o.type === "effort"),
|
|
157
|
+
modalities: [...(modalities.input || []), ...(modalities.output || [])].filter(
|
|
158
|
+
(v: any, i: any, a: any) => a.indexOf(v) === i
|
|
159
|
+
),
|
|
163
160
|
};
|
|
164
161
|
}
|
|
165
162
|
|
|
@@ -268,7 +265,9 @@ export function getModelFromCatalog(providerInput: string, modelIdInput: string)
|
|
|
268
265
|
}
|
|
269
266
|
|
|
270
267
|
const aliasProviders = PROVIDER_ALIASES[provider] || [provider];
|
|
271
|
-
const tryProviders = [
|
|
268
|
+
const tryProviders = [
|
|
269
|
+
...new Set([...aliasProviders, provider, provider.replace("-zen", ""), provider.replace("-go", "")]),
|
|
270
|
+
];
|
|
272
271
|
const catalog = getActiveCatalog();
|
|
273
272
|
|
|
274
273
|
for (const p of tryProviders) {
|
|
@@ -292,7 +291,11 @@ export function getModelFromCatalog(providerInput: string, modelIdInput: string)
|
|
|
292
291
|
// or normalized equality. The old loose `modelId.endsWith(key)` is removed
|
|
293
292
|
// (e.g. "gpt-4o-mini-extra" must not match "mini").
|
|
294
293
|
for (const [key, raw] of Object.entries(providerData.models as Record<string, any>)) {
|
|
295
|
-
if (
|
|
294
|
+
if (
|
|
295
|
+
key === modelId ||
|
|
296
|
+
key.endsWith(`/${modelId}`) ||
|
|
297
|
+
normalizeModelIdForLookup(key) === normalizeModelIdForLookup(modelId)
|
|
298
|
+
) {
|
|
296
299
|
result = mapModelSpec(p as ProviderId, key, raw as any);
|
|
297
300
|
setLookupCache(cacheKey, result);
|
|
298
301
|
return result;
|
|
@@ -411,7 +414,8 @@ export function getModelThinkingInfo(provider: string, modelId: string): ModelTh
|
|
|
411
414
|
allowed.add("dynamic");
|
|
412
415
|
|
|
413
416
|
const allowedLevels = Array.from(allowed);
|
|
414
|
-
const supportsDisable =
|
|
417
|
+
const supportsDisable =
|
|
418
|
+
allowed.has("none") || !!toggleOpt || Boolean(budgetOpt && (budgetOpt.min === undefined || budgetOpt.min <= 0));
|
|
415
419
|
|
|
416
420
|
return {
|
|
417
421
|
supportsThinking: true,
|
|
@@ -444,7 +448,8 @@ export class ThinkingLevelError extends ConfigError {
|
|
|
444
448
|
reason: string;
|
|
445
449
|
remedy?: string;
|
|
446
450
|
}) {
|
|
447
|
-
const allowed =
|
|
451
|
+
const allowed =
|
|
452
|
+
opts.allowedLevels.length > 0 ? ` Allowed levels: ${opts.allowedLevels.map((l) => `"${l}"`).join(", ")}.` : "";
|
|
448
453
|
const remedy = opts.remedy ? ` How to fix: ${opts.remedy}` : "";
|
|
449
454
|
super(
|
|
450
455
|
`[Agent Accelerator] Thinking level "${opts.requestedLevel}" does not fit "${opts.provider}/${opts.modelId}": ${opts.reason}${allowed}${remedy}`,
|
|
@@ -464,7 +469,11 @@ export class ThinkingLevelError extends ConfigError {
|
|
|
464
469
|
*
|
|
465
470
|
* @example `validateModelThinking("google", "gemini-3.5-flash-lite", "medium");`
|
|
466
471
|
*/
|
|
467
|
-
export function validateModelThinking(
|
|
472
|
+
export function validateModelThinking(
|
|
473
|
+
provider: string,
|
|
474
|
+
modelId: string,
|
|
475
|
+
requestedLevel?: ThinkingLevel | string
|
|
476
|
+
): void {
|
|
468
477
|
if (!requestedLevel) return;
|
|
469
478
|
const level = String(requestedLevel).toLowerCase().trim();
|
|
470
479
|
const info = getModelThinkingInfo(provider, modelId);
|
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All HTTP and wire parsing. Canonical mappers (thinking, cache, tool choice, structured output) live in `../providers.ts`, never here.
|
|
4
4
|
|
|
5
|
-
| File
|
|
6
|
-
|
|
|
7
|
-
| `google.ts`
|
|
8
|
-
| `openai.ts`
|
|
9
|
-
| `openrouter.ts`
|
|
10
|
-
| `openai-compat.ts` | OpenAI-compatible Chat Completions | Serves every custom prefix; strict subset of fields; no default base URL.
|
|
11
|
-
| `registry.ts`
|
|
12
|
-
| `shared.ts`
|
|
5
|
+
| File | Wire | Notes |
|
|
6
|
+
| :----------------- | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
7
|
+
| `google.ts` | Google Interactions | Stateful chaining (TTL gate, self-heal on `not_found`), exact replay of raw `steps`, media consts at the top, Gemini 4 long decode as background interactions. |
|
|
8
|
+
| `openai.ts` | OpenAI Responses | Stateless (`store:false`), full history every turn. |
|
|
9
|
+
| `openrouter.ts` | OpenRouter Chat Completions | Every request streams (so it can be cancelled); `generate()` collects its own stream. |
|
|
10
|
+
| `openai-compat.ts` | OpenAI-compatible Chat Completions | Serves every custom prefix; strict subset of fields; no default base URL. |
|
|
11
|
+
| `registry.ts` | - | Routes `provider/model` to an adapter; the registry is immutable; `ModelProvider` helpers. |
|
|
12
|
+
| `shared.ts` | - | Helpers every adapter uses: signals and timers, error payloads, ids, retry-after, SSE scaffold (`linkStreamAbort`, `withAbortTimer`, `readSseData`, `incompleteStreamCheck`, `failStream`). |
|
|
13
13
|
|
|
14
14
|
## Contract (`Provider`, in `../types/model.ts`)
|
|
15
|
+
|
|
15
16
|
`generate(model, context, options)` returns a `ProviderGenerateResult`; `stream(...)` returns an `AssistantMessageEventStream` that ends with an `AgentResponse`; optional `isLongRunning()` tells the loop to skip its whole-call timeouts.
|
|
16
17
|
|
|
17
18
|
## Invariants
|
|
19
|
+
|
|
18
20
|
- Fix shared streaming behaviour in `shared.ts`, never per adapter. Event parsing and request building stay in each adapter.
|
|
19
21
|
- OpenRouter and compat chat chunk handlers are deliberately not merged.
|
|
20
22
|
- A custom prefix never gets another provider's key or base URL.
|