@cleocode/contracts 2026.6.12 → 2026.6.13
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/dist/__tests__/operation-def.test.js +2 -1
- package/dist/__tests__/operation-def.test.js.map +1 -1
- package/dist/__tests__/sealed-credential.test.d.ts +19 -0
- package/dist/__tests__/sealed-credential.test.d.ts.map +1 -0
- package/dist/__tests__/sealed-credential.test.js +74 -0
- package/dist/__tests__/sealed-credential.test.js.map +1 -0
- package/dist/__tests__/skill-executor-contract.test.js +3 -0
- package/dist/__tests__/skill-executor-contract.test.js.map +1 -1
- package/dist/acceptance-gate.d.ts +2 -3
- package/dist/acceptance-gate.d.ts.map +1 -1
- package/dist/boundary.d.ts.map +1 -1
- package/dist/boundary.js +1 -19
- package/dist/boundary.js.map +1 -1
- package/dist/config.d.ts +102 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/data-accessor.d.ts +21 -1
- package/dist/data-accessor.d.ts.map +1 -1
- package/dist/data-accessor.js.map +1 -1
- package/dist/dispatch/identity.d.ts +1 -1
- package/dist/dispatch/identity.d.ts.map +1 -1
- package/dist/dispatch/identity.js +5 -0
- package/dist/dispatch/identity.js.map +1 -1
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +46 -168
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/docs/read.d.ts +2 -2
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lease-ipc/__tests__/freeze.test.d.ts +15 -0
- package/dist/lease-ipc/__tests__/freeze.test.d.ts.map +1 -0
- package/dist/lease-ipc/__tests__/freeze.test.js +221 -0
- package/dist/lease-ipc/__tests__/freeze.test.js.map +1 -0
- package/dist/lease-ipc/index.d.ts +17 -0
- package/dist/lease-ipc/index.d.ts.map +1 -0
- package/dist/lease-ipc/index.js +16 -0
- package/dist/lease-ipc/index.js.map +1 -0
- package/dist/lease-ipc/messages.d.ts +754 -0
- package/dist/lease-ipc/messages.d.ts.map +1 -0
- package/dist/lease-ipc/messages.js +383 -0
- package/dist/lease-ipc/messages.js.map +1 -0
- package/dist/lease-ipc/version.d.ts +41 -0
- package/dist/lease-ipc/version.d.ts.map +1 -0
- package/dist/lease-ipc/version.js +43 -0
- package/dist/lease-ipc/version.js.map +1 -0
- package/dist/llm/interfaces.d.ts +23 -0
- package/dist/llm/interfaces.d.ts.map +1 -1
- package/dist/llm/sealed-credential.d.ts +164 -0
- package/dist/llm/sealed-credential.d.ts.map +1 -0
- package/dist/llm/sealed-credential.js +43 -0
- package/dist/llm/sealed-credential.js.map +1 -0
- package/dist/llm/system-of-use.d.ts +383 -0
- package/dist/llm/system-of-use.d.ts.map +1 -0
- package/dist/llm/system-of-use.js +238 -0
- package/dist/llm/system-of-use.js.map +1 -0
- package/dist/llm/system-resolver.d.ts +45 -11
- package/dist/llm/system-resolver.d.ts.map +1 -1
- package/dist/llm/system-resolver.js +14 -7
- package/dist/llm/system-resolver.js.map +1 -1
- package/dist/operations/__tests__/ensures-schema-registry.test.d.ts +17 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.d.ts.map +1 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.js +113 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.js.map +1 -0
- package/dist/operations/ensures-schema-registry.d.ts +172 -0
- package/dist/operations/ensures-schema-registry.d.ts.map +1 -0
- package/dist/operations/ensures-schema-registry.js +226 -0
- package/dist/operations/ensures-schema-registry.js.map +1 -0
- package/dist/operations/llm.d.ts +101 -9
- package/dist/operations/llm.d.ts.map +1 -1
- package/dist/operations/validate.d.ts +1 -12
- package/dist/operations/validate.d.ts.map +1 -1
- package/dist/operations/validate.js +1 -1
- package/dist/playbook.d.ts +60 -0
- package/dist/playbook.d.ts.map +1 -1
- package/dist/session.d.ts +11 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/templates/manifest.d.ts +1 -1
- package/dist/tools/agent-tools.d.ts +231 -0
- package/dist/tools/agent-tools.d.ts.map +1 -0
- package/dist/tools/agent-tools.js +25 -0
- package/dist/tools/agent-tools.js.map +1 -0
- package/dist/tools/atomic.d.ts +19 -0
- package/dist/tools/atomic.d.ts.map +1 -1
- package/dist/tools/atomic.js +17 -0
- package/dist/tools/atomic.js.map +1 -1
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/skill-executor.d.ts +7 -0
- package/dist/tools/skill-executor.d.ts.map +1 -1
- package/dist/tools/web-tools.d.ts +217 -0
- package/dist/tools/web-tools.d.ts.map +1 -0
- package/dist/tools/web-tools.js +31 -0
- package/dist/tools/web-tools.js.map +1 -0
- package/package.json +6 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/__tests__/operation-def.test.ts +2 -1
- package/src/__tests__/sealed-credential.test.ts +100 -0
- package/src/__tests__/skill-executor-contract.test.ts +3 -0
- package/src/acceptance-gate.ts +2 -3
- package/src/boundary.ts +1 -20
- package/src/config.ts +104 -0
- package/src/data-accessor.ts +22 -1
- package/src/dispatch/identity.ts +5 -0
- package/src/dispatch/operations-registry.ts +51 -170
- package/src/index.ts +103 -24
- package/src/lease-ipc/__tests__/freeze.test.ts +246 -0
- package/src/lease-ipc/index.ts +63 -0
- package/src/lease-ipc/messages.ts +471 -0
- package/src/lease-ipc/version.ts +46 -0
- package/src/llm/interfaces.ts +23 -0
- package/src/llm/sealed-credential.ts +166 -0
- package/src/llm/system-of-use.ts +503 -0
- package/src/llm/system-resolver.ts +46 -11
- package/src/operations/__tests__/ensures-schema-registry.test.ts +169 -0
- package/src/operations/ensures-schema-registry.ts +260 -0
- package/src/operations/llm.ts +105 -8
- package/src/operations/validate.ts +1 -14
- package/src/playbook.ts +61 -0
- package/src/session.ts +11 -0
- package/src/tools/agent-tools.ts +270 -0
- package/src/tools/atomic.ts +21 -0
- package/src/tools/index.ts +46 -0
- package/src/tools/skill-executor.ts +7 -0
- package/src/tools/web-tools.ts +247 -0
- package/dist/tessera.d.ts +0 -32
- package/dist/tessera.d.ts.map +0 -1
- package/dist/tessera.js +0 -11
- package/dist/tessera.js.map +0 -1
- package/dist/warp-chain.d.ts +0 -129
- package/dist/warp-chain.d.ts.map +0 -1
- package/dist/warp-chain.js +0 -13
- package/dist/warp-chain.js.map +0 -1
- package/src/tessera.ts +0 -35
- package/src/warp-chain.ts +0 -185
package/src/operations/llm.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { BuiltinProviderId, ProviderId } from '../llm/provider-id.js';
|
|
13
|
+
import type { SealedCredential } from '../llm/sealed-credential.js';
|
|
14
|
+
import type { SystemOfUseKind, SystemOfUsePickerEntry } from '../llm/system-of-use.js';
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* @deprecated since Phase 4 (ADR-072). Use {@link ProviderId} from
|
|
@@ -196,6 +198,33 @@ export interface CredentialResultWire {
|
|
|
196
198
|
authType: AuthTypeWire;
|
|
197
199
|
}
|
|
198
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Non-secret credential metadata — the E10 (T11753) redacted view of a resolved
|
|
203
|
+
* credential that {@link ResolvedLLM} carries inline.
|
|
204
|
+
*
|
|
205
|
+
* This is {@link CredentialResultWire} with the secret-bearing `apiKey` field
|
|
206
|
+
* **structurally removed**. The resolver returns this metadata so consumers can
|
|
207
|
+
* branch on `authType` / `source` / `provider` (e.g. choose OAuth-vs-api_key
|
|
208
|
+
* header style, surface `cleo llm whoami` diagnostics) WITHOUT any plaintext
|
|
209
|
+
* crossing the resolver boundary. The plaintext is reachable ONLY via
|
|
210
|
+
* {@link ResolvedLLM.sealedCredential}'s `fetch()` at the wire.
|
|
211
|
+
*
|
|
212
|
+
* @task T11753
|
|
213
|
+
* @epic T11746
|
|
214
|
+
*/
|
|
215
|
+
export interface CredentialMetadataWire {
|
|
216
|
+
/** Provider transport this credential is for. */
|
|
217
|
+
provider: ModelTransport;
|
|
218
|
+
/**
|
|
219
|
+
* Which tier produced this credential. `undefined` only when no credential
|
|
220
|
+
* was resolved (in which case both this and {@link ResolvedLLM.sealedCredential}
|
|
221
|
+
* are `null`).
|
|
222
|
+
*/
|
|
223
|
+
source: CredentialSourceWire | undefined;
|
|
224
|
+
/** Scheme used to present the credential to the provider. */
|
|
225
|
+
authType: AuthTypeWire;
|
|
226
|
+
}
|
|
227
|
+
|
|
199
228
|
// ============================================================================
|
|
200
229
|
// Role-based LLM resolution wire types (T9255 — Phase 2 T-llm-1)
|
|
201
230
|
// ============================================================================
|
|
@@ -204,22 +233,28 @@ export interface CredentialResultWire {
|
|
|
204
233
|
* Which configuration tier produced a {@link ResolvedLLM}.
|
|
205
234
|
*
|
|
206
235
|
* Resolution chain order:
|
|
207
|
-
* 1. `role`
|
|
208
|
-
* 2. `profile`
|
|
209
|
-
* 3. `
|
|
210
|
-
* 4. `default
|
|
211
|
-
* 5. `
|
|
236
|
+
* 1. `role` — `config.llm.roles[role]` (explicit override)
|
|
237
|
+
* 2. `profile` — `config.llm.profiles[roles[role].profile]`
|
|
238
|
+
* 3. `system` — `config.llm.systems[systemKey]` (granular override)
|
|
239
|
+
* 4. `default` — `config.llm.default` (canonical default)
|
|
240
|
+
* 5. `default-profile` — `config.llm.profiles[config.llm.defaultProfile]`
|
|
241
|
+
* 6. `registered-default` — `registerSystemOfUse()` default (below user config)
|
|
242
|
+
* 7. `implicit-fallback` — hard-coded fallback inside the resolver
|
|
212
243
|
*
|
|
213
244
|
* Useful for `cleo llm whoami` diagnostics.
|
|
214
245
|
*
|
|
215
246
|
* @task T9306
|
|
216
247
|
* @task T11617 (`profile`, `default-profile`)
|
|
248
|
+
* @task T11748 (`system`)
|
|
249
|
+
* @task T11751 (`registered-default`)
|
|
217
250
|
*/
|
|
218
251
|
export type ResolutionSource =
|
|
219
252
|
| 'role'
|
|
220
253
|
| 'profile'
|
|
254
|
+
| 'system'
|
|
221
255
|
| 'default'
|
|
222
256
|
| 'default-profile'
|
|
257
|
+
| 'registered-default'
|
|
223
258
|
| 'implicit-fallback';
|
|
224
259
|
|
|
225
260
|
/**
|
|
@@ -256,10 +291,33 @@ export interface ResolvedLLM {
|
|
|
256
291
|
*/
|
|
257
292
|
client: unknown;
|
|
258
293
|
/**
|
|
259
|
-
* Resolved credential
|
|
260
|
-
*
|
|
294
|
+
* Resolved credential **metadata** — provider / source / authType only.
|
|
295
|
+
* `null` when no tier produced a credential (in which case
|
|
296
|
+
* {@link sealedCredential} is also `null`). Callers MUST handle this case.
|
|
297
|
+
*
|
|
298
|
+
* E10 (T11753): the secret-bearing `apiKey` field has been **removed** — this
|
|
299
|
+
* is now a {@link CredentialMetadataWire}, NOT the old
|
|
300
|
+
* {@link CredentialResultWire}. The plaintext token never rides on this
|
|
301
|
+
* envelope; obtain it ONLY via {@link sealedCredential}'s `fetch()` at the
|
|
302
|
+
* wire. Branch on `authType` / `source` here for header-style / diagnostics.
|
|
303
|
+
*/
|
|
304
|
+
credential: CredentialMetadataWire | null;
|
|
305
|
+
/**
|
|
306
|
+
* Sealed credential handle — the E10 on-demand-decrypt credential surface
|
|
307
|
+
* (T11752 · T11753 · T11746). `null` when no tier produced a credential
|
|
308
|
+
* (paired with `credential === null`); non-null exactly when a usable
|
|
309
|
+
* credential was resolved.
|
|
310
|
+
*
|
|
311
|
+
* The plaintext token is materialized ONLY by calling
|
|
312
|
+
* {@link SealedCredential.fetch} at the wire (`transportForProvider` /
|
|
313
|
+
* `session-factory.ts`) or daemon worker-injection — never returned up this
|
|
314
|
+
* envelope. This is the canonical credential surface; the old inline
|
|
315
|
+
* `credential.apiKey` plaintext is gone.
|
|
316
|
+
*
|
|
317
|
+
* @task T11752
|
|
318
|
+
* @task T11753
|
|
261
319
|
*/
|
|
262
|
-
|
|
320
|
+
sealedCredential: SealedCredential | null;
|
|
263
321
|
/** Which config path produced this resolution. */
|
|
264
322
|
source: ResolutionSource;
|
|
265
323
|
/** When `roles[role].credentialLabel` was set, the label that was used. */
|
|
@@ -278,6 +336,19 @@ export interface ResolveLLMForRoleOptions {
|
|
|
278
336
|
* Defaults to `process.cwd()`.
|
|
279
337
|
*/
|
|
280
338
|
projectRoot?: string;
|
|
339
|
+
/**
|
|
340
|
+
* Optional encoded system-of-use key (e.g. `'sentient'`, `'tool:web-search'`)
|
|
341
|
+
* that activates the `llm.systems[key]` override tier in the resolution chain
|
|
342
|
+
* (E9 · T11748).
|
|
343
|
+
*
|
|
344
|
+
* When set, `llm.systems[systemKey]` is consulted AFTER any explicit
|
|
345
|
+
* role/argument override but BEFORE the global `llm.defaultProfile`. Threaded
|
|
346
|
+
* down by `resolveLLMForSystem`; direct role callers leave it unset and the
|
|
347
|
+
* system tier is skipped — preserving role-resolution behaviour unchanged.
|
|
348
|
+
*
|
|
349
|
+
* @task T11748
|
|
350
|
+
*/
|
|
351
|
+
systemKey?: string;
|
|
281
352
|
}
|
|
282
353
|
|
|
283
354
|
// ============================================================================
|
|
@@ -570,6 +641,32 @@ export interface LlmWhoamiResult {
|
|
|
570
641
|
entries: LlmWhoamiEntry[];
|
|
571
642
|
}
|
|
572
643
|
|
|
644
|
+
/**
|
|
645
|
+
* Parameters for `llm.systems-of-use` (query — the profile-picker enumeration).
|
|
646
|
+
*
|
|
647
|
+
* Reserved for future filters (e.g. by {@link SystemOfUsePickerEntry.kind}).
|
|
648
|
+
*
|
|
649
|
+
* @task T11751
|
|
650
|
+
*/
|
|
651
|
+
export interface LlmSystemsOfUseParams {
|
|
652
|
+
/** Optional kind filter — when set, only that axis is enumerated. */
|
|
653
|
+
kind?: SystemOfUseKind;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Result envelope for `llm.systems-of-use` (query · T11751 · AC2).
|
|
658
|
+
*
|
|
659
|
+
* The merged picker surface: every builtin {@link SystemOfUse} plus every
|
|
660
|
+
* runtime-registered system (`registerSystemOfUse`), so the TUI / Studio
|
|
661
|
+
* profile picker can enumerate them from ONE op.
|
|
662
|
+
*
|
|
663
|
+
* @task T11751
|
|
664
|
+
*/
|
|
665
|
+
export interface LlmSystemsOfUseResult {
|
|
666
|
+
/** One entry per builtin or registered system-of-use. */
|
|
667
|
+
entries: SystemOfUsePickerEntry[];
|
|
668
|
+
}
|
|
669
|
+
|
|
573
670
|
// ProviderProfile interface lives in ./llm/provider-profile.ts (T9262).
|
|
574
671
|
// The generated catalog (packages/core/src/llm/generated/provider-profiles.ts)
|
|
575
672
|
// imports the canonical type from the contracts package and emits each
|
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
* Validate / Check Domain Operations
|
|
3
3
|
*
|
|
4
4
|
* T982 extension: Added new types for gate, archive, coherence, compliance-sync,
|
|
5
|
-
*
|
|
5
|
+
* grade, canon, workflow-compliance, verify-explain, and all protocol subtypes.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { WarpChain } from '../warp-chain.js';
|
|
9
|
-
|
|
10
8
|
export type ValidationSeverity = 'error' | 'warning' | 'info';
|
|
11
9
|
|
|
12
10
|
export interface ValidationViolation {
|
|
@@ -242,16 +240,6 @@ export interface ValidateArchiveStatsParams {
|
|
|
242
240
|
}
|
|
243
241
|
export type ValidateArchiveStatsResult = Record<string, unknown>;
|
|
244
242
|
|
|
245
|
-
export interface ValidateChainParams {
|
|
246
|
-
chain: WarpChain;
|
|
247
|
-
}
|
|
248
|
-
export interface ValidateChainResult {
|
|
249
|
-
wellFormed: boolean;
|
|
250
|
-
gateSatisfiable: boolean;
|
|
251
|
-
errors: string[];
|
|
252
|
-
warnings: string[];
|
|
253
|
-
}
|
|
254
|
-
|
|
255
243
|
export interface ValidateGradeParams {
|
|
256
244
|
sessionId: string;
|
|
257
245
|
}
|
|
@@ -379,7 +367,6 @@ export type CheckOps = {
|
|
|
379
367
|
readonly 'gate.set': readonly [ValidateGateParams, ValidateGateResult];
|
|
380
368
|
readonly 'verify.explain': readonly [ValidateVerifyExplainParams, ValidateVerifyExplainResult];
|
|
381
369
|
readonly 'archive.stats': readonly [ValidateArchiveStatsParams, ValidateArchiveStatsResult];
|
|
382
|
-
readonly 'chain.validate': readonly [ValidateChainParams, ValidateChainResult];
|
|
383
370
|
readonly grade: readonly [ValidateGradeParams, ValidateGradeResult];
|
|
384
371
|
readonly 'grade.list': readonly [ValidateGradeListParams, ValidateGradeListResult];
|
|
385
372
|
readonly canon: readonly [ValidateCanonParams, ValidateCanonResult];
|
package/src/playbook.ts
CHANGED
|
@@ -77,6 +77,55 @@ export interface PlaybookApprovalNode extends PlaybookNodeBase {
|
|
|
77
77
|
|
|
78
78
|
export type PlaybookNode = PlaybookAgenticNode | PlaybookDeterministicNode | PlaybookApprovalNode;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Declarative, eval-free predicate over the playbook run `context` used to
|
|
82
|
+
* guard a conditional branch edge (T11806).
|
|
83
|
+
*
|
|
84
|
+
* The predicate is intentionally a *pure data* description — never an
|
|
85
|
+
* arbitrary expression — so the runtime stays deterministic and sandbox-safe.
|
|
86
|
+
* The named `field` is resolved against the accumulated run context
|
|
87
|
+
* (`context[field]`) and compared by exactly one of the optional operators
|
|
88
|
+
* below. When a `PlaybookEdge` carries a `when` predicate, the runtime only
|
|
89
|
+
* traverses that edge if the predicate evaluates to `true`.
|
|
90
|
+
*
|
|
91
|
+
* Exactly one comparison operator (`equals`, `notEquals`, `exists`, `in`, or
|
|
92
|
+
* `truthy`) should be supplied; the parser enforces this so an ambiguous
|
|
93
|
+
* predicate is rejected at parse time rather than mis-routing at runtime.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```yaml
|
|
97
|
+
* edges:
|
|
98
|
+
* - from: classify
|
|
99
|
+
* to: deep-research # taken when context.needsResearch === true
|
|
100
|
+
* when: { field: needsResearch, equals: true }
|
|
101
|
+
* - from: classify
|
|
102
|
+
* to: skip-research # taken when context.needsResearch !== true
|
|
103
|
+
* when: { field: needsResearch, notEquals: true }
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @task T11806 — cantbook runtime branching
|
|
107
|
+
*/
|
|
108
|
+
export interface PlaybookEdgeCondition {
|
|
109
|
+
/** Context key whose value the predicate is evaluated against. */
|
|
110
|
+
field: string;
|
|
111
|
+
/** Edge is satisfied when `context[field]` strictly equals this value. */
|
|
112
|
+
equals?: unknown;
|
|
113
|
+
/** Edge is satisfied when `context[field]` strictly does NOT equal this value. */
|
|
114
|
+
notEquals?: unknown;
|
|
115
|
+
/**
|
|
116
|
+
* When `true`, edge is satisfied iff `field` is present in context;
|
|
117
|
+
* when `false`, satisfied iff `field` is absent from context.
|
|
118
|
+
*/
|
|
119
|
+
exists?: boolean;
|
|
120
|
+
/** Edge is satisfied when `context[field]` is one of these values. */
|
|
121
|
+
in?: unknown[];
|
|
122
|
+
/**
|
|
123
|
+
* When `true`, edge is satisfied iff `context[field]` is truthy;
|
|
124
|
+
* when `false`, satisfied iff `context[field]` is falsy.
|
|
125
|
+
*/
|
|
126
|
+
truthy?: boolean;
|
|
127
|
+
}
|
|
128
|
+
|
|
80
129
|
export interface PlaybookEdge {
|
|
81
130
|
from: string;
|
|
82
131
|
to: string;
|
|
@@ -84,6 +133,18 @@ export interface PlaybookEdge {
|
|
|
84
133
|
requires?: string[];
|
|
85
134
|
ensures?: string[];
|
|
86
135
|
};
|
|
136
|
+
/**
|
|
137
|
+
* Optional declarative branch guard (T11806). When present, the edge is
|
|
138
|
+
* only traversed if the {@link PlaybookEdgeCondition} predicate over the
|
|
139
|
+
* run `context` is satisfied. Edges without `when` are unconditional.
|
|
140
|
+
*
|
|
141
|
+
* A node may have multiple outgoing edges as long as every additional
|
|
142
|
+
* edge carries a `when` guard — the runtime evaluates them against the
|
|
143
|
+
* current context and routes to the single satisfied successor. More than
|
|
144
|
+
* one *unconditional* successor remains a fail-closed error (genuine
|
|
145
|
+
* ambiguity).
|
|
146
|
+
*/
|
|
147
|
+
when?: PlaybookEdgeCondition;
|
|
87
148
|
}
|
|
88
149
|
|
|
89
150
|
export interface PlaybookErrorHandler {
|
package/src/session.ts
CHANGED
|
@@ -121,6 +121,17 @@ export interface Session {
|
|
|
121
121
|
previousSessionId?: string | null;
|
|
122
122
|
/** ID of the session that follows this one. @defaultValue undefined */
|
|
123
123
|
nextSessionId?: string | null;
|
|
124
|
+
/**
|
|
125
|
+
* ID of the fork-tree PARENT session that spawned this one (T11639).
|
|
126
|
+
*
|
|
127
|
+
* Sourced from `CLEO_PARENT_SESSION_ID` (stamped by the supervisor — T11629).
|
|
128
|
+
* Distinct from {@link Session.previousSessionId} (the linear resume chain):
|
|
129
|
+
* `parentSessionId` is the orchestrator→worker spawn edge. NULL/undefined for a
|
|
130
|
+
* root session with no spawning parent.
|
|
131
|
+
*
|
|
132
|
+
* @defaultValue undefined
|
|
133
|
+
*/
|
|
134
|
+
parentSessionId?: string | null;
|
|
124
135
|
/** Provider-specific agent identifier string. @defaultValue undefined */
|
|
125
136
|
agentIdentifier?: string | null;
|
|
126
137
|
/** ISO 8601 timestamp of when the handoff was consumed. @defaultValue undefined */
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-facing tool family I/O contracts (T1741 · epic T11456 · SG-TOOLS).
|
|
3
|
+
*
|
|
4
|
+
* The shared, types-only I/O shapes for the six CORE agent-tool families wired
|
|
5
|
+
* into the {@link ./atomic.js | atomic} primitive layer and surfaced through the
|
|
6
|
+
* `AgentToolRegistry` (`packages/core/src/tools/agent-registry.ts`):
|
|
7
|
+
*
|
|
8
|
+
* - **terminal** — `run_shell` with PTY + non-PTY modes ({@link RunShellInput}).
|
|
9
|
+
* - **file/read** — `read_file` with pagination ({@link ReadFilePagedInput}).
|
|
10
|
+
* - **file/patch** — `apply_patch` with fuzzy hunk matching ({@link ApplyPatchInput}).
|
|
11
|
+
* - **search** — `search_files` over ripgrep ({@link SearchFilesInput}).
|
|
12
|
+
* - **git** — status / diff / log / commit ({@link GitStatusInput} …).
|
|
13
|
+
*
|
|
14
|
+
* These compose OVER the atomic `fs`/`shell`/`search` primitives — they never
|
|
15
|
+
* introduce a new side-effect surface. The implementations
|
|
16
|
+
* (`packages/core/src/tools/builtin/*`) perform ALL work through the injected
|
|
17
|
+
* `GuardedToolSurface` (deny-first chokepoint), so the same guardrail policy
|
|
18
|
+
* applies. Types-only — no runtime logic (Gate 10 `contracts-purity`).
|
|
19
|
+
*
|
|
20
|
+
* @epic T11456
|
|
21
|
+
* @task T1741
|
|
22
|
+
* @see ./atomic.js — the raw primitive I/O shapes these compose over
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// terminal — run_shell (PTY + non-PTY)
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Execution mode for {@link RunShellInput}.
|
|
31
|
+
*
|
|
32
|
+
* - `pty` — allocate a pseudo-terminal (line-discipline, colour, interactive
|
|
33
|
+
* programs). Requires the OPTIONAL `node-pty` native dep; when it cannot be
|
|
34
|
+
* loaded the implementation transparently falls back to `spawn`.
|
|
35
|
+
* - `spawn` — plain `child_process.spawn` (no TTY). Always available.
|
|
36
|
+
* - `auto` — prefer `pty` when `node-pty` is loadable, else `spawn`.
|
|
37
|
+
*/
|
|
38
|
+
export type ShellRunMode = 'pty' | 'spawn' | 'auto';
|
|
39
|
+
|
|
40
|
+
/** Input for the `run_shell` terminal tool. */
|
|
41
|
+
export interface RunShellInput {
|
|
42
|
+
/** Executable to run (argv form — NOT a shell string; no shell interpolation). */
|
|
43
|
+
readonly command: string;
|
|
44
|
+
/** Arguments for {@link RunShellInput.command}. */
|
|
45
|
+
readonly args?: readonly string[];
|
|
46
|
+
/** Working directory. */
|
|
47
|
+
readonly cwd?: string;
|
|
48
|
+
/** Extra environment variables (scrubbed at the guard chokepoint). */
|
|
49
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
50
|
+
/** Hard timeout in milliseconds; the process is killed when exceeded. */
|
|
51
|
+
readonly timeoutMs?: number;
|
|
52
|
+
/** Execution mode. Defaults to `auto`. */
|
|
53
|
+
readonly mode?: ShellRunMode;
|
|
54
|
+
/** PTY column count (PTY mode only). Defaults to 80. */
|
|
55
|
+
readonly cols?: number;
|
|
56
|
+
/** PTY row count (PTY mode only). Defaults to 24. */
|
|
57
|
+
readonly rows?: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Result of the `run_shell` terminal tool. */
|
|
61
|
+
export interface RunShellResult {
|
|
62
|
+
/**
|
|
63
|
+
* Combined output. In `spawn` mode this is stdout; in `pty` mode stdout and
|
|
64
|
+
* stderr are interleaved on the single PTY stream (as a real terminal does).
|
|
65
|
+
*/
|
|
66
|
+
readonly stdout: string;
|
|
67
|
+
/** Captured standard error. Empty in PTY mode (merged into {@link RunShellResult.stdout}). */
|
|
68
|
+
readonly stderr: string;
|
|
69
|
+
/** Process exit code (0 = success). `null` when killed by signal/timeout. */
|
|
70
|
+
readonly code: number | null;
|
|
71
|
+
/** The mode that actually ran (`pty` downgrades to `spawn` when unavailable). */
|
|
72
|
+
readonly mode: 'pty' | 'spawn';
|
|
73
|
+
/** Whether a PTY was requested but unavailable, so `spawn` was used instead. */
|
|
74
|
+
readonly ptyFellBack: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// file — read_file (pagination)
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
/** Input for the paginated `read_file` tool. */
|
|
82
|
+
export interface ReadFilePagedInput {
|
|
83
|
+
/** Absolute path to read. */
|
|
84
|
+
readonly path: string;
|
|
85
|
+
/** 0-based line offset to start from. Defaults to 0. */
|
|
86
|
+
readonly offset?: number;
|
|
87
|
+
/** Maximum number of lines to return. Omit for "to end of file". */
|
|
88
|
+
readonly limit?: number;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Result of a paginated read. */
|
|
92
|
+
export interface ReadFilePagedResult {
|
|
93
|
+
/** Absolute path that was read. */
|
|
94
|
+
readonly path: string;
|
|
95
|
+
/** The selected slice of lines (joined with `\n`). */
|
|
96
|
+
readonly content: string;
|
|
97
|
+
/** 0-based line offset the slice began at. */
|
|
98
|
+
readonly offset: number;
|
|
99
|
+
/** Number of lines returned. */
|
|
100
|
+
readonly lineCount: number;
|
|
101
|
+
/** Total number of lines in the file. */
|
|
102
|
+
readonly totalLines: number;
|
|
103
|
+
/** Whether more lines exist after the returned slice. */
|
|
104
|
+
readonly hasMore: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// file — apply_patch (fuzzy)
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
/** Input for the `apply_patch` tool (fuzzy, whitespace-tolerant replacement). */
|
|
112
|
+
export interface ApplyPatchInput {
|
|
113
|
+
/** Absolute path of the file to patch. */
|
|
114
|
+
readonly path: string;
|
|
115
|
+
/** Exact-or-fuzzy block of original text to locate. */
|
|
116
|
+
readonly oldText: string;
|
|
117
|
+
/** Replacement text. */
|
|
118
|
+
readonly newText: string;
|
|
119
|
+
/**
|
|
120
|
+
* Permit fuzzy (leading/trailing whitespace-insensitive) matching when an
|
|
121
|
+
* exact match is not found. Defaults to `true`.
|
|
122
|
+
*/
|
|
123
|
+
readonly fuzzy?: boolean;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Result of an `apply_patch`. */
|
|
127
|
+
export interface ApplyPatchResult {
|
|
128
|
+
/** Absolute path that was patched. */
|
|
129
|
+
readonly path: string;
|
|
130
|
+
/** Whether the replacement was applied. */
|
|
131
|
+
readonly applied: boolean;
|
|
132
|
+
/** How the match was located: exact, fuzzy (whitespace-normalised), or none. */
|
|
133
|
+
readonly matchKind: 'exact' | 'fuzzy' | 'none';
|
|
134
|
+
/** 0-based line where the replacement began (when applied). */
|
|
135
|
+
readonly startLine?: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
// search — search_files (ripgrep)
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
/** Input for the ripgrep-backed `search_files` tool. */
|
|
143
|
+
export interface SearchFilesInput {
|
|
144
|
+
/** Pattern to search for (regex by default — see {@link SearchFilesInput.fixedStrings}). */
|
|
145
|
+
readonly pattern: string;
|
|
146
|
+
/** Root directory to search under. */
|
|
147
|
+
readonly root: string;
|
|
148
|
+
/** Treat {@link SearchFilesInput.pattern} as a literal string, not a regex. */
|
|
149
|
+
readonly fixedStrings?: boolean;
|
|
150
|
+
/** Case-insensitive matching. */
|
|
151
|
+
readonly ignoreCase?: boolean;
|
|
152
|
+
/** Restrict to files matching this ripgrep glob (e.g. `*.ts`). */
|
|
153
|
+
readonly glob?: string;
|
|
154
|
+
/** Cap on returned matches. Defaults to 1000. */
|
|
155
|
+
readonly maxResults?: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** A single `search_files` match. */
|
|
159
|
+
export interface SearchFilesMatch {
|
|
160
|
+
/** Absolute (or root-relative) path of the matching file. */
|
|
161
|
+
readonly path: string;
|
|
162
|
+
/** 1-based line number of the match. */
|
|
163
|
+
readonly line: number;
|
|
164
|
+
/** The matching line's text (trailing newline stripped). */
|
|
165
|
+
readonly text: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Result of `search_files`. */
|
|
169
|
+
export interface SearchFilesResult {
|
|
170
|
+
/** Matches in ripgrep order. */
|
|
171
|
+
readonly matches: readonly SearchFilesMatch[];
|
|
172
|
+
/** Whether {@link SearchFilesInput.maxResults} truncated the results. */
|
|
173
|
+
readonly truncated: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* `true` when ripgrep (`rg`) was unavailable and the search degraded to a
|
|
176
|
+
* built-in scan, so callers can surface reduced fidelity.
|
|
177
|
+
*/
|
|
178
|
+
readonly degraded: boolean;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
// git — status / diff / log / commit
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
/** Common options for the git tools. */
|
|
186
|
+
export interface GitToolBase {
|
|
187
|
+
/** Repository working directory. Defaults to `process.cwd()`. */
|
|
188
|
+
readonly cwd?: string;
|
|
189
|
+
/** Hard timeout in milliseconds. */
|
|
190
|
+
readonly timeoutMs?: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Input for `git_status`. */
|
|
194
|
+
export interface GitStatusInput extends GitToolBase {}
|
|
195
|
+
|
|
196
|
+
/** One porcelain-v1 status entry. */
|
|
197
|
+
export interface GitStatusEntry {
|
|
198
|
+
/** Two-char XY porcelain status code (e.g. ` M`, `A `, `??`). */
|
|
199
|
+
readonly status: string;
|
|
200
|
+
/** Path the status applies to. */
|
|
201
|
+
readonly path: string;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Result of `git_status`. */
|
|
205
|
+
export interface GitStatusResult {
|
|
206
|
+
/** The current branch name (`HEAD` when detached/unknown). */
|
|
207
|
+
readonly branch: string;
|
|
208
|
+
/** Parsed porcelain entries. */
|
|
209
|
+
readonly entries: readonly GitStatusEntry[];
|
|
210
|
+
/** Whether the working tree has any uncommitted changes. */
|
|
211
|
+
readonly clean: boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Input for `git_diff`. */
|
|
215
|
+
export interface GitDiffInput extends GitToolBase {
|
|
216
|
+
/** Show staged (`--cached`) changes instead of the working tree. */
|
|
217
|
+
readonly staged?: boolean;
|
|
218
|
+
/** Restrict the diff to these paths. */
|
|
219
|
+
readonly paths?: readonly string[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Result of `git_diff`. */
|
|
223
|
+
export interface GitDiffResult {
|
|
224
|
+
/** The unified diff text (empty when there are no changes). */
|
|
225
|
+
readonly diff: string;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Input for `git_log`. */
|
|
229
|
+
export interface GitLogInput extends GitToolBase {
|
|
230
|
+
/** Maximum number of commits to return. Defaults to 20. */
|
|
231
|
+
readonly maxCount?: number;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** One commit in a `git_log` result. */
|
|
235
|
+
export interface GitLogEntry {
|
|
236
|
+
/** Full commit SHA. */
|
|
237
|
+
readonly sha: string;
|
|
238
|
+
/** Author name. */
|
|
239
|
+
readonly author: string;
|
|
240
|
+
/** ISO-8601 author date. */
|
|
241
|
+
readonly date: string;
|
|
242
|
+
/** Commit subject (first line). */
|
|
243
|
+
readonly subject: string;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Result of `git_log`. */
|
|
247
|
+
export interface GitLogResult {
|
|
248
|
+
/** Commits newest-first. */
|
|
249
|
+
readonly commits: readonly GitLogEntry[];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Input for `git_commit`. */
|
|
253
|
+
export interface GitCommitInput extends GitToolBase {
|
|
254
|
+
/** Commit message. */
|
|
255
|
+
readonly message: string;
|
|
256
|
+
/** Stage all tracked modifications first (`-a`). Defaults to `false`. */
|
|
257
|
+
readonly all?: boolean;
|
|
258
|
+
/** Explicit paths to stage before committing. */
|
|
259
|
+
readonly paths?: readonly string[];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Result of `git_commit`. */
|
|
263
|
+
export interface GitCommitResult {
|
|
264
|
+
/** Whether the commit was created. */
|
|
265
|
+
readonly committed: boolean;
|
|
266
|
+
/** The new commit SHA (when created). */
|
|
267
|
+
readonly sha?: string;
|
|
268
|
+
/** Git's stdout/stderr summary (e.g. "nothing to commit"). */
|
|
269
|
+
readonly summary: string;
|
|
270
|
+
}
|
package/src/tools/atomic.ts
CHANGED
|
@@ -36,6 +36,27 @@ export const TOOL_CLASSES = ['fs', 'shell', 'search', 'net', 'notebook'] as cons
|
|
|
36
36
|
/** One of the canonical {@link TOOL_CLASSES}. */
|
|
37
37
|
export type ToolClass = (typeof TOOL_CLASSES)[number];
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Agent-facing **toolset** groups (T1739 · AC4 · epic T11456).
|
|
41
|
+
*
|
|
42
|
+
* Where {@link TOOL_CLASSES} groups primitives by their SIDE-EFFECT surface (and
|
|
43
|
+
* therefore by guardrail policy), a {@link Toolset} groups tools by the
|
|
44
|
+
* AGENT-FACING CAPABILITY a model selects when reasoning — the dimension Hermes'
|
|
45
|
+
* `tools/registry.py` exposes to the loop. The two axes are orthogonal: an `fs`
|
|
46
|
+
* class primitive belongs to the `file` toolset, a `shell` class primitive to the
|
|
47
|
+
* `terminal` toolset, a `net` class primitive to the `web` toolset, etc.
|
|
48
|
+
*
|
|
49
|
+
* - `terminal` — shell / process execution (`executeShell`, `runGit`).
|
|
50
|
+
* - `file` — filesystem read/write/search (`readFileText`, `writeFileAtomic`, …).
|
|
51
|
+
* - `web` — outbound network / fetch (`fetch`).
|
|
52
|
+
* - `agent` — sub-agent / delegation / task orchestration tools.
|
|
53
|
+
* - `media` — image / audio / notebook authoring (`notebookEdit`, …).
|
|
54
|
+
*/
|
|
55
|
+
export const AGENT_TOOLSETS = ['terminal', 'file', 'web', 'agent', 'media'] as const;
|
|
56
|
+
|
|
57
|
+
/** One of the canonical {@link AGENT_TOOLSETS}. */
|
|
58
|
+
export type Toolset = (typeof AGENT_TOOLSETS)[number];
|
|
59
|
+
|
|
39
60
|
/**
|
|
40
61
|
* Descriptor for a single registered tool primitive. The registry of these is
|
|
41
62
|
* the SoT for "what atomic tools exist", consumed by the guardrail chokepoint
|
package/src/tools/index.ts
CHANGED
|
@@ -7,6 +7,30 @@
|
|
|
7
7
|
* @epic T9835
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
// === Agent-facing tool families (T1741 / T11456) ===
|
|
11
|
+
export type {
|
|
12
|
+
ApplyPatchInput,
|
|
13
|
+
ApplyPatchResult,
|
|
14
|
+
GitCommitInput,
|
|
15
|
+
GitCommitResult,
|
|
16
|
+
GitDiffInput,
|
|
17
|
+
GitDiffResult,
|
|
18
|
+
GitLogEntry,
|
|
19
|
+
GitLogInput,
|
|
20
|
+
GitLogResult,
|
|
21
|
+
GitStatusEntry,
|
|
22
|
+
GitStatusInput,
|
|
23
|
+
GitStatusResult,
|
|
24
|
+
GitToolBase,
|
|
25
|
+
ReadFilePagedInput,
|
|
26
|
+
ReadFilePagedResult,
|
|
27
|
+
RunShellInput,
|
|
28
|
+
RunShellResult,
|
|
29
|
+
SearchFilesInput,
|
|
30
|
+
SearchFilesMatch,
|
|
31
|
+
SearchFilesResult,
|
|
32
|
+
ShellRunMode,
|
|
33
|
+
} from './agent-tools.js';
|
|
10
34
|
export type { FetchBrainEntriesInput, FetchBrainEntriesOutput } from './brain-fetch.js';
|
|
11
35
|
export type { ObserveBrainInput, ObserveBrainOutput } from './brain-observe.js';
|
|
12
36
|
// === BrainTools (T10070 / T9835c) ===
|
|
@@ -41,3 +65,25 @@ export type {
|
|
|
41
65
|
ScoreTaskInput,
|
|
42
66
|
ScoreTaskResult,
|
|
43
67
|
} from './score-task-priority.js';
|
|
68
|
+
// === Web + browser agent tools (T1742 / T11456) ===
|
|
69
|
+
export type {
|
|
70
|
+
AccessibilityNode,
|
|
71
|
+
BrowserActionResult,
|
|
72
|
+
BrowserClickInput,
|
|
73
|
+
BrowserNavigateInput,
|
|
74
|
+
BrowserPageState,
|
|
75
|
+
BrowserPressInput,
|
|
76
|
+
BrowserScrollDirection,
|
|
77
|
+
BrowserScrollInput,
|
|
78
|
+
BrowserScrollResult,
|
|
79
|
+
BrowserSnapshotResult,
|
|
80
|
+
BrowserTypeInput,
|
|
81
|
+
BrowserVisionInput,
|
|
82
|
+
BrowserVisionResult,
|
|
83
|
+
WebExtractInput,
|
|
84
|
+
WebExtractResult,
|
|
85
|
+
WebSearchBackendId,
|
|
86
|
+
WebSearchHit,
|
|
87
|
+
WebSearchInput,
|
|
88
|
+
WebSearchResult,
|
|
89
|
+
} from './web-tools.js';
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
* @see ./atomic.js — the tool I/O shapes this seam composes over
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
|
+
import type { RunShellInput, RunShellResult } from './agent-tools.js';
|
|
47
48
|
import type {
|
|
48
49
|
ExecuteShellInput,
|
|
49
50
|
ExecuteShellResult,
|
|
@@ -86,6 +87,12 @@ export interface GuardedToolSurface {
|
|
|
86
87
|
pathExists(input: PathExistsInput): Promise<PathExistsResult>;
|
|
87
88
|
/** Run a command with explicit cwd/env/timeout through the guard. */
|
|
88
89
|
executeShell(input: ExecuteShellInput): Promise<ExecuteShellResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Run a command under a pseudo-terminal (PTY) through the guard, falling back
|
|
92
|
+
* to a non-PTY spawn when a PTY backend is unavailable. Subject to the same
|
|
93
|
+
* deny-first command policy + env scrubbing as {@link GuardedToolSurface.executeShell}.
|
|
94
|
+
*/
|
|
95
|
+
executePty(input: RunShellInput): Promise<RunShellResult>;
|
|
89
96
|
/** Run a git subcommand through the guard. */
|
|
90
97
|
runGit(input: RunGitInput): Promise<ExecuteShellResult>;
|
|
91
98
|
}
|