agent-accelerator 0.5.6 → 0.5.8
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 +10 -17
- package/package.json +1 -1
- package/src/agent/agent.ts +92 -57
- package/src/agent/architecture.md +25 -0
- package/src/agent/context.ts +7 -3
- package/src/agent/delegation.ts +30 -96
- package/src/agent/loop.ts +54 -56
- package/src/agent/subagent.ts +4 -4
- package/src/agent/worker.ts +1 -3
- package/src/architecture.md +28 -0
- package/src/index.ts +13 -80
- package/src/models/architecture.md +14 -0
- package/src/models/catalog-cache.ts +10 -7
- package/src/models/catalog.ts +20 -13
- package/src/providers/architecture.md +24 -0
- package/src/providers/google.ts +24 -4
- package/src/providers/openai-compat.ts +29 -7
- package/src/providers/openai.ts +22 -6
- package/src/providers/openrouter.ts +14 -2
- package/src/providers/registry.ts +1 -0
- package/src/providers/shared.ts +4 -4
- package/src/providers.ts +9 -53
- package/src/scheduler/architecture.md +22 -0
- package/src/scheduler/scheduler.ts +131 -56
- package/src/scheduler/store.ts +274 -54
- package/src/scheduler/time.ts +2 -0
- package/src/session/architecture.md +19 -0
- package/src/session/store.ts +37 -22
- package/src/session/usage.ts +1 -0
- package/src/streaming/architecture.md +13 -0
- package/src/streaming/event-stream.ts +16 -11
- package/src/telemetry-file.ts +74 -24
- package/src/telemetry.ts +3 -2
- package/src/tools/architecture.md +19 -0
- package/src/tools/executor.ts +14 -1
- package/src/tools/schema.ts +1 -0
- package/src/tools/subagent-result.ts +1 -0
- package/src/tools/tool.ts +8 -8
- package/src/types/agent.ts +22 -20
- package/src/types/architecture.md +20 -0
- package/src/types/response.ts +8 -8
- package/src/types/scheduler.ts +2 -2
- package/src/types/tool.ts +5 -5
- package/src/update-models.ts +2 -2
- package/src/utils/architecture.md +25 -0
- package/src/utils/base64.ts +2 -0
- package/src/utils/cache.ts +6 -4
- package/src/utils/durable.ts +78 -3
- package/src/utils/env.ts +1 -1
- package/src/utils/errors.ts +4 -0
- package/src/utils/headers.ts +7 -4
- package/src/utils/home.ts +1 -1
- package/src/utils/media.ts +1 -0
- package/src/utils/raw-capture.ts +3 -0
- package/src/utils/retry.ts +2 -1
- package/src/utils/safe-io.ts +4 -0
- package/src/utils/session.ts +10 -166
package/src/providers.ts
CHANGED
|
@@ -42,6 +42,7 @@ export type ProviderCapabilityStatus =
|
|
|
42
42
|
*/
|
|
43
43
|
const emittedWarnings = new Set<string>();
|
|
44
44
|
|
|
45
|
+
/** Warns once per provider, capability and request about something that cannot be applied as asked: a `provider_warning` bus event, the legacy global sink and console; in: the mappers and adapters, out: those channels. */
|
|
45
46
|
export function emitProviderWarning(options: {
|
|
46
47
|
provider: string;
|
|
47
48
|
capability: string;
|
|
@@ -190,40 +191,6 @@ export function mapThinkingLevelToOpenRouterChat(
|
|
|
190
191
|
return {};
|
|
191
192
|
}
|
|
192
193
|
|
|
193
|
-
/**
|
|
194
|
-
* Maps a canonical ThinkingLevel onto OpenRouter Responses `reasoning.effort`.
|
|
195
|
-
* Documented efforts: minimal|low|medium|high (server default medium).
|
|
196
|
-
* Wire-validated extras: `none` disables reasoning output; `xhigh`/`max` are
|
|
197
|
-
* echoed but are NOT documented levels, so they clamp to `high` with a warning.
|
|
198
|
-
*
|
|
199
|
-
* @deprecated The Responses skin is discontinued for OpenRouter
|
|
200
|
-
* (removed from core). Use
|
|
201
|
-
* {@link mapThinkingLevelToOpenRouterChat} with the stable Chat Completions
|
|
202
|
-
* transport instead.
|
|
203
|
-
*/
|
|
204
|
-
export function mapThinkingLevelToOpenRouter(
|
|
205
|
-
level: ThinkingLevel | string | undefined
|
|
206
|
-
): { effort?: string } {
|
|
207
|
-
if (!level) return {};
|
|
208
|
-
const norm = String(level).toLowerCase().trim();
|
|
209
|
-
if (norm === "dynamic") return {}; // server default (medium)
|
|
210
|
-
if (norm === "none") return { effort: "none" };
|
|
211
|
-
if (norm === "xhigh" || norm === "max") {
|
|
212
|
-
emitProviderWarning({
|
|
213
|
-
provider: "openrouter",
|
|
214
|
-
capability: "thinking level",
|
|
215
|
-
requested: String(level),
|
|
216
|
-
reason: "OpenRouter documents reasoning efforts up to high.",
|
|
217
|
-
fallback: "reasoning effort high",
|
|
218
|
-
});
|
|
219
|
-
return { effort: "high" };
|
|
220
|
-
}
|
|
221
|
-
if (norm === "minimal" || norm === "low" || norm === "medium" || norm === "high") {
|
|
222
|
-
return { effort: norm };
|
|
223
|
-
}
|
|
224
|
-
return {};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
194
|
/** Maps canonical ServiceTier onto OpenRouter `service_tier` (omit = auto). */
|
|
228
195
|
export function mapServiceTierToOpenRouter(tier: ServiceTier | undefined): "flex" | "priority" | undefined {
|
|
229
196
|
if (tier === "flex" || tier === "priority") return tier;
|
|
@@ -287,25 +254,6 @@ export function mapToolChoiceToOpenRouterChat(
|
|
|
287
254
|
return undefined;
|
|
288
255
|
}
|
|
289
256
|
|
|
290
|
-
/** OpenRouter Responses `tool_choice` wire values.
|
|
291
|
-
* @deprecated Discontinued skin; see {@link OpenRouterChatToolChoice}. */
|
|
292
|
-
export type OpenRouterToolChoice = "auto" | "none" | "required" | { type: "function"; name: string };
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Maps canonical toolChoice onto OpenRouter Responses `tool_choice`.
|
|
296
|
-
* `auto` is the server default (omitted); `required` is natively supported
|
|
297
|
-
* (validated); a function pin passes through verbatim.
|
|
298
|
-
*/
|
|
299
|
-
export function mapToolChoiceToOpenRouter(
|
|
300
|
-
choice: "auto" | "none" | "required" | { type: "function"; function: { name: string } } | undefined
|
|
301
|
-
): OpenRouterToolChoice | undefined {
|
|
302
|
-
if (!choice || choice === "auto") return undefined;
|
|
303
|
-
if (choice === "none" || choice === "required") return choice;
|
|
304
|
-
const name = choice.function?.name;
|
|
305
|
-
if (name) return { type: "function", name };
|
|
306
|
-
return undefined;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
257
|
/**
|
|
310
258
|
* Maps a canonical ThinkingLevel onto OpenAI Responses `reasoning.effort`.
|
|
311
259
|
* Documented efforts: none|minimal|low|medium|high|xhigh|max (server default
|
|
@@ -383,6 +331,7 @@ export function normalizeToolChoice(
|
|
|
383
331
|
return { mode: "any" };
|
|
384
332
|
}
|
|
385
333
|
|
|
334
|
+
// True for a non-array object; in: the argument and schema helpers, out: a type guard.
|
|
386
335
|
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
387
336
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
388
337
|
}
|
|
@@ -449,6 +398,7 @@ export interface GenerationParams {
|
|
|
449
398
|
|
|
450
399
|
/** Most stop sequences a Chat Completions request may carry (OpenRouter chat-completion api-ref `maxItems`, OpenAI the same). */
|
|
451
400
|
const MAX_CHAT_STOP = 4;
|
|
401
|
+
// True for a finite number; in: the generation-param mappers, out: a type guard.
|
|
452
402
|
const finiteNumber = (v: unknown): v is number => typeof v === "number" && Number.isFinite(v);
|
|
453
403
|
|
|
454
404
|
/** Normalizes the public `stop` option (`string | string[]`) to a clean array, or undefined. */
|
|
@@ -484,6 +434,7 @@ export function mapGenerationParamsToChat(params: GenerationParams | undefined,
|
|
|
484
434
|
return out;
|
|
485
435
|
}
|
|
486
436
|
|
|
437
|
+
// Warns that `stop`/`seed` have no parameter on this wire and are dropped; in: the OpenAI and Google mappers, out: provider_warning events.
|
|
487
438
|
function warnUnsupportedStopSeed(provider: string, modelRef: string, params: GenerationParams, reasonSuffix: string): void {
|
|
488
439
|
if (params.stop && params.stop.length > 0) {
|
|
489
440
|
emitProviderWarning({
|
|
@@ -533,6 +484,7 @@ export function mapGenerationParamsToGoogle(
|
|
|
533
484
|
// Structured outputs (canonical, pure, no I/O)
|
|
534
485
|
// ---------------------------------------------------------------------------
|
|
535
486
|
|
|
487
|
+
// True when a value looks like a Zod schema (parse/safeParse/_def/~standard); in: structured-output normalization, out: a boolean.
|
|
536
488
|
function isZodLike(value: unknown): boolean {
|
|
537
489
|
if (!value || typeof value !== "object") return false;
|
|
538
490
|
const v = value as Record<string, unknown>;
|
|
@@ -544,6 +496,7 @@ function isZodLike(value: unknown): boolean {
|
|
|
544
496
|
);
|
|
545
497
|
}
|
|
546
498
|
|
|
499
|
+
// True when a plain object has JSON Schema keywords; in: structured-output normalization, out: a boolean.
|
|
547
500
|
function looksLikeJsonSchema(value: unknown): boolean {
|
|
548
501
|
if (!isPlainObject(value)) return false;
|
|
549
502
|
const v = value as Record<string, unknown>;
|
|
@@ -559,12 +512,14 @@ function looksLikeJsonSchema(value: unknown): boolean {
|
|
|
559
512
|
);
|
|
560
513
|
}
|
|
561
514
|
|
|
515
|
+
// A structured-output name limited to letters, digits, `_` and `-` (64 chars), default `structured_output`; in: normalizeStructuredOutput, out: the name.
|
|
562
516
|
function sanitizeOutputName(raw: unknown): string {
|
|
563
517
|
const base = typeof raw === "string" && raw.trim() ? raw.trim() : "structured_output";
|
|
564
518
|
const cleaned = base.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64) || "structured_output";
|
|
565
519
|
return cleaned;
|
|
566
520
|
}
|
|
567
521
|
|
|
522
|
+
// A Zod schema or JSON Schema object as a JSON Schema object, else a ValidationError; in: normalizeStructuredOutput, out: the schema.
|
|
568
523
|
function schemaToJsonSchema(schema: unknown, what: string): Record<string, unknown> {
|
|
569
524
|
if (isZodLike(schema)) {
|
|
570
525
|
try {
|
|
@@ -634,6 +589,7 @@ export function extractOutputValidator(output: unknown): { safeParse: (v: unknow
|
|
|
634
589
|
return undefined;
|
|
635
590
|
}
|
|
636
591
|
|
|
592
|
+
// Removes a surrounding ```json fence from a model answer; in: parseStructuredOutput, out: the bare text.
|
|
637
593
|
function stripCodeFences(text: string): string {
|
|
638
594
|
const trimmed = text.trim();
|
|
639
595
|
const fenced = trimmed.match(/^```(?:json)?\s*\n([\s\S]*?)\n```\s*$/i);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# src/scheduler/
|
|
2
|
+
|
|
3
|
+
Scheduled actions: a worker that runs later (once or repeating) and saves its answer to a file. Off unless `dynamicSubagents.allowScheduledActions` is set.
|
|
4
|
+
|
|
5
|
+
| File | What it is |
|
|
6
|
+
| :-- | :-- |
|
|
7
|
+
| `scheduler.ts` | One `Scheduler` per home folder: a 1 s unref'd clock that runs only while something is pending, startup sweep, cook/deliver state machine, and the public functions (`createScheduledAction`, `list/update/run/skip/deleteScheduledAction`). |
|
|
8
|
+
| `store.ts` | Disk layer under `<home>/scheduled/`: `<id>/task.json`, `<id>/delivery.json`, run files, one short mutex per action; validation of records. |
|
|
9
|
+
| `time.ts` | Pure `DD:HH:MM` and local-clock maths. No timezone, DST or `Intl`; `now` is always passed in. |
|
|
10
|
+
| `tool.ts` + `scheduled-actions.md` | The model-facing `scheduled_actions` tool and `get_datetime`; the `.md` is the tool description. |
|
|
11
|
+
|
|
12
|
+
## Invariants
|
|
13
|
+
- The files are the truth: every write re-reads first and goes through the durable writer. The file format is a stable public contract: see `docs/scheduled-action-files.md` and add a changelog row for any change.
|
|
14
|
+
- Write order when a run ends: run file, then `<id>/delivery.json`, then `<id>/task.json`. The startup sweep repairs a crash in between.
|
|
15
|
+
- `startCook` advances the next times BEFORE the run starts; a run still cooking when the next is due is skipped, never stacked.
|
|
16
|
+
- Runs are fresh stateless workers built by `buildDynamicWorkerConfig`; their spending guardrail is `workerBudget` only.
|
|
17
|
+
- The Agent registry holds `WeakRef`s by name: keep every Agent that owns actions referenced, or its runs become `missed`.
|
|
18
|
+
- Several processes may share a home (the file store is safe for it; the home lock is lifted in a later change of this release). Ownership: a process only starts, delivers or recovers actions whose Agent it registered. An action nobody here owns is left alone until its delivery time passed with no run started, then marked `missed` (`no_agent`).
|
|
19
|
+
- Exactly once: a scheduled start re-checks under the action's mutex that it is still `waiting` and due; `markMissed` only changes the state the caller saw; a delivery is emitted only by the process that removed its entry from `delivery.json`.
|
|
20
|
+
- A run in flight keeps `<id>/.heartbeat` (pid, host, token; mtime refreshed every 5 s, stale after 60 s), written before the record shows `cooking`. A cooking action whose owner is dead (pid gone, stale, or none) is recovered by a live process that owns its Agent, at start and every 15 s. `delete` of a run another live process is cooking is refused, even with `force`.
|
|
21
|
+
- Times come from `Date`, local clock only. Tests inject `scheduler.now` / `tickMs` and call `tick()`.
|
|
22
|
+
- Events: `scheduled_action.{created,updated,started,ready,failed,delivered,missed,skipped,deleted,invalid,store_corrupt,error}`.
|