buckyos 0.7.138 → 0.7.142

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 (91) hide show
  1. package/cli/core/app.ts +4 -0
  2. package/cli/core/auth.ts +2 -3
  3. package/cli/dist/cli.mjs +547 -127
  4. package/cli/dist/cli.mjs.map +1 -1
  5. package/cli/modules/aiws.ts +294 -0
  6. package/cli/modules/executor.ts +98 -0
  7. package/cli/version.ts +1 -1
  8. package/dist/account.d.ts +0 -2
  9. package/dist/account.d.ts.map +1 -1
  10. package/dist/aiworkspace_client.d.ts +91 -0
  11. package/dist/aiworkspace_client.d.ts.map +1 -0
  12. package/dist/app-frame.cjs +1 -1
  13. package/dist/app-frame.cjs.map +1 -1
  14. package/dist/app-frame.d.ts +103 -3
  15. package/dist/app-frame.d.ts.map +1 -1
  16. package/dist/app-frame.mjs +189 -8
  17. package/dist/app-frame.mjs.map +1 -1
  18. package/dist/browser.cjs +1 -1
  19. package/dist/browser.cjs.map +1 -1
  20. package/dist/browser.d.ts +2 -0
  21. package/dist/browser.d.ts.map +1 -1
  22. package/dist/browser.mjs +18 -15
  23. package/dist/browser.mjs.map +1 -1
  24. package/dist/content.cjs +1 -1
  25. package/dist/content.cjs.map +1 -1
  26. package/dist/content.d.ts +18 -0
  27. package/dist/content.d.ts.map +1 -1
  28. package/dist/content.mjs +61 -1
  29. package/dist/content.mjs.map +1 -1
  30. package/dist/executor_client-b3ff97ba.js +13 -0
  31. package/dist/executor_client-b3ff97ba.js.map +1 -0
  32. package/dist/{ndm_proxy-6b03b9ec.mjs → executor_client-eb372968.mjs} +901 -396
  33. package/dist/executor_client-eb372968.mjs.map +1 -0
  34. package/dist/executor_client.d.ts +138 -0
  35. package/dist/executor_client.d.ts.map +1 -0
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.ts +4 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.mjs +23 -15
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/internal/hash_worker.d.ts +2 -1
  43. package/dist/internal/hash_worker.d.ts.map +1 -1
  44. package/dist/internal/tus_client.d.ts +3 -0
  45. package/dist/internal/tus_client.d.ts.map +1 -1
  46. package/dist/namelib.d.ts +1 -10
  47. package/dist/namelib.d.ts.map +1 -1
  48. package/dist/ndm_client.d.ts +56 -7
  49. package/dist/ndm_client.d.ts.map +1 -1
  50. package/dist/ndn_types-08dc9ef1.js +2 -0
  51. package/dist/ndn_types-08dc9ef1.js.map +1 -0
  52. package/dist/{ndn_types-ac9c1e48.mjs → ndn_types-bbb1f6a6.mjs} +53 -100
  53. package/dist/ndn_types-bbb1f6a6.mjs.map +1 -0
  54. package/dist/nfsp.cjs +1 -1
  55. package/dist/nfsp.cjs.map +1 -1
  56. package/dist/nfsp.d.ts +16 -0
  57. package/dist/nfsp.d.ts.map +1 -1
  58. package/dist/nfsp.mjs +6 -0
  59. package/dist/nfsp.mjs.map +1 -1
  60. package/dist/node.cjs +1 -1
  61. package/dist/node.cjs.map +1 -1
  62. package/dist/node.d.ts +2 -0
  63. package/dist/node.d.ts.map +1 -1
  64. package/dist/node.mjs +18 -15
  65. package/dist/node.mjs.map +1 -1
  66. package/dist/provision.cjs +2 -2
  67. package/dist/provision.cjs.map +1 -1
  68. package/dist/provision.mjs +18 -12
  69. package/dist/provision.mjs.map +1 -1
  70. package/dist/provision_activate.d.ts.map +1 -1
  71. package/dist/runtime.d.ts +3 -4
  72. package/dist/runtime.d.ts.map +1 -1
  73. package/dist/sdk_core.d.ts +4 -0
  74. package/dist/sdk_core.d.ts.map +1 -1
  75. package/dist/{tus_client-2b915a81.js → tus_client-65c5fc5e.js} +4 -4
  76. package/dist/tus_client-65c5fc5e.js.map +1 -0
  77. package/dist/{tus_client-19baa342.mjs → tus_client-d313689e.mjs} +40 -2
  78. package/dist/tus_client-d313689e.mjs.map +1 -0
  79. package/dist/types.d.ts +0 -9
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/verify-hub-client.d.ts +1 -9
  82. package/dist/verify-hub-client.d.ts.map +1 -1
  83. package/package.json +1 -1
  84. package/dist/ndm_proxy-67651066.js +0 -13
  85. package/dist/ndm_proxy-67651066.js.map +0 -1
  86. package/dist/ndm_proxy-6b03b9ec.mjs.map +0 -1
  87. package/dist/ndn_types-324121ae.js +0 -2
  88. package/dist/ndn_types-324121ae.js.map +0 -1
  89. package/dist/ndn_types-ac9c1e48.mjs.map +0 -1
  90. package/dist/tus_client-19baa342.mjs.map +0 -1
  91. package/dist/tus_client-2b915a81.js.map +0 -1
