@tangle-network/agent-app 0.45.50 → 0.45.52
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 +1 -1
- package/dist/chat-routes/index.js +1 -1
- package/dist/{chunk-7HY4LX7O.js → chunk-JEZILUC3.js} +380 -277
- package/dist/chunk-JEZILUC3.js.map +1 -0
- package/dist/{chunk-RRH23CGS.js → chunk-MA2RIIIH.js} +14 -12
- package/dist/chunk-MA2RIIIH.js.map +1 -0
- package/dist/sandbox/index.d.ts +10 -6
- package/dist/sandbox/index.js +1 -3
- package/dist/skills-placement/index.js +1 -0
- package/dist/skills-placement/index.js.map +1 -1
- package/dist/theme/tokens.css +45 -1
- package/dist/web-react/index.d.ts +25 -4
- package/dist/web-react/index.js +1 -1
- package/package.json +18 -18
- package/dist/chunk-7HY4LX7O.js.map +0 -1
- package/dist/chunk-RRH23CGS.js.map +0 -1
package/dist/sandbox/index.d.ts
CHANGED
|
@@ -1612,19 +1612,23 @@ declare function syncSandboxMemberAdd(box: SandboxInstance, seam: MemberSyncSeam
|
|
|
1612
1612
|
declare function syncSandboxMemberRemove(box: SandboxInstance, userId: string): Promise<Outcome<void>>;
|
|
1613
1613
|
/** Synchronize a sandbox member's role by updating permissions based on the provided role mapping */
|
|
1614
1614
|
declare function syncSandboxMemberRole(box: SandboxInstance, seam: MemberSyncSeam, userId: string, role: string): Promise<Outcome<void>>;
|
|
1615
|
-
/**
|
|
1615
|
+
/**
|
|
1616
|
+
* Write-only secret port: create, replace, and delete a secret by name.
|
|
1617
|
+
*
|
|
1618
|
+
* There is no read method. The platform's secrets API returns names and
|
|
1619
|
+
* timestamps only — a stored value is never served back, it is injected into
|
|
1620
|
+
* the sandbox as an environment variable. A `get` here could only ever return
|
|
1621
|
+
* a value this process already held, so the port does not offer one.
|
|
1622
|
+
*/
|
|
1616
1623
|
interface SecretStore {
|
|
1617
1624
|
create: (name: string, value: string) => Promise<void>;
|
|
1618
1625
|
update: (name: string, value: string) => Promise<void>;
|
|
1619
|
-
get: (name: string) => Promise<string>;
|
|
1620
1626
|
delete: (name: string) => Promise<void>;
|
|
1621
1627
|
}
|
|
1622
1628
|
/** Resolve a SecretStore interface using the provided SandboxRuntimeConfig shell */
|
|
1623
1629
|
declare function secretStoreFromClient(shell: SandboxRuntimeConfig): SecretStore;
|
|
1624
|
-
/** Resolve storing a secret by creating or
|
|
1630
|
+
/** Resolve storing a secret by creating it, or replacing it when it exists */
|
|
1625
1631
|
declare function storeSecret(store: SecretStore, name: string, value: string): Promise<Outcome<void>>;
|
|
1626
|
-
/** Resolve a secret value from the store by its name and return the outcome asynchronously */
|
|
1627
|
-
declare function readSecret(store: SecretStore, name: string): Promise<Outcome<string>>;
|
|
1628
1632
|
/** Delete a secret by name from the given secret store and return the operation outcome */
|
|
1629
1633
|
declare function deleteSecret(store: SecretStore, name: string): Promise<Outcome<void>>;
|
|
1630
1634
|
/** Represent a token with its expiration date and associated scope */
|
|
@@ -1667,4 +1671,4 @@ declare function isTerminalPromptEvent(event: unknown): boolean;
|
|
|
1667
1671
|
/** Resolve the interactive question text from a structured event or return null if none found */
|
|
1668
1672
|
declare function detectInteractiveQuestion(event: unknown): string | null;
|
|
1669
1673
|
|
|
1670
|
-
export { type AppToolDescriptor, type BuildAppToolMcpServersOptions, type BuildSandboxToolFileMountsOptions, type D1PrewarmClaimStoreOptions, DEFAULT_PREWARM_CLAIM_TABLE, DEFAULT_PROVISION_TIMEOUT_MS, DEFAULT_SANDBOX_RESOURCES, DEFAULT_SIDECAR_PROCESS_PATTERN, type DriveSandboxTurnOptions, EGRESS_PROXY_RECOVERY_PHASE, EGRESS_PROXY_RECOVERY_REQUIRED, ENV_TOTAL_MAX_BYTES, ENV_VALUE_MAX_BYTES, type EnsureWorkspaceSandboxOptions, type LivenessProbeConfig, type MemberSyncSeam, type ModelSelection, type ModelSelectionError, type ModelSelectionFailure, type ModelSelectionSource, type Outcome, PREWARM_CLAIM_TABLE_DDL, PROVISION_PAYLOAD_MAX_BYTES, PYPI_EGRESS_DOMAINS, type PeekWorkspaceSandboxOutcome, type PrewarmClaimD1Like, type PrewarmClaimStore, type PrewarmDecision, type PrewarmEvent, type PrewarmOutcome, type PrewarmResult, type ProfileComposeOptions, type PromptInputPart, type ProviderResolutionConfig, type ProvisionPayloadSections, type ProvisionProfileSection, type ResolveSandboxClientCredentialsOptions, type ResolvedModel, type SafeSandboxErrorCause, type SafeSandboxErrorDiagnostics, type SandboxBuildContext, type SandboxClientCredentials, type SandboxCredentialEnvironment, SandboxEgressPolicyMismatchError, type SandboxEgressPolicySource, type SandboxExecChannel, type SandboxExecOptions, type SandboxExistingBoxStage, type SandboxFileBytesOutcome, type SandboxFileSizeOutcome, SandboxModelResolutionError, type SandboxPermissionLevel, type SandboxPrewarmScope, type SandboxPrewarmer, type SandboxPrewarmerOptions, type SandboxProvisionedObservation, type SandboxReadiness, SandboxRecoveryFailedError, type SandboxRecoveryPhase, type SandboxResourceConfig, type SandboxRestoreSpec, SandboxRuntimeAuthRefreshError, type SandboxRuntimeConfig, type SandboxScope, type SandboxSpendHooks, type SandboxStepTransition, type SandboxStreamEvent, type SandboxTerminalConnectionRouteOptions, type SandboxToolPathOptions, type SandboxToolSpec, type ScopedTokenResult, type SecretStore, type StoppedSandboxResumeFailure, type StoppedSandboxResumeRecovery, type StreamSandboxPromptOptions, type TerminalConnectionBoxLike, WORKSPACE_SANDBOX_HOST_EXHAUSTED, WORKSPACE_SANDBOX_MISSING, WORKSPACE_SANDBOX_RECOVERY_ACTIONS, WORKSPACE_SANDBOX_RECOVERY_CODES, WORKSPACE_SANDBOX_SNAPSHOT_MAX_AGE_MS, WORKSPACE_SANDBOX_UNRECOVERABLE, type WorkspaceSandboxEnsureContext, type WorkspaceSandboxInstanceLike, type WorkspaceSandboxManager, type WorkspaceSandboxManagerOptions, type WorkspaceSandboxRecoveryAction, type WorkspaceSandboxRecoveryCode, type WorkspaceSandboxRecoveryDecision, type WorkspaceSandboxRecoveryManager, WorkspaceSandboxRecoveryRequiredError, type WorkspaceSandboxRecoveryState, type WorkspaceSandboxRecoveryStore, type WorkspaceSandboxSnapshot, type WorkspaceSandboxSnapshotAssessment, type WorkspaceSandboxSnapshotAvailability, type WorkspaceSandboxSnapshotFreshness, type WriteProfileFilesOptions, adaptSandboxStream, assertEnvWithinLimits, assertProvisionPayloadWithinCap, assessWorkspaceSandboxSnapshot, attachReasoningEffort, buildAppToolMcpServers, buildProductEgressPolicy, buildSandboxToolFileMounts, buildSandboxToolPathSetupScript, classifySeveredStream, collectSandboxPromptText, createD1PrewarmClaimStore, createSandboxPrewarmer, createSandboxTerminalConnectionRoute, createWorkspaceSandboxManager, createWorkspaceSandboxRecoveryManager, deferredCorpusHash, deleteSecret, detectInteractiveQuestion, driveSandboxTurn, ensureWorkspaceSandbox, flattenHistory, formatSandboxProvisioningSupportDetails, formatSandboxProvisioningUserMessage, getClient, isEgressProxyRecoveryRequiredError, isSandboxApiBearerAuthFailure, isSandboxApiSandboxMissingFailure, isSandboxAuthFailure, isSandboxHostCapacityFailure, isTerminalPromptEvent, isWorkspaceSandboxRecoveryAction, isWorkspaceSandboxRecoveryCode, isWorkspaceSandboxRecoveryState, isWorkspaceSandboxSnapshotRestoreError, mergeExtraMcp, mergeHistoryIntoParts, mintSandboxScopedToken, peekWorkspaceSandbox, preferredWorkspaceSandboxRecoveryBoxKey, readSandboxBinaryBytes,
|
|
1674
|
+
export { type AppToolDescriptor, type BuildAppToolMcpServersOptions, type BuildSandboxToolFileMountsOptions, type D1PrewarmClaimStoreOptions, DEFAULT_PREWARM_CLAIM_TABLE, DEFAULT_PROVISION_TIMEOUT_MS, DEFAULT_SANDBOX_RESOURCES, DEFAULT_SIDECAR_PROCESS_PATTERN, type DriveSandboxTurnOptions, EGRESS_PROXY_RECOVERY_PHASE, EGRESS_PROXY_RECOVERY_REQUIRED, ENV_TOTAL_MAX_BYTES, ENV_VALUE_MAX_BYTES, type EnsureWorkspaceSandboxOptions, type LivenessProbeConfig, type MemberSyncSeam, type ModelSelection, type ModelSelectionError, type ModelSelectionFailure, type ModelSelectionSource, type Outcome, PREWARM_CLAIM_TABLE_DDL, PROVISION_PAYLOAD_MAX_BYTES, PYPI_EGRESS_DOMAINS, type PeekWorkspaceSandboxOutcome, type PrewarmClaimD1Like, type PrewarmClaimStore, type PrewarmDecision, type PrewarmEvent, type PrewarmOutcome, type PrewarmResult, type ProfileComposeOptions, type PromptInputPart, type ProviderResolutionConfig, type ProvisionPayloadSections, type ProvisionProfileSection, type ResolveSandboxClientCredentialsOptions, type ResolvedModel, type SafeSandboxErrorCause, type SafeSandboxErrorDiagnostics, type SandboxBuildContext, type SandboxClientCredentials, type SandboxCredentialEnvironment, SandboxEgressPolicyMismatchError, type SandboxEgressPolicySource, type SandboxExecChannel, type SandboxExecOptions, type SandboxExistingBoxStage, type SandboxFileBytesOutcome, type SandboxFileSizeOutcome, SandboxModelResolutionError, type SandboxPermissionLevel, type SandboxPrewarmScope, type SandboxPrewarmer, type SandboxPrewarmerOptions, type SandboxProvisionedObservation, type SandboxReadiness, SandboxRecoveryFailedError, type SandboxRecoveryPhase, type SandboxResourceConfig, type SandboxRestoreSpec, SandboxRuntimeAuthRefreshError, type SandboxRuntimeConfig, type SandboxScope, type SandboxSpendHooks, type SandboxStepTransition, type SandboxStreamEvent, type SandboxTerminalConnectionRouteOptions, type SandboxToolPathOptions, type SandboxToolSpec, type ScopedTokenResult, type SecretStore, type StoppedSandboxResumeFailure, type StoppedSandboxResumeRecovery, type StreamSandboxPromptOptions, type TerminalConnectionBoxLike, WORKSPACE_SANDBOX_HOST_EXHAUSTED, WORKSPACE_SANDBOX_MISSING, WORKSPACE_SANDBOX_RECOVERY_ACTIONS, WORKSPACE_SANDBOX_RECOVERY_CODES, WORKSPACE_SANDBOX_SNAPSHOT_MAX_AGE_MS, WORKSPACE_SANDBOX_UNRECOVERABLE, type WorkspaceSandboxEnsureContext, type WorkspaceSandboxInstanceLike, type WorkspaceSandboxManager, type WorkspaceSandboxManagerOptions, type WorkspaceSandboxRecoveryAction, type WorkspaceSandboxRecoveryCode, type WorkspaceSandboxRecoveryDecision, type WorkspaceSandboxRecoveryManager, WorkspaceSandboxRecoveryRequiredError, type WorkspaceSandboxRecoveryState, type WorkspaceSandboxRecoveryStore, type WorkspaceSandboxSnapshot, type WorkspaceSandboxSnapshotAssessment, type WorkspaceSandboxSnapshotAvailability, type WorkspaceSandboxSnapshotFreshness, type WriteProfileFilesOptions, adaptSandboxStream, assertEnvWithinLimits, assertProvisionPayloadWithinCap, assessWorkspaceSandboxSnapshot, attachReasoningEffort, buildAppToolMcpServers, buildProductEgressPolicy, buildSandboxToolFileMounts, buildSandboxToolPathSetupScript, classifySeveredStream, collectSandboxPromptText, createD1PrewarmClaimStore, createSandboxPrewarmer, createSandboxTerminalConnectionRoute, createWorkspaceSandboxManager, createWorkspaceSandboxRecoveryManager, deferredCorpusHash, deleteSecret, detectInteractiveQuestion, driveSandboxTurn, ensureWorkspaceSandbox, flattenHistory, formatSandboxProvisioningSupportDetails, formatSandboxProvisioningUserMessage, getClient, isEgressProxyRecoveryRequiredError, isSandboxApiBearerAuthFailure, isSandboxApiSandboxMissingFailure, isSandboxAuthFailure, isSandboxHostCapacityFailure, isTerminalPromptEvent, isWorkspaceSandboxRecoveryAction, isWorkspaceSandboxRecoveryCode, isWorkspaceSandboxRecoveryState, isWorkspaceSandboxSnapshotRestoreError, mergeExtraMcp, mergeHistoryIntoParts, mintSandboxScopedToken, peekWorkspaceSandbox, preferredWorkspaceSandboxRecoveryBoxKey, readSandboxBinaryBytes, requireTransportableModel, resetClientCache, resolveModel, resolveModelSelection, resolveSandboxClientCredentials, runSandboxPrompt, runSandboxToolPathSetup, sandboxToolBinDir, sandboxToolPath, sandboxToolRootDir, secretStoreFromClient, serializeSandboxProvisioningError, shellQuote, shouldRestoreWorkspaceSandboxRecovery, splitDeferredProfileFiles, statSandboxFileSize, storeSecret, streamSandboxPrompt, syncSandboxMemberAdd, syncSandboxMemberRemove, syncSandboxMemberRole, workspaceSandboxRecoveryDiagnostic, workspaceSandboxRecoveryFromError, workspaceSandboxRecoveryMessage, workspaceSandboxRecoveryRecommendedActions, writeProfileFilesToBox };
|
package/dist/sandbox/index.js
CHANGED
|
@@ -62,7 +62,6 @@ import {
|
|
|
62
62
|
peekWorkspaceSandbox,
|
|
63
63
|
preferredWorkspaceSandboxRecoveryBoxKey,
|
|
64
64
|
readSandboxBinaryBytes,
|
|
65
|
-
readSecret,
|
|
66
65
|
requireTransportableModel,
|
|
67
66
|
resetClientCache,
|
|
68
67
|
resolveModel,
|
|
@@ -89,7 +88,7 @@ import {
|
|
|
89
88
|
workspaceSandboxRecoveryMessage,
|
|
90
89
|
workspaceSandboxRecoveryRecommendedActions,
|
|
91
90
|
writeProfileFilesToBox
|
|
92
|
-
} from "../chunk-
|
|
91
|
+
} from "../chunk-MA2RIIIH.js";
|
|
93
92
|
import "../chunk-TH7L265V.js";
|
|
94
93
|
import "../chunk-LWSJK546.js";
|
|
95
94
|
import "../chunk-P5PIAQVS.js";
|
|
@@ -162,7 +161,6 @@ export {
|
|
|
162
161
|
peekWorkspaceSandbox,
|
|
163
162
|
preferredWorkspaceSandboxRecoveryBoxKey,
|
|
164
163
|
readSandboxBinaryBytes,
|
|
165
|
-
readSecret,
|
|
166
164
|
requireTransportableModel,
|
|
167
165
|
resetClientCache,
|
|
168
166
|
resolveModel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/skills-placement/index.ts"],"sourcesContent":["/**\n * Harness-native skill directory resolution — the one place agent-app binds\n * to the platform's authoritative per-harness skill-dir map.\n *\n * `../skills` renders skill CONTENT (parse, tier-filter, `inline`/`mounted`\n * delivery) but deliberately stops short of naming WHICH cwd path a `mounted`\n * skill lands at on a given harness — that mapping is owned by the platform\n * materializer (`@tangle-network/agent-profile-materialize`'s\n * `skillDirForHarness`), not by app-shell. This subpath exists so no product\n * — and no other agent-app module — ever writes a skill path literal\n * (`~/.claude/skills/...`, `.opencode/skills`, ...) of its own; it bridges\n * agent-app's `Harness` taxonomy onto the platform's `HarnessId` and asks the\n * platform for the answer.\n *\n * Requires the OPTIONAL peer `@tangle-network/agent-profile-materialize`.\n * Products that don't install it simply don't import this subpath — every\n * other agent-app skills surface (`../skills`, `ProfileChannels.skillRefs`)\n * works without it, falling back to `inline` delivery.\n */\n\nimport { KNOWN_HARNESSES, type Harness } from '../harness/index'\nimport { skillDirForHarness, type HarnessId } from '@tangle-network/agent-profile-materialize'\nimport { composeSkills, renderInlineSkills, type ComposedSkills, type SkillEntry } from '../skills/index'\n\n/** agent-app `Harness` -> platform `HarnessId`, identity-mapped for exactly\n * the harnesses the platform map covers. Harnesses absent here (`amp`,\n * `factory-droids`, `forge`, `acp`, `cursor`, `cli-base`) resolve to `null` —\n * {@link composeSkillsForHarness} refuses by default rather than silently\n * delivering `inline`; a caller that genuinely needs `inline` on one of\n * these opts in explicitly (`onNoSkillDir: 'inline'`). `cursor`'s adapter\n * supports `resources.skills` bespokely but isn't in the platform map yet;\n * treating it as unbridged is the safe posture until the map covers it,\n * rather than guessing its cwd skill dir here. */\nconst HARNESS_BRIDGE: Partial<Record<Harness, HarnessId>> = {\n opencode: 'opencode',\n 'claude-code': 'claude-code',\n nanoclaw: 'nanoclaw',\n 'kimi-code': 'kimi-code',\n codex: 'codex',\n pi: 'pi',\n hermes: 'hermes',\n openclaw: 'openclaw',\n}\n\n/** Resolve the cwd-relative skill dir `resources.skills` refs materialize\n * into on `harness` — via the platform's `skillDirForHarness`. `null` when\n * `harness` isn't bridged (see {@link HARNESS_BRIDGE}) or when the platform\n * itself has no cwd skill primitive for it (e.g. `hermes`, user-dir-only). */\nexport function resolveSkillDir(harness: Harness): string | null {\n const bridged = HARNESS_BRIDGE[harness]\n if (!bridged) return null\n return skillDirForHarness(bridged)\n}\n\n/** Filter `harnesses` down to those with no mounted skill dir (deduped,\n * first-seen order preserved) — the set that must fall back to `inline`\n * delivery, or that a caller should warn about before offering \"mounted\"\n * install UX. */\nexport function unsupportedSkillHarnesses(harnesses: Iterable<Harness>): Harness[] {\n const seen = new Set<Harness>()\n const out: Harness[] = []\n for (const harness of harnesses) {\n if (resolveSkillDir(harness) !== null) continue\n if (seen.has(harness)) continue\n seen.add(harness)\n out.push(harness)\n }\n return out\n}\n\n/** Inputs to {@link composeSkillsForHarness}. */\nexport interface ComposeSkillsForHarnessInput {\n skills: SkillEntry[]\n harness: Harness\n tier?: string\n heading?: string\n /**\n * What to do when `harness` has no native skill-mount directory (see\n * {@link resolveSkillDir}). Default `'throw'`: refuse rather than silently\n * inlining every skill BODY into the system prompt. Pass `'inline'` only as\n * a deliberate, auditable opt-in — the caller has decided every skill must\n * reach this harness even though it will be concatenated into the prompt.\n */\n onNoSkillDir?: 'throw' | 'inline'\n}\n\n/** `KNOWN_HARNESSES` filtered to those the platform materializer can mount\n * skill files onto natively (a non-null {@link resolveSkillDir}). Computed\n * fresh rather than cached — the platform map can grow without a release\n * here. Used only to build the actionable error in\n * {@link composeSkillsForHarness}; not exported because it duplicates\n * {@link unsupportedSkillHarnesses}'s complement and callers should reach\n * for that instead when they need the harness list at runtime. */\nfunction nativeSkillMountHarnesses(): Harness[] {\n return KNOWN_HARNESSES.filter((harness) => resolveSkillDir(harness) !== null)\n}\n\n/**\n * Compose {@link ComposedSkills} for `harness`.\n *\n * `mounted` delivery is the standard path: whenever the platform names a cwd\n * skill dir for `harness`, skills ride the typed `resources.skills` channel\n * and the platform materializer writes each one to that directory as a real\n * file — the agent reads it on demand with its own file tools.\n *\n * `inline` delivery — every skill BODY rendered straight into the system\n * prompt — is a NARROW fallback for harnesses with no native skill dir, never\n * a co-equal mode. An `AgentProfile` is a RECIPE that materializes into a\n * sandbox, not a prompt template: skill bodies belong in a file mount, and\n * `prompt.systemPrompt` should carry only what the agent must obey without a\n * tool call (identity, tool-call contract, safety rules, output format) plus\n * a short index of what's mounted. Concatenating skill bodies into the prompt\n * degrades the model toward empty answers once it grows large enough — one\n * product reproduced a 151,882-byte prompt exactly this way, from an\n * unnoticed inline fallback.\n *\n * Because of that, `onNoSkillDir` defaults to `'throw'`: a harness with no\n * skill dir refuses instead of silently inlining. The thrown error names the\n * harness, the skill count, the byte size that would have been inlined, and\n * the harnesses that DO support native mounting. Pass `onNoSkillDir:\n * 'inline'` only as a deliberate, auditable opt-in when every skill genuinely\n * must reach this harness regardless of prompt cost.\n *\n * The one function a product calls instead of hand-checking `resolveSkillDir`\n * and branching between {@link composeSkills}'s two modes itself.\n */\nexport function composeSkillsForHarness(input: ComposeSkillsForHarnessInput): ComposedSkills {\n const { skills, harness, tier, heading, onNoSkillDir = 'throw' } = input\n const skillDir = resolveSkillDir(harness)\n if (skillDir) return composeSkills({ skills, mode: 'mounted', skillDir, tier, heading })\n if (onNoSkillDir === 'inline') return composeSkills({ skills, mode: 'inline', tier, heading })\n\n const relevant = tier ? skills.filter((s) => s.tier === tier) : skills\n const promptSection = renderInlineSkills({ skills, tier, heading })\n const bytes = new TextEncoder().encode(promptSection).byteLength\n const mountable = nativeSkillMountHarnesses()\n throw new Error(\n `composeSkillsForHarness: \"${harness}\" has no native skill-mount directory. ` +\n `Inlining ${relevant.length} skill(s) (${bytes} bytes) into its system prompt would silently ` +\n `convert mounted skills into prompt text — a 151,882-byte prompt shipped this way once, and ` +\n `oversized prompts degrade toward empty answers. Mount the skills instead: pick a harness with ` +\n `native skill support (${mountable.join(', ')}), or pass onNoSkillDir: 'inline' to opt in ` +\n `explicitly and accept the inlined bytes.`,\n )\n}\n\nexport type { ComposedSkills, SkillEntry } from '../skills/index'\n"],"mappings":";;;;;;;;;AAqBA,SAAS,0BAA0C;AAYnD,IAAM,iBAAsD;AAAA,EAC1D,UAAU;AAAA,EACV,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,UAAU;AACZ;AAMO,SAAS,gBAAgB,SAAiC;AAC/D,QAAM,UAAU,eAAe,OAAO;AACtC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,mBAAmB,OAAO;AACnC;AAMO,SAAS,0BAA0B,WAAyC;AACjF,QAAM,OAAO,oBAAI,IAAa;AAC9B,QAAM,MAAiB,CAAC;AACxB,aAAW,WAAW,WAAW;AAC/B,QAAI,gBAAgB,OAAO,MAAM,KAAM;AACvC,QAAI,KAAK,IAAI,OAAO,EAAG;AACvB,SAAK,IAAI,OAAO;AAChB,QAAI,KAAK,OAAO;AAAA,EAClB;AACA,SAAO;AACT;AAyBA,SAAS,4BAAuC;AAC9C,SAAO,gBAAgB,OAAO,CAAC,YAAY,gBAAgB,OAAO,MAAM,IAAI;AAC9E;AA+BO,SAAS,wBAAwB,OAAqD;AAC3F,QAAM,EAAE,QAAQ,SAAS,MAAM,SAAS,eAAe,QAAQ,IAAI;AACnE,QAAM,WAAW,gBAAgB,OAAO;AACxC,MAAI,SAAU,QAAO,cAAc,EAAE,QAAQ,MAAM,WAAW,UAAU,MAAM,QAAQ,CAAC;AACvF,MAAI,iBAAiB,SAAU,QAAO,cAAc,EAAE,QAAQ,MAAM,UAAU,MAAM,QAAQ,CAAC;AAE7F,QAAM,WAAW,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI;AAChE,QAAM,gBAAgB,mBAAmB,EAAE,QAAQ,MAAM,QAAQ,CAAC;AAClE,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,aAAa,EAAE;AACtD,QAAM,YAAY,0BAA0B;AAC5C,QAAM,IAAI;AAAA,IACR,6BAA6B,OAAO,mDACtB,SAAS,MAAM,cAAc,KAAK,qQAGrB,UAAU,KAAK,IAAI,CAAC;AAAA,EAEjD;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/skills-placement/index.ts"],"sourcesContent":["/**\n * Harness-native skill directory resolution — the one place agent-app binds\n * to the platform's authoritative per-harness skill-dir map.\n *\n * `../skills` renders skill CONTENT (parse, tier-filter, `inline`/`mounted`\n * delivery) but deliberately stops short of naming WHICH cwd path a `mounted`\n * skill lands at on a given harness — that mapping is owned by the platform\n * materializer (`@tangle-network/agent-profile-materialize`'s\n * `skillDirForHarness`), not by app-shell. This subpath exists so no product\n * — and no other agent-app module — ever writes a skill path literal\n * (`~/.claude/skills/...`, `.opencode/skills`, ...) of its own; it bridges\n * agent-app's `Harness` taxonomy onto the platform's `HarnessId` and asks the\n * platform for the answer.\n *\n * Requires the OPTIONAL peer `@tangle-network/agent-profile-materialize`.\n * Products that don't install it simply don't import this subpath — every\n * other agent-app skills surface (`../skills`, `ProfileChannels.skillRefs`)\n * works without it, falling back to `inline` delivery.\n */\n\nimport { KNOWN_HARNESSES, type Harness } from '../harness/index'\nimport { skillDirForHarness, type HarnessId } from '@tangle-network/agent-profile-materialize'\nimport { composeSkills, renderInlineSkills, type ComposedSkills, type SkillEntry } from '../skills/index'\n\n/** agent-app `Harness` -> platform `HarnessId`, identity-mapped for exactly\n * the harnesses the platform map covers. Harnesses absent here (`amp`,\n * `factory-droids`, `forge`, `acp`, `cursor`, `cli-base`) resolve to `null` —\n * {@link composeSkillsForHarness} refuses by default rather than silently\n * delivering `inline`; a caller that genuinely needs `inline` on one of\n * these opts in explicitly (`onNoSkillDir: 'inline'`). `cursor`'s adapter\n * supports `resources.skills` bespokely but isn't in the platform map yet;\n * treating it as unbridged is the safe posture until the map covers it,\n * rather than guessing its cwd skill dir here. */\nconst HARNESS_BRIDGE: Partial<Record<Harness, HarnessId>> = {\n opencode: 'opencode',\n 'claude-code': 'claude-code',\n nanoclaw: 'nanoclaw',\n 'kimi-code': 'kimi-code',\n codex: 'codex',\n pi: 'pi',\n prime: 'prime',\n hermes: 'hermes',\n openclaw: 'openclaw',\n}\n\n/** Resolve the cwd-relative skill dir `resources.skills` refs materialize\n * into on `harness` — via the platform's `skillDirForHarness`. `null` when\n * `harness` isn't bridged (see {@link HARNESS_BRIDGE}) or when the platform\n * itself has no cwd skill primitive for it (e.g. `hermes`, user-dir-only). */\nexport function resolveSkillDir(harness: Harness): string | null {\n const bridged = HARNESS_BRIDGE[harness]\n if (!bridged) return null\n return skillDirForHarness(bridged)\n}\n\n/** Filter `harnesses` down to those with no mounted skill dir (deduped,\n * first-seen order preserved) — the set that must fall back to `inline`\n * delivery, or that a caller should warn about before offering \"mounted\"\n * install UX. */\nexport function unsupportedSkillHarnesses(harnesses: Iterable<Harness>): Harness[] {\n const seen = new Set<Harness>()\n const out: Harness[] = []\n for (const harness of harnesses) {\n if (resolveSkillDir(harness) !== null) continue\n if (seen.has(harness)) continue\n seen.add(harness)\n out.push(harness)\n }\n return out\n}\n\n/** Inputs to {@link composeSkillsForHarness}. */\nexport interface ComposeSkillsForHarnessInput {\n skills: SkillEntry[]\n harness: Harness\n tier?: string\n heading?: string\n /**\n * What to do when `harness` has no native skill-mount directory (see\n * {@link resolveSkillDir}). Default `'throw'`: refuse rather than silently\n * inlining every skill BODY into the system prompt. Pass `'inline'` only as\n * a deliberate, auditable opt-in — the caller has decided every skill must\n * reach this harness even though it will be concatenated into the prompt.\n */\n onNoSkillDir?: 'throw' | 'inline'\n}\n\n/** `KNOWN_HARNESSES` filtered to those the platform materializer can mount\n * skill files onto natively (a non-null {@link resolveSkillDir}). Computed\n * fresh rather than cached — the platform map can grow without a release\n * here. Used only to build the actionable error in\n * {@link composeSkillsForHarness}; not exported because it duplicates\n * {@link unsupportedSkillHarnesses}'s complement and callers should reach\n * for that instead when they need the harness list at runtime. */\nfunction nativeSkillMountHarnesses(): Harness[] {\n return KNOWN_HARNESSES.filter((harness) => resolveSkillDir(harness) !== null)\n}\n\n/**\n * Compose {@link ComposedSkills} for `harness`.\n *\n * `mounted` delivery is the standard path: whenever the platform names a cwd\n * skill dir for `harness`, skills ride the typed `resources.skills` channel\n * and the platform materializer writes each one to that directory as a real\n * file — the agent reads it on demand with its own file tools.\n *\n * `inline` delivery — every skill BODY rendered straight into the system\n * prompt — is a NARROW fallback for harnesses with no native skill dir, never\n * a co-equal mode. An `AgentProfile` is a RECIPE that materializes into a\n * sandbox, not a prompt template: skill bodies belong in a file mount, and\n * `prompt.systemPrompt` should carry only what the agent must obey without a\n * tool call (identity, tool-call contract, safety rules, output format) plus\n * a short index of what's mounted. Concatenating skill bodies into the prompt\n * degrades the model toward empty answers once it grows large enough — one\n * product reproduced a 151,882-byte prompt exactly this way, from an\n * unnoticed inline fallback.\n *\n * Because of that, `onNoSkillDir` defaults to `'throw'`: a harness with no\n * skill dir refuses instead of silently inlining. The thrown error names the\n * harness, the skill count, the byte size that would have been inlined, and\n * the harnesses that DO support native mounting. Pass `onNoSkillDir:\n * 'inline'` only as a deliberate, auditable opt-in when every skill genuinely\n * must reach this harness regardless of prompt cost.\n *\n * The one function a product calls instead of hand-checking `resolveSkillDir`\n * and branching between {@link composeSkills}'s two modes itself.\n */\nexport function composeSkillsForHarness(input: ComposeSkillsForHarnessInput): ComposedSkills {\n const { skills, harness, tier, heading, onNoSkillDir = 'throw' } = input\n const skillDir = resolveSkillDir(harness)\n if (skillDir) return composeSkills({ skills, mode: 'mounted', skillDir, tier, heading })\n if (onNoSkillDir === 'inline') return composeSkills({ skills, mode: 'inline', tier, heading })\n\n const relevant = tier ? skills.filter((s) => s.tier === tier) : skills\n const promptSection = renderInlineSkills({ skills, tier, heading })\n const bytes = new TextEncoder().encode(promptSection).byteLength\n const mountable = nativeSkillMountHarnesses()\n throw new Error(\n `composeSkillsForHarness: \"${harness}\" has no native skill-mount directory. ` +\n `Inlining ${relevant.length} skill(s) (${bytes} bytes) into its system prompt would silently ` +\n `convert mounted skills into prompt text — a 151,882-byte prompt shipped this way once, and ` +\n `oversized prompts degrade toward empty answers. Mount the skills instead: pick a harness with ` +\n `native skill support (${mountable.join(', ')}), or pass onNoSkillDir: 'inline' to opt in ` +\n `explicitly and accept the inlined bytes.`,\n )\n}\n\nexport type { ComposedSkills, SkillEntry } from '../skills/index'\n"],"mappings":";;;;;;;;;AAqBA,SAAS,0BAA0C;AAYnD,IAAM,iBAAsD;AAAA,EAC1D,UAAU;AAAA,EACV,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AACZ;AAMO,SAAS,gBAAgB,SAAiC;AAC/D,QAAM,UAAU,eAAe,OAAO;AACtC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,mBAAmB,OAAO;AACnC;AAMO,SAAS,0BAA0B,WAAyC;AACjF,QAAM,OAAO,oBAAI,IAAa;AAC9B,QAAM,MAAiB,CAAC;AACxB,aAAW,WAAW,WAAW;AAC/B,QAAI,gBAAgB,OAAO,MAAM,KAAM;AACvC,QAAI,KAAK,IAAI,OAAO,EAAG;AACvB,SAAK,IAAI,OAAO;AAChB,QAAI,KAAK,OAAO;AAAA,EAClB;AACA,SAAO;AACT;AAyBA,SAAS,4BAAuC;AAC9C,SAAO,gBAAgB,OAAO,CAAC,YAAY,gBAAgB,OAAO,MAAM,IAAI;AAC9E;AA+BO,SAAS,wBAAwB,OAAqD;AAC3F,QAAM,EAAE,QAAQ,SAAS,MAAM,SAAS,eAAe,QAAQ,IAAI;AACnE,QAAM,WAAW,gBAAgB,OAAO;AACxC,MAAI,SAAU,QAAO,cAAc,EAAE,QAAQ,MAAM,WAAW,UAAU,MAAM,QAAQ,CAAC;AACvF,MAAI,iBAAiB,SAAU,QAAO,cAAc,EAAE,QAAQ,MAAM,UAAU,MAAM,QAAQ,CAAC;AAE7F,QAAM,WAAW,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI;AAChE,QAAM,gBAAgB,mBAAmB,EAAE,QAAQ,MAAM,QAAQ,CAAC;AAClE,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,aAAa,EAAE;AACtD,QAAM,YAAY,0BAA0B;AAC5C,QAAM,IAAI;AAAA,IACR,6BAA6B,OAAO,mDACtB,SAAS,MAAM,cAAc,KAAK,qQAGrB,UAAU,KAAK,IAAI,CAAC;AAAA,EAEjD;AACF;","names":[]}
|
package/dist/theme/tokens.css
CHANGED
|
@@ -522,7 +522,8 @@
|
|
|
522
522
|
|
|
523
523
|
/* The waiting label. `background-clip: text` over a moving gradient, so the
|
|
524
524
|
shimmer runs THROUGH the glyphs rather than behind them. Marked essential:
|
|
525
|
-
it is the only signal that work is still in flight.
|
|
525
|
+
it is the only signal that work is still in flight. Its reduced-motion
|
|
526
|
+
answer is at the bottom of this file, with the floor it opts out of. */
|
|
526
527
|
.agent-shimmer {
|
|
527
528
|
background: linear-gradient(
|
|
528
529
|
90deg,
|
|
@@ -583,6 +584,13 @@
|
|
|
583
584
|
* out by declaring `data-motion="essential"`; the exclusion covers that element
|
|
584
585
|
* and its subtree, and `:where()` keeps the selector at zero specificity so a
|
|
585
586
|
* consumer's own `!important` can still win.
|
|
587
|
+
*
|
|
588
|
+
* `essential` is an exemption from the BLANKET rule, not a licence to keep
|
|
589
|
+
* running. It exists because collapsing a meaning-carrying animation to a 1ms
|
|
590
|
+
* flash destroys the meaning, so the element gets to answer for itself — and it
|
|
591
|
+
* then OWES that answer. An element with no end condition owes it most, which
|
|
592
|
+
* is why `.agent-shimmer` states its own below: the sweep stops, and what it
|
|
593
|
+
* was saying is re-stated as a static difference the reader can still see.
|
|
586
594
|
*/
|
|
587
595
|
@media (prefers-reduced-motion: reduce) {
|
|
588
596
|
:root {
|
|
@@ -603,6 +611,42 @@
|
|
|
603
611
|
transition-duration: 1ms !important;
|
|
604
612
|
}
|
|
605
613
|
|
|
614
|
+
/* The waiting label's own answer. It is `data-motion="essential"` because the
|
|
615
|
+
sweep is the ONLY thing separating an agent that is working from one that
|
|
616
|
+
is stuck, so the floor above must not collapse it — but an INFINITE
|
|
617
|
+
animation is exactly what someone asking for reduced motion is asking to be
|
|
618
|
+
rid of, and running it anyway because the element declared itself essential
|
|
619
|
+
is the override this file calls a defect.
|
|
620
|
+
|
|
621
|
+
So the meaning is carried without the motion. The sweep stops and the
|
|
622
|
+
gradient comes off (it exists only to be moved), which puts the glyphs back
|
|
623
|
+
under `color` instead of leaving them transparent windows onto it.
|
|
624
|
+
|
|
625
|
+
The DOTTED RULE is the discriminator, and it is the only one. Measured in
|
|
626
|
+
Chromium under `prefers-reduced-motion: reduce`, light and dark: the live
|
|
627
|
+
label computes `text-decoration: underline dotted` where a settled label
|
|
628
|
+
beside it computes `none`, and the two resolve to the SAME color and the
|
|
629
|
+
same weight. That is by construction — `color: inherit` hands the label
|
|
630
|
+
whatever its context already uses, and the settled label shares that
|
|
631
|
+
context. In `mission-activity`'s lane both tool names read rgb(12,12,21)
|
|
632
|
+
light / rgb(236,236,241) dark; in the chat trace toggle "Thinking · 12s"
|
|
633
|
+
and "Thought for 12s" both read rgb(96,96,99) light / rgb(158,158,160)
|
|
634
|
+
dark, because that button is `text-muted-foreground`. So the reader tells
|
|
635
|
+
in-flight from done by the rule under the word, from a still frame — not by
|
|
636
|
+
tone and not by weight.
|
|
637
|
+
|
|
638
|
+
Not `content: '…'` or any other generated text: this element's text is read
|
|
639
|
+
by a screen reader, and adding pseudo-content changes what is announced. */
|
|
640
|
+
.agent-shimmer {
|
|
641
|
+
animation: none;
|
|
642
|
+
background: none;
|
|
643
|
+
background-clip: border-box;
|
|
644
|
+
-webkit-background-clip: border-box;
|
|
645
|
+
color: inherit;
|
|
646
|
+
text-decoration: underline dotted currentColor;
|
|
647
|
+
text-underline-offset: 3px;
|
|
648
|
+
}
|
|
649
|
+
|
|
606
650
|
html {
|
|
607
651
|
scroll-behavior: auto !important;
|
|
608
652
|
}
|
|
@@ -134,11 +134,19 @@ type FieldValues = Record<string, {
|
|
|
134
134
|
* intentionally used only when an interaction carries `answers`, never to
|
|
135
135
|
* guess an answer from the absence of an outstanding sidecar ask. */
|
|
136
136
|
declare function fieldValuesFromAnswers(fields: ChatInteractionField[], answers: InteractionAnswers | undefined): FieldValues;
|
|
137
|
-
/** The submitted value for one field, or null when it has no answer yet.
|
|
138
|
-
|
|
137
|
+
/** The submitted value for one field, or null when it has no answer yet.
|
|
138
|
+
*
|
|
139
|
+
* Returns `InteractionAnswers[string]`, not the wider `InteractionData[string]`:
|
|
140
|
+
* a card reads its value out of a rendered control, so every branch below
|
|
141
|
+
* yields a plain scalar or string array. `InteractionData` also admits a
|
|
142
|
+
* one-use `secret_handle` reference, which no control here can produce and
|
|
143
|
+
* which `onResolved` must never receive — that path persists into the visible
|
|
144
|
+
* transcript. Declaring the narrow type keeps the handle out by construction
|
|
145
|
+
* rather than by review. */
|
|
146
|
+
declare function fieldAnswer(field: ChatInteractionField, values: FieldValues): InteractionAnswers[string] | null;
|
|
139
147
|
/** All required fields answered → the respond payload; else null (not
|
|
140
148
|
* submittable yet). Optional unanswered fields are omitted. */
|
|
141
|
-
declare function buildAnswerData(fields: ChatInteractionField[], values: FieldValues):
|
|
149
|
+
declare function buildAnswerData(fields: ChatInteractionField[], values: FieldValues): InteractionAnswers | null;
|
|
142
150
|
/** Determine if a status is late answerable by checking if it is expired or cancelled */
|
|
143
151
|
declare function isLateAnswerableStatus(status: ChatInteractionStatus): boolean;
|
|
144
152
|
/** Secrets must never leave the sidecar answer channel for the visible chat
|
|
@@ -527,7 +535,14 @@ interface QuestionOptionListProps {
|
|
|
527
535
|
}
|
|
528
536
|
/** The radio/checkbox option rows for a select field. Renders a fragment of
|
|
529
537
|
* option `<label>` rows so a card keeps its own wrapping layout and appends
|
|
530
|
-
* its own write-in input.
|
|
538
|
+
* its own write-in input.
|
|
539
|
+
*
|
|
540
|
+
* The rows arrive as a SEQUENCE (`.agent-arrive` + `--stagger-index`), which
|
|
541
|
+
* is the difference between reading a list and being shown one: the eye is
|
|
542
|
+
* told there are N choices and in what order before it has read any of them.
|
|
543
|
+
* The index is safe to take straight from the map because an option list does
|
|
544
|
+
* not re-sort under a mounted card — a different set of options is a
|
|
545
|
+
* different `key`, and a different ask resets the card wholesale. */
|
|
531
546
|
declare function QuestionOptionList({ groupName, idPrefix, options, multi, selectedValues, disabled, onToggle, answered, }: QuestionOptionListProps): react.JSX.Element;
|
|
532
547
|
interface InteractionQuestionCardProps {
|
|
533
548
|
interaction: ChatInteraction;
|
|
@@ -1050,6 +1065,12 @@ interface MissionActivityLaneProps {
|
|
|
1050
1065
|
/**
|
|
1051
1066
|
* Collapsed sub-rows under a mission step — one row per delegated run —
|
|
1052
1067
|
* expanding to the step's waterfall. Renders nothing for an empty lane.
|
|
1068
|
+
*
|
|
1069
|
+
* A sub-row appears because a delegated run STARTED or FINISHED, which is the
|
|
1070
|
+
* one kind of list change worth choreographing: it arrives, and the group
|
|
1071
|
+
* arrives as a sequence. Keying on `taskId` is what keeps the rest still — the
|
|
1072
|
+
* snapshot re-renders every poll, and a row whose status merely advanced holds
|
|
1073
|
+
* the DOM node it already had.
|
|
1053
1074
|
*/
|
|
1054
1075
|
declare function MissionActivityLane({ activity, startedAt, nowMs }: MissionActivityLaneProps): react.JSX.Element | null;
|
|
1055
1076
|
interface AgentActivityPanelProps {
|
package/dist/web-react/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.52",
|
|
4
4
|
"packageManager": "pnpm@11.17.0",
|
|
5
5
|
"description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
|
|
6
6
|
"keywords": [
|
|
@@ -518,15 +518,15 @@
|
|
|
518
518
|
"@storybook/react": "^10.5.5",
|
|
519
519
|
"@storybook/react-vite": "^10.5.5",
|
|
520
520
|
"@tangle-network/agent-docs": "0.2.1",
|
|
521
|
-
"@tangle-network/agent-eval": "0.
|
|
522
|
-
"@tangle-network/agent-integrations": "0.53.
|
|
523
|
-
"@tangle-network/agent-interface": "0.
|
|
524
|
-
"@tangle-network/agent-knowledge": "7.
|
|
525
|
-
"@tangle-network/agent-profile-materialize": "0.
|
|
526
|
-
"@tangle-network/agent-runtime": "0.
|
|
527
|
-
"@tangle-network/brand": "1.
|
|
528
|
-
"@tangle-network/sandbox": "0.
|
|
529
|
-
"@tangle-network/sandbox-ui": "0.
|
|
521
|
+
"@tangle-network/agent-eval": "0.145.3",
|
|
522
|
+
"@tangle-network/agent-integrations": "0.53.53",
|
|
523
|
+
"@tangle-network/agent-interface": "0.47.0",
|
|
524
|
+
"@tangle-network/agent-knowledge": "7.2.4",
|
|
525
|
+
"@tangle-network/agent-profile-materialize": "0.14.0",
|
|
526
|
+
"@tangle-network/agent-runtime": "0.132.13",
|
|
527
|
+
"@tangle-network/brand": "1.4.0",
|
|
528
|
+
"@tangle-network/sandbox": "0.21.1",
|
|
529
|
+
"@tangle-network/sandbox-ui": "0.100.1",
|
|
530
530
|
"@tangle-network/ui": "^11.2.2",
|
|
531
531
|
"@testing-library/dom": "^10.4.1",
|
|
532
532
|
"@testing-library/react": "^16.3.2",
|
|
@@ -570,15 +570,15 @@
|
|
|
570
570
|
"@firecrawl/pdf-inspector-wasm": ">=0.1.3",
|
|
571
571
|
"@huggingface/transformers": ">=3",
|
|
572
572
|
"@radix-ui/react-dialog": ">=1.1",
|
|
573
|
-
"@tangle-network/agent-eval": ">=0.
|
|
573
|
+
"@tangle-network/agent-eval": ">=0.145.2",
|
|
574
574
|
"@tangle-network/agent-integrations": ">=0.52.0",
|
|
575
|
-
"@tangle-network/agent-interface": ">=0.
|
|
576
|
-
"@tangle-network/agent-knowledge": ">=
|
|
577
|
-
"@tangle-network/agent-profile-materialize": ">=0.
|
|
578
|
-
"@tangle-network/agent-runtime": ">=0.
|
|
579
|
-
"@tangle-network/brand": ">=1.
|
|
580
|
-
"@tangle-network/sandbox": ">=0.
|
|
581
|
-
"@tangle-network/sandbox-ui": ">=0.
|
|
575
|
+
"@tangle-network/agent-interface": ">=0.47.0 <0.48.0",
|
|
576
|
+
"@tangle-network/agent-knowledge": ">=7.2.4",
|
|
577
|
+
"@tangle-network/agent-profile-materialize": ">=0.14.0",
|
|
578
|
+
"@tangle-network/agent-runtime": ">=0.132.13",
|
|
579
|
+
"@tangle-network/brand": ">=1.4.0",
|
|
580
|
+
"@tangle-network/sandbox": ">=0.21.1",
|
|
581
|
+
"@tangle-network/sandbox-ui": ">=0.100.1",
|
|
582
582
|
"@tangle-network/ui": ">=11.2.2",
|
|
583
583
|
"@xyflow/react": ">=12.0.0",
|
|
584
584
|
"better-auth": ">=1.6.16",
|