@tangle-network/agent-app 0.44.5 → 0.44.7
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/budget-BOucfcb_.d.ts +142 -0
- package/dist/chat-routes/index.d.ts +11 -2
- package/dist/chat-routes/index.js +8 -2
- package/dist/chat-routes/index.js.map +1 -1
- package/dist/{chunk-JHYJZSFX.js → chunk-JXIQSGOV.js} +22 -2
- package/dist/chunk-JXIQSGOV.js.map +1 -0
- package/dist/chunk-LWSJK546.js +129 -0
- package/dist/chunk-LWSJK546.js.map +1 -0
- package/dist/profile/index.d.ts +3 -37
- package/dist/profile/index.js +7 -43
- package/dist/profile/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +2 -1
- package/dist/sandbox/index.js +2 -2
- package/package.json +2 -1
- package/dist/chunk-IVUN7FL7.js +0 -72
- package/dist/chunk-IVUN7FL7.js.map +0 -1
- package/dist/chunk-JHYJZSFX.js.map +0 -1
- package/dist/fingerprint-DbmOgy0n.d.ts +0 -69
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { AgentProfile } from '@tangle-network/agent-interface';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Profile fingerprinting — prove WHICH profile a turn actually executed.
|
|
5
|
+
*
|
|
6
|
+
* The backtest invariant this exists to enforce: an eval's score is only worth
|
|
7
|
+
* publishing if the benchmarked profile IS the shipped profile. The failure
|
|
8
|
+
* mode is structural, not hypothetical — a product's eval composed the
|
|
9
|
+
* production profile in one module, executed a hand-rolled stub in another,
|
|
10
|
+
* and stamped the composed profile's identity onto the stub's scorecard.
|
|
11
|
+
* Nothing compared the two, so nothing could notice.
|
|
12
|
+
*
|
|
13
|
+
* A `ProfileFingerprint` is a channelled identity of the profile handed to the
|
|
14
|
+
* sandbox SDK: the system-prompt digest plus the names of every capability
|
|
15
|
+
* surface (MCP servers, subagents, file mounts, hub connections) and the
|
|
16
|
+
* model/harness the turn dispatched at. It is deliberately NOT a byte-exhaustive
|
|
17
|
+
* serialization — channels are what drift in practice, and a channelled diff
|
|
18
|
+
* names the surface that moved instead of reporting "bytes differ".
|
|
19
|
+
*
|
|
20
|
+
* The write half of the seam is `StreamSandboxPromptOptions.onProfileResolved`
|
|
21
|
+
* (`/sandbox`): the one place the final profile exists is inside
|
|
22
|
+
* `streamSandboxPrompt` after the system-prompt override, the MCP merge, and
|
|
23
|
+
* reasoning-effort attachment, so that is where the fingerprint is taken. A
|
|
24
|
+
* caller re-deriving a profile to fingerprint it would reintroduce the exact
|
|
25
|
+
* gap this closes.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** The dispatch context a profile cannot see but a turn's identity includes. */
|
|
29
|
+
interface ProfileFingerprintContext {
|
|
30
|
+
model?: string;
|
|
31
|
+
harness?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Channelled identity of one executed (or composed) profile. */
|
|
34
|
+
interface ProfileFingerprint {
|
|
35
|
+
/** sha256 over every channel below — one value to log/compare. */
|
|
36
|
+
hash: string;
|
|
37
|
+
/** sha256 of `prompt.systemPrompt` ('' when absent). */
|
|
38
|
+
promptSha: string;
|
|
39
|
+
/** UTF-8 byte length of `prompt.systemPrompt`. */
|
|
40
|
+
promptBytes: number;
|
|
41
|
+
/** Sorted MCP server keys. */
|
|
42
|
+
mcpKeys: string[];
|
|
43
|
+
/** Sorted subagent names. */
|
|
44
|
+
subagentNames: string[];
|
|
45
|
+
/** Sorted `resources.files[].path` mounts. */
|
|
46
|
+
fileMountPaths: string[];
|
|
47
|
+
/** Sorted hub connection ids (alias-qualified when present). */
|
|
48
|
+
connectionIds: string[];
|
|
49
|
+
model?: string;
|
|
50
|
+
harness?: string;
|
|
51
|
+
}
|
|
52
|
+
/** Fingerprint a profile as the SDK would receive it. */
|
|
53
|
+
declare function fingerprintAgentProfile(profile: AgentProfile, context?: ProfileFingerprintContext): Promise<ProfileFingerprint>;
|
|
54
|
+
/** One drifted channel between two fingerprints, rendered as comparable strings. */
|
|
55
|
+
interface ProfileDriftEntry {
|
|
56
|
+
channel: 'promptSha' | 'promptBytes' | 'mcpKeys' | 'subagentNames' | 'fileMountPaths' | 'connectionIds' | 'model' | 'harness';
|
|
57
|
+
a: string;
|
|
58
|
+
b: string;
|
|
59
|
+
}
|
|
60
|
+
interface ProfileDrift {
|
|
61
|
+
equal: boolean;
|
|
62
|
+
drift: ProfileDriftEntry[];
|
|
63
|
+
}
|
|
64
|
+
/** Channel-by-channel comparison of two fingerprints. */
|
|
65
|
+
declare function diffProfileFingerprints(a: ProfileFingerprint, b: ProfileFingerprint): ProfileDrift;
|
|
66
|
+
/** Human-readable drift report; exactly 'profiles identical' when equal. */
|
|
67
|
+
declare function formatProfileDrift(drift: ProfileDrift): string;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The composed-system-prompt byte budget, split out of `./index` so it imports
|
|
71
|
+
* NOTHING.
|
|
72
|
+
*
|
|
73
|
+
* `./index` pulls `@tangle-network/agent-eval` (the evolvable-section seam), so
|
|
74
|
+
* `/sandbox` — which has no agent-eval import and must not gain one — could not
|
|
75
|
+
* enforce the budget from there. The gate is the same function either way; only
|
|
76
|
+
* its module home moved. `./index` re-exports every symbol below, so the
|
|
77
|
+
* published `/profile` surface is byte-identical.
|
|
78
|
+
*
|
|
79
|
+
* Why the gate belongs at more than one call site: `composeAgentProfile` is
|
|
80
|
+
* OPT-IN. A product may hand-build its `AgentProfile`, and one does —
|
|
81
|
+
* creative-agent's create-time profile is deliberately minimal and its full
|
|
82
|
+
* system prompt rides the PER-TURN backend (`buildPromptBackend`), which never
|
|
83
|
+
* touches the composer. `/sandbox` therefore runs this gate at the three points
|
|
84
|
+
* where the profile that actually executes exists.
|
|
85
|
+
*/
|
|
86
|
+
/** Byte budget on the FINAL composed `prompt.systemPrompt`. Past this the
|
|
87
|
+
* model degrades sharply (a 122,659-byte prompt shipped once and the model
|
|
88
|
+
* returned empty answers), so the default gate throws well before that. */
|
|
89
|
+
declare const DEFAULT_MAX_SYSTEM_PROMPT_BYTES = 40000;
|
|
90
|
+
/** Budget config for the composed system prompt. */
|
|
91
|
+
interface ComposeProfileBudget {
|
|
92
|
+
/** Byte cap on the composed `prompt.systemPrompt`.
|
|
93
|
+
* Default {@link DEFAULT_MAX_SYSTEM_PROMPT_BYTES}. */
|
|
94
|
+
maxSystemPromptBytes?: number;
|
|
95
|
+
/** Downgrade the over-budget throw to a `console.warn` — the escape hatch
|
|
96
|
+
* for a product with a known-big prompt that must still ship (it yells on
|
|
97
|
+
* every compose instead of blocking). */
|
|
98
|
+
warnOnly?: boolean;
|
|
99
|
+
/** Required to raise {@link maxSystemPromptBytes} above
|
|
100
|
+
* {@link DEFAULT_MAX_SYSTEM_PROMPT_BYTES} or to set {@link warnOnly}: a
|
|
101
|
+
* written reason naming what stays inline and why it cannot be mounted.
|
|
102
|
+
* Weakening the cap is a product decision that outlives the person making
|
|
103
|
+
* it, and the usual cause is reference material concatenated into the prompt
|
|
104
|
+
* that belongs in `resources.files`; demanding the sentence here keeps that
|
|
105
|
+
* from happening by accident. */
|
|
106
|
+
overBudgetReason?: string;
|
|
107
|
+
}
|
|
108
|
+
/** Largest markdown-heading-delimited sections of a prompt, by UTF-8 bytes.
|
|
109
|
+
* Cheap heuristic: split on `#`-heading lines; the preamble before the first
|
|
110
|
+
* heading reports as "(preamble)". */
|
|
111
|
+
declare function largestPromptSections(prompt: string, top?: number): Array<{
|
|
112
|
+
title: string;
|
|
113
|
+
bytes: number;
|
|
114
|
+
}>;
|
|
115
|
+
/** Enforce {@link ComposeProfileBudget} on a composed system prompt: over
|
|
116
|
+
* budget throws (or warns with `warnOnly`) with the actual size and the
|
|
117
|
+
* top-3 largest sections. Exported so a product assembling its prompt
|
|
118
|
+
* outside `composeAgentProfile` (e.g. via the `/prompt` assembler) can
|
|
119
|
+
* run the same gate at its own final-composition point. */
|
|
120
|
+
declare function assertSystemPromptWithinBudget(systemPrompt: string, budget?: ComposeProfileBudget,
|
|
121
|
+
/** Prefixed to the message so a throw from a turn/provision choke point says
|
|
122
|
+
* WHERE it fired — "composed systemPrompt" alone reads like a compose-time
|
|
123
|
+
* error even when it fired on `driveSandboxTurn`. */
|
|
124
|
+
origin?: string): void;
|
|
125
|
+
/** Run {@link assertSystemPromptWithinBudget} over a profile-shaped object's
|
|
126
|
+
* `prompt.systemPrompt`. Structural on purpose: `/sandbox` calls this on the
|
|
127
|
+
* SDK's `AgentProfile` and on the product-supplied seam result without either
|
|
128
|
+
* module importing the other's types. A profile with no string systemPrompt
|
|
129
|
+
* is a no-op — there is nothing to measure.
|
|
130
|
+
*
|
|
131
|
+
* The `hint` exists because this gate can fire on a product that ALREADY made
|
|
132
|
+
* a deliberate budget decision somewhere else. gtm-agent composes with
|
|
133
|
+
* `{ maxSystemPromptBytes: 50_000 }`; without the hint, the shell's 40 KB
|
|
134
|
+
* default reads as the gate contradicting a choice the product already made
|
|
135
|
+
* rather than as "declare the same number here too". */
|
|
136
|
+
declare function assertProfilePromptWithinBudget(profile: {
|
|
137
|
+
prompt?: {
|
|
138
|
+
systemPrompt?: unknown;
|
|
139
|
+
};
|
|
140
|
+
} | undefined, budget?: ComposeProfileBudget, origin?: string, hint?: string): void;
|
|
141
|
+
|
|
142
|
+
export { type ComposeProfileBudget as C, DEFAULT_MAX_SYSTEM_PROMPT_BYTES as D, type ProfileDrift as P, type ProfileDriftEntry as a, type ProfileFingerprint as b, type ProfileFingerprintContext as c, assertProfilePromptWithinBudget as d, assertSystemPromptWithinBudget as e, diffProfileFingerprints as f, fingerprintAgentProfile as g, formatProfileDrift as h, largestPromptSections as l };
|
|
@@ -18,7 +18,7 @@ import '../auth-anc7mv2W.js';
|
|
|
18
18
|
import '../types-BCxK0wyS.js';
|
|
19
19
|
import '../harness/index.js';
|
|
20
20
|
import '../model-CdCDfBA9.js';
|
|
21
|
-
import '../
|
|
21
|
+
import '../budget-BOucfcb_.js';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Incremental ("draft") persistence of the assistant row WHILE a turn streams.
|
|
@@ -822,6 +822,15 @@ interface ModelFailoverStreamHandle {
|
|
|
822
822
|
* sandbox turn — so the budget is capped rather than trusted.
|
|
823
823
|
*/
|
|
824
824
|
declare const MAX_EMPTY_TURN_RETRIES = 3;
|
|
825
|
+
/**
|
|
826
|
+
* Coerce the caller's budget to a finite, bounded, non-negative integer.
|
|
827
|
+
*
|
|
828
|
+
* `Math.trunc(NaN)` is `NaN` and `retry >= NaN` is false for every `retry`, so
|
|
829
|
+
* a naive clamp turns a bad config value into a loop that opens sandbox streams
|
|
830
|
+
* until the worker dies. `Infinity` has the same shape. Both resolve to `0` —
|
|
831
|
+
* an unusable budget disables the retry rather than running unbounded.
|
|
832
|
+
*/
|
|
833
|
+
declare function resolveEmptyTurnRetries(value: number | undefined): number;
|
|
825
834
|
/**
|
|
826
835
|
* Wrap `open` in reactive model failover, streaming from the first model in
|
|
827
836
|
* `models` that reaches its commit point.
|
|
@@ -1661,4 +1670,4 @@ interface PromoteAgentFilePartOptions {
|
|
|
1661
1670
|
/** Promote a part of an agent file with optional byte limits and MIME type detection */
|
|
1662
1671
|
declare function promoteAgentFilePart(options: PromoteAgentFilePartOptions): Promise<PromoteFilePartResult>;
|
|
1663
1672
|
|
|
1664
|
-
export { type AssistantDraftSnapshot, type AssistantDraftStore, type AssistantDraftWriter, type AssistantDraftWriterOptions, type AssistantRowValues, type AttachmentPathArgs, type AttachmentPathCheck, type AttachmentReadResult, type AttachmentUploadAuthorization, type AttachmentWriteResult, type BuildDispatchPartsInput, ChatAttachmentKind, type ChatRouteDurableProjection, type ChatRouteDurableProjectionLogger, type ChatRouteEvent, type ChatTurnAuthorization, type ChatTurnAuthorizeArgs, type ChatTurnCompleteInput, ChatTurnFilePartInput, type ChatTurnGateResult, type ChatTurnHeartbeat, type ChatTurnInputPatch, type ChatTurnLifecycle, type ChatTurnLifecycleComplete, type ChatTurnLifecycleError, type ChatTurnLifecycleStart, type ChatTurnLock, type ChatTurnLockResult, type ChatTurnMessageStore, type ChatTurnModelFailover, ChatTurnPartInput, type ChatTurnProduceArgs, ChatTurnRequestPayload, type ChatTurnRouteProducer, type ChatTurnRoutes, type ChatTurnUsage, type CreateAttachmentUploadRouteOptions, type CreateChatTurnRoutesOptions, type CreateUploadRouteOptions, type DetachedTurnFinal, type DetachedTurnOptions, type DetachedTurnParts, type DetachedTurnResult, type DispatchPartsOutcome, type DraftPersistenceTuning, type DraftStoredMessage, type EmptyTurnRetryInfo, type FilePartPromotionOutcome, MAX_EMPTY_TURN_RETRIES, type ModelFailoverStreamHandle, type ModelFailoverStreamOptions, type ModelFallbackInfo, type OpenModelStream, PROMOTE_MAX_FILE_BYTES, type PromoteAgentFilePartOptions, type PromoteFilePartResult, PromptInputPart, type RawAgentFilePart, type ReadAttachmentFn, type ReadSandboxMentionFn, type ResolveChatAttachmentsOptions, type ResolveChatAttachmentsResult, type SandboxChatProducerOptions, type SandboxUploadSink, UPLOAD_INLINE_MAX_BYTES, UPLOAD_MAX_FILE_BYTES, type UploadAuthorization, type UploadedChatFile, type WriteAttachmentFn, assistantRowIdForTurn, buildDispatchParts, bytesToBase64, classifyTerminalFailure, createAssistantDraftWriter, createAttachmentUploadRoute, createChatTurnRoutes, createSandboxChatProducer, createUploadRoute, defaultValidateAttachmentPath, isCommittingSandboxEvent, isDraftContentEvent, promoteAgentFilePart, resolveChatAttachments, rowIdOf, runDetachedTurn, sanitizeUploadFilename, sniffMimeFromName, storeSupportsDraftPersistence, streamWithModelFailover, withDurableChatProjection };
|
|
1673
|
+
export { type AssistantDraftSnapshot, type AssistantDraftStore, type AssistantDraftWriter, type AssistantDraftWriterOptions, type AssistantRowValues, type AttachmentPathArgs, type AttachmentPathCheck, type AttachmentReadResult, type AttachmentUploadAuthorization, type AttachmentWriteResult, type BuildDispatchPartsInput, ChatAttachmentKind, type ChatRouteDurableProjection, type ChatRouteDurableProjectionLogger, type ChatRouteEvent, type ChatTurnAuthorization, type ChatTurnAuthorizeArgs, type ChatTurnCompleteInput, ChatTurnFilePartInput, type ChatTurnGateResult, type ChatTurnHeartbeat, type ChatTurnInputPatch, type ChatTurnLifecycle, type ChatTurnLifecycleComplete, type ChatTurnLifecycleError, type ChatTurnLifecycleStart, type ChatTurnLock, type ChatTurnLockResult, type ChatTurnMessageStore, type ChatTurnModelFailover, ChatTurnPartInput, type ChatTurnProduceArgs, ChatTurnRequestPayload, type ChatTurnRouteProducer, type ChatTurnRoutes, type ChatTurnUsage, type CreateAttachmentUploadRouteOptions, type CreateChatTurnRoutesOptions, type CreateUploadRouteOptions, type DetachedTurnFinal, type DetachedTurnOptions, type DetachedTurnParts, type DetachedTurnResult, type DispatchPartsOutcome, type DraftPersistenceTuning, type DraftStoredMessage, type EmptyTurnRetryInfo, type FilePartPromotionOutcome, MAX_EMPTY_TURN_RETRIES, type ModelFailoverStreamHandle, type ModelFailoverStreamOptions, type ModelFallbackInfo, type OpenModelStream, PROMOTE_MAX_FILE_BYTES, type PromoteAgentFilePartOptions, type PromoteFilePartResult, PromptInputPart, type RawAgentFilePart, type ReadAttachmentFn, type ReadSandboxMentionFn, type ResolveChatAttachmentsOptions, type ResolveChatAttachmentsResult, type SandboxChatProducerOptions, type SandboxUploadSink, UPLOAD_INLINE_MAX_BYTES, UPLOAD_MAX_FILE_BYTES, type UploadAuthorization, type UploadedChatFile, type WriteAttachmentFn, assistantRowIdForTurn, buildDispatchParts, bytesToBase64, classifyTerminalFailure, createAssistantDraftWriter, createAttachmentUploadRoute, createChatTurnRoutes, createSandboxChatProducer, createUploadRoute, defaultValidateAttachmentPath, isCommittingSandboxEvent, isDraftContentEvent, promoteAgentFilePart, resolveChatAttachments, resolveEmptyTurnRetries, rowIdOf, runDetachedTurn, sanitizeUploadFilename, sniffMimeFromName, storeSupportsDraftPersistence, streamWithModelFailover, withDurableChatProjection };
|
|
@@ -92,8 +92,8 @@ import {
|
|
|
92
92
|
flattenHistory,
|
|
93
93
|
readSandboxBinaryBytes,
|
|
94
94
|
statSandboxFileSize
|
|
95
|
-
} from "../chunk-
|
|
96
|
-
import "../chunk-
|
|
95
|
+
} from "../chunk-JXIQSGOV.js";
|
|
96
|
+
import "../chunk-LWSJK546.js";
|
|
97
97
|
import "../chunk-CQZSAR77.js";
|
|
98
98
|
import "../chunk-ICOHEZK6.js";
|
|
99
99
|
import "../chunk-3EJ6SFJI.js";
|
|
@@ -1081,6 +1081,11 @@ function createSandboxChatProducer(options) {
|
|
|
1081
1081
|
if (!options.openEvents && !options.events) {
|
|
1082
1082
|
throw new Error("createSandboxChatProducer: pass `openEvents` (failover-capable) or `events`");
|
|
1083
1083
|
}
|
|
1084
|
+
if (!options.openEvents && resolveEmptyTurnRetries(options.emptyTurnRetries) > 0) {
|
|
1085
|
+
throw new Error(
|
|
1086
|
+
"createSandboxChatProducer: `emptyTurnRetries` requires `openEvents` \u2014 a fixed `events` stream cannot be re-opened"
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1084
1089
|
const chain = options.model ? buildModelChain(options.model, options.modelFailover === false ? [] : options.fallbackModels ?? []) : [];
|
|
1085
1090
|
const pendingModelNotices = [];
|
|
1086
1091
|
let modelNoticeCount = 0;
|
|
@@ -2341,6 +2346,7 @@ export {
|
|
|
2341
2346
|
promptPartsByteSize,
|
|
2342
2347
|
reconcileStaleTurnLock,
|
|
2343
2348
|
resolveChatAttachments,
|
|
2349
|
+
resolveEmptyTurnRetries,
|
|
2344
2350
|
rowIdOf,
|
|
2345
2351
|
runDetachedTurn,
|
|
2346
2352
|
sanitizeAttachmentFileName,
|