@tangle-network/agent-app 0.60.170 → 0.60.171

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.
@@ -8,15 +8,15 @@ import "../chunk-FBVLEGEG.js";
8
8
  import "../chunk-CW6F6GDP.js";
9
9
  import "../chunk-ILZQAXJH.js";
10
10
  import "../chunk-E4AY62T2.js";
11
- import "../chunk-CCTQQ45L.js";
11
+ import "../chunk-CRHXK3QT.js";
12
12
  import "../chunk-Y6PRDUFJ.js";
13
13
  import "../chunk-GEYACSFW.js";
14
14
  import {
15
15
  ChatComposer
16
- } from "../chunk-ZEMO7S2G.js";
16
+ } from "../chunk-PZHZV6QY.js";
17
17
  import "../chunk-L7MB2LLM.js";
18
18
  import "../chunk-SJWIZT7B.js";
19
- import "../chunk-XSPUKVHF.js";
19
+ import "../chunk-KICTB6RK.js";
20
20
  import "../chunk-R5K5ML3Q.js";
21
21
  import {
22
22
  ModelPicker
@@ -27,7 +27,7 @@ import {
27
27
  } from "../chunk-LSUELMHY.js";
28
28
  import "../chunk-FQYAJYPW.js";
29
29
  import "../chunk-WTC6AOPL.js";
30
- import "../chunk-WVESWAJJ.js";
30
+ import "../chunk-MXNVSY6J.js";
31
31
  import "../chunk-B7CL7ENS.js";
32
32
  import "../chunk-PV33JZKV.js";
33
33
  import "../chunk-AMUXRAUO.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ComposerModeControls,
3
3
  EntryComposer
4
- } from "../chunk-ZEMO7S2G.js";
4
+ } from "../chunk-PZHZV6QY.js";
5
5
  import "../chunk-L7MB2LLM.js";
6
6
  import "../chunk-SJWIZT7B.js";
7
- import "../chunk-XSPUKVHF.js";
7
+ import "../chunk-KICTB6RK.js";
8
8
  import "../chunk-R5K5ML3Q.js";
9
9
  import "../chunk-AA4FKEQW.js";
10
10
  import "../chunk-RASGKEAL.js";
11
11
  import "../chunk-WTC6AOPL.js";
12
- import "../chunk-WVESWAJJ.js";
12
+ import "../chunk-MXNVSY6J.js";
13
13
  import "../chunk-AMUXRAUO.js";
14
14
  import "../chunk-YHRWZZJN.js";
15
15
  import "../chunk-TXD5HXLE.js";
@@ -42,9 +42,9 @@ import {
42
42
  flattenHistory,
43
43
  readSandboxBinaryBytes,
44
44
  statSandboxFileSize
45
- } from "../chunk-4DZVSTET.js";
45
+ } from "../chunk-RCRC2JKP.js";
46
46
  import "../chunk-4LBCTFBP.js";
47
- import "../chunk-WVESWAJJ.js";
47
+ import "../chunk-MXNVSY6J.js";
48
48
  import "../chunk-LWSJK546.js";
49
49
  import "../chunk-74WXGIEK.js";
50
50
  import "../chunk-6A7MYOUI.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HarnessPicker,
3
3
  filterAcceptedFiles
4
- } from "./chunk-XSPUKVHF.js";
4
+ } from "./chunk-KICTB6RK.js";
5
5
  import {
6
6
  EffortPicker,
7
7
  ModelPicker,
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  isModelCompatibleWithHarness,
15
15
  snapModelToHarness
16
- } from "./chunk-WVESWAJJ.js";
16
+ } from "./chunk-MXNVSY6J.js";
17
17
  import {
18
18
  isCommitSha,
19
19
  parseGitHubLocation,
@@ -2214,4 +2214,4 @@ export {
2214
2214
  AGENT_PROFILE_EDITOR_SECTIONS,
2215
2215
  AgentProfileEditor
2216
2216
  };
2217
- //# sourceMappingURL=chunk-CCTQQ45L.js.map
2217
+ //# sourceMappingURL=chunk-CRHXK3QT.js.map
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  snapHarnessToModel,
17
17
  snapModelToHarness
18
- } from "./chunk-WVESWAJJ.js";
18
+ } from "./chunk-MXNVSY6J.js";
19
19
 
20
20
  // src/web-react/composer-file-accept.ts
21
21
  function isAcceptedFileType(file, accept) {
@@ -576,4 +576,4 @@ export {
576
576
  HarnessPicker,
577
577
  AgentSessionControls
578
578
  };
579
- //# sourceMappingURL=chunk-XSPUKVHF.js.map
579
+ //# sourceMappingURL=chunk-KICTB6RK.js.map
@@ -83,6 +83,31 @@ function assertHarnessModelCompatible(harness, selection) {
83
83
  );
84
84
  }
85
85
  }
