@huynle/hub 0.8.3 → 0.8.4

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 (32) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +1 -1
  3. package/packages/claude-code/package.json +1 -1
  4. package/packages/cli/dist/hub-cli.js +6 -6
  5. package/packages/cli/package.json +1 -1
  6. package/packages/codex/package.json +1 -1
  7. package/packages/node/package.json +1 -1
  8. package/packages/preset/package.json +1 -1
  9. package/packages/protocol/package.json +1 -1
  10. package/packages/protocol/src/index.ts +7 -2
  11. package/packages/runtime-openshell/package.json +1 -1
  12. package/packages/runtime-sdk/package.json +1 -1
  13. package/packages/sdk/package.json +1 -1
  14. package/packages/spoke-sdk/package.json +1 -1
  15. package/src/central/registry.ts +93 -22
  16. package/src/index.ts +28 -0
  17. package/src/spoke/spoke.ts +150 -10
  18. package/src/status.ts +70 -14
  19. package/web/dist/assets/{ArtifactPage-CSotAWob.js → ArtifactPage-Cb1DcrQf.js} +1 -1
  20. package/web/dist/assets/{ArtifactPane-DPHjiWce.js → ArtifactPane-XTnwXl-Y.js} +1 -1
  21. package/web/dist/assets/{ArtifactWorkbench-CkmWnP6L.js → ArtifactWorkbench-C37tZZ3e.js} +1 -1
  22. package/web/dist/assets/{Library-DTLEyekn.js → Library-CZSSHvOJ.js} +2 -2
  23. package/web/dist/assets/{ProfilesDestination-GriuOpiZ.js → ProfilesDestination-dZa3vioh.js} +1 -1
  24. package/web/dist/assets/{TeamsPage-C-5lYeeM.js → TeamsPage-DJt-Kk84.js} +1 -1
  25. package/web/dist/assets/{Watchtower-DOlPsiIy.js → Watchtower-BXaUaXO1.js} +2 -2
  26. package/web/dist/assets/{index-C5OmwA1y.css → index-DVSkeAvn.css} +1 -1
  27. package/web/dist/assets/{index-6mdQ7eUY.js → index-DifgVuKS.js} +22 -22
  28. package/web/dist/assets/{live-CDWcyavI.js → live-D-RZbeUi.js} +1 -1
  29. package/web/dist/assets/{renderer2d-CNFdTDTr.js → renderer2d-DILxLFEq.js} +1 -1
  30. package/web/dist/assets/{renderer3d-C45jPvYX.js → renderer3d-PvN9Qbt2.js} +1 -1
  31. package/web/dist/assets/{safe-area-sA9a8vYJ.js → safe-area-BS6ii3M7.js} +1 -1
  32. package/web/dist/index.html +2 -2
