@tangle-network/agent-app 0.44.8 → 0.44.10
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.d.ts +4 -4
- package/dist/assistant/index.js +6 -6
- package/dist/{attachment-validation-DRuLEjAE.d.ts → attachment-validation-yJ6Id4pR.d.ts} +1 -1
- package/dist/chat-routes/index.d.ts +28 -5
- package/dist/chat-routes/index.js +45 -5
- package/dist/chat-routes/index.js.map +1 -1
- package/dist/chat-store/index.d.ts +3 -3
- package/dist/chat-store/index.js +2 -2
- package/dist/{chunk-V55WJSR4.js → chunk-5GA3MKOC.js} +2 -2
- package/dist/{chunk-UDSY2F6N.js → chunk-72TPRENZ.js} +21 -8
- package/dist/chunk-72TPRENZ.js.map +1 -0
- package/dist/{chunk-AFNTRJQ7.js → chunk-FEUW4G2L.js} +2 -2
- package/dist/{chunk-TKRI463Z.js → chunk-J6TNPRQN.js} +4 -4
- package/dist/{chunk-F2CBC4DY.js → chunk-V3HO43PG.js} +15 -1
- package/dist/chunk-V3HO43PG.js.map +1 -0
- package/dist/{chunk-UP33Z633.js → chunk-ZRSUCTST.js} +2 -2
- package/dist/{parts-Co_lFgLI.d.ts → parts-DIKcC1p6.d.ts} +1 -1
- package/dist/{queue-CD5-_VTX.d.ts → queue-DBkulxW1.d.ts} +1 -1
- package/dist/turn-health/index.d.ts +149 -13
- package/dist/turn-health/index.js +192 -12
- package/dist/turn-health/index.js.map +1 -1
- package/dist/{types-XIZqIdX1.d.ts → types-DeEOhQbv.d.ts} +25 -3
- package/dist/web-react/index.d.ts +6 -6
- package/dist/web-react/index.js +6 -6
- package/dist/work-product/index.d.ts +73 -5
- package/dist/work-product/index.js +131 -17
- package/dist/work-product/index.js.map +1 -1
- package/dist/work-product-react/index.d.ts +1 -1
- package/dist/work-product-react/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-F2CBC4DY.js.map +0 -1
- package/dist/chunk-UDSY2F6N.js.map +0 -1
- /package/dist/{chunk-V55WJSR4.js.map → chunk-5GA3MKOC.js.map} +0 -0
- /package/dist/{chunk-AFNTRJQ7.js.map → chunk-FEUW4G2L.js.map} +0 -0
- /package/dist/{chunk-TKRI463Z.js.map → chunk-J6TNPRQN.js.map} +0 -0
- /package/dist/{chunk-UP33Z633.js.map → chunk-ZRSUCTST.js.map} +0 -0
|
@@ -38,13 +38,35 @@ interface WorkProductArtifact {
|
|
|
38
38
|
/** The structured field map lineage targets anchor to (tax: form-line ids). */
|
|
39
39
|
fields?: Record<string, unknown>;
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
41
|
+
/** A half-open `[start, end)` character range into the source document's text.
|
|
42
|
+
* Offsets index exactly the string the product's `readSourceText` seam
|
|
43
|
+
* returns for the same `sourceRef` — which is the string its document-reading
|
|
44
|
+
* tool pages with an `offset`. The PLATFORM slices `locator.quote` out of it,
|
|
45
|
+
* so a span citation cannot name text the document does not contain. */
|
|
46
|
+
interface EvidenceSpan {
|
|
47
|
+
start: number;
|
|
48
|
+
end: number;
|
|
49
|
+
}
|
|
50
|
+
/** How `locator.quote` got there. Server-set on every path — never read from
|
|
51
|
+
* model args, because the whole value of the distinction is that a reviewer
|
|
52
|
+
* can trust it:
|
|
53
|
+
* - `span` the platform sliced it out of the source bytes (unfalsifiable)
|
|
54
|
+
* - `model` the model supplied the text and the platform PROVED it occurs */
|
|
55
|
+
type QuoteBasis = 'span' | 'model';
|
|
56
|
+
/** Point into a source document: page, free-form range, span, verbatim quote */
|
|
42
57
|
interface EvidenceLocator {
|
|
43
58
|
page?: number;
|
|
44
59
|
/** 'L120-L134' | 'B7' | '¶4' — free-form, non-empty when present. */
|
|
45
60
|
range?: string;
|
|
46
|
-
/** Verbatim supporting quote from the source.
|
|
61
|
+
/** Verbatim supporting quote from the source. Model-supplied and verified,
|
|
62
|
+
* or platform-sliced from {@link EvidenceLocator.span} — read `quoteBasis`
|
|
63
|
+
* to tell which. */
|
|
47
64
|
quote?: string;
|
|
65
|
+
/** Character range the quote is sliced from. The preferred citation form:
|
|
66
|
+
* two integers cannot be a fabricated quote. */
|
|
67
|
+
span?: EvidenceSpan;
|
|
68
|
+
/** Server-set provenance for `quote`; a model-supplied value is discarded. */
|
|
69
|
+
quoteBasis?: QuoteBasis;
|
|
48
70
|
}
|
|
49
71
|
/** One lineage row: a source document location supporting one artifact claim */
|
|
50
72
|
interface EvidenceEntry {
|
|
@@ -265,4 +287,4 @@ declare function workProductToPersistedPart(record: WorkProductRecord): WorkProd
|
|
|
265
287
|
/** Re-validate a stored/wire part into the typed anchor; null for junk. */
|
|
266
288
|
declare function persistedPartToWorkProduct(part: Record<string, unknown>): WorkProductPersistedPart | null;
|
|
267
289
|
|
|
268
|
-
export { type AgentCheckInput as A, type EvidenceEntry as E, type ProfileBacktestSummary as P, type QualityCheck as Q, type WorkProductRef as W, type WorkProductProvenance as a, type WorkProductRecord as b, type WorkProductPersistedPart as c, type WorkProductStorePort as d, type WorkProductAuditEvent as e, type WorkProductArtifact as f, type ExceptionEntry as g, type WorkProductStatus as h, type EvidenceLocator as i, type
|
|
290
|
+
export { type AgentCheckInput as A, type EvidenceEntry as E, type ProfileBacktestSummary as P, type QualityCheck as Q, type WorkProductRef as W, type WorkProductProvenance as a, type WorkProductRecord as b, type WorkProductPersistedPart as c, type WorkProductStorePort as d, type WorkProductAuditEvent as e, type WorkProductArtifact as f, type ExceptionEntry as g, type WorkProductStatus as h, type EvidenceLocator as i, type EvidenceSpan as j, type ExceptionSeverity as k, type QuoteBasis as l, type WorkProductParseResult as m, type WorkProductPatch as n, type WorkProductUpdateGuard as o, type WorkProductVersionEntry as p, isWorkProductStatus as q, parseAgentCheckInput as r, parseArtifactInput as s, parseEvidenceInput as t, parseExceptionInput as u, persistedPartToWorkProduct as v, unresolvedBlockingExceptions as w, workProductToPersistedPart as x };
|
|
@@ -5,17 +5,17 @@ export { f as ChatFreeTextField, g as ComposerAnswerDelivery, h as INTERACTION_C
|
|
|
5
5
|
import { ChatPlan } from '../plans/index.js';
|
|
6
6
|
import { InteractionData } from '@tangle-network/agent-interface';
|
|
7
7
|
export { InteractionData, InteractionOutcome, InteractionRequest } from '@tangle-network/agent-interface';
|
|
8
|
-
import { M as FileMention, g as ChatMentionPart, b as ChatAttachmentPart, a as ChatAttachmentKind, Q as ChatAttachmentInput } from '../parts-
|
|
9
|
-
export { f as ChatMentionKind, P as ChatTurnFilePartInput, O as ChatTurnPartInput, N as ChatTurnRequestPayload, U as DISPATCH_MAX_MEDIA_PARTS, V as DISPATCH_MAX_PARTS, W as DISPATCH_REQUEST_MAX_BYTES, X as DISPATCH_STRUCTURAL_RESERVE_BYTES, $ as ProducerErrorEvent, a0 as ProducerNoticeEvent, a1 as ProducerPassthroughEvent, a2 as ProducerPassthroughEventType, a3 as ProducerReasoningEvent, a4 as ProducerTextEvent, a5 as ProducerToolCallEvent, a6 as ProducerToolResultEvent, a7 as ProducerUsageEvent, a8 as ProducerWireEvent, u as attachmentInputToPart, v as attachmentKindForMime, w as attachmentPartsFromMessageParts, ab as base64WireLen, ac as buildMentionPromptBlock, ad as chatTurnRequestInit, ae as fileMentionsToParts, z as isChatAttachmentPart, ag as mediaTypeForMentionPath, J as mentionInputToPart, ah as mentionKindForPath, K as mentionPartsFromMessageParts } from '../parts-
|
|
10
|
-
import { E as EvidenceEntry, g as ExceptionEntry, a as WorkProductProvenance, P as ProfileBacktestSummary, Q as QualityCheck, c as WorkProductPersistedPart, h as WorkProductStatus } from '../types-
|
|
8
|
+
import { M as FileMention, g as ChatMentionPart, b as ChatAttachmentPart, a as ChatAttachmentKind, Q as ChatAttachmentInput } from '../parts-DIKcC1p6.js';
|
|
9
|
+
export { f as ChatMentionKind, P as ChatTurnFilePartInput, O as ChatTurnPartInput, N as ChatTurnRequestPayload, U as DISPATCH_MAX_MEDIA_PARTS, V as DISPATCH_MAX_PARTS, W as DISPATCH_REQUEST_MAX_BYTES, X as DISPATCH_STRUCTURAL_RESERVE_BYTES, $ as ProducerErrorEvent, a0 as ProducerNoticeEvent, a1 as ProducerPassthroughEvent, a2 as ProducerPassthroughEventType, a3 as ProducerReasoningEvent, a4 as ProducerTextEvent, a5 as ProducerToolCallEvent, a6 as ProducerToolResultEvent, a7 as ProducerUsageEvent, a8 as ProducerWireEvent, u as attachmentInputToPart, v as attachmentKindForMime, w as attachmentPartsFromMessageParts, ab as base64WireLen, ac as buildMentionPromptBlock, ad as chatTurnRequestInit, ae as fileMentionsToParts, z as isChatAttachmentPart, ag as mediaTypeForMentionPath, J as mentionInputToPart, ah as mentionKindForPath, K as mentionPartsFromMessageParts } from '../parts-DIKcC1p6.js';
|
|
10
|
+
import { E as EvidenceEntry, g as ExceptionEntry, a as WorkProductProvenance, P as ProfileBacktestSummary, Q as QualityCheck, c as WorkProductPersistedPart, h as WorkProductStatus } from '../types-DeEOhQbv.js';
|
|
11
11
|
import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
|
|
12
12
|
import { F as FlowTrace } from '../flow-types-CJxEmaRy.js';
|
|
13
|
-
import { a as ReviewQueueItem, c as ReviewQueueState } from '../queue-
|
|
14
|
-
export { p as parseReviewQueueItem } from '../queue-
|
|
13
|
+
import { a as ReviewQueueItem, c as ReviewQueueState } from '../queue-DBkulxW1.js';
|
|
14
|
+
export { p as parseReviewQueueItem } from '../queue-DBkulxW1.js';
|
|
15
15
|
export { S as SandboxTerminalConnection, a as SandboxTerminalConnectionResponse, U as UseSandboxTerminalConnectionOptions, b as UseSandboxTerminalConnectionResult, t as tabTerminalConnectionId, u as useSandboxTerminalConnection } from '../sandbox-terminal-ChNEdHF8.js';
|
|
16
16
|
import { CatalogModel } from '../catalog/index.js';
|
|
17
17
|
import { Harness } from '../harness/index.js';
|
|
18
|
-
export { a as ATTACHMENT_ACCEPT, e as FileIndexReadyResponse, f as FileIndexResponse, g as FileIndexWarmingResponse } from '../attachment-validation-
|
|
18
|
+
export { a as ATTACHMENT_ACCEPT, e as FileIndexReadyResponse, f as FileIndexResponse, g as FileIndexWarmingResponse } from '../attachment-validation-yJ6Id4pR.js';
|
|
19
19
|
export { a as attachmentPartKey } from '../stream-normalizer-DnuqkZvw.js';
|
|
20
20
|
|
|
21
21
|
/** Represent durable plan decisions as either approved or rejected */
|
package/dist/web-react/index.js
CHANGED
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
useSmoothText,
|
|
75
75
|
useThinkingSeconds,
|
|
76
76
|
waterfallLayout
|
|
77
|
-
} from "../chunk-
|
|
77
|
+
} from "../chunk-J6TNPRQN.js";
|
|
78
78
|
import "../chunk-FBVLEGEG.js";
|
|
79
79
|
import {
|
|
80
80
|
EvidenceLineageTable,
|
|
@@ -87,17 +87,17 @@ import {
|
|
|
87
87
|
reviewQueueStateLabel,
|
|
88
88
|
workProductPartsFromMessageParts,
|
|
89
89
|
workProductStatusLabel
|
|
90
|
-
} from "../chunk-
|
|
90
|
+
} from "../chunk-72TPRENZ.js";
|
|
91
91
|
import {
|
|
92
92
|
parseReviewQueueItem
|
|
93
|
-
} from "../chunk-
|
|
93
|
+
} from "../chunk-ZRSUCTST.js";
|
|
94
94
|
import {
|
|
95
95
|
tabTerminalConnectionId,
|
|
96
96
|
useSandboxTerminalConnection
|
|
97
97
|
} from "../chunk-HCOROIRT.js";
|
|
98
98
|
import {
|
|
99
99
|
ATTACHMENT_ACCEPT
|
|
100
|
-
} from "../chunk-
|
|
100
|
+
} from "../chunk-5GA3MKOC.js";
|
|
101
101
|
import {
|
|
102
102
|
DISPATCH_MAX_MEDIA_PARTS,
|
|
103
103
|
DISPATCH_MAX_PARTS,
|
|
@@ -115,8 +115,8 @@ import {
|
|
|
115
115
|
mentionInputToPart,
|
|
116
116
|
mentionKindForPath,
|
|
117
117
|
mentionPartsFromMessageParts
|
|
118
|
-
} from "../chunk-
|
|
119
|
-
import "../chunk-
|
|
118
|
+
} from "../chunk-FEUW4G2L.js";
|
|
119
|
+
import "../chunk-V3HO43PG.js";
|
|
120
120
|
import {
|
|
121
121
|
attachmentPartKey
|
|
122
122
|
} from "../chunk-5EPIPT4V.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as WorkProductProvenance, d as WorkProductStorePort, e as WorkProductAuditEvent, b as WorkProductRecord, f as WorkProductArtifact, Q as QualityCheck, E as EvidenceEntry, g as ExceptionEntry, h as WorkProductStatus, c as WorkProductPersistedPart } from '../types-
|
|
2
|
-
export { A as AgentCheckInput, i as EvidenceLocator, j as ExceptionSeverity, P as ProfileBacktestSummary,
|
|
1
|
+
import { a as WorkProductProvenance, d as WorkProductStorePort, e as WorkProductAuditEvent, b as WorkProductRecord, f as WorkProductArtifact, Q as QualityCheck, E as EvidenceEntry, g as ExceptionEntry, h as WorkProductStatus, c as WorkProductPersistedPart } from '../types-DeEOhQbv.js';
|
|
2
|
+
export { A as AgentCheckInput, i as EvidenceLocator, j as EvidenceSpan, k as ExceptionSeverity, P as ProfileBacktestSummary, l as QuoteBasis, m as WorkProductParseResult, n as WorkProductPatch, W as WorkProductRef, o as WorkProductUpdateGuard, p as WorkProductVersionEntry, q as isWorkProductStatus, r as parseAgentCheckInput, s as parseArtifactInput, t as parseEvidenceInput, u as parseExceptionInput, v as persistedPartToWorkProduct, w as unresolvedBlockingExceptions, x as workProductToPersistedPart } from '../types-DeEOhQbv.js';
|
|
3
3
|
import { a as AppToolContext, c as AppToolDefinition } from '../types-BCxK0wyS.js';
|
|
4
4
|
import { JudgeVerdict } from '@tangle-network/agent-eval';
|
|
5
5
|
import { T as TrustItem } from '../trust-gate-Dcm5xSva.js';
|
|
6
|
-
export { R as ReviewQueueInputs, a as ReviewQueueItem, b as ReviewQueuePendingAsk, c as ReviewQueueState, d as ReviewQueueThread, p as parseReviewQueueItem, e as projectReviewQueue } from '../queue-
|
|
6
|
+
export { R as ReviewQueueInputs, a as ReviewQueueItem, b as ReviewQueuePendingAsk, c as ReviewQueueState, d as ReviewQueueThread, p as parseReviewQueueItem, e as projectReviewQueue } from '../queue-DBkulxW1.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* The guarded work-product status machine — the `/missions` service PATTERN
|
|
@@ -242,8 +242,22 @@ interface WorkProductToolConfig {
|
|
|
242
242
|
* Omit the seam entirely and no quote is checked. */
|
|
243
243
|
readSourceText?: (ref: string, ctx: AppToolContext) => Promise<string | null>;
|
|
244
244
|
/** The material targets the platform coverage check requires evidence for.
|
|
245
|
-
* Product-owned vocabulary; omit to skip the coverage gate.
|
|
245
|
+
* Product-owned vocabulary; omit to skip the coverage gate.
|
|
246
|
+
*
|
|
247
|
+
* Return ONLY targets a source document can actually evidence. A gate that
|
|
248
|
+
* demands document lineage for a value the session COMPUTED is not
|
|
249
|
+
* satisfiable by any honest answer, and an unsatisfiable gate does not stop
|
|
250
|
+
* a submit — it selects for an invented one. Computed values belong to a
|
|
251
|
+
* product's own computation check, where "matches what we already
|
|
252
|
+
* calculated" is satisfiable by construction. */
|
|
246
253
|
materialTargets?: (artifact: WorkProductArtifact) => string[];
|
|
254
|
+
/** Require every material target to carry a SOURCE ANCHOR — a span-sliced or
|
|
255
|
+
* verified quote — not merely an evidence row. Off by default (a bare
|
|
256
|
+
* `claim` is legitimate lineage for products with no readable sources);
|
|
257
|
+
* turn it ON once `readSourceText` is wired and `materialTargets` names only
|
|
258
|
+
* document-derived targets, and coverage stops being satisfiable by
|
|
259
|
+
* assertion. */
|
|
260
|
+
requireAnchoredEvidence?: boolean;
|
|
247
261
|
/** Per-turn provenance closure the ROUTE supplies (profileHash + runId are
|
|
248
262
|
* known at dispatch; trusted, never read from model args). */
|
|
249
263
|
provenance: (ctx: AppToolContext) => WorkProductProvenanceBase;
|
|
@@ -292,6 +306,60 @@ declare function normalizeQuoteText(value: string): string;
|
|
|
292
306
|
* substring of every document and pass the gate vacuously.
|
|
293
307
|
*/
|
|
294
308
|
declare function sourceContainsQuote(sourceText: string, quote: string): boolean;
|
|
309
|
+
/**
|
|
310
|
+
* Slice a citation out of the source text by character offset — the reason
|
|
311
|
+
* this module exists in its stronger form.
|
|
312
|
+
*
|
|
313
|
+
* Verification above is a REJECTION gate: the model retypes a quote and the
|
|
314
|
+
* shell refuses it when the characters do not occur. That gate is correct and
|
|
315
|
+
* it works, but a model that reproduces a line character-for-character only
|
|
316
|
+
* some of the time cannot USE it — every miss is a refusal, and the package
|
|
317
|
+
* ends up with no lineage at all rather than false lineage. A measured 9 of 59
|
|
318
|
+
* on the live tax surface is what "some of the time" meant in practice.
|
|
319
|
+
*
|
|
320
|
+
* A span inverts it. The model names two integers into text it just read; the
|
|
321
|
+
* PLATFORM produces the quote from the bytes it already holds. There is no
|
|
322
|
+
* retyping step to get wrong, so a fabricated quote is not rejected — it is
|
|
323
|
+
* unrepresentable. `sourceContainsQuote(text, sliceSourceSpan(text, span))` is
|
|
324
|
+
* true for every span this function returns, by construction.
|
|
325
|
+
*
|
|
326
|
+
* Offsets index the SAME string the product's document-reading tool pages
|
|
327
|
+
* with an offset, which is the same string its `readSourceText` seam returns.
|
|
328
|
+
* That is the one contract a product must keep; violate it and spans point at
|
|
329
|
+
* the wrong characters (still real characters of that document — never
|
|
330
|
+
* invented text, but the wrong line).
|
|
331
|
+
*
|
|
332
|
+
* Half-open `[start, end)`, matching `String.prototype.slice` and the
|
|
333
|
+
* `offset`/`offset + text.length` window a paged read already reports.
|
|
334
|
+
*/
|
|
335
|
+
type SourceSpanFailure = {
|
|
336
|
+
reason: 'not_integer';
|
|
337
|
+
field: 'start' | 'end';
|
|
338
|
+
} | {
|
|
339
|
+
reason: 'negative';
|
|
340
|
+
field: 'start' | 'end';
|
|
341
|
+
} | {
|
|
342
|
+
reason: 'inverted';
|
|
343
|
+
} | {
|
|
344
|
+
reason: 'out_of_range';
|
|
345
|
+
totalChars: number;
|
|
346
|
+
} | {
|
|
347
|
+
reason: 'blank';
|
|
348
|
+
};
|
|
349
|
+
type SourceSpanResult = {
|
|
350
|
+
ok: true;
|
|
351
|
+
quote: string;
|
|
352
|
+
} | {
|
|
353
|
+
ok: false;
|
|
354
|
+
failure: SourceSpanFailure;
|
|
355
|
+
};
|
|
356
|
+
/** Resolve `[start, end)` against `sourceText`. Every rejection is a caller
|
|
357
|
+
* mistake the model can correct from the paged read it already has, so each
|
|
358
|
+
* carries the discriminator a tool layer turns into a specific message. */
|
|
359
|
+
declare function sliceSourceSpan(sourceText: string, span: {
|
|
360
|
+
start: number;
|
|
361
|
+
end: number;
|
|
362
|
+
}): SourceSpanResult;
|
|
295
363
|
|
|
296
364
|
/**
|
|
297
365
|
* Framework-neutral work-product review endpoints — the
|
|
@@ -382,4 +450,4 @@ interface WorkProductRoutes {
|
|
|
382
450
|
/** Create the work-product review endpoints over the store port and product seams */
|
|
383
451
|
declare function createWorkProductRoutes(options: WorkProductRoutesOptions): WorkProductRoutes;
|
|
384
452
|
|
|
385
|
-
export { type CreateWorkProductInput, EVIDENCE_COVERAGE_CHECK, EvidenceEntry, ExceptionEntry, type FinalizeWorkProductProvenanceInput, type InMemoryWorkProductStore, MAX_WORK_PRODUCT_BATCH, QUOTE_VERIFICATION_CHECK, QualityCheck, type SubmitWorkProductInput, TrustItem, WorkProductArtifact, WorkProductAuditEvent, type WorkProductAuthorizeArgs, type WorkProductOutcome, WorkProductPersistedPart, WorkProductProvenance, type WorkProductProvenanceBase, WorkProductRecord, type WorkProductRouteAuthorization, type WorkProductRoutes, type WorkProductRoutesOptions, type WorkProductService, type WorkProductServiceOptions, WorkProductStatus, WorkProductStorePort, type WorkProductToolConfig, type WorkProductVerdictBody, type WorkProductVerdictInput, buildWorkProductTools, canTransitionWorkProduct, createInMemoryWorkProductStore, createWorkProductRoutes, createWorkProductService, finalizeWorkProductProvenance, isWorkProductTerminal, normalizeQuoteText, sourceContainsQuote, stampProvenance, validateWorkProductVerdictBody, workProductTrustInputs };
|
|
453
|
+
export { type CreateWorkProductInput, EVIDENCE_COVERAGE_CHECK, EvidenceEntry, ExceptionEntry, type FinalizeWorkProductProvenanceInput, type InMemoryWorkProductStore, MAX_WORK_PRODUCT_BATCH, QUOTE_VERIFICATION_CHECK, QualityCheck, type SourceSpanFailure, type SourceSpanResult, type SubmitWorkProductInput, TrustItem, WorkProductArtifact, WorkProductAuditEvent, type WorkProductAuthorizeArgs, type WorkProductOutcome, WorkProductPersistedPart, WorkProductProvenance, type WorkProductProvenanceBase, WorkProductRecord, type WorkProductRouteAuthorization, type WorkProductRoutes, type WorkProductRoutesOptions, type WorkProductService, type WorkProductServiceOptions, WorkProductStatus, WorkProductStorePort, type WorkProductToolConfig, type WorkProductVerdictBody, type WorkProductVerdictInput, buildWorkProductTools, canTransitionWorkProduct, createInMemoryWorkProductStore, createWorkProductRoutes, createWorkProductService, finalizeWorkProductProvenance, isWorkProductTerminal, normalizeQuoteText, sliceSourceSpan, sourceContainsQuote, stampProvenance, validateWorkProductVerdictBody, workProductTrustInputs };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseReviewQueueItem,
|
|
3
3
|
projectReviewQueue
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ZRSUCTST.js";
|
|
5
5
|
import {
|
|
6
6
|
isWorkProductStatus,
|
|
7
7
|
parseAgentCheckInput,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
persistedPartToWorkProduct,
|
|
12
12
|
unresolvedBlockingExceptions,
|
|
13
13
|
workProductToPersistedPart
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-V3HO43PG.js";
|
|
15
15
|
import {
|
|
16
16
|
ToolInputError,
|
|
17
17
|
defineAppTool
|
|
@@ -403,6 +403,20 @@ function sourceContainsQuote(sourceText, quote) {
|
|
|
403
403
|
if (normalizedQuote.length === 0) return false;
|
|
404
404
|
return normalizeQuoteText(sourceText).includes(normalizedQuote);
|
|
405
405
|
}
|
|
406
|
+
function sliceSourceSpan(sourceText, span) {
|
|
407
|
+
for (const field of ["start", "end"]) {
|
|
408
|
+
const value = span[field];
|
|
409
|
+
if (!Number.isInteger(value)) return { ok: false, failure: { reason: "not_integer", field } };
|
|
410
|
+
if (value < 0) return { ok: false, failure: { reason: "negative", field } };
|
|
411
|
+
}
|
|
412
|
+
if (span.end <= span.start) return { ok: false, failure: { reason: "inverted" } };
|
|
413
|
+
if (span.end > sourceText.length) {
|
|
414
|
+
return { ok: false, failure: { reason: "out_of_range", totalChars: sourceText.length } };
|
|
415
|
+
}
|
|
416
|
+
const quote = sourceText.slice(span.start, span.end);
|
|
417
|
+
if (quote.trim().length === 0) return { ok: false, failure: { reason: "blank" } };
|
|
418
|
+
return { ok: true, quote };
|
|
419
|
+
}
|
|
406
420
|
|
|
407
421
|
// src/work-product/tools.ts
|
|
408
422
|
var MAX_WORK_PRODUCT_BATCH = 50;
|
|
@@ -452,17 +466,61 @@ async function resolveDraft(service, config, scopeKey, ctx) {
|
|
|
452
466
|
provenance: stampProvenance(config.provenance(ctx), config.now)
|
|
453
467
|
});
|
|
454
468
|
}
|
|
455
|
-
|
|
469
|
+
function spanErrorDetail(failure) {
|
|
470
|
+
switch (failure.reason) {
|
|
471
|
+
case "not_integer":
|
|
472
|
+
return `${failure.field} must be a whole character offset.`;
|
|
473
|
+
case "negative":
|
|
474
|
+
return `${failure.field} must not be negative.`;
|
|
475
|
+
case "inverted":
|
|
476
|
+
return "end must be greater than start \u2014 the range is half-open [start, end).";
|
|
477
|
+
case "out_of_range":
|
|
478
|
+
return `end is past the end of the document, which is ${failure.totalChars} characters. Offsets are absolute in the whole document: when you read with an offset, add that offset to the position within the returned text.`;
|
|
479
|
+
case "blank":
|
|
480
|
+
return "that range is only whitespace. Widen it to the characters that carry the value.";
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
async function resolveEvidenceQuotes(config, entries, ctx) {
|
|
456
484
|
const readSourceText = config.readSourceText;
|
|
457
|
-
if (!readSourceText) return;
|
|
458
485
|
const texts = /* @__PURE__ */ new Map();
|
|
486
|
+
const readText = async (ref) => {
|
|
487
|
+
if (!texts.has(ref)) texts.set(ref, await readSourceText(ref, ctx));
|
|
488
|
+
return texts.get(ref) ?? null;
|
|
489
|
+
};
|
|
459
490
|
for (let index = 0; index < entries.length; index += 1) {
|
|
460
491
|
const entry = entries[index];
|
|
492
|
+
const span = entry.locator.span;
|
|
461
493
|
const quote = entry.locator.quote;
|
|
494
|
+
if (span) {
|
|
495
|
+
if (!readSourceText) {
|
|
496
|
+
throw new ToolInputError(
|
|
497
|
+
"span_unsupported",
|
|
498
|
+
`entries[${index}].locator.span: this deployment cannot read source text, so a span cannot be resolved into a quote. Record the entry without locator.span.`,
|
|
499
|
+
500
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
const text2 = await readText(entry.sourceRef);
|
|
503
|
+
if (text2 === null) {
|
|
504
|
+
throw new ToolInputError(
|
|
505
|
+
"unverifiable_quote",
|
|
506
|
+
`entries[${index}].locator.span: "${entry.sourceRef}" has no readable text, so the span cannot be resolved. Record the entry without locator.span or locator.quote and state the basis in claim.`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
const sliced = sliceSourceSpan(text2, span);
|
|
510
|
+
if (!sliced.ok) {
|
|
511
|
+
throw new ToolInputError(
|
|
512
|
+
"invalid_span",
|
|
513
|
+
`entries[${index}].locator.span [${span.start}, ${span.end}) into "${entry.sourceRef}": ${spanErrorDetail(sliced.failure)}`
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
entry.locator.quote = sliced.quote;
|
|
517
|
+
entry.locator.quoteBasis = "span";
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
462
520
|
if (quote === void 0 || quote.trim().length === 0) continue;
|
|
463
|
-
if (!
|
|
464
|
-
const text =
|
|
465
|
-
if (text === null
|
|
521
|
+
if (!readSourceText) continue;
|
|
522
|
+
const text = await readText(entry.sourceRef);
|
|
523
|
+
if (text === null) {
|
|
466
524
|
throw new ToolInputError(
|
|
467
525
|
"unverifiable_quote",
|
|
468
526
|
`entries[${index}].locator.quote: "${entry.sourceRef}" has no readable text, so the quote cannot be verified. Record the entry without locator.quote and state the basis in claim.`
|
|
@@ -471,9 +529,10 @@ async function assertQuotesOccurInSources(config, entries, ctx) {
|
|
|
471
529
|
if (!sourceContainsQuote(text, quote)) {
|
|
472
530
|
throw new ToolInputError(
|
|
473
531
|
"quote_not_found",
|
|
474
|
-
`entries[${index}].locator.quote: ${JSON.stringify(quote)} does not occur in "${entry.sourceRef}".
|
|
532
|
+
`entries[${index}].locator.quote: ${JSON.stringify(quote)} does not occur in "${entry.sourceRef}". Cite locator.span {start, end} instead \u2014 the character range you read it at, which this platform slices out of the document itself so the text is right by construction. If the value is COMPUTED rather than read, omit both and state the computation in claim.`
|
|
475
533
|
);
|
|
476
534
|
}
|
|
535
|
+
entry.locator.quoteBasis = "model";
|
|
477
536
|
}
|
|
478
537
|
}
|
|
479
538
|
async function summarizeQuoteVerification(config, evidence, ctx) {
|
|
@@ -481,6 +540,7 @@ async function summarizeQuoteVerification(config, evidence, ctx) {
|
|
|
481
540
|
if (!readSourceText) return void 0;
|
|
482
541
|
const texts = /* @__PURE__ */ new Map();
|
|
483
542
|
let verified = 0;
|
|
543
|
+
let spanAnchored = 0;
|
|
484
544
|
let withoutQuote = 0;
|
|
485
545
|
const failed = [];
|
|
486
546
|
for (const entry of evidence) {
|
|
@@ -491,10 +551,23 @@ async function summarizeQuoteVerification(config, evidence, ctx) {
|
|
|
491
551
|
}
|
|
492
552
|
if (!texts.has(entry.sourceRef)) texts.set(entry.sourceRef, await readSourceText(entry.sourceRef, ctx));
|
|
493
553
|
const text = texts.get(entry.sourceRef);
|
|
494
|
-
if (typeof text
|
|
554
|
+
if (typeof text !== "string") {
|
|
555
|
+
failed.push(entry.id);
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
const span = entry.locator.span;
|
|
559
|
+
if (span) {
|
|
560
|
+
const sliced = sliceSourceSpan(text, span);
|
|
561
|
+
if (sliced.ok && sliced.quote === quote) {
|
|
562
|
+
verified += 1;
|
|
563
|
+
spanAnchored += 1;
|
|
564
|
+
} else failed.push(entry.id);
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
if (sourceContainsQuote(text, quote)) verified += 1;
|
|
495
568
|
else failed.push(entry.id);
|
|
496
569
|
}
|
|
497
|
-
return { verified, withoutQuote, failed };
|
|
570
|
+
return { verified, spanAnchored, withoutQuote, failed };
|
|
498
571
|
}
|
|
499
572
|
function buildWorkProductTools(config) {
|
|
500
573
|
const service = createWorkProductService({
|
|
@@ -504,7 +577,7 @@ function buildWorkProductTools(config) {
|
|
|
504
577
|
});
|
|
505
578
|
const upsertEvidence = defineAppTool({
|
|
506
579
|
name: "upsert_evidence",
|
|
507
|
-
description: "Record source\u2192field lineage for the current work product, incrementally as you find it. Each entry links a source document (sourceRef + locator) to one artifact target and states the claim it supports. Re-emitting an entry id replaces that entry. Address the work product by scopeKey; the first call creates the draft.",
|
|
580
|
+
description: "Record source\u2192field lineage for the current work product, incrementally as you find it. Each entry links a source document (sourceRef + locator) to one artifact target and states the claim it supports. Cite by locator.span {start, end} \u2014 the character range you read the value at \u2014 and the platform slices the supporting quote out of the document for you. Re-emitting an entry id replaces that entry. Address the work product by scopeKey; the first call creates the draft.",
|
|
508
581
|
parameters: {
|
|
509
582
|
type: "object",
|
|
510
583
|
properties: {
|
|
@@ -523,9 +596,18 @@ function buildWorkProductTools(config) {
|
|
|
523
596
|
properties: {
|
|
524
597
|
page: { type: "number" },
|
|
525
598
|
range: { type: "string", description: "Free-form location: 'L120-L134' | 'B7' | '\xB64'." },
|
|
599
|
+
span: {
|
|
600
|
+
type: "object",
|
|
601
|
+
description: "PREFERRED. The character range you read the value at, as absolute offsets into the whole document: start is the first character, end is one past the last. If you read with an offset, add that offset to the position within the text you got back. The platform slices the quote out of the document itself and stores it, and returns it to you \u2014 you never retype source text, so the citation cannot be wrong. Use this whenever the value was READ from a document.",
|
|
602
|
+
properties: {
|
|
603
|
+
start: { type: "integer", minimum: 0 },
|
|
604
|
+
end: { type: "integer", minimum: 1 }
|
|
605
|
+
},
|
|
606
|
+
required: ["start", "end"]
|
|
607
|
+
},
|
|
526
608
|
quote: {
|
|
527
609
|
type: "string",
|
|
528
|
-
description: "
|
|
610
|
+
description: "Fallback for sources that cannot give you character offsets: the supporting text copied character-for-character. The platform checks it occurs in the document and REFUSES the entry if it does not. Prefer span. For a value you COMPUTED rather than read, omit both and state the computation in claim."
|
|
529
611
|
}
|
|
530
612
|
}
|
|
531
613
|
},
|
|
@@ -557,10 +639,24 @@ function buildWorkProductTools(config) {
|
|
|
557
639
|
);
|
|
558
640
|
}
|
|
559
641
|
}
|
|
560
|
-
await
|
|
642
|
+
await resolveEvidenceQuotes(config, entries, ctx);
|
|
561
643
|
const draft = await resolveDraft(service, config, scopeKey, ctx);
|
|
562
644
|
const record = await unwrap(() => service.upsertEvidence(draft.id, entries), "evidence_rejected");
|
|
563
|
-
return {
|
|
645
|
+
return {
|
|
646
|
+
workProductId: record.id,
|
|
647
|
+
version: record.version,
|
|
648
|
+
evidenceCount: record.evidence.length,
|
|
649
|
+
// Echo what was actually STORED for the entries in this call. A span
|
|
650
|
+
// citation's quote is produced here, not sent here, so the model must
|
|
651
|
+
// be able to see the text its offsets selected — that is how it
|
|
652
|
+
// notices an off-by-a-line span without a second read.
|
|
653
|
+
entries: entries.map((entry) => ({
|
|
654
|
+
id: entry.id,
|
|
655
|
+
target: entry.target,
|
|
656
|
+
...entry.locator.quote === void 0 ? {} : { quote: entry.locator.quote },
|
|
657
|
+
...entry.locator.quoteBasis === void 0 ? {} : { quoteBasis: entry.locator.quoteBasis }
|
|
658
|
+
}))
|
|
659
|
+
};
|
|
564
660
|
}
|
|
565
661
|
});
|
|
566
662
|
const flagException = defineAppTool({
|
|
@@ -692,7 +788,7 @@ function buildWorkProductTools(config) {
|
|
|
692
788
|
id: QUOTE_VERIFICATION_CHECK,
|
|
693
789
|
name: QUOTE_VERIFICATION_CHECK,
|
|
694
790
|
passed: quotes.failed.length === 0,
|
|
695
|
-
detail: quotes.failed.length === 0 ? `${quotes.verified}/${quoted} quoted evidence entries verified against their source; ${quotes.withoutQuote} recorded without a quote` : `Unverifiable quotes on: ${quotes.failed.join(", ")}`,
|
|
791
|
+
detail: quotes.failed.length === 0 ? `${quotes.verified}/${quoted} quoted evidence entries verified against their source (${quotes.spanAnchored} platform-sliced from a source span, ${quotes.verified - quotes.spanAnchored} model-quoted and proved to occur); ${quotes.withoutQuote} recorded without a quote` : `Unverifiable quotes on: ${quotes.failed.join(", ")}`,
|
|
696
792
|
source: "platform"
|
|
697
793
|
});
|
|
698
794
|
if (quotes.failed.length > 0) {
|
|
@@ -707,11 +803,21 @@ function buildWorkProductTools(config) {
|
|
|
707
803
|
const targets = config.materialTargets(artifact);
|
|
708
804
|
const covered = new Set(draft.evidence.map((entry) => entry.target));
|
|
709
805
|
const missing = targets.filter((target) => !covered.has(target));
|
|
806
|
+
const anchoredTargets = new Set(
|
|
807
|
+
draft.evidence.filter((entry) => entry.locator.quoteBasis !== void 0).map((entry) => entry.target)
|
|
808
|
+
);
|
|
809
|
+
const spanTargets = new Set(
|
|
810
|
+
draft.evidence.filter((entry) => entry.locator.quoteBasis === "span").map((entry) => entry.target)
|
|
811
|
+
);
|
|
812
|
+
const present = targets.filter((target) => covered.has(target));
|
|
813
|
+
const unanchored = present.filter((target) => !anchoredTargets.has(target));
|
|
814
|
+
const spanCount = present.filter((target) => spanTargets.has(target)).length;
|
|
815
|
+
const breakdown = `${spanCount} span-anchored, ${present.length - spanCount - unanchored.length} quote-verified, ${unanchored.length} claim-only`;
|
|
710
816
|
const coverage = {
|
|
711
817
|
id: EVIDENCE_COVERAGE_CHECK,
|
|
712
818
|
name: EVIDENCE_COVERAGE_CHECK,
|
|
713
|
-
passed: missing.length === 0,
|
|
714
|
-
detail: missing.length
|
|
819
|
+
passed: missing.length === 0 && !(config.requireAnchoredEvidence && unanchored.length > 0),
|
|
820
|
+
detail: missing.length > 0 ? `Missing evidence for: ${missing.join(", ")}` : config.requireAnchoredEvidence && unanchored.length > 0 ? `No source anchor for: ${unanchored.join(", ")}` : `${targets.length}/${targets.length} material targets evidenced (${breakdown})`,
|
|
715
821
|
source: "platform"
|
|
716
822
|
};
|
|
717
823
|
checks.unshift(coverage);
|
|
@@ -722,6 +828,13 @@ function buildWorkProductTools(config) {
|
|
|
722
828
|
`Cannot submit: material targets lack evidence: ${missing.join(", ")}. Add upsert_evidence entries targeting each, then resubmit.`
|
|
723
829
|
);
|
|
724
830
|
}
|
|
831
|
+
if (config.requireAnchoredEvidence && unanchored.length > 0) {
|
|
832
|
+
await unwrap(() => service.recordChecks(draft.id, checks), "checks_rejected");
|
|
833
|
+
throw new ToolInputError(
|
|
834
|
+
"evidence_not_anchored",
|
|
835
|
+
`Cannot submit: these material targets have an evidence row but no source anchor: ${unanchored.join(", ")}. Re-emit each with locator.span {start, end} \u2014 the character range in the document you read the value at. The platform slices the quote out of the document itself, so you never retype source text.`
|
|
836
|
+
);
|
|
837
|
+
}
|
|
725
838
|
}
|
|
726
839
|
const provenance = stampProvenance(config.provenance(ctx), config.now);
|
|
727
840
|
const record = await unwrap(
|
|
@@ -851,6 +964,7 @@ export {
|
|
|
851
964
|
parseReviewQueueItem,
|
|
852
965
|
persistedPartToWorkProduct,
|
|
853
966
|
projectReviewQueue,
|
|
967
|
+
sliceSourceSpan,
|
|
854
968
|
sourceContainsQuote,
|
|
855
969
|
stampProvenance,
|
|
856
970
|
unresolvedBlockingExceptions,
|