86
+ var HARNESS_CAPABILITIES = {
87
+ "claude-code": { subagents: true, mcp: "native", toolControls: "runtime", skillsDir: ".claude/skills" },
88
+ nanoclaw: { subagents: true, mcp: "native", toolControls: "runtime", skillsDir: ".claude/skills" },
89
+ opencode: { subagents: true, mcp: "config-file", toolControls: "runtime", skillsDir: ".opencode/skills" },
90
+ codex: { subagents: true, mcp: "config-file", toolControls: "runtime", skillsDir: ".codex/skills" },
91
+ "kimi-code": { subagents: false, mcp: "config-file", toolControls: "runtime", skillsDir: ".kimi/skills" },
92
+ pi: { subagents: false, mcp: "extension", toolControls: "startup", skillsDir: ".pi/skills" },
93
+ prime: { subagents: true, mcp: "native", toolControls: "runtime", skillsDir: ".prime/agent/skills" },
94
+ hermes: { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null },
95
+ openclaw: { subagents: false, mcp: "config-file", toolControls: "runtime", skillsDir: "skills" },
96
+ // Harnesses the platform placement map does not bridge yet: conservative
97
+ // facts — assert nothing they have not proven. Each upgrades to its real
98
+ // facts when the materializer grows support for it.
99
+ acp: { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null },
100
+ amp: { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null },
101
+ "factory-droids": { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null },
102
+ forge: { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null },
103
+ cursor: { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null },
104
+ "cli-base": { subagents: false, mcp: "native", toolControls: "runtime", skillsDir: null }
105
+ };
106
+ function harnessCapabilities(harness) {
107
+ const caps = HARNESS_CAPABILITIES[harness];
108
+ if (!caps) throw new Error(`harnessCapabilities: no capability facts for "${harness}"`);
109
+ return caps;
110
+ }
86
111
 