@@ -141,6 +141,12 @@ export interface SpokeHost {
141
141
  * were already running when this process started, or while its event stream was down.
142
142
  */
143
143
  activity?(directories: readonly string[]): Promise<{ readonly active: readonly string[]; readonly jobs: ReadonlyArray<JobInfo & { readonly sessionID: string }> }>
144
+ /**
145
+ * What OpenCode waits for in each of the sessions, from this process's own server: pending forms (FormInfo, as in
146
+ * form.created) and permission requests (as in permission.asked). A session it could not read is left out.
147
+ * Absent, or empty when the server cannot be reached: only what this process saw asked is re-announced.
148
+ */
149
+ pending?(sessionIDs: readonly string[]): Promise<ReadonlyArray<PendingAsks>>
144
150
  /**
145
151
  * Recent root sessions with their workspace: those in the history window (`days`, at most `max`), plus `include`
146
152
  * (always listed: open, running, ...). The background service lists every session; a foreground `opencode serve`
@@ -177,6 +183,13 @@ export interface SpokeHost {
177
183
  revertCommit?(sessionID: string): Promise<unknown>
178
184
  }
179
185
 
186
+ /** A session's pending forms and permission requests as OpenCode lists them (raw, see SpokeHost.pending). */
187
+ export interface PendingAsks {
188
+ readonly sessionID: string
189
+ readonly forms: readonly unknown[]
190
+ readonly permissions: readonly unknown[]
191
+ }
192
+
180
193
  /** A form reply for OpenCode: an answer, or a cancel. */
181
194
  export type FormAction =
182
195
  | { readonly sessionID: string; readonly formID: string; readonly answer: FormAnswer }
@@ -205,6 +218,8 @@ export interface SpokeOptions {
205
218
  readonly forkNoteTimeoutMs?: number
206
219
  readonly snapshotIntervalMs?: number
207
220
  readonly seedIntervalMs?: number
221
+ /** Longest the own server may take to list a seed's pending forms and permissions (default 5 s). */
222
+ readonly pendingTimeoutMs?: number
208
223
  /** Delay before re-listing the service's sessions after a session event (default 2 s). */
209
224
  readonly seedDebounceMs?: number
210
225
  /** Longest one session listing may take before it is abandoned and later listings run (default 60 s). */
@@ -389,6 +404,15 @@ export class Spoke {
389
404
  private started = false
390
405
  /** A seedActivity call is in flight. */
391
406
  private seeding = false
407
+ /**
408
+ * Pending permissions and forms (`per <id>` / `frm <id>`) with the event that asked them, as forwarded: the hub
409
+ * keeps them only as long as this connection, so they are announced again after a reconnect (see reannounce).
410
+ * `seq` orders them against a pending listing (one asked while OpenCode was being asked is never closed by it).
411
+ */
412
+ private readonly asks = new Map<string, { sessionID: string; event: { type: string; data: Record<string, unknown> }; seq: number }>()
413
+ private askSeq = 0
414
+ /** Asks seen answered or cancelled (an ID never comes back): a listing taken before the reply cannot revive them. */
415
+ private readonly closedAsks = new Set<string>()
392
416
  /** Sessions shown by OpenCode TUIs (voice.presence). */
393
417
  private readonly presenceBook = new PresenceBook()
394
418
  /** Form replies waiting for a TUI to carry them out (when the plugin cannot reach its own server). */
@@ -907,6 +931,9 @@ export class Spoke {
907
931
  onWelcome: () => {
908
932
  this.sendSnapshot()
909
933
  this.sendTerminals(true)
934
+ // A new connection: the hub dropped what was pending with the old one (or restarted). What this process
935
+ // remembers goes out again at once; the seed then asks OpenCode what it still waits for.
936
+ this.reannounce()
910
937
  void this.seedActivity()
911
938
  },
912
939
  onState: (state, error) => {
@@ -1784,6 +1811,7 @@ export class Spoke {
1784
1811
  const title = (event.data as Record<string, unknown>).title
1785
1812
  if (typeof title === "string") for (const waiter of this.renameWaiters.get(sessionID) ?? []) waiter(title)
1786
1813
  }
1814
+ this.trackAsk(event)
1787
1815
  if (this.tracker.observe(event, Date.now())) this.scheduleSnapshot()
1788
1816
  if (REVERT_EVENTS.has(event.type) && typeof sessionID === "string") void this.observeRevert(event, sessionID)
1789
1817
  if (typeof sessionID === "string") this.profiles.settle(sessionID) // a turn boundary makes a staged profile effective
@@ -1791,21 +1819,123 @@ export class Spoke {
1791
1819
  this.scheduleSeed()
1792
1820
  }
1793
1821
  void this.fetchInfo()
1794
- if (this.connection?.state === "connected" && (FORWARDED_EVENTS.has(event.type) || COMPACTED_EVENTS.has(event.type))) {
1795
- // Activity events go out compact: tool inputs become a short summary, outputs are dropped; job exits
1796
- // get their session from the job.
1797
- const compact = this.withOrigin(compactActivity({ type: event.type, data: (event.data ?? {}) as Record<string, unknown> }, (id) => this.tracker.jobSession(id)))
1798
- if (compact && shouldForward(this.config, this.tracker, compact)) {
1799
- this.announce(compact)
1800
- this.connection.send({ t: "event", event: compact })
1801
- if (compact.type === "session.execution.failed" && typeof sessionID === "string" && !this.announced.has(sessionID)) this.unheardFailures.add(sessionID)
1802
- }
1803
- }
1822
+ this.forward(event)
1804
1823
  } catch (cause) {
1805
1824
  console.error("[hub] event handling failed", cause)
1806
1825
  }
1807
1826
  }
1808
1827
 
1828
+ /** Sends an OpenCode event to the hub (compact), when connected and the hub may see its session. */
1829
+ private forward(event: EventLike): void {
1830
+ if (this.connection?.state !== "connected" || (!FORWARDED_EVENTS.has(event.type) && !COMPACTED_EVENTS.has(event.type))) return
1831
+ // Activity events go out compact: tool inputs become a short summary, outputs are dropped; job exits
1832
+ // get their session from the job.
1833
+ const compact = this.withOrigin(compactActivity({ type: event.type, data: (event.data ?? {}) as Record<string, unknown> }, (id) => this.tracker.jobSession(id)))
1834
+ if (!compact || !shouldForward(this.config, this.tracker, compact)) return
1835
+ this.announce(compact)
1836
+ this.connection.send({ t: "event", event: compact })
1837
+ const sessionID = (event.data as Record<string, unknown> | undefined)?.sessionID
1838
+ if (compact.type === "session.execution.failed" && typeof sessionID === "string" && !this.announced.has(sessionID)) this.unheardFailures.add(sessionID)
1839
+ }
1840
+
1841
+ /** Keeps `asks` current: a permission or form asked, replied, cancelled, or its session deleted. */
1842
+ private trackAsk(event: EventLike): void {
1843
+ const data = (event.data ?? {}) as Record<string, any>
1844
+ if (event.type === "permission.asked" && typeof data.id === "string" && typeof data.sessionID === "string") {
1845
+ this.rememberAsk(`per ${data.id}`, data.sessionID, event)
1846
+ } else if (event.type === "form.created" && typeof data.form?.id === "string" && typeof data.form?.sessionID === "string") {
1847
+ this.rememberAsk(`frm ${data.form.id}`, data.form.sessionID, event)
1848
+ } else if (event.type === "permission.replied" && typeof data.requestID === "string") this.closeAsk(`per ${data.requestID}`)
1849
+ else if ((event.type === "form.replied" || event.type === "form.cancelled") && typeof data.id === "string") this.closeAsk(`frm ${data.id}`)
1850
+ else if (event.type === "session.deleted" && typeof data.sessionID === "string") {
1851
+ for (const [key, ask] of this.asks) if (ask.sessionID === data.sessionID) this.asks.delete(key)
1852
+ }
1853
+ }
1854
+
1855
+ private closeAsk(key: string): void {
1856
+ this.asks.delete(key)
1857
+ this.closedAsks.add(key)
1858
+ if (this.closedAsks.size > ASKS_CLOSED_KEPT) this.closedAsks.delete(this.closedAsks.values().next().value!)
1859
+ }
1860
+
1861
+ private rememberAsk(key: string, sessionID: string, event: EventLike): void {
1862
+ if (this.closedAsks.has(key)) return
1863
+ this.asks.delete(key)
1864
+ this.asks.set(key, { sessionID, event: { type: event.type, data: (event.data ?? {}) as Record<string, unknown> }, seq: ++this.askSeq })
1865
+ if (this.asks.size > ASKS_KEPT) this.asks.delete(this.asks.keys().next().value!)
1866
+ }
1867
+
1868
+ /**
1869
+ * Announces every pending permission and form again (after a reconnect: the hub dropped them with the old
1870
+ * connection). A hub without "pendingReplay" would notify a re-sent permission again: it gets the forms only.
1871
+ */
1872
+ private reannounce(): void {
1873
+ const permissions = this.hubSupports("pendingReplay")
1874
+ for (const ask of [...this.asks.values()]) if (permissions || ask.event.type !== "permission.asked") this.forward(ask.event)
1875
+ }
1876
+
1877
+ /**
1878
+ * Asks OpenCode what the sessions wait for (the active ones, and those with something pending here): forms and
1879
+ * permissions this process never saw asked (it started afterwards, or its stream was down) are announced; those
1880
+ * it remembers that OpenCode no longer lists (answered while the stream was down) are closed on the hub.
1881
+ */
1882
+ private async reconcileAsks(active: readonly string[]): Promise<void> {
1883
+ const pending = this.host.pending
1884
+ if (!pending) return
1885
+ // Sessions with something remembered first: a reply missed while the stream was down is only seen by asking.
1886
+ const ids = [...new Set([...[...this.asks.values()].map((a) => a.sessionID).reverse(), ...active])].slice(0, PENDING_SESSIONS_MAX)
1887
+ if (!ids.length) return
1888
+ const asked = this.askSeq
1889
+ const limit = this.options.pendingTimeoutMs ?? PENDING_TIMEOUT_MS
1890
+ let timer: ReturnType<typeof setTimeout> | undefined
1891
+ let lists: ReadonlyArray<PendingAsks>
1892
+ try {
1893
+ const listed = Promise.resolve(pending.call(this.host, ids))
1894
+ listed.catch(() => {}) // a listing that fails after the timeout is not an unhandled rejection
1895
+ const timeout = new Promise<never>((_, reject) => (timer = setTimeout(() => reject(new Error(`no answer within ${limit} ms`)), limit)))
1896
+ lists = await Promise.race([listed, timeout])
1897
+ } catch (cause) {
1898
+ console.error("[hub] could not read pending questions and permissions", errorText(cause))
1899
+ return
1900
+ } finally {
1901
+ clearTimeout(timer)
1902
+ }
1903
+ for (const list of lists) {
1904
+ if (!ids.includes(list.sessionID)) continue
1905
+ const listed = new Set<string>()
1906
+ const found: EventLike[] = []
1907
+ for (const form of Array.isArray(list.forms) ? list.forms : []) {
1908
+ const f = form as Record<string, unknown> | null
1909
+ if (typeof f?.id !== "string" || f.sessionID !== list.sessionID) continue
1910
+ listed.add(`frm ${f.id}`)
1911
+ if (!this.asks.has(`frm ${f.id}`) && !this.closedAsks.has(`frm ${f.id}`)) found.push({ type: "form.created", data: { form: f } })
1912
+ }
1913
+ for (const request of Array.isArray(list.permissions) ? list.permissions : []) {
1914
+ const r = request as Record<string, unknown> | null
1915
+ if (typeof r?.id !== "string" || r.sessionID !== list.sessionID) continue
1916
+ listed.add(`per ${r.id}`)
1917
+ if (!this.asks.has(`per ${r.id}`) && !this.closedAsks.has(`per ${r.id}`)) found.push({ type: "permission.asked", data: r })
1918
+ }
1919
+ const gone: EventLike[] = []
1920
+ for (const [key, ask] of this.asks) {
1921
+ if (ask.sessionID !== list.sessionID || ask.seq > asked || listed.has(key)) continue
1922
+ const id = key.slice(4)
1923
+ // unlisted: the hub drops only this process's hold on it (another process may still hold it).
1924
+ gone.push(
1925
+ key.startsWith("per ")
1926
+ ? { type: "permission.replied", data: { sessionID: ask.sessionID, requestID: id, unlisted: true } }
1927
+ : { type: "form.cancelled", data: { sessionID: ask.sessionID, id, unlisted: true } },
1928
+ )
1929
+ }
1930
+ for (const event of [...found, ...gone]) {
1931
+ this.trackAsk(event)
1932
+ this.tasks.observe(event, Date.now())
1933
+ if (this.tracker.observe(event, Date.now())) this.scheduleSnapshot()
1934
+ this.forward(event)
1935
+ }
1936
+ }
1937
+ }
1938
+
1809
1939
  /**
1810
1940
  * Adds who put the item in the inbox (user or hub) to session.inbox.delivered, for hubs that route messages
1811
1941
  * (they reset reply-chain hops on a user's turn); when unknown, the event goes out unchanged.
@@ -1878,6 +2008,7 @@ export class Spoke {
1878
2008
  const event = { type: "session.seed", data: { sessionID: id, status, jobs, ...(error ? { error } : {}) } }
1879
2009
  if (this.connection?.state === "connected" && shouldForward(this.config, this.tracker, event)) this.connection.send({ t: "event", event })
1880
2010
  }
2011
+ await this.reconcileAsks([...active])
1881
2012
  void this.fetchInfo()
1882
2013
  this.scheduleSnapshot()
1883
2014
  } catch (cause) {
@@ -2030,6 +2161,15 @@ const LISTING_TIMEOUT_MS = 60_000
2030
2161
  /** Directories whose shells are listed when seeding. */
2031
2162
  const SEED_DIRECTORIES = 20
2032
2163
 
2164
+ /** Pending permissions and forms remembered to announce again (oldest dropped). */
2165
+ const ASKS_KEPT = 200
2166
+ /** Answered or cancelled asks remembered (oldest dropped). */
2167
+ const ASKS_CLOSED_KEPT = 1000
2168
+ /** Sessions whose pending forms and permissions are read from OpenCode in one seed. */
2169
+ const PENDING_SESSIONS_MAX = 50
2170
+ /** Longest the own server may take to list them (SpokeOptions.pendingTimeoutMs). */
2171
+ const PENDING_TIMEOUT_MS = 5000
2172
+
2033
2173
  /** Keeps the terminals frame within the protocol's limits. */
2034
2174
  function limitWorkspaces(workspaces: readonly HerdrWorkspace[]): HerdrWorkspace[] {
2035
2175
  return workspaces.slice(0, 200).map((w) => ({ id: w.id, label: w.label, directories: w.directories.slice(0, 20) }))
package/src/status.ts CHANGED
@@ -64,6 +64,8 @@ export interface FormFieldSpec {
64
64
 
65
65
  export const FORM_MAX_FIELDS = 20
66
66
  export const FORM_MAX_OPTIONS = 50
67
+ /** Largest blocker kept and shown (JSON characters): the board, the catalog and the hub's kept copy carry it. */
68
+ export const BLOCKER_MAX_BYTES = 64_000
67
69
  const FORM_TEXT_MAX = 2000
68
70
  const FORM_LABEL_MAX = 300
69
71
  const FIELD_TYPES = new Set<FormFieldSpec["type"]>(["string", "number", "integer", "boolean", "multiselect", "external"])
@@ -98,6 +100,22 @@ const SOURCE_ID_MAX = 200
98
100
  export const BLOCKER_MAX_RESOURCES = 10
99
101
  const BLOCKER_RESOURCE_MAX = 500
100
102
 
103
+ /** Longest blocker ID (a longer one is no usable request) and permission summary kept. */
104
+ export const BLOCKER_ID_MAX = 200
105
+ const BLOCKER_SUMMARY_MAX = 2000
106
+
107
+ /** The strings of `list` joined with ", ", at most `max` characters (never joins more than it keeps). */
108
+ function joinBounded(list: unknown, max: number): string {
109
+ if (!Array.isArray(list)) return ""
110
+ let out = ""
111
+ for (const v of list) {
112
+ if (typeof v !== "string") continue
113
+ out = out ? `${out}, ${v}` : v
114
+ if (out.length >= max) return out.slice(0, max)
115
+ }
116
+ return out
117
+ }
118
+
101
119
  /** Strings of `list`, bounded; `cut` is set when anything was dropped or shortened. */
102
120
  function boundedStrings(list: unknown, maxItems: number, maxLength: number): { items: string[]; cut: boolean } {
103
121
  if (!Array.isArray(list)) return { items: [], cut: list !== undefined }
@@ -134,7 +152,7 @@ function permissionBlocker(data: Record<string, any>): Blocker {
134
152
  return {
135
153
  kind: "permission",
136
154
  id: data.id,
137
- summary: [data.action, (data.resources ?? []).join(", ")].filter(Boolean).join(": "),
155
+ summary: [action, joinBounded(data.resources, BLOCKER_SUMMARY_MAX)].filter(Boolean).join(": "),
138
156
  ...(action ? { action } : {}),
139
157
  ...(resources.length ? { resources } : {}),
140
158
  }
@@ -169,29 +187,55 @@ export function formFieldSpec(raw: any): FormFieldSpec | undefined {
169
187
  const d = raw.default
170
188
  if (typeof d === "boolean" || num(d) !== undefined) out.default = d
171
189
  else if (typeof d === "string") out.default = d.slice(0, FORM_TEXT_MAX)
172
- else if (Array.isArray(d)) out.default = d.filter((x: unknown) => typeof x === "string").slice(0, FORM_MAX_OPTIONS)
190
+ else if (Array.isArray(d)) out.default = d.filter((x: unknown) => typeof x === "string").slice(0, FORM_MAX_OPTIONS).map((x: string) => x.slice(0, FORM_LABEL_MAX))
173
191
  if (Array.isArray(raw.when)) {
174
192
  const when = raw.when
175
193
  .filter((w: any) => typeof w?.key === "string" && (w.op === "eq" || w.op === "neq") && ["string", "number", "boolean"].includes(typeof w.value))
176
194
  .slice(0, 10)
177
- .map((w: any) => ({ key: w.key, op: w.op, value: w.value }))
195
+ .map((w: any) => ({ key: w.key.slice(0, FORM_LABEL_MAX), op: w.op, value: typeof w.value === "string" ? w.value.slice(0, FORM_LABEL_MAX) : w.value }))
178
196
  if (when.length) out.when = when
179
197
  }
180
198
  return out as unknown as FormFieldSpec
181
199
  }
182
200
 
183
- /** A form.created event's form as a blocker. */
201
+ /**
202
+ * A form.created event's form as a blocker, at most BLOCKER_MAX_BYTES: over it the descriptions go, then the fields
203
+ * (the card then asks to answer in the terminal).
204
+ */
184
205
  function formBlocker(form: any): Blocker {
185
- const fields = Array.isArray(form.fields) ? form.fields.map(formFieldSpec).filter(Boolean).slice(0, FORM_MAX_FIELDS) : []
186
- return {
187
- kind: "form",
206
+ const fields: FormFieldSpec[] = []
207
+ for (const raw of Array.isArray(form.fields) ? form.fields : []) {
208
+ if (fields.length >= FORM_MAX_FIELDS) break
209
+ const field = formFieldSpec(raw)
210
+ if (field) fields.push(field)
211
+ }
212
+ const head = {
213
+ kind: "form" as const,
188
214
  id: form.id,
189
215
  summary: typeof form.title === "string" && form.title ? form.title.slice(0, FORM_LABEL_MAX) : "question",
190
216
  ...(form.metadata?.kind === "question" ? { question: true as const } : {}),
191
- ...(fields.length ? { fields } : {}),
192
217
  }
218
+ const full: Blocker = { ...head, ...(fields.length ? { fields } : {}) }
219
+ if (JSON.stringify(full).length <= BLOCKER_MAX_BYTES) return full
220
+ const plain: Blocker = { ...head, fields: fields.map(withoutDescriptions) }
221
+ return JSON.stringify(plain).length <= BLOCKER_MAX_BYTES ? plain : head
222
+ }
223
+
224
+ function withoutDescriptions(field: FormFieldSpec): FormFieldSpec {
225
+ const { description: _, ...rest } = field
226
+ return rest.options ? { ...rest, options: rest.options.map(({ description: _d, ...option }) => option) } : rest
193
227
  }
194
228
 
229
+ /** The blocker a permission.asked or form.created event shows (bounded); undefined for other events. */
230
+ export function askBlocker(event: EventLike): Blocker | undefined {
231
+ const data = (event.data ?? {}) as Record<string, any>
232
+ if (event.type === "permission.asked" && usableID(data.id)) return permissionBlocker(data)
233
+ if (event.type === "form.created" && usableID(data.form?.id)) return formBlocker(data.form)
234
+ return undefined
235
+ }
236
+
237
+ const usableID = (id: unknown): id is string => typeof id === "string" && id.length > 0 && id.length <= BLOCKER_ID_MAX
238
+
195
239
  /** A model request OpenCode retries: the attempt, why, when the next one runs (epoch ms) and the error's type. */
196
240
  export interface RetryInfo {
197
241
  readonly attempt?: number
@@ -336,18 +380,22 @@ export class StatusBoard {
336
380
  entry.retry = undefined
337
381
  return true
338
382
  }
339
- case "permission.asked":
340
- return this.update(data.sessionID, (entry) => {
383
+ case "permission.asked": {
384
+ const blocker = askBlocker(event)
385
+ return !!blocker && this.update(data.sessionID, (entry) => {
341
386
  if (entry.blockers.some((b) => b.id === data.id)) return
342
- entry.blockers.push(permissionBlocker(data))
387
+ entry.blockers.push(blocker)
343
388
  })
389
+ }
344
390
  case "permission.replied":
345
391
  return this.unblock(data.sessionID, data.requestID)
346
- case "form.created":
347
- return this.update(data.form?.sessionID, (entry) => {
392
+ case "form.created": {
393
+ const blocker = askBlocker(event)
394
+ return !!blocker && this.update(data.form?.sessionID, (entry) => {
348
395
  if (entry.blockers.some((b) => b.id === data.form.id)) return
349
- entry.blockers.push(formBlocker(data.form))
396
+ entry.blockers.push(blocker)
350
397
  })
398
+ }
351
399
  case "form.replied":
352
400
  case "form.cancelled":
353
401
  return this.unblock(data.sessionID, data.id)
@@ -389,6 +437,14 @@ export class StatusBoard {
389
437
  }
390
438
  }
391
439
 
440
+ /** Puts a pending blocker (askBlocker) back on a session of the tree. True when it was missing. */
441
+ restoreBlocker(sessionID: string, blocker: Blocker): boolean {
442
+ const entry = this.sessions.get(sessionID)
443
+ if (!entry || entry.blockers.some((b) => b.id === blocker.id)) return false
444
+ entry.blockers.push(structuredClone(blocker))
445
+ return true
446
+ }
447
+
392
448
  get(id: string): SessionStatus | undefined {
393
449
  const entry = this.sessions.get(id)
394
450
  return entry && view(entry)
@@ -1 +1 @@
1
- import{At as e,Et as t,ft as n,i as r,r as i,yt as a}from"./ui-Qo2Pd9-O.js";import{L as o,R as s,z as c}from"./index-6mdQ7eUY.js";import{t as l}from"./ArtifactWorkbench-CkmWnP6L.js";var u=a(`<div class="feature-page av-page">`),d=a(`<a class="icon-btn av-back"href=/artifacts aria-label="All artifacts"title="All artifacts">`);function f(a){return(()=>{var f=u();return n(f,e(l,{get id(){return a.id},layout:`page`,get lead(){return[e(t,{get when(){return o()},get children(){return e(r,{icon:`menu`,label:`Open sidebar`,onClick:s})}}),(()=>{var t=d();return n(t,e(i,{name:`back`})),t})()]},get actions(){return e(r,{class:`av-wide`,icon:`split`,label:`Open in pane`,onClick:()=>c(a.id)})}})),f})()}export{f as default};
1
+ import{At as e,Et as t,ft as n,i as r,r as i,yt as a}from"./ui-Qo2Pd9-O.js";import{L as o,R as s,z as c}from"./index-DifgVuKS.js";import{t as l}from"./ArtifactWorkbench-C37tZZ3e.js";var u=a(`<div class="feature-page av-page">`),d=a(`<a class="icon-btn av-back"href=/artifacts aria-label="All artifacts"title="All artifacts">`);function f(a){return(()=>{var f=u();return n(f,e(l,{get id(){return a.id},layout:`page`,get lead(){return[e(t,{get when(){return o()},get children(){return e(r,{icon:`menu`,label:`Open sidebar`,onClick:s})}}),(()=>{var t=d();return n(t,e(i,{name:`back`})),t})()]},get actions(){return e(r,{class:`av-wide`,icon:`split`,label:`Open in pane`,onClick:()=>c(a.id)})}})),f})()}export{f as default};
@@ -1 +1 @@
1
- import{At as e,Pt as t,ft as n,ht as r,r as i,yt as a}from"./ui-Qo2Pd9-O.js";import{t as o}from"./ArtifactWorkbench-CkmWnP6L.js";var s=a(`<a class=icon-btn aria-label="Full page"title="Open the artifact's full page">`);function c(a){return e(o,{get id(){return a.artifactID},layout:`pane`,onArtifact:e=>a.onTitle?.(e.title||`Untitled`),get actions(){return(()=>{var o=s();return n(o,e(i,{name:`expand`})),t(()=>r(o,`href`,`/artifacts/${encodeURIComponent(a.artifactID)}`)),o})()},get trailing(){return a.paneTools}})}export{c as ArtifactPane};
1
+ import{At as e,Pt as t,ft as n,ht as r,r as i,yt as a}from"./ui-Qo2Pd9-O.js";import{t as o}from"./ArtifactWorkbench-C37tZZ3e.js";var s=a(`<a class=icon-btn aria-label="Full page"title="Open the artifact's full page">`);function c(a){return e(o,{get id(){return a.artifactID},layout:`pane`,onArtifact:e=>a.onTitle?.(e.title||`Untitled`),get actions(){return(()=>{var o=s();return n(o,e(i,{name:`expand`})),t(()=>r(o,`href`,`/artifacts/${encodeURIComponent(a.artifactID)}`)),o})()},get trailing(){return a.paneTools}})}export{c as ArtifactPane};
@@ -1,4 +1,4 @@
1
- import{$ as e,At as t,Ct as n,Et as r,G as i,Ht as a,Lt as o,Mt as s,Nt as c,Ot as l,Pt as u,Tt as d,Ut as f,Vt as p,Wt as m,a as h,bt as g,dt as _,ft as v,g as y,gt as b,ht as x,i as S,it as C,lt as w,nt as T,pt as E,q as D,r as O,st as k,tt as A,u as j,ut as M,vt as N,wt as P,yt as F}from"./ui-Qo2Pd9-O.js";import{A as I,O as L,P as R,U as z,V as ee,k as te,z as ne}from"./index-6mdQ7eUY.js";import{c as re,d as ie,f as ae,i as oe,l as se,n as ce,r as le,t as ue,u as de}from"./source-BFLJQ43_.js";var fe=`ai-actions`,B=16,pe=[`ask`,`propose-edit`,`run-action`],me=[`queued`,`running`,`succeeded`,`failed`,`cancelled`],he=[`starting`,`waiting`,`offline`,`ready`,`ended`,`failed`],ge=/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/,V=e=>typeof e==`object`&&!!e&&!Array.isArray(e),H=e=>typeof e==`string`&&e.length>0,U=e=>typeof e==`number`&&Number.isFinite(e),_e=(e,t)=>typeof t==`string`&&e.includes(t),ve=e=>e.replace(/\/+$/,``).split(`/`).pop()||e;function ye(e){if(V(e)&&_e(he,e.status)){if(e.kind===`session`&&H(e.address))return e;if(e.kind===`launch`&&H(e.machine)&&H(e.repo))return{harness:``,mode:`checkout`,...e}}}function be(e){if(!V(e)||!_e([`pending`,`applied`,`conflict`],e.state)||!Array.isArray(e.files))return;let t=e.files.filter(e=>V(e)&&H(e.mediaType)&&U(e.bytes)&&H(e.hash));return{state:e.state,files:t,...Array.isArray(e.keep)?{keep:e.keep.filter(H)}:{},...H(e.entry)?{entry:e.entry}:{},...H(e.appliedRevisionID)?{appliedRevisionID:e.appliedRevisionID}:{}}}function xe(e){if(!V(e)||!H(e.id)||!H(e.artifactID)||!H(e.baseRevisionID)||!U(e.revision)||!_e(me,e.state)||!_e(pe,e.kind)||typeof e.instruction!=`string`||!H(e.by)||!U(e.createdAt)||!U(e.updatedAt))return;let t=ye(e.handler);if(!t)return;let n=be(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 Se(e){let t=V(e)?e:{};return{items:Array.isArray(t.items)?t.items.flatMap(e=>xe(e)??[]):[],...H(t.cursor)?{cursor:t.cursor}:{}}}function Ce(e){let t=e?.[fe];return t?t.split(`,`).map(e=>e.trim()).filter(D).slice(0,B):[]}var W=e=>e.state===`queued`||e.state===`running`;function G(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} · ${ve(e.repo)}`}function we(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: ${G(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 ${G(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 ${G(r,t)}`);case`ready`:return e.state===`running`?i(`running`,`Working: ${G(r,t)} has the request.`):i(`waiting`,`Request delivered to ${G(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 Te(e){return e===`user`?`You`:e.startsWith(`app:`)?`App ${e.slice(4)}`:`Session ${e}`}function K(e,t){let n=t.get(e);return n===void 0?`revision ${e.slice(-6)}`:`revision ${n}`}function Ee(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||ve(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 De(e,t,n){let r=t.trim().toLowerCase();return r?e.filter(e=>e.key===n||e.search.includes(r)):[...e]}function Oe(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 ke(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 Ae(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>de.aiInstructionChars)return t(`Keep it under ${de.aiInstructionChars.toLocaleString(`en-US`)} characters.`);if(ge.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 je=4e6,Me=3,Ne=e=>{let t=e.replace(/\r\n?/g,`
1
+ import{$ as e,At as t,Ct as n,Et as r,G as i,Ht as a,Lt as o,Mt as s,Nt as c,Ot as l,Pt as u,Tt as d,Ut as f,Vt as p,Wt as m,a as h,bt as g,dt as _,ft as v,g as y,gt as b,ht as x,i as S,it as C,lt as w,nt as T,pt as E,q as D,r as O,st as k,tt as A,u as j,ut as M,vt as N,wt as P,yt as F}from"./ui-Qo2Pd9-O.js";import{A as I,O as L,P as R,U as z,V as ee,k as te,z as ne}from"./index-DifgVuKS.js";import{c as re,d as ie,f as ae,i as oe,l as se,n as ce,r as le,t as ue,u as de}from"./source-BFLJQ43_.js";var fe=`ai-actions`,B=16,pe=[`ask`,`propose-edit`,`run-action`],me=[`queued`,`running`,`succeeded`,`failed`,`cancelled`],he=[`starting`,`waiting`,`offline`,`ready`,`ended`,`failed`],ge=/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/,V=e=>typeof e==`object`&&!!e&&!Array.isArray(e),H=e=>typeof e==`string`&&e.length>0,U=e=>typeof e==`number`&&Number.isFinite(e),_e=(e,t)=>typeof t==`string`&&e.includes(t),ve=e=>e.replace(/\/+$/,``).split(`/`).pop()||e;function ye(e){if(V(e)&&_e(he,e.status)){if(e.kind===`session`&&H(e.address))return e;if(e.kind===`launch`&&H(e.machine)&&H(e.repo))return{harness:``,mode:`checkout`,...e}}}function be(e){if(!V(e)||!_e([`pending`,`applied`,`conflict`],e.state)||!Array.isArray(e.files))return;let t=e.files.filter(e=>V(e)&&H(e.mediaType)&&U(e.bytes)&&H(e.hash));return{state:e.state,files:t,...Array.isArray(e.keep)?{keep:e.keep.filter(H)}:{},...H(e.entry)?{entry:e.entry}:{},...H(e.appliedRevisionID)?{appliedRevisionID:e.appliedRevisionID}:{}}}function xe(e){if(!V(e)||!H(e.id)||!H(e.artifactID)||!H(e.baseRevisionID)||!U(e.revision)||!_e(me,e.state)||!_e(pe,e.kind)||typeof e.instruction!=`string`||!H(e.by)||!U(e.createdAt)||!U(e.updatedAt))return;let t=ye(e.handler);if(!t)return;let n=be(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 Se(e){let t=V(e)?e:{};return{items:Array.isArray(t.items)?t.items.flatMap(e=>xe(e)??[]):[],...H(t.cursor)?{cursor:t.cursor}:{}}}function Ce(e){let t=e?.[fe];return t?t.split(`,`).map(e=>e.trim()).filter(D).slice(0,B):[]}var W=e=>e.state===`queued`||e.state===`running`;function G(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} · ${ve(e.repo)}`}function we(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: ${G(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 ${G(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 ${G(r,t)}`);case`ready`:return e.state===`running`?i(`running`,`Working: ${G(r,t)} has the request.`):i(`waiting`,`Request delivered to ${G(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 Te(e){return e===`user`?`You`:e.startsWith(`app:`)?`App ${e.slice(4)}`:`Session ${e}`}function K(e,t){let n=t.get(e);return n===void 0?`revision ${e.slice(-6)}`:`revision ${n}`}function Ee(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||ve(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 De(e,t,n){let r=t.trim().toLowerCase();return r?e.filter(e=>e.key===n||e.search.includes(r)):[...e]}function Oe(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 ke(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 Ae(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>de.aiInstructionChars)return t(`Keep it under ${de.aiInstructionChars.toLocaleString(`en-US`)} characters.`);if(ge.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 je=4e6,Me=3,Ne=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 Pe(e,t){let n=Ne(e),r=Ne(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)>je)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-Me);e<=Math.min(f.length-1,t+Me);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 Fe(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 Ie(e){let t=V(e)||e instanceof Error?e:{},n=U(t.status)?t.status:0,r=typeof t.code==`string`?t.code:``,i=typeof t.message==`string`?t.message:String(e),a=V(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 Le(e){return e.proposal?.state===`conflict`?`stale-base`:`job-changed`}function Re(e){return Math.min(1e4,Math.round(1500*1.5**Math.max(0,e)))}var ze={set(e,t){let n=setTimeout(e,t);return()=>clearTimeout(n)}},Be=()=>globalThis.crypto?.randomUUID?.()??`${Date.now()}-${Math.random().toString(36).slice(2)}`,Ve=e=>!(e&&typeof e==`object`&&typeof e.status==`number`);function He(e){let{source:t,artifactID:n,onState:r}=e,i=e.timers??ze,a=e.key??Be,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:Ce(e.metadata),revisionNumbers:r})}function v(){c?.(),c=void 0,u||!o.jobs.some(W)?l=0:c=i.set(()=>{c=void 0,x()},Re(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:Ie(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:Ie(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=>!W(e)&&r.get(e.id)&&W(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:Ie(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=Ve(e)?{body:r,key:i}:void 0;let t=Ie(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=Ae({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]||!W(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=Ie(t),r=n.kind===`conflict`?await E(e):void 0;return h(e,{kind:n.kind===`conflict`?`conflict`:`error`,text:r&&!W(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=Ie(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&&Le(r)===`stale-base`){let t=o.artifact?K(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:ke(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:Ie(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=Fe(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:Pe(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:Ie(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 Ue=`/api/agent/artifacts`,q={textBytes:2097152,imageBytes:10485760,editBytes:1048576,revisionsPage:20},We=encodeURIComponent,Ge=e=>`${Ue}/${We(e)}`,Ke=(e,t)=>`${Ge(e)}/revisions?limit=${q.revisionsPage}${t?`&cursor=${We(t)}`:``}`,qe=(e,t)=>`${Ge(e)}/revisions/${We(t)}`,Je=(e,t,n)=>`${qe(e,t)}/blobs/${We(n)}`,Ye=e=>typeof e==`object`&&!!e&&!Array.isArray(e),J=e=>typeof e==`string`&&e.length>0,Xe=e=>typeof e==`number`&&Number.isFinite(e),Ze=e=>typeof e==`string`&&se.includes(e),Qe=(e,t)=>Ye(e)&&Ye(e[t])?e[t]:e;function $e(e){let t=Qe(e,`artifact`);if(!Ye(t)||!J(t.id)||typeof t.title!=`string`||!Ze(t.kind)||!J(t.latestRevisionID)||!Xe(t.revision))return;let n=Array.isArray(t.tags)?t.tags.filter(e=>typeof e==`string`):void 0;return{v:1,id:t.id,title:t.title,kind:t.kind,state:t.state===`archived`?`archived`:`active`,visibility:t.visibility===`workspace`?`workspace`:`private`,latestRevisionID:t.latestRevisionID,revision:t.revision,createdAt:Xe(t.createdAt)?t.createdAt:0,updatedAt:Xe(t.updatedAt)?t.updatedAt:0,...J(t.description)?{description:t.description}:{},...J(t.workspaceID)?{workspaceID:t.workspaceID}:{},...J(t.createdBySessionID)?{createdBySessionID:t.createdBySessionID}:{},...n?.length?{tags:n}:{}}}function et(e){if(Ye(e)){if(e.kind===`user`)return{kind:`user`};if(e.kind===`session`&&J(e.sessionID))return{kind:`session`,sessionID:e.sessionID};if(e.kind===`ai_job`&&J(e.jobID))return{kind:`ai_job`,jobID:e.jobID}}}function tt(e){let t=Qe(e,`revision`);if(!Ye(t)||!J(t.id)||!J(t.artifactID)||!Xe(t.number)||!Array.isArray(t.blobs))return;let n=et(t.author);if(!n)return;let r=t.blobs.filter(e=>ae(e)===void 0);return{v:1,id:t.id,artifactID:t.artifactID,number:t.number,blobs:r.map(e=>({hash:e.hash,bytes:e.bytes,mediaType:e.mediaType,...e.path===void 0?{}:{path:e.path}})),author:n,createdAt:Xe(t.createdAt)?t.createdAt:0,...J(t.baseRevisionID)?{baseRevisionID:t.baseRevisionID}:{},...J(t.entry)?{entry:t.entry}:{}}}function nt(e){let t=Ye(e)?e:{};return{items:Array.isArray(t.items)?t.items.flatMap(e=>tt(e)??[]):[],...J(t.cursor)?{cursor:t.cursor}:{}}}function rt(e){return e.kind===`user`?`You`:e.kind===`session`?`Session ${e.sessionID.slice(0,12)}…`:`AI job`}var it=[`text/markdown`,`text/plain`,`text/csv`,`text/html`,`text/css`,`text/javascript`,`application/json`],at=[`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`image/svg+xml`],ot={markdown:{"text/markdown":`markdown`,"text/plain":`markdown`},code:Object.fromEntries(it.map(e=>[e,`code`])),image:Object.fromEntries(at.map(e=>[e,`image`])),table:{"text/csv":`table`,"application/json":`table`},chart:{"application/json":`chart`},dashboard:{"application/json":`dashboard`},file:{...Object.fromEntries(at.map(e=>[e,`image`])),"text/plain":`text`,"text/markdown":`text`}},st={ts:`ts`,tsx:`tsx`,js:`js`,jsx:`jsx`,mjs:`js`,cjs:`js`,py:`python`,go:`go`,rs:`rust`,sh:`bash`,bash:`bash`,json:`json`,css:`css`,html:`html`,htm:`html`,md:`markdown`,yaml:`yaml`,yml:`yaml`,toml:`toml`,sql:`sql`,java:`java`,c:`c`,h:`c`,cpp:`cpp`,rb:`ruby`,swift:`swift`,kt:`kotlin`,diff:`diff`,csv:`csv`,txt:``},ct={"text/javascript":`js`,"text/css":`css`,"application/json":`json`,"text/html":`html`,"text/markdown":`markdown`,"text/csv":`csv`};function lt(e){let t=e.path?.split(`/`).pop()?.split(`.`).slice(1).pop()?.toLowerCase();return t!==void 0&&t in st?st[t]:ct[e.mediaType]??``}function ut(e,t){let n=t.blobs;if(ie.includes(e))return{mode:`isolated`,files:n,...n[0]?{file:dt(t)??n[0]}:{}};if(!n.length)return{mode:`empty`,files:n};let r=ot[e],i=dt(t)??n.find(e=>r[e.mediaType])??n[0],a=r[i.mediaType];if(!a)return{mode:`download`,file:i,files:n,note:`A ${i.mediaType} file can't be shown as ${e===`image`?`an`:`a`} ${e} here.`};let o=a===`image`?q.imageBytes:q.textBytes;return i.bytes>o?{mode:`download`,file:i,files:n,note:`This file is too large to preview (${Math.ceil(i.bytes/1024)} KiB).`}:{mode:a,file:i,files:n,...a===`code`?{lang:lt(i)}:{}}}function dt(e){return e.entry===void 0?void 0:e.blobs.find(t=>t.path===e.entry)}var ft=class extends Error{limit;name=`TooLargeError`;code=`too_large`;constructor(e){super(`A file here is at most ${Math.round(e/1024)} KiB`),this.limit=e}};async function pt(e,t){let n=Number(e.headers.get(`content-length`)??``);if(Number.isFinite(n)&&n>t)throw await e.body?.cancel().catch(()=>{}),new ft(t);if(!e.body)return new Uint8Array;let r=e.body.getReader(),i=[],a=0;for(;;){let{done:e,value:n}=await r.read();if(e)break;if(a+=n.byteLength,a>t)throw await r.cancel().catch(()=>{}),new ft(t);i.push(n)}let o=new Uint8Array(a),s=0;for(let e of i)o.set(e,s),s+=e.byteLength;return o}function mt(e){let t=e&&typeof e==`object`?e:{},n=typeof t.status==`number`?t.status:0,r=typeof t.message==`string`?t.message:``;return t.name===`NetworkError`||n===503?{kind:`offline`,text:`Can't reach the hub right now. Nothing was lost; try again when it's back.`}:t.name===`TooLargeError`||t.code===`too_large`?{kind:`too_large`,text:r||`The file is too large.`}:n===404||n===403?{kind:`not_found`,text:`This artifact doesn't exist or you can't see it.`}:n===401?{kind:`forbidden`,text:`This device isn't signed in to the hub.`}:n===422||t.code===`unsupported`?{kind:`unsupported`,text:`Artifacts aren't supported on this hub yet.`}:n===409||t.code===`conflict`?{kind:`conflict`,text:`The artifact changed since you opened it.`}:n===429||t.code===`rate_limited`?{kind:`rate_limited`,text:r?`Limit reached: ${r}`:`A limit was reached; try again later.`}:n===400?{kind:`invalid`,text:r||`The hub refused the change.`}:{kind:`error`,text:r?`Something went wrong: ${r}`:`Something went wrong (HTTP ${n}).`}}var ht=e=>new TextEncoder().encode(e).byteLength;function gt(e,t){if(e.state!==`active`||t.id!==e.latestRevisionID||ie.includes(e.kind)||t.blobs.length!==1)return!1;let n=t.blobs[0];return it.includes(n.mediaType)&&n.bytes<=q.editBytes}function _t(e,t,n){if(ht(n)>q.editBytes)throw new ft(q.editBytes);return{baseRevisionID:e,upload:[{mediaType:t.mediaType,data:n,encoding:`utf8`,...t.path===void 0?{}:{path:t.path}}]}}var vt=e=>`hub.artifactDraft.v1.${e}`;function yt(e,t){try{let n=e?.getItem(vt(t)),r=n?JSON.parse(n):void 0;return Ye(r)&&r.v===1&&J(r.base)&&typeof r.text==`string`?{v:1,base:r.base,text:r.text}:void 0}catch{return}}function bt(e,t){let n=yt(t.storage,e.artifactID),r=n?n.base===e.baseRevisionID?{status:`editing`,draft:n.text,baseRevisionID:n.base,restored:!0}:{status:`conflict`,draft:n.text,baseRevisionID:n.base,latestRevisionID:e.baseRevisionID,restored:!0}:{status:`editing`,draft:e.original,baseRevisionID:e.baseRevisionID},i=e.original,a,o=e=>{r=e,t.onChange()},s=()=>{try{r.draft===i&&r.baseRevisionID===e.baseRevisionID?t.storage?.removeItem(vt(e.artifactID)):ht(r.draft)<=q.editBytes&&t.storage?.setItem(vt(e.artifactID),JSON.stringify({v:1,base:r.baseRevisionID,text:r.draft}))}catch{}};return{state:()=>r,setDraft(e){o({...r,draft:e,status:r.status===`conflict`?`conflict`:`editing`}),s()},async save(){if(r.status===`saving`||r.status===`conflict`||r.draft===i&&r.baseRevisionID===e.baseRevisionID)return;let n;try{n=_t(r.baseRevisionID,e.file,r.draft)}catch(e){o({...r,status:`error`,error:{kind:`too_large`,text:`${e.message}; shorten the draft to save it.`}});return}let c=`${r.baseRevisionID}\n${r.draft}`,l=a?.sig===c?a.key:t.newKey();a={sig:c,key:l};let u=r;o({...r,status:`saving`});try{let r=await t.revise(e.artifactID,n,l);return i=u.draft,t.storage?.removeItem(vt(e.artifactID)),o({status:`saved`,draft:u.draft,baseRevisionID:r.id}),r}catch(e){let t=mt(e),n=e.details;t.kind===`conflict`?o({...u,status:`conflict`,error:t,...J(n?.latestRevisionID)?{latestRevisionID:n.latestRevisionID}:{}}):o({...u,status:`error`,error:t}),s();return}},rebase(e){let{latestRevisionID:t,error:n,...i}=r;o({...i,status:`editing`,baseRevisionID:e}),s()},discard(){t.storage?.removeItem(vt(e.artifactID)),a=void 0,o({status:`editing`,draft:i,baseRevisionID:e.baseRevisionID})}}}var xt={markdown:`Markdown`,code:`Code`,image:`Image`,table:`Table`,chart:`Chart`,dashboard:`Dashboard`,html:`HTML`,app:`App`,file:`File`};function St(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 Ct={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 wt(e,t){return{name:e?.path?.split(`/`).pop()||`Untitled`,language:t?Ct[t]??t.toUpperCase():`Plain text`}}function Tt(e,t){let n=[{label:`Type`,value:xt[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?rt({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=Ce(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 Et={ask:`ask`,edit:`propose-edit`,action:`run-action`};function Dt(e,t){let n=/^\/([a-z]+)(?:\s+([\s\S]*))?$/.exec(e),r=n?Et[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 Ot=`hub.artifactAiHandler.v1`;function kt(e,t){try{e?.setItem(Ot,t)}catch{}}function At(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 jt(e){return[...e].reverse()}var Mt=`hub.artifactAiPanel.v1`,Y={min:280,max:640,default:380,share:.6};function Nt(e,t){if(!Number.isFinite(e))return Y.default;let n=Math.max(Y.min,Math.min(Y.max,Math.floor(t*Y.share)));return Math.min(n,Math.max(Y.min,Math.round(e)))}function Pt(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 Ft(e,t){try{e?.setItem(Mt,JSON.stringify(t))}catch{}}var It=F(`<input type=search class=aai-picker-search aria-label="Search handlers"placeholder=Find… title="Find a handler by @name, title or session ID">`),Lt=F(`<optgroup label="Your sessions">`),Rt=F(`<optgroup label="New session in a workspace repo">`),zt=F(`<span><select aria-label="Handled by"title="Who handles this request"><option value>`),Bt=F(`<option>`),Vt=F(`<button type=button class=aai-recent>Use `);function Ht(){try{return window.localStorage}catch{return}}function Ut(e){let[i,a]=o(``),s=()=>e.value?void 0:At(Ht(),e.handlers),l=c(()=>De(e.handlers,i(),e.value)),d=()=>l().filter(e=>e.kind===`session`),f=()=>l().filter(e=>e.kind===`launch`),p=()=>!!i().trim()&&!l().some(t=>t.key!==e.value);return(()=>{var o=zt(),c=o.firstChild,l=c.firstChild;return v(o,t(r,{get when(){return e.handlers.length>1},get children(){var t=It();return t.$$input=e=>a(e.currentTarget.value),t.addEventListener(`focus`,()=>e.onPick?.()),u(()=>t.value=i()),t}}),c),c.addEventListener(`change`,t=>e.onChange(t.currentTarget.value)),c.addEventListener(`focus`,()=>e.onPick?.()),v(l,()=>p()?`No handler matches the search`:`Choose a session…`),v(c,t(r,{get when(){return d().length},get children(){var r=Lt();return v(r,t(n,{get each(){return d()},children:t=>(()=>{var n=Bt();return v(n,()=>t.label),u(()=>n.selected=t.key===e.value),u(()=>n.value=t.key),n})()})),r}}),null),v(c,t(r,{get when(){return f().length},get children(){var r=Rt();return v(r,t(n,{get each(){return f()},children:t=>(()=>{var n=Bt();return v(n,()=>t.label),u(()=>n.selected=t.key===e.value),u(()=>n.value=t.key),n})()})),r}}),null),v(o,t(r,{get when(){return s()},children:t=>(()=>{var n=Vt();return n.firstChild,n.$$click=()=>e.onChange(t().key),v(n,()=>t().display,null),u(e=>{var r=`Last used on this device: ${t().label}`,i=`Use ${t().display} (last used)`;return r!==e.e&&x(n,`title`,e.e=r),i!==e.t&&x(n,`aria-label`,e.t=i),e},{e:void 0,t:void 0}),n})()}),null),u(()=>M(o,`aai-picker ${e.class??``}`)),u(()=>c.value=e.value),o})()}_([`input`,`click`]);var Wt=`/api/agent/artifacts`,Gt=50,Kt=262144,qt=e=>e.startsWith(`text/`)||e===`application/json`||e===`image/svg+xml`,X=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Jt=t=>new e(502,`The hub answered an unexpected ${t}`);function Yt(e){let t=X(e)&&X(e.artifact)?e.artifact:e;if(!X(t)||typeof t.id!=`string`||typeof t.latestRevisionID!=`string`||typeof t.revision!=`number`)throw Jt(`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}:{},...X(t.metadata)?{metadata:t.metadata}:{}}}var Xt=e=>{let t=xe(X(e)?e.job:void 0);if(!t)throw Jt(`job`);return t},Zt=async(e,t,n={})=>(await A(e,{method:`POST`,json:t,headers:n})).json();async function Qt(){try{let e=await C(`/api/agent/who`),t=X(e)&&Array.isArray(e.sessions)?e.sessions:[];return new Map(t.flatMap(e=>X(e)&&typeof e.sessionID==`string`&&typeof e.name==`string`&&e.name?[[e.sessionID,e.name]]:[]))}catch{return new Map}}function $t(e){let t=e=>`${Wt}/${T(e)}/jobs`,n=(e,n,r=``)=>`${t(e)}/${T(n)}${r}`;return{artifact:async e=>Yt(await C(`${Wt}/${T(e)}`)),async revisionNumbers(e){let t=await C(`${Wt}/${T(e)}/revisions?limit=200`),n=X(t)&&Array.isArray(t.items)?t.items:[];return new Map(n.flatMap(e=>X(e)&&typeof e.id==`string`&&typeof e.number==`number`?[[e.id,e.number]]:[]))},jobs:async(e,n)=>Se(await C(`${t(e)}?limit=${Gt}${n?`&cursor=${T(n)}`:``}`)),job:async(e,t)=>Xt(await C(n(e,t))),create:async(e,n,r)=>Xt(await Zt(t(e),n,{"idempotency-key":r})),cancel:async(e,t,r)=>Xt(await Zt(n(e,t,`/cancel`),{expectedRevision:r})),async apply(e,t,r){let i=await Zt(n(e,t,`/apply`),{expectedRevision:r}),a=X(i)&&X(i.revision)?i.revision:{};if(typeof a.id!=`string`)throw Jt(`revision`);return{job:Xt(i),revisionID:a.id,...typeof a.number==`number`?{revisionNumber:a.number}:{}}},proposal:async(e,t)=>{let r=await C(n(e,t,`/proposal`));if(!X(r)||!Array.isArray(r.files))throw Jt(`proposal`);return{...r,keep:Array.isArray(r.keep)?r.keep:[],truncated:r.truncated===!0}},async revisionFiles(e,t){let n=await C(`${Wt}/${T(e)}/revisions/${T(t)}`),r=X(n)&&X(n.revision)&&Array.isArray(n.revision.blobs)?n.revision.blobs:[],i=Kt,a=[];for(let n of r){if(!X(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};qt(n.mediaType)?n.bytes>i?a.push({...r,omitted:`budget`}):(i-=n.bytes,a.push({...r,text:await(await A(`${Wt}/${T(e)}/revisions/${T(t)}/blobs/${T(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 C(`/api/agent/workspaces/${T(t.workspaceID)}/bindings`);return(X(e)&&Array.isArray(e.bindings)?e.bindings:[]).flatMap(e=>X(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[]}})(),Qt()]);return Ee({sessions:e.sessions().map(e=>r.get(e.id)?{...e,name:r.get(e.id)}:e),bindings:n,machines:e.machines()})}}}var en=F(`<span>an unknown revision`),tn=F(`<button type=button class=aai-link>`),nn=F(`<span>`),rn=F(`<strong class=aai-older>You are viewing an older revision.`),an=F(`<p class=aai-sub>Requests use the latest revision (<!>).`),on=F(`<p class=aai-note role=status>Loading AI requests…`),sn=F(`<button type=button class="btn small aai-older-btn">Load older requests`),cn=F(`<ol class=aai-jobs aria-label="AI request history">`),ln=F(`<p class=aai-note>Could not list handlers: `),un=F(`<p class=aai-note role=status>`),dn=F(`<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`),fn=F(`<select class=aai-action aria-label="Declared action"><option value>Choose an action…`),pn=F(`<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>`),mn=F(`<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>`),hn=F(`<button type=button class="btn small">Retry`),gn=F(`<p class=aai-note> `),_n=F(`<kbd>/action `),vn=F(`<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>.`),yn=F(`<p class="aai-note err"role=alert>`),bn=F(`<label class=aai-seg-item><input type=radio>`),xn=F(`<option>`),Sn=F(`<span class=aai-dot aria-hidden=true>`),Cn=F(`<div class=aai-answer>`),wn=F(`<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.`),Tn=F(`<button type=button class="btn primary small">`),En=F(`<button type=button class="btn small">Request again on the latest revision`),Dn=F(`<button type=button class="btn small">`),On=F(`<button type=button class="btn small">Continue in side chat`),kn=F(`<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>`),An=F(`<div class=aai-proposal>`),jn=F(`<button type=button class="btn small">Review proposed edit (<!> file<!>)`),Mn=F(`<p class=aai-note role=status>Loading the proposal…`),Nn=F(`<p class="aai-note err">Could not load the proposal: `),Pn=F(`<ul class=aai-files aria-label="Proposed files">`),Fn=F(`<p class=aai-note>Some files are too large to show here.`),In=F(`<li><span class=aai-file-change></span> <code>`),Ln=F(`<p class=aai-meta><code>`),Rn=F(`<table class=diff><tbody>`),zn=F(`<div class=aai-diff>`),Bn=F(`<p class=aai-note>`),Vn=F(`<tr><td class=ln></td><td class=ln></td><td class=code-line><span class=sign>`),Hn=F(`<p>`),Un={ask:`Ask`,"propose-edit":`Edit`,"run-action":`Action`},Wn={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`},Gn=e=>e.kind===`ask`?`Question`:e.kind===`propose-edit`?`Edit`:`Action: ${e.action??`?`}`;function Kn(){return $t({sessions:()=>{let e=new Map;for(let t of ee.machines??[])for(let n of t.processes)for(let t of n.sessions)e.set(t.id,n.harness||`opencode`);return z().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:()=>(ee.machines??[]).map(e=>({id:e.id,name:e.name,online:!!e.online}))})}function qn(e){let[i,p]=o(),h=!e.controller,_=e.controller?.ai??He({source:e.source??Kn(),artifactID:e.artifactID,onState:p});m(()=>h&&void _.load()),f(()=>h&&_.dispose());let y=()=>(h?i():e.controller.state())??_.state(),b=()=>y().revisionNumbers,S=()=>y().artifact?.latestRevisionID,[C,w]=o(`ask`),[T,D]=o(``),[k,A]=o(``),[j,M]=o(``),[N,P]=o(!1),F,I,L,R=c(()=>y().handlers.find(e=>e.key===k())),z=()=>C()===`ask`?`Ask`:C()===`propose-edit`?`Propose edit`:j()?`Run ${j()}…`:`Run action…`,ee=c(()=>jt(y().jobs));s(a(()=>[y().jobs.length,e.tailCount??0],()=>queueMicrotask(()=>L&&(L.scrollTop=L.scrollHeight))));async function te(){let e=k(),t=await _.request({kind:C(),instruction:T(),...e?{handlerKey:e}:{},...C()===`run-action`&&j()?{action:j()}:{}});P(!1),t&&(D(``),kt(Ht(),e))}function ne(e){e?.preventDefault(),!y().sending&&(C()===`run-action`&&j()&&k()?(P(!0),queueMicrotask(()=>F?.focus())):te())}function re(e){let t=Dt(e,y().actions);t.kind&&/\s$/.test(e)?(w(t.kind),t.action&&M(t.action),P(!1),D(t.text),I&&(I.value=t.text)):D(e)}async function ie(t){if(await _.accept(t.id)){let t=S();t&&e.onRevised?.(t)}}let ae=(n,i=``)=>t(r,{when:n,get fallback(){return(()=>{var e=en(),t=e.firstChild;return v(e,i,t),e})()},children:n=>t(r,{get when(){return e.onShowRevision},get fallback(){return(()=>{var e=nn();return v(e,()=>i+K(n(),b())),e})()},get children(){var t=tn();return t.$$click=()=>e.onShowRevision?.(n()),v(t,()=>i+K(n(),b())),t}})});return(()=>{var i=mn(),a=i.firstChild,o=a.firstChild,s=o.nextSibling,c=s.firstChild,f=a.nextSibling;v(o,t(O,{name:`spark`})),v(s,t(r,{get when(){return y().status===`ready`},get children(){var n=an(),i=n.firstChild.nextSibling;return i.nextSibling,v(n,()=>ae(S()),i),v(n,t(r,{get when(){return E(()=>!!(e.revisionID&&S()))()&&e.revisionID!==S()},get children(){return[` `,rn()]}}),null),n}}),null),v(a,()=>e.headerActions,null);var p=L;return typeof p==`function`?g(p,f):L=f,v(f,t(l,{get children(){return[t(d,{get when(){return y().status===`loading`},get children(){return on()}}),t(d,{get when(){return E(()=>y().status===`error`)()&&y().error},children:e=>(()=>{var n=gn(),i=n.firstChild;return v(n,()=>e().text,i),v(n,t(r,{get when(){return e().kind===`error`||e().kind===`offline`},get children(){var e=hn();return e.$$click=()=>void _.load(),e}}),null),u(t=>{var r=e().kind===`error`,i=e().kind===`error`?`alert`:`status`;return r!==t.e&&n.classList.toggle(`err`,t.e=r),i!==t.t&&x(n,`role`,t.t=i),t},{e:void 0,t:void 0}),n})()}),t(d,{get when(){return y().status===`ready`},get children(){return[t(r,{get when(){return y().more},get children(){var e=sn();return e.$$click=()=>void _.more(),u(t=>{var n=y().loadingMore,r=y().loadingMore;return n!==t.e&&(e.disabled=t.e=n),r!==t.t&&x(e,`aria-busy`,t.t=r),t},{e:void 0,t:void 0}),e}}),t(r,{get when(){return y().jobs.length},get fallback(){return(()=>{var e=vn(),n=e.firstChild.nextSibling.nextSibling,i=n.firstChild.nextSibling.nextSibling.nextSibling.nextSibling;return v(n,t(r,{get when(){return y().actions.length},get children(){return[` `,`or `,(()=>{var e=_n();return e.firstChild,v(e,()=>y().actions[0],null),e})()]}}),i),e})()},get children(){var r=cn();return v(r,t(n,{get each(){return ee()},children:n=>t(Jn,{job:n,get state(){return y()},revisionRef:ae,onCancel:()=>void _.cancel(n.id),onReview:()=>void _.review(n.id),onAccept:()=>void ie(n),onRerequest:()=>void _.rerequest(n.id),get onContinue(){return e.onContinueInSideChat}})})),r}})]}})]}}),null),v(f,()=>e.threadTail,null),v(i,t(r,{get when(){return y().status===`ready`},get children(){var i=pn(),a=i.firstChild,o=a.firstChild,s=o.firstChild,c=o.nextSibling,l=c.nextSibling,d=l.firstChild,f=d.nextSibling,p=f.firstChild;i.addEventListener(`submit`,ne),v(i,t(r,{get when(){return y().sendError},children:e=>(()=>{var t=yn();return v(t,()=>e().text),t})()}),a),v(i,t(r,{get when(){return y().handlersError},get children(){var e=ln();return e.firstChild,v(e,()=>y().handlersError,null),e}}),a),v(i,t(r,{get when(){return E(()=>!!R())()&&!R().online},get children(){var e=un();return v(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),v(i,t(r,{get when(){return N()},get children(){var e=dn(),t=e.firstChild,n=t.firstChild.nextSibling,r=n.nextSibling.nextSibling,i=r.nextSibling.nextSibling,a=t.nextSibling.firstChild,o=a.nextSibling;e.$$keydown=e=>{e.key===`Escape`&&(e.preventDefault(),P(!1),I?.focus())},v(n,j),v(t,()=>K(S()??``,b()),r),v(i,()=>R()?.display),a.$$click=()=>void te();var s=F;return typeof s==`function`?g(s,a):F=a,o.$$click=()=>{P(!1),I?.focus()},u(()=>a.disabled=y().sending),e}}),a),v(s,t(n,{each:[`ask`,`propose-edit`,`run-action`],children:t=>{let n=()=>t===`run-action`&&y().actions.length===0;return(()=>{var r=bn(),i=r.firstChild;return i.addEventListener(`change`,()=>{w(t),P(!1)}),i.value=t,v(r,()=>Un[t],null),u(a=>{var o=C()===t,s=!!n(),c=n()?`This artifact declares no AI actions`:Wn[t],l=`aai-mode-${e.artifactID}`,u=n();return o!==a.e&&r.classList.toggle(`on`,a.e=o),s!==a.t&&r.classList.toggle(`disabled`,a.t=s),c!==a.a&&x(r,`title`,a.a=c),l!==a.o&&x(i,`name`,a.o=l),u!==a.i&&(i.disabled=a.i=u),a},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),u(()=>i.checked=C()===t),r})()}})),v(o,t(r,{get when(){return C()===`run-action`},get children(){var e=fn();return e.firstChild,e.addEventListener(`change`,e=>(M(e.currentTarget.value),P(!1))),v(e,t(n,{get each(){return y().actions},children:e=>(()=>{var t=xn();return t.value=e,v(t,e),t})()}),null),u(()=>e.value=j()),e}}),null),c.$$keydown=e=>{e.key===`Enter`&&(e.metaKey||e.ctrlKey)&&ne(e)},c.$$input=e=>re(e.currentTarget.value);var m=I;return typeof m==`function`?g(m,c):I=c,v(l,t(Ut,{get handlers(){return y().handlers},get value(){return k()},onPick:()=>void _.reloadHandlers(),onChange:e=>(A(e),P(!1))}),d),v(f,t(O,{name:`send`}),p),v(p,(()=>{var e=E(()=>!!y().sending);return()=>e()?`Sending…`:z()})()),u(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&&x(c,`aria-label`,e.e=t),n!==e.t&&x(c,`placeholder`,e.t=n),r!==e.a&&(f.disabled=e.a=r),i!==e.o&&x(f,`aria-busy`,e.o=i),a!==e.i&&x(f,`aria-label`,e.i=a),o!==e.n&&x(f,`title`,e.n=o),e},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),u(()=>c.value=T()),i}}),null),u(t=>{var n=`aai-h-${e.artifactID}`,r=`aai-h-${e.artifactID}`;return n!==t.e&&x(i,`aria-labelledby`,t.e=n),r!==t.t&&x(c,`id`,t.t=r),t},{e:void 0,t:void 0}),i})()}function Jn(e){let i=()=>e.job,a=c(()=>Oe(e.state.handlers)),o=e=>a().get(e)??z().find(t=>t.id===e)?.title,s=()=>we(i(),o),f=()=>e.state.pending[i().id],p=()=>e.state.notices[i().id],m=()=>e.state.reviews[i().id],h=()=>e.state.artifact?.latestRevisionID,g=()=>i().kind===`propose-edit`&&i().state===`succeeded`&&i().proposal?.state===`pending`,_=()=>g()&&h()!==void 0&&i().baseRevisionID!==h(),y=()=>i().kind===`propose-edit`&&(i().proposal?.state===`conflict`||_()||p()?.stale);return(()=>{var a=kn(),c=a.firstChild,h=c.firstChild,b=h.firstChild,S=b.nextSibling,C=S.firstChild,T=h.nextSibling,D=c.nextSibling,O=D.firstChild,k=O.firstChild.nextSibling;k.nextSibling;var A=O.nextSibling,N=A.nextSibling;return v(b,()=>Gn(i())),v(S,()=>Te(i().by),C),v(S,()=>j(i().createdAt),null),v(T,()=>i().instruction),v(O,()=>e.revisionRef(i().baseRevisionID),k),v(O,()=>G(i().handler,o),null),v(O,t(r,{get when(){return i().proposal?.appliedRevisionID},children:t=>[` · became `,E(()=>e.revisionRef(t()))]}),null),v(A,t(r,{get when(){return s().active},get children(){return Sn()}}),null),v(A,()=>s().text,null),v(D,t(r,{get when(){return i().answer},get children(){var t=Cn();return v(t,()=>i().answer),u(()=>x(t,`aria-label`,`Answer from ${G(i().handler,o)} on ${K(i().baseRevisionID,e.state.revisionNumbers)}`)),t}}),N),v(D,t(r,{get when(){return E(()=>!!(i().proposal&&i().proposal.state!==`applied`))()&&i().proposal},children:i=>(()=>{var a=An();return v(a,t(r,{get when(){return m()},get fallback(){return(()=>{var t=jn(),n=t.firstChild.nextSibling,r=n.nextSibling.nextSibling;return r.nextSibling,w(t,`click`,e.onReview,!0),v(t,()=>i().files.length,n),v(t,()=>i().files.length===1?``:`s`,r),v(t,(()=>{var e=E(()=>!!i().keep?.length);return()=>e()?`, ${i().keep.length} kept`:``})(),r),t})()},children:e=>t(l,{get children(){return[t(d,{get when(){return e().status===`loading`},get children(){return Mn()}}),t(d,{get when(){return E(()=>e().status===`error`)()&&e()},children:e=>(()=>{var t=Nn();return t.firstChild,v(t,()=>e().text,null),t})()}),t(d,{get when(){return E(()=>e().status===`ready`)()&&e()},children:e=>{let i=()=>e();return[t(r,{get when(){return i().changes.some(e=>e.path!==void 0)},get children(){var e=Pn();return v(e,t(n,{get each(){return i().changes},children:e=>(()=>{var t=In(),n=t.firstChild,r=n.nextSibling.nextSibling;return v(n,()=>e.change),v(r,()=>e.path),u(()=>M(t,`aai-file ${e.change}`)),t})()})),e}}),t(n,{get each(){return i().diffs},children:e=>(()=>{var i=zn();return v(i,t(r,{get when(){return e.path},get children(){var t=Ln(),n=t.firstChild;return v(n,()=>e.path),t}}),null),v(i,t(r,{get when(){return e.lines},get fallback(){return(()=>{var t=Bn();return v(t,()=>e.note),t})()},get children(){var r=Rn(),i=r.firstChild;return v(i,t(n,{get each(){return e.lines},children:e=>(()=>{var t=Vn(),n=t.firstChild,r=n.nextSibling,i=r.nextSibling,a=i.firstChild;return v(n,()=>e.oldNo??``),v(r,()=>e.newNo??``),v(a,(()=>{var t=E(()=>e.type===`add`);return()=>t()?`+`:e.type===`del`?`−`:` `})()),v(i,()=>e.text,null),u(()=>M(t,e.type)),t})()})),u(()=>x(r,`aria-label`,`Changes${e.path?` to ${e.path}`:``}`)),r}}),null),i})()}),t(r,{get when(){return i().truncated},get children(){return Fn()}})]}})]}})})),a})()}),N),v(D,t(r,{get when(){return E(()=>!!_())()&&!p()},get children(){return wn()}}),N),v(D,t(r,{get when(){return p()},children:e=>(()=>{var t=Hn();return v(t,()=>e().text),u(n=>{var r=`aai-note ${e().kind===`info`?`ok`:e().kind===`conflict`?`warn`:`err`}`,i=e().kind===`info`?`status`:`alert`;return r!==n.e&&M(t,n.e=r),i!==n.t&&x(t,`role`,n.t=i),n},{e:void 0,t:void 0}),t})()}),N),v(N,t(r,{get when(){return g()},get children(){var t=Tn();return w(t,`click`,e.onAccept,!0),v(t,()=>f()===`apply`?`Accepting…`:`Accept as new revision`),u(e=>{var n=!!f(),r=f()===`apply`;return n!==e.e&&(t.disabled=e.e=n),r!==e.t&&x(t,`aria-busy`,e.t=r),e},{e:void 0,t:void 0}),t}}),null),v(N,t(r,{get when(){return y()},get children(){var t=En();return w(t,`click`,e.onRerequest,!0),u(()=>t.disabled=!!f()||e.state.sending),t}}),null),v(N,t(r,{get when(){return W(i())},get children(){var t=Dn();return w(t,`click`,e.onCancel,!0),v(t,()=>f()===`cancel`?`Cancelling…`:`Cancel`),u(e=>{var n=!!f(),r=f()===`cancel`;return n!==e.e&&(t.disabled=e.e=n),r!==e.t&&x(t,`aria-busy`,e.t=r),e},{e:void 0,t:void 0}),t}}),null),v(N,t(r,{get when(){return E(()=>!!e.onContinue)()&&i().handler.sessionID},get children(){var t=On();return t.$$click=()=>e.onContinue?.(i()),t}}),null),u(e=>{var t=i().id,n=i().state,r=`${Gn(i())}: ${i().instruction}`,o=`aai-status ${s().tone}`;return t!==e.e&&x(a,`data-job`,e.e=t),n!==e.t&&x(a,`data-state`,e.t=n),r!==e.a&&x(a,`aria-label`,e.a=r),o!==e.o&&M(A,e.o=o),e},{e:void 0,t:void 0,a:void 0,o:void 0}),a})()}_([`click`,`keydown`,`input`]);var Yn={rows:1e3,columns:50,cellChars:2e3};function Xn(e){let t=e.length>Yn.columns,n=e.slice(0,Yn.columns).map(e=>i(e)),r=[];function i(e){return typeof e==`string`&&e.length>Yn.cellChars?(t=!0,e.slice(0,Yn.cellChars)):e}return{add(e,a){return r.length>=Yn.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 Zn(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<=Yn.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,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ArtifactPage-CSotAWob.js","assets/ui-Qo2Pd9-O.js","assets/index-6mdQ7eUY.js","assets/pane-layout-Csk-vPNe.js","assets/plural-Bspvoqfq.js","assets/index-C5OmwA1y.css","assets/ArtifactWorkbench-CkmWnP6L.js","assets/source-BFLJQ43_.js","assets/ArtifactWorkbench-9eTj1CeW.css"])))=>i.map(i=>d[i]);
2
- import{At as e,Bt as t,C as n,Ct as r,Et as i,Lt as a,Mt as o,Nt as s,Ot as c,Pt as l,S as u,Tt as d,Wt as f,dt as p,ft as m,ht as h,lt as g,pt as _,u as v,yt as y}from"./ui-Qo2Pd9-O.js";import{F as b,I as x,L as S,j as C,t as w,z as T}from"./index-6mdQ7eUY.js";import{a as E,c as D,i as O,l as k,n as A,o as j,r as M,s as N,t as P}from"./source-BFLJQ43_.js";var F=y(`<p class="lib-intro muted">Everything your sessions made, across workspaces.`),I=y(`<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`),L=y(`<p class=muted role=status>Loading artifacts…`),R=y(`<option>`),z=y(`<p class="lib-note err"role=alert> <button type=button class="btn small">Retry`),B=y(`<p class=lib-note>`),V=y(`<ul class=lib-list aria-label=Artifacts>`),H=y(`<p class="lib-note err"role=alert>`),U=y(`<button type=button class="btn lib-more">Load more`),W=y(`<p class=lib-desc>`),G=y(`<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>`),K=t(()=>C(()=>import(`./ArtifactPage-CSotAWob.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8]))),q={markdown:`Markdown`,code:`Code`,image:`Image`,table:`Table`,chart:`Chart`,dashboard:`Dashboard`,html:`HTML`,app:`App`,file:`File`};function J(t){return e(i,{get when(){return t.rest[0]},keyed:!0,get fallback(){return e(X,{})},children:t=>e(K,{id:t})})}var Y=(e,t)=>e.workspace===t.workspace&&e.type===t.type;function X(){let t=s(()=>N(u().search),void 0,{equals:Y}),[p,g]=a({status:`loading`}),v=O(P,g);o(()=>v.load(t()));let[y,b]=a(new Map);f(()=>void A().then(e=>b(new Map(e.map(e=>[e.id,e.title])))));let x=e=>n(`/artifacts${j({...t(),...e})}`),S=s(()=>{let e=new Set(y().keys()),n=p();if(n.status===`ready`)for(let t of n.items)t.workspaceID&&e.add(t.workspaceID);let r=t().workspace;return r&&r!==`none`&&e.add(r),[...e].map(e=>({id:e,label:D(e,y())}))}),C=()=>{let e=p();return e.status===`error`&&e.error.kind!==`error`};return e(w,{title:`Artifacts`,get children(){return[F(),e(i,{get when(){return!C()},get children(){var n=I(),i=n.firstChild,a=i.firstChild.nextSibling,o=a.firstChild,s=o.nextSibling,c=i.nextSibling.firstChild.nextSibling,u=c.firstChild;return a.addEventListener(`change`,e=>x({workspace:e.currentTarget.value})),m(a,e(r,{get each(){return S()},children:e=>(()=>{var n=R();return m(n,()=>e.label),l(()=>n.selected=t().workspace===e.id),l(()=>n.value=e.id),n})()}),null),c.addEventListener(`change`,e=>x({type:e.currentTarget.value})),m(c,e(r,{get each(){return[...k]},children:e=>(()=>{var n=R();return n.value=e,m(n,()=>q[e]),l(()=>n.selected=t().type===e),n})()}),null),l(e=>{var n=t().workspace===``,r=t().workspace===`none`,i=t().type===``;return n!==e.e&&(o.selected=e.e=n),r!==e.t&&(s.selected=e.t=r),i!==e.a&&(u.selected=e.a=i),e},{e:void 0,t:void 0,a:void 0}),n}}),e(c,{get children(){return[e(d,{get when(){return p().status===`loading`},get children(){return L()}}),e(d,{get when(){return _(()=>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 m(e,()=>n().text),e})()},get children(){var e=z(),t=e.firstChild,r=t.nextSibling;return m(e,()=>n().text,t),r.$$click=()=>v.reload(),e}})}}),e(d,{get when(){return _(()=>p().status===`ready`)()&&p()},children:n=>{let a=()=>n();return[e(i,{get when(){return a().items.length},get fallback(){return(()=>{var e=B();return m(e,()=>E(t(),a().more)),e})()},get children(){var t=V();return m(t,e(r,{get each(){return a().items},children:t=>e(Q,{item:t,get names(){return y()}})})),t}}),e(i,{get when(){return a().moreError},get children(){var e=H();return m(e,()=>a().moreError),e}}),e(i,{get when(){return a().more},get children(){var e=U();return e.$$click=()=>v.more(),l(t=>{var n=a().loadingMore,r=a().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}})]}})]}})]}})}function Z(e,t){return e.workspaceID?D(e.workspaceID,t):`Private`}function Q(t){let n=()=>t.item;return(()=>{var r=G(),a=r.firstChild,o=a.nextSibling,s=o.nextSibling.firstChild,c=s.nextSibling,u=c.nextSibling;return g(r,`dragend`,b),r.addEventListener(`dragstart`,e=>x(e,{target:{artifactID:n().id},label:n().title||`Untitled`})),m(a,()=>n().title||`Untitled`),o.$$click=()=>T(n().id),m(s,()=>q[n().kind]),m(c,()=>Z(n(),t.names)),m(u,()=>v(n().updatedAt)),m(r,e(i,{get when(){return n().description},get children(){var e=W();return m(e,()=>n().description),e}}),null),l(e=>{var t=n().id,i=!S(),s=M(n().id),c=`Open ${n().title||`Untitled`} in a pane`;return t!==e.e&&h(r,`data-artifact`,e.e=t),i!==e.t&&h(r,`draggable`,e.t=i),s!==e.a&&h(a,`href`,e.a=s),c!==e.o&&h(o,`aria-label`,e.o=c),e},{e:void 0,t:void 0,a:void 0,o:void 0}),r})()}p([`click`]);export{J as default};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ArtifactPage-Cb1DcrQf.js","assets/ui-Qo2Pd9-O.js","assets/index-DifgVuKS.js","assets/pane-layout-Csk-vPNe.js","assets/plural-Bspvoqfq.js","assets/index-DVSkeAvn.css","assets/ArtifactWorkbench-C37tZZ3e.js","assets/source-BFLJQ43_.js","assets/ArtifactWorkbench-9eTj1CeW.css"])))=>i.map(i=>d[i]);
2
+ import{At as e,Bt as t,C as n,Ct as r,Et as i,Lt as a,Mt as o,Nt as s,Ot as c,Pt as l,S as u,Tt as d,Wt as f,dt as p,ft as m,ht as h,lt as g,pt as _,u as v,yt as y}from"./ui-Qo2Pd9-O.js";import{F as b,I as x,L as S,j as C,t as w,z as T}from"./index-DifgVuKS.js";import{a as E,c as D,i as O,l as k,n as A,o as j,r as M,s as N,t as P}from"./source-BFLJQ43_.js";var F=y(`<p class="lib-intro muted">Everything your sessions made, across workspaces.`),I=y(`<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`),L=y(`<p class=muted role=status>Loading artifacts…`),R=y(`<option>`),z=y(`<p class="lib-note err"role=alert> <button type=button class="btn small">Retry`),B=y(`<p class=lib-note>`),V=y(`<ul class=lib-list aria-label=Artifacts>`),H=y(`<p class="lib-note err"role=alert>`),U=y(`<button type=button class="btn lib-more">Load more`),W=y(`<p class=lib-desc>`),G=y(`<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>`),K=t(()=>C(()=>import(`./ArtifactPage-Cb1DcrQf.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8]))),q={markdown:`Markdown`,code:`Code`,image:`Image`,table:`Table`,chart:`Chart`,dashboard:`Dashboard`,html:`HTML`,app:`App`,file:`File`};function J(t){return e(i,{get when(){return t.rest[0]},keyed:!0,get fallback(){return e(X,{})},children:t=>e(K,{id:t})})}var Y=(e,t)=>e.workspace===t.workspace&&e.type===t.type;function X(){let t=s(()=>N(u().search),void 0,{equals:Y}),[p,g]=a({status:`loading`}),v=O(P,g);o(()=>v.load(t()));let[y,b]=a(new Map);f(()=>void A().then(e=>b(new Map(e.map(e=>[e.id,e.title])))));let x=e=>n(`/artifacts${j({...t(),...e})}`),S=s(()=>{let e=new Set(y().keys()),n=p();if(n.status===`ready`)for(let t of n.items)t.workspaceID&&e.add(t.workspaceID);let r=t().workspace;return r&&r!==`none`&&e.add(r),[...e].map(e=>({id:e,label:D(e,y())}))}),C=()=>{let e=p();return e.status===`error`&&e.error.kind!==`error`};return e(w,{title:`Artifacts`,get children(){return[F(),e(i,{get when(){return!C()},get children(){var n=I(),i=n.firstChild,a=i.firstChild.nextSibling,o=a.firstChild,s=o.nextSibling,c=i.nextSibling.firstChild.nextSibling,u=c.firstChild;return a.addEventListener(`change`,e=>x({workspace:e.currentTarget.value})),m(a,e(r,{get each(){return S()},children:e=>(()=>{var n=R();return m(n,()=>e.label),l(()=>n.selected=t().workspace===e.id),l(()=>n.value=e.id),n})()}),null),c.addEventListener(`change`,e=>x({type:e.currentTarget.value})),m(c,e(r,{get each(){return[...k]},children:e=>(()=>{var n=R();return n.value=e,m(n,()=>q[e]),l(()=>n.selected=t().type===e),n})()}),null),l(e=>{var n=t().workspace===``,r=t().workspace===`none`,i=t().type===``;return n!==e.e&&(o.selected=e.e=n),r!==e.t&&(s.selected=e.t=r),i!==e.a&&(u.selected=e.a=i),e},{e:void 0,t:void 0,a:void 0}),n}}),e(c,{get children(){return[e(d,{get when(){return p().status===`loading`},get children(){return L()}}),e(d,{get when(){return _(()=>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 m(e,()=>n().text),e})()},get children(){var e=z(),t=e.firstChild,r=t.nextSibling;return m(e,()=>n().text,t),r.$$click=()=>v.reload(),e}})}}),e(d,{get when(){return _(()=>p().status===`ready`)()&&p()},children:n=>{let a=()=>n();return[e(i,{get when(){return a().items.length},get fallback(){return(()=>{var e=B();return m(e,()=>E(t(),a().more)),e})()},get children(){var t=V();return m(t,e(r,{get each(){return a().items},children:t=>e(Q,{item:t,get names(){return y()}})})),t}}),e(i,{get when(){return a().moreError},get children(){var e=H();return m(e,()=>a().moreError),e}}),e(i,{get when(){return a().more},get children(){var e=U();return e.$$click=()=>v.more(),l(t=>{var n=a().loadingMore,r=a().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}})]}})]}})]}})}function Z(e,t){return e.workspaceID?D(e.workspaceID,t):`Private`}function Q(t){let n=()=>t.item;return(()=>{var r=G(),a=r.firstChild,o=a.nextSibling,s=o.nextSibling.firstChild,c=s.nextSibling,u=c.nextSibling;return g(r,`dragend`,b),r.addEventListener(`dragstart`,e=>x(e,{target:{artifactID:n().id},label:n().title||`Untitled`})),m(a,()=>n().title||`Untitled`),o.$$click=()=>T(n().id),m(s,()=>q[n().kind]),m(c,()=>Z(n(),t.names)),m(u,()=>v(n().updatedAt)),m(r,e(i,{get when(){return n().description},get children(){var e=W();return m(e,()=>n().description),e}}),null),l(e=>{var t=n().id,i=!S(),s=M(n().id),c=`Open ${n().title||`Untitled`} in a pane`;return t!==e.e&&h(r,`data-artifact`,e.e=t),i!==e.t&&h(r,`draggable`,e.t=i),s!==e.a&&h(a,`href`,e.a=s),c!==e.o&&h(o,`aria-label`,e.o=c),e},{e:void 0,t:void 0,a:void 0,o:void 0}),r})()}p([`click`]);export{J as default};