@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
|
@@ -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,6 +76,7 @@ __export(runtime_exports, {
|
|
|
73
76
|
readySourceRefs: () => readySourceRefs,
|
|
74
77
|
registeredFileEdge: () => registeredFileEdge,
|
|
75
78
|
reloadedCard: () => reloadedCard,
|
|
79
|
+
rememberPickedParts: () => rememberPickedParts,
|
|
76
80
|
removeCard: () => removeCard,
|
|
77
81
|
renderedPartChars: () => renderedPartChars,
|
|
78
82
|
restartCard: () => restartCard,
|
|
@@ -87,7 +91,11 @@ __export(runtime_exports, {
|
|
|
87
91
|
setSourceTopic: () => setSourceTopic,
|
|
88
92
|
settleCard: () => settleCard,
|
|
89
93
|
sourceAttachTargets: () => sourceAttachTargets,
|
|
94
|
+
sourceCardChars: () => sourceCardChars,
|
|
95
|
+
sourceCardMeasuredState: () => sourceCardMeasuredState,
|
|
96
|
+
sourceCardState: () => sourceCardState,
|
|
90
97
|
sourceDelivery: () => sourceDelivery,
|
|
98
|
+
sourceEntryChars: () => sourceEntryChars,
|
|
91
99
|
sourceKey: () => sourceKey,
|
|
92
100
|
sourceRecoveryGuards: () => sourceRecoveryGuards,
|
|
93
101
|
sourceRoomLeft: () => sourceRoomLeft,
|
|
@@ -110,12 +118,12 @@ function deliveryPatch(delivery) {
|
|
|
110
118
|
var DELIVERY_WORDS = {
|
|
111
119
|
direct: {
|
|
112
120
|
label: "Include the text",
|
|
113
|
-
hint: "
|
|
121
|
+
hint: "Sent in full",
|
|
114
122
|
summary: "Text included"
|
|
115
123
|
},
|
|
116
124
|
context: {
|
|
117
125
|
label: "Let the AI look it up",
|
|
118
|
-
hint: "
|
|
126
|
+
hint: "Read as needed",
|
|
119
127
|
summary: "Looked up when needed"
|
|
120
128
|
}
|
|
121
129
|
};
|
|
@@ -192,7 +200,7 @@ function resumableInput(draft) {
|
|
|
192
200
|
case "youtube":
|
|
193
201
|
return input.url?.trim() ? input : null;
|
|
194
202
|
case "audio":
|
|
195
|
-
return input.fileId ? input : null;
|
|
203
|
+
return input.fileId || input.text?.trim() ? input : null;
|
|
196
204
|
default:
|
|
197
205
|
return null;
|
|
198
206
|
}
|
|
@@ -208,12 +216,12 @@ function reloadedCard(draft, status) {
|
|
|
208
216
|
return { action: "lost", sentence: RELOADED_WHILE_ADDING };
|
|
209
217
|
}
|
|
210
218
|
var MAX_KEPT_TEXT_KNOB = { feature: "sources", key: "max_kept_draft_chars" };
|
|
211
|
-
var NOT_KEPT_FOR_RELOAD = "Too large to
|
|
219
|
+
var NOT_KEPT_FOR_RELOAD = "Too large to restore if the page reloads before it is added.";
|
|
212
220
|
var WAITING_FOR_ORGANIZATION = "Waiting for an organization \u2014 choose one and this continues by itself.";
|
|
213
221
|
var KEEP_WAITING_FOR_ORGANIZATION = "Read. Waiting for an organization to keep it \u2014 choose one and it is kept by itself.";
|
|
214
222
|
|
|
215
223
|
// sources/runtime/fileSource.ts
|
|
216
|
-
var UNREADABLE = "
|
|
224
|
+
var UNREADABLE = "Can't read this file \u2014 add a PDF, Word or text copy.";
|
|
217
225
|
function nextFileStep(status, ctx) {
|
|
218
226
|
const pdId = status?.processed_document_id ?? null;
|
|
219
227
|
if (pdId) return { do: "keep", processedDocumentId: pdId };
|
|
@@ -221,7 +229,7 @@ function nextFileStep(status, ctx) {
|
|
|
221
229
|
if (status?.state === "failed")
|
|
222
230
|
return {
|
|
223
231
|
do: "unreadable",
|
|
224
|
-
reason: status.error?.message ? `
|
|
232
|
+
reason: status.error?.message ? `Can't read this file: ${status.error.message}. Add it again.` : UNREADABLE
|
|
225
233
|
};
|
|
226
234
|
if (!ctx.started) return { do: "start" };
|
|
227
235
|
return { do: "unreadable", reason: UNREADABLE };
|
|
@@ -337,191 +345,10 @@ function totalChars(value) {
|
|
|
337
345
|
return value.sources.filter((entry) => entry.state === "ready" || entry.state === "processing").reduce((sum, entry) => sum + manifestEntryChars(entry), 0);
|
|
338
346
|
}
|
|
339
347
|
|
|
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
348
|
// sources/runtime/state.ts
|
|
524
349
|
var EMPTY_SOURCE_SET_STATE = Object.freeze({ cards: Object.freeze([]), topic: "" });
|
|
350
|
+
var PARTS_MATCHED_BY_PAGE = "The clean version is ready \u2014 your parts were matched to it by page.";
|
|
351
|
+
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
352
|
var SAME_SOURCE_AGAIN = "You added this again \u2014 it is the same Source, so it is listed once.";
|
|
526
353
|
function isSourceDraft(value) {
|
|
527
354
|
return !!value && typeof value === "object" && typeof value.kind === "string" && typeof value.label === "string";
|
|
@@ -588,7 +415,7 @@ function settleCard(state, id, patch, options = {}) {
|
|
|
588
415
|
}));
|
|
589
416
|
}
|
|
590
417
|
function failCard(state, id, sentence) {
|
|
591
|
-
return replaceCard(state, id, (c) => ({ ...c, status: "error", error: sentence }));
|
|
418
|
+
return replaceCard(state, id, (c) => ({ ...c, status: "error", error: sentence, manifest: null }));
|
|
592
419
|
}
|
|
593
420
|
function restartCard(state, id) {
|
|
594
421
|
return replaceCard(state, id, (c) => ({ ...c, status: "resolving", error: null }));
|
|
@@ -604,7 +431,68 @@ function updateCardRef(state, id, options) {
|
|
|
604
431
|
return replaceCard(state, id, (c) => {
|
|
605
432
|
if (!c.draft.ref) return c;
|
|
606
433
|
const ref = createSourceRef(c.draft.ref.resource_type, c.draft.ref.resource_id, { ...c.draft.ref, ...options });
|
|
607
|
-
return { ...c, draft: { ...c.draft, ref } };
|
|
434
|
+
return rememberPickedParts({ ...c, draft: { ...c.draft, ref } });
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
function rememberPickedParts(card) {
|
|
438
|
+
const ids = card.draft.ref?.include_segments ?? [];
|
|
439
|
+
if (ids.length === 0) {
|
|
440
|
+
return card.draft.pickedParts === void 0 ? card : { ...card, draft: { ...card.draft, pickedParts: void 0 } };
|
|
441
|
+
}
|
|
442
|
+
const segments = card.manifest?.segments ?? [];
|
|
443
|
+
const known = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));
|
|
444
|
+
const picked = [];
|
|
445
|
+
for (const id of ids) {
|
|
446
|
+
const segment = segments.find((s) => s.id === id);
|
|
447
|
+
if (segment) {
|
|
448
|
+
const pages = partPages(segment);
|
|
449
|
+
picked.push({ id, label: segment.label, ...pages ? { pages } : {} });
|
|
450
|
+
} else {
|
|
451
|
+
const before = known.get(id);
|
|
452
|
+
if (before) picked.push(before);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return { ...card, draft: { ...card.draft, pickedParts: picked.length ? picked : void 0 } };
|
|
456
|
+
}
|
|
457
|
+
function withNote(notes, note, drop = []) {
|
|
458
|
+
const kept = (notes ?? []).filter((n) => n !== note && !drop.includes(n));
|
|
459
|
+
return [...kept, note];
|
|
460
|
+
}
|
|
461
|
+
function carryPickedParts(card, entry) {
|
|
462
|
+
const ref = card.draft.ref;
|
|
463
|
+
const picked = ref?.include_segments ?? [];
|
|
464
|
+
const segments = entry.segments ?? [];
|
|
465
|
+
if (!ref || picked.length === 0 || segments.length === 0) return card;
|
|
466
|
+
const ids = new Set(segments.map((s) => s.id));
|
|
467
|
+
const stale = picked.filter((id) => !ids.has(id));
|
|
468
|
+
if (stale.length === 0) return card;
|
|
469
|
+
const remembered = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));
|
|
470
|
+
const oldSegments = card.manifest?.segments ?? [];
|
|
471
|
+
const spans = [];
|
|
472
|
+
let unknown = 0;
|
|
473
|
+
for (const id of stale) {
|
|
474
|
+
const old = oldSegments.find((s) => s.id === id);
|
|
475
|
+
const pages = remembered.get(id)?.pages ?? (old ? partPages(old) : null);
|
|
476
|
+
if (pages) spans.push(pages);
|
|
477
|
+
else unknown += 1;
|
|
478
|
+
}
|
|
479
|
+
const keep = new Set(picked.filter((id) => ids.has(id)));
|
|
480
|
+
for (const segment of segments) {
|
|
481
|
+
const pages = partPages(segment);
|
|
482
|
+
if (pages && spans.some(([from, to]) => pages[0] <= to && pages[1] >= from)) keep.add(segment.id);
|
|
483
|
+
}
|
|
484
|
+
const nextIds = segments.filter((s) => keep.has(s.id)).map((s) => s.id);
|
|
485
|
+
const matched = unknown === 0 && nextIds.length > 0;
|
|
486
|
+
const nextRef = createSourceRef(ref.resource_type, ref.resource_id, {
|
|
487
|
+
...ref,
|
|
488
|
+
include_segments: matched ? nextIds : void 0
|
|
489
|
+
});
|
|
490
|
+
const note = matched ? PARTS_MATCHED_BY_PAGE : PARTS_NOT_MATCHED;
|
|
491
|
+
const other = matched ? PARTS_NOT_MATCHED : PARTS_MATCHED_BY_PAGE;
|
|
492
|
+
return rememberPickedParts({
|
|
493
|
+
...card,
|
|
494
|
+
manifest: entry,
|
|
495
|
+
draft: { ...card.draft, ref: nextRef, notes: withNote(card.draft.notes, note, [other]) }
|
|
608
496
|
});
|
|
609
497
|
}
|
|
610
498
|
function setCardWaitForClean(state, id, wait) {
|
|
@@ -620,7 +508,7 @@ function applyReviewedSourceSet(state, set) {
|
|
|
620
508
|
if (!ref) continue;
|
|
621
509
|
const match = set.sources.find((r) => sameSourceRef(r, ref));
|
|
622
510
|
if (!match) continue;
|
|
623
|
-
next = replaceCard(next, card.id, (c) => ({ ...c, draft: { ...c.draft, ref: match } }));
|
|
511
|
+
next = replaceCard(next, card.id, (c) => rememberPickedParts({ ...c, draft: { ...c.draft, ref: match } }));
|
|
624
512
|
}
|
|
625
513
|
return set.topic !== void 0 ? setSourceTopic(next, set.topic) : next;
|
|
626
514
|
}
|
|
@@ -630,7 +518,13 @@ function applyManifest(state, manifest) {
|
|
|
630
518
|
const ref = card.draft.ref;
|
|
631
519
|
if (!ref || card.status !== "ready") continue;
|
|
632
520
|
const entry = manifest.sources.find((e) => sameSourceRef(e.ref, ref));
|
|
633
|
-
if (entry)
|
|
521
|
+
if (!entry) continue;
|
|
522
|
+
next = replaceCard(next, card.id, (c) => {
|
|
523
|
+
const carried = carryPickedParts(c, entry);
|
|
524
|
+
if (carried !== c) return carried;
|
|
525
|
+
const measured = { ...c, manifest: entry };
|
|
526
|
+
return c.draft.ref?.include_segments?.length && !c.draft.pickedParts ? rememberPickedParts(measured) : measured;
|
|
527
|
+
});
|
|
634
528
|
}
|
|
635
529
|
return next;
|
|
636
530
|
}
|
|
@@ -703,6 +597,27 @@ function selectTotalChars(state) {
|
|
|
703
597
|
model_context_tokens: null
|
|
704
598
|
});
|
|
705
599
|
}
|
|
600
|
+
function sourceEntryChars(entry, ref) {
|
|
601
|
+
if (entry.state !== "ready" && entry.state !== "processing") return null;
|
|
602
|
+
return totalChars({
|
|
603
|
+
__kind: "source_manifest",
|
|
604
|
+
sources: [{ ...entry, ref }],
|
|
605
|
+
total_chars: 0,
|
|
606
|
+
estimated_tokens: 0,
|
|
607
|
+
model_context_tokens: null
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
function sourceCardChars(card) {
|
|
611
|
+
return card.manifest && card.draft.ref ? sourceEntryChars(card.manifest, card.draft.ref) : null;
|
|
612
|
+
}
|
|
613
|
+
function sourceCardState(card) {
|
|
614
|
+
if (card.status === "pending" || card.status === "resolving") return "adding";
|
|
615
|
+
if (card.status === "error") return card.error === WAITING_FOR_ORGANIZATION ? "waiting_for_organization" : "failed";
|
|
616
|
+
return card.manifest?.state ?? "unmeasured";
|
|
617
|
+
}
|
|
618
|
+
function sourceCardMeasuredState(card) {
|
|
619
|
+
return card.status === "ready" ? card.manifest?.state ?? null : null;
|
|
620
|
+
}
|
|
706
621
|
function selectSettled(state) {
|
|
707
622
|
return state.cards.every((c) => c.status === "ready");
|
|
708
623
|
}
|
|
@@ -724,6 +639,190 @@ function withDisplayNames(resolved, cards) {
|
|
|
724
639
|
};
|
|
725
640
|
}
|
|
726
641
|
|
|
642
|
+
// sources/runtime/plan.ts
|
|
643
|
+
var HEAVY_SHARE = 0.7;
|
|
644
|
+
var PAGE_SUFFIX = (page) => page !== void 0 && page > 0 ? ` (page ${page})` : "";
|
|
645
|
+
function renderedPartChars(segment, chars) {
|
|
646
|
+
return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;
|
|
647
|
+
}
|
|
648
|
+
function capParts(parts, maxChars) {
|
|
649
|
+
if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };
|
|
650
|
+
const kept = [];
|
|
651
|
+
let used = 0;
|
|
652
|
+
for (const seg of parts) {
|
|
653
|
+
if (used + seg.chars <= maxChars) {
|
|
654
|
+
kept.push({ seg, chars: seg.chars });
|
|
655
|
+
used += seg.chars;
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
const room = maxChars - used;
|
|
659
|
+
if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });
|
|
660
|
+
return { kept, capped: true };
|
|
661
|
+
}
|
|
662
|
+
return { kept, capped: false };
|
|
663
|
+
}
|
|
664
|
+
function chosenForm(entry, ref) {
|
|
665
|
+
const key = ref.representation ?? entry.default_form;
|
|
666
|
+
return entry.forms.find((f) => f.form === key) ?? entry.forms.find((f) => f.form === entry.default_form) ?? null;
|
|
667
|
+
}
|
|
668
|
+
function isUsable(entry) {
|
|
669
|
+
return entry.state === "ready" || entry.state === "processing";
|
|
670
|
+
}
|
|
671
|
+
function measure(entry, ref) {
|
|
672
|
+
const form = chosenForm(entry, ref);
|
|
673
|
+
const formChars = form?.chars ?? 0;
|
|
674
|
+
const formLabel = form?.label ?? "Text";
|
|
675
|
+
const segments = entry.segments ?? null;
|
|
676
|
+
if (segments && segments.length > 0) {
|
|
677
|
+
const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;
|
|
678
|
+
const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;
|
|
679
|
+
const { kept, capped: capped2 } = capParts(chosen, ref.max_chars);
|
|
680
|
+
const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);
|
|
681
|
+
const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;
|
|
682
|
+
return {
|
|
683
|
+
formChars,
|
|
684
|
+
formLabel,
|
|
685
|
+
sentChars,
|
|
686
|
+
exact: true,
|
|
687
|
+
partsSent: kept.length,
|
|
688
|
+
partsTotal: segments.length,
|
|
689
|
+
capped: capped2
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
const capped = ref.max_chars !== void 0 && formChars > ref.max_chars;
|
|
693
|
+
return {
|
|
694
|
+
formChars,
|
|
695
|
+
formLabel,
|
|
696
|
+
sentChars: capped ? ref.max_chars ?? formChars : formChars,
|
|
697
|
+
exact: false,
|
|
698
|
+
partsSent: null,
|
|
699
|
+
partsTotal: null,
|
|
700
|
+
capped
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
function planSourceReview(input) {
|
|
704
|
+
const estimateTokens = input.estimateTokens ?? estimateSourceTokens;
|
|
705
|
+
const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;
|
|
706
|
+
const windowTokens = windowIsFallback ? input.fallbackWindowTokens : input.modelWindowTokens;
|
|
707
|
+
let sentChars = 0;
|
|
708
|
+
const entries = input.manifest.sources.map((entry, index) => {
|
|
709
|
+
const ref = input.refs[index] ?? entry.ref;
|
|
710
|
+
const m = measure(entry, ref);
|
|
711
|
+
const base = { index, ref, entry, ...m, chars: sourceEntryChars(entry, ref) ?? 0 };
|
|
712
|
+
if (!isUsable(entry)) {
|
|
713
|
+
return { ...base, status: "unusable", sentChars: 0, sentTokens: 0 };
|
|
714
|
+
}
|
|
715
|
+
if (sourceDelivery(ref) === "context") {
|
|
716
|
+
return { ...base, status: "on_demand", sentChars: 0, sentTokens: 0 };
|
|
717
|
+
}
|
|
718
|
+
if (estimateTokens(sentChars + m.sentChars) > windowTokens) {
|
|
719
|
+
return { ...base, status: "left_out", sentTokens: estimateTokens(m.sentChars) };
|
|
720
|
+
}
|
|
721
|
+
sentChars += m.sentChars;
|
|
722
|
+
return { ...base, status: "included", sentTokens: estimateTokens(m.sentChars) };
|
|
723
|
+
});
|
|
724
|
+
const sentTokens = estimateTokens(sentChars);
|
|
725
|
+
const leftOut = entries.filter((e) => e.status === "left_out");
|
|
726
|
+
const share = windowTokens > 0 ? sentTokens / windowTokens : 0;
|
|
727
|
+
const anythingGoesIn = entries.some((e) => e.status === "included" || e.status === "on_demand");
|
|
728
|
+
const verdict = !anythingGoesIn && leftOut.length === 0 ? "empty" : leftOut.length > 0 ? "too_much" : share >= HEAVY_SHARE ? "heavy" : "fine";
|
|
729
|
+
const kept = entries.filter((e) => e.status !== "left_out").map(
|
|
730
|
+
(e) => createSourceRef(e.ref.resource_type, e.ref.resource_id, {
|
|
731
|
+
representation: e.ref.representation,
|
|
732
|
+
include_segments: e.ref.include_segments,
|
|
733
|
+
delivery: e.ref.delivery,
|
|
734
|
+
max_chars: e.ref.max_chars,
|
|
735
|
+
promote: e.ref.promote,
|
|
736
|
+
exclude: e.ref.exclude
|
|
737
|
+
})
|
|
738
|
+
);
|
|
739
|
+
const grounding = input.base.grounding === "selected" && !kept.some((r) => r.include_segments?.length) ? void 0 : input.base.grounding;
|
|
740
|
+
const sourceSet = createSourceSet(kept, {
|
|
741
|
+
topic: input.base.topic,
|
|
742
|
+
grounding,
|
|
743
|
+
retrieve_query: input.base.retrieve_query,
|
|
744
|
+
target_model_id: input.targetModelId ?? input.base.target_model_id
|
|
745
|
+
});
|
|
746
|
+
return {
|
|
747
|
+
entries,
|
|
748
|
+
chars: entries.filter((e) => e.status === "included").reduce((sum, e) => sum + e.chars, 0),
|
|
749
|
+
sentChars,
|
|
750
|
+
sentTokens,
|
|
751
|
+
windowTokens,
|
|
752
|
+
windowIsFallback,
|
|
753
|
+
verdict,
|
|
754
|
+
share,
|
|
755
|
+
leftOut,
|
|
756
|
+
sourceSet
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// sources/runtime/client.ts
|
|
761
|
+
function marked(options) {
|
|
762
|
+
return {
|
|
763
|
+
bodyCarriedRead: true,
|
|
764
|
+
...options?.organizationId ? { organizationId: options.organizationId } : {},
|
|
765
|
+
...options?.signal ? { signal: options.signal } : {}
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
function createSourcesClient(transport) {
|
|
769
|
+
return {
|
|
770
|
+
manifest: (sourceSet, options) => transport.post("/sources/manifest", { source_set: sourceSet }, marked(options)),
|
|
771
|
+
resolve: (sourceSet, options) => transport.post("/sources/resolve", { source_set: sourceSet }, marked(options)),
|
|
772
|
+
searchParts: (ref, query, options) => transport.post("/sources/parts/search", { source_ref: ref, query }, marked(options))
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
var SourceDoorError = class extends Error {
|
|
776
|
+
status;
|
|
777
|
+
body;
|
|
778
|
+
constructor(status, message, body) {
|
|
779
|
+
super(message);
|
|
780
|
+
this.name = "SourceDoorError";
|
|
781
|
+
this.status = status;
|
|
782
|
+
this.body = body;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
function refusalMessage(status, body) {
|
|
786
|
+
if (body && typeof body === "object") {
|
|
787
|
+
const record = body;
|
|
788
|
+
const error = record.error;
|
|
789
|
+
if (error && typeof error === "object") {
|
|
790
|
+
const message = error.user_message ?? error.message;
|
|
791
|
+
if (typeof message === "string" && message) return message;
|
|
792
|
+
}
|
|
793
|
+
if (typeof record.detail === "string" && record.detail) return record.detail;
|
|
794
|
+
}
|
|
795
|
+
return `The server answered ${status}.`;
|
|
796
|
+
}
|
|
797
|
+
function createFetchSourcesTransport(options) {
|
|
798
|
+
const base = options.baseUrl.replace(/\/+$/, "");
|
|
799
|
+
return {
|
|
800
|
+
async post(path, body, call) {
|
|
801
|
+
const doFetch = options.fetch ?? fetch;
|
|
802
|
+
const headers = {
|
|
803
|
+
"Content-Type": "application/json",
|
|
804
|
+
...options.headers ? await options.headers() : {}
|
|
805
|
+
};
|
|
806
|
+
if (call.organizationId) headers[options.organizationHeader ?? "X-Organization-Id"] = call.organizationId;
|
|
807
|
+
const response = await doFetch(`${base}${path}`, {
|
|
808
|
+
method: "POST",
|
|
809
|
+
headers,
|
|
810
|
+
body: JSON.stringify(body),
|
|
811
|
+
...call.signal ? { signal: call.signal } : {}
|
|
812
|
+
});
|
|
813
|
+
const text = await response.text();
|
|
814
|
+
let parsed = null;
|
|
815
|
+
try {
|
|
816
|
+
parsed = text ? JSON.parse(text) : null;
|
|
817
|
+
} catch {
|
|
818
|
+
parsed = text;
|
|
819
|
+
}
|
|
820
|
+
if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);
|
|
821
|
+
return parsed;
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
|
|
727
826
|
// sources/runtime/controller.ts
|
|
728
827
|
function randomId() {
|
|
729
828
|
const cryptoApi = globalThis.crypto;
|
|
@@ -1143,20 +1242,45 @@ function createSourceIntake(set, deps) {
|
|
|
1143
1242
|
});
|
|
1144
1243
|
await hold(() => landPaste(id, trimmed, name));
|
|
1145
1244
|
},
|
|
1245
|
+
async addRecordedText(text, name) {
|
|
1246
|
+
const trimmed = text.trim();
|
|
1247
|
+
if (!trimmed) return;
|
|
1248
|
+
const max = deps.maxKeptChars();
|
|
1249
|
+
const kept = max !== null && trimmed.length <= max;
|
|
1250
|
+
const id = set.addPending({
|
|
1251
|
+
kind: "audio",
|
|
1252
|
+
label: name?.trim() || "Recording",
|
|
1253
|
+
origin: "Recording",
|
|
1254
|
+
input: kept ? { text: trimmed, name } : void 0,
|
|
1255
|
+
notes: kept ? void 0 : [NOT_KEPT_FOR_RELOAD]
|
|
1256
|
+
});
|
|
1257
|
+
await hold(() => landPaste(id, trimmed, name));
|
|
1258
|
+
},
|
|
1146
1259
|
async addWebPage(raw) {
|
|
1147
1260
|
const url = /^https?:\/\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;
|
|
1148
1261
|
const id = set.addPending({ kind: "web", label: hostOf(url), origin: url, input: { url } });
|
|
1149
1262
|
await hold(() => landWebPage(id, url));
|
|
1150
1263
|
},
|
|
1151
|
-
|
|
1264
|
+
beginWebPage(raw) {
|
|
1265
|
+
const url = /^https?:\/\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;
|
|
1266
|
+
return set.addPending({ kind: "web", label: hostOf(url), origin: url, input: { url } });
|
|
1267
|
+
},
|
|
1268
|
+
async addScrapedPage(page, pendingId) {
|
|
1152
1269
|
const label = page.title || hostOf(page.url);
|
|
1270
|
+
const cardFor = () => {
|
|
1271
|
+
if (pendingId && set.restart(pendingId)) {
|
|
1272
|
+
set.updateDraft(pendingId, { label, origin: page.url, input: { url: page.url } });
|
|
1273
|
+
return pendingId;
|
|
1274
|
+
}
|
|
1275
|
+
return set.addPending({ kind: "web", label, origin: page.url, input: { url: page.url } });
|
|
1276
|
+
};
|
|
1153
1277
|
if (!page.processedDocumentId) {
|
|
1154
|
-
const id2 =
|
|
1278
|
+
const id2 = cardFor();
|
|
1155
1279
|
await hold(() => landPaste(id2, page.text, label));
|
|
1156
1280
|
return;
|
|
1157
1281
|
}
|
|
1158
1282
|
const pdId = page.processedDocumentId;
|
|
1159
|
-
const id =
|
|
1283
|
+
const id = cardFor();
|
|
1160
1284
|
await hold(async () => {
|
|
1161
1285
|
let notes = [];
|
|
1162
1286
|
try {
|
|
@@ -1231,7 +1355,8 @@ function createSourceIntake(set, deps) {
|
|
|
1231
1355
|
return true;
|
|
1232
1356
|
}
|
|
1233
1357
|
case "audio":
|
|
1234
|
-
void transcribeRecording(card.id, input.fileId
|
|
1358
|
+
if (input.fileId) void transcribeRecording(card.id, input.fileId, card.draft.label);
|
|
1359
|
+
else void landPaste(card.id, (input.text ?? "").trim(), input.name);
|
|
1235
1360
|
return true;
|
|
1236
1361
|
default:
|
|
1237
1362
|
return false;
|