@tangle-network/agent-app 0.45.1 → 0.45.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assistant/index.js +3 -3
- package/dist/assistant/index.js.map +1 -1
- package/dist/chat-routes/index.js +4 -4
- package/dist/{chunk-CQZSAR77.js → chunk-73F3CKVK.js} +28 -18
- package/dist/chunk-73F3CKVK.js.map +1 -0
- package/dist/{chunk-EC7CUA4L.js → chunk-AOQ4FCSH.js} +4 -4
- package/dist/chunk-AOQ4FCSH.js.map +1 -0
- package/dist/{chunk-ICOHEZK6.js → chunk-ITCINLSU.js} +2 -2
- package/dist/{chunk-3EJ6SFJI.js → chunk-IVEKCOM7.js} +68 -26
- package/dist/chunk-IVEKCOM7.js.map +1 -0
- package/dist/{chunk-WXWU2FEB.js → chunk-YRFB2KEA.js} +96 -87
- package/dist/chunk-YRFB2KEA.js.map +1 -0
- package/dist/design-canvas/index.d.ts +2 -1
- package/dist/design-canvas/index.js +1 -1
- package/dist/harness/index.d.ts +25 -8
- package/dist/harness/index.js +1 -1
- package/dist/mcp-BOgNWSED.d.ts +174 -0
- package/dist/run/index.js +1 -1
- package/dist/runtime/index.d.ts +17 -7
- package/dist/runtime/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +31 -1
- package/dist/sandbox/index.js +4 -4
- package/dist/sequences/index.d.ts +2 -1
- package/dist/sequences/index.js +1 -1
- package/dist/skills-placement/index.js +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.js +5 -3
- package/dist/web-react/index.d.ts +9 -2
- package/dist/web-react/index.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-3EJ6SFJI.js.map +0 -1
- package/dist/chunk-CQZSAR77.js.map +0 -1
- package/dist/chunk-EC7CUA4L.js.map +0 -1
- package/dist/chunk-WXWU2FEB.js.map +0 -1
- package/dist/mcp-Dt4V4ZLT.d.ts +0 -95
- /package/dist/{chunk-ICOHEZK6.js.map → chunk-ITCINLSU.js.map} +0 -0
|
@@ -100,11 +100,11 @@ import {
|
|
|
100
100
|
flattenHistory,
|
|
101
101
|
readSandboxBinaryBytes,
|
|
102
102
|
statSandboxFileSize
|
|
103
|
-
} from "../chunk-
|
|
103
|
+
} from "../chunk-AOQ4FCSH.js";
|
|
104
104
|
import "../chunk-LWSJK546.js";
|
|
105
|
-
import "../chunk-
|
|
106
|
-
import "../chunk-
|
|
107
|
-
import "../chunk-
|
|
105
|
+
import "../chunk-73F3CKVK.js";
|
|
106
|
+
import "../chunk-ITCINLSU.js";
|
|
107
|
+
import "../chunk-IVEKCOM7.js";
|
|
108
108
|
import "../chunk-YEFFHORB.js";
|
|
109
109
|
import "../chunk-S5SRJJQG.js";
|
|
110
110
|
import "../chunk-JML7WKWU.js";
|
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
// src/harness/index.ts
|
|
2
2
|
import {
|
|
3
3
|
harnessSupportsModel,
|
|
4
|
+
harnessTypeSchema,
|
|
4
5
|
modelProvider,
|
|
5
6
|
preferredHarnessForModel,
|
|
6
7
|
snapHarnessToModel as aiSnapHarnessToModel,
|
|
7
8
|
snapModelToHarness as aiSnapModelToHarness
|
|
8
9
|
} from "@tangle-network/agent-interface";
|
|
10
|
+
var NON_BACKEND_HARNESSES = ["gemini"];
|
|
11
|
+
var EXTRA_HARNESSES = ["forge", "cursor"];
|
|
12
|
+
var nonBackendHarnesses = new Set(NON_BACKEND_HARNESSES);
|
|
9
13
|
var KNOWN_HARNESSES = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"codex",
|
|
15
|
-
"amp",
|
|
16
|
-
"factory-droids",
|
|
17
|
-
"pi",
|
|
18
|
-
"hermes",
|
|
19
|
-
"forge",
|
|
20
|
-
"openclaw",
|
|
21
|
-
"acp",
|
|
22
|
-
"cursor",
|
|
23
|
-
"cli-base"
|
|
14
|
+
...harnessTypeSchema.options.filter(
|
|
15
|
+
(harness) => !nonBackendHarnesses.has(harness)
|
|
16
|
+
),
|
|
17
|
+
...EXTRA_HARNESSES
|
|
24
18
|
];
|
|
25
19
|
var DEFAULT_HARNESS = "opencode";
|
|
26
20
|
var HARNESS_SET = new Set(KNOWN_HARNESSES);
|
|
@@ -40,14 +34,30 @@ function resolveSessionHarness(input = {}) {
|
|
|
40
34
|
const harness = coerceHarness(input.requested, coerceHarness(input.workspaceDefault, fallback));
|
|
41
35
|
return { harness, locked: false, swapAttempted: false };
|
|
42
36
|
}
|
|
37
|
+
var canonicalHarnesses = new Set(harnessTypeSchema.options);
|
|
38
|
+
function canonicalHarness(harness) {
|
|
39
|
+
return canonicalHarnesses.has(harness) ? harness : null;
|
|
40
|
+
}
|
|
43
41
|
function isModelCompatibleWithHarness(harness, modelId) {
|
|
44
|
-
|
|
42
|
+
const canonical = canonicalHarness(harness);
|
|
43
|
+
if (!canonical) return true;
|
|
44
|
+
return harnessSupportsModel(canonical, modelId);
|
|
45
45
|
}
|
|
46
46
|
function snapModelToHarness(harness, modelId, canonicalIds) {
|
|
47
|
-
|
|
47
|
+
const canonical = canonicalHarness(harness);
|
|
48
|
+
if (!canonical) return modelId;
|
|
49
|
+
return aiSnapModelToHarness(canonical, modelId, canonicalIds);
|
|
48
50
|
}
|
|
49
51
|
function snapHarnessToModel(harness, modelId) {
|
|
50
|
-
|
|
52
|
+
const canonical = canonicalHarness(harness);
|
|
53
|
+
if (!canonical) return harness;
|
|
54
|
+
const snapped = aiSnapHarnessToModel(canonical, modelId);
|
|
55
|
+
if (!isHarness(snapped)) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Harness "${harness}" snapped to "${snapped}" for model "${modelId}", which this platform has no backend for.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return snapped;
|
|
51
61
|
}
|
|
52
62
|
function assertHarnessModelCompatible(harness, modelId) {
|
|
53
63
|
if (!isModelCompatibleWithHarness(harness, modelId)) {
|
|
@@ -71,4 +81,4 @@ export {
|
|
|
71
81
|
snapHarnessToModel,
|
|
72
82
|
assertHarnessModelCompatible
|
|
73
83
|
};
|
|
74
|
-
//# sourceMappingURL=chunk-
|
|
84
|
+
//# sourceMappingURL=chunk-73F3CKVK.js.map
|
|
@@ -0,0 +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.\n */\n\nimport {\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. `KNOWN_HARNESSES` is dispatched as\n * `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\n/**\n * Backends the platform runs that the canonical enum does not carry yet. The guard below turns\n * their adoption upstream into a compile error, so this list is emptied rather than duplicating a\n * canonical id.\n */\nconst EXTRA_HARNESSES = ['forge', 'cursor'] as const\n\ntype ExtrasAlreadyCanonical = Extract<HarnessType, (typeof EXTRA_HARNESSES)[number]>\nconst _extrasAreNotYetCanonical: ExtrasAlreadyCanonical extends never ? true : never = true\nvoid _extrasAreNotYetCanonical\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 =\n | Exclude<HarnessType, (typeof NON_BACKEND_HARNESSES)[number]>\n | (typeof EXTRA_HARNESSES)[number]\n\n/**\n * The known coding-agent backends: the canonical harness set minus what has no provider adapter,\n * plus adapters the canonical set has yet to adopt. Derived from `harnessTypeSchema.options` so a\n * harness added upstream reaches this shell without an edit here, and kept structural so this\n * 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 ...EXTRA_HARNESSES,\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 * Harness ↔ model compatibility + snapping — delegated to `@tangle-network/agent-interface`.\n *\n * `Harness` and `HarnessType` OVERLAP rather than nest: this shell drops canonical harnesses the\n * platform has no backend for, and carries backends the canonical enum has yet to adopt. So a\n * harness is narrowed to a canonical id before any capability lookup, and the non-canonical\n * remainder is answered here — those runners are multi-provider CLIs with no vendor lock, so they\n * run any model and never snap. As the canonical enum adopts them, `canonicalHarness` starts\n * returning them and the lookup below takes over with no change at these call sites.\n */\n\nconst canonicalHarnesses: ReadonlySet<string> = new Set(harnessTypeSchema.options)\n\n/** The canonical id for a harness, or `null` for a backend the canonical enum does not list. */\nfunction canonicalHarness(harness: Harness): HarnessType | null {\n return canonicalHarnesses.has(harness) ? (harness as HarnessType) : null\n}\n\nexport { modelProvider }\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 const canonical = canonicalHarness(harness)\n if (!canonical) return true\n return harnessSupportsModel(canonical, 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 const canonical = canonicalHarness(harness)\n if (!canonical) return modelId\n return aiSnapModelToHarness(canonical, 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 canonical = canonicalHarness(harness)\n if (!canonical) return harness\n const snapped = aiSnapHarnessToModel(canonical, 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 * Call before dispatching a sandbox turn so a bypassed UI can't reach the sidecar\n * with an incompatible pair. */\nexport function assertHarnessModelCompatible(harness: Harness, modelId: string): void {\n if (!isModelCompatibleWithHarness(harness, modelId)) {\n const provider = modelProvider(modelId)\n const native = preferredHarnessForModel(modelId)\n throw new Error(\n `Harness \"${harness}\" cannot run model \"${modelId}\" (provider \"${provider}\"). ` +\n `Use ${native ?? 'a router-backed harness (opencode)'} or an allowed model.`,\n )\n }\n}\n"],"mappings":";AAqBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,OAEjB;AAOP,IAAM,wBAAwB,CAAC,QAAQ;AAOvC,IAAM,kBAAkB,CAAC,SAAS,QAAQ;AAM1C,IAAM,sBAAsB,IAAI,IAAY,qBAAqB;AAa1D,IAAM,kBAAsC;AAAA,EACjD,GAAG,kBAAkB,QAAQ;AAAA,IAC3B,CAAC,YACC,CAAC,oBAAoB,IAAI,OAAO;AAAA,EACpC;AAAA,EACA,GAAG;AACL;AAGO,IAAM,kBAA2B;AAExC,IAAM,cAAmC,IAAI,IAAI,eAAe;AAGzD,SAAS,UAAU,OAAkC;AAC1D,SAAO,OAAO,UAAU,YAAY,YAAY,IAAI,KAAK;AAC3D;AAGO,SAAS,cAAc,OAAgB,WAAoB,iBAA0B;AAC1F,SAAO,UAAU,KAAK,IAAI,QAAQ;AACpC;AAkCO,SAAS,sBAAsB,QAAoC,CAAC,GAA2B;AACpG,QAAM,WAAW,MAAM,YAAY;AACnC,MAAI,UAAU,MAAM,cAAc,GAAG;AACnC,UAAM,SAAS,MAAM;AACrB,UAAM,gBAAgB,UAAU,MAAM,SAAS,KAAK,MAAM,cAAc;AACxE,WAAO,EAAE,SAAS,QAAQ,QAAQ,MAAM,cAAc;AAAA,EACxD;AACA,QAAM,UAAU,cAAc,MAAM,WAAW,cAAc,MAAM,kBAAkB,QAAQ,CAAC;AAC9F,SAAO,EAAE,SAAS,QAAQ,OAAO,eAAe,MAAM;AACxD;AAaA,IAAM,qBAA0C,IAAI,IAAI,kBAAkB,OAAO;AAGjF,SAAS,iBAAiB,SAAsC;AAC9D,SAAO,mBAAmB,IAAI,OAAO,IAAK,UAA0B;AACtE;AAMO,SAAS,6BAA6B,SAAkB,SAA0B;AACvF,QAAM,YAAY,iBAAiB,OAAO;AAC1C,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,qBAAqB,WAAW,OAAO;AAChD;AAKO,SAAS,mBAAmB,SAAkB,SAAiB,cAAyC;AAC7G,QAAM,YAAY,iBAAiB,OAAO;AAC1C,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,qBAAqB,WAAW,SAAS,YAAY;AAC9D;AAIO,SAAS,mBAAmB,SAAkB,SAA0B;AAC7E,QAAM,YAAY,iBAAiB,OAAO;AAC1C,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,UAAU,qBAAqB,WAAW,OAAO;AACvD,MAAI,CAAC,UAAU,OAAO,GAAG;AACvB,UAAM,IAAI;AAAA,MACR,YAAY,OAAO,iBAAiB,OAAO,gBAAgB,OAAO;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,6BAA6B,SAAkB,SAAuB;AACpF,MAAI,CAAC,6BAA6B,SAAS,OAAO,GAAG;AACnD,UAAM,WAAW,cAAc,OAAO;AACtC,UAAM,SAAS,yBAAyB,OAAO;AAC/C,UAAM,IAAI;AAAA,MACR,YAAY,OAAO,uBAAuB,OAAO,gBAAgB,QAAQ,WAChE,UAAU,oCAAoC;AAAA,IACzD;AAAA,EACF;AACF;","names":[]}
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-LWSJK546.js";
|
|
5
5
|
import {
|
|
6
6
|
assertHarnessModelCompatible
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-73F3CKVK.js";
|
|
8
8
|
import {
|
|
9
9
|
buildAppToolMcpServer
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IVEKCOM7.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveTangleExecutionEnvironment,
|
|
13
13
|
trimOrNull
|
|
@@ -519,7 +519,7 @@ function buildAppToolMcpServers(options) {
|
|
|
519
519
|
entries[key] = buildAppToolMcpServer({
|
|
520
520
|
tool,
|
|
521
521
|
baseUrl: options.baseUrl,
|
|
522
|
-
|
|
522
|
+
tokenEnvKey: options.tokenEnvKey,
|
|
523
523
|
ctx: options.ctx,
|
|
524
524
|
description,
|
|
525
525
|
headerNames: options.headerNames
|
|
@@ -1776,4 +1776,4 @@ export {
|
|
|
1776
1776
|
isTerminalPromptEvent,
|
|
1777
1777
|
detectInteractiveQuestion
|
|
1778
1778
|
};
|
|
1779
|
-
//# sourceMappingURL=chunk-
|
|
1779
|
+
//# sourceMappingURL=chunk-AOQ4FCSH.js.map
|