87
112
  export {
88
113
  modelProvider,
@@ -95,6 +120,7 @@ export {
95
120
  isModelCompatibleWithHarness,
96
121
  snapModelToHarness,
97
122
  snapHarnessToModel,
98
- assertHarnessModelCompatible
123
+ assertHarnessModelCompatible,
124
+ harnessCapabilities
99
125
  };
100
- //# sourceMappingURL=chunk-WVESWAJJ.js.map
126
+ //# sourceMappingURL=chunk-MXNVSY6J.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/harness/index.ts"],"sourcesContent":["/**\n * Coding-agent harness selection — taxonomy, coercion, and the session-lock invariant.\n *\n * A \"harness\" is the coding-agent CLI a sandbox drives (opencode / codex /\n * claude-code / …). The shell governs WHICH harness a chat session uses and\n * enforces that a session is LOCKED to the harness it started with — the model\n * may change mid-session, the harness may not (swapping it mid-session would\n * orphan the session's running agent state). Every product otherwise hand-rolls\n * this and hard-codes a single harness; this is the one place the rule lives.\n *\n * Substrate-free: the harness list is derived from `@tangle-network/agent-interface`'s canonical\n * harness enum and mirrors the sandbox SDK's `BackendType` (no sandbox dependency). The consumer\n * owns storage — which harness a workspace defaults to, which one a session locked — and maps the\n * resolved value onto the SDK's `backend.type`.\n *\n * Harness↔model COMPATIBILITY (which models a harness can run, snapping) is NOT defined here — it\n * comes from `@tangle-network/agent-interface`, the single source of truth shared with the\n * sandbox-ui pickers and the cli-bridge backends. This module owns the harness TAXONOMY + the\n * session lock, and its server assertion also checks resolved transport-provider evidence.\n */\n\nimport {\n harnessProviders,\n harnessSupportsModel,\n harnessTypeSchema,\n modelProvider,\n preferredHarnessForModel,\n snapHarnessToModel as aiSnapHarnessToModel,\n snapModelToHarness as aiSnapModelToHarness,\n type HarnessType,\n} from '@tangle-network/agent-interface'\n\n/**\n * Canonical harnesses that are NOT sandbox backends. Each value in `KNOWN_HARNESSES` is dispatched\n * as `backend.type`, so a harness the platform ships no provider adapter for must stay out —\n * offering it would resolve a session onto a runner that cannot start.\n */\nconst NON_BACKEND_HARNESSES = ['gemini'] as const satisfies readonly HarnessType[]\n\nconst nonBackendHarnesses = new Set<string>(NON_BACKEND_HARNESSES)\n\n/** A coding-agent backend this shell can dispatch a session onto. */\nexport type Harness = Exclude<HarnessType, (typeof NON_BACKEND_HARNESSES)[number]>\n\n/**\n * The known coding-agent backends: the canonical harness set minus what has no provider adapter,\n * Derived from `harnessTypeSchema.options` so a harness added upstream reaches this shell without\n * an edit here, and kept structural so this module still needs no sandbox dependency.\n */\nexport const KNOWN_HARNESSES: readonly Harness[] = [\n ...harnessTypeSchema.options.filter(\n (harness): harness is Exclude<HarnessType, (typeof NON_BACKEND_HARNESSES)[number]> =>\n !nonBackendHarnesses.has(harness),\n ),\n]\n\n/** Define the default harness to use for code execution and testing environments */\nexport const DEFAULT_HARNESS: Harness = 'opencode'\n\nconst HARNESS_SET: ReadonlySet<string> = new Set(KNOWN_HARNESSES)\n\n/** Determine if a value is a recognized harness string identifier */\nexport function isHarness(value: unknown): value is Harness {\n return typeof value === 'string' && HARNESS_SET.has(value)\n}\n\n/** Coerce an arbitrary value to a known harness, falling back (default `opencode`). */\nexport function coerceHarness(value: unknown, fallback: Harness = DEFAULT_HARNESS): Harness {\n return isHarness(value) ? value : fallback\n}\n\n/** Resolve input options to determine the appropriate session harness to use */\nexport interface ResolveSessionHarnessInput {\n /** The harness already locked to this session (recorded at its first turn). */\n sessionHarness?: unknown\n /** The harness requested now — a new session's choice, or a turn's attempt to switch. */\n requested?: unknown\n /** The workspace's default harness, used only when starting a fresh session. */\n workspaceDefault?: unknown\n /** Final fallback when nothing else resolves (default `opencode`). */\n fallback?: Harness\n}\n\n/** Represent resolved session state including harness, lock status, and swap attempt flag */\nexport interface ResolvedSessionHarness {\n /** The harness to actually run — the locked one when the session already has it. */\n harness: Harness\n /** True when the session already had a locked harness (this turn did not pick it). */\n locked: boolean\n /** True when `requested` differs from the locked harness — a forbidden mid-session\n * swap the caller should reject or warn on. The lock always wins regardless. */\n swapAttempted: boolean\n}\n\n/**\n * Resolve the harness for a turn, enforcing the session lock.\n *\n * - **Session already started** (`sessionHarness` is a known harness): that harness\n * wins (`locked: true`); a differing `requested` sets `swapAttempted` so the caller\n * can reject the swap. The model is a separate per-turn concern and is unaffected.\n * - **Fresh session**: pick `requested → workspaceDefault → fallback`. The caller\n * persists the result as the session's lock for every subsequent turn.\n */\nexport function resolveSessionHarness(input: ResolveSessionHarnessInput = {}): ResolvedSessionHarness {\n const fallback = input.fallback ?? DEFAULT_HARNESS\n if (isHarness(input.sessionHarness)) {\n const locked = input.sessionHarness\n const swapAttempted = isHarness(input.requested) && input.requested !== locked\n return { harness: locked, locked: true, swapAttempted }\n }\n const harness = coerceHarness(input.requested, coerceHarness(input.workspaceDefault, fallback))\n return { harness, locked: false, swapAttempted: false }\n}\n\n/**\n * An app's harness configuration, read from its deploy configuration (for example the env vars\n * `AGENT_HARNESS` and `AGENT_HARNESS_WORKSPACES`), so no product hard-codes `backend.type`.\n */\nexport interface HarnessConfig {\n /** The app default for new sessions. Unset or blank means {@link DEFAULT_HARNESS}. */\n default?: string\n /** Per-workspace choices: a JSON object mapping a workspace id to a harness. */\n workspaces?: string\n}\n\nfunction configHarness(value: unknown, where: string): Harness {\n if (!isHarness(value)) throw new Error(`${where} names an unknown harness: ${String(value)}`)\n return value\n}\n\n/**\n * The harness a workspace's new sessions start on: its own choice, else the app default, else\n * {@link DEFAULT_HARNESS}. Pass the result to {@link resolveSessionHarness} as `workspaceDefault`\n * so a session that already ran keeps its harness. A value naming an unknown harness throws:\n * a configuration typo must fail loudly, never run a different harness than the one configured.\n */\nexport function configuredHarness(config: HarnessConfig, workspaceId?: string): Harness {\n const appDefault = config.default?.trim()\n ? configHarness(config.default.trim(), 'The harness default') : DEFAULT_HARNESS\n const raw = config.workspaces?.trim()\n if (!raw) return appDefault\n let choices: unknown\n try {\n choices = JSON.parse(raw)\n } catch {\n throw new Error('The per-workspace harness configuration is not JSON')\n }\n if (!choices || typeof choices !== 'object' || Array.isArray(choices)) {\n throw new Error('The per-workspace harness configuration must map workspace ids to harnesses')\n }\n // Every entry is checked, not only the caller's, so one bad entry fails every workspace's\n // first turn after the deploy instead of hiding until that workspace sends a message.\n const parsed = new Map(Object.entries(choices).map(([id, value]) =>\n [id, configHarness(value, `The harness for workspace ${id}`)]))\n return (workspaceId === undefined ? undefined : parsed.get(workspaceId)) ?? appDefault\n}\n\n/**\n * Harness ↔ model compatibility + snapping — delegated to `@tangle-network/agent-interface`.\n *\n * `Harness` is the dispatchable subset of `HarnessType`: this shell drops only canonical harnesses\n * for which the platform has no backend. Compatibility therefore comes entirely from Interface;\n * this package keeps no second harness taxonomy.\n */\n\nexport { modelProvider }\n\n/** A resolved model and the transport provider that will execute it. */\nexport interface HarnessModelSelection {\n model: string\n provider?: string\n}\n\n/** Provider-less ids (sentinels like \"default\", or a session's own config) are\n * compatible everywhere — every harness honors its own configuration. */\nexport function isModelCompatibleWithHarness(harness: Harness, modelId: string): boolean {\n return harnessSupportsModel(harness, modelId)\n}\n\n/** Keep `modelId` when the harness can run it; else the harness's best compatible\n * catalog id (preferred patterns in order, highest version). When nothing in the\n * catalog fits, return the original so the caller sees the incompatibility. */\nexport function snapModelToHarness(harness: Harness, modelId: string, canonicalIds: readonly string[]): string {\n return aiSnapModelToHarness(harness, modelId, canonicalIds)\n}\n\n/** Keep the harness when it can run `modelId`; else the model's native harness\n * (anthropic → claude-code, openai → codex, moonshot → kimi-code), falling back to opencode. */\nexport function snapHarnessToModel(harness: Harness, modelId: string): Harness {\n const snapped = aiSnapHarnessToModel(harness, modelId)\n if (!isHarness(snapped)) {\n throw new Error(\n `Harness \"${harness}\" snapped to \"${snapped}\" for model \"${modelId}\", which this platform has no backend for.`,\n )\n }\n return snapped\n}\n\n/** Fail-loud server guard: throw when a harness is asked to run a model it can't.\n * A resolved model tuple supplies provider evidence when its id is unqualified.\n * Call before dispatching a sandbox turn so a bypassed UI cannot reach the\n * sidecar with an incompatible or unproven pair. */\nexport function assertHarnessModelCompatible(\n harness: Harness,\n selection: string | HarnessModelSelection,\n): void {\n const modelId = typeof selection === 'string' ? selection : selection.model\n const transportProvider = typeof selection === 'string' ? undefined : selection.provider\n const providers = harnessProviders(harness)\n const provider = modelProvider(modelId) ?? transportProvider ?? null\n // An omitted/default model is deliberately left to the harness. Once a\n // caller names a model, however, a vendor-locked harness must have provider\n // evidence. Treating a router provider as compatible with every native CLI\n // is how a bare Gemini model reached Claude Code and produced \"Not logged in\".\n const isDefaultSentinel = modelId.trim() === '' || modelId.trim() === 'default'\n const compatible = isDefaultSentinel\n || providers === null\n || (provider !== null && providers.includes(provider))\n if (!compatible) {\n const native = preferredHarnessForModel(modelId)\n const providerDescription = provider ?? 'unqualified'\n throw new Error(\n `Harness \"${harness}\" cannot run model \"${modelId}\" (provider \"${providerDescription}\"). ` +\n `Use ${native ?? 'a router-backed harness (opencode)'} or an allowed model.`,\n )\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/harness/index.ts"],"sourcesContent":["/**\n * Coding-agent harness selection — taxonomy, coercion, and the session-lock invariant.\n *\n * A \"harness\" is the coding-agent CLI a sandbox drives (opencode / codex /\n * claude-code / …). The shell governs WHICH harness a chat session uses and\n * enforces that a session is LOCKED to the harness it started with — the model\n * may change mid-session, the harness may not (swapping it mid-session would\n * orphan the session's running agent state). Every product otherwise hand-rolls\n * this and hard-codes a single harness; this is the one place the rule lives.\n *\n * Substrate-free: the harness list is derived from `@tangle-network/agent-interface`'s canonical\n * harness enum and mirrors the sandbox SDK's `BackendType` (no sandbox dependency). The consumer\n * owns storage — which harness a workspace defaults to, which one a session locked — and maps the\n * resolved value onto the SDK's `backend.type`.\n *\n * Harness↔model COMPATIBILITY (which models a harness can run, snapping) is NOT defined here — it\n * comes from `@tangle-network/agent-interface`, the single source of truth shared with the\n * sandbox-ui pickers and the cli-bridge backends. This module owns the harness TAXONOMY + the\n * session lock, and its server assertion also checks resolved transport-provider evidence.\n */\n\nimport {\n harnessProviders,\n harnessSupportsModel,\n harnessTypeSchema,\n modelProvider,\n preferredHarnessForModel,\n snapHarnessToModel as aiSnapHarnessToModel,\n snapModelToHarness as aiSnapModelToHarness,\n type HarnessType,\n} from '@tangle-network/agent-interface'\n\n/**\n * Canonical harnesses that are NOT sandbox backends. Each value in `KNOWN_HARNESSES` is dispatched\n * as `backend.type`, so a harness the platform ships no provider adapter for must stay out —\n * offering it would resolve a session onto a runner that cannot start.\n */\nconst NON_BACKEND_HARNESSES = ['gemini'] as const satisfies readonly HarnessType[]\n\nconst nonBackendHarnesses = new Set<string>(NON_BACKEND_HARNESSES)\n\n/** A coding-agent backend this shell can dispatch a session onto. */\nexport type Harness = Exclude<HarnessType, (typeof NON_BACKEND_HARNESSES)[number]>\n\n/**\n * The known coding-agent backends: the canonical harness set minus what has no provider adapter,\n * Derived from `harnessTypeSchema.options` so a harness added upstream reaches this shell without\n * an edit here, and kept structural so this module still needs no sandbox dependency.\n */\nexport const KNOWN_HARNESSES: readonly Harness[] = [\n ...harnessTypeSchema.options.filter(\n (harness): harness is Exclude<HarnessType, (typeof NON_BACKEND_HARNESSES)[number]> =>\n !nonBackendHarnesses.has(harness),\n ),\n]\n\n/** Define the default harness to use for code execution and testing environments */\nexport const DEFAULT_HARNESS: Harness = 'opencode'\n\nconst HARNESS_SET: ReadonlySet<string> = new Set(KNOWN_HARNESSES)\n\n/** Determine if a value is a recognized harness string identifier */\nexport function isHarness(value: unknown): value is Harness {\n return typeof value === 'string' && HARNESS_SET.has(value)\n}\n\n/** Coerce an arbitrary value to a known harness, falling back (default `opencode`). */\nexport function coerceHarness(value: unknown, fallback: Harness = DEFAULT_HARNESS): Harness {\n return isHarness(value) ? value : fallback\n}\n\n/** Resolve input options to determine the appropriate session harness to use */\nexport interface ResolveSessionHarnessInput {\n /** The harness already locked to this session (recorded at its first turn). */\n sessionHarness?: unknown\n /** The harness requested now — a new session's choice, or a turn's attempt to switch. */\n requested?: unknown\n /** The workspace's default harness, used only when starting a fresh session. */\n workspaceDefault?: unknown\n /** Final fallback when nothing else resolves (default `opencode`). */\n fallback?: Harness\n}\n\n/** Represent resolved session state including harness, lock status, and swap attempt flag */\nexport interface ResolvedSessionHarness {\n /** The harness to actually run — the locked one when the session already has it. */\n harness: Harness\n /** True when the session already had a locked harness (this turn did not pick it). */\n locked: boolean\n /** True when `requested` differs from the locked harness — a forbidden mid-session\n * swap the caller should reject or warn on. The lock always wins regardless. */\n swapAttempted: boolean\n}\n\n/**\n * Resolve the harness for a turn, enforcing the session lock.\n *\n * - **Session already started** (`sessionHarness` is a known harness): that harness\n * wins (`locked: true`); a differing `requested` sets `swapAttempted` so the caller\n * can reject the swap. The model is a separate per-turn concern and is unaffected.\n * - **Fresh session**: pick `requested → workspaceDefault → fallback`. The caller\n * persists the result as the session's lock for every subsequent turn.\n */\nexport function resolveSessionHarness(input: ResolveSessionHarnessInput = {}): ResolvedSessionHarness {\n const fallback = input.fallback ?? DEFAULT_HARNESS\n if (isHarness(input.sessionHarness)) {\n const locked = input.sessionHarness\n const swapAttempted = isHarness(input.requested) && input.requested !== locked\n return { harness: locked, locked: true, swapAttempted }\n }\n const harness = coerceHarness(input.requested, coerceHarness(input.workspaceDefault, fallback))\n return { harness, locked: false, swapAttempted: false }\n}\n\n/**\n * An app's harness configuration, read from its deploy configuration (for example the env vars\n * `AGENT_HARNESS` and `AGENT_HARNESS_WORKSPACES`), so no product hard-codes `backend.type`.\n */\nexport interface HarnessConfig {\n /** The app default for new sessions. Unset or blank means {@link DEFAULT_HARNESS}. */\n default?: string\n /** Per-workspace choices: a JSON object mapping a workspace id to a harness. */\n workspaces?: string\n}\n\nfunction configHarness(value: unknown, where: string): Harness {\n if (!isHarness(value)) throw new Error(`${where} names an unknown harness: ${String(value)}`)\n return value\n}\n\n/**\n * The harness a workspace's new sessions start on: its own choice, else the app default, else\n * {@link DEFAULT_HARNESS}. Pass the result to {@link resolveSessionHarness} as `workspaceDefault`\n * so a session that already ran keeps its harness. A value naming an unknown harness throws:\n * a configuration typo must fail loudly, never run a different harness than the one configured.\n */\nexport function configuredHarness(config: HarnessConfig, workspaceId?: string): Harness {\n const appDefault = config.default?.trim()\n ? configHarness(config.default.trim(), 'The harness default') : DEFAULT_HARNESS\n const raw = config.workspaces?.trim()\n if (!raw) return appDefault\n let choices: unknown\n try {\n choices = JSON.parse(raw)\n } catch {\n throw new Error('The per-workspace harness configuration is not JSON')\n }\n if (!choices || typeof choices !== 'object' || Array.isArray(choices)) {\n throw new Error('The per-workspace harness configuration must map workspace ids to harnesses')\n }\n // Every entry is checked, not only the caller's, so one bad entry fails every workspace's\n // first turn after the deploy instead of hiding until that workspace sends a message.\n const parsed = new Map(Object.entries(choices).map(([id, value]) =>\n [id, configHarness(value, `The harness for workspace ${id}`)]))\n return (workspaceId === undefined ? undefined : parsed.get(workspaceId)) ?? appDefault\n}\n\n/**\n * Harness ↔ model compatibility + snapping — delegated to `@tangle-network/agent-interface`.\n *\n * `Harness` is the dispatchable subset of `HarnessType`: this shell drops only canonical harnesses\n * for which the platform has no backend. Compatibility therefore comes entirely from Interface;\n * this package keeps no second harness taxonomy.\n */\n\nexport { modelProvider }\n\n/** A resolved model and the transport provider that will execute it. */\nexport interface HarnessModelSelection {\n model: string\n provider?: string\n}\n\n/** Provider-less ids (sentinels like \"default\", or a session's own config) are\n * compatible everywhere — every harness honors its own configuration. */\nexport function isModelCompatibleWithHarness(harness: Harness, modelId: string): boolean {\n return harnessSupportsModel(harness, modelId)\n}\n\n/** Keep `modelId` when the harness can run it; else the harness's best compatible\n * catalog id (preferred patterns in order, highest version). When nothing in the\n * catalog fits, return the original so the caller sees the incompatibility. */\nexport function snapModelToHarness(harness: Harness, modelId: string, canonicalIds: readonly string[]): string {\n return aiSnapModelToHarness(harness, modelId, canonicalIds)\n}\n\n/** Keep the harness when it can run `modelId`; else the model's native harness\n * (anthropic → claude-code, openai → codex, moonshot → kimi-code), falling back to opencode. */\nexport function snapHarnessToModel(harness: Harness, modelId: string): Harness {\n const snapped = aiSnapHarnessToModel(harness, modelId)\n if (!isHarness(snapped)) {\n throw new Error(\n `Harness \"${harness}\" snapped to \"${snapped}\" for model \"${modelId}\", which this platform has no backend for.`,\n )\n }\n return snapped\n}\n\n/** Fail-loud server guard: throw when a harness is asked to run a model it can't.\n * A resolved model tuple supplies provider evidence when its id is unqualified.\n * Call before dispatching a sandbox turn so a bypassed UI cannot reach the\n * sidecar with an incompatible or unproven pair. */\nexport function assertHarnessModelCompatible(\n harness: Harness,\n selection: string | HarnessModelSelection,\n): void {\n const modelId = typeof selection === 'string' ? selection : selection.model\n const transportProvider = typeof selection === 'string' ? undefined : selection.provider\n const providers = harnessProviders(harness)\n const provider = modelProvider(modelId) ?? transportProvider ?? null\n // An omitted/default model is deliberately left to the harness. Once a\n // caller names a model, however, a vendor-locked harness must have provider\n // evidence. Treating a router provider as compatible with every native CLI\n // is how a bare Gemini model reached Claude Code and produced \"Not logged in\".\n const isDefaultSentinel = modelId.trim() === '' || modelId.trim() === 'default'\n const compatible = isDefaultSentinel\n || providers === null\n || (provider !== null && providers.includes(provider))\n if (!compatible) {\n const native = preferredHarnessForModel(modelId)\n const providerDescription = provider ?? 'unqualified'\n throw new Error(\n `Harness \"${harness}\" cannot run model \"${modelId}\" (provider \"${providerDescription}\"). ` +\n `Use ${native ?? 'a router-backed harness (opencode)'} or an allowed model.`,\n )\n }\n}\n\n// ── Harness capabilities ───────────────────────────────────────────────────\n//\n// The one place a product learns WHAT a harness can express, before it\n// assembles a profile — so incompatible content is never added in the first\n// place instead of being dropped (or refused) after the fact. Facts here are\n// sourced from the platform materializer's behavior (the per-harness subagent\n// lowering, the MCP config channel, the startup control validation) and the\n// placement map; when those change, this table changes with them.\n\n/** What a harness can express, for profile assembly. */\nexport interface HarnessCapabilities {\n /** Lower `profile.subagents` into native cwd files (e.g. `.claude/agents/`).\n * False: a profile carrying subagents is refused at materialization —\n * builders must not add them. */\n subagents: boolean\n /** How `profile.mcp` reaches the harness. */\n mcp: 'native' | 'config-file' | 'extension' | 'none'\n /** When tool controls are validated: 'startup' means an allowlist naming\n * MCP-carried verbs is checked before MCP tools register (spawn-time\n * validation refuses unknown names); 'runtime' tolerates them. */\n toolControls: 'startup' | 'runtime'\n /** cwd-relative directory `resources.skills` materializes into, or null\n * when the harness has no cwd skill primitive (falls back to inline). */\n skillsDir: string | null\n}\n\nconst HARNESS_CAPABILITIES: Record<Harness, HarnessCapabilities> = {\n 'claude-code': { subagents: true, mcp: 'native', toolControls: 'runtime', skillsDir: '.claude/skills' },\n nanoclaw: { subagents: true, mcp: 'native', toolControls: 'runtime', skillsDir: '.claude/skills' },\n opencode: { subagents: true, mcp: 'config-file', toolControls: 'runtime', skillsDir: '.opencode/skills' },\n codex: { subagents: true, mcp: 'config-file', toolControls: 'runtime', skillsDir: '.codex/skills' },\n 'kimi-code': { subagents: false, mcp: 'config-file', toolControls: 'runtime', skillsDir: '.kimi/skills' },\n pi: { subagents: false, mcp: 'extension', toolControls: 'startup', skillsDir: '.pi/skills' },\n prime: { subagents: true, mcp: 'native', toolControls: 'runtime', skillsDir: '.prime/agent/skills' },\n hermes: { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n openclaw: { subagents: false, mcp: 'config-file', toolControls: 'runtime', skillsDir: 'skills' },\n // Harnesses the platform placement map does not bridge yet: conservative\n // facts — assert nothing they have not proven. Each upgrades to its real\n // facts when the materializer grows support for it.\n acp: { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n amp: { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n 'factory-droids': { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n forge: { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n cursor: { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n 'cli-base': { subagents: false, mcp: 'native', toolControls: 'runtime', skillsDir: null },\n}\n\n/** The capability facts for `harness`. Every harness in KNOWN_HARNESSES has\n * an entry; the map is exhaustive by construction (tests assert parity). */\nexport function harnessCapabilities(harness: Harness): HarnessCapabilities {\n const caps = HARNESS_CAPABILITIES[harness]\n if (!caps) throw new Error(`harnessCapabilities: no capability facts for \"${harness}\"`)\n return caps\n}\n"],"mappings":"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","names":[]}
@@ -10,7 +10,7 @@ import {
10
10
  filterAcceptedFiles,
11
11
  isAcceptedFileType,
12
12
  renamePastedImages
13
- } from "./chunk-XSPUKVHF.js";
13
+ } from "./chunk-KICTB6RK.js";
14
14
  import {
15
15
  OVERLAY_SHADOW,
16
16
  POPOVER_OPTION_FOCUS,
@@ -1552,4 +1552,4 @@ export {
1552
1552
  ComposerModeControls,
1553
1553
  EntryComposer
1554
1554
  };
1555
- //# sourceMappingURL=chunk-ZEMO7S2G.js.map
1555
+ //# sourceMappingURL=chunk-PZHZV6QY.js.map
@@ -13,7 +13,7 @@ import {
13
13
  DEFAULT_HARNESS,
14
14
  assertHarnessModelCompatible,
15
15
  isHarness
16
- } from "./chunk-WVESWAJJ.js";
16
+ } from "./chunk-MXNVSY6J.js";
17
17
  import {
18
18
  assertProfilePromptWithinBudget,
19
19
  fingerprintAgentProfile
@@ -3343,4 +3343,4 @@ export {
3343
3343
  isTerminalPromptEvent,
3344
3344
  detectInteractiveQuestion
3345
3345
  };
3346
- //# sourceMappingURL=chunk-4DZVSTET.js.map
3346
+ //# sourceMappingURL=chunk-RCRC2JKP.js.map
@@ -115,3 +115,22 @@ export declare function snapHarnessToModel(harness: Harness, modelId: string): H
115
115
  * Call before dispatching a sandbox turn so a bypassed UI cannot reach the
116
116
  * sidecar with an incompatible or unproven pair. */
117
117
  export declare function assertHarnessModelCompatible(harness: Harness, selection: string | HarnessModelSelection): void;
118
+ /** What a harness can express, for profile assembly. */
119
+ export interface HarnessCapabilities {
120
+ /** Lower `profile.subagents` into native cwd files (e.g. `.claude/agents/`).
121
+ * False: a profile carrying subagents is refused at materialization —
122
+ * builders must not add them. */
123
+ subagents: boolean;
124
+ /** How `profile.mcp` reaches the harness. */
125
+ mcp: 'native' | 'config-file' | 'extension' | 'none';
126
+ /** When tool controls are validated: 'startup' means an allowlist naming
127
+ * MCP-carried verbs is checked before MCP tools register (spawn-time
128
+ * validation refuses unknown names); 'runtime' tolerates them. */
129
+ toolControls: 'startup' | 'runtime';
130
+ /** cwd-relative directory `resources.skills` materializes into, or null
131
+ * when the harness has no cwd skill primitive (falls back to inline). */
132
+ skillsDir: string | null;
133
+ }
134
+ /** The capability facts for `harness`. Every harness in KNOWN_HARNESSES has
135
+ * an entry; the map is exhaustive by construction (tests assert parity). */
136
+ export declare function harnessCapabilities(harness: Harness): HarnessCapabilities;
@@ -4,19 +4,21 @@ import {
4
4
  assertHarnessModelCompatible,
5
5
  coerceHarness,
6
6
  configuredHarness,
7
+ harnessCapabilities,
7
8
  isHarness,
8
9
  isModelCompatibleWithHarness,
9
10
  modelProvider,
10
11
  resolveSessionHarness,
11
12
  snapHarnessToModel,
12
13
  snapModelToHarness
13
- } from "../chunk-WVESWAJJ.js";
14
+ } from "../chunk-MXNVSY6J.js";
14
15
  export {
15
16
  DEFAULT_HARNESS,
16
17
  KNOWN_HARNESSES,
17
18
  assertHarnessModelCompatible,
18
19
  coerceHarness,
19
20
  configuredHarness,
21
+ harnessCapabilities,
20
22
  isHarness,
21
23
  isModelCompatibleWithHarness,
22
24
  modelProvider,
@@ -97,7 +97,7 @@ import {
97
97
  warmBinOf,
98
98
  warmWeekdayOf,
99
99
  writeProfileFilesToBox
100
- } from "../chunk-4DZVSTET.js";
100
+ } from "../chunk-RCRC2JKP.js";
101
101
  import {
102
102
  EGRESS_PROXY_RECOVERY_PHASE,
103
103
  EGRESS_PROXY_RECOVERY_REQUIRED,
@@ -136,7 +136,7 @@ import {
136
136
  workspaceSandboxRecoveryMessage,
137
137
  workspaceSandboxRecoveryRecommendedActions
138
138
  } from "../chunk-4LBCTFBP.js";
139
- import "../chunk-WVESWAJJ.js";
139
+ import "../chunk-MXNVSY6J.js";
140
140
  import "../chunk-LWSJK546.js";
141
141
  import "../chunk-74WXGIEK.js";
142
142
  import "../chunk-6A7MYOUI.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  KNOWN_HARNESSES
3
- } from "../chunk-WVESWAJJ.js";
3
+ } from "../chunk-MXNVSY6J.js";
4
4
  import {
5
5
  composeSkills,
6
6
  renderInlineSkills
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  AGENT_PROFILE_EDITOR_SECTIONS,
3
3
  AgentProfileEditor
4
- } from "../chunk-CCTQQ45L.js";
5
- import "../chunk-XSPUKVHF.js";
4
+ } from "../chunk-CRHXK3QT.js";
5
+ import "../chunk-KICTB6RK.js";
6
6
  import "../chunk-R5K5ML3Q.js";
