@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.
- package/CHANGELOG.md +38 -0
- package/package.json +1 -1
- package/packages/claude-code/package.json +1 -1
- package/packages/cli/dist/hub-cli.js +6 -6
- package/packages/cli/package.json +1 -1
- package/packages/codex/package.json +1 -1
- package/packages/node/package.json +1 -1
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/src/index.ts +7 -2
- 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/registry.ts +93 -22
- package/src/index.ts +28 -0
- package/src/spoke/spoke.ts +150 -10
- package/src/status.ts +70 -14
- package/web/dist/assets/{ArtifactPage-CSotAWob.js → ArtifactPage-Cb1DcrQf.js} +1 -1
- package/web/dist/assets/{ArtifactPane-DPHjiWce.js → ArtifactPane-XTnwXl-Y.js} +1 -1
- package/web/dist/assets/{ArtifactWorkbench-CkmWnP6L.js → ArtifactWorkbench-C37tZZ3e.js} +1 -1
- package/web/dist/assets/{Library-DTLEyekn.js → Library-CZSSHvOJ.js} +2 -2
- package/web/dist/assets/{ProfilesDestination-GriuOpiZ.js → ProfilesDestination-dZa3vioh.js} +1 -1
- package/web/dist/assets/{TeamsPage-C-5lYeeM.js → TeamsPage-DJt-Kk84.js} +1 -1
- package/web/dist/assets/{Watchtower-DOlPsiIy.js → Watchtower-BXaUaXO1.js} +2 -2
- package/web/dist/assets/{index-C5OmwA1y.css → index-DVSkeAvn.css} +1 -1
- package/web/dist/assets/{index-6mdQ7eUY.js → index-DifgVuKS.js} +22 -22
- package/web/dist/assets/{live-CDWcyavI.js → live-D-RZbeUi.js} +1 -1
- package/web/dist/assets/{renderer2d-CNFdTDTr.js → renderer2d-DILxLFEq.js} +1 -1
- package/web/dist/assets/{renderer3d-C45jPvYX.js → renderer3d-PvN9Qbt2.js} +1 -1
- package/web/dist/assets/{safe-area-sA9a8vYJ.js → safe-area-BS6ii3M7.js} +1 -1
- package/web/dist/index.html +2 -2
package/src/spoke/spoke.ts
CHANGED
|
@@ -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
|
-
|
|
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: [
|
|
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
|
-
/**
|
|
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 =
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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};
|