@tangle-network/agent-interface 0.7.0 → 0.9.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/dist/agent-profile.d.ts +7 -4
- package/dist/harness-capabilities.d.ts +46 -0
- package/dist/harness-capabilities.js +105 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/profile-schema.d.ts +2 -0
- package/dist/profile-schema.js +1 -1
- package/package.json +1 -1
package/dist/agent-profile.d.ts
CHANGED
|
@@ -87,11 +87,14 @@ export interface AgentProfileResources {
|
|
|
87
87
|
/**
|
|
88
88
|
* Portable reasoning/thinking effort. Backends map it to their native control at materialization:
|
|
89
89
|
* codex `model_reasoning_effort`, kimi `--thinking`/`--no-thinking`, claude thinking budget.
|
|
90
|
-
* Ordered low→high:
|
|
91
|
-
*
|
|
92
|
-
*
|
|
90
|
+
* Ordered low→high:
|
|
91
|
+
* - `none` — extended thinking OFF (no reasoning budget at all)
|
|
92
|
+
* - `minimal` — thinking ON, the lowest budget (distinct from `none`)
|
|
93
|
+
* - `low` / `medium` / `high` / `xhigh`
|
|
94
|
+
* - `ultracode` — maximum (claude-code's "ultracode" run mode; codex's `max` reconciles here).
|
|
95
|
+
* A backend without a matching native tier clamps to its nearest (e.g. codex maps `xhigh`/`ultracode` → `high`).
|
|
93
96
|
*/
|
|
94
|
-
export type ReasoningEffort = 'none' | 'low' | 'medium' | 'high' | 'xhigh' | 'ultracode';
|
|
97
|
+
export type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'ultracode';
|
|
95
98
|
/**
|
|
96
99
|
* Model selection hints for backends.
|
|
97
100
|
*/
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ReasoningEffort } from "./agent-profile.js";
|
|
2
|
+
import { type HarnessType } from "./harness.js";
|
|
3
|
+
/**
|
|
4
|
+
* The unified harness capability layer — the single source of truth for:
|
|
5
|
+
* 1. harness ↔ model compatibility (which models a harness can run), and
|
|
6
|
+
* 2. reasoning-effort support (which thinking levels a harness/model expresses).
|
|
7
|
+
*
|
|
8
|
+
* Both are facets of the same question — "what can this (harness, model) pair actually do" — and
|
|
9
|
+
* apply to BOTH harness-backed systems (vendor-locked CLIs like claude-code/codex/kimi) AND
|
|
10
|
+
* router-backed systems (opencode, cli-base: any model the router serves). Lifted here so the
|
|
11
|
+
* cli-bridge backends, the sandbox UI pickers, and the router all read one truth instead of each
|
|
12
|
+
* hand-rolling a divergent copy.
|
|
13
|
+
*
|
|
14
|
+
* Grounded in cli-bridge's real backend clamps (codex caps at `high`, kimi is binary on/off, claude
|
|
15
|
+
* carries the full range, cli-base has no agent) — NOT a guessed matrix. The per-MODEL reasoning
|
|
16
|
+
* capability (does this specific model reason at all) is dynamic catalog data the caller supplies.
|
|
17
|
+
*/
|
|
18
|
+
/** low → high. `none` = thinking off; `ultracode` = max (claude-code mode). */
|
|
19
|
+
export declare const reasoningLadder: readonly ReasoningEffort[];
|
|
20
|
+
/** Provider prefix of a canonical model id (`anthropic/claude-…` → `anthropic`), or null. */
|
|
21
|
+
export declare function modelProvider(modelId: string): string | null;
|
|
22
|
+
/** The providers a harness is locked to, or `null` when it is router-backed (any model). */
|
|
23
|
+
export declare function harnessProviders(harness: HarnessType): readonly string[] | null;
|
|
24
|
+
/**
|
|
25
|
+
* Whether a harness can run a model. Router-backed harnesses (no provider lock) accept anything;
|
|
26
|
+
* a model id with no provider prefix (a sentinel like `default`) is treated as compatible too.
|
|
27
|
+
*/
|
|
28
|
+
export declare function harnessSupportsModel(harness: HarnessType, modelId: string): boolean;
|
|
29
|
+
/** The harness to adopt for a model whose provider is vendor-locked (`anthropic` → `claude-code`,
|
|
30
|
+
* `openai` → `codex`, `moonshot` → `kimi-code`); `null` when any router-backed harness will do. */
|
|
31
|
+
export declare function preferredHarnessForModel(modelId: string): HarnessType | null;
|
|
32
|
+
/** The reasoning efforts a harness can express, independent of model — `none` up to its ceiling. */
|
|
33
|
+
export declare function harnessReasoningEfforts(harness: HarnessType): readonly ReasoningEffort[];
|
|
34
|
+
/** What the caller knows about a model's own reasoning capability (from a model catalog). */
|
|
35
|
+
export interface ModelReasoningCapability {
|
|
36
|
+
/** Does the model reason at all? `false` → only `none` is offered, on any harness. */
|
|
37
|
+
supportsReasoning?: boolean;
|
|
38
|
+
/** The model's own ceiling, if narrower than the harness's. */
|
|
39
|
+
maxEffort?: ReasoningEffort;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The effective reasoning efforts for a (harness, model) pair: the harness clamp, further narrowed by
|
|
43
|
+
* the model's own capability. A model that doesn't reason collapses to `['none']`; a model with a
|
|
44
|
+
* lower ceiling caps the list there. Pass `model` from your catalog; omit it for the harness-only set.
|
|
45
|
+
*/
|
|
46
|
+
export declare function reasoningEffortsFor(harness: HarnessType, model?: ModelReasoningCapability | null): readonly ReasoningEffort[];
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { canonicalizeHarness } from "./harness.js";
|
|
2
|
+
/**
|
|
3
|
+
* The unified harness capability layer — the single source of truth for:
|
|
4
|
+
* 1. harness ↔ model compatibility (which models a harness can run), and
|
|
5
|
+
* 2. reasoning-effort support (which thinking levels a harness/model expresses).
|
|
6
|
+
*
|
|
7
|
+
* Both are facets of the same question — "what can this (harness, model) pair actually do" — and
|
|
8
|
+
* apply to BOTH harness-backed systems (vendor-locked CLIs like claude-code/codex/kimi) AND
|
|
9
|
+
* router-backed systems (opencode, cli-base: any model the router serves). Lifted here so the
|
|
10
|
+
* cli-bridge backends, the sandbox UI pickers, and the router all read one truth instead of each
|
|
11
|
+
* hand-rolling a divergent copy.
|
|
12
|
+
*
|
|
13
|
+
* Grounded in cli-bridge's real backend clamps (codex caps at `high`, kimi is binary on/off, claude
|
|
14
|
+
* carries the full range, cli-base has no agent) — NOT a guessed matrix. The per-MODEL reasoning
|
|
15
|
+
* capability (does this specific model reason at all) is dynamic catalog data the caller supplies.
|
|
16
|
+
*/
|
|
17
|
+
/** low → high. `none` = thinking off; `ultracode` = max (claude-code mode). */
|
|
18
|
+
export const reasoningLadder = [
|
|
19
|
+
"none",
|
|
20
|
+
"minimal",
|
|
21
|
+
"low",
|
|
22
|
+
"medium",
|
|
23
|
+
"high",
|
|
24
|
+
"xhigh",
|
|
25
|
+
"ultracode",
|
|
26
|
+
];
|
|
27
|
+
// ── Harness ↔ model compatibility ────────────────────────────────────────────
|
|
28
|
+
/**
|
|
29
|
+
* Provider prefixes a harness is vendor-locked to (canonical-id prefix, e.g. `anthropic`, `openai`).
|
|
30
|
+
* A harness with no entry is router-backed: it runs any model. Keyed by the BASE runner — aliases
|
|
31
|
+
* (`claude`/`claudish`/`kimi`) resolve through `canonicalizeHarness` first.
|
|
32
|
+
*/
|
|
33
|
+
const harnessProviderLock = {
|
|
34
|
+
"claude-code": ["anthropic"],
|
|
35
|
+
nanoclaw: ["anthropic"],
|
|
36
|
+
codex: ["openai"],
|
|
37
|
+
"kimi-code": ["moonshot"],
|
|
38
|
+
};
|
|
39
|
+
/** Provider prefix of a canonical model id (`anthropic/claude-…` → `anthropic`), or null. */
|
|
40
|
+
export function modelProvider(modelId) {
|
|
41
|
+
const slash = modelId.indexOf("/");
|
|
42
|
+
return slash > 0 ? modelId.slice(0, slash) : null;
|
|
43
|
+
}
|
|
44
|
+
/** The providers a harness is locked to, or `null` when it is router-backed (any model). */
|
|
45
|
+
export function harnessProviders(harness) {
|
|
46
|
+
return harnessProviderLock[canonicalizeHarness(harness)] ?? null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether a harness can run a model. Router-backed harnesses (no provider lock) accept anything;
|
|
50
|
+
* a model id with no provider prefix (a sentinel like `default`) is treated as compatible too.
|
|
51
|
+
*/
|
|
52
|
+
export function harnessSupportsModel(harness, modelId) {
|
|
53
|
+
const providers = harnessProviders(harness);
|
|
54
|
+
if (!providers)
|
|
55
|
+
return true;
|
|
56
|
+
const provider = modelProvider(modelId);
|
|
57
|
+
return provider === null || providers.includes(provider);
|
|
58
|
+
}
|
|
59
|
+
/** The harness to adopt for a model whose provider is vendor-locked (`anthropic` → `claude-code`,
|
|
60
|
+
* `openai` → `codex`, `moonshot` → `kimi-code`); `null` when any router-backed harness will do. */
|
|
61
|
+
export function preferredHarnessForModel(modelId) {
|
|
62
|
+
const provider = modelProvider(modelId);
|
|
63
|
+
if (!provider)
|
|
64
|
+
return null;
|
|
65
|
+
for (const [harness, providers] of Object.entries(harnessProviderLock)) {
|
|
66
|
+
if (providers?.includes(provider))
|
|
67
|
+
return harness;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// ── Reasoning-effort support ──────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* The highest reasoning effort a harness's runtime can express (its native clamp ceiling). Grounded
|
|
74
|
+
* in cli-bridge: codex's `model_reasoning_effort` caps at `high` (xhigh/ultracode clamp down); kimi's
|
|
75
|
+
* `--thinking` is binary, so `high` is its "on"; claude-code carries the full range; `cli-base` has
|
|
76
|
+
* no agent and thus no thinking. Router/model-driven harnesses default to the full range.
|
|
77
|
+
*/
|
|
78
|
+
const harnessReasoningCeiling = {
|
|
79
|
+
"cli-base": "none",
|
|
80
|
+
codex: "high",
|
|
81
|
+
"kimi-code": "high",
|
|
82
|
+
"claude-code": "ultracode",
|
|
83
|
+
nanoclaw: "ultracode",
|
|
84
|
+
};
|
|
85
|
+
/** The reasoning efforts a harness can express, independent of model — `none` up to its ceiling. */
|
|
86
|
+
export function harnessReasoningEfforts(harness) {
|
|
87
|
+
const ceiling = harnessReasoningCeiling[canonicalizeHarness(harness)] ?? "ultracode";
|
|
88
|
+
return reasoningLadder.slice(0, reasoningLadder.indexOf(ceiling) + 1);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The effective reasoning efforts for a (harness, model) pair: the harness clamp, further narrowed by
|
|
92
|
+
* the model's own capability. A model that doesn't reason collapses to `['none']`; a model with a
|
|
93
|
+
* lower ceiling caps the list there. Pass `model` from your catalog; omit it for the harness-only set.
|
|
94
|
+
*/
|
|
95
|
+
export function reasoningEffortsFor(harness, model) {
|
|
96
|
+
if (model?.supportsReasoning === false)
|
|
97
|
+
return ["none"];
|
|
98
|
+
let efforts = harnessReasoningEfforts(harness);
|
|
99
|
+
if (model?.maxEffort) {
|
|
100
|
+
const cap = reasoningLadder.indexOf(model.maxEffort);
|
|
101
|
+
if (cap >= 0)
|
|
102
|
+
efforts = efforts.filter((e) => reasoningLadder.indexOf(e) <= cap);
|
|
103
|
+
}
|
|
104
|
+
return efforts;
|
|
105
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/profile-schema.d.ts
CHANGED
|
@@ -118,6 +118,7 @@ export declare const agentProfileModelHintsSchema: z.ZodObject<{
|
|
|
118
118
|
provider: z.ZodOptional<z.ZodString>;
|
|
119
119
|
reasoningEffort: z.ZodOptional<z.ZodEnum<{
|
|
120
120
|
none: "none";
|
|
121
|
+
minimal: "minimal";
|
|
121
122
|
low: "low";
|
|
122
123
|
medium: "medium";
|
|
123
124
|
high: "high";
|
|
@@ -211,6 +212,7 @@ export declare const agentProfileSchema: z.ZodObject<{
|
|
|
211
212
|
provider: z.ZodOptional<z.ZodString>;
|
|
212
213
|
reasoningEffort: z.ZodOptional<z.ZodEnum<{
|
|
213
214
|
none: "none";
|
|
215
|
+
minimal: "minimal";
|
|
214
216
|
low: "low";
|
|
215
217
|
medium: "medium";
|
|
216
218
|
high: "high";
|
package/dist/profile-schema.js
CHANGED
|
@@ -37,7 +37,7 @@ export const agentProfileModelHintsSchema = z.object({
|
|
|
37
37
|
default: z.string().optional(),
|
|
38
38
|
small: z.string().optional(),
|
|
39
39
|
provider: z.string().optional(),
|
|
40
|
-
reasoningEffort: z.enum(['none', 'low', 'medium', 'high', 'xhigh', 'ultracode']).optional(),
|
|
40
|
+
reasoningEffort: z.enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'ultracode']).optional(),
|
|
41
41
|
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
42
42
|
});
|
|
43
43
|
export const agentProfilePromptSchema = z.object({
|