@@ -0,0 +1,294 @@
1
+ import type { CommandDefinition, CommandModule, JsonSchema, OptionDefinition, PositionalDefinition } from '../core/command.ts'
2
+ import type { CommandContext } from '../core/context.ts'
3
+ import { ToolError, UsageError } from '../core/errors.ts'
4
+ import { callService, expectObject, inputString, requiredInputString } from '../core/service.ts'
5
+ import { getHost } from '../runtime/host.ts'
6
+
7
+ // AI Workspace (`/kapi/aiworkspace`): reading a workspace, and the executor protocol of a wish run
8
+ // (内核架构改进 M3): claim → heartbeat → report. Source of truth for the methods:
9
+ // buckyos/src/frame/aiworkspace/README.md (Protocol).
10
+ const SERVICE = 'aiworkspace'
11
+ const OBJECT_OUTPUT: JsonSchema = { type: 'object', additionalProperties: true }
12
+ const WORKSPACE_OPTION: OptionDefinition = { name: 'workspace', property: 'workspace_id', description: 'Workspace id (ws_…)', type: 'string', required: true }
13
+ const RUN_OPTION: OptionDefinition = { name: 'run', property: 'run_id', description: 'Run id (run_…)', type: 'string', required: true }
14
+ const ATTEMPT_OPTION: OptionDefinition = { name: 'attempt', property: 'attempt', description: 'The attempt number `run-claim` answered', type: 'integer', required: true }
15
+
16
+ function workspaceInput(extra: Record<string, JsonSchema>, required: string[] = []): JsonSchema {
17
+ return { type: 'object', properties: { workspace_id: { type: 'string', minLength: 1 }, ...extra }, required: ['workspace_id', ...required], additionalProperties: false }
18
+ }
19
+
20
+ async function aiws(ctx: CommandContext, method: string, params: Record<string, unknown>): Promise<Record<string, unknown>> {
21
+ const result = expectObject(await callService<unknown>(ctx, SERVICE, method, params), method)
22
+ if (result.ok === false) {
23
+ const error = expectObject(result.error, `${method}.error`)
24
+ const code = typeof error.code === 'string' ? error.code : 'AIWS_ERROR'
25
+ const detail = typeof error.detail === 'string' ? error.detail : code
26
+ throw new ToolError(code, `${code}${typeof error.sub_code === 'string' ? `/${error.sub_code}` : ''}: ${detail}`)
27
+ }
28
+ return result
29
+ }
30
+
31
+ async function jsonInput(input: Record<string, unknown>, textKey: string, fileKey: string, label: string): Promise<unknown> {
32
+ const text = inputString(input, textKey)
33
+ const file = inputString(input, fileKey)
34
+ if (text && file) throw new UsageError('AIWS_USAGE', `${textKey} and ${fileKey} are exclusive`)
35
+ if (file) return JSON.parse(await getHost().readTextFile(file)) as unknown
36
+ if (text) return JSON.parse(text) as unknown
37
+ throw new UsageError('AIWS_USAGE', `${label}: pass --${textKey.replace(/_/g, '-')} or --${fileKey.replace(/_/g, '-')}`)
38
+ }
39
+
40
+ const readCommand: CommandDefinition = {
41
+ verb: 'read',
42
+ summary: 'Read one entity of a workspace (envelope and content)',
43
+ positionals: [{ name: 'entity_id', description: 'Entity id', required: true } satisfies PositionalDefinition],
44
+ options: [WORKSPACE_OPTION, { name: 'selector', property: 'selector', description: 'Selector JSON, e.g. {"kind":"table_record","record_id":"r1"}', type: 'string' }],
45
+ inputSchema: workspaceInput({ entity_id: { type: 'string', minLength: 1 }, selector: { type: 'string' } }, ['entity_id']),
46
+ outputSchema: OBJECT_OUTPUT,
47
+ resultSchemaVersion: 1,
48
+ access: { mode: 'fixed', level: 'read' },
49
+ asyncMode: 'sync',
50
+ requiresSession: true,
51
+ examples: ['buckyos aiws read orders --workspace ws_abc'],
52
+ handler: (ctx, input) => {
53
+ const selector = inputString(input, 'selector')
54
+ return aiws(ctx, 'doc.read', { workspace_id: requiredInputString(input, 'workspace_id'), entity_id: requiredInputString(input, 'entity_id'), ...(selector ? { selector: JSON.parse(selector) } : {}) })
55
+ },
56
+ }
57
+
58
+ const queryCommand: CommandDefinition = {
59
+ verb: 'query',
60
+ summary: 'Query the rows of a table (or through a saved view)',
61
+ options: [
62
+ WORKSPACE_OPTION,
63
+ { name: 'source', property: 'source_id', description: 'Table entity id', type: 'string' },
64
+ { name: 'view', property: 'view_id', description: 'Table view (Block) id', type: 'string' },
65
+ { name: 'filter', property: 'filter', description: 'Filter JSON (README: doc.query)', type: 'string' },
66
+ { name: 'limit', property: 'limit', description: 'Rows per page (≤ 1000)', type: 'integer' },
67
+ { name: 'cursor', property: 'cursor', description: 'Continue from a previous page', type: 'string' },
68
+ ],
69
+ inputSchema: workspaceInput({ source_id: { type: 'string' }, view_id: { type: 'string' }, filter: { type: 'string' }, limit: { type: 'integer' }, cursor: { type: 'string' } }),
70
+ outputSchema: OBJECT_OUTPUT,
71
+ resultSchemaVersion: 1,
72
+ access: { mode: 'fixed', level: 'read' },
73
+ asyncMode: 'sync',
74
+ requiresSession: true,
75
+ examples: ['buckyos aiws query --workspace ws_abc --source orders --limit 100'],
76
+ handler: (ctx, input) => {
77
+ const params: Record<string, unknown> = { workspace_id: requiredInputString(input, 'workspace_id') }
78
+ for (const key of ['source_id', 'view_id', 'cursor']) { const value = inputString(input, key); if (value) params[key] = value }
79
+ const filter = inputString(input, 'filter')
80
+ if (filter) params.filter = JSON.parse(filter)
81
+ if (typeof input.limit === 'number') params.limit = input.limit
82
+ if (!params.source_id && !params.view_id) throw new UsageError('AIWS_USAGE', 'pass --source or --view')
83
+ return aiws(ctx, 'doc.query', params)
84
+ },
85
+ }
86
+
87
+ const infoCommand: CommandDefinition = {
88
+ verb: 'info',
89
+ summary: 'Workspace info: versions, capabilities of the caller, usage, hosted execution configuration',
90
+ options: [WORKSPACE_OPTION],
91
+ inputSchema: workspaceInput({}),
92
+ outputSchema: OBJECT_OUTPUT,
93
+ resultSchemaVersion: 1,
94
+ access: { mode: 'fixed', level: 'read' },
95
+ asyncMode: 'sync',
96
+ requiresSession: true,
97
+ examples: ['buckyos aiws info --workspace ws_abc'],
98
+ handler: (ctx, input) => aiws(ctx, 'ws.get_info', { workspace_id: requiredInputString(input, 'workspace_id') }),
99
+ }
100
+
101
+ const runGetCommand: CommandDefinition = {
102
+ verb: 'run-get',
103
+ summary: 'A wish run: state, execution context, the brief an executor starts from, candidate and preview',
104
+ options: [WORKSPACE_OPTION, RUN_OPTION],
105
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 } }, ['run_id']),
106
+ outputSchema: OBJECT_OUTPUT,
107
+ resultSchemaVersion: 1,
108
+ access: { mode: 'fixed', level: 'read' },
109
+ asyncMode: 'sync',
110
+ requiresSession: true,
111
+ examples: ['buckyos aiws run-get --workspace ws_abc --run run_xyz'],
112
+ handler: (ctx, input) => aiws(ctx, 'proc.get', { workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id') }),
113
+ }
114
+
115
+ const runClaimCommand: CommandDefinition = {
116
+ verb: 'run-claim',
117
+ summary: 'Take a run as its executor: starts an attempt, answers the attempt number, a run token and the lease',
118
+ options: [WORKSPACE_OPTION, RUN_OPTION, { name: 'claim-token', property: 'claim_token', description: 'The claim token the run was dispatched with (ct_…)', type: 'string', required: true, secret: true }],
119
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 }, claim_token: { type: 'string', minLength: 1 } }, ['run_id', 'claim_token']),
120
+ outputSchema: OBJECT_OUTPUT,
121
+ resultSchemaVersion: 1,
122
+ access: { mode: 'fixed', level: 'write' },
123
+ asyncMode: 'sync',
124
+ requiresSession: true,
125
+ examples: ['buckyos aiws run-claim --workspace ws_abc --run run_xyz --claim-token ct_…'],
126
+ handler: (ctx, input) => aiws(ctx, 'proc.claim', {
127
+ workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id'), claim_token: requiredInputString(input, 'claim_token'),
128
+ executor: { kind: 'agent', principal: ctx.principal.id },
129
+ }),
130
+ }
131
+
132
+ const runHeartbeatCommand: CommandDefinition = {
133
+ verb: 'run-heartbeat',
134
+ summary: 'Keep the lease of a claimed run alive (every minute while working); optionally report progress',
135
+ options: [WORKSPACE_OPTION, RUN_OPTION, ATTEMPT_OPTION, { name: 'phase', property: 'phase', description: 'A short progress phase, e.g. "reading inputs"', type: 'string' }],
136
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 }, attempt: { type: 'integer', minimum: 1 }, phase: { type: 'string' } }, ['run_id', 'attempt']),
137
+ outputSchema: OBJECT_OUTPUT,
138
+ resultSchemaVersion: 1,
139
+ access: { mode: 'fixed', level: 'write' },
140
+ asyncMode: 'sync',
141
+ requiresSession: true,
142
+ examples: ['buckyos aiws run-heartbeat --workspace ws_abc --run run_xyz --attempt 1 --phase "reading inputs"'],
143
+ handler: (ctx, input) => {
144
+ const phase = inputString(input, 'phase')
145
+ return aiws(ctx, 'proc.heartbeat', { workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id'), attempt: input.attempt, ...(phase ? { progress: { phase } } : {}) })
146
+ },
147
+ }
148
+
149
+ const runFilesCommand: CommandDefinition = {
150
+ verb: 'run-files',
151
+ summary: 'Write the stage of a claimed run into a directory: the snapshot (context/), request.json, the Renderer catalog and the program host (lib/)',
152
+ description: 'Run the program there the way the service does: `deno run -A lib/run.js` reads program/main.js and writes output/.aiws/results.json.',
153
+ options: [WORKSPACE_OPTION, RUN_OPTION, ATTEMPT_OPTION, { name: 'dir', property: 'dir', description: 'Directory to write into (created)', type: 'string', required: true }],
154
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 }, attempt: { type: 'integer', minimum: 1 }, dir: { type: 'string', minLength: 1 } }, ['run_id', 'attempt', 'dir']),
155
+ outputSchema: { type: 'object', properties: { dir: { type: 'string' }, files: { type: 'array', items: { type: 'string' } } }, required: ['dir', 'files'], additionalProperties: true },
156
+ resultSchemaVersion: 1,
157
+ access: { mode: 'fixed', level: 'read' },
158
+ asyncMode: 'sync',
159
+ requiresSession: true,
160
+ examples: ['buckyos aiws run-files --workspace ws_abc --run run_xyz --attempt 1 --dir work'],
161
+ handler: async (ctx, input) => {
162
+ const result = await aiws(ctx, 'proc.files', { workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id'), attempt: input.attempt })
163
+ const dir = requiredInputString(input, 'dir')
164
+ const host = getHost()
165
+ const written: string[] = []
166
+ for (const [path, file] of Object.entries(expectObject(result.files, 'proc.files.files'))) {
167
+ const f = expectObject(file, path)
168
+ if (typeof f.text !== 'string' && typeof f.base64 !== 'string') continue
169
+ const target = `${dir}/${path}`
170
+ await host.mkdir(target.slice(0, target.lastIndexOf('/')), { recursive: true })
171
+ if (typeof f.text === 'string') await host.writeTextFile(target, f.text)
172
+ else await host.writeFile(target, Uint8Array.from(atob(f.base64 as string), (c) => c.charCodeAt(0)))
173
+ written.push(path)
174
+ }
175
+ await host.mkdir(`${dir}/output`, { recursive: true })
176
+ await host.mkdir(`${dir}/program`, { recursive: true })
177
+ return { dir, files: written }
178
+ },
179
+ }
180
+
181
+ const runToolCommand: CommandDefinition = {
182
+ verb: 'run-tool',
183
+ summary: 'Call one stage tool of a claimed run (ws_profile, ws_read, ws_query, submit_analysis, put_result, check_results, finish, …): the service answers as it answers the model',
184
+ options: [WORKSPACE_OPTION, RUN_OPTION, ATTEMPT_OPTION, { name: 'name', property: 'name', description: 'Tool name (the claim answered the list, with their argument schemas)', type: 'string', required: true }, { name: 'args', property: 'args', description: 'Arguments JSON', type: 'string' }, { name: 'args-file', property: 'args_file', description: 'Path of a JSON file holding the arguments', type: 'string' }],
185
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 }, attempt: { type: 'integer', minimum: 1 }, name: { type: 'string', minLength: 1 }, args: { type: 'string' }, args_file: { type: 'string' } }, ['run_id', 'attempt', 'name']),
186
+ outputSchema: OBJECT_OUTPUT,
187
+ resultSchemaVersion: 1,
188
+ access: { mode: 'fixed', level: 'write' },
189
+ asyncMode: 'sync',
190
+ requiresSession: true,
191
+ examples: ['buckyos aiws run-tool --workspace ws_abc --run run_xyz --attempt 1 --name ws_profile --args \'{"target":"@B1"}\'', 'buckyos aiws run-tool --workspace ws_abc --run run_xyz --attempt 1 --name finish --args \'{"summary":"done"}\''],
192
+ handler: async (ctx, input) => {
193
+ const args = inputString(input, 'args') || inputString(input, 'args_file') ? await jsonInput(input, 'args', 'args_file', 'arguments') : {}
194
+ return aiws(ctx, 'proc.tool', { workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id'), attempt: input.attempt, name: requiredInputString(input, 'name'), args })
195
+ },
196
+ }
197
+
198
+ const runProgramCommand: CommandDefinition = {
199
+ verb: 'run-program',
200
+ summary: 'Hand in a program run: the program source, what lib/run.js wrote to output/.aiws/results.json, the files under output/ and the log; the service validates it like its own run_program',
201
+ options: [
202
+ WORKSPACE_OPTION, RUN_OPTION, ATTEMPT_OPTION,
203
+ { name: 'dir', property: 'dir', description: 'The stage directory written by run-files (program/main.js, output/)', type: 'string', required: true },
204
+ { name: 'log-file', property: 'log_file', description: 'Path of the program log to attach (stdout/stderr of deno run)', type: 'string' },
205
+ ],
206
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 }, attempt: { type: 'integer', minimum: 1 }, dir: { type: 'string', minLength: 1 }, log_file: { type: 'string' } }, ['run_id', 'attempt', 'dir']),
207
+ outputSchema: OBJECT_OUTPUT,
208
+ resultSchemaVersion: 1,
209
+ access: { mode: 'fixed', level: 'write' },
210
+ asyncMode: 'sync',
211
+ requiresSession: true,
212
+ examples: ['buckyos aiws run-program --workspace ws_abc --run run_xyz --attempt 1 --dir work --log-file work/run.log'],
213
+ handler: async (ctx, input) => {
214
+ const dir = requiredInputString(input, 'dir')
215
+ const host = getHost()
216
+ const source = await host.readTextFile(`${dir}/program/main.js`)
217
+ let results: unknown = null
218
+ try { results = JSON.parse(await host.readTextFile(`${dir}/output/.aiws/results.json`)) } catch { results = null }
219
+ const logFile = inputString(input, 'log_file')
220
+ const log = logFile ? await host.readTextFile(logFile).catch(() => '') : ''
221
+ const files: Record<string, unknown> = {}
222
+ const walk = async (rel: string) => {
223
+ for (const entry of await host.readDir(`${dir}/output${rel ? `/${rel}` : ''}`)) {
224
+ const name = rel ? `${rel}/${entry.name}` : entry.name
225
+ if (name === '.aiws' || name.startsWith('.aiws/')) continue
226
+ if (entry.isDirectory) await walk(name)
227
+ else {
228
+ const bytes = await host.readFile(`${dir}/output/${name}`)
229
+ let text: string | null = null
230
+ try { text = bytes.includes(0) ? null : new TextDecoder('utf-8', { fatal: true }).decode(bytes) } catch { text = null }
231
+ files[`output/${name}`] = text ?? { base64: btoa(Array.from(bytes, (b) => String.fromCharCode(b)).join('')) }
232
+ }
233
+ }
234
+ }
235
+ await walk('')
236
+ return aiws(ctx, 'proc.program', { workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id'), attempt: input.attempt, source, results, log, files })
237
+ },
238
+ }
239
+
240
+ const runReportCommand: CommandDefinition = {
241
+ verb: 'run-report',
242
+ summary: 'End a claimed run: --finished after the stage tools accepted the work (submit_analysis / finish), or the candidate itself (results / analysis), or a failure',
243
+ description: 'The service validates and plans what is reported; the user confirms it in the workspace. A superseded attempt or a cancelled run gets RUN_REVOKED.',
244
+ options: [
245
+ WORKSPACE_OPTION, RUN_OPTION, ATTEMPT_OPTION,
246
+ { name: 'finished', property: 'finished', description: 'The stage is done: what the tools collected becomes the candidate', type: 'boolean' },
247
+ { name: 'results', property: 'results', description: 'Results JSON array (execute runs): [{ name, type, title?, content, config? }]', type: 'string' },
248
+ { name: 'results-file', property: 'results_file', description: 'Path of a JSON file holding the results array', type: 'string' },
249
+ { name: 'analysis', property: 'analysis', description: 'Analysis JSON (analyze runs, wish.analysis.v2)', type: 'string' },
250
+ { name: 'analysis-file', property: 'analysis_file', description: 'Path of a JSON file holding the analysis', type: 'string' },
251
+ { name: 'summary', property: 'summary', description: 'One paragraph on what was done', type: 'string' },
252
+ { name: 'warning', property: 'warnings', description: 'A warning for the user (repeatable)', type: 'string' },
253
+ { name: 'error', property: 'error', description: 'Report a failure instead: its reason', type: 'string' },
254
+ ],
255
+ inputSchema: workspaceInput({ run_id: { type: 'string', minLength: 1 }, attempt: { type: 'integer', minimum: 1 }, finished: { type: 'boolean' }, results: { type: 'string' }, results_file: { type: 'string' }, analysis: { type: 'string' }, analysis_file: { type: 'string' }, summary: { type: 'string' }, warnings: { type: 'string' }, error: { type: 'string' } }, ['run_id', 'attempt']),
256
+ outputSchema: OBJECT_OUTPUT,
257
+ resultSchemaVersion: 1,
258
+ access: { mode: 'fixed', level: 'write' },
259
+ asyncMode: 'sync',
260
+ requiresSession: true,
261
+ examples: [
262
+ 'buckyos aiws run-report --workspace ws_abc --run run_xyz --attempt 1 --finished',
263
+ 'buckyos aiws run-report --workspace ws_abc --run run_xyz --attempt 1 --results-file out/results.json --summary "monthly totals and a commentary"',
264
+ 'buckyos aiws run-report --workspace ws_abc --run run_xyz --attempt 1 --analysis-file out/analysis.json',
265
+ 'buckyos aiws run-report --workspace ws_abc --run run_xyz --attempt 1 --error "the input table is empty"',
266
+ ],
267
+ handler: async (ctx, input) => {
268
+ const params: Record<string, unknown> = { workspace_id: requiredInputString(input, 'workspace_id'), run_id: requiredInputString(input, 'run_id'), attempt: input.attempt }
269
+ const error = inputString(input, 'error')
270
+ if (error) {
271
+ params.error = { code: 'EXECUTOR_FAILED', detail: error }
272
+ } else if (input.finished === true) {
273
+ params.finished = true
274
+ } else if (inputString(input, 'analysis') || inputString(input, 'analysis_file')) {
275
+ params.analysis = await jsonInput(input, 'analysis', 'analysis_file', 'an analysis')
276
+ } else {
277
+ params.results = await jsonInput(input, 'results', 'results_file', 'results')
278
+ params.read_set = []
279
+ }
280
+ const summary = inputString(input, 'summary')
281
+ if (summary) params.summary = summary
282
+ const warning = inputString(input, 'warnings')
283
+ if (warning) params.warnings = [warning]
284
+ return aiws(ctx, 'proc.report', params)
285
+ },
286
+ }
287
+
288
+ export function createAiwsModule(): CommandModule {
289
+ return {
290
+ name: 'aiws',
291
+ summary: 'AI Workspace: read a workspace, and execute wish runs as their executor (claim, heartbeat, report)',
292
+ commands: [infoCommand, readCommand, queryCommand, runGetCommand, runClaimCommand, runHeartbeatCommand, runFilesCommand, runToolCommand, runProgramCommand, runReportCommand],
293
+ }
294
+ }
@@ -0,0 +1,98 @@
1
+ import { ExecutorCommandStream } from 'buckyos/node'
2
+ import type { CommandDefinition, CommandModule, JsonSchema } from '../core/command.ts'
3
+ import type { CommandContext } from '../core/context.ts'
4
+ import { ToolError } from '../core/errors.ts'
5
+ import { getHost } from '../runtime/host.ts'
6
+
7
+ const text = { type: 'string' as const, minLength: 1 }
8
+ type ExecutorRoute = Parameters<typeof ExecutorCommandStream.connect>[0]
9
+ type ExecutorOperationLocator = Parameters<InstanceType<typeof ExecutorCommandStream>['query']>[0]
10
+ const object = { type: 'object' as const, additionalProperties: true }
11
+ const targetProperties = {
12
+ executor_id: text, generation: { type: 'integer' as const, minimum: 1 },
13
+ profile_id: text, store_id: text, locator: text,
14
+ }
15
+
16
+ function call<T>(ctx: CommandContext, method: string, params: Record<string, unknown>): Promise<T> {
17
+ return ctx.clients.call('control-panel', method, params, {
18
+ traceId: ctx.traceId, signal: ctx.signal, timeoutMs: Math.max(1, (ctx.deadline ?? Date.now() + 30000) - Date.now()),
19
+ })
20
+ }
21
+
22
+ function management(verb: string, method: string, properties: Record<string, JsonSchema>, required: string[], write = false): CommandDefinition {
23
+ return {
24
+ verb, summary: `Executor ${verb}`, inputSchema: { ...object, properties, required, additionalProperties: false },
25
+ outputSchema: object, resultSchemaVersion: 1, access: { mode: 'fixed', level: write ? 'write' : 'read' },
26
+ asyncMode: 'sync', requiresSession: true,
27
+ options: Object.entries(properties).filter(([, schema]) => schema.type !== 'object').map(([name, schema]) => ({
28
+ name: name.replaceAll('_', '-'), property: name, description: name, type: schema.type === 'integer' ? 'integer' as const : 'string' as const,
29
+ required: required.includes(name),
30
+ })),
31
+ handler: (ctx, input) => call(ctx, method, input),
32
+ }
33
+ }
34
+
35
+ export function createExecutorModule(): CommandModule {
36
+ return {
37
+ name: 'executor', summary: 'Manage lightweight devices and explicitly target online command/file executors',
38
+ commands: [
39
+ management('create', 'executor.device.create', { name: text, profiles: object, limits: object, expires_at_ms: { type: 'integer' } }, ['name', 'profiles'], true),
40
+ management('list', 'executor.device.list', {}, []),
41
+ management('issue', 'executor.device.issue', { executor_id: text, expires_at_ms: { type: 'integer' } }, ['executor_id'], true),
42
+ management('revoke', 'executor.device.revoke', { executor_id: text }, ['executor_id'], true),
43
+ management('delete', 'executor.device.delete', { executor_id: text }, ['executor_id'], true),
44
+ management('online', 'executor.online.list', {}, []),
45
+ operation('exec', { cmd: text, cwd: text, env: object, execution_timeout_ms: { type: 'integer', minimum: 1 } }, ['cmd', 'cwd']),
46
+ operation('read', { path: text }, ['path']),
47
+ operation('write', { path: text, content: { type: 'string' }, mode: { type: 'string', enum: ['replace', 'append', 'create_new'] } }, ['path', 'content']),
48
+ operation('edit', { path: text, old_string: text, new_string: { type: 'string' } }, ['path', 'old_string', 'new_string']),
49
+ operation('query', { channel: { type: 'string', enum: ['stdout', 'stderr', 'content'] }, offset: { type: 'integer', minimum: 0 }, wait_ms: { type: 'integer', minimum: 0 } }, []),
50
+ operation('cancel', {}, []),
51
+ ],
52
+ }
53
+ }
54
+
55
+ function operation(verb: string, extra: Record<string, JsonSchema>, required: string[]): CommandDefinition {
56
+ const recovery = verb === 'query' || verb === 'cancel'
57
+ const properties: Record<string, JsonSchema> = { ...targetProperties, ...extra }
58
+ return {
59
+ verb, summary: `${verb} on an explicit executor; persist --locator before dispatch and query it after disconnection`,
60
+ inputSchema: { ...object, properties, required: [...Object.keys(targetProperties), ...required], additionalProperties: false },
61
+ outputSchema: object, resultSchemaVersion: 1,
62
+ access: { mode: 'fixed', level: ['read', 'query'].includes(verb) ? 'read' : 'write' },
63
+ asyncMode: 'sync', requiresSession: true,
64
+ options: Object.entries(properties).filter(([, schema]) => schema.type !== 'object').map(([name, schema]) => ({
65
+ name: name.replaceAll('_', '-'), property: name, description: name,
66
+ type: schema.type === 'integer' ? 'integer' as const : 'string' as const,
67
+ required: Object.keys(targetProperties).includes(name) || required.includes(name),
68
+ })),
69
+ handler: async (ctx, input) => {
70
+ const target = { executor_id: String(input.executor_id), generation: Number(input.generation), profile_id: String(input.profile_id), store_id: String(input.store_id) }
71
+ const path = String(input.locator)
72
+ const host = getHost()
73
+ let locator: ExecutorOperationLocator
74
+ if (recovery) locator = JSON.parse(await host.readTextFile(path))
75
+ else {
76
+ locator = { ...target, op_id: crypto.randomUUID(), run_id: ctx.traceId, call_id: ctx.idempotencyKey ?? crypto.randomUUID() }
77
+ await host.writeTextFile(path, JSON.stringify(locator) + '\n', { createNew: true, mode: 0o600 })
78
+ }
79
+ if (!ctx.session) throw new ToolError('AUTH_REQUIRED', 'An authenticated App session is required')
80
+ const { token } = await ctx.session.ensureValid()
81
+ const route = await call<ExecutorRoute>(ctx, 'executor.stream.open', { executor_id: target.executor_id, generation: target.generation, profile_id: target.profile_id })
82
+ const stream = await ExecutorCommandStream.connect(route, target, token, 'buckyos-cli', locator.run_id)
83
+ if (!stream) throw new ToolError('INVALID_SERVICE_RESPONSE', 'Executor stream did not initialize')
84
+ const abort = () => stream.close()
85
+ ctx.signal.addEventListener('abort', abort, { once: true })
86
+ try {
87
+ let reply
88
+ if (verb === 'exec') reply = await stream.exec(locator, String(input.cmd), String(input.cwd), (input.env ?? {}) as Record<string, string>, Number(input.execution_timeout_ms ?? 60000))
89
+ else if (verb === 'read') reply = await stream.read(locator, String(input.path))
90
+ else if (verb === 'write') reply = await stream.write(locator, String(input.path), new TextEncoder().encode(String(input.content)), (input.mode ?? 'replace') as 'replace' | 'append' | 'create_new')
91
+ else if (verb === 'edit') reply = await stream.edit(locator, String(input.path), [{ old_string: String(input.old_string), new_string: String(input.new_string) }])
92
+ else if (verb === 'cancel') reply = await stream.cancel(locator)
93
+ else reply = await stream.query(locator, input.channel as 'stdout' | 'stderr' | 'content' | undefined, Number(input.offset ?? 0), Number(input.wait_ms ?? 0))
94
+ return { locator, reply }
95
+ } finally { ctx.signal.removeEventListener('abort', abort); stream.close() }
96
+ },
97
+ }
98
+ }
package/cli/version.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // Generated by scripts/generate-cli-version.mjs. Do not edit.
2
- export const PACKAGE_VERSION = '0.7.138'
2
+ export const PACKAGE_VERSION = '0.7.142'
3
3
  export const TOOL_VERSION = PACKAGE_VERSION
4
4
  export const SDK_VERSION = PACKAGE_VERSION
5
5
  export const PROTOCOL_VERSION = '1'
package/dist/account.d.ts CHANGED
@@ -16,7 +16,6 @@ export interface BrowserUserInfo {
16
16
  /** Zone account type as verify-hub returned it; see `ZoneUserType`. */
17
17
  user_type: string;
18
18
  }
19
- export declare const LOGIN_EVENT = "onLogin";
20
19
  export declare function hashPassword(username: string, password: string, nonce?: number | null): string;
21
20
  export declare function cleanLocalAccountInfo(appId: string): void;
22
21
  export declare function saveLocalAccountInfo(appId: string, account_info: AccountInfo): void;
@@ -27,5 +26,4 @@ export declare function clearBrowserUserInfo(): void;
27
26
  export declare function saveBrowserIdentity(identity: unknown): void;
28
27
  export declare function getBrowserIdentityRaw(): unknown;
29
28
  export declare function clearBrowserIdentity(): void;
30
- export declare function getLocalAccountInfo(appId: string): AccountInfo | null;
31
29
  //# sourceMappingURL=account.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../src/account.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;CACrB;AAyED,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,wBAAgB,YAAY,CAAC,QAAQ,EAAC,MAAM,EAAC,QAAQ,EAAC,MAAM,EAAC,KAAK,GAAC,MAAM,GAAC,IAAS,GAAE,MAAM,CAY1F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAC,MAAM,QAiBjD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAC,MAAM,EAAE,YAAY,EAAC,WAAW,QAe1E;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAC,eAAe,QAE3D;AAED,wBAAgB,kBAAkB,IAAG,eAAe,GAAC,IAAI,CAExD;AAED,wBAAgB,oBAAoB,SAEnC;AAED,uGAAuG;AACvG,wBAAgB,mBAAmB,CAAC,QAAQ,EAAC,OAAO,QAEnD;AAED,wBAAgB,qBAAqB,IAAG,OAAO,CAU9C;AAED,wBAAgB,oBAAoB,SAEnC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAC,MAAM,GAAE,WAAW,GAAC,IAAI,CAajE"}
1
+ {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../src/account.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAKD,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;CACrB;AAwCD,wBAAgB,YAAY,CAAC,QAAQ,EAAC,MAAM,EAAC,QAAQ,EAAC,MAAM,EAAC,KAAK,GAAC,MAAM,GAAC,IAAS,GAAE,MAAM,CAY1F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAC,MAAM,QAajD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAC,MAAM,EAAE,YAAY,EAAC,WAAW,QAe1E;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAC,eAAe,QAE3D;AAED,wBAAgB,kBAAkB,IAAG,eAAe,GAAC,IAAI,CAExD;AAED,wBAAgB,oBAAoB,SAEnC;AAED,uGAAuG;AACvG,wBAAgB,mBAAmB,CAAC,QAAQ,EAAC,OAAO,QAEnD;AAED,wBAAgB,qBAAqB,IAAG,OAAO,CAU9C;AAED,wBAAgB,oBAAoB,SAEnC"}
@@ -0,0 +1,91 @@
1
+ import type { kRPCClient } from './krpc_client';
2
+ export declare const AIWORKSPACE_SERVICE_NAME = "aiworkspace";
3
+ /** Business results of the AI Workspace service: `{ ok, ... }`, `{ ok: false, error }`, or a three-state commit result. */
4
+ export interface AiwsError {
5
+ code: string;
6
+ retryable: boolean;
7
+ detail: string;
8
+ sub_code?: string;
9
+ data?: unknown;
10
+ }
11
+ export type AiwsResult<T> = (T & {
12
+ ok: true;
13
+ }) | {
14
+ ok: false;
15
+ error: AiwsError;
16
+ };
17
+ export declare class AiwsFailure extends Error {
18
+ readonly code: string;
19
+ readonly subCode?: string;
20
+ readonly data?: unknown;
21
+ constructor(error: AiwsError);
22
+ }
23
+ /** A reference object (内核架构改进 D10): where, and which version. */
24
+ export interface AiwsReference {
25
+ zone?: string;
26
+ workspace_id?: string;
27
+ entity_id: string;
28
+ selector?: Record<string, unknown>;
29
+ mode: 'live' | 'fixed';
30
+ version?: {
31
+ epoch: string;
32
+ seq: number;
33
+ } | {
34
+ content_root: string;
35
+ path?: string;
36
+ };
37
+ }
38
+ /** What an executor outside the service reports for a run (M3): results in the Mock executor's shape, or an analysis. */
39
+ export interface AiwsRunReport {
40
+ run_id: string;
41
+ attempt: number;
42
+ progress?: Record<string, unknown>;
43
+ error?: {
44
+ code: string;
45
+ detail: string;
46
+ };
47
+ results?: Record<string, unknown>[];
48
+ read_set?: Record<string, unknown>[];
49
+ summary?: string;
50
+ warnings?: string[];
51
+ assumptions?: string[];
52
+ analysis?: Record<string, unknown>;
53
+ }
54
+ /**
55
+ * kRPC client of the AI Workspace service (`/kapi/aiworkspace`). Every method takes the business result out of
56
+ * `result` and throws `AiwsFailure` on `{ ok: false }`; commits return the three-state result as it is.
57
+ * Stable methods: see `src/frame/aiworkspace/README.md` (Protocol, method levels).
58
+ */
59
+ export declare class AiWorkspaceClient {
60
+ private rpcClient;
61
+ constructor(rpcClient: kRPCClient);
62
+ call<T = Record<string, unknown>>(method: string, params: Record<string, unknown>): Promise<T>;
63
+ list(): Promise<Record<string, unknown>>;
64
+ info(workspace_id: string): Promise<Record<string, unknown>>;
65
+ getUserState(workspace_id: string): Promise<Record<string, unknown>>;
66
+ setUserState(workspace_id: string, entries: Record<string, unknown>, expect?: Record<string, number>): Promise<Record<string, unknown>>;
67
+ resolve(workspace_id: string, reference: AiwsReference | Record<string, unknown>): Promise<Record<string, unknown>>;
68
+ resolvePath(workspace_id: string, path: string): Promise<Record<string, unknown>>;
69
+ read(workspace_id: string, entity_id: string, selector?: Record<string, unknown>): Promise<Record<string, unknown>>;
70
+ query(workspace_id: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
71
+ outline(workspace_id: string): Promise<Record<string, unknown>>;
72
+ prepare(workspace_id: string, request: Record<string, unknown>): Promise<Record<string, unknown>>;
73
+ /** The three-state commit result (`status: accepted | conflict | rejected`), never thrown. */
74
+ commit(workspace_id: string, request: Record<string, unknown>): Promise<Record<string, unknown>>;
75
+ getSubmission(workspace_id: string, epoch: string, idempotency_key: string): Promise<Record<string, unknown>>;
76
+ runStart(workspace_id: string, program: string, params: Record<string, unknown>, idempotency_key: string): Promise<Record<string, unknown>>;
77
+ runGet(workspace_id: string, run_id: string, choices?: Record<string, unknown>): Promise<Record<string, unknown>>;
78
+ runList(workspace_id: string, wish_id?: string, limit?: number): Promise<Record<string, unknown>>;
79
+ runClaim(workspace_id: string, run_id: string, claim_token: string, executor?: Record<string, unknown>): Promise<{
80
+ run_id: string;
81
+ attempt: number;
82
+ run_token: string;
83
+ lease_until: string;
84
+ lease_ms: number;
85
+ }>;
86
+ runHeartbeat(workspace_id: string, run_id: string, attempt: number, progress?: Record<string, unknown>): Promise<Record<string, unknown>>;
87
+ runReport(workspace_id: string, report: AiwsRunReport): Promise<Record<string, unknown>>;
88
+ runApply(workspace_id: string, run_id: string, plan_digest: string, session_id?: string): Promise<Record<string, unknown>>;
89
+ runCancel(workspace_id: string, run_id: string): Promise<Record<string, unknown>>;
90
+ }
91
+ //# sourceMappingURL=aiworkspace_client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiworkspace_client.d.ts","sourceRoot":"","sources":["../src/aiworkspace_client.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./content.cjs"),t=(e,t,i={})=>({protocol:"buckyos.app-frame",version:1,type:e,payload:t,...i}),i=e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"buckyos.app-frame"===t.protocol&&1===t.version&&"string"==typeof t.type&&!!t.payload&&"object"==typeof t.payload};exports.AppFrameClient=class{constructor(e){if(this.options=e,this.listener=e=>{this.receive(e)},this.origin=new URL(e.shellOrigin).origin,this.nonce=new URLSearchParams(window.location.hash.slice(1)).get("bfp"),window.addEventListener("message",this.listener),window.parent!==window&&this.nonce){const i=()=>window.parent.postMessage(t("frame.hello",{nonce:this.nonce,appCapabilities:[...e.onOpen?["open"]:[],...e.onBeforeClose?["beforeClose"]:[],...e.onBack?["back"]:[]]}),this.origin);i(),this.helloTimer=setInterval(i,250),this.helloDeadline=setTimeout((()=>clearInterval(this.helloTimer)),1500)}}async receive(s){var n,o,r,a,l,p,c,h,d,u,y,f,w,m;if(s.source!==window.parent||s.origin!==this.origin||!i(s.data))return;const g=s.data,v=g.payload;if("frame.init"===g.type){if(!this.nonce||v.nonce!==this.nonce||"string"!=typeof v.locale||!v.theme||"string"!=typeof v.windowId||v.launch&&!e.isOpenRequest(v.launch))return;return clearInterval(this.helloTimer),clearTimeout(this.helloDeadline),this.init=v,void(null==(o=(n=this.options).onInit)||o.call(n,this.init))}if(!this.init)return;const b=e=>window.parent.postMessage(t(g.type+"Result",e,{replyTo:g.id}),this.origin);try{"frame.open"===g.type&&e.isOpenRequest(v.request)&&b(await(null==(a=(r=this.options).onOpen)?void 0:a.call(r,v.request))??{accepted:!1}),"frame.beforeClose"===g.type&&b({decision:await(null==(p=(l=this.options).onBeforeClose)?void 0:p.call(l,v.reason))??"allow"}),"frame.back"===g.type&&b({handled:await(null==(h=(c=this.options).onBack)?void 0:h.call(c))??!1}),"frame.themeChanged"!==g.type||"dark"!==v.mode&&"light"!==v.mode||null==(u=(d=this.options).onTheme)||u.call(d,v),"frame.localeChanged"===g.type&&"string"==typeof v.locale&&(null==(f=(y=this.options).onLocale)||f.call(y,v.locale)),"frame.focusChanged"===g.type&&(null==(m=(w=this.options).onFocus)||m.call(w,!0===v.focused))}catch{"frame.open"===g.type&&b({accepted:!1,fallback:"preview"}),"frame.beforeClose"===g.type&&b({decision:"deny"})}}send(e,i){this.init&&window.parent.postMessage(t(e,i),this.origin)}setTitle(e,t=!1){this.send("window.setTitle",{title:e,dirty:t})}requestClose(){this.send("window.requestClose",{})}openContent(e,t="default",i=!1){this.send("content.open",{request:e,target:t,newWindow:i})}dispose(){clearInterval(this.helloTimer),clearTimeout(this.helloDeadline),window.removeEventListener("message",this.listener)}},exports.AppFrameHost=class{constructor(e){this.options=e,this.ready=!1,this.capabilities=[],this.pending=new Map,this.listener=e=>this.receive(e),this.opens=[],window.addEventListener("message",this.listener)}receive(t){var s,n,o,r,a,l,p,c;if(t.source!==this.options.target()||t.origin!==this.options.origin||!i(t.data))return;const h=t.data,d=h.payload;if("frame.hello"===h.type){if(d.nonce!==this.options.init.nonce||!Array.isArray(d.appCapabilities))return;return this.ready=!0,this.capabilities=d.appCapabilities.filter((e=>"string"==typeof e)),this.send("frame.init",this.options.init),void(null==(n=(s=this.options).onReady)||n.call(s))}if(this.ready)if(h.replyTo){const e=this.pending.get(h.replyTo);e&&h.type===e.type+"Result"&&(clearTimeout(e.timer),this.pending.delete(h.replyTo),e.resolve(h.payload))}else if("window.setTitle"===h.type&&"string"==typeof d.title&&(null==(r=(o=this.options).onTitle)||r.call(o,d.title.slice(0,256),!0===d.dirty)),"window.requestClose"===h.type&&(null==(l=(a=this.options).onRequestClose)||l.call(a)),"content.open"===h.type&&("default"===d.target||"preview"===d.target)){const t={...d.request,requestId:crypto.randomUUID()};if(!e.isOpenRequest(t))return;if(this.opens=this.opens.filter((e=>e>Date.now()-1e4)),this.opens.length>=5)return;this.opens.push(Date.now()),null==(c=(p=this.options).onContentOpen)||c.call(p,t,d.target,!0===d.newWindow)}}update(e){this.options.init={...this.options.init,...e}}send(e,i){var s;this.ready&&(null==(s=this.options.target())||s.postMessage(t(e,i),this.options.origin))}request(e,i,s=3e3){if(!this.ready)return Promise.reject(new Error("App frame is not ready"));const n=crypto.randomUUID();return new Promise(((o,r)=>{var a;const l=setTimeout((()=>{this.pending.delete(n),r(new Error("App frame timed out"))}),s);this.pending.set(n,{resolve:o,reject:r,timer:l,type:e}),null==(a=this.options.target())||a.postMessage(t(e,i,{id:n}),this.options.origin)}))}async open(e){return this.capabilities.includes("open")?await this.request("frame.open",{request:e}):{accepted:!1}}async beforeClose(e="user"){if(!this.ready||!this.capabilities.includes("beforeClose"))return"allow";const t=await this.request("frame.beforeClose",{reason:e});return"allow"===t.decision||"pending"===t.decision?t.decision:"deny"}async back(){return!!this.capabilities.includes("back")&&!0===(await this.request("frame.back",{})).handled}dispose(){window.removeEventListener("message",this.listener),this.pending.forEach((e=>{clearTimeout(e.timer),e.reject(new Error("App frame disposed"))})),this.pending.clear(),this.ready=!1}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./content.cjs"),t=(e,t,i={})=>({protocol:"buckyos.app-frame",version:1,type:e,payload:t,...i}),i=e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"buckyos.app-frame"===t.protocol&&1===t.version&&"string"==typeof t.type&&!!t.payload&&"object"==typeof t.payload};const s="buckyos.preview-embed",n=(e,t)=>({protocol:s,version:1,type:e,payload:t}),o=e=>{const t=e;return!!t&&t.protocol===s&&1===t.version&&"string"==typeof t.type&&!!t.payload&&"object"==typeof t.payload},r="/embed/preview";exports.AppFrameClient=class{constructor(e){if(this.options=e,this.listener=e=>{this.receive(e)},this.origin=new URL(e.shellOrigin).origin,this.nonce=new URLSearchParams(window.location.hash.slice(1)).get("bfp"),window.addEventListener("message",this.listener),window.parent!==window&&this.nonce){const i=()=>window.parent.postMessage(t("frame.hello",{nonce:this.nonce,appCapabilities:[...e.onOpen?["open"]:[],...e.onBeforeClose?["beforeClose"]:[],...e.onBack?["back"]:[]]}),this.origin);i(),this.helloTimer=setInterval(i,250),this.helloDeadline=setTimeout((()=>clearInterval(this.helloTimer)),1500)}}async receive(s){var n,o,r,a,l,p,c,d,h,u,f,w,y,m;if(s.source!==window.parent||s.origin!==this.origin||!i(s.data))return;const g=s.data,v=g.payload;if("frame.init"===g.type){if(!this.nonce||v.nonce!==this.nonce||"string"!=typeof v.locale||!v.theme||"string"!=typeof v.windowId||v.launch&&!e.isOpenRequest(v.launch))return;return clearInterval(this.helloTimer),clearTimeout(this.helloDeadline),this.init=v,this.title=void 0,this.focused=void 0,void(null==(o=(n=this.options).onInit)||o.call(n,this.init))}if(!this.init)return;const b=e=>window.parent.postMessage(t(g.type+"Result",e,{replyTo:g.id}),this.origin);try{"frame.open"===g.type&&e.isOpenRequest(v.request)&&b(await(null==(a=(r=this.options).onOpen)?void 0:a.call(r,v.request))??{accepted:!1}),"frame.beforeClose"===g.type&&b({decision:await(null==(p=(l=this.options).onBeforeClose)?void 0:p.call(l,v.reason))??"allow"}),"frame.back"===g.type&&b({handled:await(null==(d=(c=this.options).onBack)?void 0:d.call(c))??!1}),"frame.themeChanged"!==g.type||"dark"!==v.mode&&"light"!==v.mode||null==(u=(h=this.options).onTheme)||u.call(h,v),"frame.localeChanged"===g.type&&"string"==typeof v.locale&&(null==(w=(f=this.options).onLocale)||w.call(f,v.locale)),"frame.focusChanged"===g.type&&this.focused!==(!0===v.focused)&&(this.focused=!0===v.focused,null==(m=(y=this.options).onFocus)||m.call(y,this.focused))}catch{"frame.open"===g.type&&b({accepted:!1,fallback:"preview"}),"frame.beforeClose"===g.type&&b({decision:"deny"})}}send(e,i){this.init&&window.parent.postMessage(t(e,i),this.origin)}setTitle(e,t=!1){const i=JSON.stringify([e,t]);this.init&&i!==this.title&&(this.title=i,this.send("window.setTitle",{title:e,dirty:t}))}requestClose(){this.send("window.requestClose",{})}openContent(t,i="default",s={}){const n=s.hints??{};return this.init?(this.send("content.open",{request:t,target:i,newWindow:!0===s.newWindow,hints:n}),!0):!!this.options.systemOrigin&&(window.open(e.systemOpenUrl(this.options.systemOrigin,{request:t,target:i,hints:n,from:this.options.appId}),"_blank","noopener"),!0)}dispose(){clearInterval(this.helloTimer),clearTimeout(this.helloDeadline),window.removeEventListener("message",this.listener)}},exports.AppFrameHost=class{constructor(e){this.options=e,this.ready=!1,this.capabilities=[],this.pending=new Map,this.listener=e=>this.receive(e),this.opens=[],window.addEventListener("message",this.listener)}receive(t){var s,n,o,r,a,l,p,c;if(t.source!==this.options.target()||t.origin!==this.options.origin||!i(t.data))return;const d=t.data,h=d.payload;if("frame.hello"===d.type){if(h.nonce!==this.options.init.nonce||!Array.isArray(h.appCapabilities))return;return this.ready=!0,this.capabilities=h.appCapabilities.filter((e=>"string"==typeof e)),this.send("frame.init",this.options.init),void 0!==this.focused&&this.send("frame.focusChanged",{focused:this.focused}),void(null==(n=(s=this.options).onReady)||n.call(s))}if(this.ready)if(d.replyTo){const e=this.pending.get(d.replyTo);e&&d.type===e.type+"Result"&&(clearTimeout(e.timer),this.pending.delete(d.replyTo),e.resolve(d.payload))}else if("window.setTitle"===d.type&&"string"==typeof h.title&&(null==(r=(o=this.options).onTitle)||r.call(o,h.title.slice(0,256),!0===h.dirty)),"window.requestClose"===d.type&&(null==(l=(a=this.options).onRequestClose)||l.call(a)),"content.open"===d.type&&("default"===h.target||"preview"===h.target||"chooser"===h.target)){const t={...h.request,requestId:crypto.randomUUID()};if(!e.isOpenRequest(t))return;if(this.opens=this.opens.filter((e=>e>Date.now()-1e4)),this.opens.length>=5)return;this.opens.push(Date.now()),null==(c=(p=this.options).onContentOpen)||c.call(p,t,h.target,{newWindow:!0===h.newWindow,hints:e.readContentHints(h.hints)})}}update(e){this.options.init={...this.options.init,...e}}setFocused(e){this.focused!==e&&(this.focused=e,this.send("frame.focusChanged",{focused:e}))}send(e,i){var s;this.ready&&(null==(s=this.options.target())||s.postMessage(t(e,i),this.options.origin))}request(e,i,s=3e3){if(!this.ready)return Promise.reject(new Error("App frame is not ready"));const n=crypto.randomUUID();return new Promise(((o,r)=>{var a;const l=setTimeout((()=>{this.pending.delete(n),r(new Error("App frame timed out"))}),s);this.pending.set(n,{resolve:o,reject:r,timer:l,type:e}),null==(a=this.options.target())||a.postMessage(t(e,i,{id:n}),this.options.origin)}))}async open(e){return this.capabilities.includes("open")?await this.request("frame.open",{request:e}):{accepted:!1}}async beforeClose(e="user"){if(!this.ready||!this.capabilities.includes("beforeClose"))return"allow";const t=await this.request("frame.beforeClose",{reason:e});return"allow"===t.decision||"pending"===t.decision?t.decision:"deny"}async back(){return!!this.capabilities.includes("back")&&!0===(await this.request("frame.back",{})).handled}dispose(){window.removeEventListener("message",this.listener),this.pending.forEach((e=>{clearTimeout(e.timer),e.reject(new Error("App frame disposed"))})),this.pending.clear(),this.ready=!1}},exports.PREVIEW_EMBED_PATH=r,exports.PreviewEmbed=class{constructor(e){this.options=e,this.nonce=crypto.randomUUID(),this.listener=e=>this.receive(e),this.origin=new URL(e.systemOrigin).origin,this.init=e.init,this.url=`${this.origin}${r}#bpe=${this.nonce}&po=${encodeURIComponent(window.location.origin)}`,window.addEventListener("message",this.listener)}post(e,t){var i,s;null==(s=null==(i=this.options.frame())?void 0:i.contentWindow)||s.postMessage(n(e,t),this.origin)}receive(t){var i,s,n,r,a,l,p;if(t.origin!==this.origin||t.source!==(null==(i=this.options.frame())?void 0:i.contentWindow)||!o(t.data))return;const{type:c,payload:d}=t.data;if("embed.hello"!==c){if("embed.state"===c&&("loading"===d.status||"ready"===d.status||"error"===d.status)){const e=d.error;null==(n=(s=this.options).onState)||n.call(s,{status:d.status,error:e&&"string"==typeof e.kind&&"string"==typeof e.code?{kind:e.kind,code:e.code}:void 0,title:"string"==typeof d.title?d.title.slice(0,256):void 0,mediaType:"string"==typeof d.mediaType?d.mediaType.slice(0,128):void 0})}if("embed.openWith"===c){const t=d.request;t&&e.isTransferableRef(t.source)&&(void 0===t.session||e.isTransferableSession(t.session))&&(null==(a=(r=this.options).onOpenWith)||a.call(r,{request:{source:t.source,session:t.session},hints:e.readContentHints(d.hints)}))}"embed.exit"===c&&(null==(p=(l=this.options).onExit)||p.call(l))}else d.nonce===this.nonce&&this.post("embed.init",{...this.init,nonce:this.nonce})}update(e){this.init={...this.init,...e},this.post("embed.update",e)}dispose(){window.removeEventListener("message",this.listener)}},exports.PreviewEmbedHost=class{constructor(e){this.options=e,this.ready=!1,this.listener=e=>this.receive(e);const t=new URLSearchParams(window.location.hash.slice(1));this.nonce=t.get("bpe");let i=null;try{i=new URL(t.get("po")??"").origin}catch{}if(this.parentOrigin=window.parent!==window&&this.nonce&&i&&e.accept(i)?i:null,!this.parentOrigin)return;window.addEventListener("message",this.listener);const s=()=>window.parent.postMessage(n("embed.hello",{nonce:this.nonce}),this.parentOrigin);s(),this.hello=setInterval((()=>{this.ready||s()}),250)}receive(t){var i,s;if(t.source!==window.parent||t.origin!==this.parentOrigin||!o(t.data))return;const{type:n,payload:r}=t.data;if("embed.init"===n){if(r.nonce!==this.nonce||(a=r.source,!(e.isTransferableRef(a)||a&&"object"==typeof a&&"blob"===a.kind&&"undefined"!=typeof Blob&&a.blob instanceof Blob&&"string"==typeof a.name))||void 0!==r.session&&!e.isTransferableSession(r.session)||"string"!=typeof r.locale)return;return this.ready=!0,clearInterval(this.hello),void this.options.onInit({nonce:String(r.nonce),source:r.source,session:r.session,theme:"dark"===r.theme?"dark":"light",locale:r.locale})}var a;if("embed.update"===n&&this.ready){const e={};"dark"!==r.theme&&"light"!==r.theme||(e.theme=r.theme),"string"==typeof r.locale&&(e.locale=r.locale),null==(s=(i=this.options).onUpdate)||s.call(i,e)}}post(e,t){this.ready&&this.parentOrigin&&window.parent.postMessage(n(e,t),this.parentOrigin)}state(e){this.post("embed.state",e)}openWith(e){this.post("embed.openWith",e)}exit(){this.post("embed.exit",{})}dispose(){clearInterval(this.hello),window.removeEventListener("message",this.listener)}},exports.embedderOrigin=function(e){var t;if(window.parent===window)return null;const i=[null==(t=window.location.ancestorOrigins)?void 0:t[0],document.referrer];for(const s of i)if(s)try{const t=new URL(s).origin;if(e(t))return t}catch{}return null},exports.originInZone=(e,t)=>{try{const i=new URL(e);return i.protocol===window.location.protocol&&(i.hostname===t||i.hostname.endsWith(`.${t}`))}catch{return!1}};
2
2
  //# sourceMappingURL=app-frame.cjs.map