@elie-laloum/outpost 9.0.6 → 9.1.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/CHANGELOG.md +26 -0
- package/README.md +7 -4
- package/SECURITY.md +1 -1
- package/dist/adapters/decisions/system-one-provider.constants.d.ts +2 -0
- package/dist/adapters/decisions/system-one-provider.constants.js +8 -0
- package/dist/adapters/decisions/system-one-provider.constants.js.map +1 -0
- package/dist/adapters/decisions/system-one-provider.d.ts +3 -0
- package/dist/adapters/decisions/system-one-provider.js +94 -0
- package/dist/adapters/decisions/system-one-provider.js.map +1 -0
- package/dist/adapters/decisions/system-one-provider.types.d.ts +6 -0
- package/dist/adapters/decisions/system-one-provider.types.js +2 -0
- package/dist/adapters/decisions/system-one-provider.types.js.map +1 -0
- package/dist/adapters/decisions/system-one-response.d.ts +2 -0
- package/dist/adapters/decisions/system-one-response.js +45 -0
- package/dist/adapters/decisions/system-one-response.js.map +1 -0
- package/dist/application/custom-turn.js +2 -0
- package/dist/application/custom-turn.js.map +1 -1
- package/dist/application/decision-task.d.ts +4 -0
- package/dist/application/decision-task.js +29 -0
- package/dist/application/decision-task.js.map +1 -0
- package/dist/application/decision.d.ts +4 -0
- package/dist/application/decision.js +101 -0
- package/dist/application/decision.js.map +1 -0
- package/dist/application/decision.types.d.ts +10 -0
- package/dist/application/decision.types.js +2 -0
- package/dist/application/decision.types.js.map +1 -0
- package/dist/application/harness-context.js +6 -0
- package/dist/application/harness-context.js.map +1 -1
- package/dist/application/harness-history.js +3 -0
- package/dist/application/harness-history.js.map +1 -1
- package/dist/application/harness-loop.js +8 -1
- package/dist/application/harness-loop.js.map +1 -1
- package/dist/application/harness-model-provider.js +0 -3
- package/dist/application/harness-model-provider.js.map +1 -1
- package/dist/application/harness-routing.d.ts +3 -0
- package/dist/application/harness-routing.js +88 -0
- package/dist/application/harness-routing.js.map +1 -0
- package/dist/application/harness-subagent.js +2 -0
- package/dist/application/harness-subagent.js.map +1 -1
- package/dist/application/harness.types.d.ts +4 -0
- package/dist/application/harness.types.js.map +1 -1
- package/dist/application/replay-turn.js +19 -1
- package/dist/application/replay-turn.js.map +1 -1
- package/dist/domain/agent-observation.js +3 -0
- package/dist/domain/agent-observation.js.map +1 -1
- package/dist/domain/agent.types.d.ts +2 -1
- package/dist/domain/agent.types.js.map +1 -1
- package/dist/domain/decision-result.d.ts +6 -0
- package/dist/domain/decision-result.js +116 -0
- package/dist/domain/decision-result.js.map +1 -0
- package/dist/domain/decision.constants.d.ts +12 -0
- package/dist/domain/decision.constants.js +18 -0
- package/dist/domain/decision.constants.js.map +1 -0
- package/dist/domain/decision.d.ts +5 -0
- package/dist/domain/decision.js +75 -0
- package/dist/domain/decision.js.map +1 -0
- package/dist/domain/decision.types.d.ts +99 -0
- package/dist/domain/decision.types.js +2 -0
- package/dist/domain/decision.types.js.map +1 -0
- package/dist/domain/harness-routing.constants.d.ts +2 -0
- package/dist/domain/harness-routing.constants.js +13 -0
- package/dist/domain/harness-routing.constants.js.map +1 -0
- package/dist/domain/harness-routing.d.ts +3 -0
- package/dist/domain/harness-routing.js +44 -0
- package/dist/domain/harness-routing.js.map +1 -0
- package/dist/domain/harness-routing.types.d.ts +45 -0
- package/dist/domain/harness-routing.types.js +2 -0
- package/dist/domain/harness-routing.types.js.map +1 -0
- package/dist/domain/harness.constants.js +1 -0
- package/dist/domain/harness.constants.js.map +1 -1
- package/dist/domain/harness.js +12 -0
- package/dist/domain/harness.js.map +1 -1
- package/dist/domain/harness.types.d.ts +3 -0
- package/dist/domain/harness.types.js.map +1 -1
- package/dist/domain/observation.types.d.ts +9 -2
- package/dist/domain/observation.types.js.map +1 -1
- package/dist/domain/replay.constants.d.ts +1 -0
- package/dist/domain/replay.constants.js +5 -0
- package/dist/domain/replay.constants.js.map +1 -1
- package/dist/domain/replay.js +57 -3
- package/dist/domain/replay.js.map +1 -1
- package/dist/domain/replay.types.d.ts +11 -0
- package/dist/domain/replay.types.js.map +1 -1
- package/dist/domain/transcript.js +2 -1
- package/dist/domain/transcript.js.map +1 -1
- package/dist/domain/transcript.types.d.ts +5 -2
- package/dist/domain/transcript.types.js.map +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/conversations/harness-transcript.js +24 -14
- package/dist/infrastructure/conversations/harness-transcript.js.map +1 -1
- package/dist/infrastructure/conversations/harness-transcript.types.d.ts +1 -0
- package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -1
- package/dist/infrastructure/journal.constants.js +2 -0
- package/dist/infrastructure/journal.constants.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.1.1
|
|
4
|
+
|
|
5
|
+
- Add typed System One decisions (`defineDecision`, `decide`, `defineDecisionTask`) and one bounded HTTP provider for Jev and compatible Laya endpoints. Preserve native distributions, metadata and input-truncation diagnostics.
|
|
6
|
+
- Add per-step model routing to the built-in harness, including subagents, explicit confidence and outage fallback policies, cumulative routing usage and version-2 transcripts with version-1 compatibility.
|
|
7
|
+
- Document decisions and routing in English and French, with public reference contracts and deterministic HTTP, workflow and conversation regression tests.
|
|
8
|
+
- Accept accumulated four-decimal rounding in native decision distributions and weighted scores without renormalizing them; continue rejecting incoherent responses.
|
|
9
|
+
- Add the runnable System One example with direct decisions and a typed workflow against a local Laya server or an authenticated compatible endpoint.
|
|
10
|
+
- Announce System One support in a bilingual indigo banner. Use a square logo button, equally sized Guide/API buttons with icons, colored source-link hovers and search aligned with the content border on wide screens.
|
|
11
|
+
- Open `/reference/` at the first alphabetical API symbol. Remove family overview pages and redirect their old URLs to the corresponding practical Guide pages.
|
|
12
|
+
- Retire the repository roadmap and preserve its removal in the documentation migration audit. Keep validation limits in the guides and release notes.
|
|
13
|
+
- Pin the documentation's transitive `source-map-js` dependency to the patched 1.2.2 version.
|
|
14
|
+
|
|
15
|
+
The v9.1.0 release was blocked by the documentation dependency audit and was not published.
|
|
16
|
+
|
|
17
|
+
Direct decisions and decision tasks were exercised against a local Laya 0.3.28 CPU server. Live Jev inference and conversational model routing remain unvalidated; the ordinary test suites use deterministic local fixtures.
|
|
18
|
+
|
|
19
|
+
## 9.0.8
|
|
20
|
+
|
|
21
|
+
- Redesign the bilingual documentation home with a full-viewport hero, a four-step journey and a nine-capability grid linking to the Guide. Show a medium-sized CSV-export workflow with parallel tests and review, bounded correction rounds and human approval.
|
|
22
|
+
- Add a site favicon, localized social previews, homepage search metadata and structured data, and a robots endpoint.
|
|
23
|
+
- Replace direct console output in Guide, homepage and README snippets with reporters and sample-output comments. Typecheck the shared reporter and execute the offline examples in both languages.
|
|
24
|
+
- Hide code-tab and snippet scrollbars while preserving horizontal scrolling, mouse dragging and keyboard navigation.
|
|
25
|
+
- Include the shared reporter when executing real container documentation examples in both languages.
|
|
26
|
+
|
|
27
|
+
Public library contracts and runtime behavior are unchanged.
|
|
28
|
+
|
|
3
29
|
## 9.0.6
|
|
4
30
|
|
|
5
31
|
- Rewrite the English and French Guide with clearer titles and explanations. The recommended setup builds an agent image, then imports Outpost in user-written TypeScript files; generated `init` workflow projects remain optional. Link option and property definitions to their API contracts instead of repeating them in the Guide.
|
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ Use an ESM directory (`"type": "module"` in `package.json`); a CommonJS reposito
|
|
|
54
54
|
import {
|
|
55
55
|
createAgent,
|
|
56
56
|
createCodexHarness,
|
|
57
|
+
createReporter,
|
|
57
58
|
dispatch,
|
|
58
59
|
} from "@elie-laloum/outpost";
|
|
59
60
|
import { createDockerSandboxProvider } from "@elie-laloum/outpost/providers/docker";
|
|
@@ -64,15 +65,17 @@ const result = await dispatch({
|
|
|
64
65
|
harness: createCodexHarness({ authentication: "account" }),
|
|
65
66
|
}),
|
|
66
67
|
sandboxProvider: createDockerSandboxProvider({ image: "outpost:dev" }),
|
|
68
|
+
observe: createReporter(),
|
|
67
69
|
branch: { mode: "named", name: "outpost/fix-tests" },
|
|
68
70
|
brief: {
|
|
69
71
|
text: "Fix the failing tests, run them to verify and commit the change.",
|
|
70
72
|
},
|
|
71
73
|
});
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
// Example output:
|
|
76
|
+
// [outpost · pass 1] running · codex
|
|
77
|
+
// Fixed the failing tests and committed the change.
|
|
78
|
+
// [outpost · pass 1] finished · 12.00s · status 0 · input 1200 · cache read 0 · cache write 0 · output 320
|
|
76
79
|
```
|
|
77
80
|
|
|
78
81
|
`dispatch()` closes the sandbox it allocates; the named branch remains for review. Use a fresh branch name for each independent task. The agent’s answer is not an enforced test result: add explicit verification when checks must gate integration.
|
|
@@ -100,7 +103,7 @@ Conversation support varies: Claude Code, Codex and Kimi support capture, resume
|
|
|
100
103
|
|
|
101
104
|
Docker and Podman mount the selected workspace and Git metadata by default. These mounts are not an adversarial security boundary. Cloud providers receive repository data and declared credentials; explicit local execution runs on the host without isolation. Read [SECURITY.md](SECURITY.md) before choosing an environment for untrusted code.
|
|
102
105
|
|
|
103
|
-
Speculation remains experimental. See the [
|
|
106
|
+
Speculation remains experimental. See the [speculation guide](https://elie-laloum.github.io/outpost/guide/speculation/) for validation limits and the [changelog](CHANGELOG.md) for version history.
|
|
104
107
|
|
|
105
108
|
## Development and contributions
|
|
106
109
|
|
package/SECURITY.md
CHANGED
|
@@ -24,7 +24,7 @@ Explicit storage transports can send artifacts, journals, transcripts, recovery
|
|
|
24
24
|
|
|
25
25
|
The optional Firecracker jailer mode requires a trusted root supervisor and root-owned boot assets, executables, SSH trust files, jail base and cgroup v2 parent. Outpost does not elevate privileges. The VMM drops to the explicitly selected non-root UID/GID, uses the jailer's mount namespace and receives CPU, memory, swap and process limits. The supervisor remains privileged and outside the VMM cgroup; its workflow code, configuration, dependencies and transfer destinations must be trusted. Guest file downloads currently buffer individual files in the supervisor, so the VMM memory limit is not a total host-resource budget. Kernel work outside that cgroup is likewise not charged to its CPU quota. Operators own TAP setup, network filtering, parent resources and crash recovery. Control-plane resource accounting and adversarial validation of this mode remain open.
|
|
26
26
|
|
|
27
|
-
Egress policies restrict sandbox outbound connections, not host model-provider calls, image downloads or cloud control-plane traffic. Vercel domain rules inspect TLS SNI rather than encrypted HTTP Host headers; allowed CIDRs grant independent IP access and denied CIDRs take precedence. A domain allowlist is not a general defense against exfiltration through allowed services or shared infrastructure. Mounted host sockets can expose separate network capabilities. Outpost copies network configuration at provider composition.
|
|
27
|
+
Egress policies restrict sandbox outbound connections, not host model-provider or decision-provider calls, image downloads or cloud control-plane traffic. Vercel domain rules inspect TLS SNI rather than encrypted HTTP Host headers; allowed CIDRs grant independent IP access and denied CIDRs take precedence. A domain allowlist is not a general defense against exfiltration through allowed services or shared infrastructure. Mounted host sockets can expose separate network capabilities. Outpost copies network configuration at provider composition.
|
|
28
28
|
|
|
29
29
|
Daytona egress is sent at creation and confirmed through its network-update API before Outpost prepares the workspace or exposes the lease. A rejected confirmation fails acquisition and triggers deletion. Tier 3/4 and WRITE_SANDBOXES are required; native creation options alone do not establish this guarantee. Autonomous image startup precedes confirmation and must be trusted, without embedded secrets or startup workloads. Unsupported combinations and wildcard patterns that would implicitly grant apex access are rejected. Docker/Podman allowlists remain unsupported; local and Firecracker execution reject Outpost egress policies. See the bilingual outbound-network guide for capabilities and live-validation limits.
|
|
30
30
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { MODEL_TIMEOUT_MS as DECISION_TIMEOUT_MS, MODEL_RESPONSE_BYTES as DECISION_RESPONSE_BYTES, MODEL_MAX_TIMEOUT_MS as DECISION_MAX_TIMEOUT_MS, MODEL_UNAVAILABLE_STATUSES as DECISION_UNAVAILABLE_STATUSES, } from "../models/model.constants.ts";
|
|
2
|
+
export declare const SYSTEM_ONE_PROVIDER_FIELDS: Set<string>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { MODEL_TIMEOUT_MS as DECISION_TIMEOUT_MS, MODEL_RESPONSE_BYTES as DECISION_RESPONSE_BYTES, MODEL_MAX_TIMEOUT_MS as DECISION_MAX_TIMEOUT_MS, MODEL_UNAVAILABLE_STATUSES as DECISION_UNAVAILABLE_STATUSES, } from "../models/model.constants.js";
|
|
2
|
+
export const SYSTEM_ONE_PROVIDER_FIELDS = new Set([
|
|
3
|
+
"baseUrl",
|
|
4
|
+
"apiKey",
|
|
5
|
+
"timeoutMs",
|
|
6
|
+
"maxResponseBytes",
|
|
7
|
+
]);
|
|
8
|
+
//# sourceMappingURL=system-one-provider.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-one-provider.constants.js","sourceRoot":"","sources":["../../../src/adapters/decisions/system-one-provider.constants.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,IAAI,mBAAmB,EACvC,oBAAoB,IAAI,uBAAuB,EAC/C,oBAAoB,IAAI,uBAAuB,EAC/C,0BAA0B,IAAI,6BAA6B,GAC5D,MAAM,8BAA8B,CAAC;AAEtC,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IAChD,SAAS;IACT,QAAQ;IACR,WAAW;IACX,kBAAkB;CACnB,CAAC,CAAC","sourcesContent":["export {\n MODEL_TIMEOUT_MS as DECISION_TIMEOUT_MS,\n MODEL_RESPONSE_BYTES as DECISION_RESPONSE_BYTES,\n MODEL_MAX_TIMEOUT_MS as DECISION_MAX_TIMEOUT_MS,\n MODEL_UNAVAILABLE_STATUSES as DECISION_UNAVAILABLE_STATUSES,\n} from \"../models/model.constants.ts\";\n\nexport const SYSTEM_ONE_PROVIDER_FIELDS = new Set([\n \"baseUrl\",\n \"apiKey\",\n \"timeoutMs\",\n \"maxResponseBytes\",\n]);\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DecisionProvider } from "../../domain/decision.types.ts";
|
|
2
|
+
import type { SystemOneDecisionProviderOptions } from "./system-one-provider.types.ts";
|
|
3
|
+
export declare function createSystemOneDecisionProvider(options: SystemOneDecisionProviderOptions): DecisionProvider;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { invariant, OutpostError, positive } from "../../domain/errors.js";
|
|
2
|
+
import { defineDecision, validateDecisionState, } from "../../domain/decision.js";
|
|
3
|
+
import { resetTimestamp } from "../../domain/quota.js";
|
|
4
|
+
import { modelJson } from "../models/model-http.js";
|
|
5
|
+
import { retryAfterMs } from "../models/retry-after.js";
|
|
6
|
+
import { readSystemOneResponse } from "./system-one-response.js";
|
|
7
|
+
import { DECISION_TIMEOUT_MS, DECISION_RESPONSE_BYTES, DECISION_MAX_TIMEOUT_MS, DECISION_UNAVAILABLE_STATUSES, SYSTEM_ONE_PROVIDER_FIELDS, } from "./system-one-provider.constants.js";
|
|
8
|
+
export function createSystemOneDecisionProvider(options) {
|
|
9
|
+
invariant(options && typeof options === "object", "Decision provider options must be an object");
|
|
10
|
+
invariant(Object.keys(options).every((key) => SYSTEM_ONE_PROVIDER_FIELDS.has(key)), "Unsupported System One provider option");
|
|
11
|
+
let base;
|
|
12
|
+
try {
|
|
13
|
+
base = new URL(options.baseUrl);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new OutpostError("configuration", "Decision baseUrl must be an absolute HTTP(S) URL");
|
|
17
|
+
}
|
|
18
|
+
invariant(["http:", "https:"].includes(base.protocol) &&
|
|
19
|
+
!base.username &&
|
|
20
|
+
!base.password &&
|
|
21
|
+
!base.href.includes("?") &&
|
|
22
|
+
!base.href.includes("#"), "Decision baseUrl must use HTTP(S) without credentials, query or fragment");
|
|
23
|
+
invariant(options.apiKey === false ||
|
|
24
|
+
(typeof options.apiKey === "string" &&
|
|
25
|
+
options.apiKey.trim() &&
|
|
26
|
+
!/[\r\n]/.test(options.apiKey)), "Decision apiKey must be nonempty or false");
|
|
27
|
+
const endpoint = `${base.href.replace(/\/+$/, "")}/systemone`;
|
|
28
|
+
const timeoutMs = positive(options.timeoutMs ?? DECISION_TIMEOUT_MS, "Decision timeoutMs");
|
|
29
|
+
invariant(timeoutMs <= DECISION_MAX_TIMEOUT_MS, "Decision timeoutMs exceeds the supported timer range");
|
|
30
|
+
const maxBytes = positive(options.maxResponseBytes ?? DECISION_RESPONSE_BYTES, "Decision maxResponseBytes");
|
|
31
|
+
const key = options.apiKey;
|
|
32
|
+
return Object.freeze({
|
|
33
|
+
name: "system-one",
|
|
34
|
+
identity: `system-one:${endpoint}`,
|
|
35
|
+
async request(request) {
|
|
36
|
+
invariant(request && typeof request.model === "string" && request.model.trim(), "Decision model must be nonempty text");
|
|
37
|
+
const decision = defineDecision({ questions: request.questions });
|
|
38
|
+
validateDecisionState(request.state);
|
|
39
|
+
request.signal?.throwIfAborted();
|
|
40
|
+
const deadline = new AbortController();
|
|
41
|
+
const signal = request.signal
|
|
42
|
+
? AbortSignal.any([request.signal, deadline.signal])
|
|
43
|
+
: deadline.signal;
|
|
44
|
+
const timer = setTimeout(() => deadline.abort(), timeoutMs);
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(endpoint, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
redirect: "error",
|
|
49
|
+
headers: {
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
...(key === false ? {} : { Authorization: `Bearer ${key}` }),
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify({
|
|
54
|
+
model: request.model,
|
|
55
|
+
state: request.state,
|
|
56
|
+
questions: decision.questions,
|
|
57
|
+
}),
|
|
58
|
+
signal,
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const retryAfter = retryAfterMs(response.headers.get("Retry-After"));
|
|
62
|
+
await response.body?.cancel();
|
|
63
|
+
const resetAt = response.status === 429 && retryAfter !== undefined
|
|
64
|
+
? resetTimestamp(retryAfter)
|
|
65
|
+
: undefined;
|
|
66
|
+
throw new OutpostError(response.status === 429 ? "quota" : "provider", `Decision request failed with HTTP ${response.status}`, {
|
|
67
|
+
status: response.status,
|
|
68
|
+
...(retryAfter === undefined ? {} : { retryAfterMs: retryAfter }),
|
|
69
|
+
...(resetAt === undefined ? {} : { resetAt }),
|
|
70
|
+
...(DECISION_UNAVAILABLE_STATUSES.has(response.status)
|
|
71
|
+
? { unavailable: `HTTP ${response.status}` }
|
|
72
|
+
: {}),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const value = await modelJson(response, maxBytes);
|
|
76
|
+
signal.throwIfAborted();
|
|
77
|
+
return readSystemOneResponse(value);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (signal.aborted)
|
|
81
|
+
throw new OutpostError(request.signal?.aborted ? "aborted" : "timeout", request.signal?.aborted
|
|
82
|
+
? "Decision request was cancelled"
|
|
83
|
+
: "Decision request timed out");
|
|
84
|
+
if (error instanceof OutpostError)
|
|
85
|
+
throw error;
|
|
86
|
+
throw new OutpostError("provider", "Decision request failed during HTTP transport", { unavailable: "HTTP transport failure" });
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=system-one-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-one-provider.js","sourceRoot":"","sources":["../../../src/adapters/decisions/system-one-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant, OutpostError, positive } from \"../../domain/errors.ts\";\nimport {\n defineDecision,\n validateDecisionState,\n} from \"../../domain/decision.ts\";\nimport { resetTimestamp } from \"../../domain/quota.ts\";\nimport type {\n DecisionProvider,\n DecisionRequest,\n} from \"../../domain/decision.types.ts\";\nimport { modelJson } from \"../models/model-http.ts\";\nimport { retryAfterMs } from \"../models/retry-after.ts\";\nimport { readSystemOneResponse } from \"./system-one-response.ts\";\nimport type { SystemOneDecisionProviderOptions } from \"./system-one-provider.types.ts\";\nimport {\n DECISION_TIMEOUT_MS,\n DECISION_RESPONSE_BYTES,\n DECISION_MAX_TIMEOUT_MS,\n DECISION_UNAVAILABLE_STATUSES,\n SYSTEM_ONE_PROVIDER_FIELDS,\n} from \"./system-one-provider.constants.ts\";\n\nexport function createSystemOneDecisionProvider(\n options: SystemOneDecisionProviderOptions,\n): DecisionProvider {\n invariant(\n options && typeof options === \"object\",\n \"Decision provider options must be an object\",\n );\n invariant(\n Object.keys(options).every((key) => SYSTEM_ONE_PROVIDER_FIELDS.has(key)),\n \"Unsupported System One provider option\",\n );\n let base: URL;\n try {\n base = new URL(options.baseUrl);\n } catch {\n throw new OutpostError(\n \"configuration\",\n \"Decision baseUrl must be an absolute HTTP(S) URL\",\n );\n }\n invariant(\n [\"http:\", \"https:\"].includes(base.protocol) &&\n !base.username &&\n !base.password &&\n !base.href.includes(\"?\") &&\n !base.href.includes(\"#\"),\n \"Decision baseUrl must use HTTP(S) without credentials, query or fragment\",\n );\n invariant(\n options.apiKey === false ||\n (typeof options.apiKey === \"string\" &&\n options.apiKey.trim() &&\n !/[\\r\\n]/.test(options.apiKey)),\n \"Decision apiKey must be nonempty or false\",\n );\n const endpoint = `${base.href.replace(/\\/+$/, \"\")}/systemone`;\n const timeoutMs = positive(\n options.timeoutMs ?? DECISION_TIMEOUT_MS,\n \"Decision timeoutMs\",\n );\n invariant(\n timeoutMs <= DECISION_MAX_TIMEOUT_MS,\n \"Decision timeoutMs exceeds the supported timer range\",\n );\n const maxBytes = positive(\n options.maxResponseBytes ?? DECISION_RESPONSE_BYTES,\n \"Decision maxResponseBytes\",\n );\n const key = options.apiKey;\n return Object.freeze({\n name: \"system-one\",\n identity: `system-one:${endpoint}`,\n async request(request: DecisionRequest) {\n invariant(\n request && typeof request.model === \"string\" && request.model.trim(),\n \"Decision model must be nonempty text\",\n );\n const decision = defineDecision({ questions: request.questions });\n validateDecisionState(request.state);\n request.signal?.throwIfAborted();\n const deadline = new AbortController();\n const signal = request.signal\n ? AbortSignal.any([request.signal, deadline.signal])\n : deadline.signal;\n const timer = setTimeout(() => deadline.abort(), timeoutMs);\n try {\n const response = await fetch(endpoint, {\n method: \"POST\",\n redirect: \"error\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(key === false ? {} : { Authorization: `Bearer ${key}` }),\n },\n body: JSON.stringify({\n model: request.model,\n state: request.state,\n questions: decision.questions,\n }),\n signal,\n });\n if (!response.ok) {\n const retryAfter = retryAfterMs(response.headers.get(\"Retry-After\"));\n await response.body?.cancel();\n const resetAt =\n response.status === 429 && retryAfter !== undefined\n ? resetTimestamp(retryAfter)\n : undefined;\n throw new OutpostError(\n response.status === 429 ? \"quota\" : \"provider\",\n `Decision request failed with HTTP ${response.status}`,\n {\n status: response.status,\n ...(retryAfter === undefined ? {} : { retryAfterMs: retryAfter }),\n ...(resetAt === undefined ? {} : { resetAt }),\n ...(DECISION_UNAVAILABLE_STATUSES.has(response.status)\n ? { unavailable: `HTTP ${response.status}` }\n : {}),\n },\n );\n }\n const value = await modelJson(response, maxBytes);\n signal.throwIfAborted();\n return readSystemOneResponse(value);\n } catch (error) {\n if (signal.aborted)\n throw new OutpostError(\n request.signal?.aborted ? \"aborted\" : \"timeout\",\n request.signal?.aborted\n ? \"Decision request was cancelled\"\n : \"Decision request timed out\",\n );\n if (error instanceof OutpostError) throw error;\n throw new OutpostError(\n \"provider\",\n \"Decision request failed during HTTP transport\",\n { unavailable: \"HTTP transport failure\" },\n );\n } finally {\n clearTimeout(timer);\n }\n },\n });\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-one-provider.types.js","sourceRoot":"","sources":["../../../src/adapters/decisions/system-one-provider.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface SystemOneDecisionProviderOptions {\n readonly baseUrl: string;\n readonly apiKey: string | false;\n readonly timeoutMs?: number;\n readonly maxResponseBytes?: number;\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { decisionObject, requireDecisionResponse, } from "../../domain/decision-result.js";
|
|
2
|
+
import { checkpointValue } from "../../domain/workflow/checkpoint-value.js";
|
|
3
|
+
import { OutpostError } from "../../domain/errors.js";
|
|
4
|
+
export function readSystemOneResponse(value) {
|
|
5
|
+
const data = decisionObject(value);
|
|
6
|
+
requireDecisionResponse(typeof data.model === "string");
|
|
7
|
+
const answers = decisionObject(data.answers);
|
|
8
|
+
const usage = data.usage === undefined ? undefined : decisionObject(data.usage);
|
|
9
|
+
if (usage)
|
|
10
|
+
requireDecisionResponse([usage.input_tokens, usage.output_tokens].every((value) => typeof value === "number" &&
|
|
11
|
+
Number.isSafeInteger(value) &&
|
|
12
|
+
value >= 0));
|
|
13
|
+
requireDecisionResponse(data.truncated === undefined || typeof data.truncated === "boolean");
|
|
14
|
+
requireDecisionResponse(usage?.truncated === undefined || typeof usage.truncated === "boolean");
|
|
15
|
+
requireDecisionResponse(data.truncated === undefined ||
|
|
16
|
+
usage?.truncated === undefined ||
|
|
17
|
+
data.truncated === usage.truncated);
|
|
18
|
+
const truncated = usage?.truncated ?? data.truncated;
|
|
19
|
+
requireDecisionResponse(truncated === undefined || typeof truncated === "boolean");
|
|
20
|
+
const metadata = (() => {
|
|
21
|
+
try {
|
|
22
|
+
return checkpointValue(value);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new OutpostError("response", "Decision response must contain lossless JSON");
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
requireDecisionResponse(metadata.kind === "json");
|
|
29
|
+
return {
|
|
30
|
+
model: data.model,
|
|
31
|
+
answers,
|
|
32
|
+
...(usage
|
|
33
|
+
? {
|
|
34
|
+
usage: {
|
|
35
|
+
input: Number(usage.input_tokens),
|
|
36
|
+
cached: 0,
|
|
37
|
+
output: Number(usage.output_tokens),
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
: {}),
|
|
41
|
+
...(truncated === undefined ? {} : { truncated }),
|
|
42
|
+
metadata: structuredClone(metadata.value),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=system-one-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-one-response.js","sourceRoot":"","sources":["../../../src/adapters/decisions/system-one-response.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,uBAAuB,GACxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,uBAAuB,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,KAAK,GACT,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpE,IAAI,KAAK;QACP,uBAAuB,CACrB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,KAAK,CAC7C,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC3B,KAAK,IAAI,CAAC,CACb,CACF,CAAC;IACJ,uBAAuB,CACrB,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,SAAS,CACpE,CAAC;IACF,uBAAuB,CACrB,KAAK,EAAE,SAAS,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,SAAS,CACvE,CAAC;IACF,uBAAuB,CACrB,IAAI,CAAC,SAAS,KAAK,SAAS;QAC1B,KAAK,EAAE,SAAS,KAAK,SAAS;QAC9B,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CACrC,CAAC;IACF,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC;IACrD,uBAAuB,CACrB,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS,KAAK,SAAS,CAC1D,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE;QACrB,IAAI,CAAC;YACH,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,YAAY,CACpB,UAAU,EACV,8CAA8C,CAC/C,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IACL,uBAAuB,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAClD,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO;QACP,GAAG,CAAC,KAAK;YACP,CAAC,CAAC;gBACE,KAAK,EAAE;oBACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC;oBACjC,MAAM,EAAE,CAAC;oBACT,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;iBACpC;aACF;YACH,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;QACjD,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC;KAC1C,CAAC;AACJ,CAAC","sourcesContent":["import {\n decisionObject,\n requireDecisionResponse,\n} from \"../../domain/decision-result.ts\";\nimport { checkpointValue } from \"../../domain/workflow/checkpoint-value.ts\";\nimport { OutpostError } from \"../../domain/errors.ts\";\nimport type { DecisionProviderResult } from \"../../domain/decision.types.ts\";\n\nexport function readSystemOneResponse(value: unknown): DecisionProviderResult {\n const data = decisionObject(value);\n requireDecisionResponse(typeof data.model === \"string\");\n const answers = decisionObject(data.answers);\n const usage =\n data.usage === undefined ? undefined : decisionObject(data.usage);\n if (usage)\n requireDecisionResponse(\n [usage.input_tokens, usage.output_tokens].every(\n (value) =>\n typeof value === \"number\" &&\n Number.isSafeInteger(value) &&\n value >= 0,\n ),\n );\n requireDecisionResponse(\n data.truncated === undefined || typeof data.truncated === \"boolean\",\n );\n requireDecisionResponse(\n usage?.truncated === undefined || typeof usage.truncated === \"boolean\",\n );\n requireDecisionResponse(\n data.truncated === undefined ||\n usage?.truncated === undefined ||\n data.truncated === usage.truncated,\n );\n const truncated = usage?.truncated ?? data.truncated;\n requireDecisionResponse(\n truncated === undefined || typeof truncated === \"boolean\",\n );\n const metadata = (() => {\n try {\n return checkpointValue(value);\n } catch {\n throw new OutpostError(\n \"response\",\n \"Decision response must contain lossless JSON\",\n );\n }\n })();\n requireDecisionResponse(metadata.kind === \"json\");\n return {\n model: data.model,\n answers,\n ...(usage\n ? {\n usage: {\n input: Number(usage.input_tokens),\n cached: 0,\n output: Number(usage.output_tokens),\n },\n }\n : {}),\n ...(truncated === undefined ? {} : { truncated }),\n metadata: structuredClone(metadata.value),\n };\n}\n"]}
|
|
@@ -111,6 +111,7 @@ export async function customTurn(lease, agent, prompt, options, pass, context) {
|
|
|
111
111
|
repository: context.repository,
|
|
112
112
|
store: storage,
|
|
113
113
|
model: agent.model.name,
|
|
114
|
+
routed: Boolean(agent.harness.routing),
|
|
114
115
|
...(context.continuation
|
|
115
116
|
? { continuation: context.continuation }
|
|
116
117
|
: {}),
|
|
@@ -120,6 +121,7 @@ export async function customTurn(lease, agent, prompt, options, pass, context) {
|
|
|
120
121
|
emit({ kind: "conversation", id: transcript.id });
|
|
121
122
|
const run = (tools, mcp) => harnessLoop({
|
|
122
123
|
agent,
|
|
124
|
+
observation: options.observation?.child({ pass }),
|
|
123
125
|
repository: context.repository,
|
|
124
126
|
...(transcript ? { conversation: transcript.id } : {}),
|
|
125
127
|
budget,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-turn.js","sourceRoot":"","sources":["../../src/application/custom-turn.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEvent, CustomAgent, Usage } from \"../domain/agent.types.ts\";\nimport type { ModelResult } from \"../domain/model.types.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { invariant, OutpostError } from \"../domain/errors.ts\";\nimport { steeringInbox } from \"../domain/steering.ts\";\nimport { harnessSteering } from \"./harness-steering.ts\";\nimport { harnessBudget } from \"./harness-budget.ts\";\nimport { harnessModelProvider } from \"./harness-model-provider.ts\";\nimport { MAX_DELEGATION_DEPTH } from \"../domain/subagent.constants.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport { activityWatchdog } from \"./activity-watchdog.ts\";\nimport { executionDefaults } from \"./execution.constants.ts\";\nimport type { DispatchOptions, Turn } from \"./execution.types.ts\";\nimport { openTranscript } from \"../infrastructure/conversations/harness-transcript.ts\";\nimport type { TranscriptHandle } from \"../infrastructure/conversations/harness-transcript.types.ts\";\nimport { storageFor } from \"./agent-storage.ts\";\nimport { harnessHistory } from \"./harness-history.ts\";\nimport { harnessLoop } from \"./harness-loop.ts\";\nimport { withMcpTools } from \"./harness-mcp.ts\";\nimport type { HarnessTool } from \"../domain/tool.types.ts\";\nimport type { HarnessMcpContext } from \"../domain/harness.types.ts\";\nimport type { CustomTurnContext } from \"./harness.types.ts\";\nimport { stopReason } from \"./stop-reason.ts\";\nimport { notify } from \"./observation.ts\";\n\nexport async function customTurn(\n lease: SandboxLease,\n agent: CustomAgent,\n prompt: string,\n options: DispatchOptions<unknown>,\n pass: number,\n context: CustomTurnContext,\n): Promise<Turn> {\n const start = Date.now();\n const controller = new AbortController();\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n const watchdog = activityWatchdog(controller, options, pass);\n const timer = setTimeout(\n () =>\n controller.abort(\n new OutpostError(\"timeout\", \"Harness execution timed out\"),\n ),\n options.deadlineMs ?? executionDefaults.deadlineMs,\n );\n let usage: Usage = { input: 0, cached: 0, output: 0 };\n const pending = new Set<Promise<unknown>>();\n const track = <T>(operation: Promise<T>): Promise<T> => {\n pending.add(operation);\n void operation\n .finally(() => pending.delete(operation))\n .catch(() => undefined);\n return operation;\n };\n const emit = (event: AgentEvent) => {\n signal.throwIfAborted();\n watchdog.refresh(false);\n notify(options.observe, { ...event, pass, at: new Date().toISOString() });\n };\n const budget = harnessBudget(agent.harness.limits);\n const inbox = steeringInbox(options.steering);\n const account = (result: ModelResult, subagentId?: string): void => {\n const tokens = result.usage ?? {\n input: 0,\n cached: 0,\n output: 0,\n complete: false,\n };\n usage = addUsage(usage, tokens);\n notify(options.observe, {\n kind: \"usage\",\n tokens,\n ...(subagentId ? { subagentId } : {}),\n pass,\n at: new Date().toISOString(),\n });\n watchdog.refresh(false);\n };\n const modelScope = { track, account };\n const modelProvider = harnessModelProvider({\n agent,\n signal,\n budget,\n ...modelScope,\n });\n const sandbox: SandboxLease = {\n root: lease.root,\n home: lease.home,\n ...(lease.liveInput ? { liveInput: true } : {}),\n invoke: (command) => {\n signal.throwIfAborted();\n return track(\n lease.invoke({\n ...command,\n observe(channel, chunk) {\n watchdog.refresh(false);\n notify((value) => command.observe?.(channel, value), chunk);\n },\n signal: command.signal\n ? AbortSignal.any([command.signal, signal])\n : signal,\n }),\n );\n },\n upload: (source, destination, settings = {}) => {\n signal.throwIfAborted();\n return track(\n lease.upload(source, destination, {\n ...settings,\n signal: settings.signal\n ? AbortSignal.any([settings.signal, signal])\n : signal,\n }),\n );\n },\n download: (source, destination, settings = {}) => {\n signal.throwIfAborted();\n return track(\n lease.download(source, destination, {\n ...settings,\n signal: settings.signal\n ? AbortSignal.any([settings.signal, signal])\n : signal,\n }),\n );\n },\n release: async () => {\n throw new OutpostError(\n \"configuration\",\n \"The harness does not own its sandbox lease\",\n );\n },\n };\n let transcript: TranscriptHandle | undefined;\n try {\n signal.throwIfAborted();\n watchdog.refresh(false);\n const storage = storageFor(agent);\n transcript = storage\n ? await openTranscript({\n repository: context.repository,\n store: storage,\n model: agent.model.name,\n ...(context.continuation\n ? { continuation: context.continuation }\n : {}),\n })\n : undefined;\n if (transcript) emit({ kind: \"conversation\", id: transcript.id });\n const run = (\n tools: readonly HarnessTool[],\n mcp: HarnessMcpContext | undefined,\n ) =>\n harnessLoop(\n {\n agent,\n repository: context.repository,\n ...(transcript ? { conversation: transcript.id } : {}),\n budget,\n modelScope,\n permissions: agent.harness.permissions\n ? [agent.harness.permissions]\n : [],\n depth: 0,\n maxDepth:\n agent.harness.limits.maxDelegationDepth ?? MAX_DELEGATION_DEPTH,\n verbose: options.observation?.verbose ?? false,\n tools,\n modelProvider,\n sandbox,\n mcp,\n signal,\n ...(inbox ? { steering: harnessSteering(inbox) } : {}),\n emit,\n hold: () => watchdog.hold(),\n },\n prompt,\n harnessHistory(transcript),\n );\n // Repairs keep read-only tools but still start MCP servers for prompt instructions.\n const text = await withMcpTools(\n agent.harness,\n sandbox,\n signal,\n agent.harness.tools,\n (tools, mcp) =>\n run(\n context.repair ? tools.filter((tool) => tool.readOnly) : tools,\n mcp,\n ),\n );\n signal.throwIfAborted();\n for (const value of [\n usage.input,\n usage.cached,\n usage.output,\n usage.cacheCreated ?? 0,\n ])\n invariant(\n Number.isSafeInteger(value) && value >= 0,\n \"Harness usage must contain nonnegative token counts\",\n );\n invariant(\n usage.cached + (usage.cacheCreated ?? 0) <= usage.input,\n \"Cached tokens must be included in input usage\",\n );\n notify(options.observe, {\n kind: \"result\",\n text,\n pass,\n at: new Date().toISOString(),\n });\n notify(options.observe, {\n kind: \"finished\",\n pass,\n at: new Date().toISOString(),\n });\n return {\n text,\n usage,\n status: 0,\n durationMs: Date.now() - start,\n ...(transcript ? { conversation: transcript.id } : {}),\n };\n } catch (error) {\n const reason = stopReason(options.signal, controller.signal.reason, error);\n if (reason)\n notify(options.observe, {\n kind: \"stopped\",\n reason,\n pass,\n at: new Date().toISOString(),\n });\n signal.throwIfAborted();\n throw error;\n } finally {\n await transcript?.close();\n controller.abort(new OutpostError(\"aborted\", \"Harness turn ended\"));\n clearTimeout(timer);\n watchdog.close();\n await Promise.allSettled([...pending]);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"custom-turn.js","sourceRoot":"","sources":["../../src/application/custom-turn.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEvent, CustomAgent, Usage } from \"../domain/agent.types.ts\";\nimport type { ModelResult } from \"../domain/model.types.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { invariant, OutpostError } from \"../domain/errors.ts\";\nimport { steeringInbox } from \"../domain/steering.ts\";\nimport { harnessSteering } from \"./harness-steering.ts\";\nimport { harnessBudget } from \"./harness-budget.ts\";\nimport { harnessModelProvider } from \"./harness-model-provider.ts\";\nimport { MAX_DELEGATION_DEPTH } from \"../domain/subagent.constants.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport { activityWatchdog } from \"./activity-watchdog.ts\";\nimport { executionDefaults } from \"./execution.constants.ts\";\nimport type { DispatchOptions, Turn } from \"./execution.types.ts\";\nimport { openTranscript } from \"../infrastructure/conversations/harness-transcript.ts\";\nimport type { TranscriptHandle } from \"../infrastructure/conversations/harness-transcript.types.ts\";\nimport { storageFor } from \"./agent-storage.ts\";\nimport { harnessHistory } from \"./harness-history.ts\";\nimport { harnessLoop } from \"./harness-loop.ts\";\nimport { withMcpTools } from \"./harness-mcp.ts\";\nimport type { HarnessTool } from \"../domain/tool.types.ts\";\nimport type { HarnessMcpContext } from \"../domain/harness.types.ts\";\nimport type { CustomTurnContext } from \"./harness.types.ts\";\nimport { stopReason } from \"./stop-reason.ts\";\nimport { notify } from \"./observation.ts\";\n\nexport async function customTurn(\n lease: SandboxLease,\n agent: CustomAgent,\n prompt: string,\n options: DispatchOptions<unknown>,\n pass: number,\n context: CustomTurnContext,\n): Promise<Turn> {\n const start = Date.now();\n const controller = new AbortController();\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n const watchdog = activityWatchdog(controller, options, pass);\n const timer = setTimeout(\n () =>\n controller.abort(\n new OutpostError(\"timeout\", \"Harness execution timed out\"),\n ),\n options.deadlineMs ?? executionDefaults.deadlineMs,\n );\n let usage: Usage = { input: 0, cached: 0, output: 0 };\n const pending = new Set<Promise<unknown>>();\n const track = <T>(operation: Promise<T>): Promise<T> => {\n pending.add(operation);\n void operation\n .finally(() => pending.delete(operation))\n .catch(() => undefined);\n return operation;\n };\n const emit = (event: AgentEvent) => {\n signal.throwIfAborted();\n watchdog.refresh(false);\n notify(options.observe, { ...event, pass, at: new Date().toISOString() });\n };\n const budget = harnessBudget(agent.harness.limits);\n const inbox = steeringInbox(options.steering);\n const account = (result: ModelResult, subagentId?: string): void => {\n const tokens = result.usage ?? {\n input: 0,\n cached: 0,\n output: 0,\n complete: false,\n };\n usage = addUsage(usage, tokens);\n notify(options.observe, {\n kind: \"usage\",\n tokens,\n ...(subagentId ? { subagentId } : {}),\n pass,\n at: new Date().toISOString(),\n });\n watchdog.refresh(false);\n };\n const modelScope = { track, account };\n const modelProvider = harnessModelProvider({\n agent,\n signal,\n budget,\n ...modelScope,\n });\n const sandbox: SandboxLease = {\n root: lease.root,\n home: lease.home,\n ...(lease.liveInput ? { liveInput: true } : {}),\n invoke: (command) => {\n signal.throwIfAborted();\n return track(\n lease.invoke({\n ...command,\n observe(channel, chunk) {\n watchdog.refresh(false);\n notify((value) => command.observe?.(channel, value), chunk);\n },\n signal: command.signal\n ? AbortSignal.any([command.signal, signal])\n : signal,\n }),\n );\n },\n upload: (source, destination, settings = {}) => {\n signal.throwIfAborted();\n return track(\n lease.upload(source, destination, {\n ...settings,\n signal: settings.signal\n ? AbortSignal.any([settings.signal, signal])\n : signal,\n }),\n );\n },\n download: (source, destination, settings = {}) => {\n signal.throwIfAborted();\n return track(\n lease.download(source, destination, {\n ...settings,\n signal: settings.signal\n ? AbortSignal.any([settings.signal, signal])\n : signal,\n }),\n );\n },\n release: async () => {\n throw new OutpostError(\n \"configuration\",\n \"The harness does not own its sandbox lease\",\n );\n },\n };\n let transcript: TranscriptHandle | undefined;\n try {\n signal.throwIfAborted();\n watchdog.refresh(false);\n const storage = storageFor(agent);\n transcript = storage\n ? await openTranscript({\n repository: context.repository,\n store: storage,\n model: agent.model.name,\n routed: Boolean(agent.harness.routing),\n ...(context.continuation\n ? { continuation: context.continuation }\n : {}),\n })\n : undefined;\n if (transcript) emit({ kind: \"conversation\", id: transcript.id });\n const run = (\n tools: readonly HarnessTool[],\n mcp: HarnessMcpContext | undefined,\n ) =>\n harnessLoop(\n {\n agent,\n observation: options.observation?.child({ pass }),\n repository: context.repository,\n ...(transcript ? { conversation: transcript.id } : {}),\n budget,\n modelScope,\n permissions: agent.harness.permissions\n ? [agent.harness.permissions]\n : [],\n depth: 0,\n maxDepth:\n agent.harness.limits.maxDelegationDepth ?? MAX_DELEGATION_DEPTH,\n verbose: options.observation?.verbose ?? false,\n tools,\n modelProvider,\n sandbox,\n mcp,\n signal,\n ...(inbox ? { steering: harnessSteering(inbox) } : {}),\n emit,\n hold: () => watchdog.hold(),\n },\n prompt,\n harnessHistory(transcript),\n );\n // Repairs keep read-only tools but still start MCP servers for prompt instructions.\n const text = await withMcpTools(\n agent.harness,\n sandbox,\n signal,\n agent.harness.tools,\n (tools, mcp) =>\n run(\n context.repair ? tools.filter((tool) => tool.readOnly) : tools,\n mcp,\n ),\n );\n signal.throwIfAborted();\n for (const value of [\n usage.input,\n usage.cached,\n usage.output,\n usage.cacheCreated ?? 0,\n ])\n invariant(\n Number.isSafeInteger(value) && value >= 0,\n \"Harness usage must contain nonnegative token counts\",\n );\n invariant(\n usage.cached + (usage.cacheCreated ?? 0) <= usage.input,\n \"Cached tokens must be included in input usage\",\n );\n notify(options.observe, {\n kind: \"result\",\n text,\n pass,\n at: new Date().toISOString(),\n });\n notify(options.observe, {\n kind: \"finished\",\n pass,\n at: new Date().toISOString(),\n });\n return {\n text,\n usage,\n status: 0,\n durationMs: Date.now() - start,\n ...(transcript ? { conversation: transcript.id } : {}),\n };\n } catch (error) {\n const reason = stopReason(options.signal, controller.signal.reason, error);\n if (reason)\n notify(options.observe, {\n kind: \"stopped\",\n reason,\n pass,\n at: new Date().toISOString(),\n });\n signal.throwIfAborted();\n throw error;\n } finally {\n await transcript?.close();\n controller.abort(new OutpostError(\"aborted\", \"Harness turn ended\"));\n clearTimeout(timer);\n watchdog.close();\n await Promise.allSettled([...pending]);\n }\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DecisionQuestions, DecisionResult } from "../domain/decision.types.ts";
|
|
2
|
+
import type { Task } from "../domain/workflow.types.ts";
|
|
3
|
+
import type { DecisionTaskOptions } from "./decision.types.ts";
|
|
4
|
+
export declare function defineDecisionTask<const Q extends DecisionQuestions>(options: DecisionTaskOptions<Q>): Task<DecisionResult<Q>>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineTask } from "../domain/workflow.js";
|
|
2
|
+
import { validateDecisionProvider, defineDecision, validateDecisionState, } from "../domain/decision.js";
|
|
3
|
+
import { invariant } from "../domain/errors.js";
|
|
4
|
+
import { executeDecision } from "./decision.js";
|
|
5
|
+
export function defineDecisionTask(options) {
|
|
6
|
+
const { provider, model, decision, state, allowTruncated, ...task } = options;
|
|
7
|
+
validateDecisionProvider(provider);
|
|
8
|
+
invariant(typeof model === "string" && model.trim(), "Decision model must be nonempty text");
|
|
9
|
+
invariant(decision?.kind === "decision", "Declare decisions with defineDecision");
|
|
10
|
+
const declared = defineDecision({ questions: decision.questions });
|
|
11
|
+
invariant(allowTruncated === undefined || typeof allowTruncated === "boolean", "Decision allowTruncated must be boolean");
|
|
12
|
+
if (typeof state !== "function")
|
|
13
|
+
validateDecisionState(state);
|
|
14
|
+
return defineTask({
|
|
15
|
+
...task,
|
|
16
|
+
async perform(context) {
|
|
17
|
+
return executeDecision({
|
|
18
|
+
provider,
|
|
19
|
+
model,
|
|
20
|
+
decision: declared,
|
|
21
|
+
state: typeof state === "function" ? await state(context) : state,
|
|
22
|
+
signal: context.signal,
|
|
23
|
+
...(context.observation ? { observation: context.observation } : {}),
|
|
24
|
+
...(allowTruncated === undefined ? {} : { allowTruncated }),
|
|
25
|
+
}, { account: (usage) => context.reportUsage(usage) });
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=decision-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-task.js","sourceRoot":"","sources":["../../src/application/decision-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAOhD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,UAAU,kBAAkB,CAChC,OAA+B;IAE/B,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAC9E,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACnC,SAAS,CACP,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EACzC,sCAAsC,CACvC,CAAC;IACF,SAAS,CACP,QAAQ,EAAE,IAAI,KAAK,UAAU,EAC7B,uCAAuC,CACxC,CAAC;IACF,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACnE,SAAS,CACP,cAAc,KAAK,SAAS,IAAI,OAAO,cAAc,KAAK,SAAS,EACnE,yCAAyC,CAC1C,CAAC;IACF,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,UAAU,CAAC;QAChB,GAAG,IAAI;QACP,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,OAAO,eAAe,CACpB;gBACE,QAAQ;gBACR,KAAK;gBACL,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK;gBACjE,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC;aAC5D,EACD,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CACnD,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { defineTask } from \"../domain/workflow.ts\";\nimport {\n validateDecisionProvider,\n defineDecision,\n validateDecisionState,\n} from \"../domain/decision.ts\";\nimport { invariant } from \"../domain/errors.ts\";\nimport type {\n DecisionQuestions,\n DecisionResult,\n} from \"../domain/decision.types.ts\";\nimport type { Task } from \"../domain/workflow.types.ts\";\nimport type { DecisionTaskOptions } from \"./decision.types.ts\";\nimport { executeDecision } from \"./decision.ts\";\n\nexport function defineDecisionTask<const Q extends DecisionQuestions>(\n options: DecisionTaskOptions<Q>,\n): Task<DecisionResult<Q>> {\n const { provider, model, decision, state, allowTruncated, ...task } = options;\n validateDecisionProvider(provider);\n invariant(\n typeof model === \"string\" && model.trim(),\n \"Decision model must be nonempty text\",\n );\n invariant(\n decision?.kind === \"decision\",\n \"Declare decisions with defineDecision\",\n );\n const declared = defineDecision({ questions: decision.questions });\n invariant(\n allowTruncated === undefined || typeof allowTruncated === \"boolean\",\n \"Decision allowTruncated must be boolean\",\n );\n if (typeof state !== \"function\") validateDecisionState(state);\n return defineTask({\n ...task,\n async perform(context) {\n return executeDecision(\n {\n provider,\n model,\n decision: declared,\n state: typeof state === \"function\" ? await state(context) : state,\n signal: context.signal,\n ...(context.observation ? { observation: context.observation } : {}),\n ...(allowTruncated === undefined ? {} : { allowTruncated }),\n },\n { account: (usage) => context.reportUsage(usage) },\n );\n },\n });\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DecideOptions, DecisionQuestions, DecisionResult } from "../domain/decision.types.ts";
|
|
2
|
+
import type { DecisionAccounting } from "./decision.types.ts";
|
|
3
|
+
export declare function decide<const Q extends DecisionQuestions>(options: DecideOptions<Q>): Promise<DecisionResult<Q>>;
|
|
4
|
+
export declare function executeDecision<Q extends DecisionQuestions>(options: DecideOptions<Q>, accounting?: DecisionAccounting): Promise<DecisionResult<Q>>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { OutpostError, invariant } from "../domain/errors.js";
|
|
2
|
+
import { defineDecision, validateDecisionState, validateDecisionProvider, } from "../domain/decision.js";
|
|
3
|
+
import { decisionAnswers, decisionUsage, requireDecisionResponse, } from "../domain/decision-result.js";
|
|
4
|
+
export function decide(options) {
|
|
5
|
+
return executeDecision(options);
|
|
6
|
+
}
|
|
7
|
+
export async function executeDecision(options, accounting) {
|
|
8
|
+
invariant(options && typeof options === "object", "Decision options must be an object");
|
|
9
|
+
validateDecisionProvider(options.provider);
|
|
10
|
+
invariant(typeof options.model === "string" && options.model.trim(), "Decision model must be nonempty text");
|
|
11
|
+
invariant(options.decision?.kind === "decision", "Declare decisions with defineDecision");
|
|
12
|
+
const decision = defineDecision({ questions: options.decision.questions });
|
|
13
|
+
invariant(options.allowTruncated === undefined ||
|
|
14
|
+
typeof options.allowTruncated === "boolean", "Decision allowTruncated must be boolean");
|
|
15
|
+
validateDecisionState(options.state);
|
|
16
|
+
options.signal?.throwIfAborted();
|
|
17
|
+
const start = Date.now();
|
|
18
|
+
const emit = options.observation;
|
|
19
|
+
const summary = {
|
|
20
|
+
kind: "decision",
|
|
21
|
+
provider: options.provider.name,
|
|
22
|
+
model: options.model,
|
|
23
|
+
};
|
|
24
|
+
emit?.emit("decision", { ...summary, status: "started" });
|
|
25
|
+
if (emit?.verbose)
|
|
26
|
+
emit.emit("decision", {
|
|
27
|
+
kind: "decision-request",
|
|
28
|
+
request: {
|
|
29
|
+
model: options.model,
|
|
30
|
+
state: options.state,
|
|
31
|
+
questions: decision.questions,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
let usage;
|
|
35
|
+
let truncated;
|
|
36
|
+
try {
|
|
37
|
+
const response = await options.provider.request({
|
|
38
|
+
model: options.model,
|
|
39
|
+
questions: decision.questions,
|
|
40
|
+
state: options.state,
|
|
41
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
42
|
+
});
|
|
43
|
+
requireDecisionResponse(response !== null && typeof response === "object");
|
|
44
|
+
usage = decisionUsage(response.usage);
|
|
45
|
+
if (typeof response.truncated === "boolean")
|
|
46
|
+
truncated = response.truncated;
|
|
47
|
+
accounting?.account(usage);
|
|
48
|
+
options.signal?.throwIfAborted();
|
|
49
|
+
const answers = decisionAnswers(decision.questions, response);
|
|
50
|
+
if (response.truncated && !options.allowTruncated)
|
|
51
|
+
throw new OutpostError("response", "Decision input was truncated", {
|
|
52
|
+
truncated: true,
|
|
53
|
+
});
|
|
54
|
+
const result = {
|
|
55
|
+
provider: options.provider.name,
|
|
56
|
+
model: response.model,
|
|
57
|
+
answers,
|
|
58
|
+
usage,
|
|
59
|
+
...(response.truncated === undefined
|
|
60
|
+
? {}
|
|
61
|
+
: { truncated: response.truncated }),
|
|
62
|
+
...(response.metadata === undefined
|
|
63
|
+
? {}
|
|
64
|
+
: { metadata: response.metadata }),
|
|
65
|
+
};
|
|
66
|
+
emit?.emit("decision", {
|
|
67
|
+
...summary,
|
|
68
|
+
model: result.model,
|
|
69
|
+
status: "finished",
|
|
70
|
+
usage,
|
|
71
|
+
durationMs: Date.now() - start,
|
|
72
|
+
...(result.truncated === undefined
|
|
73
|
+
? {}
|
|
74
|
+
: { truncated: result.truncated }),
|
|
75
|
+
});
|
|
76
|
+
if (emit?.verbose)
|
|
77
|
+
emit.emit("decision", { kind: "decision-response", response: result });
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (usage === undefined) {
|
|
82
|
+
usage = decisionUsage(undefined);
|
|
83
|
+
try {
|
|
84
|
+
accounting?.account(usage);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Failed-request accounting must preserve the original provider fault.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
emit?.emit("decision", {
|
|
91
|
+
...summary,
|
|
92
|
+
status: "failed",
|
|
93
|
+
durationMs: Date.now() - start,
|
|
94
|
+
usage,
|
|
95
|
+
...(truncated === undefined ? {} : { truncated }),
|
|
96
|
+
...(error instanceof OutpostError ? { code: error.code } : {}),
|
|
97
|
+
});
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/application/decision.ts"],"names":[],"mappings":"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","sourcesContent":["import { OutpostError, invariant } from \"../domain/errors.ts\";\nimport {\n defineDecision,\n validateDecisionState,\n validateDecisionProvider,\n} from \"../domain/decision.ts\";\nimport {\n decisionAnswers,\n decisionUsage,\n requireDecisionResponse,\n} from \"../domain/decision-result.ts\";\nimport type {\n DecideOptions,\n DecisionQuestions,\n DecisionResult,\n} from \"../domain/decision.types.ts\";\nimport type { DecisionAccounting } from \"./decision.types.ts\";\nimport type { Usage } from \"../domain/agent.types.ts\";\n\nexport function decide<const Q extends DecisionQuestions>(\n options: DecideOptions<Q>,\n): Promise<DecisionResult<Q>> {\n return executeDecision(options);\n}\n\nexport async function executeDecision<Q extends DecisionQuestions>(\n options: DecideOptions<Q>,\n accounting?: DecisionAccounting,\n): Promise<DecisionResult<Q>> {\n invariant(\n options && typeof options === \"object\",\n \"Decision options must be an object\",\n );\n validateDecisionProvider(options.provider);\n invariant(\n typeof options.model === \"string\" && options.model.trim(),\n \"Decision model must be nonempty text\",\n );\n invariant(\n options.decision?.kind === \"decision\",\n \"Declare decisions with defineDecision\",\n );\n const decision = defineDecision({ questions: options.decision.questions });\n invariant(\n options.allowTruncated === undefined ||\n typeof options.allowTruncated === \"boolean\",\n \"Decision allowTruncated must be boolean\",\n );\n validateDecisionState(options.state);\n options.signal?.throwIfAborted();\n const start = Date.now();\n const emit = options.observation;\n const summary = {\n kind: \"decision\" as const,\n provider: options.provider.name,\n model: options.model,\n };\n emit?.emit(\"decision\", { ...summary, status: \"started\" });\n if (emit?.verbose)\n emit.emit(\"decision\", {\n kind: \"decision-request\",\n request: {\n model: options.model,\n state: options.state,\n questions: decision.questions,\n },\n });\n let usage: Usage | undefined;\n let truncated: boolean | undefined;\n try {\n const response = await options.provider.request({\n model: options.model,\n questions: decision.questions,\n state: options.state,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n requireDecisionResponse(response !== null && typeof response === \"object\");\n usage = decisionUsage(response.usage);\n if (typeof response.truncated === \"boolean\") truncated = response.truncated;\n accounting?.account(usage);\n options.signal?.throwIfAborted();\n const answers = decisionAnswers(decision.questions, response);\n if (response.truncated && !options.allowTruncated)\n throw new OutpostError(\"response\", \"Decision input was truncated\", {\n truncated: true,\n });\n const result: DecisionResult<Q> = {\n provider: options.provider.name,\n model: response.model,\n answers,\n usage,\n ...(response.truncated === undefined\n ? {}\n : { truncated: response.truncated }),\n ...(response.metadata === undefined\n ? {}\n : { metadata: response.metadata }),\n };\n emit?.emit(\"decision\", {\n ...summary,\n model: result.model,\n status: \"finished\",\n usage,\n durationMs: Date.now() - start,\n ...(result.truncated === undefined\n ? {}\n : { truncated: result.truncated }),\n });\n if (emit?.verbose)\n emit.emit(\"decision\", { kind: \"decision-response\", response: result });\n return result;\n } catch (error) {\n if (usage === undefined) {\n usage = decisionUsage(undefined);\n try {\n accounting?.account(usage);\n } catch {\n // Failed-request accounting must preserve the original provider fault.\n }\n }\n emit?.emit(\"decision\", {\n ...summary,\n status: \"failed\",\n durationMs: Date.now() - start,\n usage,\n ...(truncated === undefined ? {} : { truncated }),\n ...(error instanceof OutpostError ? { code: error.code } : {}),\n });\n throw error;\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Usage } from "../domain/agent.types.ts";
|
|
2
|
+
import type { DecideOptions, DecisionQuestions } from "../domain/decision.types.ts";
|
|
3
|
+
import type { TaskContext, TaskOptions } from "../domain/workflow.types.ts";
|
|
4
|
+
import type { DecisionResult, DecisionState } from "../domain/decision.types.ts";
|
|
5
|
+
export type DecisionTaskOptions<Q extends DecisionQuestions = DecisionQuestions> = Omit<TaskOptions<DecisionResult<Q>>, "perform" | "gate" | "interaction"> & Omit<DecideOptions<Q>, "state" | "signal" | "observation"> & {
|
|
6
|
+
readonly state: DecisionState | ((context: TaskContext) => DecisionState | Promise<DecisionState>);
|
|
7
|
+
};
|
|
8
|
+
export interface DecisionAccounting {
|
|
9
|
+
account(usage: Usage): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.types.js","sourceRoot":"","sources":["../../src/application/decision.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Usage } from \"../domain/agent.types.ts\";\nimport type {\n DecideOptions,\n DecisionQuestions,\n} from \"../domain/decision.types.ts\";\nimport type { TaskContext, TaskOptions } from \"../domain/workflow.types.ts\";\nimport type {\n DecisionResult,\n DecisionState,\n} from \"../domain/decision.types.ts\";\n\nexport type DecisionTaskOptions<\n Q extends DecisionQuestions = DecisionQuestions,\n> = Omit<TaskOptions<DecisionResult<Q>>, \"perform\" | \"gate\" | \"interaction\"> &\n Omit<DecideOptions<Q>, \"state\" | \"signal\" | \"observation\"> & {\n readonly state:\n | DecisionState\n | ((context: TaskContext) => DecisionState | Promise<DecisionState>);\n };\n\nexport interface DecisionAccounting {\n account(usage: Usage): void;\n}\n"]}
|
|
@@ -37,6 +37,12 @@ export async function compact(runtime, history, step) {
|
|
|
37
37
|
async function summarize(runtime, messages) {
|
|
38
38
|
const result = await runtime.modelProvider.request({
|
|
39
39
|
model: runtime.agent.model.name,
|
|
40
|
+
...(runtime.agent.model.reasoning === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: { reasoning: runtime.agent.model.reasoning }),
|
|
43
|
+
...(runtime.agent.model.maxOutputTokens === undefined
|
|
44
|
+
? {}
|
|
45
|
+
: { maxOutputTokens: runtime.agent.model.maxOutputTokens }),
|
|
40
46
|
system: SUMMARY_INSTRUCTIONS,
|
|
41
47
|
prompt: messages.map(render).join("\n\n") || "(no earlier messages)",
|
|
42
48
|
});
|