File size: 3,563 Bytes
b152fd5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { useEffect, useState } from "react";
import type { AdapterConfigFieldsProps } from "./types";
import { Field, help } from "../components/agent-config-primitives";

// TODO(issue-worktree-support): re-enable this UI once the workflow is ready to ship.
const SHOW_EXPERIMENTAL_ISSUE_WORKTREE_UI = false;

const inputClass =
  "w-full rounded-md border border-border px-2.5 py-1.5 bg-transparent outline-none text-sm font-mono placeholder:text-muted-foreground/40";

function asRecord(value: unknown): Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value)
    ? (value as Record<string, unknown>)
    : {};
}

function formatJsonObject(value: unknown): string {
  const record = asRecord(value);
  return Object.keys(record).length > 0 ? JSON.stringify(record, null, 2) : "";
}

function updateJsonConfig(
  isCreate: boolean,
  key: "runtimeServicesJson" | "payloadTemplateJson",
  next: string,
  set: AdapterConfigFieldsProps["set"],
  mark: AdapterConfigFieldsProps["mark"],
  configKey: string,
) {
  if (isCreate) {
    set?.({ [key]: next });
    return;
  }

  const trimmed = next.trim();
  if (!trimmed) {
    mark("adapterConfig", configKey, undefined);
    return;
  }

  try {
    const parsed = JSON.parse(trimmed);
    if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
      mark("adapterConfig", configKey, parsed);
    }
  } catch {
    // Keep local draft until JSON is valid.
  }
}

type JsonFieldProps = Pick<
  AdapterConfigFieldsProps,
  "isCreate" | "values" | "set" | "config" | "mark"
>;

export function RuntimeServicesJsonField({
  isCreate,
  values,
  set,
  config,
  mark,
}: JsonFieldProps) {
  if (!SHOW_EXPERIMENTAL_ISSUE_WORKTREE_UI) {
    return null;
  }

  const existing = formatJsonObject(config.workspaceRuntime);
  const [draft, setDraft] = useState(existing);

  useEffect(() => {
    if (!isCreate) setDraft(existing);
  }, [existing, isCreate]);

  const value = isCreate ? values?.runtimeServicesJson ?? "" : draft;

  return (
    <Field label="Runtime services JSON" hint={help.runtimeServicesJson}>
      <textarea
        className={`${inputClass} min-h-[148px]`}
        value={value}
        onChange={(e) => {
          const next = e.target.value;
          if (!isCreate) setDraft(next);
          updateJsonConfig(isCreate, "runtimeServicesJson", next, set, mark, "workspaceRuntime");
        }}
        placeholder={`{\n  "services": [\n    {\n      "name": "preview",\n      "lifecycle": "ephemeral",\n      "metadata": {\n        "purpose": "remote preview"\n      }\n    }\n  ]\n}`}
      />
    </Field>
  );
}

export function PayloadTemplateJsonField({
  isCreate,
  values,
  set,
  config,
  mark,
}: JsonFieldProps) {
  const existing = formatJsonObject(config.payloadTemplate);
  const [draft, setDraft] = useState(existing);

  useEffect(() => {
    if (!isCreate) setDraft(existing);
  }, [existing, isCreate]);

  const value = isCreate ? values?.payloadTemplateJson ?? "" : draft;

  return (
    <Field label="Payload template JSON" hint={help.payloadTemplateJson}>
      <textarea
        className={`${inputClass} min-h-[132px]`}
        value={value}
        onChange={(e) => {
          const next = e.target.value;
          if (!isCreate) setDraft(next);
          updateJsonConfig(isCreate, "payloadTemplateJson", next, set, mark, "payloadTemplate");
        }}
        placeholder={`{\n  "agentId": "remote-agent-123",\n  "metadata": {\n    "team": "platform"\n  }\n}`}
      />
    </Field>
  );
}