paseo-plugin-zcode-provider 0.0.0-stage → 0.2.0

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.
Files changed (141) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +29 -0
  3. package/README.md +112 -2
  4. package/client/account.tsx +827 -0
  5. package/client/diagnostics.tsx +379 -0
  6. package/client/runtime.tsx +296 -0
  7. package/client/settings.tsx +84 -0
  8. package/client/value.tsx +20 -0
  9. package/icon.svg +1 -0
  10. package/index.client.tsx +22 -0
  11. package/index.server.ts +39 -0
  12. package/package.json +77 -4
  13. package/paseo-plugin.json +6 -0
  14. package/server/account.ts +781 -0
  15. package/server/attachments.ts +150 -0
  16. package/server/build-info.ts +2 -0
  17. package/server/conversation.ts +319 -0
  18. package/server/diagnostics.ts +252 -0
  19. package/server/discovery/discover.ts +225 -0
  20. package/server/discovery/manifest.ts +36 -0
  21. package/server/discovery/types.ts +30 -0
  22. package/server/errors.ts +36 -0
  23. package/server/host/bridge.ts +490 -0
  24. package/server/host/schemas.ts +119 -0
  25. package/server/logger.ts +19 -0
  26. package/server/mapping.ts +270 -0
  27. package/server/models.ts +68 -0
  28. package/server/persistence.ts +146 -0
  29. package/server/presentation.ts +470 -0
  30. package/server/provider-status.ts +81 -0
  31. package/server/provider.ts +838 -0
  32. package/server/runtime/managed.ts +501 -0
  33. package/server/runtime/pins.ts +72 -0
  34. package/server/runtime-setup.ts +77 -0
  35. package/server/session-types.ts +49 -0
  36. package/server/session.ts +866 -0
  37. package/server/status.ts +89 -0
  38. package/server/timeline.ts +18 -0
  39. package/server/usage.ts +362 -0
  40. package/server/vendor/zcode/LICENSE +202 -0
  41. package/server/vendor/zcode/NOTICE.md +70 -0
  42. package/server/vendor/zcode/THIRD-PARTY-NOTICES.md +37 -0
  43. package/server/vendor/zcode/packages/model-option-map/src/compiler.ts +92 -0
  44. package/server/vendor/zcode/packages/model-option-map/src/evaluator.ts +214 -0
  45. package/server/vendor/zcode/packages/model-option-map/src/index.ts +5 -0
  46. package/server/vendor/zcode/packages/model-option-map/src/merge-patch.ts +97 -0
  47. package/server/vendor/zcode/packages/model-option-map/src/option-maps.ts +42 -0
  48. package/server/vendor/zcode/packages/model-option-map/src/parser.ts +240 -0
  49. package/server/vendor/zcode/packages/model-option-map/src/tokenizer.ts +141 -0
  50. package/server/vendor/zcode/packages/model-option-map/src/types.ts +36 -0
  51. package/server/vendor/zcode/packages/rpc/src/buffer.ts +88 -0
  52. package/server/vendor/zcode/packages/rpc/src/channelClient.ts +275 -0
  53. package/server/vendor/zcode/packages/rpc/src/channelServer.ts +283 -0
  54. package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +66 -0
  55. package/server/vendor/zcode/packages/rpc/src/channels.ts +4 -0
  56. package/server/vendor/zcode/packages/rpc/src/delayedChannel.ts +17 -0
  57. package/server/vendor/zcode/packages/rpc/src/foundation.ts +260 -0
  58. package/server/vendor/zcode/packages/rpc/src/protocol.ts +397 -0
  59. package/server/vendor/zcode/packages/rpc/src/proxy-channel.ts +213 -0
  60. package/server/vendor/zcode/packages/rpc/src/serialization.ts +291 -0
  61. package/server/vendor/zcode/packages/shared/src/account-provider-state.ts +13 -0
  62. package/server/vendor/zcode/packages/shared/src/background-bash-output.ts +24 -0
  63. package/server/vendor/zcode/packages/shared/src/background-task-controls.ts +404 -0
  64. package/server/vendor/zcode/packages/shared/src/bash-output-display.ts +11 -0
  65. package/server/vendor/zcode/packages/shared/src/bots.ts +558 -0
  66. package/server/vendor/zcode/packages/shared/src/browser-use/backend.ts +80 -0
  67. package/server/vendor/zcode/packages/shared/src/browser-use/command-metadata.ts +170 -0
  68. package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +588 -0
  69. package/server/vendor/zcode/packages/shared/src/browser-use/result.ts +130 -0
  70. package/server/vendor/zcode/packages/shared/src/browser-use/snapshot.ts +77 -0
  71. package/server/vendor/zcode/packages/shared/src/command-types.ts +96 -0
  72. package/server/vendor/zcode/packages/shared/src/config-schema.ts +8 -0
  73. package/server/vendor/zcode/packages/shared/src/cuaAccessibilitySettings.ts +41 -0
  74. package/server/vendor/zcode/packages/shared/src/database-startup.ts +178 -0
  75. package/server/vendor/zcode/packages/shared/src/env.ts +63 -0
  76. package/server/vendor/zcode/packages/shared/src/execution-output-preview.ts +14 -0
  77. package/server/vendor/zcode/packages/shared/src/localTtft.ts +192 -0
  78. package/server/vendor/zcode/packages/shared/src/model-config.ts +123 -0
  79. package/server/vendor/zcode/packages/shared/src/model-execution.ts +23 -0
  80. package/server/vendor/zcode/packages/shared/src/model-provider-family.ts +171 -0
  81. package/server/vendor/zcode/packages/shared/src/model-provider-types.ts +81 -0
  82. package/server/vendor/zcode/packages/shared/src/model-selection.ts +60 -0
  83. package/server/vendor/zcode/packages/shared/src/oauth.ts +203 -0
  84. package/server/vendor/zcode/packages/shared/src/official-mcp-auth.ts +272 -0
  85. package/server/vendor/zcode/packages/shared/src/official-mcp-tool-error.ts +68 -0
  86. package/server/vendor/zcode/packages/shared/src/process-diagnostic.ts +42 -0
  87. package/server/vendor/zcode/packages/shared/src/protocol.ts +369 -0
  88. package/server/vendor/zcode/packages/shared/src/provider-family-connection-selection.ts +32 -0
  89. package/server/vendor/zcode/packages/shared/src/remoteAssetInstallMode.ts +11 -0
  90. package/server/vendor/zcode/packages/shared/src/remoteResourcePackages.ts +91 -0
  91. package/server/vendor/zcode/packages/shared/src/runtimeEnv.ts +315 -0
  92. package/server/vendor/zcode/packages/shared/src/settings-source.ts +10 -0
  93. package/server/vendor/zcode/packages/shared/src/usage-quota.ts +74 -0
  94. package/server/vendor/zcode/packages/shared/src/usage-stats.ts +462 -0
  95. package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +562 -0
  96. package/server/vendor/zcode/packages/shared/src/workspacePurpose.ts +2 -0
  97. package/server/vendor/zcode/packages/shared/src/wslUserValidation.ts +33 -0
  98. package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +25 -0
  99. package/server/vendor/zcode/packages/shared/src/zcode-media-policy.ts +10 -0
  100. package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +3720 -0
  101. package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +529 -0
  102. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +218 -0
  103. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +14 -0
  104. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +482 -0
  105. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/core.ts +100 -0
  106. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +156 -0
  107. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/cuaPermission.ts +41 -0
  108. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +147 -0
  109. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +69 -0
  110. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +432 -0
  111. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/session-config.ts +43 -0
  112. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +195 -0
  113. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +85 -0
  114. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-import.ts +38 -0
  115. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-ref.ts +10 -0
  116. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +509 -0
  117. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +5 -0
  118. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +264 -0
  119. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +1152 -0
  120. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +574 -0
  121. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-binary.ts +65 -0
  122. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-codec.ts +240 -0
  123. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +39 -0
  124. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire.ts +159 -0
  125. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +291 -0
  126. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-observation-display.ts +281 -0
  127. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +163 -0
  128. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +62 -0
  129. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +517 -0
  130. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +512 -0
  131. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-config.ts +81 -0
  132. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-hook-review.ts +210 -0
  133. package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +6 -0
  134. package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +1187 -0
  135. package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +296 -0
  136. package/server/vendor/zcode/provenance.json +405 -0
  137. package/shared/account.ts +201 -0
  138. package/shared/diagnostics.ts +52 -0
  139. package/shared/runtime-setup.ts +73 -0
  140. package/vendor/acp-registry/LICENSE +176 -0
  141. package/vendor/paseo/LICENSE +211 -0
