@huynle/hub 0.9.0 → 0.9.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/CHANGELOG.md +36 -0
- package/README.md +7 -4
- package/package.json +1 -1
- package/packages/claude-code/package.json +1 -1
- package/packages/claude-code/src/wrapper.ts +2 -2
- package/packages/cli/dist/hub-cli.js +1126 -479
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/bootstrap/PHASE3-CONTRACT.md +112 -0
- package/packages/cli/src/bootstrap/adapters/node-services/control.ts +164 -21
- package/packages/cli/src/bootstrap/adapters/node-services/plan.ts +24 -7
- package/packages/cli/src/bootstrap/adapters/node-services/render.ts +116 -9
- package/packages/cli/src/bootstrap/adapters/node-services/validate.ts +8 -2
- package/packages/cli/src/bootstrap/contracts/actions.ts +8 -6
- package/packages/cli/src/bootstrap/contracts/discovery.ts +4 -3
- package/packages/cli/src/bootstrap/contracts/exec.ts +4 -2
- package/packages/cli/src/bootstrap/contracts/paths.ts +2 -1
- package/packages/cli/src/bootstrap/contracts/platform.ts +5 -5
- package/packages/cli/src/bootstrap/discovery/discover.ts +7 -2
- package/packages/cli/src/bootstrap/discovery/host.ts +2 -0
- package/packages/cli/src/bootstrap/preview/plan.ts +5 -1
- package/packages/cli/src/bootstrap/profiles/desired.ts +16 -1
- package/packages/cli/src/bootstrap/profiles/history.ts +2 -1
- package/packages/cli/src/bootstrap/profiles/upgrade.ts +2 -2
- package/packages/cli/src/bootstrap/release/assets.ts +4 -1
- package/packages/cli/src/node.ts +94 -12
- package/packages/cli/src/setup/commands.ts +27 -7
- package/packages/cli/src/setup/runtime.ts +31 -4
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/wrapper.ts +2 -2
- package/packages/node/package.json +1 -1
- package/packages/node/src/config.ts +49 -17
- package/packages/node/src/git.ts +16 -2
- package/packages/node/src/harnesses.ts +54 -9
- package/packages/node/src/host.ts +61 -15
- package/packages/node/src/opencode-service.ts +111 -0
- package/packages/node/src/opencode-warm.ts +11 -5
- package/packages/node/src/run.ts +50 -5
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/src/index.ts +3 -1
- package/packages/protocol/src/launch.ts +39 -4
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/spoke-sdk/package.json +1 -1
- package/src/central/agent/launch-spec.ts +4 -2
- package/src/central/agent/webhooks.ts +5 -2
- package/src/central/config.ts +24 -2
- package/src/central/http.ts +1 -0
- package/src/central/install/CONTRACT.md +4 -4
- package/src/central/install/install.ps1 +37 -5
- package/src/central/install/render.ts +13 -8
- package/src/central/push-target.ts +11 -2
- package/web/dist/assets/{ArtifactPage-4GoBqSpU.js → ArtifactPage-BKISN-Qj.js} +1 -1
- package/web/dist/assets/{ArtifactPane-Dx_0iWwH.js → ArtifactPane-CKOiAUNH.js} +1 -1
- package/web/dist/assets/{ArtifactWorkbench-CuHgARMk.js → ArtifactWorkbench-d7R1o-rs.js} +1 -1
- package/web/dist/assets/{Diagram-CZM_R7MG.js → Diagram-azw2B_QH.js} +1 -1
- package/web/dist/assets/{Library-TwvrwqSk.js → Library-CcjZXsfF.js} +2 -2
- package/web/dist/assets/{ProfilesDestination-rKNDpLjR.js → ProfilesDestination-DdzbzmeK.js} +1 -1
- package/web/dist/assets/{TeamsPage-DtJylLrt.js → TeamsPage-CDyjrK-I.js} +1 -1
- package/web/dist/assets/{Watchtower-Bmgdyfjb.js → Watchtower-DYwoUWME.js} +2 -2
- package/web/dist/assets/{index-D-xG9nrc.js → index-LNMZCqgE.js} +15 -15
- package/web/dist/assets/{live-7q72Lyj2.js → live-ycZ_aQZO.js} +1 -1
- package/web/dist/assets/{renderer2d-hfZxM6Xl.js → renderer2d-BIwbgRoX.js} +1 -1
- package/web/dist/assets/{renderer3d-Km9vipTM.js → renderer3d-C1a7eYGQ.js} +1 -1
- package/web/dist/assets/{safe-area-BAbgBiFk.js → safe-area-DHhPy61Q.js} +1 -1
- package/web/dist/index.html +1 -1
|
@@ -157,6 +157,8 @@ export interface WebhooksDeps {
|
|
|
157
157
|
readonly resolve: ResolveHost
|
|
158
158
|
/** hub.json agents.webhooks.allowPrivate. */
|
|
159
159
|
readonly allowPrivate?: boolean
|
|
160
|
+
/** hub.json agents.webhooks.allowPrivateHosts: exact hostnames that may resolve to private addresses (https only). */
|
|
161
|
+
readonly privateHosts?: readonly string[]
|
|
160
162
|
readonly fetch?: typeof globalThis.fetch
|
|
161
163
|
/** Whether an app token (by its id) may still have webhooks; its registrations are dropped when not. */
|
|
162
164
|
readonly appAlive?: (userID: string, tokenID: string) => boolean
|
|
@@ -283,8 +285,8 @@ export class Webhooks {
|
|
|
283
285
|
const { url } = input
|
|
284
286
|
if (typeof url !== "string" || url.length === 0) throw invalid("url must be a string")
|
|
285
287
|
if (url.length > MAX_WEBHOOK_URL) throw invalid(`url must be at most ${MAX_WEBHOOK_URL} characters`)
|
|
286
|
-
const problem = await publicURLProblem(url, { resolve: this.deps.resolve, label: "Webhook URL", allowPrivate: this.deps.allowPrivate === true })
|
|
287
|
-
if (problem) throw invalid(problem, this.deps.allowPrivate ? undefined : "Webhooks need an https URL on a public host")
|
|
288
|
+
const problem = await publicURLProblem(url, { resolve: this.deps.resolve, label: "Webhook URL", allowPrivate: this.deps.allowPrivate === true, ...(this.deps.privateHosts?.length ? { privateHosts: this.deps.privateHosts } : {}) })
|
|
289
|
+
if (problem) throw invalid(problem, this.deps.allowPrivate ? undefined : "Webhooks need an https URL on a public host (or one listed in hub.json agents.webhooks.allowPrivateHosts)")
|
|
288
290
|
const events = eventsOf(input.events)
|
|
289
291
|
let label: string | undefined
|
|
290
292
|
if (input.label !== undefined && input.label !== null) {
|
|
@@ -512,6 +514,7 @@ export class Webhooks {
|
|
|
512
514
|
resolve: this.deps.resolve,
|
|
513
515
|
label: "Webhook URL",
|
|
514
516
|
allowPrivate: this.deps.allowPrivate === true,
|
|
517
|
+
...(this.deps.privateHosts?.length ? { privateHosts: this.deps.privateHosts } : {}),
|
|
515
518
|
timeoutMs,
|
|
516
519
|
maxBytes: this.deps.maxResponseBytes ?? WEBHOOK_RESPONSE_MAX,
|
|
517
520
|
...(this.deps.fetch ? { fetch: this.deps.fetch } : {}),
|
package/src/central/config.ts
CHANGED
|
@@ -71,6 +71,8 @@ export interface CentralConfig {
|
|
|
71
71
|
readonly launchCaps?: HubLaunches
|
|
72
72
|
/** hub.json `agents.webhooks.allowPrivate`: webhooks may target http, loopback, private and local hosts (admin opt-in). */
|
|
73
73
|
readonly webhooksAllowPrivate?: true
|
|
74
|
+
/** hub.json `agents.webhooks.allowPrivateHosts`: exact hostnames whose https webhook URLs may resolve privately. */
|
|
75
|
+
readonly webhooksPrivateHosts?: readonly string[]
|
|
74
76
|
/**
|
|
75
77
|
* HUB_RELEASE_BASE: where /install.sh and /install.ps1 tell machines to download hubctl (default: this version's
|
|
76
78
|
* hub-releases GitHub release). https, or plain http on loopback or a private-network IP address.
|
|
@@ -132,6 +134,8 @@ export interface HubAgents {
|
|
|
132
134
|
export interface HubWebhooks {
|
|
133
135
|
/** Lets webhook URLs use http and private or local targets (self-hosted receivers); off by default (SSRF). */
|
|
134
136
|
readonly allowPrivate?: boolean
|
|
137
|
+
/** Exact hostnames whose https webhook URLs may resolve to private addresses (a LAN-hosted receiver), nothing else. */
|
|
138
|
+
readonly allowPrivateHosts?: readonly string[]
|
|
135
139
|
}
|
|
136
140
|
|
|
137
141
|
/** hub.json, validated. */
|
|
@@ -151,7 +155,9 @@ type Env = Readonly<Record<string, string | undefined>>
|
|
|
151
155
|
const HUB_KEYS = new Set(["host", "port", "publicURL", "stateDir", "speech", "auth", "agents", "cluster"])
|
|
152
156
|
const CLUSTER_KEYS = ["database", "valkey"] as const
|
|
153
157
|
const AGENTS_KEYS = new Set(["never", "launches", "webhooks"])
|
|
154
|
-
const WEBHOOK_KEYS = new Set(["allowPrivate"])
|
|
158
|
+
const WEBHOOK_KEYS = new Set(["allowPrivate", "allowPrivateHosts"])
|
|
159
|
+
const PRIVATE_HOSTS_MAX = 50
|
|
160
|
+
const HOSTNAME = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/
|
|
155
161
|
const LAUNCH_CAP_KEYS = ["maxQueued", "maxActive", "perHour", "lostAfterMinutes"] as const
|
|
156
162
|
/** The longest lostAfterMinutes (a day): far below setTimeout's 32-bit limit. */
|
|
157
163
|
const LOST_AFTER_MAX = 1440
|
|
@@ -337,7 +343,22 @@ function readHubWebhooks(raw: unknown, file: string, warnings: string[], fail: (
|
|
|
337
343
|
const input = raw as Record<string, unknown>
|
|
338
344
|
for (const key of Object.keys(input)) if (!WEBHOOK_KEYS.has(key)) warnings.push(`${file}: unknown key "agents.webhooks.${key}" ignored`)
|
|
339
345
|
if (input.allowPrivate !== undefined && typeof input.allowPrivate !== "boolean") fail("agents.webhooks.allowPrivate must be true or false")
|
|
340
|
-
|
|
346
|
+
const hosts = input.allowPrivateHosts === undefined ? undefined : readPrivateHosts(input.allowPrivateHosts, fail)
|
|
347
|
+
return { ...(input.allowPrivate === undefined ? {} : { allowPrivate: input.allowPrivate as boolean }), ...(hosts ? { allowPrivateHosts: hosts } : {}) }
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** Plain DNS hostnames with a dot (no IPs, wildcards, schemes, ports or paths), lowercase, trailing dot dropped, deduplicated. */
|
|
351
|
+
function readPrivateHosts(raw: unknown, fail: (message: string) => never): string[] {
|
|
352
|
+
if (!Array.isArray(raw)) fail("agents.webhooks.allowPrivateHosts must be a list of hostnames")
|
|
353
|
+
const list = raw as unknown[]
|
|
354
|
+
if (list.length > PRIVATE_HOSTS_MAX) fail(`agents.webhooks.allowPrivateHosts holds at most ${PRIVATE_HOSTS_MAX} hostnames`)
|
|
355
|
+
const out: string[] = []
|
|
356
|
+
for (const item of list) {
|
|
357
|
+
const host = typeof item === "string" ? item.trim().toLowerCase().replace(/\.$/, "") : ""
|
|
358
|
+
if (!HOSTNAME.test(host) || /^[0-9.]+$/.test(host)) fail(`agents.webhooks.allowPrivateHosts: ${JSON.stringify(item)} is not a hostname (no IPs, wildcards, schemes, ports or paths)`)
|
|
359
|
+
if (!out.includes(host)) out.push(host)
|
|
360
|
+
}
|
|
361
|
+
return out
|
|
341
362
|
}
|
|
342
363
|
|
|
343
364
|
function readHubLaunches(raw: unknown, file: string, warnings: string[], fail: (message: string) => never): HubLaunches {
|
|
@@ -536,6 +557,7 @@ export function centralConfig(rawEnv: Env = process.env, home: string = homedir(
|
|
|
536
557
|
agentsNever: [...(file.agents?.never ?? [])],
|
|
537
558
|
...(file.agents?.launches ? { launchCaps: { ...file.agents.launches } } : {}),
|
|
538
559
|
...(file.agents?.webhooks?.allowPrivate === true ? { webhooksAllowPrivate: true as const } : {}),
|
|
560
|
+
...(file.agents?.webhooks?.allowPrivateHosts?.length ? { webhooksPrivateHosts: [...file.agents.webhooks.allowPrivateHosts] } : {}),
|
|
539
561
|
...(releaseBase ? { releaseBase } : {}),
|
|
540
562
|
...(cluster ? { cluster } : {}),
|
|
541
563
|
...(remoteFetch === "off" ? { remoteFetch: false } : {}),
|
package/src/central/http.ts
CHANGED
|
@@ -1061,6 +1061,7 @@ export function startCentral(options: CentralOptions): Central {
|
|
|
1061
1061
|
users: () => store.users().map((u) => u.id),
|
|
1062
1062
|
resolve: options.resolveHost ?? systemResolveHost,
|
|
1063
1063
|
...(config.webhooksAllowPrivate ? { allowPrivate: true } : {}),
|
|
1064
|
+
...(config.webhooksPrivateHosts?.length ? { privateHosts: config.webhooksPrivateHosts } : {}),
|
|
1064
1065
|
appAlive: (userID, tokenID) => store.agentData(userID).appTokens?.some((t) => t.id === tokenID && Array.isArray(t.scopes) && WEBHOOK_APP_SCOPES.some((scope) => t.scopes!.includes(scope))) === true,
|
|
1065
1066
|
appScopes: (userID, tokenID) => store.agentData(userID).appTokens?.find((t) => t.id === tokenID)?.scopes,
|
|
1066
1067
|
userAgent: `hub/${options.version ?? "0.0.0"}`,
|
|
@@ -11,11 +11,11 @@ it only through the integrator.
|
|
|
11
11
|
|
|
12
12
|
Query (every key optional, each at most once; any other key → 400):
|
|
13
13
|
|
|
14
|
-
| Key | Values | Default | install.ps1 (Phase
|
|
14
|
+
| Key | Values | Default | install.ps1 (Phase 3) |
|
|
15
15
|
|---|---|---|---|
|
|
16
|
-
| `profile` | `session-only` · `launch-node` · `full-harness` | `session-only` |
|
|
17
|
-
| `root` | workspace root for `launch-node`: 1–200 chars of `[A-Za-z0-9._/~-]`, starts with `/` or `~/`, no `..` segment, no `//` | `~/projects` when profile is `launch-node` |
|
|
18
|
-
| `activate` | `0` · `1` | `0` |
|
|
16
|
+
| `profile` | `session-only` · `launch-node` · `full-harness` | `session-only` | `session-only` · `launch-node`; `full-harness` 400 (no Claude Code / Codex user services on Windows yet) |
|
|
17
|
+
| `root` | workspace root for `launch-node`: 1–200 chars of `[A-Za-z0-9._/~-]`, starts with `/` or `~/`, no `..` segment, no `//` | `~/projects` when profile is `launch-node` | starts with `~/` or a drive path `X:/` (one letter, `:`, `/`, forward slashes), then the same allowlist and rules; `/…` is 400. install.sh refuses a drive path |
|
|
18
|
+
| `activate` | `0` · `1` | `0` | `0` · `1` |
|
|
19
19
|
|
|
20
20
|
`root` with another profile → 400. Errors are `400 text/plain` with a one-line reason (no script).
|
|
21
21
|
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
#
|
|
5
5
|
# The PowerShell twin of install.sh: downloads the hubctl release this hub pins (hubctl-windows-x64.exe), checks its
|
|
6
6
|
# sha256, enrolls this machine with the hub (device code, approved in the console), then runs `hubctl setup preview`,
|
|
7
|
-
# `setup apply` and `setup verify` for the session-only profile (
|
|
7
|
+
# `setup apply` and `setup verify` for the session-only or launch-node profile (full-harness is not on Windows yet;
|
|
8
|
+
# launch-node gets --workspace-root, and --confirm-activation when ACTIVATE is 1, as in install.sh), and adds
|
|
8
9
|
# %USERPROFILE%\.local\bin to the user PATH. Every hubctl run gets an empty stdin. Re-running it is safe: an enrolled
|
|
9
10
|
# machine is not enrolled again, and apply converges.
|
|
10
11
|
#
|
|
@@ -222,11 +223,37 @@ function Invoke-HubSetup {
|
|
|
222
223
|
return $true
|
|
223
224
|
}
|
|
224
225
|
|
|
226
|
+
# The workspace root as a native path for --workspace-root: `~/...` under %USERPROFILE%, `C:/...` with backslashes.
|
|
227
|
+
# The hub already checked it (CONTRACT.md); this repeats the check, so a hand-edited script cannot pass anything
|
|
228
|
+
# else.
|
|
229
|
+
function ConvertTo-HubWorkspaceRoot([string] $Root) {
|
|
230
|
+
$ok = $Root.Length -le 200 -and $Root -cmatch '^(~/|[A-Za-z]:/)[A-Za-z0-9._/~-]*$' -and -not $Root.Contains('//') -and
|
|
231
|
+
-not (@($Root -split '/') -contains '..')
|
|
232
|
+
if (-not $ok) { throw "the workspace root $Root is not ~/... or a drive path such as C:/...; pick another in the console" }
|
|
233
|
+
if ($Root.StartsWith('~/')) {
|
|
234
|
+
$base = $env:USERPROFILE
|
|
235
|
+
if (-not $base) { $base = Get-HubHome }
|
|
236
|
+
$rest = $Root.Substring(2).TrimEnd('/')
|
|
237
|
+
if (-not $rest) { return $base }
|
|
238
|
+
return $base.TrimEnd('\', '/') + '\' + $rest.Replace('/', '\')
|
|
239
|
+
}
|
|
240
|
+
$native = $Root.Replace('/', '\')
|
|
241
|
+
if ($native.Length -gt 3) { $native = $native.TrimEnd('\') }
|
|
242
|
+
return $native
|
|
243
|
+
}
|
|
244
|
+
|
|
225
245
|
$tmp = $null
|
|
226
246
|
try {
|
|
227
247
|
$HubUrl = $HubUrl.TrimEnd('/')
|
|
228
|
-
if ($SetupProfile -
|
|
229
|
-
throw "on Windows
|
|
248
|
+
if ($SetupProfile -eq 'full-harness') {
|
|
249
|
+
throw "on Windows 'All harnesses' (full-harness) is not available yet: Claude Code and Codex need user services hubctl does not install on Windows yet; pick 'OpenCode only' or '+ launch node' in the console"
|
|
250
|
+
}
|
|
251
|
+
if ($SetupProfile -ne 'session-only' -and $SetupProfile -ne 'launch-node') { throw "unknown profile $SetupProfile" }
|
|
252
|
+
if ($Activate -ne '0' -and $Activate -ne '1') { throw "unknown activate value $Activate" }
|
|
253
|
+
$nativeRoot = ''
|
|
254
|
+
if ($WorkspaceRoot -ne '') {
|
|
255
|
+
if ($SetupProfile -ne 'launch-node') { throw 'a workspace root is only for launch-node' }
|
|
256
|
+
$nativeRoot = ConvertTo-HubWorkspaceRoot $WorkspaceRoot
|
|
230
257
|
}
|
|
231
258
|
$release = $env:HUB_INSTALL_RELEASE_BASE
|
|
232
259
|
if (-not $release) { $release = $ReleaseBase }
|
|
@@ -300,7 +327,10 @@ function Invoke-HubSetup {
|
|
|
300
327
|
|
|
301
328
|
# ---------- preview and apply ----------
|
|
302
329
|
$preview = Join-Path $tmp 'preview.json'
|
|
303
|
-
$
|
|
330
|
+
$command = @('setup', 'preview', '--profile', $SetupProfile, '--enrollment', 'separate', '--manifest', $manifest, '--out', $preview)
|
|
331
|
+
if ($nativeRoot) { $command += @('--workspace-root', $nativeRoot) }
|
|
332
|
+
if ($Activate -eq '1') { $command += '--confirm-activation' }
|
|
333
|
+
$rc = Invoke-HubTool $command
|
|
304
334
|
if ($rc -ne 0) { throw "setup preview failed (hubctl exit $rc); nothing was changed" }
|
|
305
335
|
if (-not (Test-Path -LiteralPath $preview) -or (Get-Item -LiteralPath $preview).Length -eq 0) {
|
|
306
336
|
throw 'setup preview wrote no preview; nothing was changed'
|
|
@@ -312,7 +342,9 @@ function Invoke-HubSetup {
|
|
|
312
342
|
throw 'nothing was applied: make the edits listed above by hand (hubctl does not write those files), then run this command again'
|
|
313
343
|
}
|
|
314
344
|
|
|
315
|
-
$
|
|
345
|
+
$command = @('setup', 'apply', '--preview', $preview, '--manifest', $manifest)
|
|
346
|
+
if ($Activate -eq '1') { $command += '--confirm-activation' }
|
|
347
|
+
$rc = Invoke-HubTool $command
|
|
316
348
|
switch ($rc) {
|
|
317
349
|
0 { break }
|
|
318
350
|
10 { throw 'setup apply needs edits by hand or found a conflict (see above); resolve them, then run this command again' }
|
|
@@ -23,7 +23,10 @@ export type Placeholder = (typeof PLACEHOLDERS)[number]
|
|
|
23
23
|
const PROFILES: readonly InstallProfile[] = ["session-only", "launch-node", "full-harness"]
|
|
24
24
|
const KEYS = new Set(["profile", "root", "activate"])
|
|
25
25
|
const DEFAULT_ROOT = "~/projects"
|
|
26
|
-
|
|
26
|
+
/** install.sh roots: POSIX `/…` or `~/…`. */
|
|
27
|
+
const ROOT_SH = /^(?:\/|~\/)[A-Za-z0-9._/~-]*$/
|
|
28
|
+
/** install.ps1 roots: `~/…` or a drive path `C:/…` (forward slashes; the `:` only after a single drive letter). */
|
|
29
|
+
const ROOT_PS1 = /^(?:~\/|[A-Za-z]:\/)[A-Za-z0-9._/~-]*$/
|
|
27
30
|
const ROOT_MAX = 200
|
|
28
31
|
const SEMVER = /^\d+\.\d+\.\d+$/
|
|
29
32
|
const UNSAFE = /['"`$\\\r\n]/
|
|
@@ -33,9 +36,13 @@ type Parsed = { readonly ok: true; readonly choices: InstallChoices } | { readon
|
|
|
33
36
|
|
|
34
37
|
const refuse = (reason: string): Parsed => ({ ok: false, reason })
|
|
35
38
|
|
|
36
|
-
function rootProblem(root: string): string | undefined {
|
|
39
|
+
function rootProblem(script: InstallScript, root: string): string | undefined {
|
|
37
40
|
if (root.length < 1 || root.length > ROOT_MAX) return `root must be 1-${ROOT_MAX} characters`
|
|
38
|
-
if (
|
|
41
|
+
if (script === "ps1") {
|
|
42
|
+
if (!ROOT_PS1.test(root)) return "root must start with ~/ or a drive (C:/, forward slashes) and use only letters, digits and . _ / ~ -"
|
|
43
|
+
} else if (!ROOT_SH.test(root)) {
|
|
44
|
+
return "root must start with / or ~/ and use only letters, digits and . _ / ~ -"
|
|
45
|
+
}
|
|
39
46
|
if (root.includes("//")) return "root must not contain //"
|
|
40
47
|
if (root.split("/").includes("..")) return "root must not contain a .. segment"
|
|
41
48
|
return undefined
|
|
@@ -54,14 +61,12 @@ export function parseInstallQuery(script: InstallScript, search: URLSearchParams
|
|
|
54
61
|
const activate = seen.get("activate") ?? "0"
|
|
55
62
|
if (activate !== "0" && activate !== "1") return refuse("activate must be 0 or 1")
|
|
56
63
|
const root = seen.get("root")
|
|
57
|
-
if (script === "ps1") {
|
|
58
|
-
|
|
59
|
-
if (root !== undefined) return refuse("install.ps1 takes no root (no launch-node on Windows yet)")
|
|
60
|
-
if (activate !== "0") return refuse("install.ps1 supports only activate=0 for now")
|
|
64
|
+
if (script === "ps1" && profile === "full-harness") {
|
|
65
|
+
return refuse("install.ps1 does not support profile=full-harness yet: Claude Code and Codex need user services hubctl does not install on Windows yet (use session-only or launch-node)")
|
|
61
66
|
}
|
|
62
67
|
if (root !== undefined && profile !== "launch-node") return refuse("root is only for profile=launch-node")
|
|
63
68
|
if (root !== undefined) {
|
|
64
|
-
const problem = rootProblem(root)
|
|
69
|
+
const problem = rootProblem(script, root)
|
|
65
70
|
if (problem) return refuse(problem)
|
|
66
71
|
}
|
|
67
72
|
return { ok: true, choices: { profile: profile as InstallProfile, root: profile === "launch-node" ? (root ?? DEFAULT_ROOT) : "", activate } }
|
|
@@ -82,6 +82,12 @@ export interface PublicURLOptions {
|
|
|
82
82
|
* addresses and local names pass without a lookup. Other schemes and credentials still fail.
|
|
83
83
|
*/
|
|
84
84
|
readonly allowPrivate?: boolean
|
|
85
|
+
/**
|
|
86
|
+
* The narrow admin opt-in (hub.json agents.webhooks.allowPrivateHosts): these exact hostnames, normalised (lowercase,
|
|
87
|
+
* no trailing dot), may resolve to private addresses, on port 443 only. Still https only, no credentials, and the
|
|
88
|
+
* name must resolve; a listed name also skips the local-suffix rule (.local, .lan, …).
|
|
89
|
+
*/
|
|
90
|
+
readonly privateHosts?: readonly string[]
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
/** Why the hub must not send to a URL (SSRF), or undefined when it may. */
|
|
@@ -100,7 +106,10 @@ export async function publicURLProblem(raw: string, options: PublicURLOptions):
|
|
|
100
106
|
if (options.allowPrivate) return undefined
|
|
101
107
|
const host = url.hostname.toLowerCase().replace(/^\[(.*)\]$/, "$1").replace(/\.$/, "")
|
|
102
108
|
if (isIPv4(host) || isIPv6(host)) return isPrivateAddress(host) ? `${label} is a private or local address` : undefined
|
|
103
|
-
|
|
109
|
+
const listed = options.privateHosts?.some((h) => h.toLowerCase().replace(/\.$/, "") === host) === true
|
|
110
|
+
// A listed host is reachable on the https port only, so the exception never opens other services on that address.
|
|
111
|
+
if (listed && url.port !== "" && url.port !== "443") return `${label} must use port 443 for a host in allowPrivateHosts`
|
|
112
|
+
if (!listed && (host === "localhost" || !host.includes(".") || LOCAL_SUFFIXES.some((suffix) => host.endsWith(suffix)))) {
|
|
104
113
|
return `${label} is a local hostname`
|
|
105
114
|
}
|
|
106
115
|
let addresses: readonly string[]
|
|
@@ -110,7 +119,7 @@ export async function publicURLProblem(raw: string, options: PublicURLOptions):
|
|
|
110
119
|
return `${label} host ${host} does not resolve`
|
|
111
120
|
}
|
|
112
121
|
if (addresses.length === 0) return `${label} host ${host} does not resolve`
|
|
113
|
-
if (addresses.some(isPrivateAddress)) return `${label} resolves to a private or local address`
|
|
122
|
+
if (!listed && addresses.some(isPrivateAddress)) return `${label} resolves to a private or local address`
|
|
114
123
|
return undefined
|
|
115
124
|
}
|
|
116
125
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B as e,I as t,S as n,i as r,k as i,r as a}from"./ui-CFB4wQfF.js";import{o}from"./artifacts-DU9uRgs1.js";import{it as s,rt as c}from"./index-
|
|
1
|
+
import{B as e,I as t,S as n,i as r,k as i,r as a}from"./ui-CFB4wQfF.js";import{o}from"./artifacts-DU9uRgs1.js";import{it as s,rt as c}from"./index-LNMZCqgE.js";import{t as l}from"./ArtifactWorkbench-d7R1o-rs.js";var u=i(`<div class="feature-page av-page">`),d=i(`<a class="icon-btn av-back"href=/artifacts aria-label="All artifacts"title="All artifacts">`);function f(i){return(()=>{var f=u();return n(f,e(l,{get id(){return i.id},layout:`page`,get lead(){return[e(t,{get when(){return c()},get children(){return e(r,{icon:`menu`,label:`Open sidebar`,onClick:s})}}),(()=>{var t=d();return n(t,e(a,{name:`back`})),t})()]},get actions(){return e(r,{class:`av-wide`,icon:`split`,label:`Open in pane`,onClick:()=>o(i.id)})}})),f})()}export{f as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B as e,G as t,S as n,T as r,k as i,r as a}from"./ui-CFB4wQfF.js";import{t as o}from"./ArtifactWorkbench-
|
|
1
|
+
import{B as e,G as t,S as n,T as r,k as i,r as a}from"./ui-CFB4wQfF.js";import{t as o}from"./ArtifactWorkbench-d7R1o-rs.js";var s=i(`<a class=icon-btn aria-label="Full page"title="Open the artifact's full page">`);function c(i){return e(o,{get id(){return i.artifactID},layout:`pane`,onArtifact:e=>i.onTitle?.(e.title||`Untitled`),get actions(){return(()=>{var o=s();return n(o,e(a,{name:`expand`})),t(()=>r(o,`href`,`/artifacts/${encodeURIComponent(i.artifactID)}`)),o})()},get trailing(){return i.paneTools}})}export{c as ArtifactPane};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{$ as e,A as t,B as n,C as r,E as i,F as a,G as o,I as s,J as c,N as l,O as u,P as d,Q as f,R as p,S as m,T as h,U as g,W as _,_ as v,a as y,b,et as x,g as S,i as C,k as w,r as T,tt as E,u as D,x as O,y as k}from"./ui-CFB4wQfF.js";import{B as A,H as j,L as M,U as N,V as P,j as F,k as I,z as L}from"./toast-Cuu2K0hx.js";import{n as R,o as z}from"./artifacts-DU9uRgs1.js";import{B as ee,F as B,G as te,H as V,I as ne,J as H,K as re,L as ie,M as ae,N as oe,P as se,Q as ce,R as le,U as ue,V as de,W as fe,X as pe,Y as U,Z as me,at as he,et as ge,j as _e,q as ve,st as ye,z as be}from"./index-
|
|
1
|
+
import{$ as e,A as t,B as n,C as r,E as i,F as a,G as o,I as s,J as c,N as l,O as u,P as d,Q as f,R as p,S as m,T as h,U as g,W as _,_ as v,a as y,b,et as x,g as S,i as C,k as w,r as T,tt as E,u as D,x as O,y as k}from"./ui-CFB4wQfF.js";import{B as A,H as j,L as M,U as N,V as P,j as F,k as I,z as L}from"./toast-Cuu2K0hx.js";import{n as R,o as z}from"./artifacts-DU9uRgs1.js";import{B as ee,F as B,G as te,H as V,I as ne,J as H,K as re,L as ie,M as ae,N as oe,P as se,Q as ce,R as le,U as ue,V as de,W as fe,X as pe,Y as U,Z as me,at as he,et as ge,j as _e,q as ve,st as ye,z as be}from"./index-LNMZCqgE.js";import{c as xe,i as Se,n as Ce,r as we,t as Te}from"./source-BWlvaODa.js";var Ee=`ai-actions`,De=16,Oe=[`ask`,`propose-edit`,`run-action`],ke=[`queued`,`running`,`succeeded`,`failed`,`cancelled`],Ae=[`starting`,`waiting`,`offline`,`ready`,`ended`,`failed`],je=/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/,W=e=>typeof e==`object`&&!!e&&!Array.isArray(e),G=e=>typeof e==`string`&&e.length>0,Me=e=>typeof e==`number`&&Number.isFinite(e),Ne=(e,t)=>typeof t==`string`&&e.includes(t),Pe=e=>e.replace(/\/+$/,``).split(`/`).pop()||e;function Fe(e){if(W(e)&&Ne(Ae,e.status)){if(e.kind===`session`&&G(e.address))return e;if(e.kind===`launch`&&G(e.machine)&&G(e.repo))return{harness:``,mode:`checkout`,...e}}}function Ie(e){if(!W(e)||!Ne([`pending`,`applied`,`conflict`],e.state)||!Array.isArray(e.files))return;let t=e.files.filter(e=>W(e)&&G(e.mediaType)&&Me(e.bytes)&&G(e.hash));return{state:e.state,files:t,...Array.isArray(e.keep)?{keep:e.keep.filter(G)}:{},...G(e.entry)?{entry:e.entry}:{},...G(e.appliedRevisionID)?{appliedRevisionID:e.appliedRevisionID}:{}}}function Le(e){if(!W(e)||!G(e.id)||!G(e.artifactID)||!G(e.baseRevisionID)||!Me(e.revision)||!Ne(ke,e.state)||!Ne(Oe,e.kind)||typeof e.instruction!=`string`||!G(e.by)||!Me(e.createdAt)||!Me(e.updatedAt))return;let t=Fe(e.handler);if(!t)return;let n=Ie(e.proposal),{proposal:r,...i}=e;return{...i,handler:t,...n?{proposal:n}:{},...typeof e.answer==`string`?{answer:e.answer}:{},...typeof e.error==`string`?{error:e.error}:{}}}function Re(e){let t=W(e)?e:{};return{items:Array.isArray(t.items)?t.items.flatMap(e=>Le(e)??[]):[],...G(t.cursor)?{cursor:t.cursor}:{}}}function ze(e){let t=e?.[Ee];return t?t.split(`,`).map(e=>e.trim()).filter(F).slice(0,De):[]}var Be=e=>e.state===`queued`||e.state===`running`;function Ve(e,t){return e.kind===`session`?e.address.startsWith(`@`)?e.address:t?.(e.sessionID??e.address)??(e.sessionID?t?.(e.address):void 0)??e.address:`New ${e.harness||`agent`} session on ${e.machine} · ${Pe(e.repo)}`}function He(e,t){let n=(e,t)=>({tone:e,active:!1,text:t});if(e.state===`failed`)return n(`failed`,`Failed: ${e.error||`no reason given`}`);if(e.state===`cancelled`)return n(`cancelled`,`Cancelled`);if(e.state===`succeeded`){if(e.kind!==`propose-edit`)return n(`done`,`Answered`);let t=e.proposal;return t?t.state===`applied`?n(`done`,`Edit accepted`):t.state===`conflict`?n(`failed`,`Not accepted: the artifact changed after this edit was proposed. Request it again on the latest revision.`):n(`done`,`Proposed an edit: review it below`):n(`done`,`Finished without a proposal`)}let r=e.handler,i=(e,t)=>({tone:e,active:!0,text:t});switch(r.status){case`offline`:return r.kind===`session`?i(`offline`,`Waiting: ${Ve(r,t)} is offline. The request is queued and is delivered when it reconnects.`):i(`offline`,`Waiting: ${r.machine} is offline. The request is queued until it's back.`);case`starting`:return i(`waiting`,r.kind===`session`?`Sending to ${Ve(r,t)}…`:`Starting a session on ${r.machine}…`);case`waiting`:return i(`waiting`,r.kind===`launch`?`Waiting for a session on ${r.machine}${r.reason?`: ${r.reason}`:``}`:`Waiting for ${Ve(r,t)}`);case`ready`:return e.state===`running`?i(`running`,`Working: ${Ve(r,t)} has the request.`):i(`waiting`,`Request delivered to ${Ve(r,t)}; waiting for it to pick it up.`);default:return i(`waiting`,`The handler ${r.status===`ended`?`ended`:`failed`}; the job finishes shortly.`)}}function Ue(e){return e===`user`?`You`:e.startsWith(`app:`)?`App ${e.slice(4)}`:`Session ${e}`}function We(e,t){let n=t.get(e);return n===void 0?`revision ${e.slice(-6)}`:`revision ${n}`}function Ge(e){let t=[],n=[];for(let r of e.sessions){if(r.archived)continue;let e=r.name?.replace(/^@+/,``)?`@${r.name.replace(/^@+/,``)}`:void 0,i=r.title||r.id,a=[r.machineName,r.harness].filter(Boolean).join(` · `),o=`${r.online?`●`:`○`} ${e?`${e} — ${i} · ${a}`:`${i} · ${a}`}${r.online?``:` (offline: queued until it reconnects)`}`,s={key:`session:${r.id}`,kind:`session`,label:o,display:e??i,online:r.online,handler:{session:r.id},search:[e,r.title,r.id,r.machineName,r.harness].filter(Boolean).join(` `).toLowerCase()};e?t.push({...s,sortName:e.toLowerCase()}):n.push(s)}t.sort((e,t)=>e.sortName<t.sortName?-1:+(e.sortName>t.sortName));let r=[...t.map(({sortName:e,...t})=>t),...n];for(let t of e.bindings){let n=e.machines.find(e=>e.id===t.machineID),i=n?.online??!1,a=`New session in ${t.label||Pe(t.repo)} on ${n?.name??t.machineID}`;r.push({key:`launch:${t.id}`,kind:`launch`,label:`${a}${i?``:` (machine offline: waits for it)`}`,display:a,online:i,handler:{launch:{machine:t.machineID,repo:t.repo}},search:[a,t.repo,t.machineID].join(` `).toLowerCase()})}return r}function Ke(e,t,n){let r=t.trim().toLowerCase();return r?e.filter(e=>e.key===n||e.search.includes(r)):[...e]}function qe(e){let t=new Map;for(let n of e)n.kind===`session`&&`session`in n.handler&&n.handler.session&&t.set(n.handler.session,n.display);return t}function Je(e){return e.kind===`session`?{session:e.sessionID??e.address}:{launch:{machine:e.machine,repo:e.repo,...e.harness?{harness:e.harness}:{},...e.model?{model:e.model}:{},...e.agent?{agent:e.agent}:{},mode:e.mode}}}function Ye(e){let t=e=>({ok:!1,problem:e});if(!e.handler)return t(`Choose who handles this request.`);let n=e.instruction.trim();if(e.kind===`run-action`){let r=e.actions??[];if(r.length===0)return t(`This artifact declares no AI actions.`);if(!e.action||!r.includes(e.action))return t(`Choose one of the artifact's actions.`);n||=`Run the ${e.action} action.`}if(!n)return t(e.kind===`ask`?`Write a question.`:`Describe the edit.`);if(n.length>R.aiInstructionChars)return t(`Keep it under ${R.aiInstructionChars.toLocaleString(`en-US`)} characters.`);if(je.test(n))return t(`Use plain text (no control characters).`);let r={kind:e.kind,baseRevisionID:e.baseRevisionID,instruction:n,handler:e.handler};return e.kind===`run-action`?{ok:!0,request:{kind:`run-action`,action:e.action,baseRevisionID:e.baseRevisionID,instruction:n,handler:e.handler}}:{ok:!0,request:e.kind===`propose-edit`?{...r,apply:`manual`}:r}}var Xe=4e6,Ze=3,Qe=e=>{let t=e.replace(/\r\n?/g,`
|
|
2
2
|
`).split(`
|
|
3
3
|
`);return t.length>1&&t[t.length-1]===``&&t.pop(),e===``?[]:t};function $e(e,t){let n=Qe(e),r=Qe(t),i=[{type:`meta`,text:`Too large to compare line by line.`}];if(n.length+r.length>1e4)return i;let a=0;for(;a<n.length&&a<r.length&&n[a]===r[a];)a++;let o=n.length,s=r.length;for(;o>a&&s>a&&n[o-1]===r[s-1];)o--,s--;let c=o-a,l=s-a;if((c+1)*(l+1)>Xe)return i;let u=l+1,d=new Uint32Array((c+1)*u);for(let e=c-1;e>=0;e--)for(let t=l-1;t>=0;t--)d[e*u+t]=n[a+e]===r[a+t]?d[(e+1)*u+t+1]+1:Math.max(d[(e+1)*u+t],d[e*u+t+1]);let f=[];for(let e=0;e<a;e++)f.push({type:`context`,text:n[e],oldNo:e+1,newNo:e+1});let p=0,m=0,h=[],g=[],_=()=>{f.push(...h,...g),h=[],g=[]};for(;p<c||m<l;)p<c&&m<l&&n[a+p]===r[a+m]?(_(),f.push({type:`context`,text:n[a+p],oldNo:a+p+1,newNo:a+m+1}),p++,m++):m<l&&(p===c||d[p*u+m+1]>=d[(p+1)*u+m])?(g.push({type:`add`,text:r[a+m],newNo:a+m+1}),m++):(h.push({type:`del`,text:n[a+p],oldNo:a+p+1}),p++);_();for(let e=0;e<n.length-o;e++)f.push({type:`context`,text:n[o+e],oldNo:o+e+1,newNo:s+e+1});let v=new Uint8Array(f.length);f.forEach((e,t)=>{if(e.type!==`context`)for(let e=Math.max(0,t-Ze);e<=Math.min(f.length-1,t+Ze);e++)v[e]=1});let y=[],b=0;for(;b<f.length;){if(!v[b]){b++;continue}let e=b;for(;e<f.length&&v[e];)e++;let t=f.slice(b,e),n=t.find(e=>e.oldNo!==void 0)?.oldNo??0,r=t.find(e=>e.newNo!==void 0)?.newNo??0,i=t.filter(e=>e.type!==`add`).length,a=t.filter(e=>e.type!==`del`).length;y.push({type:`hunk`,text:`@@ -${n},${i} +${r},${a} @@`});for(let e of t)y.push(e);b=e}return y}function et(e,t){if(!(t.files.some(e=>e.path!==void 0)||t.keep.length>0||e.some(e=>e.path!==void 0))){let n=e[0];return t.files.map(e=>({change:n?n.hash===e.hash?`unchanged`:`changed`:`added`,mediaType:e.mediaType,bytes:e.bytes,...n?{baseBytes:n.bytes}:{}}))}let n=new Map(e.map(e=>[e.path??``,e])),r=[],i=new Set;for(let e of t.files){let t=e.path??``;i.add(t);let a=n.get(t);r.push({path:t,change:a?a.hash===e.hash?`unchanged`:`changed`:`added`,mediaType:e.mediaType,bytes:e.bytes,...a?{baseBytes:a.bytes}:{}})}for(let e of t.keep){if(i.has(e))continue;i.add(e);let t=n.get(e);r.push({path:e,change:`kept`,mediaType:t?.mediaType??``,bytes:t?.bytes??0,...t?{baseBytes:t.bytes}:{}})}for(let t of e){let e=t.path??``;i.has(e)||r.push({path:e,change:`removed`,mediaType:t.mediaType,bytes:0,baseBytes:t.bytes})}return r}function K(e){let t=W(e)||e instanceof Error?e:{},n=Me(t.status)?t.status:0,r=typeof t.code==`string`?t.code:``,i=typeof t.message==`string`?t.message:String(e),a=W(t.details)?t.details:{};if(n===422||r===`unsupported`){let e=typeof a.feature==`string`?a.feature:``;return e===`artifactActions`?{kind:`unsupported`,text:`This artifact declares no AI actions.`}:!e||e===`artifacts`?{kind:`unsupported`,text:`AI requests aren't supported on this hub.`}:{kind:`unsupported`,text:`Not supported on this hub (${e}): ${i}`}}return n===404||r===`not_found`?{kind:`unavailable`,text:`AI requests aren't available for this artifact (it doesn't exist, or you can't see it).`}:n===401||n===403||r===`forbidden`?{kind:`forbidden`,text:`Not allowed: ${i}`}:n===409||r===`conflict`?{kind:`conflict`,text:i}:n===429||r===`rate_limited`?{kind:`rate_limited`,text:`Too many AI requests are running (on this artifact or for you). Wait for one to finish.`}:n===503||r===`offline`?{kind:`offline`,text:`Offline: ${i}`}:n===400||r===`invalid`?{kind:`invalid`,text:i}:{kind:`error`,text:i}}function tt(e){return e.proposal?.state===`conflict`?`stale-base`:`job-changed`}function nt(e){return Math.min(1e4,Math.round(1500*1.5**Math.max(0,e)))}var rt={set(e,t){let n=setTimeout(e,t);return()=>clearTimeout(n)}},it=()=>globalThis.crypto?.randomUUID?.()??`${Date.now()}-${Math.random().toString(36).slice(2)}`,at=e=>!(e&&typeof e==`object`&&typeof e.status==`number`);function ot(e){let{source:t,artifactID:n,onState:r}=e,i=e.timers??rt,a=e.key??it,o={status:`loading`,actions:[],revisionNumbers:new Map,jobs:[],more:!1,loadingMore:!1,handlers:[],sending:!1,pending:{},notices:{},reviews:{}},s,c,l=0,u=!1,d,f=e=>{u||(o={...o,...e},r(o))},p=e=>o.jobs.find(t=>t.id===e),m=e=>f({jobs:o.jobs.some(t=>t.id===e.id)?o.jobs.map(t=>t.id===e.id?e:t):[e,...o.jobs]}),h=(e,t)=>{let{[e]:n,...r}=o.notices;f({notices:t?{...r,[e]:t}:r})},g=(e,t)=>{let{[e]:n,...r}=o.pending;f({pending:t?{...r,[e]:t}:r})};async function _(){let[e,r]=await Promise.all([t.artifact(n),t.revisionNumbers(n).catch(()=>o.revisionNumbers)]);f({artifact:e,actions:ze(e.metadata),revisionNumbers:r})}function v(){c?.(),c=void 0,u||!o.jobs.some(Be)?l=0:c=i.set(()=>{c=void 0,x()},nt(l))}async function y(){f({status:`loading`});try{let[,e]=await Promise.all([_(),t.jobs(n)]);s=e.cursor,f({status:`ready`,jobs:e.items,more:!!e.cursor,error:void 0})}catch(e){f({status:`error`,error:K(e)});return}v(),await b()}async function b(){if(!u&&o.artifact)try{f({handlers:await t.handlers(o.artifact),handlersError:void 0})}catch(e){f({handlersError:K(e).text})}}async function x(){if(!(u||o.status!==`ready`)){try{let e=await t.jobs(n),r=new Map(o.jobs.map(e=>[e.id,e])),i=new Set(e.items.map(e=>e.id)),a=e.items.some(e=>r.get(e.id)?.revision!==e.revision),s=e.items.some(e=>!Be(e)&&r.get(e.id)&&Be(r.get(e.id)));f({jobs:[...e.items,...o.jobs.filter(e=>!i.has(e.id))]}),l=a?0:l+1,s&&await _().catch(()=>void 0)}catch{l++}v()}}async function S(){if(s&&!o.loadingMore){f({loadingMore:!0});try{let e=await t.jobs(n,s);s=e.cursor;let r=new Set(o.jobs.map(e=>e.id));f({jobs:[...o.jobs,...e.items.filter(e=>!r.has(e.id))],more:!!e.cursor,loadingMore:!1})}catch(e){f({loadingMore:!1,sendError:K(e)})}}}async function C(e){let r=JSON.stringify(e),i=d?.body===r?d.key:a();try{let r=await t.create(n,e,i);return d=void 0,m(r),f({sending:!1,sendError:void 0}),l=0,v(),r}catch(e){d=at(e)?{body:r,key:i}:void 0;let t=K(e);f({sending:!1,sendError:t}),t.kind===`conflict`&&await _().catch(()=>void 0);return}}async function w(e){return await T(e)!==void 0}async function T(e){if(o.sending||!o.artifact)return;if(e.baseRevisionID!==void 0&&e.baseRevisionID!==o.artifact.latestRevisionID){f({sendError:{kind:`conflict`,text:`The artifact changed since that view opened: the request was not sent.`}});return}let t=o.handlers.find(t=>t.key===e.handlerKey)?.handler,n=Ye({kind:e.kind,instruction:e.instruction,baseRevisionID:o.artifact.latestRevisionID,...t?{handler:t}:{},...e.action?{action:e.action}:{},actions:o.actions});if(!n.ok)f({sendError:{kind:`invalid`,text:n.problem}});else return f({sending:!0,sendError:void 0}),C(n.request)}async function E(e){try{let r=await t.job(n,e);return m(r),r}catch{return}}async function D(e){let r=p(e);if(!r||o.pending[e]||!Be(r))return!1;g(e,`cancel`);try{return m(await t.cancel(n,e,r.revision)),h(e,void 0),!0}catch(t){let n=K(t),r=n.kind===`conflict`?await E(e):void 0;return h(e,{kind:n.kind===`conflict`?`conflict`:`error`,text:r&&!Be(r)?`Not cancelled: it already ${r.state===`succeeded`?`finished`:r.state}.`:n.text}),!1}finally{g(e,void 0),v()}}async function O(e){let r=p(e);if(!r||o.pending[e]||r.kind!==`propose-edit`||r.state!==`succeeded`||r.proposal?.state!==`pending`)return!1;g(e,`apply`);try{let i=await t.apply(n,e,r.revision);m(i.job),await _().catch(()=>void 0);let a=i.revisionNumber??o.revisionNumbers.get(i.revisionID);return h(e,{kind:`info`,text:a===void 0?`Accepted as a new revision.`:`Accepted as revision ${a}.`}),!0}catch(t){let n=K(t);if(n.kind!==`conflict`)return h(e,{kind:`error`,text:n.text}),!1;let[r]=await Promise.all([E(e),_().catch(()=>void 0)]);if(r&&tt(r)===`stale-base`){let t=o.artifact?We(o.artifact.latestRevisionID,o.revisionNumbers):`a newer revision`;h(e,{kind:`conflict`,stale:!0,text:`Not accepted: the artifact changed since this edit was proposed (it is at ${t} now). Nothing was changed. Request the edit again on the latest revision.`})}else h(e,{kind:`conflict`,stale:!1,text:`This request changed since you read it. Review it again, then Accept.`});return!1}finally{g(e,void 0)}}async function k(e){let t=p(e);if(!t||o.pending[e]||o.sending||t.kind!==`propose-edit`)return!1;g(e,`rerequest`),f({sending:!0,sendError:void 0});try{await _();let n=!!await C({kind:`propose-edit`,baseRevisionID:o.artifact.latestRevisionID,instruction:t.instruction,handler:Je(t.handler),apply:`manual`});return n&&h(e,{kind:`info`,text:`Requested again on the latest revision.`}),n}catch(e){return f({sending:!1,sendError:K(e)}),!1}finally{g(e,void 0)}}async function A(e){let r=p(e);if(r?.proposal){f({reviews:{...o.reviews,[e]:{status:`loading`}}});try{let[i,a]=await Promise.all([t.proposal(n,e),t.revisionFiles(n,r.baseRevisionID)]),s=et(a,{files:i.files,keep:i.keep}),c=a.length<=1&&i.files.every(e=>e.path===void 0),l=i.files.map(e=>{let t=c?a[0]:a.find(t=>t.path===e.path),n=e.path===void 0?{}:{path:e.path};return e.omitted===`binary`?{...n,note:`Binary file: not compared.`}:e.omitted===`budget`||e.text===void 0?{...n,note:`Too large to show here.`}:t&&t.text===void 0?{...n,note:t.omitted===`binary`?`Replaces a binary file.`:`The current file is too large to compare.`}:t&&t.hash===e.hash?{...n,note:`Unchanged.`}:{...n,lines:$e(t?.text??``,e.text)}});f({reviews:{...o.reviews,[e]:{status:`ready`,changes:s,diffs:l,truncated:i.truncated}}})}catch(t){f({reviews:{...o.reviews,[e]:{status:`error`,text:K(t).text}}})}}}return{state:()=>o,load:y,refresh:x,more:S,request:w,requestJob:T,cancel:D,accept:O,rerequest:k,review:A,reloadHandlers:b,dispose(){c?.(),c=void 0,u=!0}}}var st={markdown:`Markdown`,code:`Code`,image:`Image`,table:`Table`,chart:`Chart`,dashboard:`Dashboard`,html:`HTML`,app:`App`,file:`File`};function ct(e){let t=[[]];for(let n of e)n.text.split(`
|
|
4
4
|
`).forEach((e,r)=>{r>0&&t.push([]),e&&t[t.length-1].push(n.kind?{text:e,kind:n.kind}:{text:e})});return t.length>1&&t[t.length-1].length===0&&t.pop(),t}var lt={ts:`TypeScript`,tsx:`TypeScript (TSX)`,js:`JavaScript`,jsx:`JavaScript (JSX)`,python:`Python`,go:`Go`,rust:`Rust`,bash:`Shell`,json:`JSON`,css:`CSS`,html:`HTML`,markdown:`Markdown`,yaml:`YAML`,toml:`TOML`,sql:`SQL`,java:`Java`,c:`C`,cpp:`C++`,ruby:`Ruby`,swift:`Swift`,kotlin:`Kotlin`,diff:`Diff`,csv:`CSV`};function ut(e,t){return{name:e?.path?.split(`/`).pop()||`Untitled`,language:t?lt[t]??t.toUpperCase():`Plain text`}}function dt(e,t){let n=[{label:`Type`,value:st[e.kind]??e.kind},{label:`Visibility`,value:e.visibility===`workspace`?`Workspace members`:`Private (only you)`}];e.workspaceID&&n.push({label:`Workspace`,value:t.workspaceName??e.workspaceID}),n.push({label:`Created by`,value:e.createdBySessionID?ne({kind:`session`,sessionID:e.createdBySessionID}):`You`}),n.push({label:`Created`,value:t.when(e.createdAt)},{label:`Updated`,value:t.when(e.updatedAt)}),e.state===`archived`&&n.push({label:`State`,value:`Archived (read only)`}),e.tags?.length&&n.push({label:`Tags`,value:e.tags.join(`, `)});let r=ze(e.metadata);r.length&&n.push({label:`AI actions`,value:r.join(`, `)});for(let[t,r]of Object.entries(e.metadata??{}))t!==`ai-actions`&&n.push({label:t,value:r});return n}var ft={ask:`ask`,edit:`propose-edit`,action:`run-action`};function pt(e,t){let n=/^\/([a-z]+)(?:\s+([\s\S]*))?$/.exec(e),r=n?ft[n[1]]:void 0;if(!n||!r)return{text:e};let i=n[2]??``;if(r!==`run-action`)return{kind:r,text:i};let a=/^(\S+)\s*([\s\S]*)$/.exec(i);return!a||!t.includes(a[1])?{text:e}:{kind:r,action:a[1],text:a[2]}}var mt=`hub.artifactAiHandler.v1`;function ht(e,t){try{e?.setItem(mt,t)}catch{}}function gt(e,t){let n=null;try{n=e?.getItem(`hub.artifactAiHandler.v1`)??null}catch{return}return n?t.find(e=>e.key===n):void 0}function _t(e){return[...e].reverse()}var vt=`hub.artifactAiPanel.v1`,q={min:280,max:640,default:380,share:.6};function yt(e,t){if(!Number.isFinite(e))return q.default;let n=Math.max(q.min,Math.min(q.max,Math.floor(t*q.share)));return Math.min(n,Math.max(q.min,Math.round(e)))}function bt(e){try{let t=JSON.parse(e?.getItem(`hub.artifactAiPanel.v1`)??`null`);if(!t||typeof t!=`object`)return{};let{open:n,width:r}=t;return{...typeof n==`boolean`?{open:n}:{},...typeof r==`number`&&Number.isFinite(r)?{width:r}:{}}}catch{return{}}}function xt(e,t){try{e?.setItem(vt,JSON.stringify(t))}catch{}}var St=w(`<input type=search class=aai-picker-search aria-label="Search handlers"placeholder=Find… title="Find a handler by @name, title or session ID">`),Ct=w(`<optgroup label="Your sessions">`),wt=w(`<optgroup label="New session in a workspace repo">`),Tt=w(`<span><select aria-label="Handled by"title="Who handles this request"><option value>`),Et=w(`<option>`),Dt=w(`<button type=button class=aai-recent>Use `);function Ot(){try{return window.localStorage}catch{return}}function kt(e){let[t,r]=c(``),i=()=>e.value?void 0:gt(Ot(),e.handlers),a=_(()=>Ke(e.handlers,t(),e.value)),u=()=>a().filter(e=>e.kind===`session`),d=()=>a().filter(e=>e.kind===`launch`),f=()=>!!t().trim()&&!a().some(t=>t.key!==e.value);return(()=>{var a=Tt(),c=a.firstChild,p=c.firstChild;return m(a,n(s,{get when(){return e.handlers.length>1},get children(){var n=St();return n.$$input=e=>r(e.currentTarget.value),n.addEventListener(`focus`,()=>e.onPick?.()),o(()=>n.value=t()),n}}),c),c.addEventListener(`change`,t=>e.onChange(t.currentTarget.value)),c.addEventListener(`focus`,()=>e.onPick?.()),m(p,()=>f()?`No handler matches the search`:`Choose a session…`),m(c,n(s,{get when(){return u().length},get children(){var t=Ct();return m(t,n(l,{get each(){return u()},children:t=>(()=>{var n=Et();return m(n,()=>t.label),o(()=>n.selected=t.key===e.value),o(()=>n.value=t.key),n})()})),t}}),null),m(c,n(s,{get when(){return d().length},get children(){var t=wt();return m(t,n(l,{get each(){return d()},children:t=>(()=>{var n=Et();return m(n,()=>t.label),o(()=>n.selected=t.key===e.value),o(()=>n.value=t.key),n})()})),t}}),null),m(a,n(s,{get when(){return i()},children:t=>(()=>{var n=Dt();return n.firstChild,n.$$click=()=>e.onChange(t().key),m(n,()=>t().display,null),o(e=>{var r=`Last used on this device: ${t().label}`,i=`Use ${t().display} (last used)`;return r!==e.e&&h(n,`title`,e.e=r),i!==e.t&&h(n,`aria-label`,e.t=i),e},{e:void 0,t:void 0}),n})()}),null),o(()=>b(a,`aai-picker ${e.class??``}`)),o(()=>c.value=e.value),a})()}O([`input`,`click`]);var At=`/api/agent/artifacts`,jt=50,Mt=262144,Nt=e=>e.startsWith(`text/`)||e===`application/json`||e===`image/svg+xml`,J=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Pt=e=>new M(502,`The hub answered an unexpected ${e}`);function Ft(e){let t=J(e)&&J(e.artifact)?e.artifact:e;if(!J(t)||typeof t.id!=`string`||typeof t.latestRevisionID!=`string`||typeof t.revision!=`number`)throw Pt(`artifact`);return{id:t.id,title:typeof t.title==`string`?t.title:``,kind:typeof t.kind==`string`?t.kind:`file`,state:typeof t.state==`string`?t.state:`active`,latestRevisionID:t.latestRevisionID,revision:t.revision,...typeof t.workspaceID==`string`?{workspaceID:t.workspaceID}:{},...J(t.metadata)?{metadata:t.metadata}:{}}}var It=e=>{let t=Le(J(e)?e.job:void 0);if(!t)throw Pt(`job`);return t},Lt=async(e,t,n={})=>(await L(e,{method:`POST`,json:t,headers:n})).json();async function Rt(){try{let e=await j(`/api/agent/who`),t=J(e)&&Array.isArray(e.sessions)?e.sessions:[];return new Map(t.flatMap(e=>J(e)&&typeof e.sessionID==`string`&&typeof e.name==`string`&&e.name?[[e.sessionID,e.name]]:[]))}catch{return new Map}}function zt(e){let t=e=>`${At}/${A(e)}/jobs`,n=(e,n,r=``)=>`${t(e)}/${A(n)}${r}`;return{artifact:async e=>Ft(await j(`${At}/${A(e)}`)),async revisionNumbers(e){let t=await j(`${At}/${A(e)}/revisions?limit=200`),n=J(t)&&Array.isArray(t.items)?t.items:[];return new Map(n.flatMap(e=>J(e)&&typeof e.id==`string`&&typeof e.number==`number`?[[e.id,e.number]]:[]))},jobs:async(e,n)=>Re(await j(`${t(e)}?limit=${jt}${n?`&cursor=${A(n)}`:``}`)),job:async(e,t)=>It(await j(n(e,t))),create:async(e,n,r)=>It(await Lt(t(e),n,{"idempotency-key":r})),cancel:async(e,t,r)=>It(await Lt(n(e,t,`/cancel`),{expectedRevision:r})),async apply(e,t,r){let i=await Lt(n(e,t,`/apply`),{expectedRevision:r}),a=J(i)&&J(i.revision)?i.revision:{};if(typeof a.id!=`string`)throw Pt(`revision`);return{job:It(i),revisionID:a.id,...typeof a.number==`number`?{revisionNumber:a.number}:{}}},proposal:async(e,t)=>{let r=await j(n(e,t,`/proposal`));if(!J(r)||!Array.isArray(r.files))throw Pt(`proposal`);return{...r,keep:Array.isArray(r.keep)?r.keep:[],truncated:r.truncated===!0}},async revisionFiles(e,t){let n=await j(`${At}/${A(e)}/revisions/${A(t)}`),r=J(n)&&J(n.revision)&&Array.isArray(n.revision.blobs)?n.revision.blobs:[],i=Mt,a=[];for(let n of r){if(!J(n)||typeof n.hash!=`string`||typeof n.mediaType!=`string`||typeof n.bytes!=`number`)continue;let r={...typeof n.path==`string`?{path:n.path}:{},hash:n.hash,mediaType:n.mediaType,bytes:n.bytes};Nt(n.mediaType)?n.bytes>i?a.push({...r,omitted:`budget`}):(i-=n.bytes,a.push({...r,text:await(await L(`${At}/${A(e)}/revisions/${A(t)}/blobs/${A(n.hash)}`)).text()})):a.push({...r,omitted:`binary`})}return a},async handlers(t){let[n,r]=await Promise.all([(async()=>{if(!t.workspaceID)return[];try{let e=await j(`/api/agent/workspaces/${A(t.workspaceID)}/bindings`);return(J(e)&&Array.isArray(e.bindings)?e.bindings:[]).flatMap(e=>J(e)&&typeof e.id==`string`&&typeof e.machineID==`string`&&typeof e.repo==`string`?[{id:e.id,machineID:e.machineID,repo:e.repo,...typeof e.label==`string`?{label:e.label}:{}}]:[])}catch{return[]}})(),Rt()]);return Ge({sessions:e.sessions().map(e=>r.get(e.id)?{...e,name:r.get(e.id)}:e),bindings:n,machines:e.machines()})}}}var Bt=w(`<span>an unknown revision`),Vt=w(`<button type=button class=aai-link>`),Ht=w(`<span>`),Ut=w(`<strong class=aai-older>You are viewing an older revision.`),Wt=w(`<p class=aai-sub>Requests use the latest revision (<!>).`),Gt=w(`<p class=aai-note role=status>Loading AI requests…`),Kt=w(`<button type=button class="btn small aai-older-btn">Load older requests`),qt=w(`<ol class=aai-jobs aria-label="AI request history">`),Jt=w(`<p class=aai-note>Could not list handlers: `),Yt=w(`<p class=aai-note role=status>`),Xt=w(`<div class=aai-confirm role=group aria-label="Confirm action"><p>Run <strong></strong> on <!>, handled by <strong></strong>? It gets a read-only copy of this revision; its answer shows here and nothing is changed.</p><div class=aai-actions><button type=button class="btn primary small">Confirm and run</button><button type=button class="btn small">Back`),Zt=w(`<select class=aai-action aria-label="Declared action"><option value>Choose an action…`),Qt=w(`<form class=aai-composer aria-label="New AI request"><div class=aai-box><div class=aai-box-top><div class=aai-seg role=radiogroup aria-label="Request type"></div></div><textarea class=aai-input rows=2></textarea><div class=aai-box-foot><span class=aai-hint>Ctrl+Enter</span><button type=submit class=aai-send><span class=aai-send-text>`),$t=w(`<section class=aai><header class=aai-head><span class=aai-mark aria-hidden=true></span><div class=aai-head-text><h2 class=aai-title>AI requests</h2></div></header><div class=aai-scroll>`),en=w(`<button type=button class="btn small">Retry`),tn=w(`<p class=aai-note> `),nn=w(`<kbd>/action `),rn=w(`<div class=aai-empty><p><strong>Ask about this artifact, or describe an edit.</strong></p><p>The session you choose gets a read-only copy. Nothing changes until you accept an edit.</p><p class=aai-tips>Tip: start with <kbd>/ask</kbd>, <kbd>/edit</kbd>.`),an=w(`<p class="aai-note err"role=alert>`),on=w(`<label class=aai-seg-item><input type=radio>`),sn=w(`<option>`),cn=w(`<span class=aai-dot aria-hidden=true>`),ln=w(`<div class=aai-answer>`),un=w(`<p class="aai-note warn"role=status>The artifact changed since this edit was proposed: accepting it will be refused. Request it again on the latest revision.`),dn=w(`<button type=button class="btn primary small">`),fn=w(`<button type=button class="btn small">Request again on the latest revision`),pn=w(`<button type=button class="btn small">`),mn=w(`<button type=button class="btn small">Continue in side chat`),hn=w(`<li class=aai-job><div class=aai-q><div class=aai-q-meta><span class=aai-badge></span><span class=aai-meta> · </span></div><p class=aai-instruction></p></div><div class=aai-a><p class="aai-meta aai-prov">On <!> · handled by </p><p role=status aria-live=polite></p><div class=aai-actions>`),gn=w(`<div class=aai-proposal>`),_n=w(`<button type=button class="btn small">Review proposed edit (<!> file<!>)`),vn=w(`<p class=aai-note role=status>Loading the proposal…`),yn=w(`<p class="aai-note err">Could not load the proposal: `),bn=w(`<ul class=aai-files aria-label="Proposed files">`),xn=w(`<p class=aai-note>Some files are too large to show here.`),Sn=w(`<li><span class=aai-file-change></span> <code>`),Cn=w(`<p class=aai-meta><code>`),wn=w(`<table class=diff><tbody>`),Tn=w(`<div class=aai-diff>`),En=w(`<p class=aai-note>`),Dn=w(`<tr><td class=ln></td><td class=ln></td><td class=code-line><span class=sign>`),On=w(`<p>`),kn={ask:`Ask`,"propose-edit":`Edit`,"run-action":`Action`},An={ask:`Ask a question (answer only)`,"propose-edit":`Propose an edit you review before it applies`,"run-action":`Run one of the artifact's declared actions`},jn=e=>e.kind===`ask`?`Question`:e.kind===`propose-edit`?`Edit`:`Action: ${e.action??`?`}`;function Mn(){return zt({sessions:()=>{let e=new Map;for(let t of he.machines??[])for(let n of t.processes)for(let t of n.sessions)e.set(t.id,n.harness||`opencode`);return ye().filter(e=>!e.hidden&&!e.archived).map(t=>({id:t.id,title:t.title,machineName:t.machineName,online:t.machineOnline,...e.get(t.id)?{harness:e.get(t.id)}:{}}))},machines:()=>(he.machines??[]).map(e=>({id:e.id,name:e.name,online:!!e.online}))})}function Nn(i){let[u,d]=c(),f=!i.controller,v=i.controller?.ai??ot({source:i.source??Mn(),artifactID:i.artifactID,onState:d});E(()=>f&&void v.load()),x(()=>f&&v.dispose());let y=()=>(f?u():i.controller.state())??v.state(),b=()=>y().revisionNumbers,S=()=>y().artifact?.latestRevisionID,[C,w]=c(`ask`),[D,O]=c(``),[k,A]=c(``),[j,M]=c(``),[N,P]=c(!1),F,I,L,R=_(()=>y().handlers.find(e=>e.key===k())),z=()=>C()===`ask`?`Ask`:C()===`propose-edit`?`Propose edit`:j()?`Run ${j()}…`:`Run action…`,ee=_(()=>_t(y().jobs));g(e(()=>[y().jobs.length,i.tailCount??0],()=>queueMicrotask(()=>L&&(L.scrollTop=L.scrollHeight))));async function B(){let e=k(),t=await v.request({kind:C(),instruction:D(),...e?{handlerKey:e}:{},...C()===`run-action`&&j()?{action:j()}:{}});P(!1),t&&(O(``),ht(Ot(),e))}function te(e){e?.preventDefault(),!y().sending&&(C()===`run-action`&&j()&&k()?(P(!0),queueMicrotask(()=>F?.focus())):B())}function V(e){let t=pt(e,y().actions);t.kind&&/\s$/.test(e)?(w(t.kind),t.action&&M(t.action),P(!1),O(t.text),I&&(I.value=t.text)):O(e)}async function ne(e){if(await v.accept(e.id)){let e=S();e&&i.onRevised?.(e)}}let H=(e,t=``)=>n(s,{when:e,get fallback(){return(()=>{var e=Bt(),n=e.firstChild;return m(e,t,n),e})()},children:e=>n(s,{get when(){return i.onShowRevision},get fallback(){return(()=>{var n=Ht();return m(n,()=>t+We(e(),b())),n})()},get children(){var n=Vt();return n.$$click=()=>i.onShowRevision?.(e()),m(n,()=>t+We(e(),b())),n}})});return(()=>{var e=$t(),c=e.firstChild,u=c.firstChild,d=u.nextSibling,f=d.firstChild,g=c.nextSibling;m(u,n(T,{name:`spark`})),m(d,n(s,{get when(){return y().status===`ready`},get children(){var e=Wt(),t=e.firstChild.nextSibling;return t.nextSibling,m(e,()=>H(S()),t),m(e,n(s,{get when(){return r(()=>!!(i.revisionID&&S()))()&&i.revisionID!==S()},get children(){return[` `,Ut()]}}),null),e}}),null),m(c,()=>i.headerActions,null);var _=L;return typeof _==`function`?t(_,g):L=g,m(g,n(p,{get children(){return[n(a,{get when(){return y().status===`loading`},get children(){return Gt()}}),n(a,{get when(){return r(()=>y().status===`error`)()&&y().error},children:e=>(()=>{var t=tn(),r=t.firstChild;return m(t,()=>e().text,r),m(t,n(s,{get when(){return e().kind===`error`||e().kind===`offline`},get children(){var e=en();return e.$$click=()=>void v.load(),e}}),null),o(n=>{var r=e().kind===`error`,i=e().kind===`error`?`alert`:`status`;return r!==n.e&&t.classList.toggle(`err`,n.e=r),i!==n.t&&h(t,`role`,n.t=i),n},{e:void 0,t:void 0}),t})()}),n(a,{get when(){return y().status===`ready`},get children(){return[n(s,{get when(){return y().more},get children(){var e=Kt();return e.$$click=()=>void v.more(),o(t=>{var n=y().loadingMore,r=y().loadingMore;return n!==t.e&&(e.disabled=t.e=n),r!==t.t&&h(e,`aria-busy`,t.t=r),t},{e:void 0,t:void 0}),e}}),n(s,{get when(){return y().jobs.length},get fallback(){return(()=>{var e=rn(),t=e.firstChild.nextSibling.nextSibling,r=t.firstChild.nextSibling.nextSibling.nextSibling.nextSibling;return m(t,n(s,{get when(){return y().actions.length},get children(){return[` `,`or `,(()=>{var e=nn();return e.firstChild,m(e,()=>y().actions[0],null),e})()]}}),r),e})()},get children(){var e=qt();return m(e,n(l,{get each(){return ee()},children:e=>n(Pn,{job:e,get state(){return y()},revisionRef:H,onCancel:()=>void v.cancel(e.id),onReview:()=>void v.review(e.id),onAccept:()=>void ne(e),onRerequest:()=>void v.rerequest(e.id),get onContinue(){return i.onContinueInSideChat}})})),e}})]}})]}}),null),m(g,()=>i.threadTail,null),m(e,n(s,{get when(){return y().status===`ready`},get children(){var e=Qt(),a=e.firstChild,c=a.firstChild,u=c.firstChild,d=c.nextSibling,f=d.nextSibling,p=f.firstChild,g=p.nextSibling,_=g.firstChild;e.addEventListener(`submit`,te),m(e,n(s,{get when(){return y().sendError},children:e=>(()=>{var t=an();return m(t,()=>e().text),t})()}),a),m(e,n(s,{get when(){return y().handlersError},get children(){var e=Jt();return e.firstChild,m(e,()=>y().handlersError,null),e}}),a),m(e,n(s,{get when(){return r(()=>!!R())()&&!R().online},get children(){var e=Yt();return m(e,()=>R().kind===`session`?`That session is offline: the request is queued and delivered when it reconnects.`:`That machine is offline: the new session starts when it's back.`),e}}),a),m(e,n(s,{get when(){return N()},get children(){var e=Xt(),n=e.firstChild,r=n.firstChild.nextSibling,i=r.nextSibling.nextSibling,a=i.nextSibling.nextSibling,s=n.nextSibling.firstChild,c=s.nextSibling;e.$$keydown=e=>{e.key===`Escape`&&(e.preventDefault(),P(!1),I?.focus())},m(r,j),m(n,()=>We(S()??``,b()),i),m(a,()=>R()?.display),s.$$click=()=>void B();var l=F;return typeof l==`function`?t(l,s):F=s,c.$$click=()=>{P(!1),I?.focus()},o(()=>s.disabled=y().sending),e}}),a),m(u,n(l,{each:[`ask`,`propose-edit`,`run-action`],children:e=>{let t=()=>e===`run-action`&&y().actions.length===0;return(()=>{var n=on(),r=n.firstChild;return r.addEventListener(`change`,()=>{w(e),P(!1)}),r.value=e,m(n,()=>kn[e],null),o(a=>{var o=C()===e,s=!!t(),c=t()?`This artifact declares no AI actions`:An[e],l=`aai-mode-${i.artifactID}`,u=t();return o!==a.e&&n.classList.toggle(`on`,a.e=o),s!==a.t&&n.classList.toggle(`disabled`,a.t=s),c!==a.a&&h(n,`title`,a.a=c),l!==a.o&&h(r,`name`,a.o=l),u!==a.i&&(r.disabled=a.i=u),a},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),o(()=>r.checked=C()===e),n})()}})),m(c,n(s,{get when(){return C()===`run-action`},get children(){var e=Zt();return e.firstChild,e.addEventListener(`change`,e=>(M(e.currentTarget.value),P(!1))),m(e,n(l,{get each(){return y().actions},children:e=>(()=>{var t=sn();return t.value=e,m(t,e),t})()}),null),o(()=>e.value=j()),e}}),null),d.$$keydown=e=>{e.key===`Enter`&&(e.metaKey||e.ctrlKey)&&te(e)},d.$$input=e=>V(e.currentTarget.value);var x=I;return typeof x==`function`?t(x,d):I=d,m(f,n(kt,{get handlers(){return y().handlers},get value(){return k()},onPick:()=>void v.reloadHandlers(),onChange:e=>(A(e),P(!1))}),p),m(g,n(T,{name:`send`}),_),m(_,(()=>{var e=r(()=>!!y().sending);return()=>e()?`Sending…`:z()})()),o(e=>{var t=C()===`ask`?`Question`:C()===`propose-edit`?`Describe the edit`:`Notes for the action (optional)`,n=C()===`ask`?`Ask about this artifact…`:C()===`propose-edit`?`Describe the edit, e.g. Add a rollback section`:`Notes for the action (optional)`,r=y().sending||N(),i=y().sending,a=y().sending?`Sending…`:z(),o=`${z()} (Ctrl+Enter)`;return t!==e.e&&h(d,`aria-label`,e.e=t),n!==e.t&&h(d,`placeholder`,e.t=n),r!==e.a&&(g.disabled=e.a=r),i!==e.o&&h(g,`aria-busy`,e.o=i),a!==e.i&&h(g,`aria-label`,e.i=a),o!==e.n&&h(g,`title`,e.n=o),e},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),o(()=>d.value=D()),e}}),null),o(t=>{var n=`aai-h-${i.artifactID}`,r=`aai-h-${i.artifactID}`;return n!==t.e&&h(e,`aria-labelledby`,t.e=n),r!==t.t&&h(f,`id`,t.t=r),t},{e:void 0,t:void 0}),e})()}function Pn(e){let t=()=>e.job,i=_(()=>qe(e.state.handlers)),c=e=>i().get(e)??ye().find(t=>t.id===e)?.title,u=()=>He(t(),c),d=()=>e.state.pending[t().id],f=()=>e.state.notices[t().id],g=()=>e.state.reviews[t().id],v=()=>e.state.artifact?.latestRevisionID,y=()=>t().kind===`propose-edit`&&t().state===`succeeded`&&t().proposal?.state===`pending`,x=()=>y()&&v()!==void 0&&t().baseRevisionID!==v(),S=()=>t().kind===`propose-edit`&&(t().proposal?.state===`conflict`||x()||f()?.stale);return(()=>{var i=hn(),_=i.firstChild,v=_.firstChild,C=v.firstChild,w=C.nextSibling,T=w.firstChild,E=v.nextSibling,O=_.nextSibling,A=O.firstChild,j=A.firstChild.nextSibling;j.nextSibling;var M=A.nextSibling,N=M.nextSibling;return m(C,()=>jn(t())),m(w,()=>Ue(t().by),T),m(w,()=>D(t().createdAt),null),m(E,()=>t().instruction),m(A,()=>e.revisionRef(t().baseRevisionID),j),m(A,()=>Ve(t().handler,c),null),m(A,n(s,{get when(){return t().proposal?.appliedRevisionID},children:t=>[` · became `,r(()=>e.revisionRef(t()))]}),null),m(M,n(s,{get when(){return u().active},get children(){return cn()}}),null),m(M,()=>u().text,null),m(O,n(s,{get when(){return t().answer},get children(){var n=ln();return m(n,()=>t().answer),o(()=>h(n,`aria-label`,`Answer from ${Ve(t().handler,c)} on ${We(t().baseRevisionID,e.state.revisionNumbers)}`)),n}}),N),m(O,n(s,{get when(){return r(()=>!!(t().proposal&&t().proposal.state!==`applied`))()&&t().proposal},children:t=>(()=>{var i=gn();return m(i,n(s,{get when(){return g()},get fallback(){return(()=>{var n=_n(),i=n.firstChild.nextSibling,a=i.nextSibling.nextSibling;return a.nextSibling,k(n,`click`,e.onReview,!0),m(n,()=>t().files.length,i),m(n,()=>t().files.length===1?``:`s`,a),m(n,(()=>{var e=r(()=>!!t().keep?.length);return()=>e()?`, ${t().keep.length} kept`:``})(),a),n})()},children:e=>n(p,{get children(){return[n(a,{get when(){return e().status===`loading`},get children(){return vn()}}),n(a,{get when(){return r(()=>e().status===`error`)()&&e()},children:e=>(()=>{var t=yn();return t.firstChild,m(t,()=>e().text,null),t})()}),n(a,{get when(){return r(()=>e().status===`ready`)()&&e()},children:e=>{let t=()=>e();return[n(s,{get when(){return t().changes.some(e=>e.path!==void 0)},get children(){var e=bn();return m(e,n(l,{get each(){return t().changes},children:e=>(()=>{var t=Sn(),n=t.firstChild,r=n.nextSibling.nextSibling;return m(n,()=>e.change),m(r,()=>e.path),o(()=>b(t,`aai-file ${e.change}`)),t})()})),e}}),n(l,{get each(){return t().diffs},children:e=>(()=>{var t=Tn();return m(t,n(s,{get when(){return e.path},get children(){var t=Cn(),n=t.firstChild;return m(n,()=>e.path),t}}),null),m(t,n(s,{get when(){return e.lines},get fallback(){return(()=>{var t=En();return m(t,()=>e.note),t})()},get children(){var t=wn(),i=t.firstChild;return m(i,n(l,{get each(){return e.lines},children:e=>(()=>{var t=Dn(),n=t.firstChild,i=n.nextSibling,a=i.nextSibling,s=a.firstChild;return m(n,()=>e.oldNo??``),m(i,()=>e.newNo??``),m(s,(()=>{var t=r(()=>e.type===`add`);return()=>t()?`+`:e.type===`del`?`−`:` `})()),m(a,()=>e.text,null),o(()=>b(t,e.type)),t})()})),o(()=>h(t,`aria-label`,`Changes${e.path?` to ${e.path}`:``}`)),t}}),null),t})()}),n(s,{get when(){return t().truncated},get children(){return xn()}})]}})]}})})),i})()}),N),m(O,n(s,{get when(){return r(()=>!!x())()&&!f()},get children(){return un()}}),N),m(O,n(s,{get when(){return f()},children:e=>(()=>{var t=On();return m(t,()=>e().text),o(n=>{var r=`aai-note ${e().kind===`info`?`ok`:e().kind===`conflict`?`warn`:`err`}`,i=e().kind===`info`?`status`:`alert`;return r!==n.e&&b(t,n.e=r),i!==n.t&&h(t,`role`,n.t=i),n},{e:void 0,t:void 0}),t})()}),N),m(N,n(s,{get when(){return y()},get children(){var t=dn();return k(t,`click`,e.onAccept,!0),m(t,()=>d()===`apply`?`Accepting…`:`Accept as new revision`),o(e=>{var n=!!d(),r=d()===`apply`;return n!==e.e&&(t.disabled=e.e=n),r!==e.t&&h(t,`aria-busy`,e.t=r),e},{e:void 0,t:void 0}),t}}),null),m(N,n(s,{get when(){return S()},get children(){var t=fn();return k(t,`click`,e.onRerequest,!0),o(()=>t.disabled=!!d()||e.state.sending),t}}),null),m(N,n(s,{get when(){return Be(t())},get children(){var t=pn();return k(t,`click`,e.onCancel,!0),m(t,()=>d()===`cancel`?`Cancelling…`:`Cancel`),o(e=>{var n=!!d(),r=d()===`cancel`;return n!==e.e&&(t.disabled=e.e=n),r!==e.t&&h(t,`aria-busy`,e.t=r),e},{e:void 0,t:void 0}),t}}),null),m(N,n(s,{get when(){return r(()=>!!e.onContinue)()&&t().handler.sessionID},get children(){var n=mn();return n.$$click=()=>e.onContinue?.(t()),n}}),null),o(e=>{var n=t().id,r=t().state,a=`${jn(t())}: ${t().instruction}`,o=`aai-status ${u().tone}`;return n!==e.e&&h(i,`data-job`,e.e=n),r!==e.t&&h(i,`data-state`,e.t=r),a!==e.a&&h(i,`aria-label`,e.a=a),o!==e.o&&b(M,e.o=o),e},{e:void 0,t:void 0,a:void 0,o:void 0}),i})()}O([`click`,`keydown`,`input`]);var Y={rows:1e3,columns:50,cellChars:2e3};function Fn(e){let t=e.length>Y.columns,n=e.slice(0,Y.columns).map(e=>i(e)),r=[];function i(e){return typeof e==`string`&&e.length>Y.cellChars?(t=!0,e.slice(0,Y.cellChars)):e}return{add(e,a){return r.length>=Y.rows?(t=!0,!1):(r.push(n.map((t,n)=>i(n<e.length?e[n]:a))),!0)},done:()=>({columns:n,rows:r,truncated:t})}}function In(e){let t=[],n=[],r=``,i=!1,a=0,o=()=>{n.push(r),r=``,(n.length!==1||n[0]!==``)&&t.push(n),n=[]};for(;a<e.length&&t.length<=Y.rows+1;){let t=e[a];i?t===`"`?e[a+1]===`"`?(r+=`"`,a++):i=!1:r+=t:t===`"`&&r===``?i=!0:t===`,`?(n.push(r),r=``):t===`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,B as t,C as n,F as r,G as i,I as a,J as o,R as s,S as c,T as l,U as u,W as d,et as f,k as p,tt as m,x as h}from"./ui-CFB4wQfF.js";import{_ as g,b as _,p as v,v as y,y as b}from"./MediaImage-Ds_JUx3a.js";import{$ as x,A as S,M as C}from"./index-
|
|
1
|
+
import{A as e,B as t,C as n,F as r,G as i,I as a,J as o,R as s,S as c,T as l,U as u,W as d,et as f,k as p,tt as m,x as h}from"./ui-CFB4wQfF.js";import{_ as g,b as _,p as v,v as y,y as b}from"./MediaImage-Ds_JUx3a.js";import{$ as x,A as S,M as C}from"./index-LNMZCqgE.js";import w from"./Lightbox-Du56MXGX.js";var T={images:!1,links:!1,linkRel:`noopener noreferrer`,fontSize:14};function E(e){let t=e.timeoutMs??1e4,n=Math.max(1,e.concurrency??2),r=Math.max(1,e.cacheSize??64),i=e.setTimer??((e,t)=>setTimeout(e,t)),a=e.clearTimer??(e=>clearTimeout(e)),o=e.failureTtlMs??6e4,s=e.now??Date.now,c=new Map,l=new Map,u=[],d=[],f=1,p=(e,t,n)=>{for(c.delete(e),c.set(e,{result:t,expires:n});c.size>r;)c.delete(c.keys().next().value)},m=e=>{let t=c.get(e);if(t?.expires!==void 0&&s()>=t.expires)c.delete(e);else return t?.result},h=(e,t,{cacheable:n,replace:r})=>{let i=e.job;i&&(a(i.timer),e.job=void 0,r&&(e.worker.onmessage=null,e.worker.onerror=null,e.worker.terminate(),d.splice(d.indexOf(e),1)),n&&p(i.key,t,n===`briefly`?s()+o:void 0),l.delete(i.key),i.resolve(t),x())},g=(e,t)=>{if(typeof t.svg!=`string`)return{status:`error`,message:typeof t.error==`string`&&t.error?t.error:`the renderer returned no SVG`};let n=y(t.svg,e.palette);return _(n)?{status:`unsafe`}:{status:`ok`,svg:n}},b=()=>{let t={worker:e.spawn()};return t.worker.onmessage=e=>{let n=e.data,r=t.job;r&&n&&n.id===r.id&&h(t,g(r,n),{cacheable:!0,replace:!1})},t.worker.onerror=e=>h(t,{status:`error`,message:e?.message||`the diagram worker failed`},{cacheable:!1,replace:!0}),d.push(t),t};function x(){for(;u.length;){let e=d.find(e=>!e.job)??(d.length<n?b():void 0);if(!e)return;let r=u.shift(),a=f++,o=r.palette.font,s={...r,id:a,timer:void 0};e.job=s,s.timer=i(()=>h(e,{status:`error`,message:`timed out after ${t/1e3} s`},{cacheable:`briefly`,replace:!0}),t),e.worker.postMessage({id:a,source:r.source,options:o?{...T,fontFamily:o}:{...T}})}}return{render(e,t,n){let r=v(e,t),i=m(r);if(i)return p(r,i,c.get(r).expires),Promise.resolve(i);let a=l.get(r);if(a)return a;let o=new Promise(t=>u.push({key:r,source:e,palette:n,resolve:t}));return l.set(r,o),x(),o},cached(e,t){return m(v(e,t))}}}var D=p(`<p class=diagram-note>`),O=p(`<div class="code-block diagram-frame"><div class=code-head><span class=code-lang></span><button type=button class=code-btn>Diagram</button><button type=button class=code-btn>Source</button><button type=button class=code-btn>`),k=p(`<div class=diagram-block>`),A=p(`<button type=button class=code-btn>Download SVG`),j=p(`<pre class=code><code>`),M=p(`<p class=diagram-loading>Drawing diagram…`),N=p(`<button type=button class=diagram-open aria-label="Open the diagram full screen"title="Open full screen"><img alt=Diagram>`),P,F=()=>P??=E({spawn:()=>new Worker(new URL(`/assets/mermaid.worker-WDVRAh32.js`,``+import.meta.url),{type:`module`})}),I=matchMedia(`(prefers-color-scheme: dark)`),[L,R]=o(I.matches);I.addEventListener(`change`,e=>R(e.matches));var z=()=>x()===`system`?L()?`dark`:`light`:x(),B={bg:`--side`,fg:`--text`,muted:`--muted`,line:`--muted`,surface:`--raise`,"surface-alt":`--raise-2`,border:`--line-2`,accent:`--accent`,font:`--sans`,"font-mono":`--mono`};function V(){let e=getComputedStyle(document.documentElement),t={};for(let[n,r]of Object.entries(B)){let i=e.getPropertyValue(r).trim();i&&(t[n]=i)}return t}function H(e){let t=URL.createObjectURL(new Blob([e],{type:`image/svg+xml`})),n=document.createElement(`a`);n.href=t,n.download=`diagram.svg`,n.click(),setTimeout(()=>URL.revokeObjectURL(t),1e4)}function U(e){return[t(S,{get lang(){return e.lang},get text(){return e.text}}),(()=>{var t=D();return c(t,()=>e.note),t})()]}function W(p){let[h,_]=o(`diagram`),[v,y]=o(!1),[x,S]=o(),[T,E]=o(!1),[D,P]=o(!1),I=d(()=>b(p.text)),L=d(()=>(z(),V())),R,B;f(()=>clearTimeout(B)),m(()=>{let e=new IntersectionObserver(e=>y(e.some(e=>e.isIntersecting)),{rootMargin:`200px 0px`});e.observe(R),f(()=>e.disconnect())}),u(()=>{if(I()||!v())return;let e=p.text,t=L(),n=JSON.stringify(t),r=F().cached(e,n);if(r)return void S(r);let i=!0;f(()=>i=!1),F().render(e,n,t).then(e=>i&&S(e))});let W=()=>{let e=x();return e?.status===`ok`?e.svg:void 0};return(()=>{var o=k(),u=R;return typeof u==`function`?e(u,o):R=o,c(o,t(s,{get children(){return[t(r,{get when(){return I()},get children(){return t(U,{get lang(){return p.lang},get text(){return p.text},note:`Diagram too large to draw`})}}),t(r,{get when(){return n(()=>x()?.status===`error`)()&&x()},children:e=>t(U,{get lang(){return p.lang},get text(){return p.text},get note(){return`Couldn't draw this diagram: ${e().message}`}})}),t(r,{get when(){return x()?.status===`unsafe`},get children(){return t(U,{get lang(){return p.lang},get text(){return p.text},note:`Diagram not shown: the drawing had active content in it.`})}}),t(r,{when:!0,get children(){return[(()=>{var e=O(),n=e.firstChild,r=n.firstChild,o=r.nextSibling,s=o.nextSibling,u=s.nextSibling;return c(r,()=>p.lang||`mermaid`),o.$$click=()=>_(`diagram`),s.$$click=()=>_(`source`),u.$$click=async()=>{await C(p.text)&&(P(!0),clearTimeout(B),B=setTimeout(()=>P(!1),1500))},c(u,()=>D()?`Copied`:`Copy`),c(n,t(a,{get when(){return W()},children:e=>(()=>{var t=A();return t.$$click=()=>H(e()),t})()}),null),c(e,t(a,{get when(){return h()===`diagram`},get fallback(){return(()=>{var e=j(),t=e.firstChild;return c(t,()=>p.text),i(()=>l(e,`data-lang`,p.lang||void 0)),e})()},get children(){return t(a,{get when(){return W()},get fallback(){return M()},children:e=>(()=>{var t=N(),n=t.firstChild;return t.$$click=()=>E(!0),i(()=>l(n,`src`,g(e()))),t})()})}}),null),i(e=>{var t=h()===`diagram`,n=h()===`source`,r=D()?`Copied`:`Copy diagram source`;return t!==e.e&&l(o,`aria-pressed`,e.e=t),n!==e.t&&l(s,`aria-pressed`,e.t=n),r!==e.a&&l(u,`aria-label`,e.a=r),e},{e:void 0,t:void 0,a:void 0}),e})(),t(w,{get open(){return n(()=>!!T())()&&!!W()},get items(){return[{key:`diagram`,name:`Diagram`,mime:`image/svg+xml`,src:g(W()??``)}]},index:0,onClose:()=>E(!1)})]}})]}})),o})()}h([`click`]);export{W as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ArtifactPage-
|
|
2
|
-
import{B as e,C as t,F as n,G as r,I as i,J as a,N as o,R as s,S as c,T as l,U as u,W as d,Z as f,k as p,tt as m,u as h,x as g,y as _}from"./ui-CFB4wQfF.js";import{o as v,s as y}from"./toast-Cuu2K0hx.js";import{o as b,t as x}from"./artifacts-DU9uRgs1.js";import{t as S}from"./preload-helper-BLdHbfdN.js";import{nt as C,rt as w,t as T,tt as E}from"./index-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ArtifactPage-BKISN-Qj.js","assets/ui-CFB4wQfF.js","assets/artifacts-DU9uRgs1.js","assets/toast-Cuu2K0hx.js","assets/pane-layout-0RrLHGDr.js","assets/index-LNMZCqgE.js","assets/plural-Bspvoqfq.js","assets/MediaImage-Ds_JUx3a.js","assets/preload-helper-BLdHbfdN.js","assets/index-C3ci5UtY.css","assets/ArtifactWorkbench-d7R1o-rs.js","assets/source-BWlvaODa.js","assets/ArtifactWorkbench-9eTj1CeW.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{B as e,C as t,F as n,G as r,I as i,J as a,N as o,R as s,S as c,T as l,U as u,W as d,Z as f,k as p,tt as m,u as h,x as g,y as _}from"./ui-CFB4wQfF.js";import{o as v,s as y}from"./toast-Cuu2K0hx.js";import{o as b,t as x}from"./artifacts-DU9uRgs1.js";import{t as S}from"./preload-helper-BLdHbfdN.js";import{nt as C,rt as w,t as T,tt as E}from"./index-LNMZCqgE.js";import{a as D,c as O,i as k,n as A,o as j,r as M,s as N,t as P}from"./source-BWlvaODa.js";var F=p(`<p class="lib-intro muted">Everything your sessions made, across workspaces.`),I=p(`<div class=lib-filters><label><span>Workspace</span><select aria-label=Workspace><option value>All workspaces</option><option value=none>No workspace</option></select></label><label><span>Type</span><select aria-label=Type><option value>All types</option></select></label><label><span>Show</span><select aria-label=Show><option value>Artifacts</option><option value=preview>Previews`),L=p(`<p class=muted role=status>Loading artifacts…`),R=p(`<option>`),z=p(`<p class="lib-note err"role=alert> <button type=button class="btn small">Retry`),B=p(`<p class=lib-note>`),V=p(`<ul class=lib-list aria-label=Artifacts>`),H=p(`<p class="lib-note err"role=alert>`),U=p(`<button type=button class="btn lib-more">Load more`),W=p(`<button type=button class="btn small lib-keep"title="Keep it as a normal artifact (previews expire)">Keep`),G=p(`<p class=lib-desc>`),K=p(`<li class=lib-row><a class=lib-title></a><button type=button class="btn small lib-pane">Open in pane</button><span class=lib-meta><span class=lib-kind></span><span></span><span>`),q=f(()=>S(()=>import(`./ArtifactPage-BKISN-Qj.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]))),J={markdown:`Markdown`,code:`Code`,image:`Image`,table:`Table`,chart:`Chart`,dashboard:`Dashboard`,html:`HTML`,app:`App`,file:`File`};function Y(t){return e(i,{get when(){return t.rest[0]},keyed:!0,get fallback(){return e(Z,{})},children:t=>e(q,{id:t})})}var X=(e,t)=>e.workspace===t.workspace&&e.type===t.type&&e.origin===t.origin;function Z(){let f=d(()=>N(v().search),void 0,{equals:X}),[p,h]=a({status:`loading`}),g=k(P,h);u(()=>g.load(f()));let[_,b]=a(new Map);m(()=>void A().then(e=>b(new Map(e.map(e=>[e.id,e.title])))));let S=e=>y(`/artifacts${j({...f(),...e})}`),[C,w]=a(),E=async e=>w(await g.keep(e)),M=d(()=>{let e=new Set(_().keys()),t=p();if(t.status===`ready`)for(let n of t.items)n.workspaceID&&e.add(n.workspaceID);let n=f().workspace;return n&&n!==`none`&&e.add(n),[...e].map(e=>({id:e,label:O(e,_())}))}),W=()=>{let e=p();return e.status===`error`&&e.error.kind!==`error`};return e(T,{title:`Artifacts`,get children(){return[F(),e(i,{get when(){return!W()},get children(){var t=I(),n=t.firstChild,i=n.firstChild.nextSibling,a=i.firstChild,s=a.nextSibling,l=n.nextSibling,u=l.firstChild.nextSibling,d=u.firstChild,p=l.nextSibling.firstChild.nextSibling,m=p.firstChild,h=m.nextSibling;return i.addEventListener(`change`,e=>S({workspace:e.currentTarget.value})),c(i,e(o,{get each(){return M()},children:e=>(()=>{var t=R();return c(t,()=>e.label),r(()=>t.selected=f().workspace===e.id),r(()=>t.value=e.id),t})()}),null),u.addEventListener(`change`,e=>S({type:e.currentTarget.value})),c(u,e(o,{get each(){return[...x]},children:e=>(()=>{var t=R();return t.value=e,c(t,()=>J[e]),r(()=>t.selected=f().type===e),t})()}),null),p.addEventListener(`change`,e=>S({origin:e.currentTarget.value===`preview`?`preview`:void 0})),r(e=>{var t=f().workspace===``,n=f().workspace===`none`,r=f().type===``,i=!f().origin,o=f().origin===`preview`;return t!==e.e&&(a.selected=e.e=t),n!==e.t&&(s.selected=e.t=n),r!==e.a&&(d.selected=e.a=r),i!==e.o&&(m.selected=e.o=i),o!==e.i&&(h.selected=e.i=o),e},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),t}}),e(s,{get children(){return[e(n,{get when(){return p().status===`loading`},get children(){return L()}}),e(n,{get when(){return t(()=>p().status===`error`)()&&p()},children:t=>{let n=()=>t().error;return e(i,{get when(){return n().kind===`error`},get fallback(){return(()=>{var e=B();return c(e,()=>n().text),e})()},get children(){var e=z(),t=e.firstChild,r=t.nextSibling;return c(e,()=>n().text,t),r.$$click=()=>g.reload(),e}})}}),e(n,{get when(){return t(()=>p().status===`ready`)()&&p()},children:t=>{let n=()=>t();return[e(i,{get when(){return n().items.length},get fallback(){return(()=>{var e=B();return c(e,()=>D(f(),n().more)),e})()},get children(){var t=V();return c(t,e(o,{get each(){return n().items},children:t=>e($,{item:t,get names(){return _()},onKeep:E})})),t}}),e(i,{get when(){return C()},get children(){var e=H();return c(e,C),e}}),e(i,{get when(){return n().moreError},get children(){var e=H();return c(e,()=>n().moreError),e}}),e(i,{get when(){return n().more},get children(){var e=U();return e.$$click=()=>g.more(),r(t=>{var r=n().loadingMore,i=n().loadingMore;return r!==t.e&&(e.disabled=t.e=r),i!==t.t&&l(e,`aria-busy`,t.t=i),t},{e:void 0,t:void 0}),e}})]}})]}})]}})}function Q(e,t){return e.workspaceID?O(e.workspaceID,t):`Private`}function $(t){let n=()=>t.item;return(()=>{var a=K(),o=a.firstChild,s=o.nextSibling,u=s.nextSibling,d=u.firstChild,f=d.nextSibling,p=f.nextSibling;return _(a,`dragend`,E),a.addEventListener(`dragstart`,e=>C(e,{target:{artifactID:n().id},label:n().title||`Untitled`})),c(o,()=>n().title||`Untitled`),s.$$click=()=>b(n().id),c(a,e(i,{get when(){return n().origin===`preview`},get children(){var e=W();return e.$$click=()=>t.onKeep(n()),r(()=>l(e,`aria-label`,`Keep ${n().title||`Untitled`} as an artifact`)),e}}),u),c(d,()=>J[n().kind]),c(f,()=>Q(n(),t.names)),c(p,()=>h(n().updatedAt)),c(a,e(i,{get when(){return n().description},get children(){var e=G();return c(e,()=>n().description),e}}),null),r(e=>{var t=n().id,r=!w(),i=M(n().id),c=`Open ${n().title||`Untitled`} in a pane`;return t!==e.e&&l(a,`data-artifact`,e.e=t),r!==e.t&&l(a,`draggable`,e.t=r),i!==e.a&&l(o,`href`,e.a=i),c!==e.o&&l(s,`aria-label`,e.o=c),e},{e:void 0,t:void 0,a:void 0,o:void 0}),a})()}g([`click`]);export{Y as default};
|