@ai-sdk/harness 0.0.0 → 1.0.0-canary.3
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 +24 -0
- package/LICENSE +13 -0
- package/README.md +142 -0
- package/agent/index.ts +17 -0
- package/bridge/index.ts +10 -0
- package/dist/agent/index.d.ts +1480 -0
- package/dist/agent/index.js +2554 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/bridge/index.d.ts +111 -0
- package/dist/bridge/index.js +414 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/index.d.ts +1510 -0
- package/dist/index.js +15834 -0
- package/dist/index.js.map +1 -0
- package/dist/observability/index.d.ts +97 -0
- package/dist/observability/index.js +225 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/utils/index.d.ts +196 -0
- package/dist/utils/index.js +327 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +104 -1
- package/src/agent/harness-agent-session.ts +352 -0
- package/src/agent/harness-agent-settings.ts +131 -0
- package/src/agent/harness-agent-tool-approval-continuation.ts +94 -0
- package/src/agent/harness-agent.ts +750 -0
- package/src/agent/harness-diagnostics.ts +88 -0
- package/src/agent/internal/bootstrap-recipe.ts +124 -0
- package/src/agent/internal/bridge-port-registry.ts +52 -0
- package/src/agent/internal/harness-stream-text-result.ts +720 -0
- package/src/agent/internal/permission-mode.ts +50 -0
- package/src/agent/internal/resolve-observability.ts +128 -0
- package/src/agent/internal/resume-state-validation.ts +51 -0
- package/src/agent/internal/run-prompt.ts +811 -0
- package/src/agent/internal/strip-work-dir.ts +68 -0
- package/src/agent/internal/to-harness-stream.ts +75 -0
- package/src/agent/internal/translate-stream-part.ts +221 -0
- package/src/agent/internal/turn-telemetry.ts +359 -0
- package/src/agent/prewarm.ts +46 -0
- package/src/bridge/index.ts +700 -0
- package/src/errors/harness-capability-unsupported-error.ts +41 -0
- package/src/errors/harness-error.ts +22 -0
- package/src/index.ts +3 -0
- package/src/observability/file-reporter.ts +209 -0
- package/src/observability/index.ts +13 -0
- package/src/observability/trace-tree-reporter.ts +122 -0
- package/src/utils/classify-disk-log.ts +43 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/sandbox-channel.ts +453 -0
- package/src/v1/harness-v1-bootstrap.ts +46 -0
- package/src/v1/harness-v1-bridge-protocol.ts +310 -0
- package/src/v1/harness-v1-builtin-tool.ts +138 -0
- package/src/v1/harness-v1-call-warning.ts +22 -0
- package/src/v1/harness-v1-diagnostic.ts +66 -0
- package/src/v1/harness-v1-metadata.ts +13 -0
- package/src/v1/harness-v1-network-sandbox-session.ts +123 -0
- package/src/v1/harness-v1-observability.ts +20 -0
- package/src/v1/harness-v1-permission-mode.ts +11 -0
- package/src/v1/harness-v1-prompt-control.ts +41 -0
- package/src/v1/harness-v1-prompt.ts +11 -0
- package/src/v1/harness-v1-resume-state.ts +46 -0
- package/src/v1/harness-v1-sandbox-provider.ts +76 -0
- package/src/v1/harness-v1-session.ts +268 -0
- package/src/v1/harness-v1-skill.ts +22 -0
- package/src/v1/harness-v1-stream-part.ts +363 -0
- package/src/v1/harness-v1-tool-spec.ts +31 -0
- package/src/v1/harness-v1.ts +83 -0
- package/src/v1/index.ts +93 -0
- package/utils/index.ts +1 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baseline permission mode for adapter-native built-in tools.
|
|
3
|
+
*
|
|
4
|
+
* Custom host-executed tools are not controlled by this setting. They use
|
|
5
|
+
* `HarnessAgentSettings.toolApproval`, similar to AI SDK's per-tool approval
|
|
6
|
+
* status map.
|
|
7
|
+
*/
|
|
8
|
+
export type HarnessV1PermissionMode =
|
|
9
|
+
| 'allow-reads'
|
|
10
|
+
| 'allow-edits'
|
|
11
|
+
| 'allow-all';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bidirectional control surface returned by `doPromptTurn`.
|
|
3
|
+
*
|
|
4
|
+
* The host uses these methods to feed asynchronous responses back to the
|
|
5
|
+
* adapter while a turn is running. All methods are optional except those
|
|
6
|
+
* the adapter actively supports (host-executed tools require
|
|
7
|
+
* `submitToolResult`; approvals require `submitToolApproval`; mid-turn
|
|
8
|
+
* messages require `submitUserMessage`).
|
|
9
|
+
*/
|
|
10
|
+
export type HarnessV1PromptControl = {
|
|
11
|
+
/**
|
|
12
|
+
* Provide a result for a `tool-call` the adapter emitted. The adapter
|
|
13
|
+
* forwards the result to the underlying runtime so the model can continue.
|
|
14
|
+
*/
|
|
15
|
+
submitToolResult(input: {
|
|
16
|
+
toolCallId: string;
|
|
17
|
+
output: unknown;
|
|
18
|
+
isError?: boolean;
|
|
19
|
+
}): PromiseLike<void>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Respond to a `tool-approval-request` the adapter emitted.
|
|
23
|
+
*/
|
|
24
|
+
submitToolApproval?(input: {
|
|
25
|
+
approvalId: string;
|
|
26
|
+
approved: boolean;
|
|
27
|
+
reason?: string;
|
|
28
|
+
}): PromiseLike<void>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Inject a fresh user message into a turn that is still in flight.
|
|
32
|
+
* Supported only by runtimes that accept interactive input.
|
|
33
|
+
*/
|
|
34
|
+
submitUserMessage?(text: string): PromiseLike<void>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolves when the adapter has finished the turn (success or failure).
|
|
38
|
+
* Rejects with the underlying error when the turn fails.
|
|
39
|
+
*/
|
|
40
|
+
readonly done: PromiseLike<void>;
|
|
41
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UserModelMessage } from '@ai-sdk/provider-utils';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Prompt shape passed to `HarnessV1Session.doPromptTurn`.
|
|
5
|
+
*
|
|
6
|
+
* A harness session represents an ongoing third-party agent runtime that
|
|
7
|
+
* owns its own conversation history. Each prompt turn carries only the
|
|
8
|
+
* fresh user input for that turn, either as a plain string or as a single
|
|
9
|
+
* `UserModelMessage`.
|
|
10
|
+
*/
|
|
11
|
+
export type HarnessV1Prompt = string | UserModelMessage;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { JSONValue } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
export type HarnessV1PendingToolApproval = {
|
|
4
|
+
readonly approvalId: string;
|
|
5
|
+
readonly toolCallId: string;
|
|
6
|
+
readonly toolName: string;
|
|
7
|
+
readonly input: string;
|
|
8
|
+
readonly kind: 'builtin' | 'custom';
|
|
9
|
+
readonly providerExecuted?: boolean;
|
|
10
|
+
readonly nativeName?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Opaque payload returned by resumable session lifecycle methods and accepted
|
|
15
|
+
* by a future `HarnessV1.doStart({ resumeFrom })` to resume the same
|
|
16
|
+
* underlying session.
|
|
17
|
+
*
|
|
18
|
+
* The contents are entirely adapter-defined. Consumers (including
|
|
19
|
+
* `HarnessAgent`) treat the value as opaque; adapters describe and validate
|
|
20
|
+
* their own schemas via `HarnessV1.resumeStateSchema`.
|
|
21
|
+
*/
|
|
22
|
+
export type HarnessV1ResumeState = {
|
|
23
|
+
/**
|
|
24
|
+
* Identifier of the harness that produced this state. Used by adapters to
|
|
25
|
+
* refuse mismatched resume payloads.
|
|
26
|
+
*/
|
|
27
|
+
readonly harnessId: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Spec version of the harness that produced this state.
|
|
31
|
+
*/
|
|
32
|
+
readonly specificationVersion: 'harness-v1';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Adapter-defined payload. May be persisted as JSON; the adapter is
|
|
36
|
+
* responsible for any necessary encoding.
|
|
37
|
+
*/
|
|
38
|
+
readonly data: JSONValue;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Framework-owned pending approval records. These are intentionally outside
|
|
42
|
+
* adapter-defined `data` so callers can persist the entire resume payload
|
|
43
|
+
* without the harness framework owning storage.
|
|
44
|
+
*/
|
|
45
|
+
readonly pendingToolApprovals?: readonly HarnessV1PendingToolApproval[];
|
|
46
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Experimental_SandboxSession as SandboxSession } from '@ai-sdk/provider-utils';
|
|
2
|
+
import type { HarnessV1NetworkSandboxSession } from './harness-v1-network-sandbox-session';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Provider that produces network sandbox sessions for harness sessions. Lives at
|
|
6
|
+
* module scope as a stable, synchronous object — analogous to
|
|
7
|
+
* `LanguageModelV4` providers, no I/O performed at construction. The actual
|
|
8
|
+
* sandbox is created (or wrapped) when `HarnessAgent` calls `createSession()`.
|
|
9
|
+
*/
|
|
10
|
+
export interface HarnessV1SandboxProvider {
|
|
11
|
+
readonly specificationVersion: 'harness-sandbox-v1';
|
|
12
|
+
readonly providerId: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Pool of ports the consumer reserved on a caller-provided sandbox for
|
|
16
|
+
* concurrent harness sessions. The session manager leases one port per
|
|
17
|
+
* session and releases on stop or destroy.
|
|
18
|
+
*
|
|
19
|
+
* Only meaningful when the provider wraps a caller-provided sandbox
|
|
20
|
+
* (the caller pre-declared the ports). In create-new modes the provider
|
|
21
|
+
* mints a fresh sandbox per session, so no leasing is needed; providers
|
|
22
|
+
* leave this undefined.
|
|
23
|
+
*/
|
|
24
|
+
readonly bridgePorts?: ReadonlyArray<number>;
|
|
25
|
+
|
|
26
|
+
readonly createSession: (options?: {
|
|
27
|
+
/**
|
|
28
|
+
* Stable per-session identifier. When supplied, the provider names the
|
|
29
|
+
* underlying resource deterministically so a future call to `resume`
|
|
30
|
+
* (potentially from a different process) can find the same sandbox.
|
|
31
|
+
* Omitted from prewarm and other paths that don't need a resumable
|
|
32
|
+
* resource — in that case the provider falls back to its native
|
|
33
|
+
* auto-naming.
|
|
34
|
+
*/
|
|
35
|
+
sessionId?: string;
|
|
36
|
+
abortSignal?: AbortSignal;
|
|
37
|
+
/**
|
|
38
|
+
* Stable identity for snapshot-based reuse. Providers that support
|
|
39
|
+
* persistence/snapshots use this as part of the persistent sandbox
|
|
40
|
+
* name; subsequent calls with the same identity resume from snapshot.
|
|
41
|
+
*
|
|
42
|
+
* Ignored when the provider is wrapping a caller-provided sandbox.
|
|
43
|
+
*/
|
|
44
|
+
identity?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Called exactly once per identity, on fresh creation. Snapshot-capable
|
|
47
|
+
* providers wire this into the platform's one-time-setup hook so the
|
|
48
|
+
* side effects are baked into the snapshot. Providers without snapshot
|
|
49
|
+
* support run it immediately after fresh create.
|
|
50
|
+
*
|
|
51
|
+
* Not called when the provider is wrapping a caller-provided sandbox
|
|
52
|
+
* (the caller owns the sandbox; the framework applies its own
|
|
53
|
+
* idempotent bootstrap post-create instead).
|
|
54
|
+
*/
|
|
55
|
+
onFirstCreate?: (
|
|
56
|
+
session: SandboxSession,
|
|
57
|
+
opts: { abortSignal?: AbortSignal },
|
|
58
|
+
) => Promise<void>;
|
|
59
|
+
}) => PromiseLike<HarnessV1NetworkSandboxSession>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Reattach to an existing sandbox previously created with the same
|
|
63
|
+
* `sessionId`. Optional — providers that cannot rehydrate by id (e.g.
|
|
64
|
+
* just-bash) omit this; the harness throws
|
|
65
|
+
* `HarnessCapabilityUnsupportedError` when resume is attempted against
|
|
66
|
+
* them.
|
|
67
|
+
*
|
|
68
|
+
* The provider derives the sandbox identifier from `sessionId` using the
|
|
69
|
+
* same deterministic naming scheme it used in `createSession`. Returns a
|
|
70
|
+
* network sandbox session bound to the existing resource.
|
|
71
|
+
*/
|
|
72
|
+
readonly resumeSession?: (options: {
|
|
73
|
+
sessionId: string;
|
|
74
|
+
abortSignal?: AbortSignal;
|
|
75
|
+
}) => PromiseLike<HarnessV1NetworkSandboxSession>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import type { HarnessV1NetworkSandboxSession } from './harness-v1-network-sandbox-session';
|
|
2
|
+
import type { HarnessV1Observability } from './harness-v1-observability';
|
|
3
|
+
import type { HarnessV1PermissionMode } from './harness-v1-permission-mode';
|
|
4
|
+
import type { HarnessV1Prompt } from './harness-v1-prompt';
|
|
5
|
+
import type { HarnessV1PromptControl } from './harness-v1-prompt-control';
|
|
6
|
+
import type { HarnessV1ResumeState } from './harness-v1-resume-state';
|
|
7
|
+
import type { HarnessV1Skill } from './harness-v1-skill';
|
|
8
|
+
import type { HarnessV1StreamPart } from './harness-v1-stream-part';
|
|
9
|
+
import type { HarnessV1ToolSpec } from './harness-v1-tool-spec';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Options passed to `HarnessV1.doStart`.
|
|
13
|
+
*
|
|
14
|
+
* `sandboxSession` and `sessionWorkDir` are coupled and always present. The
|
|
15
|
+
* framework creates the sandbox and per-session working directory before
|
|
16
|
+
* calling the adapter, so adapters never need to derive provider-specific paths.
|
|
17
|
+
*/
|
|
18
|
+
export type HarnessV1StartOptions = {
|
|
19
|
+
/**
|
|
20
|
+
* Stable identifier for this harness session. Used as the underlying
|
|
21
|
+
* resource name where the adapter has a notion of a named session
|
|
22
|
+
* (sandbox name, native session id, …).
|
|
23
|
+
*/
|
|
24
|
+
readonly sessionId: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Skills made available to the underlying runtime for the lifetime of
|
|
28
|
+
* the session. Adapters decide how to surface them — the `claude` CLI
|
|
29
|
+
* picks them up from `.claude/skills/*.md`, while the `codex` adapter
|
|
30
|
+
* inlines them into every user message.
|
|
31
|
+
*/
|
|
32
|
+
readonly skills?: ReadonlyArray<HarnessV1Skill>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Optional resume payload returned by a prior session lifecycle method. When
|
|
36
|
+
* provided, the adapter should resume the existing session rather than create
|
|
37
|
+
* a fresh one.
|
|
38
|
+
*/
|
|
39
|
+
readonly resumeFrom?: HarnessV1ResumeState;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Approval policy for built-in adapter-native tool use. Custom host-executed
|
|
43
|
+
* tools are approved by the framework before results are submitted back to
|
|
44
|
+
* the adapter.
|
|
45
|
+
*/
|
|
46
|
+
readonly permissionMode?: HarnessV1PermissionMode;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Signal that aborts startup. The adapter must propagate cancellation to
|
|
50
|
+
* any spawned processes or network calls.
|
|
51
|
+
*/
|
|
52
|
+
readonly abortSignal?: AbortSignal;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Diagnostics wiring. The framework populates this; the adapter only
|
|
56
|
+
* forwards `observability.onDiagnostic` into its `SandboxChannel` and
|
|
57
|
+
* `observability.debug` into the bridge `start` message. Absent when the
|
|
58
|
+
* consumer has not enabled diagnostics.
|
|
59
|
+
*/
|
|
60
|
+
readonly observability?: HarnessV1Observability;
|
|
61
|
+
/**
|
|
62
|
+
* Network sandbox session the adapter operates against. It is owned and
|
|
63
|
+
* lifecycled by `HarnessAgent`. Adapters call `restricted()` for the
|
|
64
|
+
* tool-safe filesystem/exec/spawn surface, and use the infra methods
|
|
65
|
+
* (`getPortUrl`, `ports`, `setNetworkPolicy`) for bridge wiring. Adapters
|
|
66
|
+
* must not call `stop()` themselves; the agent does that during cleanup.
|
|
67
|
+
*/
|
|
68
|
+
readonly sandboxSession: HarnessV1NetworkSandboxSession;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Absolute path the adapter runs the agent in for this session. Composed by
|
|
72
|
+
* the framework as `<sandboxSession.defaultWorkingDirectory>/<harnessId>-<sessionId>`
|
|
73
|
+
* and created before `doStart`, so the adapter uses it directly instead of
|
|
74
|
+
* deriving its own provider-specific path.
|
|
75
|
+
*/
|
|
76
|
+
readonly sessionWorkDir: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Options passed to `HarnessV1Session.doPromptTurn`.
|
|
81
|
+
*/
|
|
82
|
+
export type HarnessV1PromptTurnOptions = {
|
|
83
|
+
/**
|
|
84
|
+
* Fresh input for this turn — either a plain string or a single
|
|
85
|
+
* `ModelMessage`. The harness session owns its own conversation history,
|
|
86
|
+
* so prior turns are never replayed across the contract.
|
|
87
|
+
*/
|
|
88
|
+
readonly prompt: HarnessV1Prompt;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Host-defined tools to make available to the underlying runtime for this
|
|
92
|
+
* turn. The harness emits `tool-call` events when the runtime calls one
|
|
93
|
+
* and waits for `submitToolResult`.
|
|
94
|
+
*/
|
|
95
|
+
readonly tools?: ReadonlyArray<HarnessV1ToolSpec>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Free-form instructions for the session. The framework supplies the same
|
|
99
|
+
* value on every turn; the adapter is responsible for applying it once, by
|
|
100
|
+
* prepending it to the first user message of a fresh (non-resumed) session.
|
|
101
|
+
* On a resumed session the adapter must not re-apply it — the original first
|
|
102
|
+
* message already carried it and lives in the runtime's persisted history.
|
|
103
|
+
*/
|
|
104
|
+
readonly instructions?: string;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Signal that aborts the in-flight turn. The adapter must cancel any
|
|
108
|
+
* underlying work and resolve `done` (with an error if appropriate).
|
|
109
|
+
*/
|
|
110
|
+
readonly abortSignal?: AbortSignal;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Callback invoked once for each event the adapter produces during the
|
|
114
|
+
* turn. The adapter is responsible for the ordering and completeness of
|
|
115
|
+
* events. `done` resolves once the adapter has emitted all events for the
|
|
116
|
+
* turn (success or failure).
|
|
117
|
+
*/
|
|
118
|
+
readonly emit: (event: HarnessV1StreamPart) => void;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export type HarnessV1PromptOptions = HarnessV1PromptTurnOptions;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Options passed to `HarnessV1Session.doContinueTurn`.
|
|
125
|
+
*
|
|
126
|
+
* Unlike `doPromptTurn`, there is no `prompt`: `doContinueTurn` continues the
|
|
127
|
+
* in-flight turn rather than starting a new one. It is used to continue a turn
|
|
128
|
+
* that was previously suspended temporarily, e.g. by the workflow slice loop.
|
|
129
|
+
*/
|
|
130
|
+
export type HarnessV1ContinueTurnOptions = {
|
|
131
|
+
/**
|
|
132
|
+
* Host-defined tools to make available for the continued turn. Same shape
|
|
133
|
+
* as `doPromptTurn`'s `tools`. An adapter that purely attaches to a live turn
|
|
134
|
+
* may ignore them; an adapter that re-drives the turn (rerun) needs them.
|
|
135
|
+
*/
|
|
136
|
+
readonly tools?: ReadonlyArray<HarnessV1ToolSpec>;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Signal that aborts the continued turn. The adapter must cancel any
|
|
140
|
+
* underlying work and resolve `done` (with an error if appropriate).
|
|
141
|
+
*/
|
|
142
|
+
readonly abortSignal?: AbortSignal;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Callback invoked once for each event the adapter produces while the
|
|
146
|
+
* continued turn runs. Same contract as `doPromptTurn`'s `emit`.
|
|
147
|
+
*/
|
|
148
|
+
readonly emit: (event: HarnessV1StreamPart) => void;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export type HarnessV1ContinueOptions = HarnessV1ContinueTurnOptions;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Active harness session, returned by `HarnessV1.doStart`.
|
|
155
|
+
*
|
|
156
|
+
* A session is the unit of state continuity across multiple prompts (one
|
|
157
|
+
* sandbox, one conversation history, one running agent runtime). The host
|
|
158
|
+
* holds onto the session across `doPromptTurn` calls and ends the local
|
|
159
|
+
* instance via `doDetach`, `doStop`, or `doDestroy`.
|
|
160
|
+
*/
|
|
161
|
+
export type HarnessV1Session = {
|
|
162
|
+
/**
|
|
163
|
+
* Stable identifier for this session. Same value the host passed in via
|
|
164
|
+
* `HarnessV1StartOptions.sessionId`.
|
|
165
|
+
*/
|
|
166
|
+
readonly sessionId: string;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Whether this session was created from a resume payload. Fresh sessions
|
|
170
|
+
* report `false`; resumed sessions report `true`.
|
|
171
|
+
*/
|
|
172
|
+
readonly isResume: boolean;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* The model id the underlying runtime is configured to use, if the adapter
|
|
176
|
+
* knows it (e.g. from its settings). Surfaced into telemetry as
|
|
177
|
+
* `gen_ai.request.model` and the trace span labels. Omitted when the adapter
|
|
178
|
+
* defers to the runtime's own default and has no concrete id.
|
|
179
|
+
*/
|
|
180
|
+
readonly modelId?: string;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Run one prompt turn. Returns a control handle the host uses to feed
|
|
184
|
+
* tool results, approvals, and user messages back into the turn while it
|
|
185
|
+
* is in flight. The handle's `done` promise resolves when the turn ends.
|
|
186
|
+
*/
|
|
187
|
+
doPromptTurn(
|
|
188
|
+
options: HarnessV1PromptTurnOptions,
|
|
189
|
+
): PromiseLike<HarnessV1PromptControl>;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Request that the underlying runtime compact its context. The runtime owns
|
|
193
|
+
* the compaction — the harness neither implements nor schedules it; this is
|
|
194
|
+
* only the trigger. When compaction completes, the adapter surfaces a
|
|
195
|
+
* `compaction` stream part on the next/active turn.
|
|
196
|
+
*
|
|
197
|
+
* Required, but not every runtime can honour it: adapters whose transport
|
|
198
|
+
* exposes no manual compaction (e.g. Codex over `codex exec`, which still
|
|
199
|
+
* auto-compacts on its own) throw `HarnessCapabilityUnsupportedError`.
|
|
200
|
+
* `customInstructions`, when supported, steer the compaction summary.
|
|
201
|
+
*/
|
|
202
|
+
doCompact(customInstructions?: string): PromiseLike<void>;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Continue the in-flight turn **without a new user prompt**, returning the
|
|
206
|
+
* same control surface as `doPromptTurn`. Used to keep consuming a turn that
|
|
207
|
+
* was interrupted at a process boundary (the workflow slice loop), after the
|
|
208
|
+
* session itself has been resumed via `doStart({ resumeFrom })`:
|
|
209
|
+
*
|
|
210
|
+
* - When the runtime's turn is still live and reachable (bridge `attach` /
|
|
211
|
+
* `replay`), the adapter subscribes to its events and resolves `done` on
|
|
212
|
+
* the turn's `finish` — **without** re-driving it. Lossless.
|
|
213
|
+
* - When the live turn is gone (bridge respawned `rerun`, or a host-resident
|
|
214
|
+
* runtime like Pi whose turn cannot survive its process), the adapter
|
|
215
|
+
* re-drives the runtime's own thread from its persisted state. Lossy: work
|
|
216
|
+
* in flight at the interruption is recomputed.
|
|
217
|
+
*
|
|
218
|
+
* Required on every adapter. The behaviour an adapter can guarantee follows
|
|
219
|
+
* from its architecture; the contract is uniform.
|
|
220
|
+
*/
|
|
221
|
+
doContinueTurn(
|
|
222
|
+
options: HarnessV1ContinueTurnOptions,
|
|
223
|
+
): PromiseLike<HarnessV1PromptControl>;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Gracefully freeze the active turn **at a precise cursor while keeping the
|
|
227
|
+
* runtime alive**, returning the resume payload.
|
|
228
|
+
*
|
|
229
|
+
* This is the slice-boundary primitive. The adapter stops host-side
|
|
230
|
+
* consumption of the in-flight turn without telling the runtime to stop:
|
|
231
|
+
* for a bridge adapter it closes the host socket (the bridge keeps the turn
|
|
232
|
+
* running and accumulates events for replay) and resolves the active
|
|
233
|
+
* `doPromptTurn`/`doContinueTurn` `done` **cleanly** (not as an error) once buffered
|
|
234
|
+
* events have drained, so the cursor in the returned state equals the last
|
|
235
|
+
* event delivered to the host — guaranteeing the next slice's attach replays
|
|
236
|
+
* with no gap and no duplicate. A host-resident adapter (Pi) cannot keep its
|
|
237
|
+
* turn alive, so it persists what it can and the in-flight tail is recomputed
|
|
238
|
+
* on continue.
|
|
239
|
+
*
|
|
240
|
+
* Like `doDetach`, the sandbox/runtime is left running. Unlike `doDetach`,
|
|
241
|
+
* this is for an active turn at a slice boundary rather than a between-turn
|
|
242
|
+
* session handoff. Required on every adapter.
|
|
243
|
+
*/
|
|
244
|
+
doSuspendTurn(): PromiseLike<HarnessV1ResumeState>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Detach from the underlying runtime without tearing it down, returning a
|
|
248
|
+
* payload the host can later pass to `HarnessV1.doStart({ resumeFrom })`
|
|
249
|
+
* to reconnect. After `doDetach`, no further methods on this session
|
|
250
|
+
* instance may be called.
|
|
251
|
+
*
|
|
252
|
+
* Required. Adapters that cannot keep a live runtime parked still return the
|
|
253
|
+
* best resume state they can while leaving the sandbox running.
|
|
254
|
+
*/
|
|
255
|
+
doDetach(): PromiseLike<HarnessV1ResumeState>;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Persist enough state to resume later, then stop the underlying runtime.
|
|
259
|
+
* After `doStop`, no further methods on this session instance may be called.
|
|
260
|
+
*/
|
|
261
|
+
doStop(): PromiseLike<HarnessV1ResumeState>;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Stop the underlying runtime without returning resume state. After
|
|
265
|
+
* `doDestroy`, no further methods on this session instance may be called.
|
|
266
|
+
*/
|
|
267
|
+
doDestroy(): PromiseLike<void>;
|
|
268
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A self-contained instruction bundle the underlying runtime can load into
|
|
3
|
+
* its context. Adapters decide how to surface skills to the runtime — the
|
|
4
|
+
* `claude` CLI auto-discovers skills materialised as Markdown files in
|
|
5
|
+
* `.claude/skills`, while the `codex` CLI has no skill mechanism and the
|
|
6
|
+
* adapter inlines them into every user message.
|
|
7
|
+
*/
|
|
8
|
+
export type HarnessV1Skill = {
|
|
9
|
+
/** Stable identifier for the skill (kebab-case slug). */
|
|
10
|
+
readonly name: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Short, model-facing description. For runtimes that auto-select skills
|
|
14
|
+
* (Claude Code), this is what the runtime sees to decide whether the
|
|
15
|
+
* skill is relevant; for runtimes that load every skill on every turn
|
|
16
|
+
* (Codex), it appears alongside the content.
|
|
17
|
+
*/
|
|
18
|
+
readonly description: string;
|
|
19
|
+
|
|
20
|
+
/** Full skill content the model loads when the skill is active. */
|
|
21
|
+
readonly content: string;
|
|
22
|
+
};
|