@ai-matrx/agents 0.18.1 → 0.18.5
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/CHANGELOG.md +47 -0
- package/dist/content-transfer/index.cjs.map +1 -1
- package/dist/content-transfer/index.js.map +1 -1
- package/dist/content-transfer/react/index.cjs.map +1 -1
- package/dist/content-transfer/react/index.js.map +1 -1
- package/dist/mandates/index.cjs +2 -2
- package/dist/mandates/index.cjs.map +1 -1
- package/dist/mandates/index.d.cts +4 -4
- package/dist/mandates/index.d.ts +4 -4
- package/dist/mandates/index.js +2 -2
- package/dist/mandates/index.js.map +1 -1
- package/dist/sources/react/index.cjs +116 -14
- package/dist/sources/react/index.cjs.map +1 -1
- package/dist/sources/react/index.d.cts +35 -2
- package/dist/sources/react/index.d.ts +35 -2
- package/dist/sources/react/index.js +116 -14
- package/dist/sources/react/index.js.map +1 -1
- package/dist/sources/runtime/index.cjs +322 -197
- package/dist/sources/runtime/index.cjs.map +1 -1
- package/dist/sources/runtime/index.d.cts +88 -6
- package/dist/sources/runtime/index.d.ts +88 -6
- package/dist/sources/runtime/index.js +322 -197
- package/dist/sources/runtime/index.js.map +1 -1
- package/mandates/snapshots/keys.0.18.3.json +652 -0
- package/mandates/snapshots/keys.0.18.4.json +652 -0
- package/mandates/snapshots/keys.0.18.5.json +652 -0
- package/package.json +3 -3
|
@@ -8,12 +8,12 @@ function deliveryPatch(delivery) {
|
|
|
8
8
|
var DELIVERY_WORDS = {
|
|
9
9
|
direct: {
|
|
10
10
|
label: "Include the text",
|
|
11
|
-
hint: "
|
|
11
|
+
hint: "Sent in full",
|
|
12
12
|
summary: "Text included"
|
|
13
13
|
},
|
|
14
14
|
context: {
|
|
15
15
|
label: "Let the AI look it up",
|
|
16
|
-
hint: "
|
|
16
|
+
hint: "Read as needed",
|
|
17
17
|
summary: "Looked up when needed"
|
|
18
18
|
}
|
|
19
19
|
};
|
|
@@ -90,7 +90,7 @@ function resumableInput(draft) {
|
|
|
90
90
|
case "youtube":
|
|
91
91
|
return input.url?.trim() ? input : null;
|
|
92
92
|
case "audio":
|
|
93
|
-
return input.fileId ? input : null;
|
|
93
|
+
return input.fileId || input.text?.trim() ? input : null;
|
|
94
94
|
default:
|
|
95
95
|
return null;
|
|
96
96
|
}
|
|
@@ -106,12 +106,12 @@ function reloadedCard(draft, status) {
|
|
|
106
106
|
return { action: "lost", sentence: RELOADED_WHILE_ADDING };
|
|
107
107
|
}
|
|
108
108
|
var MAX_KEPT_TEXT_KNOB = { feature: "sources", key: "max_kept_draft_chars" };
|
|
109
|
-
var NOT_KEPT_FOR_RELOAD = "Too large to
|
|
109
|
+
var NOT_KEPT_FOR_RELOAD = "Too large to restore if the page reloads before it is added.";
|
|
110
110
|
var WAITING_FOR_ORGANIZATION = "Waiting for an organization \u2014 choose one and this continues by itself.";
|
|
111
111
|
var KEEP_WAITING_FOR_ORGANIZATION = "Read. Waiting for an organization to keep it \u2014 choose one and it is kept by itself.";
|
|
112
112
|
|
|
113
113
|
// sources/runtime/fileSource.ts
|
|
114
|
-
var UNREADABLE = "
|
|
114
|
+
var UNREADABLE = "Can't read this file \u2014 add a PDF, Word or text copy.";
|
|
115
115
|
function nextFileStep(status, ctx) {
|
|
116
116
|
const pdId = status?.processed_document_id ?? null;
|
|
117
117
|
if (pdId) return { do: "keep", processedDocumentId: pdId };
|
|
@@ -119,7 +119,7 @@ function nextFileStep(status, ctx) {
|
|
|
119
119
|
if (status?.state === "failed")
|
|
120
120
|
return {
|
|
121
121
|
do: "unreadable",
|
|
122
|
-
reason: status.error?.message ? `
|
|
122
|
+
reason: status.error?.message ? `Can't read this file: ${status.error.message}. Add it again.` : UNREADABLE
|
|
123
123
|
};
|
|
124
124
|
if (!ctx.started) return { do: "start" };
|
|
125
125
|
return { do: "unreadable", reason: UNREADABLE };
|
|
@@ -235,191 +235,10 @@ function totalChars(value) {
|
|
|
235
235
|
return value.sources.filter((entry) => entry.state === "ready" || entry.state === "processing").reduce((sum, entry) => sum + manifestEntryChars(entry), 0);
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
// sources/runtime/plan.ts
|
|
239
|
-
var HEAVY_SHARE = 0.7;
|
|
240
|
-
var PAGE_SUFFIX = (page) => page !== void 0 && page > 0 ? ` (page ${page})` : "";
|
|
241
|
-
function renderedPartChars(segment, chars) {
|
|
242
|
-
return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;
|
|
243
|
-
}
|
|
244
|
-
function capParts(parts, maxChars) {
|
|
245
|
-
if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };
|
|
246
|
-
const kept = [];
|
|
247
|
-
let used = 0;
|
|
248
|
-
for (const seg of parts) {
|
|
249
|
-
if (used + seg.chars <= maxChars) {
|
|
250
|
-
kept.push({ seg, chars: seg.chars });
|
|
251
|
-
used += seg.chars;
|
|
252
|
-
continue;
|
|
253
|
-
}
|
|
254
|
-
const room = maxChars - used;
|
|
255
|
-
if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });
|
|
256
|
-
return { kept, capped: true };
|
|
257
|
-
}
|
|
258
|
-
return { kept, capped: false };
|
|
259
|
-
}
|
|
260
|
-
function chosenForm(entry, ref) {
|
|
261
|
-
const key = ref.representation ?? entry.default_form;
|
|
262
|
-
return entry.forms.find((f) => f.form === key) ?? entry.forms.find((f) => f.form === entry.default_form) ?? null;
|
|
263
|
-
}
|
|
264
|
-
function isUsable(entry) {
|
|
265
|
-
return entry.state === "ready" || entry.state === "processing";
|
|
266
|
-
}
|
|
267
|
-
function measure(entry, ref) {
|
|
268
|
-
const form = chosenForm(entry, ref);
|
|
269
|
-
const formChars = form?.chars ?? 0;
|
|
270
|
-
const formLabel = form?.label ?? "Text";
|
|
271
|
-
const segments = entry.segments ?? null;
|
|
272
|
-
if (segments && segments.length > 0) {
|
|
273
|
-
const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;
|
|
274
|
-
const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;
|
|
275
|
-
const { kept, capped: capped2 } = capParts(chosen, ref.max_chars);
|
|
276
|
-
const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);
|
|
277
|
-
const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;
|
|
278
|
-
return {
|
|
279
|
-
formChars,
|
|
280
|
-
formLabel,
|
|
281
|
-
sentChars,
|
|
282
|
-
exact: true,
|
|
283
|
-
partsSent: kept.length,
|
|
284
|
-
partsTotal: segments.length,
|
|
285
|
-
capped: capped2
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
const capped = ref.max_chars !== void 0 && formChars > ref.max_chars;
|
|
289
|
-
return {
|
|
290
|
-
formChars,
|
|
291
|
-
formLabel,
|
|
292
|
-
sentChars: capped ? ref.max_chars ?? formChars : formChars,
|
|
293
|
-
exact: false,
|
|
294
|
-
partsSent: null,
|
|
295
|
-
partsTotal: null,
|
|
296
|
-
capped
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
function planSourceReview(input) {
|
|
300
|
-
const estimateTokens = input.estimateTokens ?? estimateSourceTokens;
|
|
301
|
-
const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;
|
|
302
|
-
const windowTokens = windowIsFallback ? input.fallbackWindowTokens : input.modelWindowTokens;
|
|
303
|
-
let sentChars = 0;
|
|
304
|
-
const entries = input.manifest.sources.map((entry, index) => {
|
|
305
|
-
const ref = input.refs[index] ?? entry.ref;
|
|
306
|
-
const m = measure(entry, ref);
|
|
307
|
-
const base = { index, ref, entry, ...m };
|
|
308
|
-
if (!isUsable(entry)) {
|
|
309
|
-
return { ...base, status: "unusable", sentChars: 0, sentTokens: 0 };
|
|
310
|
-
}
|
|
311
|
-
if (sourceDelivery(ref) === "context") {
|
|
312
|
-
return { ...base, status: "on_demand", sentChars: 0, sentTokens: 0 };
|
|
313
|
-
}
|
|
314
|
-
if (estimateTokens(sentChars + m.sentChars) > windowTokens) {
|
|
315
|
-
return { ...base, status: "left_out", sentTokens: estimateTokens(m.sentChars) };
|
|
316
|
-
}
|
|
317
|
-
sentChars += m.sentChars;
|
|
318
|
-
return { ...base, status: "included", sentTokens: estimateTokens(m.sentChars) };
|
|
319
|
-
});
|
|
320
|
-
const sentTokens = estimateTokens(sentChars);
|
|
321
|
-
const leftOut = entries.filter((e) => e.status === "left_out");
|
|
322
|
-
const share = windowTokens > 0 ? sentTokens / windowTokens : 0;
|
|
323
|
-
const anythingGoesIn = entries.some((e) => e.status === "included" || e.status === "on_demand");
|
|
324
|
-
const verdict = !anythingGoesIn && leftOut.length === 0 ? "empty" : leftOut.length > 0 ? "too_much" : share >= HEAVY_SHARE ? "heavy" : "fine";
|
|
325
|
-
const kept = entries.filter((e) => e.status !== "left_out").map(
|
|
326
|
-
(e) => createSourceRef(e.ref.resource_type, e.ref.resource_id, {
|
|
327
|
-
representation: e.ref.representation,
|
|
328
|
-
include_segments: e.ref.include_segments,
|
|
329
|
-
delivery: e.ref.delivery,
|
|
330
|
-
max_chars: e.ref.max_chars,
|
|
331
|
-
promote: e.ref.promote,
|
|
332
|
-
exclude: e.ref.exclude
|
|
333
|
-
})
|
|
334
|
-
);
|
|
335
|
-
const grounding = input.base.grounding === "selected" && !kept.some((r) => r.include_segments?.length) ? void 0 : input.base.grounding;
|
|
336
|
-
const sourceSet = createSourceSet(kept, {
|
|
337
|
-
topic: input.base.topic,
|
|
338
|
-
grounding,
|
|
339
|
-
retrieve_query: input.base.retrieve_query,
|
|
340
|
-
target_model_id: input.targetModelId ?? input.base.target_model_id
|
|
341
|
-
});
|
|
342
|
-
return {
|
|
343
|
-
entries,
|
|
344
|
-
sentChars,
|
|
345
|
-
sentTokens,
|
|
346
|
-
windowTokens,
|
|
347
|
-
windowIsFallback,
|
|
348
|
-
verdict,
|
|
349
|
-
share,
|
|
350
|
-
leftOut,
|
|
351
|
-
sourceSet
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// sources/runtime/client.ts
|
|
356
|
-
function marked(options) {
|
|
357
|
-
return {
|
|
358
|
-
bodyCarriedRead: true,
|
|
359
|
-
...options?.organizationId ? { organizationId: options.organizationId } : {},
|
|
360
|
-
...options?.signal ? { signal: options.signal } : {}
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
function createSourcesClient(transport) {
|
|
364
|
-
return {
|
|
365
|
-
manifest: (sourceSet, options) => transport.post("/sources/manifest", { source_set: sourceSet }, marked(options)),
|
|
366
|
-
resolve: (sourceSet, options) => transport.post("/sources/resolve", { source_set: sourceSet }, marked(options)),
|
|
367
|
-
searchParts: (ref, query, options) => transport.post("/sources/parts/search", { source_ref: ref, query }, marked(options))
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
var SourceDoorError = class extends Error {
|
|
371
|
-
status;
|
|
372
|
-
body;
|
|
373
|
-
constructor(status, message, body) {
|
|
374
|
-
super(message);
|
|
375
|
-
this.name = "SourceDoorError";
|
|
376
|
-
this.status = status;
|
|
377
|
-
this.body = body;
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
function refusalMessage(status, body) {
|
|
381
|
-
if (body && typeof body === "object") {
|
|
382
|
-
const record = body;
|
|
383
|
-
const error = record.error;
|
|
384
|
-
if (error && typeof error === "object") {
|
|
385
|
-
const message = error.user_message ?? error.message;
|
|
386
|
-
if (typeof message === "string" && message) return message;
|
|
387
|
-
}
|
|
388
|
-
if (typeof record.detail === "string" && record.detail) return record.detail;
|
|
389
|
-
}
|
|
390
|
-
return `The server answered ${status}.`;
|
|
391
|
-
}
|
|
392
|
-
function createFetchSourcesTransport(options) {
|
|
393
|
-
const base = options.baseUrl.replace(/\/+$/, "");
|
|
394
|
-
return {
|
|
395
|
-
async post(path, body, call) {
|
|
396
|
-
const doFetch = options.fetch ?? fetch;
|
|
397
|
-
const headers = {
|
|
398
|
-
"Content-Type": "application/json",
|
|
399
|
-
...options.headers ? await options.headers() : {}
|
|
400
|
-
};
|
|
401
|
-
if (call.organizationId) headers[options.organizationHeader ?? "X-Organization-Id"] = call.organizationId;
|
|
402
|
-
const response = await doFetch(`${base}${path}`, {
|
|
403
|
-
method: "POST",
|
|
404
|
-
headers,
|
|
405
|
-
body: JSON.stringify(body),
|
|
406
|
-
...call.signal ? { signal: call.signal } : {}
|
|
407
|
-
});
|
|
408
|
-
const text = await response.text();
|
|
409
|
-
let parsed = null;
|
|
410
|
-
try {
|
|
411
|
-
parsed = text ? JSON.parse(text) : null;
|
|
412
|
-
} catch {
|
|
413
|
-
parsed = text;
|
|
414
|
-
}
|
|
415
|
-
if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);
|
|
416
|
-
return parsed;
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
|
|
421
238
|
// sources/runtime/state.ts
|
|
422
239
|
var EMPTY_SOURCE_SET_STATE = Object.freeze({ cards: Object.freeze([]), topic: "" });
|
|
240
|
+
var PARTS_MATCHED_BY_PAGE = "The clean version is ready \u2014 your parts were matched to it by page.";
|
|
241
|
+
var PARTS_NOT_MATCHED = "The clean version is ready, but your parts could not be matched to it \u2014 choose parts again. Until then the whole Source goes in.";
|
|
423
242
|
var SAME_SOURCE_AGAIN = "You added this again \u2014 it is the same Source, so it is listed once.";
|
|
424
243
|
function isSourceDraft(value) {
|
|
425
244
|
return !!value && typeof value === "object" && typeof value.kind === "string" && typeof value.label === "string";
|
|
@@ -486,7 +305,7 @@ function settleCard(state, id, patch, options = {}) {
|
|
|
486
305
|
}));
|
|
487
306
|
}
|
|
488
307
|
function failCard(state, id, sentence) {
|
|
489
|
-
return replaceCard(state, id, (c) => ({ ...c, status: "error", error: sentence }));
|
|
308
|
+
return replaceCard(state, id, (c) => ({ ...c, status: "error", error: sentence, manifest: null }));
|
|
490
309
|
}
|
|
491
310
|
function restartCard(state, id) {
|
|
492
311
|
return replaceCard(state, id, (c) => ({ ...c, status: "resolving", error: null }));
|
|
@@ -502,7 +321,68 @@ function updateCardRef(state, id, options) {
|
|
|
502
321
|
return replaceCard(state, id, (c) => {
|
|
503
322
|
if (!c.draft.ref) return c;
|
|
504
323
|
const ref = createSourceRef(c.draft.ref.resource_type, c.draft.ref.resource_id, { ...c.draft.ref, ...options });
|
|
505
|
-
return { ...c, draft: { ...c.draft, ref } };
|
|
324
|
+
return rememberPickedParts({ ...c, draft: { ...c.draft, ref } });
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function rememberPickedParts(card) {
|
|
328
|
+
const ids = card.draft.ref?.include_segments ?? [];
|
|
329
|
+
if (ids.length === 0) {
|
|
330
|
+
return card.draft.pickedParts === void 0 ? card : { ...card, draft: { ...card.draft, pickedParts: void 0 } };
|
|
331
|
+
}
|
|
332
|
+
const segments = card.manifest?.segments ?? [];
|
|
333
|
+
const known = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));
|
|
334
|
+
const picked = [];
|
|
335
|
+
for (const id of ids) {
|
|
336
|
+
const segment = segments.find((s) => s.id === id);
|
|
337
|
+
if (segment) {
|
|
338
|
+
const pages = partPages(segment);
|
|
339
|
+
picked.push({ id, label: segment.label, ...pages ? { pages } : {} });
|
|
340
|
+
} else {
|
|
341
|
+
const before = known.get(id);
|
|
342
|
+
if (before) picked.push(before);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return { ...card, draft: { ...card.draft, pickedParts: picked.length ? picked : void 0 } };
|
|
346
|
+
}
|
|
347
|
+
function withNote(notes, note, drop = []) {
|
|
348
|
+
const kept = (notes ?? []).filter((n) => n !== note && !drop.includes(n));
|
|
349
|
+
return [...kept, note];
|
|
350
|
+
}
|
|
351
|
+
function carryPickedParts(card, entry) {
|
|
352
|
+
const ref = card.draft.ref;
|
|
353
|
+
const picked = ref?.include_segments ?? [];
|
|
354
|
+
const segments = entry.segments ?? [];
|
|
355
|
+
if (!ref || picked.length === 0 || segments.length === 0) return card;
|
|
356
|
+
const ids = new Set(segments.map((s) => s.id));
|
|
357
|
+
const stale = picked.filter((id) => !ids.has(id));
|
|
358
|
+
if (stale.length === 0) return card;
|
|
359
|
+
const remembered = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));
|
|
360
|
+
const oldSegments = card.manifest?.segments ?? [];
|
|
361
|
+
const spans = [];
|
|
362
|
+
let unknown = 0;
|
|
363
|
+
for (const id of stale) {
|
|
364
|
+
const old = oldSegments.find((s) => s.id === id);
|
|
365
|
+
const pages = remembered.get(id)?.pages ?? (old ? partPages(old) : null);
|
|
366
|
+
if (pages) spans.push(pages);
|
|
367
|
+
else unknown += 1;
|
|
368
|
+
}
|
|
369
|
+
const keep = new Set(picked.filter((id) => ids.has(id)));
|
|
370
|
+
for (const segment of segments) {
|
|
371
|
+
const pages = partPages(segment);
|
|
372
|
+
if (pages && spans.some(([from, to]) => pages[0] <= to && pages[1] >= from)) keep.add(segment.id);
|
|
373
|
+
}
|
|
374
|
+
const nextIds = segments.filter((s) => keep.has(s.id)).map((s) => s.id);
|
|
375
|
+
const matched = unknown === 0 && nextIds.length > 0;
|
|
376
|
+
const nextRef = createSourceRef(ref.resource_type, ref.resource_id, {
|
|
377
|
+
...ref,
|
|
378
|
+
include_segments: matched ? nextIds : void 0
|
|
379
|
+
});
|
|
380
|
+
const note = matched ? PARTS_MATCHED_BY_PAGE : PARTS_NOT_MATCHED;
|
|
381
|
+
const other = matched ? PARTS_NOT_MATCHED : PARTS_MATCHED_BY_PAGE;
|
|
382
|
+
return rememberPickedParts({
|
|
383
|
+
...card,
|
|
384
|
+
manifest: entry,
|
|
385
|
+
draft: { ...card.draft, ref: nextRef, notes: withNote(card.draft.notes, note, [other]) }
|
|
506
386
|
});
|
|
507
387
|
}
|
|
508
388
|
function setCardWaitForClean(state, id, wait) {
|
|
@@ -518,7 +398,7 @@ function applyReviewedSourceSet(state, set) {
|
|
|
518
398
|
if (!ref) continue;
|
|
519
399
|
const match = set.sources.find((r) => sameSourceRef(r, ref));
|
|
520
400
|
if (!match) continue;
|
|
521
|
-
next = replaceCard(next, card.id, (c) => ({ ...c, draft: { ...c.draft, ref: match } }));
|
|
401
|
+
next = replaceCard(next, card.id, (c) => rememberPickedParts({ ...c, draft: { ...c.draft, ref: match } }));
|
|
522
402
|
}
|
|
523
403
|
return set.topic !== void 0 ? setSourceTopic(next, set.topic) : next;
|
|
524
404
|
}
|
|
@@ -528,7 +408,13 @@ function applyManifest(state, manifest) {
|
|
|
528
408
|
const ref = card.draft.ref;
|
|
529
409
|
if (!ref || card.status !== "ready") continue;
|
|
530
410
|
const entry = manifest.sources.find((e) => sameSourceRef(e.ref, ref));
|
|
531
|
-
if (entry)
|
|
411
|
+
if (!entry) continue;
|
|
412
|
+
next = replaceCard(next, card.id, (c) => {
|
|
413
|
+
const carried = carryPickedParts(c, entry);
|
|
414
|
+
if (carried !== c) return carried;
|
|
415
|
+
const measured = { ...c, manifest: entry };
|
|
416
|
+
return c.draft.ref?.include_segments?.length && !c.draft.pickedParts ? rememberPickedParts(measured) : measured;
|
|
417
|
+
});
|
|
532
418
|
}
|
|
533
419
|
return next;
|
|
534
420
|
}
|
|
@@ -601,6 +487,27 @@ function selectTotalChars(state) {
|
|
|
601
487
|
model_context_tokens: null
|
|
602
488
|
});
|
|
603
489
|
}
|
|
490
|
+
function sourceEntryChars(entry, ref) {
|
|
491
|
+
if (entry.state !== "ready" && entry.state !== "processing") return null;
|
|
492
|
+
return totalChars({
|
|
493
|
+
__kind: "source_manifest",
|
|
494
|
+
sources: [{ ...entry, ref }],
|
|
495
|
+
total_chars: 0,
|
|
496
|
+
estimated_tokens: 0,
|
|
497
|
+
model_context_tokens: null
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
function sourceCardChars(card) {
|
|
501
|
+
return card.manifest && card.draft.ref ? sourceEntryChars(card.manifest, card.draft.ref) : null;
|
|
502
|
+
}
|
|
503
|
+
function sourceCardState(card) {
|
|
504
|
+
if (card.status === "pending" || card.status === "resolving") return "adding";
|
|
505
|
+
if (card.status === "error") return card.error === WAITING_FOR_ORGANIZATION ? "waiting_for_organization" : "failed";
|
|
506
|
+
return card.manifest?.state ?? "unmeasured";
|
|
507
|
+
}
|
|
508
|
+
function sourceCardMeasuredState(card) {
|
|
509
|
+
return card.status === "ready" ? card.manifest?.state ?? null : null;
|
|
510
|
+
}
|
|
604
511
|
function selectSettled(state) {
|
|
605
512
|
return state.cards.every((c) => c.status === "ready");
|
|
606
513
|
}
|
|
@@ -622,6 +529,190 @@ function withDisplayNames(resolved, cards) {
|
|
|
622
529
|
};
|
|
623
530
|
}
|
|
624
531
|
|
|
532
|
+
// sources/runtime/plan.ts
|
|
533
|
+
var HEAVY_SHARE = 0.7;
|
|
534
|
+
var PAGE_SUFFIX = (page) => page !== void 0 && page > 0 ? ` (page ${page})` : "";
|
|
535
|
+
function renderedPartChars(segment, chars) {
|
|
536
|
+
return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;
|
|
537
|
+
}
|
|
538
|
+
function capParts(parts, maxChars) {
|
|
539
|
+
if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };
|
|
540
|
+
const kept = [];
|
|
541
|
+
let used = 0;
|
|
542
|
+
for (const seg of parts) {
|
|
543
|
+
if (used + seg.chars <= maxChars) {
|
|
544
|
+
kept.push({ seg, chars: seg.chars });
|
|
545
|
+
used += seg.chars;
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
const room = maxChars - used;
|
|
549
|
+
if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });
|
|
550
|
+
return { kept, capped: true };
|
|
551
|
+
}
|
|
552
|
+
return { kept, capped: false };
|
|
553
|
+
}
|
|
554
|
+
function chosenForm(entry, ref) {
|
|
555
|
+
const key = ref.representation ?? entry.default_form;
|
|
556
|
+
return entry.forms.find((f) => f.form === key) ?? entry.forms.find((f) => f.form === entry.default_form) ?? null;
|
|
557
|
+
}
|
|
558
|
+
function isUsable(entry) {
|
|
559
|
+
return entry.state === "ready" || entry.state === "processing";
|
|
560
|
+
}
|
|
561
|
+
function measure(entry, ref) {
|
|
562
|
+
const form = chosenForm(entry, ref);
|
|
563
|
+
const formChars = form?.chars ?? 0;
|
|
564
|
+
const formLabel = form?.label ?? "Text";
|
|
565
|
+
const segments = entry.segments ?? null;
|
|
566
|
+
if (segments && segments.length > 0) {
|
|
567
|
+
const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;
|
|
568
|
+
const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;
|
|
569
|
+
const { kept, capped: capped2 } = capParts(chosen, ref.max_chars);
|
|
570
|
+
const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);
|
|
571
|
+
const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;
|
|
572
|
+
return {
|
|
573
|
+
formChars,
|
|
574
|
+
formLabel,
|
|
575
|
+
sentChars,
|
|
576
|
+
exact: true,
|
|
577
|
+
partsSent: kept.length,
|
|
578
|
+
partsTotal: segments.length,
|
|
579
|
+
capped: capped2
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
const capped = ref.max_chars !== void 0 && formChars > ref.max_chars;
|
|
583
|
+
return {
|
|
584
|
+
formChars,
|
|
585
|
+
formLabel,
|
|
586
|
+
sentChars: capped ? ref.max_chars ?? formChars : formChars,
|
|
587
|
+
exact: false,
|
|
588
|
+
partsSent: null,
|
|
589
|
+
partsTotal: null,
|
|
590
|
+
capped
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
function planSourceReview(input) {
|
|
594
|
+
const estimateTokens = input.estimateTokens ?? estimateSourceTokens;
|
|
595
|
+
const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;
|
|
596
|
+
const windowTokens = windowIsFallback ? input.fallbackWindowTokens : input.modelWindowTokens;
|
|
597
|
+
let sentChars = 0;
|
|
598
|
+
const entries = input.manifest.sources.map((entry, index) => {
|
|
599
|
+
const ref = input.refs[index] ?? entry.ref;
|
|
600
|
+
const m = measure(entry, ref);
|
|
601
|
+
const base = { index, ref, entry, ...m, chars: sourceEntryChars(entry, ref) ?? 0 };
|
|
602
|
+
if (!isUsable(entry)) {
|
|
603
|
+
return { ...base, status: "unusable", sentChars: 0, sentTokens: 0 };
|
|
604
|
+
}
|
|
605
|
+
if (sourceDelivery(ref) === "context") {
|
|
606
|
+
return { ...base, status: "on_demand", sentChars: 0, sentTokens: 0 };
|
|
607
|
+
}
|
|
608
|
+
if (estimateTokens(sentChars + m.sentChars) > windowTokens) {
|
|
609
|
+
return { ...base, status: "left_out", sentTokens: estimateTokens(m.sentChars) };
|
|
610
|
+
}
|
|
611
|
+
sentChars += m.sentChars;
|
|
612
|
+
return { ...base, status: "included", sentTokens: estimateTokens(m.sentChars) };
|
|
613
|
+
});
|
|
614
|
+
const sentTokens = estimateTokens(sentChars);
|
|
615
|
+
const leftOut = entries.filter((e) => e.status === "left_out");
|
|
616
|
+
const share = windowTokens > 0 ? sentTokens / windowTokens : 0;
|
|
617
|
+
const anythingGoesIn = entries.some((e) => e.status === "included" || e.status === "on_demand");
|
|
618
|
+
const verdict = !anythingGoesIn && leftOut.length === 0 ? "empty" : leftOut.length > 0 ? "too_much" : share >= HEAVY_SHARE ? "heavy" : "fine";
|
|
619
|
+
const kept = entries.filter((e) => e.status !== "left_out").map(
|
|
620
|
+
(e) => createSourceRef(e.ref.resource_type, e.ref.resource_id, {
|
|
621
|
+
representation: e.ref.representation,
|
|
622
|
+
include_segments: e.ref.include_segments,
|
|
623
|
+
delivery: e.ref.delivery,
|
|
624
|
+
max_chars: e.ref.max_chars,
|
|
625
|
+
promote: e.ref.promote,
|
|
626
|
+
exclude: e.ref.exclude
|
|
627
|
+
})
|
|
628
|
+
);
|
|
629
|
+
const grounding = input.base.grounding === "selected" && !kept.some((r) => r.include_segments?.length) ? void 0 : input.base.grounding;
|
|
630
|
+
const sourceSet = createSourceSet(kept, {
|
|
631
|
+
topic: input.base.topic,
|
|
632
|
+
grounding,
|
|
633
|
+
retrieve_query: input.base.retrieve_query,
|
|
634
|
+
target_model_id: input.targetModelId ?? input.base.target_model_id
|
|
635
|
+
});
|
|
636
|
+
return {
|
|
637
|
+
entries,
|
|
638
|
+
chars: entries.filter((e) => e.status === "included").reduce((sum, e) => sum + e.chars, 0),
|
|
639
|
+
sentChars,
|
|
640
|
+
sentTokens,
|
|
641
|
+
windowTokens,
|
|
642
|
+
windowIsFallback,
|
|
643
|
+
verdict,
|
|
644
|
+
share,
|
|
645
|
+
leftOut,
|
|
646
|
+
sourceSet
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// sources/runtime/client.ts
|
|
651
|
+
function marked(options) {
|
|
652
|
+
return {
|
|
653
|
+
bodyCarriedRead: true,
|
|
654
|
+
...options?.organizationId ? { organizationId: options.organizationId } : {},
|
|
655
|
+
...options?.signal ? { signal: options.signal } : {}
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function createSourcesClient(transport) {
|
|
659
|
+
return {
|
|
660
|
+
manifest: (sourceSet, options) => transport.post("/sources/manifest", { source_set: sourceSet }, marked(options)),
|
|
661
|
+
resolve: (sourceSet, options) => transport.post("/sources/resolve", { source_set: sourceSet }, marked(options)),
|
|
662
|
+
searchParts: (ref, query, options) => transport.post("/sources/parts/search", { source_ref: ref, query }, marked(options))
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
var SourceDoorError = class extends Error {
|
|
666
|
+
status;
|
|
667
|
+
body;
|
|
668
|
+
constructor(status, message, body) {
|
|
669
|
+
super(message);
|
|
670
|
+
this.name = "SourceDoorError";
|
|
671
|
+
this.status = status;
|
|
672
|
+
this.body = body;
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
function refusalMessage(status, body) {
|
|
676
|
+
if (body && typeof body === "object") {
|
|
677
|
+
const record = body;
|
|
678
|
+
const error = record.error;
|
|
679
|
+
if (error && typeof error === "object") {
|
|
680
|
+
const message = error.user_message ?? error.message;
|
|
681
|
+
if (typeof message === "string" && message) return message;
|
|
682
|
+
}
|
|
683
|
+
if (typeof record.detail === "string" && record.detail) return record.detail;
|
|
684
|
+
}
|
|
685
|
+
return `The server answered ${status}.`;
|
|
686
|
+
}
|
|
687
|
+
function createFetchSourcesTransport(options) {
|
|
688
|
+
const base = options.baseUrl.replace(/\/+$/, "");
|
|
689
|
+
return {
|
|
690
|
+
async post(path, body, call) {
|
|
691
|
+
const doFetch = options.fetch ?? fetch;
|
|
692
|
+
const headers = {
|
|
693
|
+
"Content-Type": "application/json",
|
|
694
|
+
...options.headers ? await options.headers() : {}
|
|
695
|
+
};
|
|
696
|
+
if (call.organizationId) headers[options.organizationHeader ?? "X-Organization-Id"] = call.organizationId;
|
|
697
|
+
const response = await doFetch(`${base}${path}`, {
|
|
698
|
+
method: "POST",
|
|
699
|
+
headers,
|
|
700
|
+
body: JSON.stringify(body),
|
|
701
|
+
...call.signal ? { signal: call.signal } : {}
|
|
702
|
+
});
|
|
703
|
+
const text = await response.text();
|
|
704
|
+
let parsed = null;
|
|
705
|
+
try {
|
|
706
|
+
parsed = text ? JSON.parse(text) : null;
|
|
707
|
+
} catch {
|
|
708
|
+
parsed = text;
|
|
709
|
+
}
|
|
710
|
+
if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);
|
|
711
|
+
return parsed;
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
|
|
625
716
|
// sources/runtime/controller.ts
|
|
626
717
|
function randomId() {
|
|
627
718
|
const cryptoApi = globalThis.crypto;
|
|
@@ -1041,20 +1132,45 @@ function createSourceIntake(set, deps) {
|
|
|
1041
1132
|
});
|
|
1042
1133
|
await hold(() => landPaste(id, trimmed, name));
|
|
1043
1134
|
},
|
|
1135
|
+
async addRecordedText(text, name) {
|
|
1136
|
+
const trimmed = text.trim();
|
|
1137
|
+
if (!trimmed) return;
|
|
1138
|
+
const max = deps.maxKeptChars();
|
|
1139
|
+
const kept = max !== null && trimmed.length <= max;
|
|
1140
|
+
const id = set.addPending({
|
|
1141
|
+
kind: "audio",
|
|
1142
|
+
label: name?.trim() || "Recording",
|
|
1143
|
+
origin: "Recording",
|
|
1144
|
+
input: kept ? { text: trimmed, name } : void 0,
|
|
1145
|
+
notes: kept ? void 0 : [NOT_KEPT_FOR_RELOAD]
|
|
1146
|
+
});
|
|
1147
|
+
await hold(() => landPaste(id, trimmed, name));
|
|
1148
|
+
},
|
|
1044
1149
|
async addWebPage(raw) {
|
|
1045
1150
|
const url = /^https?:\/\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;
|
|
1046
1151
|
const id = set.addPending({ kind: "web", label: hostOf(url), origin: url, input: { url } });
|
|
1047
1152
|
await hold(() => landWebPage(id, url));
|
|
1048
1153
|
},
|
|
1049
|
-
|
|
1154
|
+
beginWebPage(raw) {
|
|
1155
|
+
const url = /^https?:\/\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;
|
|
1156
|
+
return set.addPending({ kind: "web", label: hostOf(url), origin: url, input: { url } });
|
|
1157
|
+
},
|
|
1158
|
+
async addScrapedPage(page, pendingId) {
|
|
1050
1159
|
const label = page.title || hostOf(page.url);
|
|
1160
|
+
const cardFor = () => {
|
|
1161
|
+
if (pendingId && set.restart(pendingId)) {
|
|
1162
|
+
set.updateDraft(pendingId, { label, origin: page.url, input: { url: page.url } });
|
|
1163
|
+
return pendingId;
|
|
1164
|
+
}
|
|
1165
|
+
return set.addPending({ kind: "web", label, origin: page.url, input: { url: page.url } });
|
|
1166
|
+
};
|
|
1051
1167
|
if (!page.processedDocumentId) {
|
|
1052
|
-
const id2 =
|
|
1168
|
+
const id2 = cardFor();
|
|
1053
1169
|
await hold(() => landPaste(id2, page.text, label));
|
|
1054
1170
|
return;
|
|
1055
1171
|
}
|
|
1056
1172
|
const pdId = page.processedDocumentId;
|
|
1057
|
-
const id =
|
|
1173
|
+
const id = cardFor();
|
|
1058
1174
|
await hold(async () => {
|
|
1059
1175
|
let notes = [];
|
|
1060
1176
|
try {
|
|
@@ -1129,7 +1245,8 @@ function createSourceIntake(set, deps) {
|
|
|
1129
1245
|
return true;
|
|
1130
1246
|
}
|
|
1131
1247
|
case "audio":
|
|
1132
|
-
void transcribeRecording(card.id, input.fileId
|
|
1248
|
+
if (input.fileId) void transcribeRecording(card.id, input.fileId, card.draft.label);
|
|
1249
|
+
else void landPaste(card.id, (input.text ?? "").trim(), input.name);
|
|
1133
1250
|
return true;
|
|
1134
1251
|
default:
|
|
1135
1252
|
return false;
|
|
@@ -1257,6 +1374,8 @@ export {
|
|
|
1257
1374
|
KEEP_WAITING_FOR_ORGANIZATION,
|
|
1258
1375
|
MAX_KEPT_TEXT_KNOB,
|
|
1259
1376
|
NOT_KEPT_FOR_RELOAD,
|
|
1377
|
+
PARTS_MATCHED_BY_PAGE,
|
|
1378
|
+
PARTS_NOT_MATCHED,
|
|
1260
1379
|
RELOADED_RESUMING,
|
|
1261
1380
|
RELOADED_WHILE_ADDING,
|
|
1262
1381
|
SAME_SOURCE_AGAIN,
|
|
@@ -1270,6 +1389,7 @@ export {
|
|
|
1270
1389
|
applyReviewedSourceSet,
|
|
1271
1390
|
cardsToResume,
|
|
1272
1391
|
cardsWaitingForOrganization,
|
|
1392
|
+
carryPickedParts,
|
|
1273
1393
|
chosenForm,
|
|
1274
1394
|
continueAfterOrganization,
|
|
1275
1395
|
createFetchSourcesTransport,
|
|
@@ -1303,6 +1423,7 @@ export {
|
|
|
1303
1423
|
readySourceRefs,
|
|
1304
1424
|
registeredFileEdge,
|
|
1305
1425
|
reloadedCard,
|
|
1426
|
+
rememberPickedParts,
|
|
1306
1427
|
removeCard,
|
|
1307
1428
|
renderedPartChars,
|
|
1308
1429
|
restartCard,
|
|
@@ -1317,7 +1438,11 @@ export {
|
|
|
1317
1438
|
setSourceTopic,
|
|
1318
1439
|
settleCard,
|
|
1319
1440
|
sourceAttachTargets,
|
|
1441
|
+
sourceCardChars,
|
|
1442
|
+
sourceCardMeasuredState,
|
|
1443
|
+
sourceCardState,
|
|
1320
1444
|
sourceDelivery,
|
|
1445
|
+
sourceEntryChars,
|
|
1321
1446
|
sourceKey,
|
|
1322
1447
|
sourceRecoveryGuards,
|
|
1323
1448
|
sourceRoomLeft,
|