@growthub/cli 0.14.0 → 0.14.2
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/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/helper/apply/route.js +99 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/helper/query/route.js +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/sandbox-agent-auth/login/route.js +3 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/sandbox-agent-auth/logout/route.js +3 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/sandbox-agent-auth/status/route.js +3 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/sandbox-run/route.js +84 -10
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/components/WorkspaceHelperSetupModal.jsx +2 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/AgentSwarmPanel.jsx +107 -34
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/DataModelShell.jsx +72 -15
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/HelperSidecar.jsx +264 -22
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/OrchestrationGraphCanvas.jsx +81 -10
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/OrchestrationNodeConfigPanel.jsx +179 -117
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/SandboxAgentAuthPanel.jsx +34 -14
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/SidecarExpandView.jsx +37 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/SwarmRunCockpit.jsx +625 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/helper-commands.js +150 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/globals.css +136 -3
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workflows/WorkflowSurface.jsx +61 -13
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/docs/sandbox-environment-primitive.md +26 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/adapters/local-intelligence-browser-access.js +516 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/default-local-agent-host.js +224 -11
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/default-local-intelligence.js +4 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/default-local-process.js +3 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/index.js +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/sandbox-adapter-registry.js +5 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/data-model/field-contracts.js +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-agent-swarm.js +254 -4
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-graph-runner.js +3 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-graph.js +10 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-run-console.js +412 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/sandbox-agent-auth.js +82 -27
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/sandbox-serverless-flow.js +4 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-data-model.js +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-helper.js +23 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-metadata-store.js +8 -6
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-schema.js +6 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-swarm-proposal.js +554 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/package-lock.json +364 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/package.json +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useMemo, useState } from "react";
|
|
4
|
+
import { Check } from "lucide-react";
|
|
4
5
|
import {
|
|
5
6
|
detectFieldIdsFromLastResponse,
|
|
6
7
|
FILTER_CONJUNCTIONS,
|
|
@@ -19,6 +20,12 @@ const LOCAL_AGENT_ADAPTERS = [
|
|
|
19
20
|
{ value: "local-agent-host", label: "Local agent host" },
|
|
20
21
|
{ value: "local-intelligence", label: "Local intelligence" }
|
|
21
22
|
];
|
|
23
|
+
const LOCAL_INTELLIGENCE_MODE_OPTIONS = [
|
|
24
|
+
{ value: "ollama", label: "ollama (OLLAMA_BASE_URL + /v1/chat/completions)" },
|
|
25
|
+
{ value: "lmstudio", label: "lmstudio (LMSTUDIO_BASE_URL)" },
|
|
26
|
+
{ value: "vllm", label: "vllm (VLLM_BASE_URL required)" },
|
|
27
|
+
{ value: "custom-openai-compatible", label: "custom (use Chat completions URL above)" }
|
|
28
|
+
];
|
|
22
29
|
const EMPTY_AGENT_AUTH_PATCH = {
|
|
23
30
|
agentAuthStatus: "",
|
|
24
31
|
agentAuthProvider: "",
|
|
@@ -28,6 +35,23 @@ const EMPTY_AGENT_AUTH_PATCH = {
|
|
|
28
35
|
agentAuthLastLoginUrl: ""
|
|
29
36
|
};
|
|
30
37
|
|
|
38
|
+
function WorkflowCheckbox({ checked, disabled, onChange, children, title }) {
|
|
39
|
+
return (
|
|
40
|
+
<label className="dm-orchestration-config__field dm-orchestration-config__field-inline dm-workflow-check" title={title}>
|
|
41
|
+
<input
|
|
42
|
+
type="checkbox"
|
|
43
|
+
checked={checked}
|
|
44
|
+
disabled={disabled}
|
|
45
|
+
onChange={(event) => onChange?.(event.target.checked)}
|
|
46
|
+
/>
|
|
47
|
+
<span className="dm-workflow-check__box" aria-hidden="true">
|
|
48
|
+
{checked ? <Check size={13} strokeWidth={2.4} /> : null}
|
|
49
|
+
</span>
|
|
50
|
+
<span>{children}</span>
|
|
51
|
+
</label>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
31
55
|
function getAgentHostOptions() {
|
|
32
56
|
return Object.entries(HOST_AUTH_CATALOG || {}).map(([slug, host]) => ({
|
|
33
57
|
value: slug,
|
|
@@ -409,9 +433,9 @@ function LocalAgentHostControls({
|
|
|
409
433
|
onSandboxRowPatch
|
|
410
434
|
}) {
|
|
411
435
|
const row = sandboxRow && typeof sandboxRow === "object" ? sandboxRow : {};
|
|
412
|
-
const runLocality = String(row.runLocality || "local").trim().toLowerCase() === "serverless" ? "serverless" : "local";
|
|
413
436
|
const adapter = String(row.adapter || "local-process").trim() || "local-process";
|
|
414
437
|
const agentHost = String(row.agentHost || "").trim();
|
|
438
|
+
const browserOn = ["true", "1", "on", "yes"].includes(String(row.browserAccess || "").trim().toLowerCase());
|
|
415
439
|
const hostOptions = getAgentHostOptions();
|
|
416
440
|
const canPatch = typeof onSandboxRowPatch === "function";
|
|
417
441
|
|
|
@@ -426,36 +450,9 @@ function LocalAgentHostControls({
|
|
|
426
450
|
return (
|
|
427
451
|
<div className="dm-orchestration-config__section dm-workflow-agent-runtime">
|
|
428
452
|
<span>Local agent runtime</span>
|
|
429
|
-
<div className="dm-sandbox-locality-toggle" role="group" aria-label="Run locality">
|
|
430
|
-
{["local", "serverless"].map((mode) => (
|
|
431
|
-
<button
|
|
432
|
-
key={mode}
|
|
433
|
-
type="button"
|
|
434
|
-
className={runLocality === mode ? "is-active" : ""}
|
|
435
|
-
disabled={disabled || !canPatch}
|
|
436
|
-
onClick={() => {
|
|
437
|
-
const fields = { runLocality: mode };
|
|
438
|
-
if (mode === "serverless" && ["local-agent-host", "local-intelligence"].includes(adapter)) {
|
|
439
|
-
fields.adapter = "local-process";
|
|
440
|
-
fields.agentHost = "";
|
|
441
|
-
patchWithClearedAgentAuth(fields);
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
patch(fields);
|
|
445
|
-
}}
|
|
446
|
-
>
|
|
447
|
-
{mode === "local" ? "Local" : "Serverless"}
|
|
448
|
-
</button>
|
|
449
|
-
))}
|
|
450
|
-
</div>
|
|
451
453
|
<p className="dm-orchestration-config__hint">
|
|
452
454
|
Same runtime fields as the Data Model sandbox sidecar. Local agent host uses the Paperclip thin adapter on this machine.
|
|
453
455
|
</p>
|
|
454
|
-
{runLocality === "serverless" && (
|
|
455
|
-
<p className="dm-orchestration-config__hint">
|
|
456
|
-
Serverless delegates execution to the configured scheduler/API Registry row; local CLI auth is not used.
|
|
457
|
-
</p>
|
|
458
|
-
)}
|
|
459
456
|
<label className="dm-orchestration-config__field">
|
|
460
457
|
<span>Execution adapter</span>
|
|
461
458
|
<select
|
|
@@ -464,6 +461,7 @@ function LocalAgentHostControls({
|
|
|
464
461
|
onChange={(event) => {
|
|
465
462
|
const nextAdapter = event.target.value;
|
|
466
463
|
patchWithClearedAgentAuth({
|
|
464
|
+
runLocality: "local",
|
|
467
465
|
adapter: nextAdapter,
|
|
468
466
|
agentHost: nextAdapter === "local-agent-host" ? (agentHost || "claude_local") : ""
|
|
469
467
|
});
|
|
@@ -474,13 +472,17 @@ function LocalAgentHostControls({
|
|
|
474
472
|
))}
|
|
475
473
|
</select>
|
|
476
474
|
</label>
|
|
477
|
-
{
|
|
475
|
+
{adapter === "local-agent-host" && (
|
|
478
476
|
<label className="dm-orchestration-config__field">
|
|
479
477
|
<span>Agent host (Paperclip)</span>
|
|
480
478
|
<select
|
|
481
479
|
value={agentHost}
|
|
482
480
|
disabled={disabled || !canPatch}
|
|
483
|
-
onChange={(event) => patchWithClearedAgentAuth({
|
|
481
|
+
onChange={(event) => patchWithClearedAgentAuth({
|
|
482
|
+
runLocality: "local",
|
|
483
|
+
adapter: "local-agent-host",
|
|
484
|
+
agentHost: event.target.value
|
|
485
|
+
})}
|
|
484
486
|
>
|
|
485
487
|
<option value="">Select host...</option>
|
|
486
488
|
{hostOptions.map((item) => (
|
|
@@ -489,7 +491,7 @@ function LocalAgentHostControls({
|
|
|
489
491
|
</select>
|
|
490
492
|
</label>
|
|
491
493
|
)}
|
|
492
|
-
{
|
|
494
|
+
{adapter === "local-agent-host" && isSandboxLocalAgentHost(row) && (
|
|
493
495
|
<SandboxAgentAuthPanel
|
|
494
496
|
objectId={objectId}
|
|
495
497
|
rowName={rowName}
|
|
@@ -498,10 +500,63 @@ function LocalAgentHostControls({
|
|
|
498
500
|
onPatchDraft={patch}
|
|
499
501
|
/>
|
|
500
502
|
)}
|
|
503
|
+
{adapter === "local-intelligence" && (
|
|
504
|
+
<div className="dm-sandbox-local-intel">
|
|
505
|
+
<label className="dm-orchestration-config__field">
|
|
506
|
+
<span>Concrete model id</span>
|
|
507
|
+
<input
|
|
508
|
+
value={row.localModel || ""}
|
|
509
|
+
disabled={disabled || !canPatch}
|
|
510
|
+
placeholder="gemma3:4b"
|
|
511
|
+
onChange={(event) => patch({ runLocality: "local", localModel: event.target.value })}
|
|
512
|
+
/>
|
|
513
|
+
</label>
|
|
514
|
+
<label className="dm-orchestration-config__field">
|
|
515
|
+
<span>Chat completions URL (optional)</span>
|
|
516
|
+
<input
|
|
517
|
+
value={row.localEndpoint || ""}
|
|
518
|
+
disabled={disabled || !canPatch}
|
|
519
|
+
placeholder="http://127.0.0.1:11434/v1/chat/completions"
|
|
520
|
+
onChange={(event) => patch({ runLocality: "local", localEndpoint: event.target.value })}
|
|
521
|
+
/>
|
|
522
|
+
</label>
|
|
523
|
+
<label className="dm-orchestration-config__field">
|
|
524
|
+
<span>Resolver mode</span>
|
|
525
|
+
<select
|
|
526
|
+
value={String(row.intelligenceAdapterMode || "ollama").trim().toLowerCase()}
|
|
527
|
+
disabled={disabled || !canPatch}
|
|
528
|
+
onChange={(event) => patch({ runLocality: "local", intelligenceAdapterMode: event.target.value })}
|
|
529
|
+
>
|
|
530
|
+
{LOCAL_INTELLIGENCE_MODE_OPTIONS.map((item) => (
|
|
531
|
+
<option key={item.value} value={item.value}>{item.label}</option>
|
|
532
|
+
))}
|
|
533
|
+
</select>
|
|
534
|
+
</label>
|
|
535
|
+
<p className="dm-orchestration-config__hint">
|
|
536
|
+
Uses Instructions + Command as the task payload. With sandbox browser access off, tool intents stay proposals. With browser access on, browser tool intents execute through the local browser bridge before the final JSON response is returned.
|
|
537
|
+
</p>
|
|
538
|
+
{browserOn && (
|
|
539
|
+
<p className="dm-orchestration-config__hint">
|
|
540
|
+
This workflow's AI-agent nodes inherit browser access only when their node-level Network permission is enabled.
|
|
541
|
+
</p>
|
|
542
|
+
)}
|
|
543
|
+
</div>
|
|
544
|
+
)}
|
|
501
545
|
</div>
|
|
502
546
|
);
|
|
503
547
|
}
|
|
504
548
|
|
|
549
|
+
function buildNodeAgentAuthDraft(sandboxRow, config) {
|
|
550
|
+
const agentHost = String(config?.agentHost || sandboxRow?.agentHost || "").trim();
|
|
551
|
+
if (!agentHost) return null;
|
|
552
|
+
return {
|
|
553
|
+
...(sandboxRow || {}),
|
|
554
|
+
runLocality: "local",
|
|
555
|
+
adapter: "local-agent-host",
|
|
556
|
+
agentHost
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
|
|
505
560
|
export function OrchestrationNodeConfigPanel({
|
|
506
561
|
node,
|
|
507
562
|
onConfigChange,
|
|
@@ -559,6 +614,28 @@ export function OrchestrationNodeConfigPanel({
|
|
|
559
614
|
|
|
560
615
|
const registryConnected = isApiRegistryTestSuccessful(registryRow);
|
|
561
616
|
const responseMode = config.responseMode || config.mode || "json";
|
|
617
|
+
const nodeAgentAuthDraft = type === "ai-agent" ? buildNodeAgentAuthDraft(sandboxRow, config) : null;
|
|
618
|
+
const canPatchSandboxRow = typeof onSandboxRowPatch === "function";
|
|
619
|
+
const sandboxBrowserOn = ["true", "1", "on", "yes"].includes(String(sandboxRow?.browserAccess || "").trim().toLowerCase());
|
|
620
|
+
const sandboxAdapter = String(sandboxRow?.adapter || "").trim();
|
|
621
|
+
const nodeAdapter = String(config.adapter || "").trim() || sandboxAdapter;
|
|
622
|
+
const nodeUsesLocalIntelligence = nodeAdapter === "local-intelligence";
|
|
623
|
+
|
|
624
|
+
function patchNodeAgentHost(agentHost) {
|
|
625
|
+
const nextHost = String(agentHost || "").trim();
|
|
626
|
+
patchConfig({
|
|
627
|
+
agentHost: nextHost,
|
|
628
|
+
...(nextHost ? { adapter: "local-agent-host" } : {})
|
|
629
|
+
});
|
|
630
|
+
if (nextHost && canPatchSandboxRow) {
|
|
631
|
+
onSandboxRowPatch({
|
|
632
|
+
runLocality: "local",
|
|
633
|
+
adapter: "local-agent-host",
|
|
634
|
+
agentHost: nextHost,
|
|
635
|
+
...EMPTY_AGENT_AUTH_PATCH
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
}
|
|
562
639
|
|
|
563
640
|
return (
|
|
564
641
|
<div className="dm-orchestration-config">
|
|
@@ -696,24 +773,20 @@ export function OrchestrationNodeConfigPanel({
|
|
|
696
773
|
Latest registry test: {registryRow.status}
|
|
697
774
|
</span>
|
|
698
775
|
)}
|
|
699
|
-
<
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
onChange={(e) => patchConfig({ writeSourceRecord: e.target.checked })}
|
|
714
|
-
/>
|
|
715
|
-
<span>Write source record history</span>
|
|
716
|
-
</label>
|
|
776
|
+
<WorkflowCheckbox
|
|
777
|
+
checked={config.writeLastResponse !== false}
|
|
778
|
+
disabled={disabled}
|
|
779
|
+
onChange={(checked) => patchConfig({ writeLastResponse: checked })}
|
|
780
|
+
>
|
|
781
|
+
Write lastResponse on success
|
|
782
|
+
</WorkflowCheckbox>
|
|
783
|
+
<WorkflowCheckbox
|
|
784
|
+
checked={config.writeSourceRecord !== false}
|
|
785
|
+
disabled={disabled}
|
|
786
|
+
onChange={(checked) => patchConfig({ writeSourceRecord: checked })}
|
|
787
|
+
>
|
|
788
|
+
Write source record history
|
|
789
|
+
</WorkflowCheckbox>
|
|
717
790
|
<label className="dm-orchestration-config__field">
|
|
718
791
|
<span>Success HTTP codes</span>
|
|
719
792
|
<input
|
|
@@ -882,15 +955,13 @@ export function OrchestrationNodeConfigPanel({
|
|
|
882
955
|
)}
|
|
883
956
|
</div>
|
|
884
957
|
)}
|
|
885
|
-
<
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
<span>Require confirmation before destructive or version-changing execution</span>
|
|
893
|
-
</label>
|
|
958
|
+
<WorkflowCheckbox
|
|
959
|
+
checked={config.confirmationRequired === true}
|
|
960
|
+
disabled={disabled || config.destructive === true}
|
|
961
|
+
onChange={(checked) => patchConfig({ confirmationRequired: checked })}
|
|
962
|
+
>
|
|
963
|
+
Require confirmation before destructive or version-changing execution
|
|
964
|
+
</WorkflowCheckbox>
|
|
894
965
|
<p className="dm-orchestration-config__hint">
|
|
895
966
|
Data actions bind only to this workspace data model. Execution resolves the latest object schema at run time.
|
|
896
967
|
</p>
|
|
@@ -952,7 +1023,7 @@ export function OrchestrationNodeConfigPanel({
|
|
|
952
1023
|
<select
|
|
953
1024
|
value={config.agentHost || ""}
|
|
954
1025
|
disabled={disabled}
|
|
955
|
-
onChange={(e) =>
|
|
1026
|
+
onChange={(e) => patchNodeAgentHost(e.target.value)}
|
|
956
1027
|
>
|
|
957
1028
|
<option value="">Inherit</option>
|
|
958
1029
|
{Object.entries(HOST_AUTH_CATALOG || {}).map(([slug, host]) => (
|
|
@@ -960,27 +1031,32 @@ export function OrchestrationNodeConfigPanel({
|
|
|
960
1031
|
))}
|
|
961
1032
|
</select>
|
|
962
1033
|
</label>
|
|
963
|
-
|
|
964
|
-
<
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1034
|
+
{nodeAgentAuthDraft && isSandboxLocalAgentHost(nodeAgentAuthDraft) && (
|
|
1035
|
+
<SandboxAgentAuthPanel
|
|
1036
|
+
objectId={objectId}
|
|
1037
|
+
rowName={rowName}
|
|
1038
|
+
draft={nodeAgentAuthDraft}
|
|
1039
|
+
disabled={disabled || !canPatchSandboxRow}
|
|
1040
|
+
onPatchDraft={onSandboxRowPatch}
|
|
969
1041
|
/>
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1042
|
+
)}
|
|
1043
|
+
<WorkflowCheckbox
|
|
1044
|
+
checked={config.required !== false}
|
|
1045
|
+
disabled={disabled}
|
|
1046
|
+
onChange={(checked) => patchConfig({ required: checked })}
|
|
975
1047
|
>
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1048
|
+
Required
|
|
1049
|
+
</WorkflowCheckbox>
|
|
1050
|
+
<WorkflowCheckbox
|
|
1051
|
+
checked={config.networkAccess === true}
|
|
1052
|
+
disabled={disabled}
|
|
1053
|
+
title={sandboxBrowserOn && nodeUsesLocalIntelligence
|
|
1054
|
+
? "Network and browser are granted only when this node permission is on and the sandbox row has browser access on."
|
|
1055
|
+
: "Network is granted only when both this and the row's networkAllow are on. The row's browser access inherits through the same gate."}
|
|
1056
|
+
onChange={(checked) => patchConfig({ networkAccess: checked })}
|
|
1057
|
+
>
|
|
1058
|
+
{sandboxBrowserOn && nodeUsesLocalIntelligence ? "Network + browser" : "Network"}
|
|
1059
|
+
</WorkflowCheckbox>
|
|
984
1060
|
</div>
|
|
985
1061
|
)}
|
|
986
1062
|
|
|
@@ -1013,33 +1089,22 @@ export function OrchestrationNodeConfigPanel({
|
|
|
1013
1089
|
</label>
|
|
1014
1090
|
<div className="dm-orchestration-config__section">
|
|
1015
1091
|
<span>Permissions</span>
|
|
1016
|
-
<
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
<span>Write draft changes only</span>
|
|
1033
|
-
</label>
|
|
1034
|
-
<label className="dm-orchestration-config__field dm-orchestration-config__field-inline">
|
|
1035
|
-
<input
|
|
1036
|
-
type="checkbox"
|
|
1037
|
-
checked={config.networkAccess === true}
|
|
1038
|
-
disabled={disabled}
|
|
1039
|
-
onChange={(e) => patchConfig({ networkAccess: e.target.checked })}
|
|
1040
|
-
/>
|
|
1041
|
-
<span>Allow network access</span>
|
|
1042
|
-
</label>
|
|
1092
|
+
<WorkflowCheckbox checked={config.canReadWorkspace !== false} disabled={disabled} onChange={(checked) => patchConfig({ canReadWorkspace: checked })}>
|
|
1093
|
+
Read workspace data
|
|
1094
|
+
</WorkflowCheckbox>
|
|
1095
|
+
<WorkflowCheckbox checked={config.canWriteDraft === true} disabled={disabled} onChange={(checked) => patchConfig({ canWriteDraft: checked })}>
|
|
1096
|
+
Write draft changes only
|
|
1097
|
+
</WorkflowCheckbox>
|
|
1098
|
+
<WorkflowCheckbox
|
|
1099
|
+
checked={config.networkAccess === true}
|
|
1100
|
+
disabled={disabled}
|
|
1101
|
+
title={sandboxBrowserOn && nodeUsesLocalIntelligence
|
|
1102
|
+
? "This node gets browser access only when this permission and the sandbox row Browser access toggle are both on."
|
|
1103
|
+
: undefined}
|
|
1104
|
+
onChange={(checked) => patchConfig({ networkAccess: checked })}
|
|
1105
|
+
>
|
|
1106
|
+
{sandboxBrowserOn && nodeUsesLocalIntelligence ? "Allow network + browser access" : "Allow network access"}
|
|
1107
|
+
</WorkflowCheckbox>
|
|
1043
1108
|
</div>
|
|
1044
1109
|
<KeyValueRows
|
|
1045
1110
|
label="Output fields"
|
|
@@ -1176,10 +1241,9 @@ export function OrchestrationNodeConfigPanel({
|
|
|
1176
1241
|
<span>Message</span>
|
|
1177
1242
|
<textarea rows={6} value={config.message || ""} disabled={disabled} onChange={(e) => patchConfig({ message: e.target.value })} />
|
|
1178
1243
|
</label>
|
|
1179
|
-
<
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
</label>
|
|
1244
|
+
<WorkflowCheckbox checked={config.requireApproval !== false} disabled={disabled} onChange={(checked) => patchConfig({ requireApproval: checked })}>
|
|
1245
|
+
Require approval before sending
|
|
1246
|
+
</WorkflowCheckbox>
|
|
1183
1247
|
</>
|
|
1184
1248
|
)}
|
|
1185
1249
|
{config.action === "code-function" && (
|
|
@@ -1216,10 +1280,9 @@ export function OrchestrationNodeConfigPanel({
|
|
|
1216
1280
|
valuePlaceholder="Field type or help text"
|
|
1217
1281
|
onChange={(fields) => patchConfig({ fields })}
|
|
1218
1282
|
/>
|
|
1219
|
-
<
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
</label>
|
|
1283
|
+
<WorkflowCheckbox checked={config.required !== false} disabled={disabled} onChange={(checked) => patchConfig({ required: checked })}>
|
|
1284
|
+
Require response before continuing
|
|
1285
|
+
</WorkflowCheckbox>
|
|
1223
1286
|
</div>
|
|
1224
1287
|
)}
|
|
1225
1288
|
|
|
@@ -1233,10 +1296,9 @@ export function OrchestrationNodeConfigPanel({
|
|
|
1233
1296
|
<span>Sample response</span>
|
|
1234
1297
|
<textarea rows={5} value={config.sampleResponse || ""} disabled={disabled} onChange={(e) => patchConfig({ sampleResponse: e.target.value })} />
|
|
1235
1298
|
</label>
|
|
1236
|
-
<
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
</label>
|
|
1299
|
+
<WorkflowCheckbox checked={config.blockPublishOnFailure !== false} disabled={disabled} onChange={(checked) => patchConfig({ blockPublishOnFailure: checked })}>
|
|
1300
|
+
Block Publish unless this step passes
|
|
1301
|
+
</WorkflowCheckbox>
|
|
1240
1302
|
</div>
|
|
1241
1303
|
)}
|
|
1242
1304
|
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
* no second product surface, no terminal emulator — just a uniform
|
|
21
21
|
* readiness bridge.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* The pill represents selected local host readiness. Legacy `reachable`
|
|
24
|
+
* metadata is rendered as Active so Data Model and workflow sidecars stay
|
|
25
|
+
* visually identical after a successful host switch/check path.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import { useCallback, useState } from "react";
|
|
@@ -32,7 +32,7 @@ import { getAgentHostCapabilities } from "@/lib/sandbox-agent-host-catalog";
|
|
|
32
32
|
|
|
33
33
|
const STATUS_LABEL = {
|
|
34
34
|
active: "Active",
|
|
35
|
-
reachable: "
|
|
35
|
+
reachable: "Active",
|
|
36
36
|
stale: "Stale",
|
|
37
37
|
missing: "Missing",
|
|
38
38
|
checking: "Checking",
|
|
@@ -40,10 +40,9 @@ const STATUS_LABEL = {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
function statusKind(status) {
|
|
43
|
-
if (status === "active") return "ok";
|
|
43
|
+
if (status === "active" || status === "reachable") return "ok";
|
|
44
44
|
if (status === "stale") return "warn";
|
|
45
45
|
if (status === "missing") return "bad";
|
|
46
|
-
// "reachable" stays neutral — CLI is installed, but auth is NOT confirmed.
|
|
47
46
|
return "";
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -62,15 +61,28 @@ export function SandboxAgentAuthPanel({ objectId, rowName, draft, disabled, onPa
|
|
|
62
61
|
const [busy, setBusy] = useState(null); // "status" | "login" | "logout" | null
|
|
63
62
|
const [output, setOutput] = useState(null);
|
|
64
63
|
const [message, setMessage] = useState("");
|
|
64
|
+
const [localAuthState, setLocalAuthState] = useState(null);
|
|
65
65
|
|
|
66
66
|
const capabilities = getAgentHostCapabilities(draft);
|
|
67
67
|
const providerMatchesHost = String(draft?.agentAuthProvider || "").trim() === String(draft?.agentHost || "").trim();
|
|
68
|
+
const localMatchesHost =
|
|
69
|
+
localAuthState?.provider &&
|
|
70
|
+
String(localAuthState.provider || "").trim() === String(capabilities?.slug || "").trim();
|
|
68
71
|
const currentStatus =
|
|
69
|
-
|
|
70
|
-
?
|
|
71
|
-
: "
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
localMatchesHost && typeof localAuthState?.status === "string" && localAuthState.status.trim()
|
|
73
|
+
? localAuthState.status.trim()
|
|
74
|
+
: providerMatchesHost && typeof draft?.agentAuthStatus === "string" && draft.agentAuthStatus.trim()
|
|
75
|
+
? draft.agentAuthStatus.trim()
|
|
76
|
+
: "unknown";
|
|
77
|
+
const lastChecked = localMatchesHost && localAuthState?.checkedAt
|
|
78
|
+
? localAuthState.checkedAt
|
|
79
|
+
: providerMatchesHost
|
|
80
|
+
? draft?.agentAuthLastChecked || ""
|
|
81
|
+
: "";
|
|
82
|
+
const lastMessage =
|
|
83
|
+
localMatchesHost && typeof localAuthState?.message === "string"
|
|
84
|
+
? localAuthState.message
|
|
85
|
+
: providerMatchesHost ? draft?.agentAuthLastMessage || "" : "";
|
|
74
86
|
const displayMessage = normalizeAuthMessage(message || lastMessage, capabilities?.label)
|
|
75
87
|
|| (currentStatus === "unknown" ? "Run Check or Login to verify this local agent host." : "");
|
|
76
88
|
|
|
@@ -85,15 +97,23 @@ export function SandboxAgentAuthPanel({ objectId, rowName, draft, disabled, onPa
|
|
|
85
97
|
const res = await fetch(endpoint, {
|
|
86
98
|
method: "POST",
|
|
87
99
|
headers: { "content-type": "application/json" },
|
|
88
|
-
body: JSON.stringify({ objectId, name: rowName })
|
|
100
|
+
body: JSON.stringify({ objectId, name: rowName, agentHost: capabilities.slug })
|
|
89
101
|
});
|
|
90
102
|
const payload = await res.json();
|
|
91
103
|
setOutput(payload);
|
|
92
104
|
setMessage(payload.message || (payload.ok ? "Done" : payload.error || "Failed"));
|
|
105
|
+
if (payload.status) {
|
|
106
|
+
setLocalAuthState({
|
|
107
|
+
status: payload.status,
|
|
108
|
+
provider: payload.provider || capabilities.slug,
|
|
109
|
+
checkedAt: payload.checkedAt || new Date().toISOString(),
|
|
110
|
+
message: payload.message || ""
|
|
111
|
+
});
|
|
112
|
+
}
|
|
93
113
|
if (typeof onPatchDraft === "function" && payload.status) {
|
|
94
114
|
onPatchDraft({
|
|
95
115
|
agentAuthStatus: payload.status,
|
|
96
|
-
agentAuthProvider: payload.provider ||
|
|
116
|
+
agentAuthProvider: payload.provider || capabilities.slug,
|
|
97
117
|
agentAuthLastChecked: payload.checkedAt || new Date().toISOString(),
|
|
98
118
|
agentAuthLastExitCode:
|
|
99
119
|
typeof payload.exitCode === "number" ? payload.exitCode : null,
|
|
@@ -107,7 +127,7 @@ export function SandboxAgentAuthPanel({ objectId, rowName, draft, disabled, onPa
|
|
|
107
127
|
setBusy(null);
|
|
108
128
|
}
|
|
109
129
|
},
|
|
110
|
-
[canAct, objectId, rowName, onPatchDraft,
|
|
130
|
+
[canAct, objectId, rowName, onPatchDraft, capabilities?.slug]
|
|
111
131
|
);
|
|
112
132
|
|
|
113
133
|
const onCheckStatus = () =>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SidecarExpandView — full-width takeover WITHIN the existing helper sidecar
|
|
5
|
+
* system (SWARM_RUN_CONTRACT_V1, Phase 5).
|
|
6
|
+
*
|
|
7
|
+
* Not a modal and not a route: the parent HelperSidecar widens its own aside
|
|
8
|
+
* while this view is active and renders this wrapper inside the same body.
|
|
9
|
+
* Back returns to the prior sidecar view; Esc collapses (handled by the
|
|
10
|
+
* parent so it composes with the sidecar's existing Esc-to-close); the
|
|
11
|
+
* sidecar close button keeps closing the whole sidecar.
|
|
12
|
+
*
|
|
13
|
+
* Reuses the existing sidecar header/body grammar — no new modal stack, no
|
|
14
|
+
* new visual language.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { ArrowLeft } from "lucide-react";
|
|
18
|
+
|
|
19
|
+
export function SidecarExpandView({ title, onBack, children }) {
|
|
20
|
+
return (
|
|
21
|
+
<div className="dm-swarm-expand" data-sidecar-expand="">
|
|
22
|
+
<div className="dm-sidecar-header dm-swarm-expand-head">
|
|
23
|
+
<button
|
|
24
|
+
type="button"
|
|
25
|
+
className="dm-sidecar-icon-btn"
|
|
26
|
+
onClick={onBack}
|
|
27
|
+
aria-label="Back"
|
|
28
|
+
title="Back (Esc)"
|
|
29
|
+
>
|
|
30
|
+
<ArrowLeft size={14} />
|
|
31
|
+
</button>
|
|
32
|
+
<span className="dm-sidecar-title">{title}</span>
|
|
33
|
+
</div>
|
|
34
|
+
<div className="dm-swarm-expand-body">{children}</div>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|