@arnilo/prism 0.0.3 → 0.0.5
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/CHANGELOG.md +40 -0
- package/README.md +62 -26
- package/dist/agent-loops.d.ts +8 -1
- package/dist/agent-loops.js +57 -11
- package/dist/agents.js +212 -32
- package/dist/checkpoints.d.ts +11 -0
- package/dist/checkpoints.js +144 -0
- package/dist/cli-init.d.ts +41 -0
- package/dist/cli-init.js +390 -0
- package/dist/cli-runner.d.ts +7 -1
- package/dist/cli-runner.js +13 -1
- package/dist/compaction.js +9 -1
- package/dist/content.d.ts +121 -0
- package/dist/content.js +538 -0
- package/dist/contracts.d.ts +236 -11
- package/dist/contracts.js +8 -0
- package/dist/event-multiplexer.d.ts +23 -0
- package/dist/event-multiplexer.js +136 -0
- package/dist/execution-policy.d.ts +28 -0
- package/dist/execution-policy.js +24 -0
- package/dist/feedback.d.ts +48 -0
- package/dist/feedback.js +230 -0
- package/dist/index.d.ts +20 -6
- package/dist/index.js +13 -5
- package/dist/input.js +11 -1
- package/dist/leases.d.ts +8 -0
- package/dist/leases.js +111 -0
- package/dist/node/agent-definitions.js +3 -5
- package/dist/node/config.d.ts +1 -0
- package/dist/node/config.js +5 -3
- package/dist/node/contribution-discovery.js +5 -8
- package/dist/node/session-store-jsonl.js +8 -5
- package/dist/node/settings.js +2 -2
- package/dist/node/trust.js +2 -4
- package/dist/observability.d.ts +3 -0
- package/dist/observability.js +18 -0
- package/dist/providers/media.d.ts +44 -0
- package/dist/providers/media.js +126 -0
- package/dist/providers/openai-compatible.js +18 -119
- package/dist/providers/openai-primitives.d.ts +9 -0
- package/dist/providers/openai-primitives.js +129 -0
- package/dist/providers/transport.d.ts +40 -0
- package/dist/providers/transport.js +221 -0
- package/dist/redaction.js +40 -13
- package/dist/resources.d.ts +5 -0
- package/dist/resources.js +4 -0
- package/dist/structured-output.d.ts +11 -0
- package/dist/structured-output.js +59 -0
- package/dist/testing/feedback.d.ts +6 -0
- package/dist/testing/feedback.js +37 -0
- package/dist/testing/persistence-schema.d.ts +102 -0
- package/dist/testing/persistence-schema.js +487 -0
- package/dist/testing/provider-conformance.js +10 -1
- package/dist/testing/run-ledger-conformance.d.ts +33 -0
- package/dist/testing/run-ledger-conformance.js +178 -0
- package/dist/testing/session-store-conformance.d.ts +16 -0
- package/dist/testing/session-store-conformance.js +73 -0
- package/dist/tools.d.ts +17 -0
- package/dist/tools.js +29 -2
- package/docs/a2a.md +73 -0
- package/docs/agent-events.md +17 -10
- package/docs/agent-loops.md +11 -5
- package/docs/agent-session-runtime.md +15 -16
- package/docs/cli-rpc.md +36 -5
- package/docs/coding-agent-tools.md +43 -9
- package/docs/coding-security.md +88 -0
- package/docs/compaction-observational-memory.md +2 -0
- package/docs/context-and-skills.md +1 -0
- package/docs/credential-storage.md +177 -0
- package/docs/credentials-and-redaction.md +4 -3
- package/docs/database-persistence.md +52 -7
- package/docs/evaluations.md +122 -0
- package/docs/extensions.md +2 -2
- package/docs/host-security.md +33 -2
- package/docs/index.md +46 -18
- package/docs/input-and-prompt-assembly.md +6 -5
- package/docs/mcp-tools.md +184 -0
- package/docs/middleware-hooks.md +2 -0
- package/docs/migration.md +51 -28
- package/docs/model-registry.md +5 -3
- package/docs/multimodal-content.md +156 -0
- package/docs/observability.md +171 -0
- package/docs/performance.md +249 -1
- package/docs/persistence-credentials-multimodality-primitives.md +303 -0
- package/docs/postgres-persistence.md +143 -0
- package/docs/provider-conformance.md +18 -0
- package/docs/provider-layer.md +1 -1
- package/docs/provider-packages.md +2 -0
- package/docs/provider-primitives.md +281 -0
- package/docs/providers/ai-sdk.md +113 -0
- package/docs/providers/kimi.md +1 -0
- package/docs/providers/neuralwatt.md +1 -0
- package/docs/providers/openai-compatible.md +2 -1
- package/docs/providers/openai.md +8 -1
- package/docs/providers/opencode-go.md +1 -0
- package/docs/providers/openrouter.md +1 -0
- package/docs/providers/zai.md +1 -0
- package/docs/public-contracts.md +13 -5
- package/docs/rag.md +113 -0
- package/docs/release-and-install.md +237 -30
- package/docs/resource-loading.md +14 -4
- package/docs/review-coverage-2026-07-14.md +260 -0
- package/docs/review-coverage-2026-07-15.md +193 -0
- package/docs/run-ledger-conformance.md +96 -0
- package/docs/runs-and-usage.md +43 -4
- package/docs/server.md +139 -0
- package/docs/session-store-conformance.md +16 -0
- package/docs/session-stores-and-branching.md +1 -0
- package/docs/settings-auth-trust-security.md +6 -5
- package/docs/sqlite-persistence.md +123 -0
- package/docs/structured-output.md +9 -0
- package/docs/supervisors.md +71 -0
- package/docs/tool-conformance.md +1 -0
- package/docs/tool-execution-primitives.md +374 -0
- package/docs/tools.md +39 -1
- package/docs/workflow-orchestration-primitives.md +581 -0
- package/docs/workflow-tui-primitives.md +5 -0
- package/docs/workflows.md +293 -0
- package/docs/working-and-semantic-memory.md +169 -0
- package/package.json +43 -5
- package/templates/init/README.md.tmpl +28 -0
- package/templates/init/env.example.tmpl +1 -0
- package/templates/init/gitignore.tmpl +11 -0
- package/templates/init/optional/evals-example.ts.tmpl +17 -0
- package/templates/init/optional/workflows-example.ts.tmpl +27 -0
- package/templates/init/package.json.tmpl +22 -0
- package/templates/init/providers.json +76 -0
- package/templates/init/src/agent.ts.tmpl +10 -0
- package/templates/init/src/index.ts.tmpl +12 -0
- package/templates/init/src/tests/agent.test.ts.tmpl +24 -0
- package/templates/init/tsconfig.json.tmpl +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.0.5] - 2026-07-16
|
|
11
|
+
|
|
12
|
+
- `@arnilo/prism-providers` now installs all seven first-party adapters including AI SDK interoperability; `@arnilo/prism-all` now installs every first-party package while activating none automatically.
|
|
13
|
+
|
|
14
|
+
- Added optional `@arnilo/prism-supervisor` with bounded explicit child delegation, derived memory scope IDs, narrowing-only permissions, A2A 1.0 cards/ES256 signatures, authorized JSON-RPC/SSE serving, and an exact-origin remote client.
|
|
15
|
+
|
|
16
|
+
- Added bounded immutable run/trace feedback with exact ownership, evaluation linkage, memory/SQLite/PostgreSQL stores, schema migration 003, and safe OpenTelemetry projection.
|
|
17
|
+
|
|
18
|
+
- Phase 11 extends workflows with explicit durable schedules/background execution, nested composition, bounded validated state, immutable-lineage replay, and optional command/Web bindings over existing checkpoint/lease primitives.
|
|
19
|
+
|
|
20
|
+
- Optional `@arnilo/prism-server` package with authorized bounded Web-standard direct/SSE agent and durable workflow routes; `@arnilo/prism-mcp` now supports explicit authorized Prism tool/command server exposure and bounded Web-standard Streamable HTTP handling.
|
|
21
|
+
- Optional `@arnilo/prism-rag` package: bounded deterministic text/Markdown chunking, Phase 7 vector indexing/retrieval, stable citations, metadata filters, redaction, and explicit ContextProvider injection.
|
|
22
|
+
- Workflows now support durable human `suspend()`/approve/deny, expected-version exact-once resume, validated/redacted resume payloads, and opt-in tool approval with execution-policy recheck.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Optional `@arnilo/prism-memory` package: schema/template-backed working memory, semantic recall, package-owned `Embedder`/`VectorStore` contracts, in-memory adapters, context provider, opt-in processor, shared conformance, and PostgreSQL/pgvector production path.
|
|
27
|
+
|
|
28
|
+
## [0.0.4] - 2026-07-14
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Shared bounded provider transport, OpenAI serialization/media helpers, native structured-output contracts, provider/tool timing metadata, and audio/file/document content capability checks.
|
|
33
|
+
- Generic checkpoint, atomic lease, and bounded event-multiplexer contracts plus persistence/run-ledger conformance helpers.
|
|
34
|
+
- Optional packages for JSON Schema tool validation, MCP, coding approval/sandboxing, OpenTelemetry, encrypted/keychain credentials, SQLite/PostgreSQL persistence, and bounded workflow orchestration.
|
|
35
|
+
- Manifest-only `base`, `code`, and `sdk` profiles; `prism-all` now transitively installs every first-party package.
|
|
36
|
+
- Workflow, multimodal, persistence/resume, provider telemetry, cache, and external-adapter examples.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- Single-shot loops support ordered bounded parallel tools; `ToolDefinition.exclusive` serializes dangerous turns without reducing later concurrency.
|
|
41
|
+
- Provider requests, SSE/error bodies, media, schemas, event queues, checkpoints, and workflow fan-out/output use documented finite limits.
|
|
42
|
+
- Session/ledger writes preserve order and redact before persistence; revision-loop transcript ordering and OAuth abort polling are hardened.
|
|
43
|
+
- All first-party providers use shared bounded transport helpers and expose current structured-output, multimodal, caching, reasoning, telemetry, and retry behavior where supported.
|
|
44
|
+
|
|
45
|
+
### Security
|
|
46
|
+
|
|
47
|
+
- Added fail-closed schema/prototype-pollution, SSRF/media, SQL/tenant, path/shell approval, MCP result, credential-envelope, OAuth, redaction, and stale-worker fencing coverage.
|
|
48
|
+
- Optional privileged capabilities remain inactive until hosts explicitly register transports/tools, configure roots/credentials/databases, and approve execution.
|
|
49
|
+
|
|
10
50
|
## [0.0.3] - 2026-07-08
|
|
11
51
|
|
|
12
52
|
### Added
|
package/README.md
CHANGED
|
@@ -17,23 +17,23 @@ packages. Prism defines contracts, not apps.
|
|
|
17
17
|
OpenAI/OpenRouter use best-effort explicit cache hints, NeuralWatt uses
|
|
18
18
|
best-effort implicit prefix caching, and other providers have route/model-specific
|
|
19
19
|
or no cache-control support; see [docs/provider-caching.md](docs/provider-caching.md).
|
|
20
|
-
- **First-party packages**:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`@arnilo/prism-compaction-observational-memory`.
|
|
20
|
+
- **First-party packages**: six provider adapters, two compaction strategies,
|
|
21
|
+
coding tools/security, JSON Schema validation, MCP, workflows, OpenTelemetry,
|
|
22
|
+
encrypted credentials, SQLite/PostgreSQL persistence, and manifest-only install profiles.
|
|
24
23
|
- **Tools, context, skills**: host-owned tool registry with allow/deny filtering
|
|
25
24
|
and dispatch, context providers, and a skill registry with progressive
|
|
26
25
|
disclosure.
|
|
27
26
|
- **Input/prompt/context**: default input and prompt builders, system-prompt
|
|
28
27
|
layering, and provider-input assembly — every stage replaceable.
|
|
29
28
|
- **Sessions and memory**: in-memory and JSONL session stores, branching/fork/
|
|
30
|
-
clone, default and LLM compaction strategies, retry policy,
|
|
31
|
-
observational-memory recall/status/view
|
|
29
|
+
clone, default and LLM compaction strategies, retry policy,
|
|
30
|
+
observational-memory recall/status/view, optional working/semantic memory
|
|
31
|
+
(`@arnilo/prism-memory`), and bounded text/Markdown RAG (`@arnilo/prism-rag`).
|
|
32
32
|
- **Extensions and manifests**: extension kernel + event bus, contribution
|
|
33
33
|
registries, middleware hooks, and data-only package manifests.
|
|
34
34
|
- **Config, settings, security**: layered config merge, settings providers,
|
|
35
35
|
credential resolvers, trust/permission policies, and secret redaction.
|
|
36
|
-
- **CLI/RPC**: `prism --mode print|json|rpc`
|
|
36
|
+
- **CLI/RPC/server**: `prism --mode print|json|rpc`, `prism init`, optional framework-free authorized Web agent/workflow routes, and explicit MCP server exposure.
|
|
37
37
|
|
|
38
38
|
## Install
|
|
39
39
|
|
|
@@ -41,14 +41,18 @@ packages. Prism defines contracts, not apps.
|
|
|
41
41
|
npm install @arnilo/prism
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
First-party
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
First-party code packages are separate imports and require `@arnilo/prism` as
|
|
45
|
+
a non-optional peer. Install atomic packages directly or choose a manifest-only
|
|
46
|
+
family/profile; profiles install packages but expose no alias exports and activate nothing:
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
npm install @arnilo/prism @arnilo/prism-provider-openai
|
|
50
|
-
npm install @arnilo/prism
|
|
51
|
-
npm install @arnilo/prism-
|
|
49
|
+
npm install @arnilo/prism @arnilo/prism-provider-openai # core + one provider
|
|
50
|
+
npm install @arnilo/prism-base # core + compaction + validation
|
|
51
|
+
npm install @arnilo/prism-code @arnilo/prism-provider-openai # coding-agent profile
|
|
52
|
+
npm install @arnilo/prism-sdk @arnilo/prism-provider-openai # application profile
|
|
53
|
+
npm install @arnilo/prism-all # every first-party package
|
|
54
|
+
npm install @arnilo/prism-server @arnilo/prism-workflows # optional Web API boundary
|
|
55
|
+
npm install @arnilo/prism-supervisor # optional local delegation + A2A 1.0
|
|
52
56
|
```
|
|
53
57
|
|
|
54
58
|
See [docs/release-and-install.md](docs/release-and-install.md) for install
|
|
@@ -56,6 +60,17 @@ specifiers, tarball contents, and the offline test budget.
|
|
|
56
60
|
|
|
57
61
|
## Quick start
|
|
58
62
|
|
|
63
|
+
Scaffold a tiny project (offline mock test included):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx --package @arnilo/prism prism init my-agent
|
|
67
|
+
# or, with a real provider package selected:
|
|
68
|
+
npx --package @arnilo/prism prism init my-agent --provider openai
|
|
69
|
+
cd my-agent && npm install && npm test
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or embed Prism directly:
|
|
73
|
+
|
|
59
74
|
```ts
|
|
60
75
|
import { createAgent, createAgentSession, createMockProvider } from "@arnilo/prism";
|
|
61
76
|
|
|
@@ -67,9 +82,18 @@ const agent = createAgent({
|
|
|
67
82
|
|
|
68
83
|
const session = createAgentSession({ agent });
|
|
69
84
|
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
// Direct result: run/prompt return AgentRunResult (text, usage, status, ids).
|
|
86
|
+
const result = await session.run("Hi");
|
|
87
|
+
console.log(result.text, result.usage?.totalTokens);
|
|
88
|
+
|
|
89
|
+
// Integrated streaming: subscribe-before-run for one owned run.
|
|
90
|
+
for await (const event of session.stream("Hi again")) {
|
|
91
|
+
// AgentEvent: agent_started, message_delta, turn_finished, ...
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Long-lived subscribe() still works when you need a subscriber across runs.
|
|
95
|
+
// `subscribe()` only emits while a run is in progress, so the loop and `run()`
|
|
96
|
+
// must run together; awaiting the loop before calling `run()` would deadlock.
|
|
73
97
|
(async () => {
|
|
74
98
|
const consumer = (async () => {
|
|
75
99
|
for await (const event of session.subscribe()) {
|
|
@@ -111,8 +135,8 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
|
|
|
111
135
|
|
|
112
136
|
- [docs/index.md](docs/index.md) — navigational map of every public surface.
|
|
113
137
|
- The `examples/` directory holds compile-checked typed examples and runnable
|
|
114
|
-
|
|
115
|
-
|
|
138
|
+
offline demos covering providers, auth, tools, stores, compaction, structured
|
|
139
|
+
output, multimodality, workflows, CLI, and RPC.
|
|
116
140
|
|
|
117
141
|
## Packages
|
|
118
142
|
|
|
@@ -127,9 +151,22 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
|
|
|
127
151
|
| `@arnilo/prism-provider-neuralwatt` | NeuralWatt provider with implicit vLLM prefix caching |
|
|
128
152
|
| `@arnilo/prism-compaction-llm` | provider-backed compaction strategy |
|
|
129
153
|
| `@arnilo/prism-compaction-observational-memory` | source-backed memory + recall tool |
|
|
130
|
-
| `@arnilo/prism-
|
|
131
|
-
| `@arnilo/prism-
|
|
132
|
-
| `@arnilo/prism-
|
|
154
|
+
| `@arnilo/prism-coding-agent` | bounded shell/read/write/edit tools |
|
|
155
|
+
| `@arnilo/prism-coding-security` | coding approval, containment, and sandbox adapters |
|
|
156
|
+
| `@arnilo/prism-tool-validator-json-schema` | bounded JSON Schema tool validation |
|
|
157
|
+
| `@arnilo/prism-mcp` | MCP client/tool bridge |
|
|
158
|
+
| `@arnilo/prism-workflows` | bounded DAG workflows, durable suspend/resume, schedules/background runs, composition/state/replay, and multi-process coordination |
|
|
159
|
+
| `@arnilo/prism-supervisor` | bounded local child delegation and A2A 1.0 interoperability |
|
|
160
|
+
| `@arnilo/prism-observability-opentelemetry` | optional OpenTelemetry adapter |
|
|
161
|
+
| `@arnilo/prism-credentials-node` | encrypted-file and keychain credentials |
|
|
162
|
+
| `@arnilo/prism-session-store-sqlite` | SQLite persistence/checkpoints/leases/owned run feedback |
|
|
163
|
+
| `@arnilo/prism-session-store-postgres` | PostgreSQL persistence/checkpoints/leases/owned run feedback |
|
|
164
|
+
| `@arnilo/prism-providers` | family: all 7 provider adapters, including AI SDK interoperability |
|
|
165
|
+
| `@arnilo/prism-compaction` | family: both compaction strategies |
|
|
166
|
+
| `@arnilo/prism-base` | profile: core + compaction + JSON Schema validation |
|
|
167
|
+
| `@arnilo/prism-code` | profile: base + coding tools/security + MCP |
|
|
168
|
+
| `@arnilo/prism-sdk` | profile: base + workflows + MCP + credentials + OpenTelemetry |
|
|
169
|
+
| `@arnilo/prism-all` | every first-party package, including both persistence adapters |
|
|
133
170
|
|
|
134
171
|
## Scripts
|
|
135
172
|
|
|
@@ -142,8 +179,7 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
|
|
|
142
179
|
|
|
143
180
|
## Non-goals (v1)
|
|
144
181
|
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
- Encrypted/keychain credential storage — host-owned until a real app needs it.
|
|
182
|
+
- Privileged tools, MCP servers, telemetry, credentials, or databases activated by install — hosts explicitly configure and register every capability.
|
|
183
|
+
- Browser automation or interactive terminal UI — CLI/RPC and workflow control APIs only.
|
|
184
|
+
- Provider, credential, extension, or package auto-discovery.
|
|
185
|
+
- Core-owned database drivers, secret persistence, sandbox, or application policy — optional packages implement adapters over host-owned boundaries.
|
package/dist/agent-loops.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentLoopOptions, AgentLoopStrategy, ArtifactParser, ArtifactRepairer, ArtifactValidator } from "./contracts.js";
|
|
1
|
+
import type { AgentLoopOptions, AgentLoopStrategy, ArtifactParser, ArtifactRepairer, ArtifactValidator, LoopContext, ToolCallContent } from "./contracts.js";
|
|
2
2
|
export declare const singleShotLoop: AgentLoopStrategy;
|
|
3
3
|
export declare function isAgentLoopOptions(value: AgentLoopStrategy | AgentLoopOptions | undefined): value is AgentLoopOptions;
|
|
4
4
|
export declare function generateValidateReviseLoop(opts: {
|
|
@@ -7,6 +7,13 @@ export declare function generateValidateReviseLoop(opts: {
|
|
|
7
7
|
readonly repairer?: ArtifactRepairer<unknown>;
|
|
8
8
|
readonly maxRevisions?: number;
|
|
9
9
|
}): AgentLoopStrategy;
|
|
10
|
+
export declare function resolveToolConcurrency(options: {
|
|
11
|
+
loop?: AgentLoopStrategy | AgentLoopOptions;
|
|
12
|
+
}, config: {
|
|
13
|
+
loop?: AgentLoopStrategy | AgentLoopOptions;
|
|
14
|
+
}): number;
|
|
15
|
+
/** Dispatch tool calls with bounded concurrency; append transcript rows in call order. */
|
|
16
|
+
export declare function dispatchToolCallsInOrder(calls: readonly ToolCallContent[], ctx: LoopContext): Promise<void>;
|
|
10
17
|
export declare function resolveLoop(options: {
|
|
11
18
|
loop?: AgentLoopStrategy | AgentLoopOptions;
|
|
12
19
|
}, config: {
|
package/dist/agent-loops.js
CHANGED
|
@@ -18,13 +18,12 @@ export const singleShotLoop = {
|
|
|
18
18
|
name: "single-shot",
|
|
19
19
|
async run(ctx) {
|
|
20
20
|
let usage;
|
|
21
|
-
const toolResults = [];
|
|
22
21
|
let toolRounds = 0;
|
|
23
22
|
let nextInput = ctx.input;
|
|
24
23
|
for (let turn = 1;; turn += 1) {
|
|
25
24
|
throwIfAborted(ctx.signal);
|
|
26
25
|
ctx.emit({ type: "turn_started", sessionId: ctx.sessionId, runId: ctx.runId, turn });
|
|
27
|
-
const request = await ctx.assemble(nextInput,
|
|
26
|
+
const request = await ctx.assemble(nextInput, undefined, turn);
|
|
28
27
|
throwIfAborted(ctx.signal);
|
|
29
28
|
const { content, calls, messageId, started, usage: turnUsage } = await ctx.generate(request);
|
|
30
29
|
usage = turnUsage ?? usage;
|
|
@@ -40,12 +39,7 @@ export const singleShotLoop = {
|
|
|
40
39
|
if (calls.length === 0 || toolRounds >= ctx.maxToolRounds)
|
|
41
40
|
break;
|
|
42
41
|
toolRounds += 1;
|
|
43
|
-
|
|
44
|
-
const result = await ctx.dispatchToolCall(call);
|
|
45
|
-
toolResults.push(result);
|
|
46
|
-
await ctx.appendMessage(toolResultMessage(result));
|
|
47
|
-
throwIfAborted(ctx.signal);
|
|
48
|
-
}
|
|
42
|
+
await dispatchToolCallsInOrder(calls, ctx);
|
|
49
43
|
nextInput = [];
|
|
50
44
|
}
|
|
51
45
|
return usage;
|
|
@@ -73,6 +67,7 @@ export function generateValidateReviseLoop(opts) {
|
|
|
73
67
|
async run(ctx) {
|
|
74
68
|
let usage;
|
|
75
69
|
let nextInput = ctx.input;
|
|
70
|
+
let pendingHistory = [];
|
|
76
71
|
for (let turn = 1; turn <= max + 1; turn += 1) {
|
|
77
72
|
throwIfAborted(ctx.signal);
|
|
78
73
|
ctx.emit({ type: "turn_started", sessionId: ctx.sessionId, runId: ctx.runId, turn });
|
|
@@ -80,6 +75,10 @@ export function generateValidateReviseLoop(opts) {
|
|
|
80
75
|
throwIfAborted(ctx.signal);
|
|
81
76
|
const { content, messageId, started, usage: turnUsage } = await ctx.generate(request);
|
|
82
77
|
usage = turnUsage ?? usage;
|
|
78
|
+
if (pendingHistory.length > 0) {
|
|
79
|
+
ctx.history.push(...pendingHistory);
|
|
80
|
+
pendingHistory = [];
|
|
81
|
+
}
|
|
83
82
|
if (turn === 1)
|
|
84
83
|
ctx.history.push(...ctx.inputMessages);
|
|
85
84
|
if (started) {
|
|
@@ -121,10 +120,9 @@ export function generateValidateReviseLoop(opts) {
|
|
|
121
120
|
ctx.emit({ type: "artifact_revision_started", sessionId: ctx.sessionId, runId: ctx.runId, turn, attempt, failure: result });
|
|
122
121
|
const repair = await repairer(parsed.value, result, artifactCtx);
|
|
123
122
|
const repairMessages = inputMessages(repair).map((m) => ({ ...m, id: randomId("msg") }));
|
|
124
|
-
for (const message of repairMessages)
|
|
125
|
-
ctx.history.push(message);
|
|
123
|
+
for (const message of repairMessages)
|
|
126
124
|
await ctx.appendMessage(message);
|
|
127
|
-
|
|
125
|
+
pendingHistory = repairMessages;
|
|
128
126
|
nextInput = repairMessages;
|
|
129
127
|
continue;
|
|
130
128
|
}
|
|
@@ -135,6 +133,54 @@ export function generateValidateReviseLoop(opts) {
|
|
|
135
133
|
// ponytail: resolveLoop returns the loop to run. RunOptions.loop wins over
|
|
136
134
|
// AgentConfig.loop; default is singleShotLoop. generate-validate-revise maps
|
|
137
135
|
// its options to the factory; unknown strategy throws.
|
|
136
|
+
export function resolveToolConcurrency(options, config) {
|
|
137
|
+
const loop = options.loop ?? config.loop;
|
|
138
|
+
if (!loop || !isAgentLoopOptions(loop) || loop.strategy !== "single-shot")
|
|
139
|
+
return 1;
|
|
140
|
+
const value = loop.toolConcurrency;
|
|
141
|
+
if (value === undefined)
|
|
142
|
+
return 1;
|
|
143
|
+
if (!Number.isFinite(value) || value < 1)
|
|
144
|
+
return 1;
|
|
145
|
+
return Math.floor(value);
|
|
146
|
+
}
|
|
147
|
+
/** Dispatch tool calls with bounded concurrency; append transcript rows in call order. */
|
|
148
|
+
export async function dispatchToolCallsInOrder(calls, ctx) {
|
|
149
|
+
if (calls.length === 0)
|
|
150
|
+
return;
|
|
151
|
+
const concurrency = calls.some((call) => ctx.isToolCallExclusive?.(call))
|
|
152
|
+
? 1
|
|
153
|
+
: Math.max(1, Math.min(ctx.toolConcurrency, calls.length));
|
|
154
|
+
if (concurrency === 1) {
|
|
155
|
+
for (const call of calls) {
|
|
156
|
+
const result = await ctx.dispatchToolCall(call);
|
|
157
|
+
await appendToolResultMessage(result, ctx);
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const results = new Array(calls.length);
|
|
162
|
+
let nextIndex = 0;
|
|
163
|
+
const workers = Array.from({ length: concurrency }, async () => {
|
|
164
|
+
for (;;) {
|
|
165
|
+
throwIfAborted(ctx.signal);
|
|
166
|
+
const index = nextIndex;
|
|
167
|
+
nextIndex += 1;
|
|
168
|
+
if (index >= calls.length)
|
|
169
|
+
return;
|
|
170
|
+
results[index] = await ctx.dispatchToolCall(calls[index]);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
await Promise.all(workers);
|
|
174
|
+
for (const result of results) {
|
|
175
|
+
throwIfAborted(ctx.signal);
|
|
176
|
+
await appendToolResultMessage(result, ctx);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async function appendToolResultMessage(result, ctx) {
|
|
180
|
+
const message = toolResultMessage(result);
|
|
181
|
+
ctx.history.push(message);
|
|
182
|
+
await ctx.appendMessage(message);
|
|
183
|
+
}
|
|
138
184
|
export function resolveLoop(options, config) {
|
|
139
185
|
const loop = options.loop ?? config.loop;
|
|
140
186
|
if (!loop)
|