@volter-ai-dev/supercode-ui 0.1.62 → 0.1.63
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 +12 -3
- package/activity.mjs +23 -0
- package/components.mjs +48 -7
- package/composer.mjs +1 -0
- package/controller.d.ts +22 -0
- package/controller.mjs +19 -2
- package/conversation.mjs +1 -0
- package/core.mjs +26 -0
- package/embed.mjs +48 -7
- package/index.d.ts +17 -0
- package/messenger.mjs +48 -7
- package/package.json +1 -1
- package/react/activity.mjs +23 -0
- package/react/components.mjs +48 -7
- package/react/composer.mjs +1 -0
- package/react/conversation.mjs +1 -0
- package/react/messenger.mjs +48 -7
- package/react/sessions.mjs +1 -0
- package/react/settings.mjs +25 -6
- package/react/subagents.mjs +1 -0
- package/sessions.mjs +1 -0
- package/settings.mjs +25 -6
- package/subagents.mjs +1 -0
package/README.md
CHANGED
|
@@ -161,9 +161,13 @@ Harness inventory also retains normalized auth, runtime, protocol, repair, and a
|
|
|
161
161
|
evidence. The new-chat view renders unavailable harnesses in a compact `HarnessReadiness` section;
|
|
162
162
|
hosts can replace that component while continuing to consume the same readiness contract. For an
|
|
163
163
|
installed Claude Code or Codex that needs authentication, the default component emits the single
|
|
164
|
-
`authenticateHarness` intent. A trusted host
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
`authenticateHarness` intent. A trusted host constructs the client's
|
|
165
|
+
`HarnessAuthenticationController` with a visible terminal/process adapter and supplies it to the
|
|
166
|
+
controller binding as `authentication`. The shared controller selects the native method, handles
|
|
167
|
+
timeout/cancellation/verification, refreshes inventory after success, and exposes only sanitized
|
|
168
|
+
progress to the default component. The browser-only UI never receives a launch command, spawns a
|
|
169
|
+
local process, or handles credentials itself. `onAuthenticateHarness` remains a legacy escape hatch
|
|
170
|
+
for hosts that have not adopted the shared lifecycle.
|
|
167
171
|
|
|
168
172
|
When a controlled runtime truthfully advertises native steering, the composer sends a plain-text
|
|
169
173
|
message into the active turn and keeps a separate secondary action for queueing a follow-up. With
|
|
@@ -179,6 +183,11 @@ Trusted desktop, editor, and Node hosts can avoid rewriting ordinary snapshot an
|
|
|
179
183
|
import { createControllerBinding } from '@volter-ai-dev/supercode-ui/controller';
|
|
180
184
|
|
|
181
185
|
const binding = createControllerBinding(controller, {
|
|
186
|
+
authentication,
|
|
187
|
+
authenticationRequest: () => ({
|
|
188
|
+
environment: isRemoteClient ? 'headless' : 'local_browser',
|
|
189
|
+
cwd: projectRoot,
|
|
190
|
+
}),
|
|
182
191
|
onDraft: saveDraft,
|
|
183
192
|
onAcknowledge: clearAttention,
|
|
184
193
|
onArtifact: materializeArtifactInTrustedHost,
|
package/activity.mjs
CHANGED
|
@@ -55,6 +55,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
55
55
|
reductionReceipt: null,
|
|
56
56
|
interopSettings: null,
|
|
57
57
|
interopSettingsError: null,
|
|
58
|
+
harnessAuthentication: null,
|
|
58
59
|
error: null,
|
|
59
60
|
recoverable: false,
|
|
60
61
|
harnesses: Object.freeze([]),
|
|
@@ -74,12 +75,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
74
75
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
75
76
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
76
77
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
78
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
77
79
|
var MAX_TOOL_FIELDS = 8;
|
|
78
80
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
79
81
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
80
82
|
function record(value) {
|
|
81
83
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
82
84
|
}
|
|
85
|
+
function readHarnessAuthentication(value) {
|
|
86
|
+
const flow = record(value);
|
|
87
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
88
|
+
const plan = record(flow.plan);
|
|
89
|
+
const error = record(flow.error);
|
|
90
|
+
return {
|
|
91
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
92
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
93
|
+
phase: flow.phase,
|
|
94
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
95
|
+
plan: plan ? {
|
|
96
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
97
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
98
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
99
|
+
headless: plan.headless === true,
|
|
100
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
101
|
+
} : null,
|
|
102
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
103
|
+
};
|
|
104
|
+
}
|
|
83
105
|
function string(value, fallback = "") {
|
|
84
106
|
return typeof value === "string" ? value : fallback;
|
|
85
107
|
}
|
|
@@ -754,6 +776,7 @@ function normalizeUiState(value) {
|
|
|
754
776
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
755
777
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
756
778
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
779
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
757
780
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
758
781
|
recoverable: raw.recoverable === true,
|
|
759
782
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
package/components.mjs
CHANGED
|
@@ -58,6 +58,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
58
58
|
reductionReceipt: null,
|
|
59
59
|
interopSettings: null,
|
|
60
60
|
interopSettingsError: null,
|
|
61
|
+
harnessAuthentication: null,
|
|
61
62
|
error: null,
|
|
62
63
|
recoverable: false,
|
|
63
64
|
harnesses: Object.freeze([]),
|
|
@@ -77,12 +78,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
77
78
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
78
79
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
79
80
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
81
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
80
82
|
var MAX_TOOL_FIELDS = 8;
|
|
81
83
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
82
84
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
83
85
|
function record(value) {
|
|
84
86
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
85
87
|
}
|
|
88
|
+
function readHarnessAuthentication(value) {
|
|
89
|
+
const flow = record(value);
|
|
90
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
91
|
+
const plan = record(flow.plan);
|
|
92
|
+
const error = record(flow.error);
|
|
93
|
+
return {
|
|
94
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
95
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
96
|
+
phase: flow.phase,
|
|
97
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
98
|
+
plan: plan ? {
|
|
99
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
100
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
101
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
102
|
+
headless: plan.headless === true,
|
|
103
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
104
|
+
} : null,
|
|
105
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
106
|
+
};
|
|
107
|
+
}
|
|
86
108
|
function string(value, fallback = "") {
|
|
87
109
|
return typeof value === "string" ? value : fallback;
|
|
88
110
|
}
|
|
@@ -766,6 +788,7 @@ function normalizeUiState(value) {
|
|
|
766
788
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
767
789
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
768
790
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
791
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
769
792
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
770
793
|
recoverable: raw.recoverable === true,
|
|
771
794
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
|
@@ -2646,7 +2669,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2646
2669
|
] })
|
|
2647
2670
|
] });
|
|
2648
2671
|
}
|
|
2649
|
-
|
|
2672
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
2673
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
2674
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
2675
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2676
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
2677
|
+
const completed = flow?.phase === "authenticated";
|
|
2678
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
2679
|
+
return /* @__PURE__ */ jsx10("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
2680
|
+
}
|
|
2681
|
+
function canAuthenticateHarness(item) {
|
|
2682
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
2683
|
+
}
|
|
2684
|
+
function harnessAuthenticationReason(item, state) {
|
|
2685
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2686
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
2687
|
+
}
|
|
2688
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
2650
2689
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
2651
2690
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
2652
2691
|
return /* @__PURE__ */ jsxs9("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -2655,18 +2694,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2655
2694
|
/* @__PURE__ */ jsx10(HarnessLogo, { id: item.id, size: 25 }),
|
|
2656
2695
|
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2657
2696
|
/* @__PURE__ */ jsx10("strong", { children: item.label }),
|
|
2658
|
-
/* @__PURE__ */ jsx10("small", { children:
|
|
2697
|
+
/* @__PURE__ */ jsx10("small", { children: harnessAuthenticationReason(item, state) }),
|
|
2659
2698
|
item.protocol ? /* @__PURE__ */ jsxs9("em", { children: [
|
|
2660
2699
|
item.protocol,
|
|
2661
2700
|
" \xB7 ",
|
|
2662
2701
|
item.runtime
|
|
2663
2702
|
] }) : null
|
|
2664
2703
|
] }),
|
|
2665
|
-
|
|
2704
|
+
/* @__PURE__ */ jsx10(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2705
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2666
2706
|
] }, item.id)) })
|
|
2667
2707
|
] });
|
|
2668
2708
|
}
|
|
2669
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2709
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2670
2710
|
const [open, setOpen] = useState6(false);
|
|
2671
2711
|
const menuId = useId2();
|
|
2672
2712
|
const root = useRef7(null);
|
|
@@ -2731,9 +2771,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2731
2771
|
/* @__PURE__ */ jsx10(Logo, { id: item.id, size: 24 }),
|
|
2732
2772
|
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2733
2773
|
/* @__PURE__ */ jsx10("strong", { children: item.label }),
|
|
2734
|
-
/* @__PURE__ */ jsx10("small", { children:
|
|
2774
|
+
/* @__PURE__ */ jsx10("small", { children: harnessAuthenticationReason(item, state) })
|
|
2735
2775
|
] }),
|
|
2736
|
-
|
|
2776
|
+
/* @__PURE__ */ jsx10(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2777
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2737
2778
|
] }, item.id)) })
|
|
2738
2779
|
] }) : null
|
|
2739
2780
|
] }) : null
|
|
@@ -3231,7 +3272,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
3231
3272
|
} }),
|
|
3232
3273
|
/* @__PURE__ */ jsxs10("footer", { className: "scui-new-envelope-controls", children: [
|
|
3233
3274
|
adapter.pickContext ? /* @__PURE__ */ jsx11("button", { className: "scui-attach", type: "button", "aria-label": labels.attachContext ?? DEFAULT_LABELS.attachContext, disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx11("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx11(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
3234
|
-
/* @__PURE__ */ jsx11(Picker, { harnesses: state.harnesses, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3275
|
+
/* @__PURE__ */ jsx11(Picker, { harnesses: state.harnesses, state, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3235
3276
|
setHarness(value);
|
|
3236
3277
|
remember({ harness: value });
|
|
3237
3278
|
} }),
|
package/composer.mjs
CHANGED
package/controller.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
HarnessId,
|
|
2
3
|
SessionArtifact,
|
|
3
4
|
SessionDescriptor,
|
|
4
5
|
SessionFormat,
|
|
@@ -128,7 +129,28 @@ export interface ControllerBindingOptions {
|
|
|
128
129
|
onCloseSubagents?: () => void | Promise<void>;
|
|
129
130
|
onStartTerminal?: (intent: Extract<SupercodeUiIntent, { action: 'new' }>) => void | Promise<void>;
|
|
130
131
|
onResumeTerminal?: (intent: Extract<SupercodeUiIntent, { action: 'resume' }>) => void | Promise<void>;
|
|
132
|
+
/** Shared Supercode authentication lifecycle. The host-specific execution adapter is injected
|
|
133
|
+
* when constructing this controller; the UI only observes and starts the flow. */
|
|
134
|
+
authentication?: {
|
|
135
|
+
getSnapshot(): unknown;
|
|
136
|
+
subscribe(listener: () => void): () => void;
|
|
137
|
+
authenticate(harness: HarnessId, request?: {
|
|
138
|
+
environment?: 'local_browser' | 'headless';
|
|
139
|
+
method?: 'browser' | 'device_code';
|
|
140
|
+
cwd?: string;
|
|
141
|
+
}): Promise<{ phase: string }>;
|
|
142
|
+
};
|
|
143
|
+
authenticationRequest?: (intent: Extract<SupercodeUiIntent, { action: 'authenticateHarness' }>) => {
|
|
144
|
+
environment?: 'local_browser' | 'headless';
|
|
145
|
+
method?: 'browser' | 'device_code';
|
|
146
|
+
cwd?: string;
|
|
147
|
+
} | Promise<{
|
|
148
|
+
environment?: 'local_browser' | 'headless';
|
|
149
|
+
method?: 'browser' | 'device_code';
|
|
150
|
+
cwd?: string;
|
|
151
|
+
}>;
|
|
131
152
|
/** Launch the native harness-owned sign-in flow. The host owns the process and terminal. */
|
|
153
|
+
/** @deprecated Prefer `authentication`; retained for custom legacy hosts. */
|
|
132
154
|
onAuthenticateHarness?: (intent: Extract<SupercodeUiIntent, { action: 'authenticateHarness' }>) => void | Promise<void>;
|
|
133
155
|
copyText?: UiAdapter['copyText'];
|
|
134
156
|
resolveImage?: UiAdapter['resolveImage'];
|
package/controller.mjs
CHANGED
|
@@ -670,6 +670,14 @@ export async function dispatchControllerIntent(controller, intent, options = {})
|
|
|
670
670
|
if (intent.action === 'interrupt') return controller.dispatch({ type: 'interrupt' });
|
|
671
671
|
if (intent.action === 'respond') return controller.dispatch({ type: 'respond', requestId: intent.requestId, optionId: intent.optionId });
|
|
672
672
|
if (intent.action === 'authenticateHarness') {
|
|
673
|
+
if (options.authentication) {
|
|
674
|
+
const request = (await options.authenticationRequest?.(intent)) ?? {};
|
|
675
|
+
const result = await options.authentication.authenticate(intent.harness, request);
|
|
676
|
+
if (result?.phase === 'authenticated') {
|
|
677
|
+
await controller.dispatch({ type: 'refresh', autoObserve: false, silent: true });
|
|
678
|
+
}
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
673
681
|
return options.onAuthenticateHarness
|
|
674
682
|
? options.onAuthenticateHarness(intent)
|
|
675
683
|
: options.onUnsupported?.(intent);
|
|
@@ -705,7 +713,12 @@ export function createControllerBinding(controller, options = {}) {
|
|
|
705
713
|
if (!controller || typeof controller.getSnapshot !== 'function' || typeof controller.subscribe !== 'function' || typeof controller.dispatch !== 'function') {
|
|
706
714
|
throw new TypeError('createControllerBinding requires a SupercodeController-compatible object');
|
|
707
715
|
}
|
|
708
|
-
const getState = () =>
|
|
716
|
+
const getState = () => {
|
|
717
|
+
const state = projectClientSnapshot(controller.getSnapshot(), options.projection?.() ?? {});
|
|
718
|
+
return options.authentication
|
|
719
|
+
? normalizeUiState({ ...state, harnessAuthentication: options.authentication.getSnapshot() })
|
|
720
|
+
: state;
|
|
721
|
+
};
|
|
709
722
|
const adapter = {
|
|
710
723
|
onIntent(intent) {
|
|
711
724
|
return Promise.resolve(options.onIntent?.(intent))
|
|
@@ -724,7 +737,11 @@ export function createControllerBinding(controller, options = {}) {
|
|
|
724
737
|
adapter,
|
|
725
738
|
getState,
|
|
726
739
|
subscribe(listener) {
|
|
727
|
-
|
|
740
|
+
const unsubscribers = [controller.subscribe(() => listener(getState()))];
|
|
741
|
+
if (options.authentication?.subscribe) {
|
|
742
|
+
unsubscribers.push(options.authentication.subscribe(() => listener(getState())));
|
|
743
|
+
}
|
|
744
|
+
return () => { for (const unsubscribe of unsubscribers) unsubscribe(); };
|
|
728
745
|
},
|
|
729
746
|
};
|
|
730
747
|
}
|
package/conversation.mjs
CHANGED
package/core.mjs
CHANGED
|
@@ -56,6 +56,7 @@ export const EMPTY_UI_STATE = Object.freeze({
|
|
|
56
56
|
reductionReceipt: null,
|
|
57
57
|
interopSettings: null,
|
|
58
58
|
interopSettingsError: null,
|
|
59
|
+
harnessAuthentication: null,
|
|
59
60
|
error: null,
|
|
60
61
|
recoverable: false,
|
|
61
62
|
harnesses: Object.freeze([]),
|
|
@@ -76,6 +77,7 @@ const STARTUP = new Set(['connecting', 'starting', 'discovering', 'ready']);
|
|
|
76
77
|
const FIDELITY = new Set(['byte_lossless', 'value_lossless', 'semantic']);
|
|
77
78
|
const TOOL_CATEGORIES = new Set(['read', 'search', 'edit', 'command', 'test', 'web', 'agent', 'plan', 'other']);
|
|
78
79
|
const TOOL_DETAILS = new Set(['file', 'matches', 'diff', 'terminal', 'web', 'agent', 'plan', 'fields']);
|
|
80
|
+
const AUTHENTICATION_PHASES = new Set(['idle', 'checking', 'required', 'configured', 'unavailable', 'launching', 'awaiting_user', 'verifying', 'authenticated', 'failed', 'cancelled']);
|
|
79
81
|
const MAX_TOOL_FIELDS = 8;
|
|
80
82
|
const MAX_TOOL_FIELD_CHARS = 800;
|
|
81
83
|
const MAX_TOOL_PREVIEW_CHARS = 4_000;
|
|
@@ -84,6 +86,29 @@ function record(value) {
|
|
|
84
86
|
return value !== null && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
85
87
|
}
|
|
86
88
|
|
|
89
|
+
function readHarnessAuthentication(value) {
|
|
90
|
+
const flow = record(value);
|
|
91
|
+
if (flow?.schema !== 'supercode.harness-authentication-flow.v1' || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
92
|
+
const plan = record(flow.plan);
|
|
93
|
+
const error = record(flow.error);
|
|
94
|
+
return {
|
|
95
|
+
schema: 'supercode.harness-authentication-flow.v1',
|
|
96
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
97
|
+
phase: flow.phase,
|
|
98
|
+
harness: typeof flow.harness === 'string' ? boundedString(flow.harness, 100) : null,
|
|
99
|
+
plan: plan ? {
|
|
100
|
+
method: plan.method === 'device_code' ? 'device_code' : 'browser',
|
|
101
|
+
interaction: plan.interaction === 'device_code' ? 'device_code' : 'browser',
|
|
102
|
+
browserBehavior: plan.browserBehavior === 'none' ? 'none' : 'native_auto',
|
|
103
|
+
headless: plan.headless === true,
|
|
104
|
+
instructions: boundedString(plan.instructions, 2_000),
|
|
105
|
+
} : null,
|
|
106
|
+
error: error && typeof error.message === 'string'
|
|
107
|
+
? { code: boundedString(error.code, 100), message: boundedString(error.message, 2_000) }
|
|
108
|
+
: null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
87
112
|
function string(value, fallback = '') {
|
|
88
113
|
return typeof value === 'string' ? value : fallback;
|
|
89
114
|
}
|
|
@@ -819,6 +844,7 @@ export function normalizeUiState(value) {
|
|
|
819
844
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
820
845
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
821
846
|
interopSettingsError: typeof raw.interopSettingsError === 'string' ? boundedString(raw.interopSettingsError) : null,
|
|
847
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
822
848
|
error: typeof raw.error === 'string' ? raw.error : null,
|
|
823
849
|
recoverable: raw.recoverable === true,
|
|
824
850
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
package/embed.mjs
CHANGED
|
@@ -61,6 +61,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
61
61
|
reductionReceipt: null,
|
|
62
62
|
interopSettings: null,
|
|
63
63
|
interopSettingsError: null,
|
|
64
|
+
harnessAuthentication: null,
|
|
64
65
|
error: null,
|
|
65
66
|
recoverable: false,
|
|
66
67
|
harnesses: Object.freeze([]),
|
|
@@ -80,12 +81,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
80
81
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
81
82
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
82
83
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
84
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
83
85
|
var MAX_TOOL_FIELDS = 8;
|
|
84
86
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
85
87
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
86
88
|
function record(value) {
|
|
87
89
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
88
90
|
}
|
|
91
|
+
function readHarnessAuthentication(value) {
|
|
92
|
+
const flow = record(value);
|
|
93
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
94
|
+
const plan = record(flow.plan);
|
|
95
|
+
const error = record(flow.error);
|
|
96
|
+
return {
|
|
97
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
98
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
99
|
+
phase: flow.phase,
|
|
100
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
101
|
+
plan: plan ? {
|
|
102
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
103
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
104
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
105
|
+
headless: plan.headless === true,
|
|
106
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
107
|
+
} : null,
|
|
108
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
109
|
+
};
|
|
110
|
+
}
|
|
89
111
|
function string(value, fallback = "") {
|
|
90
112
|
return typeof value === "string" ? value : fallback;
|
|
91
113
|
}
|
|
@@ -769,6 +791,7 @@ function normalizeUiState(value) {
|
|
|
769
791
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
770
792
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
771
793
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
794
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
772
795
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
773
796
|
recoverable: raw.recoverable === true,
|
|
774
797
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
|
@@ -2563,7 +2586,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2563
2586
|
] })
|
|
2564
2587
|
] });
|
|
2565
2588
|
}
|
|
2566
|
-
|
|
2589
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
2590
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
2591
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
2592
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2593
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
2594
|
+
const completed = flow?.phase === "authenticated";
|
|
2595
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
2596
|
+
return /* @__PURE__ */ jsx9("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
2597
|
+
}
|
|
2598
|
+
function canAuthenticateHarness(item) {
|
|
2599
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
2600
|
+
}
|
|
2601
|
+
function harnessAuthenticationReason(item, state) {
|
|
2602
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2603
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
2604
|
+
}
|
|
2605
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
2567
2606
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
2568
2607
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
2569
2608
|
return /* @__PURE__ */ jsxs8("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -2572,18 +2611,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2572
2611
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: item.id, size: 25 }),
|
|
2573
2612
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2574
2613
|
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2575
|
-
/* @__PURE__ */ jsx9("small", { children:
|
|
2614
|
+
/* @__PURE__ */ jsx9("small", { children: harnessAuthenticationReason(item, state) }),
|
|
2576
2615
|
item.protocol ? /* @__PURE__ */ jsxs8("em", { children: [
|
|
2577
2616
|
item.protocol,
|
|
2578
2617
|
" \xB7 ",
|
|
2579
2618
|
item.runtime
|
|
2580
2619
|
] }) : null
|
|
2581
2620
|
] }),
|
|
2582
|
-
|
|
2621
|
+
/* @__PURE__ */ jsx9(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2622
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2583
2623
|
] }, item.id)) })
|
|
2584
2624
|
] });
|
|
2585
2625
|
}
|
|
2586
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2626
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2587
2627
|
const [open, setOpen] = useState6(false);
|
|
2588
2628
|
const menuId = useId2();
|
|
2589
2629
|
const root = useRef7(null);
|
|
@@ -2648,9 +2688,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2648
2688
|
/* @__PURE__ */ jsx9(Logo, { id: item.id, size: 24 }),
|
|
2649
2689
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2650
2690
|
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2651
|
-
/* @__PURE__ */ jsx9("small", { children:
|
|
2691
|
+
/* @__PURE__ */ jsx9("small", { children: harnessAuthenticationReason(item, state) })
|
|
2652
2692
|
] }),
|
|
2653
|
-
|
|
2693
|
+
/* @__PURE__ */ jsx9(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2694
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2654
2695
|
] }, item.id)) })
|
|
2655
2696
|
] }) : null
|
|
2656
2697
|
] }) : null
|
|
@@ -3148,7 +3189,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
3148
3189
|
} }),
|
|
3149
3190
|
/* @__PURE__ */ jsxs9("footer", { className: "scui-new-envelope-controls", children: [
|
|
3150
3191
|
adapter.pickContext ? /* @__PURE__ */ jsx10("button", { className: "scui-attach", type: "button", "aria-label": labels.attachContext ?? DEFAULT_LABELS.attachContext, disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx10("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx10(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
3151
|
-
/* @__PURE__ */ jsx10(Picker, { harnesses: state.harnesses, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3192
|
+
/* @__PURE__ */ jsx10(Picker, { harnesses: state.harnesses, state, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3152
3193
|
setHarness(value);
|
|
3153
3194
|
remember({ harness: value });
|
|
3154
3195
|
} }),
|
package/index.d.ts
CHANGED
|
@@ -258,6 +258,21 @@ export interface HarnessInteropSettingsModel {
|
|
|
258
258
|
advisories: HarnessInteropAdvisoryModel[];
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
export interface HarnessAuthenticationUiState {
|
|
262
|
+
schema: 'supercode.harness-authentication-flow.v1';
|
|
263
|
+
revision: number;
|
|
264
|
+
phase: 'idle' | 'checking' | 'required' | 'configured' | 'unavailable' | 'launching' | 'awaiting_user' | 'verifying' | 'authenticated' | 'failed' | 'cancelled';
|
|
265
|
+
harness: HarnessId | null;
|
|
266
|
+
plan: {
|
|
267
|
+
method: 'browser' | 'device_code';
|
|
268
|
+
interaction: 'browser' | 'device_code';
|
|
269
|
+
browserBehavior: 'native_auto' | 'none';
|
|
270
|
+
headless: boolean;
|
|
271
|
+
instructions: string;
|
|
272
|
+
} | null;
|
|
273
|
+
error: { code: string; message: string } | null;
|
|
274
|
+
}
|
|
275
|
+
|
|
261
276
|
export interface SessionAttention {
|
|
262
277
|
key: string;
|
|
263
278
|
kind: 'unseen' | 'finished' | 'failed';
|
|
@@ -314,6 +329,7 @@ export interface SupercodeUiState {
|
|
|
314
329
|
reductionReceipt: ReductionReceiptModel | null;
|
|
315
330
|
interopSettings: HarnessInteropSettingsModel | null;
|
|
316
331
|
interopSettingsError: string | null;
|
|
332
|
+
harnessAuthentication: HarnessAuthenticationUiState | null;
|
|
317
333
|
error: string | null;
|
|
318
334
|
recoverable: boolean;
|
|
319
335
|
harnesses: HarnessOption[];
|
|
@@ -468,6 +484,7 @@ export interface HarnessSettingsPanelProps {
|
|
|
468
484
|
|
|
469
485
|
export interface HarnessPickerProps {
|
|
470
486
|
harnesses: HarnessOption[];
|
|
487
|
+
state?: SupercodeUiState;
|
|
471
488
|
value: HarnessId;
|
|
472
489
|
disabled?: boolean;
|
|
473
490
|
adapter?: Pick<UiAdapter, 'copyText' | 'onIntent'>;
|
package/messenger.mjs
CHANGED
|
@@ -58,6 +58,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
58
58
|
reductionReceipt: null,
|
|
59
59
|
interopSettings: null,
|
|
60
60
|
interopSettingsError: null,
|
|
61
|
+
harnessAuthentication: null,
|
|
61
62
|
error: null,
|
|
62
63
|
recoverable: false,
|
|
63
64
|
harnesses: Object.freeze([]),
|
|
@@ -77,12 +78,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
77
78
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
78
79
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
79
80
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
81
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
80
82
|
var MAX_TOOL_FIELDS = 8;
|
|
81
83
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
82
84
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
83
85
|
function record(value) {
|
|
84
86
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
85
87
|
}
|
|
88
|
+
function readHarnessAuthentication(value) {
|
|
89
|
+
const flow = record(value);
|
|
90
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
91
|
+
const plan = record(flow.plan);
|
|
92
|
+
const error = record(flow.error);
|
|
93
|
+
return {
|
|
94
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
95
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
96
|
+
phase: flow.phase,
|
|
97
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
98
|
+
plan: plan ? {
|
|
99
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
100
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
101
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
102
|
+
headless: plan.headless === true,
|
|
103
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
104
|
+
} : null,
|
|
105
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
106
|
+
};
|
|
107
|
+
}
|
|
86
108
|
function string(value, fallback = "") {
|
|
87
109
|
return typeof value === "string" ? value : fallback;
|
|
88
110
|
}
|
|
@@ -766,6 +788,7 @@ function normalizeUiState(value) {
|
|
|
766
788
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
767
789
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
768
790
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
791
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
769
792
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
770
793
|
recoverable: raw.recoverable === true,
|
|
771
794
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
|
@@ -2560,7 +2583,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2560
2583
|
] })
|
|
2561
2584
|
] });
|
|
2562
2585
|
}
|
|
2563
|
-
|
|
2586
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
2587
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
2588
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
2589
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2590
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
2591
|
+
const completed = flow?.phase === "authenticated";
|
|
2592
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
2593
|
+
return /* @__PURE__ */ jsx9("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
2594
|
+
}
|
|
2595
|
+
function canAuthenticateHarness(item) {
|
|
2596
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
2597
|
+
}
|
|
2598
|
+
function harnessAuthenticationReason(item, state) {
|
|
2599
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2600
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
2601
|
+
}
|
|
2602
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
2564
2603
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
2565
2604
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
2566
2605
|
return /* @__PURE__ */ jsxs8("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -2569,18 +2608,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2569
2608
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: item.id, size: 25 }),
|
|
2570
2609
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2571
2610
|
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2572
|
-
/* @__PURE__ */ jsx9("small", { children:
|
|
2611
|
+
/* @__PURE__ */ jsx9("small", { children: harnessAuthenticationReason(item, state) }),
|
|
2573
2612
|
item.protocol ? /* @__PURE__ */ jsxs8("em", { children: [
|
|
2574
2613
|
item.protocol,
|
|
2575
2614
|
" \xB7 ",
|
|
2576
2615
|
item.runtime
|
|
2577
2616
|
] }) : null
|
|
2578
2617
|
] }),
|
|
2579
|
-
|
|
2618
|
+
/* @__PURE__ */ jsx9(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2619
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2580
2620
|
] }, item.id)) })
|
|
2581
2621
|
] });
|
|
2582
2622
|
}
|
|
2583
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2623
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2584
2624
|
const [open, setOpen] = useState6(false);
|
|
2585
2625
|
const menuId = useId2();
|
|
2586
2626
|
const root = useRef7(null);
|
|
@@ -2645,9 +2685,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2645
2685
|
/* @__PURE__ */ jsx9(Logo, { id: item.id, size: 24 }),
|
|
2646
2686
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2647
2687
|
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2648
|
-
/* @__PURE__ */ jsx9("small", { children:
|
|
2688
|
+
/* @__PURE__ */ jsx9("small", { children: harnessAuthenticationReason(item, state) })
|
|
2649
2689
|
] }),
|
|
2650
|
-
|
|
2690
|
+
/* @__PURE__ */ jsx9(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2691
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2651
2692
|
] }, item.id)) })
|
|
2652
2693
|
] }) : null
|
|
2653
2694
|
] }) : null
|
|
@@ -3145,7 +3186,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
3145
3186
|
} }),
|
|
3146
3187
|
/* @__PURE__ */ jsxs9("footer", { className: "scui-new-envelope-controls", children: [
|
|
3147
3188
|
adapter.pickContext ? /* @__PURE__ */ jsx10("button", { className: "scui-attach", type: "button", "aria-label": labels.attachContext ?? DEFAULT_LABELS.attachContext, disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx10("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx10(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
3148
|
-
/* @__PURE__ */ jsx10(Picker, { harnesses: state.harnesses, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3189
|
+
/* @__PURE__ */ jsx10(Picker, { harnesses: state.harnesses, state, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3149
3190
|
setHarness(value);
|
|
3150
3191
|
remember({ harness: value });
|
|
3151
3192
|
} }),
|
package/package.json
CHANGED
package/react/activity.mjs
CHANGED
|
@@ -55,6 +55,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
55
55
|
reductionReceipt: null,
|
|
56
56
|
interopSettings: null,
|
|
57
57
|
interopSettingsError: null,
|
|
58
|
+
harnessAuthentication: null,
|
|
58
59
|
error: null,
|
|
59
60
|
recoverable: false,
|
|
60
61
|
harnesses: Object.freeze([]),
|
|
@@ -74,12 +75,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
74
75
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
75
76
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
76
77
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
78
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
77
79
|
var MAX_TOOL_FIELDS = 8;
|
|
78
80
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
79
81
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
80
82
|
function record(value) {
|
|
81
83
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
82
84
|
}
|
|
85
|
+
function readHarnessAuthentication(value) {
|
|
86
|
+
const flow = record(value);
|
|
87
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
88
|
+
const plan = record(flow.plan);
|
|
89
|
+
const error = record(flow.error);
|
|
90
|
+
return {
|
|
91
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
92
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
93
|
+
phase: flow.phase,
|
|
94
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
95
|
+
plan: plan ? {
|
|
96
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
97
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
98
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
99
|
+
headless: plan.headless === true,
|
|
100
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
101
|
+
} : null,
|
|
102
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
103
|
+
};
|
|
104
|
+
}
|
|
83
105
|
function string(value, fallback = "") {
|
|
84
106
|
return typeof value === "string" ? value : fallback;
|
|
85
107
|
}
|
|
@@ -754,6 +776,7 @@ function normalizeUiState(value) {
|
|
|
754
776
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
755
777
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
756
778
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
779
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
757
780
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
758
781
|
recoverable: raw.recoverable === true,
|
|
759
782
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
package/react/components.mjs
CHANGED
|
@@ -58,6 +58,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
58
58
|
reductionReceipt: null,
|
|
59
59
|
interopSettings: null,
|
|
60
60
|
interopSettingsError: null,
|
|
61
|
+
harnessAuthentication: null,
|
|
61
62
|
error: null,
|
|
62
63
|
recoverable: false,
|
|
63
64
|
harnesses: Object.freeze([]),
|
|
@@ -77,12 +78,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
77
78
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
78
79
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
79
80
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
81
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
80
82
|
var MAX_TOOL_FIELDS = 8;
|
|
81
83
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
82
84
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
83
85
|
function record(value) {
|
|
84
86
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
85
87
|
}
|
|
88
|
+
function readHarnessAuthentication(value) {
|
|
89
|
+
const flow = record(value);
|
|
90
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
91
|
+
const plan = record(flow.plan);
|
|
92
|
+
const error = record(flow.error);
|
|
93
|
+
return {
|
|
94
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
95
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
96
|
+
phase: flow.phase,
|
|
97
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
98
|
+
plan: plan ? {
|
|
99
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
100
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
101
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
102
|
+
headless: plan.headless === true,
|
|
103
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
104
|
+
} : null,
|
|
105
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
106
|
+
};
|
|
107
|
+
}
|
|
86
108
|
function string(value, fallback = "") {
|
|
87
109
|
return typeof value === "string" ? value : fallback;
|
|
88
110
|
}
|
|
@@ -766,6 +788,7 @@ function normalizeUiState(value) {
|
|
|
766
788
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
767
789
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
768
790
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
791
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
769
792
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
770
793
|
recoverable: raw.recoverable === true,
|
|
771
794
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
|
@@ -2646,7 +2669,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2646
2669
|
] })
|
|
2647
2670
|
] });
|
|
2648
2671
|
}
|
|
2649
|
-
|
|
2672
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
2673
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
2674
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
2675
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2676
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
2677
|
+
const completed = flow?.phase === "authenticated";
|
|
2678
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
2679
|
+
return /* @__PURE__ */ jsx10("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
2680
|
+
}
|
|
2681
|
+
function canAuthenticateHarness(item) {
|
|
2682
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
2683
|
+
}
|
|
2684
|
+
function harnessAuthenticationReason(item, state) {
|
|
2685
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2686
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
2687
|
+
}
|
|
2688
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
2650
2689
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
2651
2690
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
2652
2691
|
return /* @__PURE__ */ jsxs9("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -2655,18 +2694,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2655
2694
|
/* @__PURE__ */ jsx10(HarnessLogo, { id: item.id, size: 25 }),
|
|
2656
2695
|
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2657
2696
|
/* @__PURE__ */ jsx10("strong", { children: item.label }),
|
|
2658
|
-
/* @__PURE__ */ jsx10("small", { children:
|
|
2697
|
+
/* @__PURE__ */ jsx10("small", { children: harnessAuthenticationReason(item, state) }),
|
|
2659
2698
|
item.protocol ? /* @__PURE__ */ jsxs9("em", { children: [
|
|
2660
2699
|
item.protocol,
|
|
2661
2700
|
" \xB7 ",
|
|
2662
2701
|
item.runtime
|
|
2663
2702
|
] }) : null
|
|
2664
2703
|
] }),
|
|
2665
|
-
|
|
2704
|
+
/* @__PURE__ */ jsx10(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2705
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2666
2706
|
] }, item.id)) })
|
|
2667
2707
|
] });
|
|
2668
2708
|
}
|
|
2669
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2709
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2670
2710
|
const [open, setOpen] = useState6(false);
|
|
2671
2711
|
const menuId = useId2();
|
|
2672
2712
|
const root = useRef7(null);
|
|
@@ -2731,9 +2771,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2731
2771
|
/* @__PURE__ */ jsx10(Logo, { id: item.id, size: 24 }),
|
|
2732
2772
|
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2733
2773
|
/* @__PURE__ */ jsx10("strong", { children: item.label }),
|
|
2734
|
-
/* @__PURE__ */ jsx10("small", { children:
|
|
2774
|
+
/* @__PURE__ */ jsx10("small", { children: harnessAuthenticationReason(item, state) })
|
|
2735
2775
|
] }),
|
|
2736
|
-
|
|
2776
|
+
/* @__PURE__ */ jsx10(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2777
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2737
2778
|
] }, item.id)) })
|
|
2738
2779
|
] }) : null
|
|
2739
2780
|
] }) : null
|
|
@@ -3231,7 +3272,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
3231
3272
|
} }),
|
|
3232
3273
|
/* @__PURE__ */ jsxs10("footer", { className: "scui-new-envelope-controls", children: [
|
|
3233
3274
|
adapter.pickContext ? /* @__PURE__ */ jsx11("button", { className: "scui-attach", type: "button", "aria-label": labels.attachContext ?? DEFAULT_LABELS.attachContext, disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx11("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx11(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
3234
|
-
/* @__PURE__ */ jsx11(Picker, { harnesses: state.harnesses, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3275
|
+
/* @__PURE__ */ jsx11(Picker, { harnesses: state.harnesses, state, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3235
3276
|
setHarness(value);
|
|
3236
3277
|
remember({ harness: value });
|
|
3237
3278
|
} }),
|
package/react/composer.mjs
CHANGED
package/react/conversation.mjs
CHANGED
package/react/messenger.mjs
CHANGED
|
@@ -58,6 +58,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
58
58
|
reductionReceipt: null,
|
|
59
59
|
interopSettings: null,
|
|
60
60
|
interopSettingsError: null,
|
|
61
|
+
harnessAuthentication: null,
|
|
61
62
|
error: null,
|
|
62
63
|
recoverable: false,
|
|
63
64
|
harnesses: Object.freeze([]),
|
|
@@ -77,12 +78,33 @@ var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering",
|
|
|
77
78
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
78
79
|
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
79
80
|
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
81
|
+
var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "required", "configured", "unavailable", "launching", "awaiting_user", "verifying", "authenticated", "failed", "cancelled"]);
|
|
80
82
|
var MAX_TOOL_FIELDS = 8;
|
|
81
83
|
var MAX_TOOL_FIELD_CHARS = 800;
|
|
82
84
|
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
83
85
|
function record(value) {
|
|
84
86
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
85
87
|
}
|
|
88
|
+
function readHarnessAuthentication(value) {
|
|
89
|
+
const flow = record(value);
|
|
90
|
+
if (flow?.schema !== "supercode.harness-authentication-flow.v1" || !AUTHENTICATION_PHASES.has(flow.phase)) return null;
|
|
91
|
+
const plan = record(flow.plan);
|
|
92
|
+
const error = record(flow.error);
|
|
93
|
+
return {
|
|
94
|
+
schema: "supercode.harness-authentication-flow.v1",
|
|
95
|
+
revision: Number.isSafeInteger(flow.revision) ? Math.max(0, flow.revision) : 0,
|
|
96
|
+
phase: flow.phase,
|
|
97
|
+
harness: typeof flow.harness === "string" ? boundedString(flow.harness, 100) : null,
|
|
98
|
+
plan: plan ? {
|
|
99
|
+
method: plan.method === "device_code" ? "device_code" : "browser",
|
|
100
|
+
interaction: plan.interaction === "device_code" ? "device_code" : "browser",
|
|
101
|
+
browserBehavior: plan.browserBehavior === "none" ? "none" : "native_auto",
|
|
102
|
+
headless: plan.headless === true,
|
|
103
|
+
instructions: boundedString(plan.instructions, 2e3)
|
|
104
|
+
} : null,
|
|
105
|
+
error: error && typeof error.message === "string" ? { code: boundedString(error.code, 100), message: boundedString(error.message, 2e3) } : null
|
|
106
|
+
};
|
|
107
|
+
}
|
|
86
108
|
function string(value, fallback = "") {
|
|
87
109
|
return typeof value === "string" ? value : fallback;
|
|
88
110
|
}
|
|
@@ -766,6 +788,7 @@ function normalizeUiState(value) {
|
|
|
766
788
|
reductionReceipt: readReductionReceipt(raw.reductionReceipt),
|
|
767
789
|
interopSettings: readInteropSettings(raw.interopSettings),
|
|
768
790
|
interopSettingsError: typeof raw.interopSettingsError === "string" ? boundedString(raw.interopSettingsError) : null,
|
|
791
|
+
harnessAuthentication: readHarnessAuthentication(raw.harnessAuthentication),
|
|
769
792
|
error: typeof raw.error === "string" ? raw.error : null,
|
|
770
793
|
recoverable: raw.recoverable === true,
|
|
771
794
|
harnesses: Array.isArray(raw.harnesses) ? raw.harnesses.flatMap((candidate) => {
|
|
@@ -2560,7 +2583,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2560
2583
|
] })
|
|
2561
2584
|
] });
|
|
2562
2585
|
}
|
|
2563
|
-
|
|
2586
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
2587
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
2588
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
2589
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2590
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
2591
|
+
const completed = flow?.phase === "authenticated";
|
|
2592
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
2593
|
+
return /* @__PURE__ */ jsx9("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
2594
|
+
}
|
|
2595
|
+
function canAuthenticateHarness(item) {
|
|
2596
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
2597
|
+
}
|
|
2598
|
+
function harnessAuthenticationReason(item, state) {
|
|
2599
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
2600
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
2601
|
+
}
|
|
2602
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
2564
2603
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
2565
2604
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
2566
2605
|
return /* @__PURE__ */ jsxs8("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -2569,18 +2608,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2569
2608
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: item.id, size: 25 }),
|
|
2570
2609
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2571
2610
|
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2572
|
-
/* @__PURE__ */ jsx9("small", { children:
|
|
2611
|
+
/* @__PURE__ */ jsx9("small", { children: harnessAuthenticationReason(item, state) }),
|
|
2573
2612
|
item.protocol ? /* @__PURE__ */ jsxs8("em", { children: [
|
|
2574
2613
|
item.protocol,
|
|
2575
2614
|
" \xB7 ",
|
|
2576
2615
|
item.runtime
|
|
2577
2616
|
] }) : null
|
|
2578
2617
|
] }),
|
|
2579
|
-
|
|
2618
|
+
/* @__PURE__ */ jsx9(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2619
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2580
2620
|
] }, item.id)) })
|
|
2581
2621
|
] });
|
|
2582
2622
|
}
|
|
2583
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2623
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2584
2624
|
const [open, setOpen] = useState6(false);
|
|
2585
2625
|
const menuId = useId2();
|
|
2586
2626
|
const root = useRef7(null);
|
|
@@ -2645,9 +2685,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2645
2685
|
/* @__PURE__ */ jsx9(Logo, { id: item.id, size: 24 }),
|
|
2646
2686
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2647
2687
|
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2648
|
-
/* @__PURE__ */ jsx9("small", { children:
|
|
2688
|
+
/* @__PURE__ */ jsx9("small", { children: harnessAuthenticationReason(item, state) })
|
|
2649
2689
|
] }),
|
|
2650
|
-
|
|
2690
|
+
/* @__PURE__ */ jsx9(HarnessAuthenticationButton, { item, state, adapter }),
|
|
2691
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2651
2692
|
] }, item.id)) })
|
|
2652
2693
|
] }) : null
|
|
2653
2694
|
] }) : null
|
|
@@ -3145,7 +3186,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
3145
3186
|
} }),
|
|
3146
3187
|
/* @__PURE__ */ jsxs9("footer", { className: "scui-new-envelope-controls", children: [
|
|
3147
3188
|
adapter.pickContext ? /* @__PURE__ */ jsx10("button", { className: "scui-attach", type: "button", "aria-label": labels.attachContext ?? DEFAULT_LABELS.attachContext, disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx10("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx10(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
3148
|
-
/* @__PURE__ */ jsx10(Picker, { harnesses: state.harnesses, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3189
|
+
/* @__PURE__ */ jsx10(Picker, { harnesses: state.harnesses, state, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3149
3190
|
setHarness(value);
|
|
3150
3191
|
remember({ harness: value });
|
|
3151
3192
|
} }),
|
package/react/sessions.mjs
CHANGED
package/react/settings.mjs
CHANGED
|
@@ -58,6 +58,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
58
58
|
reductionReceipt: null,
|
|
59
59
|
interopSettings: null,
|
|
60
60
|
interopSettingsError: null,
|
|
61
|
+
harnessAuthentication: null,
|
|
61
62
|
error: null,
|
|
62
63
|
recoverable: false,
|
|
63
64
|
harnesses: Object.freeze([]),
|
|
@@ -302,7 +303,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
302
303
|
] })
|
|
303
304
|
] });
|
|
304
305
|
}
|
|
305
|
-
|
|
306
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
307
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
308
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
309
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
310
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
311
|
+
const completed = flow?.phase === "authenticated";
|
|
312
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
313
|
+
return /* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
314
|
+
}
|
|
315
|
+
function canAuthenticateHarness(item) {
|
|
316
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
317
|
+
}
|
|
318
|
+
function harnessAuthenticationReason(item, state) {
|
|
319
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
320
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
321
|
+
}
|
|
322
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
306
323
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
307
324
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
308
325
|
return /* @__PURE__ */ jsxs3("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -311,18 +328,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
311
328
|
/* @__PURE__ */ jsx3(HarnessLogo, { id: item.id, size: 25 }),
|
|
312
329
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
313
330
|
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
314
|
-
/* @__PURE__ */ jsx3("small", { children:
|
|
331
|
+
/* @__PURE__ */ jsx3("small", { children: harnessAuthenticationReason(item, state) }),
|
|
315
332
|
item.protocol ? /* @__PURE__ */ jsxs3("em", { children: [
|
|
316
333
|
item.protocol,
|
|
317
334
|
" \xB7 ",
|
|
318
335
|
item.runtime
|
|
319
336
|
] }) : null
|
|
320
337
|
] }),
|
|
321
|
-
|
|
338
|
+
/* @__PURE__ */ jsx3(HarnessAuthenticationButton, { item, state, adapter }),
|
|
339
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
322
340
|
] }, item.id)) })
|
|
323
341
|
] });
|
|
324
342
|
}
|
|
325
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
343
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
326
344
|
const [open, setOpen] = useState(false);
|
|
327
345
|
const menuId = useId();
|
|
328
346
|
const root = useRef(null);
|
|
@@ -387,9 +405,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
387
405
|
/* @__PURE__ */ jsx3(Logo, { id: item.id, size: 24 }),
|
|
388
406
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
389
407
|
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
390
|
-
/* @__PURE__ */ jsx3("small", { children:
|
|
408
|
+
/* @__PURE__ */ jsx3("small", { children: harnessAuthenticationReason(item, state) })
|
|
391
409
|
] }),
|
|
392
|
-
|
|
410
|
+
/* @__PURE__ */ jsx3(HarnessAuthenticationButton, { item, state, adapter }),
|
|
411
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
393
412
|
] }, item.id)) })
|
|
394
413
|
] }) : null
|
|
395
414
|
] }) : null
|
package/react/subagents.mjs
CHANGED
package/sessions.mjs
CHANGED
package/settings.mjs
CHANGED
|
@@ -58,6 +58,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
58
58
|
reductionReceipt: null,
|
|
59
59
|
interopSettings: null,
|
|
60
60
|
interopSettingsError: null,
|
|
61
|
+
harnessAuthentication: null,
|
|
61
62
|
error: null,
|
|
62
63
|
recoverable: false,
|
|
63
64
|
harnesses: Object.freeze([]),
|
|
@@ -302,7 +303,23 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
302
303
|
] })
|
|
303
304
|
] });
|
|
304
305
|
}
|
|
305
|
-
|
|
306
|
+
var ACTIVE_AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["checking", "launching", "awaiting_user", "verifying"]);
|
|
307
|
+
function HarnessAuthenticationButton({ item, state, adapter }) {
|
|
308
|
+
if (!item.installed || !["claude-code", "codex"].includes(item.id) || ["ready", "configured"].includes(item.auth)) return null;
|
|
309
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
310
|
+
const busy = flow && ACTIVE_AUTHENTICATION_PHASES.has(flow.phase);
|
|
311
|
+
const completed = flow?.phase === "authenticated";
|
|
312
|
+
const label = flow?.phase === "checking" ? "Checking\u2026" : flow?.phase === "launching" ? "Opening\u2026" : flow?.phase === "awaiting_user" ? "Finish sign-in" : flow?.phase === "verifying" ? "Verifying\u2026" : flow?.phase === "authenticated" ? "Signed in" : flow?.phase === "failed" ? "Try again" : "Sign in";
|
|
313
|
+
return /* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(busy || completed), "aria-busy": Boolean(busy), onClick: () => adapter?.onIntent({ action: "authenticateHarness", harness: item.id }), children: label });
|
|
314
|
+
}
|
|
315
|
+
function canAuthenticateHarness(item) {
|
|
316
|
+
return item.installed && ["claude-code", "codex"].includes(item.id) && !["ready", "configured"].includes(item.auth);
|
|
317
|
+
}
|
|
318
|
+
function harnessAuthenticationReason(item, state) {
|
|
319
|
+
const flow = state?.harnessAuthentication?.harness === item.id ? state.harnessAuthentication : null;
|
|
320
|
+
return flow?.error?.message || flow?.plan?.instructions || item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable");
|
|
321
|
+
}
|
|
322
|
+
function HarnessReadiness({ harnesses, state, adapter }) {
|
|
306
323
|
const blocked = harnesses.filter((item) => !item.startable);
|
|
307
324
|
if (!blocked.length || harnesses.some((item) => item.startable)) return null;
|
|
308
325
|
return /* @__PURE__ */ jsxs3("details", { className: "scui-readiness", open: true, children: [
|
|
@@ -311,18 +328,19 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
311
328
|
/* @__PURE__ */ jsx3(HarnessLogo, { id: item.id, size: 25 }),
|
|
312
329
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
313
330
|
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
314
|
-
/* @__PURE__ */ jsx3("small", { children:
|
|
331
|
+
/* @__PURE__ */ jsx3("small", { children: harnessAuthenticationReason(item, state) }),
|
|
315
332
|
item.protocol ? /* @__PURE__ */ jsxs3("em", { children: [
|
|
316
333
|
item.protocol,
|
|
317
334
|
" \xB7 ",
|
|
318
335
|
item.runtime
|
|
319
336
|
] }) : null
|
|
320
337
|
] }),
|
|
321
|
-
|
|
338
|
+
/* @__PURE__ */ jsx3(HarnessAuthenticationButton, { item, state, adapter }),
|
|
339
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
322
340
|
] }, item.id)) })
|
|
323
341
|
] });
|
|
324
342
|
}
|
|
325
|
-
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
343
|
+
function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
326
344
|
const [open, setOpen] = useState(false);
|
|
327
345
|
const menuId = useId();
|
|
328
346
|
const root = useRef(null);
|
|
@@ -387,9 +405,10 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
387
405
|
/* @__PURE__ */ jsx3(Logo, { id: item.id, size: 24 }),
|
|
388
406
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
389
407
|
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
390
|
-
/* @__PURE__ */ jsx3("small", { children:
|
|
408
|
+
/* @__PURE__ */ jsx3("small", { children: harnessAuthenticationReason(item, state) })
|
|
391
409
|
] }),
|
|
392
|
-
|
|
410
|
+
/* @__PURE__ */ jsx3(HarnessAuthenticationButton, { item, state, adapter }),
|
|
411
|
+
!canAuthenticateHarness(item) && item.repair ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
393
412
|
] }, item.id)) })
|
|
394
413
|
] }) : null
|
|
395
414
|
] }) : null
|