7
7
  import "../chunk-AA4FKEQW.js";
8
8
  import "../chunk-RASGKEAL.js";
9
- import "../chunk-WVESWAJJ.js";
9
+ import "../chunk-MXNVSY6J.js";
10
10
  import "../chunk-B7CL7ENS.js";
11
11
  import "../chunk-PV33JZKV.js";
12
12
  import "../chunk-AMUXRAUO.js";
@@ -166,7 +166,7 @@ import {
166
166
  AGENT_PROFILE_EDITOR_SECTIONS,
167
167
  AgentProfileEditor,
168
168
  AgentProfileRegistryError
169
- } from "../chunk-CCTQQ45L.js";
169
+ } from "../chunk-CRHXK3QT.js";
170
170
  import {
171
171
  EvidenceLineageTable,
172
172
  ExceptionList,
@@ -195,7 +195,7 @@ import {
195
195
  preloadWhenIdle,
196
196
  useComposerAttachments,
197
197
  useDictation
198
- } from "../chunk-ZEMO7S2G.js";
198
+ } from "../chunk-PZHZV6QY.js";
199
199
  import "../chunk-L7MB2LLM.js";
200
200
  import "../chunk-SJWIZT7B.js";
201
201
  import {
@@ -207,7 +207,7 @@ import {
207
207
  filterAcceptedFiles,
208
208
  isAcceptedFileType,
209
209
  renamePastedImages
210
- } from "../chunk-XSPUKVHF.js";
210
+ } from "../chunk-KICTB6RK.js";
211
211
  import "../chunk-R5K5ML3Q.js";
212
212
  import {
213
213
  DEFAULT_EFFORT_LEVELS,
@@ -235,7 +235,7 @@ import "../chunk-FQYAJYPW.js";
235
235
  import {
236
236
  ATTACHMENT_ACCEPT
237
237
  } from "../chunk-WTC6AOPL.js";
238
- import "../chunk-WVESWAJJ.js";
238
+ import "../chunk-MXNVSY6J.js";
239
239
  import "../chunk-B7CL7ENS.js";
240
240
  import "../chunk-PV33JZKV.js";
241
241
  import "../chunk-AMUXRAUO.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.60.170",
3
+ "version": "0.60.171",
4
4
  "packageManager": "pnpm@11.24.0",
5
5
  "description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
6
6
  "keywords": [