@volter-ai-dev/supercode-ui 0.1.28 → 0.1.30
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/README.md +10 -2
- package/components.mjs +330 -133
- package/composer.mjs +5 -2
- package/controller.mjs +10 -11
- package/conversation.mjs +4 -1
- package/core.d.ts +1 -0
- package/core.mjs +97 -4
- package/embed.mjs +330 -135
- package/index.d.ts +82 -3
- package/messenger.mjs +328 -133
- package/package.json +8 -2
- package/sessions.mjs +31 -6
- package/settings.d.ts +2 -0
- package/settings.mjs +216 -0
- package/styles.css +12 -2
package/composer.mjs
CHANGED
|
@@ -40,6 +40,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
40
40
|
canReduce: false,
|
|
41
41
|
canInterrupt: false,
|
|
42
42
|
canRespond: false,
|
|
43
|
+
canConfigureSettings: false,
|
|
43
44
|
messaging: null,
|
|
44
45
|
workspace: "",
|
|
45
46
|
taskPlan: Object.freeze({ source: "none", items: Object.freeze([]), residueCount: 0, observedAt: null }),
|
|
@@ -48,6 +49,8 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
48
49
|
exportBackTarget: null,
|
|
49
50
|
exportReceipt: null,
|
|
50
51
|
reductionReceipt: null,
|
|
52
|
+
interopSettings: null,
|
|
53
|
+
interopSettingsError: null,
|
|
51
54
|
error: null,
|
|
52
55
|
recoverable: false,
|
|
53
56
|
harnesses: Object.freeze([]),
|
|
@@ -65,7 +68,7 @@ function harnessDisplayName(id) {
|
|
|
65
68
|
function canContinueHere(state) {
|
|
66
69
|
if (state.mode !== "mirror" || state.canSend) return false;
|
|
67
70
|
const row = state.attached?.key ? state.sessions.find((item) => item.key === state.attached.key) : null;
|
|
68
|
-
return state.canResume && row?.runtimeStatus !== "busy" && row?.runtimeStatus !== "idle";
|
|
71
|
+
return state.canResume && row?.runtimeStatus !== "running" && row?.runtimeStatus !== "busy" && row?.runtimeStatus !== "idle";
|
|
69
72
|
}
|
|
70
73
|
function isSendKey(event) {
|
|
71
74
|
return event.key === "Enter" && !event.shiftKey && !event.isComposing;
|
|
@@ -252,7 +255,7 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
252
255
|
if (state.mode !== "mirror" || state.canSend) return null;
|
|
253
256
|
const attached = state.attached;
|
|
254
257
|
const row = attached?.key ? state.sessions.find((item) => item.key === attached.key) : null;
|
|
255
|
-
const activeElsewhere = row?.runtimeStatus === "busy" || row?.runtimeStatus === "idle";
|
|
258
|
+
const activeElsewhere = row?.runtimeStatus === "running" || row?.runtimeStatus === "busy" || row?.runtimeStatus === "idle";
|
|
256
259
|
const resume = canContinueHere(state);
|
|
257
260
|
const join = state.canAttach;
|
|
258
261
|
const branch = state.canBranch;
|
package/controller.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createToolPresentation, normalizeUiState } from './core.mjs';
|
|
1
|
+
import { createToolPresentation, normalizeUiState, relativeAge } from './core.mjs';
|
|
2
2
|
|
|
3
3
|
const HARNESS_LABELS = {
|
|
4
4
|
'claude-code': 'Claude Code',
|
|
@@ -28,16 +28,6 @@ function workspaceName(cwd) {
|
|
|
28
28
|
return cwd.replaceAll('\\', '/').split('/').filter(Boolean).at(-1) ?? cwd;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function relativeAge(updatedAt, now) {
|
|
32
|
-
if (typeof updatedAt !== 'number' || !Number.isFinite(updatedAt) || updatedAt <= 0) return '';
|
|
33
|
-
const delta = Math.max(0, now - updatedAt);
|
|
34
|
-
if (delta < 60_000) return 'now';
|
|
35
|
-
if (delta < 3_600_000) return `${Math.floor(delta / 60_000)}m ago`;
|
|
36
|
-
if (delta < 86_400_000) return `${Math.floor(delta / 3_600_000)}h ago`;
|
|
37
|
-
if (delta < 604_800_000) return `${Math.floor(delta / 86_400_000)}d ago`;
|
|
38
|
-
return `${Math.floor(delta / 604_800_000)}w ago`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
31
|
function payloadText(payload) {
|
|
42
32
|
if (typeof payload === 'string') return payload;
|
|
43
33
|
try {
|
|
@@ -384,6 +374,7 @@ function projectClientSnapshotInternal(snapshot, options, imageRegistry) {
|
|
|
384
374
|
canReduce: actions.reduce === true,
|
|
385
375
|
canInterrupt: actions.interrupt === true,
|
|
386
376
|
canRespond: actions.respond === true,
|
|
377
|
+
canConfigureSettings: actions.configureHarness === true,
|
|
387
378
|
messaging: snapshot.connection?.messaging ?? null,
|
|
388
379
|
workspace: snapshot.workspace ?? '',
|
|
389
380
|
taskPlan: {
|
|
@@ -401,6 +392,8 @@ function projectClientSnapshotInternal(snapshot, options, imageRegistry) {
|
|
|
401
392
|
exportBackTarget: options.exportBackTarget ?? null,
|
|
402
393
|
exportReceipt: options.exportReceipt ?? null,
|
|
403
394
|
reductionReceipt: options.reductionReceipt ?? snapshot.reductionReceipt ?? null,
|
|
395
|
+
interopSettings: snapshot.interopSettings ?? null,
|
|
396
|
+
interopSettingsError: snapshot.interopSettingsError ?? null,
|
|
404
397
|
error: snapshot.error?.message ?? null,
|
|
405
398
|
recoverable: snapshot.error?.recoverable === true,
|
|
406
399
|
harnesses: (snapshot.harnesses ?? []).map((harness) => ({
|
|
@@ -464,6 +457,12 @@ async function dispatchStandard(controller, intent, options) {
|
|
|
464
457
|
if (intent.action === 'terminal') return controller.dispatch({ type: 'openTerminal' });
|
|
465
458
|
if (intent.action === 'interrupt') return controller.dispatch({ type: 'interrupt' });
|
|
466
459
|
if (intent.action === 'respond') return controller.dispatch({ type: 'respond', requestId: intent.requestId, optionId: intent.optionId });
|
|
460
|
+
if (intent.action === 'configureHarness') return controller.dispatch({
|
|
461
|
+
type: 'configureHarness',
|
|
462
|
+
harness: intent.harness,
|
|
463
|
+
changes: intent.changes,
|
|
464
|
+
expectedRevision: intent.expectedRevision,
|
|
465
|
+
});
|
|
467
466
|
if (intent.action === 'refresh') return controller.dispatch({ type: 'refresh', autoObserve: true });
|
|
468
467
|
if (intent.action === 'export' && active) {
|
|
469
468
|
const artifact = await controller.exportSession(active, intent.targetHarness);
|
package/conversation.mjs
CHANGED
|
@@ -41,6 +41,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
41
41
|
canReduce: false,
|
|
42
42
|
canInterrupt: false,
|
|
43
43
|
canRespond: false,
|
|
44
|
+
canConfigureSettings: false,
|
|
44
45
|
messaging: null,
|
|
45
46
|
workspace: "",
|
|
46
47
|
taskPlan: Object.freeze({ source: "none", items: Object.freeze([]), residueCount: 0, observedAt: null }),
|
|
@@ -49,6 +50,8 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
49
50
|
exportBackTarget: null,
|
|
50
51
|
exportReceipt: null,
|
|
51
52
|
reductionReceipt: null,
|
|
53
|
+
interopSettings: null,
|
|
54
|
+
interopSettingsError: null,
|
|
52
55
|
error: null,
|
|
53
56
|
recoverable: false,
|
|
54
57
|
harnesses: Object.freeze([]),
|
|
@@ -67,7 +70,7 @@ var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
|
67
70
|
function record(value) {
|
|
68
71
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
69
72
|
}
|
|
70
|
-
function boundedString(value, max) {
|
|
73
|
+
function boundedString(value, max = 2e3) {
|
|
71
74
|
if (typeof value !== "string") return "";
|
|
72
75
|
return value.length <= max ? value : `${value.slice(0, max)}\u2026`;
|
|
73
76
|
}
|
package/core.d.ts
CHANGED
package/core.mjs
CHANGED
|
@@ -38,6 +38,7 @@ export const EMPTY_UI_STATE = Object.freeze({
|
|
|
38
38
|
canReduce: false,
|
|
39
39
|
canInterrupt: false,
|
|
40
40
|
canRespond: false,
|
|
41
|
+
canConfigureSettings: false,
|
|
41
42
|
messaging: null,
|
|
42
43
|
workspace: '',
|
|
43
44
|
taskPlan: Object.freeze({ source: 'none', items: Object.freeze([]), residueCount: 0, observedAt: null }),
|
|
@@ -46,6 +47,8 @@ export const EMPTY_UI_STATE = Object.freeze({
|
|
|
46
47
|
exportBackTarget: null,
|
|
47
48
|
exportReceipt: null,
|
|
48
49
|
reductionReceipt: null,
|
|
50
|
+
interopSettings: null,
|
|
51
|
+
interopSettingsError: null,
|
|
49
52
|
error: null,
|
|
50
53
|
recoverable: false,
|
|
51
54
|
harnesses: Object.freeze([]),
|
|
@@ -85,7 +88,17 @@ function nullableNumber(value) {
|
|
|
85
88
|
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
86
89
|
}
|
|
87
90
|
|
|
88
|
-
function
|
|
91
|
+
export function relativeAge(updatedAt, now = Date.now()) {
|
|
92
|
+
if (typeof updatedAt !== 'number' || !Number.isFinite(updatedAt) || updatedAt <= 0) return '';
|
|
93
|
+
const delta = Math.max(0, now - updatedAt);
|
|
94
|
+
if (delta < 60_000) return 'now';
|
|
95
|
+
if (delta < 3_600_000) return `${Math.floor(delta / 60_000)}m ago`;
|
|
96
|
+
if (delta < 86_400_000) return `${Math.floor(delta / 3_600_000)}h ago`;
|
|
97
|
+
if (delta < 604_800_000) return `${Math.floor(delta / 86_400_000)}d ago`;
|
|
98
|
+
return `${Math.floor(delta / 604_800_000)}w ago`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function boundedString(value, max = 2_000) {
|
|
89
102
|
if (typeof value !== 'string') return '';
|
|
90
103
|
return value.length <= max ? value : `${value.slice(0, max)}…`;
|
|
91
104
|
}
|
|
@@ -541,11 +554,12 @@ function readSessions(value) {
|
|
|
541
554
|
title: string(row.title),
|
|
542
555
|
preview: string(row.preview),
|
|
543
556
|
age: string(row.age),
|
|
557
|
+
previewUpdatedAt: nullableNumber(row.previewUpdatedAt),
|
|
544
558
|
updatedAt: nullableNumber(row.updatedAt),
|
|
545
559
|
messages: nullableNumber(row.messages),
|
|
546
560
|
active: row.active === true,
|
|
547
561
|
live: row.live === true,
|
|
548
|
-
runtimeStatus: row.runtimeStatus === 'busy' || row.runtimeStatus === 'idle' ? row.runtimeStatus : null,
|
|
562
|
+
runtimeStatus: row.runtimeStatus === 'running' || row.runtimeStatus === 'busy' || row.runtimeStatus === 'idle' ? row.runtimeStatus : null,
|
|
549
563
|
}];
|
|
550
564
|
});
|
|
551
565
|
}
|
|
@@ -660,6 +674,81 @@ function readReductionReceipt(value) {
|
|
|
660
674
|
};
|
|
661
675
|
}
|
|
662
676
|
|
|
677
|
+
function readInteropSettings(value) {
|
|
678
|
+
const report = record(value);
|
|
679
|
+
if (
|
|
680
|
+
report?.schema !== 'supercode.harness-interop-settings.v1' ||
|
|
681
|
+
typeof report.harness !== 'string' ||
|
|
682
|
+
typeof report.revision !== 'string' ||
|
|
683
|
+
!Array.isArray(report.controls) ||
|
|
684
|
+
!Array.isArray(report.advisories)
|
|
685
|
+
) return null;
|
|
686
|
+
const controls = report.controls.slice(0, 20).flatMap((raw) => {
|
|
687
|
+
const control = record(raw);
|
|
688
|
+
if (!control || typeof control.key !== 'string' || typeof control.label !== 'string') return [];
|
|
689
|
+
return [{
|
|
690
|
+
key: boundedString(control.key, 200),
|
|
691
|
+
nativeKey: boundedString(control.native_key ?? control.nativeKey, 200),
|
|
692
|
+
label: boundedString(control.label, 300),
|
|
693
|
+
description: boundedString(control.description),
|
|
694
|
+
scope: ['user', 'project', 'managed', 'command_line'].includes(control.scope) ? control.scope : 'user',
|
|
695
|
+
sourcePath: boundedString(control.source_path ?? control.sourcePath, 4_000),
|
|
696
|
+
configuredValue: typeof (control.configured_value ?? control.configuredValue) === 'string' ? boundedString(control.configured_value ?? control.configuredValue, 500) : null,
|
|
697
|
+
effectiveValue: typeof (control.effective_value ?? control.effectiveValue) === 'string' ? boundedString(control.effective_value ?? control.effectiveValue, 500) : null,
|
|
698
|
+
effectiveKnown: (control.effective_known ?? control.effectiveKnown) === true,
|
|
699
|
+
effectiveNote: boundedString(control.effective_note ?? control.effectiveNote),
|
|
700
|
+
choices: Array.isArray(control.choices) ? control.choices.slice(0, 20).flatMap((candidate) => {
|
|
701
|
+
const choice = record(candidate);
|
|
702
|
+
return choice && typeof choice.value === 'string' && typeof choice.label === 'string'
|
|
703
|
+
? [{
|
|
704
|
+
value: boundedString(choice.value, 500),
|
|
705
|
+
label: boundedString(choice.label, 300),
|
|
706
|
+
description: boundedString(choice.description),
|
|
707
|
+
...(typeof choice.risk === 'string' ? { risk: boundedString(choice.risk) } : {}),
|
|
708
|
+
}]
|
|
709
|
+
: [];
|
|
710
|
+
}) : [],
|
|
711
|
+
writable: control.writable === true,
|
|
712
|
+
resettable: control.resettable === true,
|
|
713
|
+
requiresRestart: (control.requires_restart ?? control.requiresRestart) === true,
|
|
714
|
+
}];
|
|
715
|
+
});
|
|
716
|
+
const advisories = report.advisories.slice(0, 20).flatMap((raw) => {
|
|
717
|
+
const advisory = record(raw);
|
|
718
|
+
const recommendation = record(advisory?.recommendation);
|
|
719
|
+
const change = record(recommendation?.change);
|
|
720
|
+
if (
|
|
721
|
+
!advisory || !recommendation || !change ||
|
|
722
|
+
typeof advisory.code !== 'string' || typeof advisory.title !== 'string' ||
|
|
723
|
+
typeof advisory.setting !== 'string' || typeof change.key !== 'string'
|
|
724
|
+
) return [];
|
|
725
|
+
return [{
|
|
726
|
+
code: boundedString(advisory.code, 200),
|
|
727
|
+
severity: ['info', 'warning', 'error'].includes(advisory.severity) ? advisory.severity : 'warning',
|
|
728
|
+
title: boundedString(advisory.title, 500),
|
|
729
|
+
message: boundedString(advisory.message),
|
|
730
|
+
setting: boundedString(advisory.setting, 200),
|
|
731
|
+
recommendation: {
|
|
732
|
+
label: boundedString(recommendation.label, 500),
|
|
733
|
+
description: boundedString(recommendation.description),
|
|
734
|
+
consequence: boundedString(recommendation.consequence),
|
|
735
|
+
change: {
|
|
736
|
+
key: boundedString(change.key, 200),
|
|
737
|
+
value: typeof change.value === 'string' ? boundedString(change.value, 500) : null,
|
|
738
|
+
},
|
|
739
|
+
command: boundedString(recommendation.command, 4_000),
|
|
740
|
+
},
|
|
741
|
+
}];
|
|
742
|
+
});
|
|
743
|
+
return {
|
|
744
|
+
schema: 'supercode.harness-interop-settings.v1',
|
|
745
|
+
harness: report.harness,
|
|
746
|
+
revision: boundedString(report.revision, 500),
|
|
747
|
+
controls,
|
|
748
|
+
advisories,
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
|
|
663
752
|
export function normalizeUiState(value) {
|
|
664
753
|
const raw = record(value) ?? {};
|
|
665
754
|
const pill = record(raw.pill);
|
|
@@ -685,6 +774,7 @@ export function normalizeUiState(value) {
|
|
|
685
774
|
canReduce: raw.canReduce === true,
|
|
686
775
|
canInterrupt: raw.canInterrupt === true,
|
|
687
776
|
canRespond: raw.canRespond === true,
|
|
777
|
+
canConfigureSettings: raw.canConfigureSettings === true,
|
|
688
778
|
messaging: raw.messaging === 'live_peer' ? 'live_peer' : null,
|
|
689
779
|
workspace: string(raw.workspace),
|
|
690
780
|
taskPlan: readTaskPlan(raw.taskPlan),
|
|
@@ -693,6 +783,8 @@ export function normalizeUiState(value) {
|
|
|
693
783
|
exportBackTarget: typeof raw.exportBackTarget === 'string' ? raw.exportBackTarget : null,
|
|
694
784
|
exportReceipt: readExportReceipt(raw.exportReceipt),
|
|
695
785
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
786
|
+
interopSettings: readInteropSettings(raw.interopSettings),
|
|
787
|
+
interopSettingsError: typeof raw.interopSettingsError === 'string' ? boundedString(raw.interopSettingsError) : null,
|
|
696
788
|
error: typeof raw.error === 'string' ? raw.error : null,
|
|
697
789
|
recoverable: raw.recoverable === true,
|
|
698
790
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
|
@@ -729,6 +821,7 @@ export function sessionActivity(state, row) {
|
|
|
729
821
|
const attention = state.attention.find((item) => item.key === row.key)?.kind;
|
|
730
822
|
if (attention) return attention;
|
|
731
823
|
if (row.runtimeStatus === 'busy') return 'working';
|
|
824
|
+
if (row.runtimeStatus === 'running') return 'running';
|
|
732
825
|
if (row.live || row.runtimeStatus === 'idle') return 'recent';
|
|
733
826
|
return 'idle';
|
|
734
827
|
}
|
|
@@ -793,12 +886,12 @@ export function activitySummary(entries) {
|
|
|
793
886
|
export function canContinueHere(state) {
|
|
794
887
|
if (state.mode !== 'mirror' || state.canSend) return false;
|
|
795
888
|
const row = state.attached?.key ? state.sessions.find((item) => item.key === state.attached.key) : null;
|
|
796
|
-
return state.canResume && row?.runtimeStatus !== 'busy' && row?.runtimeStatus !== 'idle';
|
|
889
|
+
return state.canResume && row?.runtimeStatus !== 'running' && row?.runtimeStatus !== 'busy' && row?.runtimeStatus !== 'idle';
|
|
797
890
|
}
|
|
798
891
|
|
|
799
892
|
export function operationLabel(operation) {
|
|
800
893
|
if (!operation) return '';
|
|
801
|
-
const labels = { discover: 'Refreshing chats…', observe: 'Loading recent messages…', attach: 'Opening chat…', start: 'Starting new chat…', resume: 'Continuing here…', join: 'Joining live session…', detach: 'Detaching to read-only…', branch: 'Starting continuation…', reduce: 'Reducing context and verifying reversibility…', terminal: 'Preparing terminal handoff…', export: 'Exporting losslessly…', interrupt: 'Stopping agent…', respond: 'Sending response…', loadEarlier: 'Loading earlier messages…', loadSessions: 'Loading more chats…', refresh: 'Retrying…' };
|
|
894
|
+
const labels = { discover: 'Refreshing chats…', observe: 'Loading recent messages…', attach: 'Opening chat…', start: 'Starting new chat…', resume: 'Continuing here…', join: 'Joining live session…', detach: 'Detaching to read-only…', branch: 'Starting continuation…', reduce: 'Reducing context and verifying reversibility…', terminal: 'Preparing terminal handoff…', export: 'Exporting losslessly…', interrupt: 'Stopping agent…', respond: 'Sending response…', configureHarness: 'Updating harness settings…', loadEarlier: 'Loading earlier messages…', loadSessions: 'Loading more chats…', refresh: 'Retrying…' };
|
|
802
895
|
return labels[operation] ?? `${operation.replaceAll('_', ' ')}…`;
|
|
803
896
|
}
|
|
804
897
|
|