@@ -0,0 +1,379 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { Text, View } from "react-native";
3
+ import { type PluginSurfaceProps, useRpc } from "@getpaseo/plugin/client";
4
+ import {
5
+ SettingsAction,
6
+ SettingsCard,
7
+ SettingsRow,
8
+ SettingsSection,
9
+ } from "@getpaseo/plugin/client/ui";
10
+ import {
11
+ zcodeDiagnostics,
12
+ type DiagnosticsResult,
13
+ } from "../shared/diagnostics";
14
+ import { Value } from "./value";
15
+
16
+ function Installation({ result, theme, compact }: SectionProps) {
17
+ return (
18
+ <SettingsSection title="ZCode installation">
19
+ <SettingsCard>
20
+ <SettingsRow
21
+ label="Install root"
22
+ hint={
23
+ result.source === "managed"
24
+ ? "Managed runtime installed from the Settings screen"
25
+ : "PASEO_ZCODE_RUNTIME"
26
+ }
27
+ >
28
+ <Value color={theme.colors.foreground} compact={compact}>
29
+ {result.installRoot}
30
+ </Value>
31
+ </SettingsRow>
32
+ <SettingsRow label="Platform">
33
+ <Value color={theme.colors.foreground} compact={compact}>
34
+ {result.platform}
35
+ </Value>
36
+ </SettingsRow>
37
+ <SettingsRow label="ZCode Server version">
38
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
39
+ {result.appVersion ?? "Not reported"}
40
+ </Value>
41
+ </SettingsRow>
42
+ <SettingsRow label="Agent version">
43
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
44
+ {result.cliVersion ?? "Not reported"}
45
+ </Value>
46
+ </SettingsRow>
47
+ <SettingsRow label="Provider plugin version">
48
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
49
+ {result.providerVersion}
50
+ </Value>
51
+ </SettingsRow>
52
+ </SettingsCard>
53
+ </SettingsSection>
54
+ );
55
+ }
56
+
57
+ function Compatibility({ result, theme, compact }: SectionProps) {
58
+ const supported = result.compatibility === "supported";
59
+ return (
60
+ <SettingsSection title="Compatibility">
61
+ <SettingsCard>
62
+ <SettingsRow label="Status">
63
+ <Value
64
+ color={
65
+ supported ? theme.colors.statusSuccess : theme.colors.statusDanger
66
+ }
67
+ compact={compact}
68
+ >
69
+ {supported ? "Supported" : "Unsupported"}
70
+ </Value>
71
+ </SettingsRow>
72
+ <SettingsRow label="Reason">
73
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
74
+ {result.compatibilityReason}
75
+ </Value>
76
+ </SettingsRow>
77
+ <SettingsRow
78
+ label="Node.js"
79
+ hint={
80
+ result.source === "managed" ? "Managed Node.js" : "PASEO_ZCODE_NODE"
81
+ }
82
+ >
83
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
84
+ {`${result.nodeExecutable} (${result.nodeVersion})`}
85
+ </Value>
86
+ </SettingsRow>
87
+ <SettingsRow label="Server SHA-256">
88
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
89
+ {result.serverSha256}
90
+ </Value>
91
+ </SettingsRow>
92
+ <SettingsRow label="Agent SHA-256">
93
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
94
+ {result.agentSha256}
95
+ </Value>
96
+ </SettingsRow>
97
+ <SettingsRow label="Install root permissions">
98
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
99
+ {result.writableInstallRoot ? "Writable" : "Read-only"}
100
+ </Value>
101
+ </SettingsRow>
102
+ </SettingsCard>
103
+ </SettingsSection>
104
+ );
105
+ }
106
+
107
+ function HostCheck({
108
+ result,
109
+ busy,
110
+ onRun,
111
+ theme,
112
+ compact,
113
+ }: SectionProps & { busy: boolean; onRun(): void }) {
114
+ const smoke = result.smoke;
115
+ return (
116
+ <SettingsSection title="Host check">
117
+ <SettingsCard>
118
+ <SettingsRow
119
+ label="Result"
120
+ hint="Checks the configured Node.js and Server versions. No prompt is sent."
121
+ >
122
+ <Value
123
+ color={
124
+ smoke === undefined
125
+ ? theme.colors.foregroundMuted
126
+ : smoke.passed
127
+ ? theme.colors.statusSuccess
128
+ : theme.colors.statusDanger
129
+ }
130
+ compact={compact}
131
+ >
132
+ {smoke === undefined
133
+ ? "Not run"
134
+ : smoke.passed
135
+ ? "Passed"
136
+ : "Failed"}
137
+ </Value>
138
+ </SettingsRow>
139
+ {smoke === undefined ? null : (
140
+ <>
141
+ {smoke.error === undefined ? null : (
142
+ <SettingsRow label="Error">
143
+ <Value color={theme.colors.statusDanger} compact={compact}>
144
+ {smoke.error}
145
+ </Value>
146
+ </SettingsRow>
147
+ )}
148
+ </>
149
+ )}
150
+ </SettingsCard>
151
+ <SettingsAction
152
+ label="stdio Server"
153
+ actionLabel={busy ? "Checking…" : "Run host check"}
154
+ disabled={busy}
155
+ onPress={onRun}
156
+ />
157
+ </SettingsSection>
158
+ );
159
+ }
160
+
161
+ function SessionStorage({ result, theme, compact }: SectionProps) {
162
+ return (
163
+ <SettingsSection title="Session storage">
164
+ <SettingsCard>
165
+ <SettingsRow
166
+ label="Resume mapping directory"
167
+ hint="Stores identifiers and workspace paths, not message contents."
168
+ >
169
+ <Value color={theme.colors.foreground} compact={compact}>
170
+ {result.sessionsDirectory}
171
+ </Value>
172
+ </SettingsRow>
173
+ </SettingsCard>
174
+ </SettingsSection>
175
+ );
176
+ }
177
+
178
+ interface SectionProps {
179
+ result: Extract<DiagnosticsResult, { status: "ready" }>;
180
+ theme: PluginSurfaceProps["theme"];
181
+ compact: boolean;
182
+ }
183
+
184
+ function ReadyView({
185
+ result,
186
+ busy,
187
+ onCheck,
188
+ onSmoke,
189
+ theme,
190
+ compact,
191
+ }: {
192
+ result: Extract<DiagnosticsResult, { status: "ready" }>;
193
+ busy: boolean;
194
+ onCheck(): void;
195
+ onSmoke(): void;
196
+ theme: PluginSurfaceProps["theme"];
197
+ compact: boolean;
198
+ }) {
199
+ return (
200
+ <View style={{ gap: compact ? 16 : 24 }}>
201
+ <Installation result={result} theme={theme} compact={compact} />
202
+ <Compatibility result={result} theme={theme} compact={compact} />
203
+ <HostCheck
204
+ result={result}
205
+ busy={busy}
206
+ onRun={onSmoke}
207
+ theme={theme}
208
+ compact={compact}
209
+ />
210
+ <SessionStorage result={result} theme={theme} compact={compact} />
211
+ <SettingsSection title="Detection">
212
+ <SettingsAction
213
+ label="Installed ZCode"
214
+ actionLabel={busy ? "Checking…" : "Check again"}
215
+ disabled={busy}
216
+ onPress={onCheck}
217
+ />
218
+ </SettingsSection>
219
+ </View>
220
+ );
221
+ }
222
+
223
+ function FailedView({
224
+ result,
225
+ busy,
226
+ onCheck,
227
+ theme,
228
+ compact,
229
+ }: {
230
+ result: Extract<DiagnosticsResult, { status: "failed" }>;
231
+ busy: boolean;
232
+ onCheck(): void;
233
+ theme: PluginSurfaceProps["theme"];
234
+ compact: boolean;
235
+ }) {
236
+ return (
237
+ <View style={{ gap: compact ? 16 : 24 }}>
238
+ <SettingsSection title="ZCode diagnostics">
239
+ <SettingsCard>
240
+ <SettingsRow label="Result">
241
+ <Value color={theme.colors.statusDanger} compact={compact}>
242
+ Failed
243
+ </Value>
244
+ </SettingsRow>
245
+ <SettingsRow label="Error code">
246
+ <Value color={theme.colors.foreground} compact={compact}>
247
+ {result.code}
248
+ </Value>
249
+ </SettingsRow>
250
+ <SettingsRow label="Message">
251
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
252
+ {result.message}
253
+ </Value>
254
+ </SettingsRow>
255
+ <SettingsRow
256
+ label="Diagnostic report"
257
+ hint="Safe to attach to a GitHub issue; credentials, prompts, and raw native errors are excluded."
258
+ >
259
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
260
+ {result.diagnostic}
261
+ </Value>
262
+ </SettingsRow>
263
+ <SettingsRow label="Provider plugin version">
264
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
265
+ {result.providerVersion}
266
+ </Value>
267
+ </SettingsRow>
268
+ </SettingsCard>
269
+ <SettingsAction
270
+ label="Installed ZCode"
271
+ actionLabel={busy ? "Checking…" : "Check again"}
272
+ disabled={busy}
273
+ onPress={onCheck}
274
+ />
275
+ </SettingsSection>
276
+ </View>
277
+ );
278
+ }
279
+
280
+ export function DiagnosticsScreen({ theme, layout }: PluginSurfaceProps) {
281
+ const run = useRpc(zcodeDiagnostics);
282
+ const [result, setResult] = useState<DiagnosticsResult | null>(null);
283
+ const [requestError, setRequestError] = useState<string | null>(null);
284
+ const [busy, setBusy] = useState(true);
285
+
286
+ const check = useCallback(
287
+ async (smoke: boolean) => {
288
+ setBusy(true);
289
+ try {
290
+ setResult(await run({ smoke }));
291
+ setRequestError(null);
292
+ } catch (cause) {
293
+ setRequestError(
294
+ cause instanceof Error
295
+ ? cause.message
296
+ : "The diagnostics request failed.",
297
+ );
298
+ } finally {
299
+ setBusy(false);
300
+ }
301
+ },
302
+ [run],
303
+ );
304
+
305
+ useEffect(() => {
306
+ void check(false);
307
+ }, [check]);
308
+
309
+ if (result === null) {
310
+ return (
311
+ <SettingsSection title="ZCode diagnostics">
312
+ <SettingsCard>
313
+ <SettingsRow label="Status">
314
+ <Value
315
+ color={theme.colors.foregroundMuted}
316
+ compact={layout.compact}
317
+ >
318
+ {requestError ?? "Checking the ZCode installation…"}
319
+ </Value>
320
+ </SettingsRow>
321
+ </SettingsCard>
322
+ {requestError === null ? null : (
323
+ <SettingsAction
324
+ label="Diagnostics request"
325
+ actionLabel={busy ? "Checking…" : "Try again"}
326
+ disabled={busy}
327
+ onPress={() => void check(false)}
328
+ />
329
+ )}
330
+ </SettingsSection>
331
+ );
332
+ }
333
+
334
+ const props = {
335
+ busy,
336
+ onCheck: () => void check(false),
337
+ onSmoke: () => void check(true),
338
+ theme,
339
+ compact: layout.compact,
340
+ };
341
+ return result.status === "ready" ? (
342
+ <>
343
+ <ReadyView result={result} {...props} />
344
+ {requestError === null ? null : (
345
+ <RequestError
346
+ message={requestError}
347
+ theme={theme}
348
+ compact={layout.compact}
349
+ />
350
+ )}
351
+ </>
352
+ ) : (
353
+ <FailedView result={result} {...props} />
354
+ );
355
+ }
356
+
357
+ function RequestError({
358
+ message,
359
+ theme,
360
+ compact,
361
+ }: {
362
+ message: string;
363
+ theme: PluginSurfaceProps["theme"];
364
+ compact: boolean;
365
+ }) {
366
+ return (
367
+ <SettingsSection title="Last request">
368
+ <Text
369
+ accessibilityRole="alert"
370
+ style={{
371
+ color: theme.colors.statusDanger,
372
+ fontSize: compact ? 13 : 14,
373
+ }}
374
+ >
375
+ {message}
376
+ </Text>
377
+ </SettingsSection>
378
+ );
379
+ }
@@ -0,0 +1,296 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { Text, View } from "react-native";
3
+ import { type PluginSurfaceProps, useRpc } from "@getpaseo/plugin/client";
4
+ import {
5
+ SettingsAction,
6
+ SettingsCard,
7
+ SettingsRow,
8
+ SettingsSection,
9
+ } from "@getpaseo/plugin/client/ui";
10
+ import {
11
+ zcodeRuntimeInstall,
12
+ zcodeRuntimeRemove,
13
+ zcodeRuntimeStatus,
14
+ type RuntimeSetupStatus,
15
+ } from "../shared/runtime-setup";
16
+ import { Value } from "./value";
17
+
18
+ type Theme = PluginSurfaceProps["theme"];
19
+ type Job = RuntimeSetupStatus["job"];
20
+
21
+ const megabytes = (bytes: number) => `${(bytes / 1_000_000).toFixed(1)} MB`;
22
+
23
+ function jobLabel(job: Job): string {
24
+ switch (job.state) {
25
+ case "idle":
26
+ return "Not started";
27
+ case "succeeded":
28
+ return "Completed";
29
+ case "failed":
30
+ return `Failed (${job.code})`;
31
+ case "running": {
32
+ const name = job.component === "node" ? "Node.js" : "ZCode runtime";
33
+ if (job.phase !== "download") return `${name}: ${job.phase}ing`;
34
+ const percent =
35
+ job.totalBytes > 0
36
+ ? Math.floor((job.receivedBytes / job.totalBytes) * 100)
37
+ : 0;
38
+ return `${name}: downloading ${percent}% of ${megabytes(job.totalBytes)}`;
39
+ }
40
+ }
41
+ }
42
+
43
+ function Components({
44
+ status,
45
+ theme,
46
+ compact,
47
+ }: {
48
+ status: RuntimeSetupStatus;
49
+ theme: Theme;
50
+ compact: boolean;
51
+ }) {
52
+ return (
53
+ <>
54
+ {status.components.map((component) => (
55
+ <SettingsSection
56
+ key={component.id}
57
+ title={`${component.name} ${component.version}`}
58
+ >
59
+ <SettingsCard>
60
+ <SettingsRow label="Status">
61
+ <Value
62
+ color={
63
+ component.installed
64
+ ? theme.colors.statusSuccess
65
+ : theme.colors.foregroundMuted
66
+ }
67
+ compact={compact}
68
+ >
69
+ {component.installed ? "Installed" : "Not installed"}
70
+ </Value>
71
+ </SettingsRow>
72
+ <SettingsRow label="Source" hint={megabytes(component.sizeBytes)}>
73
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
74
+ {component.url}
75
+ </Value>
76
+ </SettingsRow>
77
+ <SettingsRow label="SHA-256" hint="Checked before extraction">
78
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
79
+ {component.sha256}
80
+ </Value>
81
+ </SettingsRow>
82
+ <SettingsRow label="License">
83
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
84
+ {component.license}
85
+ </Value>
86
+ </SettingsRow>
87
+ </SettingsCard>
88
+ </SettingsSection>
89
+ ))}
90
+ </>
91
+ );
92
+ }
93
+
94
+ export function RuntimeTab({ theme, layout }: PluginSurfaceProps) {
95
+ const fetchStatus = useRpc(zcodeRuntimeStatus);
96
+ const install = useRpc(zcodeRuntimeInstall);
97
+ const remove = useRpc(zcodeRuntimeRemove);
98
+ const [status, setStatus] = useState<RuntimeSetupStatus | null>(null);
99
+ const [requestError, setRequestError] = useState<string | null>(null);
100
+ const [removeMessage, setRemoveMessage] = useState<string | null>(null);
101
+ const [confirmRemove, setConfirmRemove] = useState(false);
102
+ const [pending, setPending] = useState(false);
103
+ const compact = layout.compact;
104
+
105
+ const refresh = useCallback(async () => {
106
+ try {
107
+ setStatus(await fetchStatus({}));
108
+ setRequestError(null);
109
+ } catch (cause) {
110
+ setRequestError(
111
+ cause instanceof Error ? cause.message : "The setup request failed.",
112
+ );
113
+ }
114
+ }, [fetchStatus]);
115
+
116
+ useEffect(() => {
117
+ void refresh();
118
+ }, [refresh]);
119
+
120
+ const running = status?.job.state === "running";
121
+ useEffect(() => {
122
+ if (!running) return;
123
+ const timer = setInterval(() => void refresh(), 1000);
124
+ return () => clearInterval(timer);
125
+ }, [running, refresh]);
126
+
127
+ const run = useCallback(
128
+ async (action: () => Promise<unknown>) => {
129
+ setPending(true);
130
+ try {
131
+ await action();
132
+ } catch (cause) {
133
+ setRequestError(
134
+ cause instanceof Error ? cause.message : "The setup request failed.",
135
+ );
136
+ } finally {
137
+ setPending(false);
138
+ await refresh();
139
+ }
140
+ },
141
+ [refresh],
142
+ );
143
+
144
+ if (status === null)
145
+ return (
146
+ <SettingsSection title="ZCode runtime setup">
147
+ <SettingsCard>
148
+ <SettingsRow label="Status">
149
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
150
+ {requestError ?? "Checking the managed runtime…"}
151
+ </Value>
152
+ </SettingsRow>
153
+ </SettingsCard>
154
+ </SettingsSection>
155
+ );
156
+
157
+ const installed =
158
+ status.components.length > 0 &&
159
+ status.components.every((component) => component.installed);
160
+ const total = status.components
161
+ .filter((component) => !component.installed)
162
+ .reduce((sum, component) => sum + component.sizeBytes, 0);
163
+ const busy = pending || running;
164
+
165
+ return (
166
+ <View style={{ gap: compact ? 16 : 24 }}>
167
+ <SettingsSection title="ZCode runtime setup">
168
+ <SettingsCard>
169
+ <SettingsRow label="Downloads from">
170
+ <Value color={theme.colors.foreground} compact={compact}>
171
+ nodejs.org and this plugin's GitHub releases
172
+ </Value>
173
+ </SettingsRow>
174
+ <SettingsRow
175
+ label="ZCode build"
176
+ hint="ZCode does not publish its CLI; CI builds the unmodified source."
177
+ >
178
+ <Value color={theme.colors.foreground} compact={compact}>
179
+ Unofficial, not endorsed by ZCode or Z.ai
180
+ </Value>
181
+ </SettingsRow>
182
+ <SettingsRow label="Runs as">
183
+ <Value color={theme.colors.foreground} compact={compact}>
184
+ The daemon user, on the daemon machine
185
+ </Value>
186
+ </SettingsRow>
187
+ <SettingsRow label="Changes">
188
+ <Value color={theme.colors.foreground} compact={compact}>
189
+ Only the destination below; PATH is untouched
190
+ </Value>
191
+ </SettingsRow>
192
+ <SettingsRow label="Destination">
193
+ <Value color={theme.colors.foregroundMuted} compact={compact}>
194
+ {status.directory}
195
+ </Value>
196
+ </SettingsRow>
197
+ <SettingsRow label="Platform">
198
+ <Value
199
+ color={
200
+ status.supported
201
+ ? theme.colors.foregroundMuted
202
+ : theme.colors.statusDanger
203
+ }
204
+ compact={compact}
205
+ >
206
+ {status.supported
207
+ ? status.platform
208
+ : `${status.platform} is not supported. Set PASEO_ZCODE_RUNTIME and PASEO_ZCODE_NODE instead.`}
209
+ </Value>
210
+ </SettingsRow>
211
+ {status.override ? (
212
+ <SettingsRow
213
+ label="Environment override"
214
+ hint="Unset both variables and restart the daemon to use the managed runtime."
215
+ >
216
+ <Value color={theme.colors.statusWarning} compact={compact}>
217
+ PASEO_ZCODE_RUNTIME / PASEO_ZCODE_NODE are set, so sessions use
218
+ them instead of this runtime.
219
+ </Value>
220
+ </SettingsRow>
221
+ ) : null}
222
+ <SettingsRow
223
+ label="Progress"
224
+ error={status.job.state === "failed" ? status.job.message : null}
225
+ >
226
+ <Value
227
+ color={
228
+ status.job.state === "failed"
229
+ ? theme.colors.statusDanger
230
+ : theme.colors.foregroundMuted
231
+ }
232
+ compact={compact}
233
+ >
234
+ {jobLabel(status.job)}
235
+ </Value>
236
+ </SettingsRow>
237
+ </SettingsCard>
238
+ {status.supported ? (
239
+ <SettingsAction
240
+ label={installed ? "Runtime installed" : "Install runtime"}
241
+ hint={installed ? undefined : `Downloads ${megabytes(total)}`}
242
+ actionLabel={
243
+ running
244
+ ? "Installing…"
245
+ : installed
246
+ ? "Installed"
247
+ : "Download and install"
248
+ }
249
+ disabled={busy || installed}
250
+ onPress={() => void run(() => install({}))}
251
+ />
252
+ ) : null}
253
+ </SettingsSection>
254
+ <Components status={status} theme={theme} compact={compact} />
255
+ <SettingsSection title="Remove">
256
+ <SettingsAction
257
+ label="Managed runtime"
258
+ hint={
259
+ removeMessage ??
260
+ "Deletes the destination directory. Stop ZCode sessions first. ZCode settings, logins and conversations are kept."
261
+ }
262
+ actionLabel={confirmRemove ? "Confirm removal" : "Remove"}
263
+ disabled={busy}
264
+ onPress={() => {
265
+ if (!confirmRemove) {
266
+ setConfirmRemove(true);
267
+ return;
268
+ }
269
+ setConfirmRemove(false);
270
+ void run(async () => {
271
+ const result = await remove({});
272
+ setRemoveMessage(
273
+ result.status === "removed"
274
+ ? "Removed."
275
+ : `Removal failed: ${result.message}`,
276
+ );
277
+ });
278
+ }}
279
+ />
280
+ </SettingsSection>
281
+ {requestError === null ? null : (
282
+ <SettingsSection title="Last request">
283
+ <Text
284
+ accessibilityRole="alert"
285
+ style={{
286
+ color: theme.colors.statusDanger,
287
+ fontSize: compact ? 13 : 14,
288
+ }}
289
+ >
290
+ {requestError}
291
+ </Text>
292
+ </SettingsSection>
293
+ )}
294
+ </View>
295
+ );
296
+ }