@volter-ai-dev/supercode-ui 0.1.29 → 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/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([]),
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
@@ -36,6 +36,7 @@ export {
36
36
  isSendKey,
37
37
  normalizeUiState,
38
38
  operationLabel,
39
+ relativeAge,
39
40
  sessionActivity,
40
41
  sessionDisplayName,
41
42
  terminalCommand,
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 boundedString(value, max) {
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,6 +554,7 @@ 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,
@@ -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) => {
@@ -799,7 +891,7 @@ export function canContinueHere(state) {
799
891
 
800
892
  export function operationLabel(operation) {
801
893
  if (!operation) return '';
802
- 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…' };
803
895
  return labels[operation] ?? `${operation.replaceAll('_', ' ')}…`;
804
896
  }
805
897