@tangle-network/agent-interface 2.18.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -4
- package/dist/harness-capabilities.d.ts +66 -3
- package/dist/harness-capabilities.js +127 -10
- package/dist/profile-kb/entry.d.ts +12 -0
- package/dist/profile-kb/entry.js +20 -0
- package/dist/profile-kb/harnesses.d.ts +1 -7
- package/dist/profile-kb/harnesses.js +66 -105
- package/dist/profile-kb/index.d.ts +2 -2
- package/dist/profile-kb/index.js +4 -4
- package/dist/profile-kb/models.d.ts +1 -7
- package/dist/profile-kb/models.js +161 -311
- package/dist/profile-kb/records.d.ts +2 -2
- package/dist/profile-kb/records.js +12 -10
- package/dist/profile-kb/types.d.ts +18 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,6 +116,7 @@ Providers that support recoverable workspace copies expose `workspaceBranching`
|
|
|
116
116
|
Checkpoint and fork requests bind an idempotency key to a canonical request digest.
|
|
117
117
|
Every returned resource repeats and validates that identity, lookups recover remote success after caller restart, changed-input key reuse returns a conflict, and cleanup binds its acknowledgement to the exact provider and target.
|
|
118
118
|
A checkpoint with dependent forks returns `in_use` plus the blocking environment identifiers and remains recoverable until those forks are destroyed.
|
|
119
|
+
A provider whose forks hold their own copy of the checkpoint deletes it without waiting for them.
|
|
119
120
|
The older `checkpoint()` and `fork()` methods remain source-compatible for providers that have not yet implemented recovery semantics, but clients must not present them as durable workspace branching.
|
|
120
121
|
|
|
121
122
|
`CreateAgentEnvironmentInput.idempotencyKey` makes generic environment creation one retry-safe operation.
|
|
@@ -194,9 +195,15 @@ These checks do not apply to a replacement environment owned by caller code.
|
|
|
194
195
|
|
|
195
196
|
## Profile knowledge base
|
|
196
197
|
|
|
197
|
-
`@tangle-network/agent-interface/profile-kb` holds
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
`@tangle-network/agent-interface/profile-kb` holds dated harness and model facts, conditional guidance, and reproduced platform learnings.
|
|
199
|
+
Sources guide investigation; they do not prove that a technique improves this platform's behavior.
|
|
200
|
+
|
|
201
|
+
Entries can expose optional `claims`, each with `text`, `basis` (`documented`, `vendor-guidance`, `local-observation`, or `hypothesis`), `audience` (`agent` or `operator`), and supporting `sources`.
|
|
202
|
+
A source has a URL and check date, with optional `authority` (`primary`, `secondary`, or `local`) and `locator` for the supporting section or artifact.
|
|
203
|
+
Authority describes the source, independently of the claim's basis.
|
|
204
|
+
The maintained entries derive the legacy `prompt`, `operator`, and `sources` arrays from these claims; hypotheses stay inspectable but contribute no prompt or operator text.
|
|
205
|
+
Only agent guidance enters the profile prompt. An empty `prompt` is legitimate when no supported instruction is needed; do not pad it with generic advice.
|
|
206
|
+
Keep applicability conditions in the claim's text so composition preserves them.
|
|
200
207
|
|
|
201
208
|
`withProfileKb(profile)` composes harness guidance, then model guidance, then the profile's own text into the profile's prompt:
|
|
202
209
|
|
|
@@ -217,7 +224,24 @@ The knowledge base owns the block sources `harness`, `model`, and `learning` (`P
|
|
|
217
224
|
Give each layer its own source name and pass it as `replaceSources`: the composition then replaces only those sources and keeps every other block in place. Without `replaceSources`, it replaces every block.
|
|
218
225
|
The block marker is reserved for composers: a hand-written `<profile-guidance source="model" ...>` block counts as a knowledge-base block and is replaced.
|
|
219
226
|
|
|
220
|
-
The module also exports the data (`profileKbHarnesses`, `profileKbModels`), operator notes
|
|
227
|
+
The module also exports the data (`profileKbHarnesses`, `profileKbModels`), operator notes, platform learnings (admitted only after an agent-eval check reproduced them), and `profileKbDiscrepancies`, which preserves dated naming and availability checks.
|
|
228
|
+
The source audit is retained in [Anthropic and OpenAI](src/profile-kb/research/anthropic-openai.md), [open harnesses and model APIs](src/profile-kb/research/open-harnesses.md), and the [distillation and consumer review](src/profile-kb/research/distillation-review.md).
|
|
229
|
+
|
|
230
|
+
### Applicability and evidence
|
|
231
|
+
|
|
232
|
+
Read vendor guidance within its documented, dated scope. Papers and social posts propose hypotheses to evaluate; they do not establish universal agent constraints. A measured conclusion applies to the configuration, tasks, environment, and evidence that supported it.
|
|
233
|
+
|
|
234
|
+
Keep that scope with the existing evaluation record and link it from the learning's evidence source:
|
|
235
|
+
|
|
236
|
+
- Requested model and observed served identity, provider route and adapter revision, harness and CLI version, and the authored and effective `AgentProfile` revisions or digests.
|
|
237
|
+
- Reasoning settings, tool, MCP server and hook versions or definitions, permissions, and the loaded skill and instruction revisions. Distinguish declared configuration from observed delivery and use.
|
|
238
|
+
- Task and acceptance-check revisions, environment and relevant resource limits, sampling and budget, measured outcome, errors and counterexamples, and source traces or artifacts.
|
|
239
|
+
|
|
240
|
+
Unknown identity, usage, or cost stays unknown. A requested model name does not prove which model served the run; partial accounting supports a floor, not a complete total or zero spend.
|
|
241
|
+
|
|
242
|
+
Before reusing a conclusion after a material change to any of these conditions, review its applicability against the retained evidence. State what still transfers and what needs a new check; use the existing registration and resource authorization for any experiment. Preserve the original record and append the changed scope or new evidence.
|
|
243
|
+
|
|
244
|
+
The current [learning selector](src/profile-kb/index.ts) matches only harness and model; it does not validate the other conditions above. Keep narrower limits explicit in the learning text, or retain the finding in its evaluation record until it is suitable for composed guidance. The [learning records](src/profile-kb/records.ts) remain the single admission surface. Claim provenance does not automatically revalidate a run or authorize an experiment.
|
|
221
245
|
|
|
222
246
|
## Failed execution accounting
|
|
223
247
|
|
|
@@ -21,13 +21,76 @@ import type { HarnessType } from "./harness.js";
|
|
|
21
21
|
export declare const reasoningLadder: readonly ReasoningEffort[];
|
|
22
22
|
/** Provider prefix of a canonical model id (`anthropic/claude-…` → `anthropic`), or null. */
|
|
23
23
|
export declare function modelProvider(modelId: string): string | null;
|
|
24
|
+
/**
|
|
25
|
+
* The provider a model id belongs to: its explicit prefix, else the provider of its bare-id family
|
|
26
|
+
* (`claude-sonnet-5-5` → `anthropic`). `null` for an id outside every family, such as the `default`
|
|
27
|
+
* sentinel, whose provider only the serving harness knows.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveModelProvider(modelId: string): string | null;
|
|
24
30
|
/** The providers a harness is locked to, or `null` when it is router-backed (any model). */
|
|
25
31
|
export declare function harnessProviders(harness: HarnessType): readonly string[] | null;
|
|
32
|
+
/** A harness × model pair that a production run measured to fail at its first model call. */
|
|
33
|
+
export interface HarnessModelExclusion {
|
|
34
|
+
readonly harness: HarnessType;
|
|
35
|
+
/** Canonical `provider/model` ids the measurement covers. */
|
|
36
|
+
readonly models: RegExp;
|
|
37
|
+
/**
|
|
38
|
+
* The failure needs a reasoning effort above `none`: the harness sends the rejected control only
|
|
39
|
+
* then, so the same pair without a reasoning effort is not excluded.
|
|
40
|
+
*/
|
|
41
|
+
readonly onlyWithReasoningEffort: boolean;
|
|
42
|
+
/** What the provider rejected, and why the harness triggers it. */
|
|
43
|
+
readonly reason: string;
|
|
44
|
+
/** ISO date of the production measurement. */
|
|
45
|
+
readonly measuredOn: string;
|
|
46
|
+
/** Where the measurement is recorded. */
|
|
47
|
+
readonly evidence: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Pairs a router-backed harness cannot run, measured on production with the Router credential: one
|
|
51
|
+
* prompt per pair, profile reasoning effort `medium` (2026-10-05). The same run passed pi with
|
|
52
|
+
* `openai/gpt-5.5` and `zai/glm-5.3`, and opencode with every model listed here. Pairs not listed
|
|
53
|
+
* were not measured to fail. An entry is removed when its harness adapter or the Router is fixed and
|
|
54
|
+
* the pair passes a new production measurement.
|
|
55
|
+
*
|
|
56
|
+
* pi's chat-completions client (pi-ai 0.85.1) marks a model as reasoning only when the profile asks
|
|
57
|
+
* for a reasoning effort, and only a reasoning model is sent the `developer` role and
|
|
58
|
+
* `reasoning_effort`; that is why the first two entries need a reasoning effort.
|
|
59
|
+
*/
|
|
60
|
+
export declare const harnessModelExclusions: readonly HarnessModelExclusion[];
|
|
61
|
+
/** The answer to "can this harness run this model", with the refusal a caller can show as-is. */
|
|
62
|
+
export type HarnessModelSupport = {
|
|
63
|
+
readonly supported: true;
|
|
64
|
+
/** Canonical `provider/model` id when the provider resolved, else the id as given. */
|
|
65
|
+
readonly model: string;
|
|
66
|
+
readonly provider: string | null;
|
|
67
|
+
} | {
|
|
68
|
+
readonly supported: false;
|
|
69
|
+
readonly model: string;
|
|
70
|
+
readonly provider: string | null;
|
|
71
|
+
/** The providers a vendor-locked harness accepts; absent for a measured exclusion. */
|
|
72
|
+
readonly allowedProviders?: readonly string[];
|
|
73
|
+
/** The measurement behind a refusal of a router-backed pair. */
|
|
74
|
+
readonly exclusion?: HarnessModelExclusion;
|
|
75
|
+
/** One sentence naming the harness, the model and the reason. */
|
|
76
|
+
readonly message: string;
|
|
77
|
+
};
|
|
78
|
+
export interface HarnessModelSupportOptions {
|
|
79
|
+
/** The run's reasoning effort; `null`, `undefined` and `none` all mean no reasoning effort. */
|
|
80
|
+
readonly reasoningEffort?: ReasoningEffort | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether a harness can run a model, and why not. A bare id resolves its provider through
|
|
84
|
+
* {@link resolveModelProvider}; an id whose provider cannot be resolved (a sentinel like `default`)
|
|
85
|
+
* is left to the harness, because its provider only the serving harness knows. A vendor-locked
|
|
86
|
+
* harness refuses every other provider; a router-backed harness refuses only the measured
|
|
87
|
+
* {@link harnessModelExclusions}.
|
|
88
|
+
*/
|
|
89
|
+
export declare function harnessModelSupport(harness: HarnessType, modelId: string, options?: HarnessModelSupportOptions): HarnessModelSupport;
|
|
26
90
|
/**
|
|
27
|
-
* Whether a harness can run a model
|
|
28
|
-
* a model id with no provider prefix (a sentinel like `default`) is treated as compatible too.
|
|
91
|
+
* Whether a harness can run a model; {@link harnessModelSupport} gives the reason when it cannot.
|
|
29
92
|
*/
|
|
30
|
-
export declare function harnessSupportsModel(harness: HarnessType, modelId: string): boolean;
|
|
93
|
+
export declare function harnessSupportsModel(harness: HarnessType, modelId: string, options?: HarnessModelSupportOptions): boolean;
|
|
31
94
|
/** The harness to adopt for a model whose provider is vendor-locked (`anthropic` → `claude-code`,
|
|
32
95
|
* `openai` → `codex`, `moonshot` → `kimi-code`); `null` when any router-backed harness will do. */
|
|
33
96
|
export declare function preferredHarnessForModel(modelId: string): HarnessType | null;
|
|
@@ -21,7 +21,8 @@ export const reasoningLadder = REASONING_EFFORTS;
|
|
|
21
21
|
// ── Harness ↔ model compatibility ────────────────────────────────────────────
|
|
22
22
|
/**
|
|
23
23
|
* Provider prefixes a harness is vendor-locked to (canonical-id prefix, e.g. `anthropic`, `openai`).
|
|
24
|
-
* A harness with no entry is router-backed: it runs any model
|
|
24
|
+
* A harness with no entry is router-backed: it runs any model, except the measured exclusions in
|
|
25
|
+
* {@link harnessModelExclusions}.
|
|
25
26
|
*
|
|
26
27
|
* `nanoclaw` is deliberately absent despite the "claw" name: its runner routes every provider through
|
|
27
28
|
* the Tangle router (canonical model id straight to the gateway), so it is router-backed like
|
|
@@ -37,25 +38,141 @@ export function modelProvider(modelId) {
|
|
|
37
38
|
const slash = modelId.indexOf("/");
|
|
38
39
|
return slash > 0 ? modelId.slice(0, slash) : null;
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Model families whose bare ids belong to one provider. The Router catalog serves most ids without a
|
|
43
|
+
* prefix (`claude-sonnet-5-5`, `gpt-5.5`, `glm-5.3`) and names the provider beside them, so a check
|
|
44
|
+
* that read every bare id as "any provider" offered `claude-code` with `glm-5.3`.
|
|
45
|
+
*/
|
|
46
|
+
const bareModelFamilyProviders = [
|
|
47
|
+
[/^claude-/, "anthropic"],
|
|
48
|
+
[/^(gpt-|chatgpt-|codex-|o\d+(-|$))/, "openai"],
|
|
49
|
+
[/^(kimi-|moonshot-)/, "moonshot"],
|
|
50
|
+
[/^gemini-/, "google"],
|
|
51
|
+
[/^glm-/, "zai"],
|
|
52
|
+
[/^deepseek-/, "deepseek"],
|
|
53
|
+
[/^grok-/, "xai"],
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* The provider a model id belongs to: its explicit prefix, else the provider of its bare-id family
|
|
57
|
+
* (`claude-sonnet-5-5` → `anthropic`). `null` for an id outside every family, such as the `default`
|
|
58
|
+
* sentinel, whose provider only the serving harness knows.
|
|
59
|
+
*/
|
|
60
|
+
export function resolveModelProvider(modelId) {
|
|
61
|
+
const explicit = modelProvider(modelId);
|
|
62
|
+
if (explicit)
|
|
63
|
+
return explicit;
|
|
64
|
+
const id = modelId.trim().toLowerCase();
|
|
65
|
+
for (const [family, provider] of bareModelFamilyProviders) {
|
|
66
|
+
if (family.test(id))
|
|
67
|
+
return provider;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
40
71
|
/** The providers a harness is locked to, or `null` when it is router-backed (any model). */
|
|
41
72
|
export function harnessProviders(harness) {
|
|
42
73
|
return harnessProviderLock[harness] ?? null;
|
|
43
74
|
}
|
|
75
|
+
const SANDBOX_HARNESS_MATRIX_EVIDENCE = "https://github.com/tangle-network/agent-dev-container/issues/9382";
|
|
76
|
+
/**
|
|
77
|
+
* Pairs a router-backed harness cannot run, measured on production with the Router credential: one
|
|
78
|
+
* prompt per pair, profile reasoning effort `medium` (2026-10-05). The same run passed pi with
|
|
79
|
+
* `openai/gpt-5.5` and `zai/glm-5.3`, and opencode with every model listed here. Pairs not listed
|
|
80
|
+
* were not measured to fail. An entry is removed when its harness adapter or the Router is fixed and
|
|
81
|
+
* the pair passes a new production measurement.
|
|
82
|
+
*
|
|
83
|
+
* pi's chat-completions client (pi-ai 0.85.1) marks a model as reasoning only when the profile asks
|
|
84
|
+
* for a reasoning effort, and only a reasoning model is sent the `developer` role and
|
|
85
|
+
* `reasoning_effort`; that is why the first two entries need a reasoning effort.
|
|
86
|
+
*/
|
|
87
|
+
export const harnessModelExclusions = [
|
|
88
|
+
{
|
|
89
|
+
harness: "pi",
|
|
90
|
+
models: /^anthropic\//,
|
|
91
|
+
onlyWithReasoningEffort: true,
|
|
92
|
+
reason: 'the Router\'s chat-completions route for Anthropic models rejects the "developer" role pi sends ' +
|
|
93
|
+
'to a reasoning model (400 Unexpected role "developer")',
|
|
94
|
+
measuredOn: "2026-10-05",
|
|
95
|
+
evidence: SANDBOX_HARNESS_MATRIX_EVIDENCE,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
harness: "pi",
|
|
99
|
+
models: /^openai\/gpt-5\.6-luna$/,
|
|
100
|
+
onlyWithReasoningEffort: true,
|
|
101
|
+
reason: "OpenAI does not accept function tools together with reasoning_effort for this model on " +
|
|
102
|
+
"/v1/chat/completions, the only route pi speaks",
|
|
103
|
+
measuredOn: "2026-10-05",
|
|
104
|
+
evidence: SANDBOX_HARNESS_MATRIX_EVIDENCE,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
harness: "pi",
|
|
108
|
+
models: /^google\/gemini-3\.8-flash$/,
|
|
109
|
+
onlyWithReasoningEffort: false,
|
|
110
|
+
reason: "the model requires each function call to return its thought_signature, which pi's " +
|
|
111
|
+
"chat-completions client does not send back (400 Function call is missing a thought_signature)",
|
|
112
|
+
measuredOn: "2026-10-05",
|
|
113
|
+
evidence: SANDBOX_HARNESS_MATRIX_EVIDENCE,
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
/**
|
|
117
|
+
* Whether a harness can run a model, and why not. A bare id resolves its provider through
|
|
118
|
+
* {@link resolveModelProvider}; an id whose provider cannot be resolved (a sentinel like `default`)
|
|
119
|
+
* is left to the harness, because its provider only the serving harness knows. A vendor-locked
|
|
120
|
+
* harness refuses every other provider; a router-backed harness refuses only the measured
|
|
121
|
+
* {@link harnessModelExclusions}.
|
|
122
|
+
*/
|
|
123
|
+
export function harnessModelSupport(harness, modelId, options = {}) {
|
|
124
|
+
const trimmed = modelId.trim();
|
|
125
|
+
const provider = resolveModelProvider(trimmed);
|
|
126
|
+
const model = provider !== null && modelProvider(trimmed) === null
|
|
127
|
+
? `${provider}/${trimmed}`
|
|
128
|
+
: trimmed;
|
|
129
|
+
if (provider === null)
|
|
130
|
+
return { supported: true, model, provider };
|
|
131
|
+
const allowedProviders = harnessProviders(harness);
|
|
132
|
+
if (allowedProviders && !allowedProviders.includes(provider)) {
|
|
133
|
+
return {
|
|
134
|
+
supported: false,
|
|
135
|
+
model,
|
|
136
|
+
provider,
|
|
137
|
+
allowedProviders,
|
|
138
|
+
message: `Harness ${harness} runs only ${allowedProviders.join(" or ")} models; ` +
|
|
139
|
+
`${model} is a ${provider} model. Choose a model whose id starts with ` +
|
|
140
|
+
`${allowedProviders.map((p) => `${p}/`).join(" or ")}, or a harness that runs ` +
|
|
141
|
+
`${provider} models, such as opencode.`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const reasoning = options.reasoningEffort !== undefined &&
|
|
145
|
+
options.reasoningEffort !== null &&
|
|
146
|
+
options.reasoningEffort !== "none";
|
|
147
|
+
const exclusion = harnessModelExclusions.find((entry) => entry.harness === harness &&
|
|
148
|
+
entry.models.test(model) &&
|
|
149
|
+
(!entry.onlyWithReasoningEffort || reasoning));
|
|
150
|
+
if (exclusion) {
|
|
151
|
+
return {
|
|
152
|
+
supported: false,
|
|
153
|
+
model,
|
|
154
|
+
provider,
|
|
155
|
+
exclusion,
|
|
156
|
+
message: `Harness ${harness} cannot run ${model}` +
|
|
157
|
+
(exclusion.onlyWithReasoningEffort ? " with a reasoning effort" : "") +
|
|
158
|
+
`: ${exclusion.reason} (measured ${exclusion.measuredOn}, ${exclusion.evidence}). ` +
|
|
159
|
+
(exclusion.onlyWithReasoningEffort
|
|
160
|
+
? "Remove model.reasoningEffort, or choose another harness or model."
|
|
161
|
+
: "Choose another harness or model."),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return { supported: true, model, provider };
|
|
165
|
+
}
|
|
44
166
|
/**
|
|
45
|
-
* Whether a harness can run a model
|
|
46
|
-
* a model id with no provider prefix (a sentinel like `default`) is treated as compatible too.
|
|
167
|
+
* Whether a harness can run a model; {@link harnessModelSupport} gives the reason when it cannot.
|
|
47
168
|
*/
|
|
48
|
-
export function harnessSupportsModel(harness, modelId) {
|
|
49
|
-
|
|
50
|
-
if (!providers)
|
|
51
|
-
return true;
|
|
52
|
-
const provider = modelProvider(modelId);
|
|
53
|
-
return provider === null || providers.includes(provider);
|
|
169
|
+
export function harnessSupportsModel(harness, modelId, options) {
|
|
170
|
+
return harnessModelSupport(harness, modelId, options).supported;
|
|
54
171
|
}
|
|
55
172
|
/** The harness to adopt for a model whose provider is vendor-locked (`anthropic` → `claude-code`,
|
|
56
173
|
* `openai` → `codex`, `moonshot` → `kimi-code`); `null` when any router-backed harness will do. */
|
|
57
174
|
export function preferredHarnessForModel(modelId) {
|
|
58
|
-
const provider =
|
|
175
|
+
const provider = resolveModelProvider(modelId);
|
|
59
176
|
if (!provider)
|
|
60
177
|
return null;
|
|
61
178
|
for (const [harness, providers] of Object.entries(harnessProviderLock)) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ProfileKbClaim, ProfileKbSource, ProfileKbSurface } from "./types.js";
|
|
2
|
+
export declare function claim(text: string, source: ProfileKbSource, basis?: ProfileKbClaim["basis"], audience?: ProfileKbClaim["audience"]): ProfileKbClaim;
|
|
3
|
+
/** Keep public string arrays and entry citations derived from the same claim records. */
|
|
4
|
+
export declare function kbEntry<const T extends {
|
|
5
|
+
claims: ProfileKbClaim[];
|
|
6
|
+
surfaces?: ProfileKbSurface[];
|
|
7
|
+
aliases?: string[];
|
|
8
|
+
}>(entry: T): T & {
|
|
9
|
+
sources: ProfileKbSource[];
|
|
10
|
+
prompt: string[];
|
|
11
|
+
operator: string[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function claim(text, source, basis = "documented", audience = "operator") {
|
|
2
|
+
return { text, basis, audience, sources: [source] };
|
|
3
|
+
}
|
|
4
|
+
/** Keep public string arrays and entry citations derived from the same claim records. */
|
|
5
|
+
export function kbEntry(entry) {
|
|
6
|
+
const sources = new Map();
|
|
7
|
+
for (const claim of entry.claims) {
|
|
8
|
+
for (const source of claim.sources)
|
|
9
|
+
sources.set(JSON.stringify(source), source);
|
|
10
|
+
}
|
|
11
|
+
const textFor = (audience) => entry.claims
|
|
12
|
+
.filter((claim) => claim.audience === audience && claim.basis !== "hypothesis")
|
|
13
|
+
.map((claim) => claim.text);
|
|
14
|
+
return {
|
|
15
|
+
...entry,
|
|
16
|
+
sources: [...sources.values()],
|
|
17
|
+
prompt: textFor("agent"),
|
|
18
|
+
operator: textFor("operator"),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
import type { ProfileKbHarness } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* The frontier coding harnesses this platform runs, checked against the
|
|
4
|
-
* installed CLI on 2026-09-22.
|
|
5
|
-
*
|
|
6
|
-
* `prompt` lines go into the agent's prompt; `operator` lines are launch
|
|
7
|
-
* facts. Each harness is described on its own terms.
|
|
8
|
-
*/
|
|
2
|
+
/** Source-qualified launch knowledge; versions describe checked sources, not every host's installation. */
|
|
9
3
|
export declare const profileKbHarnesses: readonly ProfileKbHarness[];
|
|
@@ -1,123 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { claim, kbEntry } from "./entry.js";
|
|
2
|
+
const CHECKED = "2026-10-04";
|
|
3
|
+
const source = (url, locator) => ({
|
|
4
|
+
url,
|
|
5
|
+
locator,
|
|
6
|
+
checkedAt: CHECKED,
|
|
7
|
+
authority: "primary",
|
|
8
|
+
});
|
|
9
|
+
const claudeCli = source("https://code.claude.com/docs/en/cli-reference", "CLI flags: --print, --bg, --bare, system prompt flags");
|
|
10
|
+
const claudeAgents = source("https://code.claude.com/docs/en/sub-agents", "How subagents work; forked subagents");
|
|
11
|
+
const codexConfig = source("https://learn.chatgpt.com/docs/config-file/config-reference", "model_instructions_file; model_reasoning_effort");
|
|
12
|
+
const codexAgents = source("https://learn.chatgpt.com/docs/agent-configuration/subagents", "Availability; approvals and sandbox controls");
|
|
13
|
+
const codexCommands = source("https://learn.chatgpt.com/docs/developer-commands", "Set or view a task goal with /goal");
|
|
14
|
+
const piBase = "https://github.com/earendil-works/pi/blob/200387122ca450d6387f033949423114a270b96c/packages/coding-agent/";
|
|
15
|
+
const piCli = source(`${piBase}docs/cli.md`, "Invocation and output; models; prompts and process");
|
|
16
|
+
const piRpc = source(`${piBase}docs/rpc.md#run-lifecycle`, "Run lifecycle");
|
|
17
|
+
const piCommands = source(`${piBase}docs/rpc-commands.md`, "steer; follow_up; get_available_thinking_levels");
|
|
18
|
+
const opencodeCli = source("https://opencode.ai/docs/cli/", "run; serve; acp");
|
|
19
|
+
const opencodePrompt = source("https://github.com/anomalyco/opencode/blob/907b3bc518fa48e90e8ec24dd327d13eee71c36c/packages/opencode/src/session/llm/request.ts#L51-L70", "LLMRequestPrep.prepare");
|
|
20
|
+
const kimiCli = source("https://moonshotai.github.io/kimi-code/en/reference/kimi-command.html", "Flag conflict rules; non-interactive execution");
|
|
21
|
+
const kimiConfig = source("https://moonshotai.github.io/kimi-code/en/configuration/config-files.html", "Config file location; thinking; complete example");
|
|
22
|
+
/** Source-qualified launch knowledge; versions describe checked sources, not every host's installation. */
|
|
9
23
|
export const profileKbHarnesses = [
|
|
10
|
-
{
|
|
24
|
+
kbEntry({
|
|
11
25
|
id: "claude-code",
|
|
12
26
|
name: "Claude Code",
|
|
13
|
-
version: "2.1.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
],
|
|
21
|
-
prompt: [
|
|
22
|
-
"Delegate independent slices to subagents, several in one turn so they run in parallel, then synthesize their results.",
|
|
23
|
-
"Use the skills listed in your session for procedures they cover.",
|
|
24
|
-
"Run long commands in the background and keep working while they finish.",
|
|
27
|
+
version: "2.1.289",
|
|
28
|
+
claims: [
|
|
29
|
+
claim("For a non-forked subagent, supply the context needed for its task; forked subagents inherit the parent conversation.", claudeAgents, "documented", "agent"),
|
|
30
|
+
claim("Headless: claude -p <prompt> --model <id> --effort <level> --output-format stream-json --verbose. --bg is a separate background-session mode and cannot combine with -p.", claudeCli),
|
|
31
|
+
claim("--append-system-prompt adds to the default; --system-prompt replaces it. On resume, prompt changes may wait for compaction.", claudeCli),
|
|
32
|
+
claim("--bare skips automatic discovery; explicitly supplied context can still load. It is not an established speed improvement for this workload.", claudeCli),
|
|
33
|
+
claim("--max-budget-usd caps the print invocation's spend, excluding restored prior spend; --json-schema constrains output structure, not correctness.", claudeCli),
|
|
25
34
|
],
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"`--append-system-prompt` adds to the built-in prompt; `--system-prompt` replaces it.",
|
|
29
|
-
"`--max-budget-usd` caps spend; `--json-schema` validates structured output; `--mcp-config` loads MCP servers.",
|
|
30
|
-
"`--bg` starts a background session; `--bare` skips hooks, plugins, memory, and CLAUDE.md discovery.",
|
|
31
|
-
],
|
|
32
|
-
},
|
|
33
|
-
{
|
|
35
|
+
}),
|
|
36
|
+
kbEntry({
|
|
34
37
|
id: "codex",
|
|
35
38
|
name: "Codex CLI",
|
|
36
|
-
version: "0.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
url: "cli:codex exec --help; codex features list",
|
|
39
|
+
version: "0.160.0",
|
|
40
|
+
claims: [
|
|
41
|
+
claim("Observed on the Mac: codex exec <prompt> -m <model> -c model_reasoning_effort=<level> --json -o <file>; --output-schema, review, resume and fork are available.", {
|
|
42
|
+
url: "cli:codex --version; codex exec --help",
|
|
41
43
|
checkedAt: CHECKED,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"Carry the task end to end in this turn: gather context, implement, run the checks, and report the evidence.",
|
|
44
|
+
authority: "local",
|
|
45
|
+
locator: "Codex 0.160.0, Mac; research/anthropic-openai.md#local-codex-catalog-evidence",
|
|
46
|
+
}, "local-observation"),
|
|
47
|
+
claim("model_instructions_file replaces model instructions. Reasoning support is model/client-specific; a requested effort does not establish the effective effort.", codexConfig),
|
|
48
|
+
claim("Current local Codex spawns subagents after a direct request or applicable project/skill instruction. Enabled features do not establish tool exposure in another integration.", codexAgents),
|
|
49
|
+
claim("/goal tracks an interactive objective; it does not establish recovery across host or process restarts.", codexCommands),
|
|
49
50
|
],
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"`--output-schema <file>` enforces structured output. `codex review` runs a non-interactive review.",
|
|
53
|
-
"Reasoning levels are per model; read them from `$CODEX_HOME/models_cache.json`.",
|
|
54
|
-
"System-prompt replacement uses the `model_instructions_file` config key; standing instructions go in AGENTS.md.",
|
|
55
|
-
"`/goal` runs long unattended work; `resume` and `fork` continue a session.",
|
|
56
|
-
],
|
|
57
|
-
},
|
|
58
|
-
{
|
|
51
|
+
}),
|
|
52
|
+
kbEntry({
|
|
59
53
|
id: "opencode",
|
|
60
54
|
name: "OpenCode",
|
|
61
|
-
version: "1.18.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
prompt: [
|
|
67
|
-
"Delegate a focused subtask to a named agent when its persona or model fits the subtask.",
|
|
68
|
-
"Use the mounted MCP tools for external actions.",
|
|
69
|
-
],
|
|
70
|
-
operator: [
|
|
71
|
-
"Headless: `opencode run <message> -m <provider/model> --agent <name> --variant <effort> --format json`.",
|
|
72
|
-
"Standing text goes through `instructions` files or appended system text; the built-in prompt stays in place.",
|
|
73
|
-
"`opencode serve` with `run --attach <url>`, or `opencode acp`, gives a parent live control.",
|
|
55
|
+
version: "1.18.34",
|
|
56
|
+
claims: [
|
|
57
|
+
claim("Headless: opencode run <message> -m <provider/model> --agent <name> --variant <variant> --format json. Variants are provider-specific.", opencodeCli),
|
|
58
|
+
claim("A configured agent.prompt replaces the provider prompt before system/user additions; plugins can transform it further. Do not assume the provider prompt is retained.", opencodePrompt),
|
|
59
|
+
claim("serve exposes an HTTP API, run --attach reuses that server, and acp exposes an IDE protocol; these capabilities do not establish a particular parent adapter's support.", opencodeCli),
|
|
74
60
|
],
|
|
75
|
-
},
|
|
76
|
-
{
|
|
61
|
+
}),
|
|
62
|
+
kbEntry({
|
|
77
63
|
id: "pi",
|
|
78
64
|
name: "Pi",
|
|
79
|
-
version: "0.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
url: "https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/rpc.md",
|
|
87
|
-
checkedAt: CHECKED,
|
|
88
|
-
},
|
|
89
|
-
{ url: "cli:pi --help", checkedAt: CHECKED, note: "0.87.1" },
|
|
90
|
-
],
|
|
91
|
-
prompt: [
|
|
92
|
-
"Expect steering messages mid-run and fold each one into the current plan.",
|
|
93
|
-
"Fan out independent work by running `pi -p <task> --mode json` from bash, several at once, and read the results back.",
|
|
94
|
-
],
|
|
95
|
-
operator: [
|
|
96
|
-
"Headless: `pi -p <prompt> --model <provider/id[:thinking]> --mode json`.",
|
|
97
|
-
"`--mode rpc` takes JSONL commands on stdin (steer, follow-up, set model, compact, fork) for live control.",
|
|
98
|
-
"`--thinking` takes off, minimal, low, medium, high, xhigh, or max.",
|
|
99
|
-
"`--system-prompt` replaces the default; `--append-system-prompt` adds to it.",
|
|
65
|
+
version: "1.0.2",
|
|
66
|
+
claims: [
|
|
67
|
+
claim("Headless: pi -p <prompt> --model <provider/id[:thinking]> --mode json. Model arguments can fuzzy-match; inspect the selected identity. --thinking clamps to model capability.", piCli),
|
|
68
|
+
claim("--system-prompt replaces the default; --append-system-prompt adds to it. JSON mode exits after supplied prompts; RPC stays alive on stdin/stdout.", piCli),
|
|
69
|
+
claim("In Pi 1.0.2 RPC, prompt acceptance and agent_end do not prove settlement: wait for agent_settled, except a handled prompt that began no run.", piRpc),
|
|
70
|
+
claim("RPC steering arrives after current tool calls, before the next model call; follow-ups wait for tool calls and steering to drain. Query get_available_thinking_levels for the selected model.", piCommands),
|
|
100
71
|
],
|
|
101
|
-
},
|
|
102
|
-
{
|
|
72
|
+
}),
|
|
73
|
+
kbEntry({
|
|
103
74
|
id: "kimi-code",
|
|
104
75
|
name: "Kimi Code CLI",
|
|
105
|
-
version: "2.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
note: "2.0.2",
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
prompt: [
|
|
115
|
-
"Plan the change first, then edit and verify each step against tests and runtime output.",
|
|
116
|
-
],
|
|
117
|
-
operator: [
|
|
118
|
-
"Headless: `kimi -p <prompt> -m kimi-code/k3 --output-format stream-json`.",
|
|
119
|
-
"`--auto` runs fully autonomous; `--agent-file <path>` loads an agent definition; `--plan` starts in plan mode.",
|
|
120
|
-
"Effort is the `[thinking] effort` key in `~/.kimi-code/config.toml`: low, high, or max.",
|
|
76
|
+
version: "2.1.1",
|
|
77
|
+
claims: [
|
|
78
|
+
claim("Headless: kimi -p <prompt> -m <configured-alias> --output-format stream-json. Print mode already uses auto policy with static deny rules; it rejects --auto, --yolo and --plan.", kimiCli),
|
|
79
|
+
claim("--agent-file selects a new session's custom agent and cannot combine with resume/continue.", kimiCli),
|
|
80
|
+
claim("kimi-code/k3 is a configured coding-provider alias, not Moonshot's public API ID kimi-k3. Configuration lives under KIMI_CODE_HOME or ~/.kimi-code.", kimiConfig),
|
|
81
|
+
claim("[thinking].effort is model-dependent; unsupported settings fall back to the model default. The documented K3 configuration supports low, high and max.", kimiConfig),
|
|
121
82
|
],
|
|
122
|
-
},
|
|
83
|
+
}),
|
|
123
84
|
];
|
|
@@ -20,8 +20,8 @@ export { composeAgentProfileGuidance, profileKbDiscrepancies, profileKbHarnesses
|
|
|
20
20
|
* replaces blocks from these sources and keeps blocks any other layer added.
|
|
21
21
|
*/
|
|
22
22
|
export declare const PROFILE_KB_SOURCES: readonly ["harness", "model", "learning"];
|
|
23
|
-
/** Date the
|
|
24
|
-
export declare const PROFILE_KB_CHECKED_AT = "2026-
|
|
23
|
+
/** Date of the latest source audit; individual historical observations retain their own dates. */
|
|
24
|
+
export declare const PROFILE_KB_CHECKED_AT = "2026-10-04";
|
|
25
25
|
/** Find a harness entry by its {@link HarnessType}. */
|
|
26
26
|
export declare function findProfileKbHarness(harness: HarnessType | string | undefined): ProfileKbHarness | undefined;
|
|
27
27
|
/**
|
package/dist/profile-kb/index.js
CHANGED
|
@@ -18,8 +18,8 @@ export { composeAgentProfileGuidance, profileKbDiscrepancies, profileKbHarnesses
|
|
|
18
18
|
* replaces blocks from these sources and keeps blocks any other layer added.
|
|
19
19
|
*/
|
|
20
20
|
export const PROFILE_KB_SOURCES = ["harness", "model", "learning"];
|
|
21
|
-
/** Date the
|
|
22
|
-
export const PROFILE_KB_CHECKED_AT = "2026-
|
|
21
|
+
/** Date of the latest source audit; individual historical observations retain their own dates. */
|
|
22
|
+
export const PROFILE_KB_CHECKED_AT = "2026-10-04";
|
|
23
23
|
/** Find a harness entry by its {@link HarnessType}. */
|
|
24
24
|
export function findProfileKbHarness(harness) {
|
|
25
25
|
if (!harness)
|
|
@@ -118,14 +118,14 @@ export function profileKbGuidance(selection) {
|
|
|
118
118
|
blocks.push({
|
|
119
119
|
source: "harness",
|
|
120
120
|
id: harness.id,
|
|
121
|
-
text: `
|
|
121
|
+
text: `Harness guidance: ${harness.name}.\n${bullets(harness.prompt)}`,
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
if (model && model.prompt.length > 0) {
|
|
125
125
|
blocks.push({
|
|
126
126
|
source: "model",
|
|
127
127
|
id: model.id,
|
|
128
|
-
text: `
|
|
128
|
+
text: `Model guidance: ${model.name}.\n${bullets(model.prompt)}`,
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
const learnings = learningsFor(harness, model);
|
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
import type { ProfileKbModel } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Current frontier models, from vendor sources read on 2026-09-22.
|
|
4
|
-
*
|
|
5
|
-
* `prompt` lines go into the model's prompt; `operator` lines configure the
|
|
6
|
-
* run. Vendor facts carry their source. Nothing here compares one model with
|
|
7
|
-
* another.
|
|
8
|
-
*/
|
|
2
|
+
/** Source-backed facts and conditional advice. API controls never become agent instructions. */
|
|
9
3
|
export declare const profileKbModels: readonly ProfileKbModel[];
|