@happyvertical/smrt-ingestion 0.60.16 → 0.60.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/manifest.json +1 -1
- package/dist/models.js +1 -1
- package/dist/models.js.map +1 -1
- package/dist/smrt-knowledge.json +3 -3
- package/dist/svelte/components/ActionReview.svelte +40 -3
- package/dist/svelte/components/ArgumentFields.svelte +19 -4
- package/dist/svelte/components/EvidenceViewer.svelte +41 -3
- package/dist/svelte/components/InboxView.svelte +57 -5
- package/dist/svelte/components/ReviewView.svelte +59 -4
- package/dist/svelte/components/TriageView.svelte +71 -8
- package/package.json +17 -17
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-ingestion",
|
|
6
|
-
"packageVersion": "0.60.
|
|
6
|
+
"packageVersion": "0.60.18",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
10
|
+
"manifest": "ca62631c0415eed45fbfab0ad18cdfdc50b6a948065a87f152573f7451625445",
|
|
11
|
+
"packageJson": "a395d0d78232c6dfdf1402e5370bf5cdc45dc301493dbe91184fd9c71c2f3d67",
|
|
12
12
|
"agents": "dea14442054ec1de798cba9be1fbdd955f44b0e4672639cbf3db8101d290c1fb",
|
|
13
13
|
"moduleDoc:agents/execution.md": "8a7c3384e90a41eb0c6f89e5bdafddd57db5e93f0c015849c764716b86ced97f",
|
|
14
14
|
"moduleDoc:README.md": "d4dfdb4a4c1af3e1def6cf038e315e5bf66ab8d5942dee12a014527737a69748",
|
|
@@ -263,7 +263,7 @@ function choose(field: string, id: string) {
|
|
|
263
263
|
{#if action.origin === 'reviewer-selected'}<p>{t(M['ingestion.reviewerSelected'])}</p>{/if}
|
|
264
264
|
<p data-testid="review-state">{t(M['ingestion.state'])}: {stateKey ? t(M[stateKey]) : action.review.state}</p>
|
|
265
265
|
{#if action.args !== undefined}
|
|
266
|
-
<h4>{t(M['ingestion.effects'])}</h4>{#if effects.length}<dl class="
|
|
266
|
+
<h4>{t(M['ingestion.effects'])}</h4>{#if effects.length}<dl class="smrt-action-review__effects" data-smrt-part="group" data-testid="effects">{#each effects as [name, value] (name)}<dt>{name}</dt><dd>{value}</dd>{/each}</dl>{/if}
|
|
267
267
|
<ArgumentFields bind:value={args} label={t(M['ingestion.args'])} catalog={fields} {candidates} {evidence} readonly={!editable || !!action.plan} {host} {itemId} {deny} />
|
|
268
268
|
{#if editable}
|
|
269
269
|
{#if missing.length}<h4>{t(M['ingestion.missing'])}</h4><ul>{#each missing as name (name)}<li>{name}</li>{/each}</ul>{/if}
|
|
@@ -271,7 +271,7 @@ function choose(field: string, id: string) {
|
|
|
271
271
|
{#if !action.plan && catalog && !drawsFields}<CandidatePicker {host} {itemId} {catalog} {deny} onchoose={choose} />{/if}
|
|
272
272
|
{#if dirty}<p>{t(M['ingestion.reviewAgain'])}</p>{/if}
|
|
273
273
|
{#if invalid}<p role="alert">{t(M['ingestion.invalid'])}</p>{/if}
|
|
274
|
-
<div class="
|
|
274
|
+
<div class="smrt-action-review__controls" data-smrt-part="actions">{#if waiting && !resolved}<Button disabled={dirty} onclick={() => decide('approve')}>{t(M['ingestion.approve'])}</Button>{/if}{#if !action.plan && !resolved}<Button disabled={!dirty} onclick={saveEdits}>{t(M['ingestion.correct'])}</Button>{/if}{#if waiting}<Button onclick={() => decide('reject')}>{t(M['ingestion.reject'])}</Button>{#if !resolved}<Button onclick={() => decide('defer')}>{t(M['ingestion.defer'])}</Button>{/if}{/if}</div>
|
|
275
275
|
{/if}
|
|
276
276
|
{#if action.plan?.stepIndex === 0 && action.plan.args && host.editPlan && planEditable && !resolved}
|
|
277
277
|
<Textarea aria-label={t(M['ingestion.planArgs'])} bind:value={planArgs} rows={8} />
|
|
@@ -298,7 +298,44 @@ function choose(field: string, id: string) {
|
|
|
298
298
|
</article>
|
|
299
299
|
<style>
|
|
300
300
|
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
301
|
+
@layer smrt.structure {
|
|
302
|
+
article {
|
|
303
|
+
min-width:0;
|
|
304
|
+
overflow-wrap:anywhere;
|
|
305
|
+
padding-block:1rem;
|
|
306
|
+
}
|
|
307
|
+
.smrt-action-review__controls {
|
|
308
|
+
display:flex;
|
|
309
|
+
flex-wrap:wrap;
|
|
310
|
+
gap:.5rem;
|
|
311
|
+
margin-block:.75rem;
|
|
312
|
+
}
|
|
313
|
+
pre {
|
|
314
|
+
white-space:pre-wrap;
|
|
315
|
+
overflow-wrap:anywhere;
|
|
316
|
+
}
|
|
317
|
+
fieldset {
|
|
318
|
+
margin-block:1rem;
|
|
319
|
+
min-width:0;
|
|
320
|
+
}
|
|
321
|
+
.smrt-action-review__effects {
|
|
322
|
+
display:grid;
|
|
323
|
+
grid-template-columns:minmax(0,max-content) minmax(0,1fr);
|
|
324
|
+
gap:.25rem 1rem;
|
|
325
|
+
margin-block:.5rem;
|
|
326
|
+
}
|
|
327
|
+
.smrt-action-review__effects dd {
|
|
328
|
+
margin:0;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
301
332
|
@layer smrt.theme {
|
|
302
|
-
article
|
|
333
|
+
article {
|
|
334
|
+
border-block-start:var(--smrt-hairline);
|
|
335
|
+
}
|
|
336
|
+
.smrt-action-review__effects dt {
|
|
337
|
+
font-weight:600;
|
|
338
|
+
}
|
|
303
339
|
}
|
|
340
|
+
|
|
304
341
|
</style>
|
|
@@ -134,13 +134,13 @@ function text(input: unknown): string {
|
|
|
134
134
|
}
|
|
135
135
|
</script>
|
|
136
136
|
{#if fields.length}
|
|
137
|
-
<fieldset class="argument-
|
|
137
|
+
<fieldset class="smrt-argument-fields__root" data-testid="argument-fields" disabled={readonly} data-smrt-component="ArgumentFields">
|
|
138
138
|
<legend>{t(M['ingestion.fields'])}</legend>
|
|
139
139
|
{#if !parsed}<p role="status">{t(M['ingestion.fieldsUnavailable'])}</p>{/if}
|
|
140
140
|
{#each fields as field (field.name)}
|
|
141
141
|
{@const current = parsed?.[field.name]}
|
|
142
142
|
{@const name = field.required ? `${field.title} *` : field.title}
|
|
143
|
-
<div class="field" data-field={field.name}>
|
|
143
|
+
<div class="smrt-argument-fields__field" data-smrt-part="field" data-field={field.name}>
|
|
144
144
|
{#if field.kind === 'candidate'}
|
|
145
145
|
{@const options = (found[field.name] ?? []).map((entry) => ({ value: entry.id, label: entry.label }))}
|
|
146
146
|
<Combobox label={name} {options} value={text(current)} valueLabel={candidateLabel(field.model, current) ?? text(current)} filter={false} disabled={readonly || !parsed} busy={!!searching[field.name]} status={searching[field.name] ? t(M['ingestion.searching']) : options.length ? undefined : t(M['ingestion.noMatches'])} onquery={(query) => search(field, query)} onvaluechange={(id) => choose(field, id)} />
|
|
@@ -162,7 +162,7 @@ function text(input: unknown): string {
|
|
|
162
162
|
</div>
|
|
163
163
|
{/each}
|
|
164
164
|
</fieldset>
|
|
165
|
-
<details class="
|
|
165
|
+
<details class="smrt-argument-fields__advanced" data-testid="advanced-arguments" data-smrt-component="ArgumentFields"><summary>{t(M['ingestion.advanced'])}</summary>
|
|
166
166
|
<Textarea aria-label={label} bind:value {readonly} {rows} />
|
|
167
167
|
</details>
|
|
168
168
|
{:else}
|
|
@@ -170,7 +170,22 @@ function text(input: unknown): string {
|
|
|
170
170
|
{/if}
|
|
171
171
|
<style>
|
|
172
172
|
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
173
|
+
@layer smrt.structure {
|
|
174
|
+
.smrt-argument-fields__root {
|
|
175
|
+
display:grid;
|
|
176
|
+
gap:.75rem;
|
|
177
|
+
min-width:0;
|
|
178
|
+
margin-block:.5rem;
|
|
179
|
+
}
|
|
180
|
+
.smrt-argument-fields__field {
|
|
181
|
+
min-width:0;
|
|
182
|
+
}
|
|
183
|
+
.smrt-argument-fields__advanced {
|
|
184
|
+
margin-block:.5rem;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
173
188
|
@layer smrt.theme {
|
|
174
|
-
.argument-fields{display:grid;gap:.75rem;min-width:0;margin-block:.5rem}.field{min-width:0}.advanced{margin-block:.5rem}
|
|
175
189
|
}
|
|
190
|
+
|
|
176
191
|
</style>
|
|
@@ -61,7 +61,7 @@ function turn(id: string, offset: number) {
|
|
|
61
61
|
<section data-testid="evidence-viewer" aria-label={t(M['ingestion.evidence'])} data-smrt-component="EvidenceViewer">
|
|
62
62
|
<h2>{t(M['ingestion.evidence'])}</h2>
|
|
63
63
|
{#if layout === 'pager' && evidence.length > 1 && position >= 0}
|
|
64
|
-
<div class="
|
|
64
|
+
<div class="smrt-evidence-viewer__pager" data-smrt-part="nav" data-testid="evidence-pager"><Button disabled={position <= 0} onclick={() => step(-1)}>{t(M['ingestion.previousOriginal'])}</Button><p role="status">{t(M['ingestion.originalOf'], { index: position + 1, count: evidence.length })}</p><Button disabled={position >= evidence.length - 1} onclick={() => step(1)}>{t(M['ingestion.nextOriginal'])}</Button></div>
|
|
65
65
|
{/if}
|
|
66
66
|
{#each shown as view (view.evidence.id)}
|
|
67
67
|
{@const url = evidenceUrl(view.viewUrl)}
|
|
@@ -72,7 +72,7 @@ function turn(id: string, offset: number) {
|
|
|
72
72
|
{#if view.evidence.mediaType.startsWith('image/')}<img src={url} alt={view.label} />
|
|
73
73
|
{:else if view.evidence.mediaType === 'application/pdf'}
|
|
74
74
|
{@const src = pageUrl(url, view.evidence.id)}
|
|
75
|
-
{#if count > 1}{@const current = page[view.evidence.id] ?? 1}<div class="
|
|
75
|
+
{#if count > 1}{@const current = page[view.evidence.id] ?? 1}<div class="smrt-evidence-viewer__pager" data-smrt-part="nav" data-testid="page-pager"><Button disabled={current <= 1} onclick={() => turn(view.evidence.id, -1)}>{t(M['ingestion.previousPage'])}</Button><p role="status">{t(M['ingestion.pageOf'], { page: current, count })}</p><Button disabled={current >= count} onclick={() => turn(view.evidence.id, 1)}>{t(M['ingestion.nextPage'])}</Button></div>{/if}
|
|
76
76
|
<!-- A fragment-only change does not reliably move an embedded PDF viewer; a new frame does. -->
|
|
77
77
|
{#key src}<iframe {src} title={view.label}></iframe>{/key}
|
|
78
78
|
{:else if view.evidence.mediaType.startsWith('audio/')}<audio controls src={url} aria-label={view.label}></audio>{/if}
|
|
@@ -84,7 +84,45 @@ function turn(id: string, offset: number) {
|
|
|
84
84
|
</section>
|
|
85
85
|
<style>
|
|
86
86
|
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
87
|
+
@layer smrt.structure {
|
|
88
|
+
section,article {
|
|
89
|
+
min-width:0;
|
|
90
|
+
}
|
|
91
|
+
article {
|
|
92
|
+
margin-block:1rem;
|
|
93
|
+
}
|
|
94
|
+
img,iframe,audio {
|
|
95
|
+
display:block;
|
|
96
|
+
max-width:100%;
|
|
97
|
+
width:100%;
|
|
98
|
+
margin-block:.5rem;
|
|
99
|
+
}
|
|
100
|
+
img {
|
|
101
|
+
object-fit:contain;
|
|
102
|
+
max-height:32rem;
|
|
103
|
+
}
|
|
104
|
+
iframe {
|
|
105
|
+
height:32rem;
|
|
106
|
+
}
|
|
107
|
+
pre {
|
|
108
|
+
white-space:pre-wrap;
|
|
109
|
+
overflow-wrap:anywhere;
|
|
110
|
+
}
|
|
111
|
+
.smrt-evidence-viewer__pager {
|
|
112
|
+
display:flex;
|
|
113
|
+
flex-wrap:wrap;
|
|
114
|
+
align-items:center;
|
|
115
|
+
gap:.5rem;
|
|
116
|
+
}
|
|
117
|
+
.smrt-evidence-viewer__pager p {
|
|
118
|
+
margin:0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
87
122
|
@layer smrt.theme {
|
|
88
|
-
|
|
123
|
+
iframe {
|
|
124
|
+
border:var(--smrt-hairline);
|
|
125
|
+
}
|
|
89
126
|
}
|
|
127
|
+
|
|
90
128
|
</style>
|
|
@@ -384,12 +384,12 @@ onMount(() => {
|
|
|
384
384
|
<section data-testid="intake-inbox" aria-busy={pending}>
|
|
385
385
|
<h1>{t(M['ingestion.inbox'])}</h1>
|
|
386
386
|
<!-- The upload leads the inbox so it is found on an empty one too (#4587). Keep retry Files separately; an unchanged native FileList must not suppress a deliberate reselection. -->
|
|
387
|
-
<div class="
|
|
387
|
+
<div class="smrt-inbox-view__upload" data-smrt-part="field" data-testid="intake-upload">
|
|
388
388
|
<FilePicker bind:files {dropzone} onclick={(event) => { event.currentTarget.value = ''; }} onchangefiles={() => { uploadRequestId = undefined; refusal = undefined; }} accept={accept ?? host.uploadAccept} multiple label={t(M['ingestion.files'])} description={dropzone ? `${t(M['ingestion.filesDrop'])} ${t(M['ingestion.filesHelp'])}` : t(M['ingestion.filesHelp'])} disabled={pending} />
|
|
389
389
|
<Button disabled={pending || !files.length} onclick={upload}>{t(M['ingestion.upload'])}</Button>
|
|
390
390
|
{#if refusal}<p role="alert" data-testid="upload-refused">{refusal}</p>{/if}
|
|
391
391
|
</div>
|
|
392
|
-
<div class="
|
|
392
|
+
<div class="smrt-inbox-view__toolbar" data-smrt-part="actions">
|
|
393
393
|
<Select aria-label={t(M['ingestion.filter'])} bind:value={selectedState} disabled={pending} onchange={() => load()}><option value="">{t(M['ingestion.all'])}</option>{#each states as value}<option {value}>{t(M[`ingestion.${value}`])}</option>{/each}</Select>
|
|
394
394
|
{#if host.assignees}<Combobox label={t(M['ingestion.assigneeName'])} options={pickerOptions(t(M['ingestion.anyAssignee']))} bind:value={assignee} valueLabel={assigneeLabels[assignee] ?? assignee} filter={false} busy={assigneeSearching} status={assigneeSearching ? t(M['ingestion.searching']) : undefined} onquery={findAssignees} disabled={pending} />{:else}<Input aria-label={t(M['ingestion.assignee'])} bind:value={assignee} disabled={pending} />{/if}
|
|
395
395
|
<Button onclick={() => load()} disabled={pending}>{t(M['ingestion.refresh'])}</Button>
|
|
@@ -397,9 +397,9 @@ onMount(() => {
|
|
|
397
397
|
{#if error}<p role="alert">{t(M['ingestion.error'])}</p>{/if}
|
|
398
398
|
{#if pending}<p role="status">{t(M['ingestion.loading'])}</p>{/if}
|
|
399
399
|
{#if !pending && !error && !items.length}<p>{t(M['ingestion.empty'])}</p>{/if}
|
|
400
|
-
<ul>{#each items as entry (entry.item.id)}<li data-item-id={entry.item.id} aria-current={entry.item.id === selectedId ? 'true' : undefined} class:
|
|
400
|
+
<ul>{#each items as entry (entry.item.id)}<li data-item-id={entry.item.id} aria-current={entry.item.id === selectedId ? 'true' : undefined} class:smrt-inbox-view__selected={entry.item.id === selectedId} data-smrt-part="item">
|
|
401
401
|
<h2>{entry.label}</h2><p data-testid="row-status">{status?.(entry) ?? t(M[`ingestion.${entry.state}`])}</p>
|
|
402
|
-
{#if rowAside}<div class="
|
|
402
|
+
{#if rowAside}<div class="smrt-inbox-view__row-aside" data-smrt-part="group">{@render rowAside(entry)}</div>{:else if entry.evidence}{@const original = evidenceUrl(entry.evidence.viewUrl)}{@const thumbnail = evidenceUrl(entry.evidence.thumbnailUrl)}{#if thumbnail || original}<div class="smrt-inbox-view__row-aside" data-smrt-part="group">
|
|
403
403
|
{#if thumbnail}<img src={thumbnail} alt={entry.evidence.label} loading="lazy" />{/if}
|
|
404
404
|
{#if original}<a href={original} target="_blank" rel="noopener noreferrer" aria-label={`${t(M['ingestion.original'])}: ${entry.label}`}>{t(M['ingestion.original'])}</a>{/if}
|
|
405
405
|
</div>{/if}{/if}
|
|
@@ -415,7 +415,59 @@ onMount(() => {
|
|
|
415
415
|
</section>
|
|
416
416
|
<style>
|
|
417
417
|
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
418
|
+
@layer smrt.structure {
|
|
419
|
+
section {
|
|
420
|
+
max-width:72rem;
|
|
421
|
+
margin-inline:auto;
|
|
422
|
+
padding:1rem;
|
|
423
|
+
}
|
|
424
|
+
.smrt-inbox-view__upload {
|
|
425
|
+
display:grid;
|
|
426
|
+
gap:.5rem;
|
|
427
|
+
justify-items:start;
|
|
428
|
+
margin-block:1rem;
|
|
429
|
+
}
|
|
430
|
+
.smrt-inbox-view__toolbar {
|
|
431
|
+
display:flex;
|
|
432
|
+
flex-wrap:wrap;
|
|
433
|
+
gap:.75rem;
|
|
434
|
+
margin-block:1rem;
|
|
435
|
+
}
|
|
436
|
+
ul {
|
|
437
|
+
list-style:none;
|
|
438
|
+
padding:0;
|
|
439
|
+
}
|
|
440
|
+
li {
|
|
441
|
+
padding:1rem;
|
|
442
|
+
display:grid;
|
|
443
|
+
gap:.75rem;
|
|
444
|
+
}
|
|
445
|
+
.smrt-inbox-view__row-aside {
|
|
446
|
+
display:flex;
|
|
447
|
+
flex-wrap:wrap;
|
|
448
|
+
align-items:center;
|
|
449
|
+
gap:.75rem;
|
|
450
|
+
}
|
|
451
|
+
.smrt-inbox-view__row-aside img {
|
|
452
|
+
max-block-size:6rem;
|
|
453
|
+
max-inline-size:100%;
|
|
454
|
+
object-fit:contain;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
418
458
|
@layer smrt.theme {
|
|
419
|
-
section
|
|
459
|
+
section {
|
|
460
|
+
color:var(--smrt-color-on-surface);
|
|
461
|
+
}
|
|
462
|
+
li {
|
|
463
|
+
border-block-end:var(--smrt-hairline);
|
|
464
|
+
}
|
|
465
|
+
li.smrt-inbox-view__selected {
|
|
466
|
+
border-inline-start:.25rem solid var(--smrt-color-primary);
|
|
467
|
+
}
|
|
468
|
+
h2 {
|
|
469
|
+
font-size:1.1rem;
|
|
470
|
+
}
|
|
420
471
|
}
|
|
472
|
+
|
|
421
473
|
</style>
|
|
@@ -868,7 +868,7 @@ onMount(() => {
|
|
|
868
868
|
{:else}
|
|
869
869
|
{@const extracted = view.analysis ? extractedContent(view.analysis.result.output) : []}
|
|
870
870
|
<h2>{view.entry.label}</h2><p>{t(M[`ingestion.${view.entry.state}`])}</p>
|
|
871
|
-
<div class="review-grid" class:
|
|
871
|
+
<div class="smrt-review-view__grid" data-smrt-part="grid" class:smrt-review-view__stacked={layout === 'stacked'}><EvidenceViewer evidence={view.evidence} pages={observedPages(view)} layout={layout === 'stacked' ? 'pager' : 'stack'} bind:chosen={viewerPart} bind:page={viewerPages} /><div class="smrt-review-view__details" data-smrt-part="body">
|
|
872
872
|
{#if view.instruction}
|
|
873
873
|
{@const applied = view.instruction.applied}{@const current = view.instruction.current}
|
|
874
874
|
{#if inFlight(view) && current}<p role="status" data-testid="reinterpreting">{t(M['ingestion.reinterpreting'])}</p>{/if}
|
|
@@ -929,7 +929,7 @@ onMount(() => {
|
|
|
929
929
|
{/if}
|
|
930
930
|
{:else}
|
|
931
931
|
{#if host.startAction && view.catalog?.some((entry) => entry.kind === 'operation')}
|
|
932
|
-
<fieldset class="
|
|
932
|
+
<fieldset class="smrt-review-view__start" data-smrt-part="submit"><legend>{t(M['ingestion.startAs'])}</legend>
|
|
933
933
|
<Select aria-label={t(M['ingestion.startHandler'])} bind:value={startHandler} onchange={draftStart} disabled={pending}><option value="">{t(M['ingestion.startHandler'])}</option>{#each view.catalog as entry (`${entry.id}@${entry.version}`)}{#if entry.kind === 'operation'}<option value={`${entry.id}@${entry.version}`}>{entry.label ?? entry.id}</option>{/if}{/each}</Select>
|
|
934
934
|
{#if startEntry}
|
|
935
935
|
<p>{startEntry.description}</p>
|
|
@@ -944,7 +944,7 @@ onMount(() => {
|
|
|
944
944
|
</fieldset>
|
|
945
945
|
{/if}
|
|
946
946
|
{#if host.resolve}
|
|
947
|
-
<fieldset class="
|
|
947
|
+
<fieldset class="smrt-review-view__resolve" data-smrt-part="confirm"><legend>{t(M['ingestion.resolveNoAction'])}</legend>
|
|
948
948
|
<Input aria-label={t(M['ingestion.resolveReason'])} bind:value={resolveReason} disabled={pending} />
|
|
949
949
|
<Button disabled={pending} onclick={resolve}>{t(M['ingestion.resolveNoAction'])}</Button>
|
|
950
950
|
</fieldset>
|
|
@@ -960,7 +960,62 @@ onMount(() => {
|
|
|
960
960
|
</section>
|
|
961
961
|
<style>
|
|
962
962
|
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
963
|
+
@layer smrt.structure {
|
|
964
|
+
section {
|
|
965
|
+
overflow-wrap:anywhere;
|
|
966
|
+
max-width:90rem;
|
|
967
|
+
margin-inline:auto;
|
|
968
|
+
padding:1rem;
|
|
969
|
+
}
|
|
970
|
+
header {
|
|
971
|
+
display:flex;
|
|
972
|
+
align-items:center;
|
|
973
|
+
justify-content:space-between;
|
|
974
|
+
gap:1rem;
|
|
975
|
+
}
|
|
976
|
+
.smrt-review-view__grid {
|
|
977
|
+
display:grid;
|
|
978
|
+
grid-template-columns:minmax(0,1fr) minmax(0,1fr);
|
|
979
|
+
gap:1.5rem;
|
|
980
|
+
}
|
|
981
|
+
.smrt-review-view__grid.smrt-review-view__stacked {
|
|
982
|
+
grid-template-columns:minmax(0,1fr);
|
|
983
|
+
}
|
|
984
|
+
.smrt-review-view__details,article {
|
|
985
|
+
min-width:0;
|
|
986
|
+
}
|
|
987
|
+
pre {
|
|
988
|
+
white-space:pre-wrap;
|
|
989
|
+
overflow-wrap:anywhere;
|
|
990
|
+
max-height:24rem;
|
|
991
|
+
overflow:auto;
|
|
992
|
+
}
|
|
993
|
+
article {
|
|
994
|
+
padding-block:1rem;
|
|
995
|
+
}
|
|
996
|
+
fieldset {
|
|
997
|
+
margin-block:1rem;
|
|
998
|
+
min-width:0;
|
|
999
|
+
display:grid;
|
|
1000
|
+
gap:.5rem;
|
|
1001
|
+
}
|
|
1002
|
+
@media(max-width:48rem) {
|
|
1003
|
+
.smrt-review-view__grid {
|
|
1004
|
+
grid-template-columns:minmax(0,1fr);
|
|
1005
|
+
}
|
|
1006
|
+
header {
|
|
1007
|
+
flex-wrap:wrap;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
963
1012
|
@layer smrt.theme {
|
|
964
|
-
section
|
|
1013
|
+
section {
|
|
1014
|
+
color:var(--smrt-color-on-surface);
|
|
1015
|
+
}
|
|
1016
|
+
article {
|
|
1017
|
+
border-block-end:var(--smrt-hairline);
|
|
1018
|
+
}
|
|
965
1019
|
}
|
|
1020
|
+
|
|
966
1021
|
</style>
|
|
@@ -684,21 +684,21 @@ function keydown(event: KeyboardEvent) {
|
|
|
684
684
|
}
|
|
685
685
|
</script>
|
|
686
686
|
<svelte:window onkeydown={keydown} />
|
|
687
|
-
<div class="
|
|
688
|
-
<div class="
|
|
687
|
+
<div class="smrt-triage-view__workspace" bind:this={root} data-testid="intake-workspace" data-smrt-component="TriageView">
|
|
688
|
+
<div class="smrt-triage-view__list" data-smrt-part="list">
|
|
689
689
|
<InboxView bind:this={inbox} {host} {rowAside} {accept} {dropzone} {listPollMs} selectedId={selected} onselect={(id) => request(id)} onitems={listed} onreadstart={readStarted} {stamp} status={rowStatus} resolveInRow={false} />
|
|
690
690
|
</div>
|
|
691
|
-
<section class="
|
|
692
|
-
<div class="
|
|
691
|
+
<section class="smrt-triage-view__item" data-smrt-part="panel" bind:this={pane} tabindex="-1" aria-label={label ?? t(M['ingestion.selectedItem'])} data-testid="workspace-item" onfocusin={noteField}>
|
|
692
|
+
<div class="smrt-triage-view__queue-nav" data-smrt-part="actions" role="group" aria-label={t(M['ingestion.workspace'])}>
|
|
693
693
|
<Button disabled={position === 0 || !rows.length} aria-keyshortcuts="K Alt+ArrowUp" onclick={() => move(-1)}>{t(M['ingestion.previousItem'])}</Button>
|
|
694
694
|
{#if position >= 0}<p data-testid="queue-position">{t(M['ingestion.itemOf'], { index: position + 1, count: rows.length })}</p>{/if}
|
|
695
695
|
<Button disabled={(position >= rows.length - 1 && !more) || !rows.length} aria-keyshortcuts="J Alt+ArrowDown" onclick={() => move(1)}>{t(M['ingestion.nextItem'])}</Button>
|
|
696
696
|
</div>
|
|
697
|
-
<p class="
|
|
697
|
+
<p class="smrt-triage-view__hint" data-smrt-part="description">{t(M['ingestion.keyboardHelp'])}</p>
|
|
698
698
|
<p role="status" data-testid="background-update">{announcement}</p>
|
|
699
699
|
<!-- One persistent live region whose text changes, so the notes are announced reliably. -->
|
|
700
|
-
<p role="status" class="
|
|
701
|
-
{#if leaving}<div class="
|
|
700
|
+
<p role="status" class="smrt-triage-view__note" data-smrt-part="message" data-testid="pane-note">{#if held}<span data-testid="advance-held">{t(M[held === 'unsent' ? 'ingestion.finishedUnsent' : held === 'failed' ? 'ingestion.advanceFailed' : 'ingestion.advanceRetry'])}</span>{:else if done && !selected}<span data-testid="queue-done">{t(M['ingestion.queueDone'])}</span>{/if}</p>
|
|
701
|
+
{#if leaving}<div class="smrt-triage-view__leave" data-smrt-part="panel" role="group" aria-labelledby="unsaved-leave-note" bind:this={stay} data-testid="unsaved-leave"><p id="unsaved-leave-note">{t(M['ingestion.unsavedLeave'])}</p><Button data-stay onclick={keepEditing}>{t(M['ingestion.stay'])}</Button><Button onclick={discardAndLeave}>{t(M['ingestion.discardLeave'])}</Button></div>{/if}
|
|
702
702
|
{#if selected}
|
|
703
703
|
{#key selected}<ReviewView {host} itemId={selected} {pollMs} layout="stacked" {stamp} onview={paneChanged} ondirty={(dirty: boolean) => { paneDirty = dirty; }} onoutcome={outcome} />{/key}
|
|
704
704
|
{:else if !done}<p>{t(M['ingestion.selectItem'])}</p>{/if}
|
|
@@ -706,7 +706,70 @@ function keydown(event: KeyboardEvent) {
|
|
|
706
706
|
</div>
|
|
707
707
|
<style>
|
|
708
708
|
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
709
|
+
@layer smrt.structure {
|
|
710
|
+
.smrt-triage-view__workspace {
|
|
711
|
+
display:grid;
|
|
712
|
+
grid-template-columns:minmax(0,1fr);
|
|
713
|
+
gap:1rem;
|
|
714
|
+
}
|
|
715
|
+
.smrt-triage-view__list,.smrt-triage-view__item {
|
|
716
|
+
min-width:0;
|
|
717
|
+
}
|
|
718
|
+
.smrt-triage-view__queue-nav {
|
|
719
|
+
display:flex;
|
|
720
|
+
flex-wrap:wrap;
|
|
721
|
+
align-items:center;
|
|
722
|
+
gap:.5rem;
|
|
723
|
+
padding-inline:1rem;
|
|
724
|
+
}
|
|
725
|
+
.smrt-triage-view__queue-nav p,.smrt-triage-view__hint {
|
|
726
|
+
margin:0;
|
|
727
|
+
}
|
|
728
|
+
.smrt-triage-view__leave {
|
|
729
|
+
display:flex;
|
|
730
|
+
flex-wrap:wrap;
|
|
731
|
+
align-items:center;
|
|
732
|
+
gap:.5rem;
|
|
733
|
+
padding:.75rem 1rem;
|
|
734
|
+
}
|
|
735
|
+
.smrt-triage-view__leave p {
|
|
736
|
+
margin:0;
|
|
737
|
+
flex-basis:100%;
|
|
738
|
+
}
|
|
739
|
+
.smrt-triage-view__hint {
|
|
740
|
+
padding-inline:1rem;
|
|
741
|
+
}
|
|
742
|
+
[data-testid='background-update'],.smrt-triage-view__note {
|
|
743
|
+
padding-inline:1rem;
|
|
744
|
+
margin:0;
|
|
745
|
+
}
|
|
746
|
+
@media(min-width:64rem) {
|
|
747
|
+
.smrt-triage-view__workspace {
|
|
748
|
+
grid-template-columns:minmax(18rem,26rem) minmax(0,1fr);
|
|
749
|
+
}
|
|
750
|
+
.smrt-triage-view__list {
|
|
751
|
+
position:sticky;
|
|
752
|
+
inset-block-start:0;
|
|
753
|
+
align-self:start;
|
|
754
|
+
max-block-size:100vh;
|
|
755
|
+
overflow:auto;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
709
760
|
@layer smrt.theme {
|
|
710
|
-
.
|
|
761
|
+
.smrt-triage-view__workspace {
|
|
762
|
+
color:var(--smrt-color-on-surface);
|
|
763
|
+
}
|
|
764
|
+
.smrt-triage-view__item {
|
|
765
|
+
outline-offset:.25rem;
|
|
766
|
+
}
|
|
767
|
+
.smrt-triage-view__leave {
|
|
768
|
+
border:var(--smrt-hairline);
|
|
769
|
+
}
|
|
770
|
+
.smrt-triage-view__hint {
|
|
771
|
+
font-size:.875rem;
|
|
772
|
+
}
|
|
711
773
|
}
|
|
774
|
+
|
|
712
775
|
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-ingestion",
|
|
3
|
-
"version": "0.60.
|
|
3
|
+
"version": "0.60.18",
|
|
4
4
|
"description": "Durable tenant-scoped intake and evidence foundations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -50,32 +50,32 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@happyvertical/smrt-core": "0.60.
|
|
54
|
-
"@happyvertical/smrt-types": "0.60.
|
|
55
|
-
"@happyvertical/smrt-tenancy": "0.60.
|
|
56
|
-
"@happyvertical/smrt-assets": "0.60.
|
|
57
|
-
"@happyvertical/smrt-jobs": "0.60.
|
|
58
|
-
"@happyvertical/sql": "^0.
|
|
53
|
+
"@happyvertical/smrt-core": "0.60.18",
|
|
54
|
+
"@happyvertical/smrt-types": "0.60.18",
|
|
55
|
+
"@happyvertical/smrt-tenancy": "0.60.18",
|
|
56
|
+
"@happyvertical/smrt-assets": "0.60.18",
|
|
57
|
+
"@happyvertical/smrt-jobs": "0.60.18",
|
|
58
|
+
"@happyvertical/sql": "^0.112.2",
|
|
59
59
|
"@happyvertical/pdf": "^0.65.9",
|
|
60
60
|
"@happyvertical/ocr": "^0.62.1",
|
|
61
|
-
"@happyvertical/speech": "^0.
|
|
62
|
-
"@happyvertical/ai": "^0.
|
|
61
|
+
"@happyvertical/speech": "^0.112.2",
|
|
62
|
+
"@happyvertical/ai": "^0.112.2",
|
|
63
63
|
"sharp": "^0.35.5",
|
|
64
|
-
"@happyvertical/smrt-agents": "0.60.
|
|
65
|
-
"@happyvertical/smrt-playbooks": "0.60.
|
|
64
|
+
"@happyvertical/smrt-agents": "0.60.18",
|
|
65
|
+
"@happyvertical/smrt-playbooks": "0.60.18",
|
|
66
66
|
"ajv": "8.20.0",
|
|
67
|
-
"@happyvertical/smrt-ui": "0.60.
|
|
67
|
+
"@happyvertical/smrt-ui": "0.60.18"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@happyvertical/smrt-vitest": "0.60.
|
|
70
|
+
"@happyvertical/smrt-vitest": "0.60.18",
|
|
71
71
|
"@types/node": "24.13.6",
|
|
72
72
|
"typescript": "6.0.3",
|
|
73
73
|
"vite": "8.1.6",
|
|
74
74
|
"vitest": "4.1.10",
|
|
75
|
-
"@happyvertical/smrt-content": "0.60.
|
|
76
|
-
"@happyvertical/smrt-messages": "0.60.
|
|
77
|
-
"@happyvertical/email": "^0.
|
|
78
|
-
"@happyvertical/smrt-users": "0.60.
|
|
75
|
+
"@happyvertical/smrt-content": "0.60.18",
|
|
76
|
+
"@happyvertical/smrt-messages": "0.60.18",
|
|
77
|
+
"@happyvertical/email": "^0.112.2",
|
|
78
|
+
"@happyvertical/smrt-users": "0.60.18",
|
|
79
79
|
"@sveltejs/package": "^2.5.8",
|
|
80
80
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
81
81
|
"svelte": "^5.57.1",
|