@ai-matrx/agents 0.18.1 → 0.19.1
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 +73 -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 +130 -18
- package/dist/sources/react/index.cjs.map +1 -1
- package/dist/sources/react/index.d.cts +46 -5
- package/dist/sources/react/index.d.ts +46 -5
- package/dist/sources/react/index.js +130 -18
- package/dist/sources/react/index.js.map +1 -1
- package/dist/sources/runtime/index.cjs +337 -201
- package/dist/sources/runtime/index.cjs.map +1 -1
- package/dist/sources/runtime/index.d.cts +109 -10
- package/dist/sources/runtime/index.d.ts +109 -10
- package/dist/sources/runtime/index.js +337 -201
- 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/mandates/snapshots/keys.0.19.1.json +652 -0
- package/package.json +3 -3
|
@@ -27,6 +27,8 @@ __export(runtime_exports, {
|
|
|
27
27
|
KEEP_WAITING_FOR_ORGANIZATION: () => KEEP_WAITING_FOR_ORGANIZATION,
|
|
28
28
|
MAX_KEPT_TEXT_KNOB: () => MAX_KEPT_TEXT_KNOB,
|
|
29
29
|
NOT_KEPT_FOR_RELOAD: () => NOT_KEPT_FOR_RELOAD,
|
|
30
|
+
PARTS_MATCHED_BY_PAGE: () => PARTS_MATCHED_BY_PAGE,
|
|
31
|
+
PARTS_NOT_MATCHED: () => PARTS_NOT_MATCHED,
|
|
30
32
|
RELOADED_RESUMING: () => RELOADED_RESUMING,
|
|
31
33
|
RELOADED_WHILE_ADDING: () => RELOADED_WHILE_ADDING,
|
|
32
34
|
SAME_SOURCE_AGAIN: () => SAME_SOURCE_AGAIN,
|
|
@@ -40,6 +42,7 @@ __export(runtime_exports, {
|
|
|
40
42
|
applyReviewedSourceSet: () => applyReviewedSourceSet,
|
|
41
43
|
cardsToResume: () => cardsToResume,
|
|
42
44
|
cardsWaitingForOrganization: () => cardsWaitingForOrganization,
|
|
45
|
+
carryPickedParts: () => carryPickedParts,
|
|
43
46
|
chosenForm: () => chosenForm,
|
|
44
47
|
continueAfterOrganization: () => continueAfterOrganization,
|
|
45
48
|
createFetchSourcesTransport: () => createFetchSourcesTransport,
|
|
@@ -73,7 +76,9 @@ __export(runtime_exports, {
|
|
|
73
76
|
readySourceRefs: () => readySourceRefs,
|
|
74
77
|
registeredFileEdge: () => registeredFileEdge,
|
|
75
78
|
reloadedCard: () => reloadedCard,
|
|
79
|
+
rememberPickedParts: () => rememberPickedParts,
|
|
76
80
|
removeCard: () => removeCard,
|
|
81
|
+
removedInReview: () => removedInReview,
|
|
77
82
|
renderedPartChars: () => renderedPartChars,
|
|
78
83
|
restartCard: () => restartCard,
|
|
79
84
|
restoredCards: () => restoredCards,
|
|
@@ -87,7 +92,11 @@ __export(runtime_exports, {
|
|
|
87
92
|
setSourceTopic: () => setSourceTopic,
|
|
88
93
|
settleCard: () => settleCard,
|
|
89
94
|
sourceAttachTargets: () => sourceAttachTargets,
|
|
95
|
+
sourceCardChars: () => sourceCardChars,
|
|
96
|
+
sourceCardMeasuredState: () => sourceCardMeasuredState,
|
|
97
|
+
sourceCardState: () => sourceCardState,
|
|
90
98
|
sourceDelivery: () => sourceDelivery,
|
|
99
|
+
sourceEntryChars: () => sourceEntryChars,
|
|
91
100
|
sourceKey: () => sourceKey,
|
|
92
101
|
sourceRecoveryGuards: () => sourceRecoveryGuards,
|
|
93
102
|
sourceRoomLeft: () => sourceRoomLeft,
|
|
@@ -110,12 +119,12 @@ function deliveryPatch(delivery) {
|
|
|
110
119
|
var DELIVERY_WORDS = {
|
|
111
120
|
direct: {
|
|
112
121
|
label: "Include the text",
|
|
113
|
-
hint: "
|
|
122
|
+
hint: "Sent in full",
|
|
114
123
|
summary: "Text included"
|
|
115
124
|
},
|
|
116
125
|
context: {
|
|
117
126
|
label: "Let the AI look it up",
|
|
118
|
-
hint: "
|
|
127
|
+
hint: "Read as needed",
|
|
119
128
|
summary: "Looked up when needed"
|
|
120
129
|
}
|
|
121
130
|
};
|
|
@@ -192,7 +201,7 @@ function resumableInput(draft) {
|
|
|
192
201
|
case "youtube":
|
|
193
202
|
return input.url?.trim() ? input : null;
|
|
194
203
|
case "audio":
|
|
195
|
-
return input.fileId ? input : null;
|
|
204
|
+
return input.fileId || input.text?.trim() ? input : null;
|
|
196
205
|
default:
|
|
197
206
|
return null;
|
|
198
207
|
}
|
|
@@ -208,12 +217,12 @@ function reloadedCard(draft, status) {
|
|
|
208
217
|
return { action: "lost", sentence: RELOADED_WHILE_ADDING };
|
|
209
218
|
}
|
|
210
219
|
var MAX_KEPT_TEXT_KNOB = { feature: "sources", key: "max_kept_draft_chars" };
|
|
211
|
-
var NOT_KEPT_FOR_RELOAD = "Too large to
|
|
220
|
+
var NOT_KEPT_FOR_RELOAD = "Too large to restore if the page reloads before it is added.";
|
|
212
221
|
var WAITING_FOR_ORGANIZATION = "Waiting for an organization \u2014 choose one and this continues by itself.";
|
|
213
222
|
var KEEP_WAITING_FOR_ORGANIZATION = "Read. Waiting for an organization to keep it \u2014 choose one and it is kept by itself.";
|
|
214
223
|
|
|
215
224
|
// sources/runtime/fileSource.ts
|
|
216
|
-
var UNREADABLE = "
|
|
225
|
+
var UNREADABLE = "Can't read this file \u2014 add a PDF, Word or text copy.";
|
|
217
226
|
function nextFileStep(status, ctx) {
|
|
218
227
|
const pdId = status?.processed_document_id ?? null;
|
|
219
228
|
if (pdId) return { do: "keep", processedDocumentId: pdId };
|
|
@@ -221,7 +230,7 @@ function nextFileStep(status, ctx) {
|
|
|
221
230
|
if (status?.state === "failed")
|
|
222
231
|
return {
|
|
223
232
|
do: "unreadable",
|
|
224
|
-
reason: status.error?.message ? `
|
|
233
|
+
reason: status.error?.message ? `Can't read this file: ${status.error.message}. Add it again.` : UNREADABLE
|
|
225
234
|
};
|
|
226
235
|
if (!ctx.started) return { do: "start" };
|
|
227
236
|
return { do: "unreadable", reason: UNREADABLE };
|
|
@@ -337,191 +346,10 @@ function totalChars(value) {
|
|
|
337
346
|
return value.sources.filter((entry) => entry.state === "ready" || entry.state === "processing").reduce((sum, entry) => sum + manifestEntryChars(entry), 0);
|
|
338
347
|
}
|
|
339
348
|
|
|
340
|
-
// sources/runtime/plan.ts
|
|
341
|
-
var HEAVY_SHARE = 0.7;
|
|
342
|
-
var PAGE_SUFFIX = (page) => page !== void 0 && page > 0 ? ` (page ${page})` : "";
|
|
343
|
-
function renderedPartChars(segment, chars) {
|
|
344
|
-
return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;
|
|
345
|
-
}
|
|
346
|
-
function capParts(parts, maxChars) {
|
|
347
|
-
if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };
|
|
348
|
-
const kept = [];
|
|
349
|
-
let used = 0;
|
|
350
|
-
for (const seg of parts) {
|
|
351
|
-
if (used + seg.chars <= maxChars) {
|
|
352
|
-
kept.push({ seg, chars: seg.chars });
|
|
353
|
-
used += seg.chars;
|
|
354
|
-
continue;
|
|
355
|
-
}
|
|
356
|
-
const room = maxChars - used;
|
|
357
|
-
if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });
|
|
358
|
-
return { kept, capped: true };
|
|
359
|
-
}
|
|
360
|
-
return { kept, capped: false };
|
|
361
|
-
}
|
|
362
|
-
function chosenForm(entry, ref) {
|
|
363
|
-
const key = ref.representation ?? entry.default_form;
|
|
364
|
-
return entry.forms.find((f) => f.form === key) ?? entry.forms.find((f) => f.form === entry.default_form) ?? null;
|
|
365
|
-
}
|
|
366
|
-
function isUsable(entry) {
|
|
367
|
-
return entry.state === "ready" || entry.state === "processing";
|
|
368
|
-
}
|
|
369
|
-
function measure(entry, ref) {
|
|
370
|
-
const form = chosenForm(entry, ref);
|
|
371
|
-
const formChars = form?.chars ?? 0;
|
|
372
|
-
const formLabel = form?.label ?? "Text";
|
|
373
|
-
const segments = entry.segments ?? null;
|
|
374
|
-
if (segments && segments.length > 0) {
|
|
375
|
-
const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;
|
|
376
|
-
const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;
|
|
377
|
-
const { kept, capped: capped2 } = capParts(chosen, ref.max_chars);
|
|
378
|
-
const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);
|
|
379
|
-
const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;
|
|
380
|
-
return {
|
|
381
|
-
formChars,
|
|
382
|
-
formLabel,
|
|
383
|
-
sentChars,
|
|
384
|
-
exact: true,
|
|
385
|
-
partsSent: kept.length,
|
|
386
|
-
partsTotal: segments.length,
|
|
387
|
-
capped: capped2
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
const capped = ref.max_chars !== void 0 && formChars > ref.max_chars;
|
|
391
|
-
return {
|
|
392
|
-
formChars,
|
|
393
|
-
formLabel,
|
|
394
|
-
sentChars: capped ? ref.max_chars ?? formChars : formChars,
|
|
395
|
-
exact: false,
|
|
396
|
-
partsSent: null,
|
|
397
|
-
partsTotal: null,
|
|
398
|
-
capped
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
function planSourceReview(input) {
|
|
402
|
-
const estimateTokens = input.estimateTokens ?? estimateSourceTokens;
|
|
403
|
-
const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;
|
|
404
|
-
const windowTokens = windowIsFallback ? input.fallbackWindowTokens : input.modelWindowTokens;
|
|
405
|
-
let sentChars = 0;
|
|
406
|
-
const entries = input.manifest.sources.map((entry, index) => {
|
|
407
|
-
const ref = input.refs[index] ?? entry.ref;
|
|
408
|
-
const m = measure(entry, ref);
|
|
409
|
-
const base = { index, ref, entry, ...m };
|
|
410
|
-
if (!isUsable(entry)) {
|
|
411
|
-
return { ...base, status: "unusable", sentChars: 0, sentTokens: 0 };
|
|
412
|
-
}
|
|
413
|
-
if (sourceDelivery(ref) === "context") {
|
|
414
|
-
return { ...base, status: "on_demand", sentChars: 0, sentTokens: 0 };
|
|
415
|
-
}
|
|
416
|
-
if (estimateTokens(sentChars + m.sentChars) > windowTokens) {
|
|
417
|
-
return { ...base, status: "left_out", sentTokens: estimateTokens(m.sentChars) };
|
|
418
|
-
}
|
|
419
|
-
sentChars += m.sentChars;
|
|
420
|
-
return { ...base, status: "included", sentTokens: estimateTokens(m.sentChars) };
|
|
421
|
-
});
|
|
422
|
-
const sentTokens = estimateTokens(sentChars);
|
|
423
|
-
const leftOut = entries.filter((e) => e.status === "left_out");
|
|
424
|
-
const share = windowTokens > 0 ? sentTokens / windowTokens : 0;
|
|
425
|
-
const anythingGoesIn = entries.some((e) => e.status === "included" || e.status === "on_demand");
|
|
426
|
-
const verdict = !anythingGoesIn && leftOut.length === 0 ? "empty" : leftOut.length > 0 ? "too_much" : share >= HEAVY_SHARE ? "heavy" : "fine";
|
|
427
|
-
const kept = entries.filter((e) => e.status !== "left_out").map(
|
|
428
|
-
(e) => createSourceRef(e.ref.resource_type, e.ref.resource_id, {
|
|
429
|
-
representation: e.ref.representation,
|
|
430
|
-
include_segments: e.ref.include_segments,
|
|
431
|
-
delivery: e.ref.delivery,
|
|
432
|
-
max_chars: e.ref.max_chars,
|
|
433
|
-
promote: e.ref.promote,
|
|
434
|
-
exclude: e.ref.exclude
|
|
435
|
-
})
|
|
436
|
-
);
|
|
437
|
-
const grounding = input.base.grounding === "selected" && !kept.some((r) => r.include_segments?.length) ? void 0 : input.base.grounding;
|
|
438
|
-
const sourceSet = createSourceSet(kept, {
|
|
439
|
-
topic: input.base.topic,
|
|
440
|
-
grounding,
|
|
441
|
-
retrieve_query: input.base.retrieve_query,
|
|
442
|
-
target_model_id: input.targetModelId ?? input.base.target_model_id
|
|
443
|
-
});
|
|
444
|
-
return {
|
|
445
|
-
entries,
|
|
446
|
-
sentChars,
|
|
447
|
-
sentTokens,
|
|
448
|
-
windowTokens,
|
|
449
|
-
windowIsFallback,
|
|
450
|
-
verdict,
|
|
451
|
-
share,
|
|
452
|
-
leftOut,
|
|
453
|
-
sourceSet
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// sources/runtime/client.ts
|
|
458
|
-
function marked(options) {
|
|
459
|
-
return {
|
|
460
|
-
bodyCarriedRead: true,
|
|
461
|
-
...options?.organizationId ? { organizationId: options.organizationId } : {},
|
|
462
|
-
...options?.signal ? { signal: options.signal } : {}
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
function createSourcesClient(transport) {
|
|
466
|
-
return {
|
|
467
|
-
manifest: (sourceSet, options) => transport.post("/sources/manifest", { source_set: sourceSet }, marked(options)),
|
|
468
|
-
resolve: (sourceSet, options) => transport.post("/sources/resolve", { source_set: sourceSet }, marked(options)),
|
|
469
|
-
searchParts: (ref, query, options) => transport.post("/sources/parts/search", { source_ref: ref, query }, marked(options))
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
var SourceDoorError = class extends Error {
|
|
473
|
-
status;
|
|
474
|
-
body;
|
|
475
|
-
constructor(status, message, body) {
|
|
476
|
-
super(message);
|
|
477
|
-
this.name = "SourceDoorError";
|
|
478
|
-
this.status = status;
|
|
479
|
-
this.body = body;
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
function refusalMessage(status, body) {
|
|
483
|
-
if (body && typeof body === "object") {
|
|
484
|
-
const record = body;
|
|
485
|
-
const error = record.error;
|
|
486
|
-
if (error && typeof error === "object") {
|
|
487
|
-
const message = error.user_message ?? error.message;
|
|
488
|
-
if (typeof message === "string" && message) return message;
|
|
489
|
-
}
|
|
490
|
-
if (typeof record.detail === "string" && record.detail) return record.detail;
|
|
491
|
-
}
|
|
492
|
-
return `The server answered ${status}.`;
|
|
493
|
-
}
|
|
494
|
-
function createFetchSourcesTransport(options) {
|
|
495
|
-
const base = options.baseUrl.replace(/\/+$/, "");
|
|
496
|
-
return {
|
|
497
|
-
async post(path, body, call) {
|
|
498
|
-
const doFetch = options.fetch ?? fetch;
|
|
499
|
-
const headers = {
|
|
500
|
-
"Content-Type": "application/json",
|
|
501
|
-
...options.headers ? await options.headers() : {}
|
|
502
|
-
};
|
|
503
|
-
if (call.organizationId) headers[options.organizationHeader ?? "X-Organization-Id"] = call.organizationId;
|
|
504
|
-
const response = await doFetch(`${base}${path}`, {
|
|
505
|
-
method: "POST",
|
|
506
|
-
headers,
|
|
507
|
-
body: JSON.stringify(body),
|
|
508
|
-
...call.signal ? { signal: call.signal } : {}
|
|
509
|
-
});
|
|
510
|
-
const text = await response.text();
|
|
511
|
-
let parsed = null;
|
|
512
|
-
try {
|
|
513
|
-
parsed = text ? JSON.parse(text) : null;
|
|
514
|
-
} catch {
|
|
515
|
-
parsed = text;
|
|
516
|
-
}
|
|
517
|
-
if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);
|
|
518
|
-
return parsed;
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
|
|
523
349
|
// sources/runtime/state.ts
|
|
524
350
|
var EMPTY_SOURCE_SET_STATE = Object.freeze({ cards: Object.freeze([]), topic: "" });
|
|
351
|
+
var PARTS_MATCHED_BY_PAGE = "The clean version is ready \u2014 your parts were matched to it by page.";
|
|
352
|
+
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.";
|
|
525
353
|
var SAME_SOURCE_AGAIN = "You added this again \u2014 it is the same Source, so it is listed once.";
|
|
526
354
|
function isSourceDraft(value) {
|
|
527
355
|
return !!value && typeof value === "object" && typeof value.kind === "string" && typeof value.label === "string";
|
|
@@ -588,7 +416,7 @@ function settleCard(state, id, patch, options = {}) {
|
|
|
588
416
|
}));
|
|
589
417
|
}
|
|
590
418
|
function failCard(state, id, sentence) {
|
|
591
|
-
return replaceCard(state, id, (c) => ({ ...c, status: "error", error: sentence }));
|
|
419
|
+
return replaceCard(state, id, (c) => ({ ...c, status: "error", error: sentence, manifest: null }));
|
|
592
420
|
}
|
|
593
421
|
function restartCard(state, id) {
|
|
594
422
|
return replaceCard(state, id, (c) => ({ ...c, status: "resolving", error: null }));
|
|
@@ -604,7 +432,68 @@ function updateCardRef(state, id, options) {
|
|
|
604
432
|
return replaceCard(state, id, (c) => {
|
|
605
433
|
if (!c.draft.ref) return c;
|
|
606
434
|
const ref = createSourceRef(c.draft.ref.resource_type, c.draft.ref.resource_id, { ...c.draft.ref, ...options });
|
|
607
|
-
return { ...c, draft: { ...c.draft, ref } };
|
|
435
|
+
return rememberPickedParts({ ...c, draft: { ...c.draft, ref } });
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
function rememberPickedParts(card) {
|
|
439
|
+
const ids = card.draft.ref?.include_segments ?? [];
|
|
440
|
+
if (ids.length === 0) {
|
|
441
|
+
return card.draft.pickedParts === void 0 ? card : { ...card, draft: { ...card.draft, pickedParts: void 0 } };
|
|
442
|
+
}
|
|
443
|
+
const segments = card.manifest?.segments ?? [];
|
|
444
|
+
const known = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));
|
|
445
|
+
const picked = [];
|
|
446
|
+
for (const id of ids) {
|
|
447
|
+
const segment = segments.find((s) => s.id === id);
|
|
448
|
+
if (segment) {
|
|
449
|
+
const pages = partPages(segment);
|
|
450
|
+
picked.push({ id, label: segment.label, ...pages ? { pages } : {} });
|
|
451
|
+
} else {
|
|
452
|
+
const before = known.get(id);
|
|
453
|
+
if (before) picked.push(before);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return { ...card, draft: { ...card.draft, pickedParts: picked.length ? picked : void 0 } };
|
|
457
|
+
}
|
|
458
|
+
function withNote(notes, note, drop = []) {
|
|
459
|
+
const kept = (notes ?? []).filter((n) => n !== note && !drop.includes(n));
|
|
460
|
+
return [...kept, note];
|
|
461
|
+
}
|
|
462
|
+
function carryPickedParts(card, entry) {
|
|
463
|
+
const ref = card.draft.ref;
|
|
464
|
+
const picked = ref?.include_segments ?? [];
|
|
465
|
+
const segments = entry.segments ?? [];
|
|
466
|
+
if (!ref || picked.length === 0 || segments.length === 0) return card;
|
|
467
|
+
const ids = new Set(segments.map((s) => s.id));
|
|
468
|
+
const stale = picked.filter((id) => !ids.has(id));
|
|
469
|
+
if (stale.length === 0) return card;
|
|
470
|
+
const remembered = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));
|
|
471
|
+
const oldSegments = card.manifest?.segments ?? [];
|
|
472
|
+
const spans = [];
|
|
473
|
+
let unknown = 0;
|
|
474
|
+
for (const id of stale) {
|
|
475
|
+
const old = oldSegments.find((s) => s.id === id);
|
|
476
|
+
const pages = remembered.get(id)?.pages ?? (old ? partPages(old) : null);
|
|
477
|
+
if (pages) spans.push(pages);
|
|
478
|
+
else unknown += 1;
|
|
479
|
+
}
|
|
480
|
+
const keep = new Set(picked.filter((id) => ids.has(id)));
|
|
481
|
+
for (const segment of segments) {
|
|
482
|
+
const pages = partPages(segment);
|
|
483
|
+
if (pages && spans.some(([from, to]) => pages[0] <= to && pages[1] >= from)) keep.add(segment.id);
|
|
484
|
+
}
|
|
485
|
+
const nextIds = segments.filter((s) => keep.has(s.id)).map((s) => s.id);
|
|
486
|
+
const matched = unknown === 0 && nextIds.length > 0;
|
|
487
|
+
const nextRef = createSourceRef(ref.resource_type, ref.resource_id, {
|
|
488
|
+
...ref,
|
|
489
|
+
include_segments: matched ? nextIds : void 0
|
|
490
|
+
});
|
|
491
|
+
const note = matched ? PARTS_MATCHED_BY_PAGE : PARTS_NOT_MATCHED;
|
|
492
|
+
const other = matched ? PARTS_NOT_MATCHED : PARTS_MATCHED_BY_PAGE;
|
|
493
|
+
return rememberPickedParts({
|
|
494
|
+
...card,
|
|
495
|
+
manifest: entry,
|
|
496
|
+
draft: { ...card.draft, ref: nextRef, notes: withNote(card.draft.notes, note, [other]) }
|
|
608
497
|
});
|
|
609
498
|
}
|
|
610
499
|
function setCardWaitForClean(state, id, wait) {
|
|
@@ -613,14 +502,24 @@ function setCardWaitForClean(state, id, wait) {
|
|
|
613
502
|
function setSourceTopic(state, topic) {
|
|
614
503
|
return state.topic === topic ? state : { ...state, topic };
|
|
615
504
|
}
|
|
616
|
-
function
|
|
505
|
+
function removedInReview(reviewed, answer) {
|
|
506
|
+
const kept = new Set(answer.sources.map(sourceKey));
|
|
507
|
+
return new Set(reviewed.sources.map(sourceKey).filter((k) => !kept.has(k)));
|
|
508
|
+
}
|
|
509
|
+
function applyReviewedSourceSet(state, set, reviewed) {
|
|
617
510
|
let next = state;
|
|
618
|
-
|
|
511
|
+
if (reviewed) {
|
|
512
|
+
const removed = removedInReview(reviewed, set);
|
|
513
|
+
for (const card of state.cards) {
|
|
514
|
+
if (card.draft.ref && removed.has(sourceKey(card.draft.ref))) next = removeCard(next, card.id);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
for (const card of next.cards) {
|
|
619
518
|
const ref = card.draft.ref;
|
|
620
519
|
if (!ref) continue;
|
|
621
520
|
const match = set.sources.find((r) => sameSourceRef(r, ref));
|
|
622
521
|
if (!match) continue;
|
|
623
|
-
next = replaceCard(next, card.id, (c) => ({ ...c, draft: { ...c.draft, ref: match } }));
|
|
522
|
+
next = replaceCard(next, card.id, (c) => rememberPickedParts({ ...c, draft: { ...c.draft, ref: match } }));
|
|
624
523
|
}
|
|
625
524
|
return set.topic !== void 0 ? setSourceTopic(next, set.topic) : next;
|
|
626
525
|
}
|
|
@@ -630,7 +529,13 @@ function applyManifest(state, manifest) {
|
|
|
630
529
|
const ref = card.draft.ref;
|
|
631
530
|
if (!ref || card.status !== "ready") continue;
|
|
632
531
|
const entry = manifest.sources.find((e) => sameSourceRef(e.ref, ref));
|
|
633
|
-
if (entry)
|
|
532
|
+
if (!entry) continue;
|
|
533
|
+
next = replaceCard(next, card.id, (c) => {
|
|
534
|
+
const carried = carryPickedParts(c, entry);
|
|
535
|
+
if (carried !== c) return carried;
|
|
536
|
+
const measured = { ...c, manifest: entry };
|
|
537
|
+
return c.draft.ref?.include_segments?.length && !c.draft.pickedParts ? rememberPickedParts(measured) : measured;
|
|
538
|
+
});
|
|
634
539
|
}
|
|
635
540
|
return next;
|
|
636
541
|
}
|
|
@@ -703,6 +608,27 @@ function selectTotalChars(state) {
|
|
|
703
608
|
model_context_tokens: null
|
|
704
609
|
});
|
|
705
610
|
}
|
|
611
|
+
function sourceEntryChars(entry, ref) {
|
|
612
|
+
if (entry.state !== "ready" && entry.state !== "processing") return null;
|
|
613
|
+
return totalChars({
|
|
614
|
+
__kind: "source_manifest",
|
|
615
|
+
sources: [{ ...entry, ref }],
|
|
616
|
+
total_chars: 0,
|
|
617
|
+
estimated_tokens: 0,
|
|
618
|
+
model_context_tokens: null
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
function sourceCardChars(card) {
|
|
622
|
+
return card.manifest && card.draft.ref ? sourceEntryChars(card.manifest, card.draft.ref) : null;
|
|
623
|
+
}
|
|
624
|
+
function sourceCardState(card) {
|
|
625
|
+
if (card.status === "pending" || card.status === "resolving") return "adding";
|
|
626
|
+
if (card.status === "error") return card.error === WAITING_FOR_ORGANIZATION ? "waiting_for_organization" : "failed";
|
|
627
|
+
return card.manifest?.state ?? "unmeasured";
|
|
628
|
+
}
|
|
629
|
+
function sourceCardMeasuredState(card) {
|
|
630
|
+
return card.status === "ready" ? card.manifest?.state ?? null : null;
|
|
631
|
+
}
|
|
706
632
|
function selectSettled(state) {
|
|
707
633
|
return state.cards.every((c) => c.status === "ready");
|
|
708
634
|
}
|
|
@@ -724,6 +650,190 @@ function withDisplayNames(resolved, cards) {
|
|
|
724
650
|
};
|
|
725
651
|
}
|
|
726
652
|
|
|
653
|
+
// sources/runtime/plan.ts
|
|
654
|
+
var HEAVY_SHARE = 0.7;
|
|
655
|
+
var PAGE_SUFFIX = (page) => page !== void 0 && page > 0 ? ` (page ${page})` : "";
|
|
656
|
+
function renderedPartChars(segment, chars) {
|
|
657
|
+
return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;
|
|
658
|
+
}
|
|
659
|
+
function capParts(parts, maxChars) {
|
|
660
|
+
if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };
|
|
661
|
+
const kept = [];
|
|
662
|
+
let used = 0;
|
|
663
|
+
for (const seg of parts) {
|
|
664
|
+
if (used + seg.chars <= maxChars) {
|
|
665
|
+
kept.push({ seg, chars: seg.chars });
|
|
666
|
+
used += seg.chars;
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
const room = maxChars - used;
|
|
670
|
+
if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });
|
|
671
|
+
return { kept, capped: true };
|
|
672
|
+
}
|
|
673
|
+
return { kept, capped: false };
|
|
674
|
+
}
|
|
675
|
+
function chosenForm(entry, ref) {
|
|
676
|
+
const key = ref.representation ?? entry.default_form;
|
|
677
|
+
return entry.forms.find((f) => f.form === key) ?? entry.forms.find((f) => f.form === entry.default_form) ?? null;
|
|
678
|
+
}
|
|
679
|
+
function isUsable(entry) {
|
|
680
|
+
return entry.state === "ready" || entry.state === "processing";
|
|
681
|
+
}
|
|
682
|
+
function measure(entry, ref) {
|
|
683
|
+
const form = chosenForm(entry, ref);
|
|
684
|
+
const formChars = form?.chars ?? 0;
|
|
685
|
+
const formLabel = form?.label ?? "Text";
|
|
686
|
+
const segments = entry.segments ?? null;
|
|
687
|
+
if (segments && segments.length > 0) {
|
|
688
|
+
const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;
|
|
689
|
+
const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;
|
|
690
|
+
const { kept, capped: capped2 } = capParts(chosen, ref.max_chars);
|
|
691
|
+
const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);
|
|
692
|
+
const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;
|
|
693
|
+
return {
|
|
694
|
+
formChars,
|
|
695
|
+
formLabel,
|
|
696
|
+
sentChars,
|
|
697
|
+
exact: true,
|
|
698
|
+
partsSent: kept.length,
|
|
699
|
+
partsTotal: segments.length,
|
|
700
|
+
capped: capped2
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const capped = ref.max_chars !== void 0 && formChars > ref.max_chars;
|
|
704
|
+
return {
|
|
705
|
+
formChars,
|
|
706
|
+
formLabel,
|
|
707
|
+
sentChars: capped ? ref.max_chars ?? formChars : formChars,
|
|
708
|
+
exact: false,
|
|
709
|
+
partsSent: null,
|
|
710
|
+
partsTotal: null,
|
|
711
|
+
capped
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function planSourceReview(input) {
|
|
715
|
+
const estimateTokens = input.estimateTokens ?? estimateSourceTokens;
|
|
716
|
+
const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;
|
|
717
|
+
const windowTokens = windowIsFallback ? input.fallbackWindowTokens : input.modelWindowTokens;
|
|
718
|
+
let sentChars = 0;
|
|
719
|
+
const entries = input.manifest.sources.map((entry, index) => {
|
|
720
|
+
const ref = input.refs[index] ?? entry.ref;
|
|
721
|
+
const m = measure(entry, ref);
|
|
722
|
+
const base = { index, ref, entry, ...m, chars: sourceEntryChars(entry, ref) ?? 0 };
|
|
723
|
+
if (!isUsable(entry)) {
|
|
724
|
+
return { ...base, status: "unusable", sentChars: 0, sentTokens: 0 };
|
|
725
|
+
}
|
|
726
|
+
if (sourceDelivery(ref) === "context") {
|
|
727
|
+
return { ...base, status: "on_demand", sentChars: 0, sentTokens: 0 };
|
|
728
|
+
}
|
|
729
|
+
if (estimateTokens(sentChars + m.sentChars) > windowTokens) {
|
|
730
|
+
return { ...base, status: "left_out", sentTokens: estimateTokens(m.sentChars) };
|
|
731
|
+
}
|
|
732
|
+
sentChars += m.sentChars;
|
|
733
|
+
return { ...base, status: "included", sentTokens: estimateTokens(m.sentChars) };
|
|
734
|
+
});
|
|
735
|
+
const sentTokens = estimateTokens(sentChars);
|
|
736
|
+
const leftOut = entries.filter((e) => e.status === "left_out");
|
|
737
|
+
const share = windowTokens > 0 ? sentTokens / windowTokens : 0;
|
|
738
|
+
const anythingGoesIn = entries.some((e) => e.status === "included" || e.status === "on_demand");
|
|
739
|
+
const verdict = !anythingGoesIn && leftOut.length === 0 ? "empty" : leftOut.length > 0 ? "too_much" : share >= HEAVY_SHARE ? "heavy" : "fine";
|
|
740
|
+
const kept = entries.filter((e) => e.status !== "left_out").map(
|
|
741
|
+
(e) => createSourceRef(e.ref.resource_type, e.ref.resource_id, {
|
|
742
|
+
representation: e.ref.representation,
|
|
743
|
+
include_segments: e.ref.include_segments,
|
|
744
|
+
delivery: e.ref.delivery,
|
|
745
|
+
max_chars: e.ref.max_chars,
|
|
746
|
+
promote: e.ref.promote,
|
|
747
|
+
exclude: e.ref.exclude
|
|
748
|
+
})
|
|
749
|
+
);
|
|
750
|
+
const grounding = input.base.grounding === "selected" && !kept.some((r) => r.include_segments?.length) ? void 0 : input.base.grounding;
|
|
751
|
+
const sourceSet = createSourceSet(kept, {
|
|
752
|
+
topic: input.base.topic,
|
|
753
|
+
grounding,
|
|
754
|
+
retrieve_query: input.base.retrieve_query,
|
|
755
|
+
target_model_id: input.targetModelId ?? input.base.target_model_id
|
|
756
|
+
});
|
|
757
|
+
return {
|
|
758
|
+
entries,
|
|
759
|
+
chars: entries.filter((e) => e.status === "included").reduce((sum, e) => sum + e.chars, 0),
|
|
760
|
+
sentChars,
|
|
761
|
+
sentTokens,
|
|
762
|
+
windowTokens,
|
|
763
|
+
windowIsFallback,
|
|
764
|
+
verdict,
|
|
765
|
+
share,
|
|
766
|
+
leftOut,
|
|
767
|
+
sourceSet
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// sources/runtime/client.ts
|
|
772
|
+
function marked(options) {
|
|
773
|
+
return {
|
|
774
|
+
bodyCarriedRead: true,
|
|
775
|
+
...options?.organizationId ? { organizationId: options.organizationId } : {},
|
|
776
|
+
...options?.signal ? { signal: options.signal } : {}
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
function createSourcesClient(transport) {
|
|
780
|
+
return {
|
|
781
|
+
manifest: (sourceSet, options) => transport.post("/sources/manifest", { source_set: sourceSet }, marked(options)),
|
|
782
|
+
resolve: (sourceSet, options) => transport.post("/sources/resolve", { source_set: sourceSet }, marked(options)),
|
|
783
|
+
searchParts: (ref, query, options) => transport.post("/sources/parts/search", { source_ref: ref, query }, marked(options))
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
var SourceDoorError = class extends Error {
|
|
787
|
+
status;
|
|
788
|
+
body;
|
|
789
|
+
constructor(status, message, body) {
|
|
790
|
+
super(message);
|
|
791
|
+
this.name = "SourceDoorError";
|
|
792
|
+
this.status = status;
|
|
793
|
+
this.body = body;
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
function refusalMessage(status, body) {
|
|
797
|
+
if (body && typeof body === "object") {
|
|
798
|
+
const record = body;
|
|
799
|
+
const error = record.error;
|
|
800
|
+
if (error && typeof error === "object") {
|
|
801
|
+
const message = error.user_message ?? error.message;
|
|
802
|
+
if (typeof message === "string" && message) return message;
|
|
803
|
+
}
|
|
804
|
+
if (typeof record.detail === "string" && record.detail) return record.detail;
|
|
805
|
+
}
|
|
806
|
+
return `The server answered ${status}.`;
|
|
807
|
+
}
|
|
808
|
+
function createFetchSourcesTransport(options) {
|
|
809
|
+
const base = options.baseUrl.replace(/\/+$/, "");
|
|
810
|
+
return {
|
|
811
|
+
async post(path, body, call) {
|
|
812
|
+
const doFetch = options.fetch ?? fetch;
|
|
813
|
+
const headers = {
|
|
814
|
+
"Content-Type": "application/json",
|
|
815
|
+
...options.headers ? await options.headers() : {}
|
|
816
|
+
};
|
|
817
|
+
if (call.organizationId) headers[options.organizationHeader ?? "X-Organization-Id"] = call.organizationId;
|
|
818
|
+
const response = await doFetch(`${base}${path}`, {
|
|
819
|
+
method: "POST",
|
|
820
|
+
headers,
|
|
821
|
+
body: JSON.stringify(body),
|
|
822
|
+
...call.signal ? { signal: call.signal } : {}
|
|
823
|
+
});
|
|
824
|
+
const text = await response.text();
|
|
825
|
+
let parsed = null;
|
|
826
|
+
try {
|
|
827
|
+
parsed = text ? JSON.parse(text) : null;
|
|
828
|
+
} catch {
|
|
829
|
+
parsed = text;
|
|
830
|
+
}
|
|
831
|
+
if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);
|
|
832
|
+
return parsed;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
|
|
727
837
|
// sources/runtime/controller.ts
|
|
728
838
|
function randomId() {
|
|
729
839
|
const cryptoApi = globalThis.crypto;
|
|
@@ -857,8 +967,8 @@ function createSourceSetController(adapter) {
|
|
|
857
967
|
hasRef: (resourceType, resourceId) => hasSourceRef(store.getState(), resourceType, resourceId),
|
|
858
968
|
liveCount: () => store.getState().cards.length,
|
|
859
969
|
toSourceSet: (options = {}) => selectSourceSet(store.getState(), options),
|
|
860
|
-
applySourceSet(set) {
|
|
861
|
-
commit(applyReviewedSourceSet(store.getState(), set));
|
|
970
|
+
applySourceSet(set, options = {}) {
|
|
971
|
+
commit(applyReviewedSourceSet(store.getState(), set, options.reviewed));
|
|
862
972
|
},
|
|
863
973
|
async manifest() {
|
|
864
974
|
const refs = readySourceRefs(store.getState());
|
|
@@ -1143,20 +1253,45 @@ function createSourceIntake(set, deps) {
|
|
|
1143
1253
|
});
|
|
1144
1254
|
await hold(() => landPaste(id, trimmed, name));
|
|
1145
1255
|
},
|
|
1256
|
+
async addRecordedText(text, name) {
|
|
1257
|
+
const trimmed = text.trim();
|
|
1258
|
+
if (!trimmed) return;
|
|
1259
|
+
const max = deps.maxKeptChars();
|
|
1260
|
+
const kept = max !== null && trimmed.length <= max;
|
|
1261
|
+
const id = set.addPending({
|
|
1262
|
+
kind: "audio",
|
|
1263
|
+
label: name?.trim() || "Recording",
|
|
1264
|
+
origin: "Recording",
|
|
1265
|
+
input: kept ? { text: trimmed, name } : void 0,
|
|
1266
|
+
notes: kept ? void 0 : [NOT_KEPT_FOR_RELOAD]
|
|
1267
|
+
});
|
|
1268
|
+
await hold(() => landPaste(id, trimmed, name));
|
|
1269
|
+
},
|
|
1146
1270
|
async addWebPage(raw) {
|
|
1147
1271
|
const url = /^https?:\/\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;
|
|
1148
1272
|
const id = set.addPending({ kind: "web", label: hostOf(url), origin: url, input: { url } });
|
|
1149
1273
|
await hold(() => landWebPage(id, url));
|
|
1150
1274
|
},
|
|
1151
|
-
|
|
1275
|
+
beginWebPage(raw) {
|
|
1276
|
+
const url = /^https?:\/\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;
|
|
1277
|
+
return set.addPending({ kind: "web", label: hostOf(url), origin: url, input: { url } });
|
|
1278
|
+
},
|
|
1279
|
+
async addScrapedPage(page, pendingId) {
|
|
1152
1280
|
const label = page.title || hostOf(page.url);
|
|
1281
|
+
const cardFor = () => {
|
|
1282
|
+
if (pendingId && set.restart(pendingId)) {
|
|
1283
|
+
set.updateDraft(pendingId, { label, origin: page.url, input: { url: page.url } });
|
|
1284
|
+
return pendingId;
|
|
1285
|
+
}
|
|
1286
|
+
return set.addPending({ kind: "web", label, origin: page.url, input: { url: page.url } });
|
|
1287
|
+
};
|
|
1153
1288
|
if (!page.processedDocumentId) {
|
|
1154
|
-
const id2 =
|
|
1289
|
+
const id2 = cardFor();
|
|
1155
1290
|
await hold(() => landPaste(id2, page.text, label));
|
|
1156
1291
|
return;
|
|
1157
1292
|
}
|
|
1158
1293
|
const pdId = page.processedDocumentId;
|
|
1159
|
-
const id =
|
|
1294
|
+
const id = cardFor();
|
|
1160
1295
|
await hold(async () => {
|
|
1161
1296
|
let notes = [];
|
|
1162
1297
|
try {
|
|
@@ -1231,7 +1366,8 @@ function createSourceIntake(set, deps) {
|
|
|
1231
1366
|
return true;
|
|
1232
1367
|
}
|
|
1233
1368
|
case "audio":
|
|
1234
|
-
void transcribeRecording(card.id, input.fileId
|
|
1369
|
+
if (input.fileId) void transcribeRecording(card.id, input.fileId, card.draft.label);
|
|
1370
|
+
else void landPaste(card.id, (input.text ?? "").trim(), input.name);
|
|
1235
1371
|
return true;
|
|
1236
1372
|
default:
|
|
1237
1373
|
return false;
|