@wowok/agent-mcp 3.1.6 → 3.1.7

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.
@@ -119,6 +119,227 @@
119
119
  "type"
120
120
  ],
121
121
  "additionalProperties": false
122
+ },
123
+ {
124
+ "type": "object",
125
+ "properties": {
126
+ "type": {
127
+ "type": "string",
128
+ "const": "upload"
129
+ },
130
+ "storage": {
131
+ "type": "string"
132
+ },
133
+ "base_url": {
134
+ "type": "string",
135
+ "description": "Storage service base URL"
136
+ },
137
+ "address": {
138
+ "description": "Signing account address",
139
+ "type": "string"
140
+ },
141
+ "hash": {
142
+ "description": "Stored file hash (meta.hash)",
143
+ "type": "string"
144
+ },
145
+ "url": {
146
+ "description": "Public download URL",
147
+ "type": "string"
148
+ },
149
+ "size": {
150
+ "type": "number"
151
+ },
152
+ "name": {
153
+ "type": "string"
154
+ },
155
+ "signed": {
156
+ "description": "Whether the WIP file carries embedded signatures",
157
+ "type": "boolean"
158
+ },
159
+ "deduplicated": {
160
+ "description": "True when the same account had already stored this hash",
161
+ "type": "boolean"
162
+ },
163
+ "error": {
164
+ "description": "Error code (e.g. QUOTA_EXCEEDED when the store account file limit is reached)",
165
+ "type": "string"
166
+ },
167
+ "message": {
168
+ "type": "string"
169
+ },
170
+ "count": {
171
+ "description": "Files currently stored by the account",
172
+ "type": "number"
173
+ },
174
+ "limit": {
175
+ "description": "Per-account file limit on the storage service",
176
+ "type": "number"
177
+ },
178
+ "files": {
179
+ "description": "Current stored files (provided on QUOTA_EXCEEDED for deletion)",
180
+ "type": "array",
181
+ "items": {
182
+ "type": "object",
183
+ "properties": {
184
+ "hash": {
185
+ "type": "string",
186
+ "description": "WIP file hash (meta.hash)"
187
+ },
188
+ "name": {
189
+ "description": "Optional display name",
190
+ "type": "string"
191
+ },
192
+ "size": {
193
+ "description": "File size in bytes",
194
+ "type": "number"
195
+ },
196
+ "created_at": {
197
+ "description": "Upload time (ms epoch)",
198
+ "type": "number"
199
+ },
200
+ "url": {
201
+ "description": "Public download URL",
202
+ "type": "string"
203
+ }
204
+ },
205
+ "required": [
206
+ "hash"
207
+ ],
208
+ "additionalProperties": false,
209
+ "description": "A WIP file stored on a wip storage service"
210
+ }
211
+ },
212
+ "guidance": {
213
+ "description": "Actionable guidance (delete files or switch to self-hosted storage)",
214
+ "type": "string"
215
+ },
216
+ "network_advisory": {
217
+ "description": "Generic advisory for large, network-sensitive WIP files (size reduction, retry, reachability check)",
218
+ "type": "string"
219
+ },
220
+ "retention_notice": {
221
+ "description": "Free-store terms (storage='store' only): 6-month retention, best-effort/force-majeure disclaimer, no automatic deletion",
222
+ "type": "string"
223
+ }
224
+ },
225
+ "required": [
226
+ "type",
227
+ "storage",
228
+ "base_url"
229
+ ],
230
+ "additionalProperties": false
231
+ },
232
+ {
233
+ "type": "object",
234
+ "properties": {
235
+ "type": {
236
+ "type": "string",
237
+ "const": "storage_list"
238
+ },
239
+ "storage": {
240
+ "type": "string"
241
+ },
242
+ "base_url": {
243
+ "type": "string"
244
+ },
245
+ "address": {
246
+ "type": "string"
247
+ },
248
+ "count": {
249
+ "type": "number"
250
+ },
251
+ "limit": {
252
+ "type": "number"
253
+ },
254
+ "files": {
255
+ "type": "array",
256
+ "items": {
257
+ "type": "object",
258
+ "properties": {
259
+ "hash": {
260
+ "type": "string",
261
+ "description": "WIP file hash (meta.hash)"
262
+ },
263
+ "name": {
264
+ "description": "Optional display name",
265
+ "type": "string"
266
+ },
267
+ "size": {
268
+ "description": "File size in bytes",
269
+ "type": "number"
270
+ },
271
+ "created_at": {
272
+ "description": "Upload time (ms epoch)",
273
+ "type": "number"
274
+ },
275
+ "url": {
276
+ "description": "Public download URL",
277
+ "type": "string"
278
+ }
279
+ },
280
+ "required": [
281
+ "hash"
282
+ ],
283
+ "additionalProperties": false,
284
+ "description": "A WIP file stored on a wip storage service"
285
+ },
286
+ "description": "Stored WIP file list"
287
+ },
288
+ "error": {
289
+ "type": "string"
290
+ },
291
+ "message": {
292
+ "type": "string"
293
+ },
294
+ "retention_notice": {
295
+ "description": "Free-store terms (storage='store' only): 6-month retention, best-effort/force-majeure disclaimer, no automatic deletion",
296
+ "type": "string"
297
+ }
298
+ },
299
+ "required": [
300
+ "type",
301
+ "storage",
302
+ "base_url"
303
+ ],
304
+ "additionalProperties": false
305
+ },
306
+ {
307
+ "type": "object",
308
+ "properties": {
309
+ "type": {
310
+ "type": "string",
311
+ "const": "storage_delete"
312
+ },
313
+ "storage": {
314
+ "type": "string"
315
+ },
316
+ "base_url": {
317
+ "type": "string"
318
+ },
319
+ "address": {
320
+ "type": "string"
321
+ },
322
+ "deleted": {
323
+ "description": "Hash of the deleted file",
324
+ "type": "string"
325
+ },
326
+ "remaining": {
327
+ "description": "Files remaining for the account after deletion",
328
+ "type": "number"
329
+ },
330
+ "error": {
331
+ "type": "string"
332
+ },
333
+ "message": {
334
+ "type": "string"
335
+ }
336
+ },
337
+ "required": [
338
+ "type",
339
+ "storage",
340
+ "base_url"
341
+ ],
342
+ "additionalProperties": false
122
343
  }
123
344
  ],
124
345
  "description": "WIP operation output schema with discriminator"
@@ -169,6 +169,131 @@
169
169
  ],
170
170
  "additionalProperties": false,
171
171
  "description": "Convert WIP file to HTML format"
172
+ },
173
+ {
174
+ "type": "object",
175
+ "properties": {
176
+ "type": {
177
+ "type": "string",
178
+ "const": "upload"
179
+ },
180
+ "wipFilePath": {
181
+ "type": "string",
182
+ "description": "WIP file to upload. Supports: 1) Local file path, 2) Network URL, 3) Data URL"
183
+ },
184
+ "account": {
185
+ "description": "Account used to sign the upload (name or address). If omitted, uses the default account",
186
+ "type": "string"
187
+ },
188
+ "storage": {
189
+ "description": "Storage backend: 'store' = official free wip.store.wowok.net (zero setup, max 10 files per account, files retained 6 months — free best-effort service, force majeure excepted, expired files are purged only by manual admin action, never automatically); 'custom' = your own or a third-party wip storage service via customBaseUrl (recommended: no store quota, full control). Default: 'store'",
190
+ "anyOf": [
191
+ {
192
+ "type": "string",
193
+ "const": "store",
194
+ "description": "Official free wip.store.wowok.net storage (zero setup, max 10 files per account, files retained 6 months). Declaration: free best-effort service — availability and data survival are not guaranteed (force majeure excepted); expired files are deleted ONLY by a manual administrator purge, never automatically"
195
+ },
196
+ {
197
+ "type": "string",
198
+ "const": "custom",
199
+ "description": "Your own or a third-party wip storage service (recommended: no store quota, full control, permanent self-managed hosting)"
200
+ }
201
+ ]
202
+ },
203
+ "customBaseUrl": {
204
+ "description": "Base URL of your own or a third-party wip storage deployment (required when storage='custom'), e.g. 'https://wip.example.com'",
205
+ "type": "string"
206
+ },
207
+ "name": {
208
+ "description": "Optional display name recorded with the stored file",
209
+ "type": "string"
210
+ }
211
+ },
212
+ "required": [
213
+ "type",
214
+ "wipFilePath"
215
+ ],
216
+ "additionalProperties": false,
217
+ "description": "Upload a signed WIP file to a wip storage service. The upload request is signed with the account's Falcon512 key; the file is validated (format, size limits, content hash, signatures) and stored under its content hash with a public download URL. When the per-account file limit is reached, the error carries the account's stored file list for deletion. Large, image-heavy WIP files are network-sensitive: keep them small (compress images before generate) and retry on transient network failures. WIP files are off-chain and network-independent: the returned public URL works on both testnet and mainnet"
218
+ },
219
+ {
220
+ "type": "object",
221
+ "properties": {
222
+ "type": {
223
+ "type": "string",
224
+ "const": "storage_list"
225
+ },
226
+ "account": {
227
+ "description": "Account used to sign the request (name or address). If omitted, uses the default account",
228
+ "type": "string"
229
+ },
230
+ "storage": {
231
+ "description": "Storage backend (default 'store')",
232
+ "anyOf": [
233
+ {
234
+ "type": "string",
235
+ "const": "store",
236
+ "description": "Official free wip.store.wowok.net storage (zero setup, max 10 files per account, files retained 6 months). Declaration: free best-effort service — availability and data survival are not guaranteed (force majeure excepted); expired files are deleted ONLY by a manual administrator purge, never automatically"
237
+ },
238
+ {
239
+ "type": "string",
240
+ "const": "custom",
241
+ "description": "Your own or a third-party wip storage service (recommended: no store quota, full control, permanent self-managed hosting)"
242
+ }
243
+ ]
244
+ },
245
+ "customBaseUrl": {
246
+ "description": "Base URL of your own or a third-party wip storage deployment (required when storage='custom')",
247
+ "type": "string"
248
+ }
249
+ },
250
+ "required": [
251
+ "type"
252
+ ],
253
+ "additionalProperties": false,
254
+ "description": "List the WIP files an account currently stores on a wip storage service (signed request). Off-chain and network-independent: the account's stored files are identical on testnet and mainnet — no chain call is involved"
255
+ },
256
+ {
257
+ "type": "object",
258
+ "properties": {
259
+ "type": {
260
+ "type": "string",
261
+ "const": "storage_delete"
262
+ },
263
+ "hash": {
264
+ "type": "string",
265
+ "description": "Hash (meta.hash) of the WIP file to delete"
266
+ },
267
+ "account": {
268
+ "description": "Account used to sign the request (name or address). If omitted, uses the default account",
269
+ "type": "string"
270
+ },
271
+ "storage": {
272
+ "description": "Storage backend (default 'store')",
273
+ "anyOf": [
274
+ {
275
+ "type": "string",
276
+ "const": "store",
277
+ "description": "Official free wip.store.wowok.net storage (zero setup, max 10 files per account, files retained 6 months). Declaration: free best-effort service — availability and data survival are not guaranteed (force majeure excepted); expired files are deleted ONLY by a manual administrator purge, never automatically"
278
+ },
279
+ {
280
+ "type": "string",
281
+ "const": "custom",
282
+ "description": "Your own or a third-party wip storage service (recommended: no store quota, full control, permanent self-managed hosting)"
283
+ }
284
+ ]
285
+ },
286
+ "customBaseUrl": {
287
+ "description": "Base URL of your own or a third-party wip storage deployment (required when storage='custom')",
288
+ "type": "string"
289
+ }
290
+ },
291
+ "required": [
292
+ "type",
293
+ "hash"
294
+ ],
295
+ "additionalProperties": false,
296
+ "description": "Delete a stored WIP file from a wip storage service. Only files owned by the signing account can be deleted (signed request; off-chain, works identically on testnet and mainnet)"
172
297
  }
173
298
  ]
174
299
  }
@@ -0,0 +1,22 @@
1
+ export declare const DEFAULT_WIP_STORE_URL: string;
2
+ export declare const FREE_STORE_RETENTION_DAYS = 180;
3
+ export declare const FREE_STORE_RETENTION_NOTICE: string;
4
+ export interface WipStorageTarget {
5
+ storage?: "store" | "custom";
6
+ customBaseUrl?: string;
7
+ }
8
+ export interface WipUploadArgs extends WipStorageTarget {
9
+ wipFilePath: string;
10
+ account?: string;
11
+ name?: string;
12
+ }
13
+ export declare function wipStorageUpload(args: WipUploadArgs): Promise<Record<string, unknown>>;
14
+ export interface WipStorageListArgs extends WipStorageTarget {
15
+ account?: string;
16
+ }
17
+ export declare function wipStorageList(args: WipStorageListArgs): Promise<Record<string, unknown>>;
18
+ export interface WipStorageDeleteArgs extends WipStorageTarget {
19
+ hash: string;
20
+ account?: string;
21
+ }
22
+ export declare function wipStorageDelete(args: WipStorageDeleteArgs): Promise<Record<string, unknown>>;
@@ -0,0 +1 @@
1
+ import{createHash,randomBytes}from'node:crypto';import{readFileSync}from'node:fs';import{Account,verify_wip}from'@wowok/wowok';export const DEFAULT_WIP_STORE_URL=process['env']['WOWOK_WIP_STORE_URL']??'https://wip.store.wowok.net';const MAX_UPLOAD_BYTES=0xc*0x400*0x400,QUOTA_GUIDANCE='Delete\x20one\x20or\x20more\x20stored\x20files\x20with\x20wip_file\x20type=\x27storage_delete\x27\x20(the\x20\x27files\x27\x20list\x20above\x20provides\x20the\x20hashes),\x20then\x20retry\x20the\x20upload.\x20'+'Alternatively,\x20use\x20your\x20own\x20or\x20a\x20third-party\x20wip\x20storage\x20service\x20and\x20upload\x20with\x20storage=\x27custom\x27\x20(recommended:\x20no\x20store\x20quota\x20and\x20full\x20control\x20over\x20your\x20documents).',LARGE_FILE_ADVISORY_BYTES=0x2*0x400*0x400,NETWORK_ADVISORY='This\x20WIP\x20file\x20is\x20large\x20(multi-MB,\x20image-heavy)\x20and\x20therefore\x20sensitive\x20to\x20network\x20conditions:\x20'+'uploads\x20may\x20be\x20slow\x20or\x20fail\x20mid-transfer,\x20and\x20customers\x20fetch\x20the\x20file\x20again\x20when\x20placing\x20orders.\x20'+'Solutions:\x20keep\x20WIP\x20files\x20small\x20(compress\x20images\x20before\x20generate;\x20each\x20image\x20<=\x202MB,\x20total\x20<=\x2010MB),\x20'+'retry\x20the\x20upload\x20on\x20transient\x20network\x20failures,\x20and\x20confirm\x20the\x20returned\x20public\x20URL\x20is\x20reachable\x20'+'afterwards\x20(wip_file\x20type=\x27verify\x27\x20with\x20the\x20URL).';export const FREE_STORE_RETENTION_DAYS=0xb4;export const FREE_STORE_RETENTION_NOTICE='Official\x20free\x20store\x20(wip.store.wowok.net):\x20files\x20are\x20retained\x20for\x20at\x20least\x206\x20months\x20(180\x20days)\x20from\x20upload.\x20'+'This\x20is\x20a\x20free,\x20best-effort\x20service\x20provided\x20as-is\x20—\x20availability\x20and\x20data\x20survival\x20are\x20not\x20guaranteed\x20(force\x20majeure\x20excepted).\x20'+'Expired\x20files\x20are\x20NEVER\x20deleted\x20automatically;\x20deletion\x20past\x20the\x20retention\x20window\x20is\x20a\x20manual\x20administrator\x20action\x20on\x20the\x20storage\x20service.\x20'+'For\x20permanent,\x20self-controlled\x20hosting\x20use\x20storage=\x27custom\x27\x20(recommended).';function resolveBaseUrl(a){const b=a['storage']==='custom'?'custom':'store';if(b==='custom'){if(!a['customBaseUrl'])throw new Error('storage=\x27custom\x27\x20requires\x20\x27customBaseUrl\x27\x20—\x20the\x20base\x20URL\x20of\x20your\x20own\x20or\x20a\x20third-party\x20wip\x20storage\x20service\x20deployment');return{'baseUrl':a['customBaseUrl']['replace'](/\/+$/,''),'storage':b};}return{'baseUrl':DEFAULT_WIP_STORE_URL['replace'](/\/+$/,''),'storage':b};}function sha256Hex(a){return createHash('sha256')['update'](a)['digest']('hex');}async function loadWipBytes(a){if(a['startsWith']('data:')){const b=a['match'](/^data:[^;,]*(?:;charset=[\w-]+)?;base64,(.+)$/);if(!b)throw new Error('Unsupported\x20data\x20URL\x20format\x20for\x20WIP\x20file\x20(expected\x20base64\x20data\x20URL)');return Buffer['from'](b[0x1],'base64');}if(/^https?:\/\//i['test'](a)){const c=await fetch(a);if(!c['ok'])throw new Error('Failed\x20to\x20fetch\x20WIP\x20file\x20from\x20'+a+':\x20'+c['status']+'\x20'+c['statusText']);const d=Buffer['from'](await c['arrayBuffer']());if(d['length']>MAX_UPLOAD_BYTES)throw new Error('WIP\x20file\x20at\x20'+a+'\x20exceeds\x20the\x20'+MAX_UPLOAD_BYTES+'\x20byte\x20transport\x20limit');return d;}return readFileSync(a);}async function signedHeaders(a,b,c){const d=Date['now'](),e=randomBytes(0x10)['toString']('hex'),f=c?'wip:'+b+':'+d+':'+e+':'+c:'wip:'+b+':'+d+':'+e,g=await Account['Instance']()['signData'](a??null,f);return{'address':g['address'],'headers':{'x-wip-timestamp':String(d),'x-wip-nonce':e,'x-wip-public-key':g['publicKey'],'x-wip-signature':g['signature'],'x-wip-address':g['address']}};}async function storagePost(a,b,c,d,e){let f;try{f=await fetch(a+b,{'method':'POST','headers':e?{...c,'content-type':e}:c,'body':d===null?undefined:typeof d==='string'?d:new Uint8Array(d)});}catch(h){throw new Error('WIP\x20storage\x20request\x20to\x20'+a+b+'\x20failed:\x20network\x20error\x20('+(h instanceof Error?h['message']:String(h))+').\x20'+'Large\x20WIP\x20files\x20are\x20sensitive\x20to\x20network\x20conditions\x20—\x20retry\x20the\x20request;\x20if\x20it\x20keeps\x20failing,\x20'+'check\x20connectivity\x20or\x20reduce\x20the\x20file\x20size\x20(compress\x20images\x20before\x20generate).');}let g=null;try{g=await f['json']();}catch{g=null;}return{'status':f['status'],'json':g};}function serverError(a,b,c){const d=c?.['message']??c?.['error']??'unknown\x20error';throw new Error('WIP\x20storage\x20'+a+'\x20failed\x20('+b+'):\x20'+d);}export async function wipStorageUpload(a){const {baseUrl:b,storage:c}=resolveBaseUrl(a),d=await verify_wip(a['wipFilePath'],undefined,undefined);if(!d['valid'])throw new Error('WIP\x20file\x20failed\x20verification\x20and\x20was\x20not\x20uploaded:\x20'+d['error']);const e=await loadWipBytes(a['wipFilePath']);if(e['length']>MAX_UPLOAD_BYTES)throw new Error('WIP\x20file\x20exceeds\x20the\x20'+MAX_UPLOAD_BYTES+'\x20byte\x20transport\x20limit');const {address:f,headers:g}=await signedHeaders(a['account'],'upload',sha256Hex(e)),h={};if(a['name'])h['x-wip-name']=encodeURIComponent(a['name']);const {status:i,json:j}=await storagePost(b,'/api/upload',{...g,...h},e,'application/octet-stream');if(i===0x199&&j?.['error']==='QUOTA_EXCEEDED')return{'type':'upload','storage':c,'base_url':b,'address':f,'error':'QUOTA_EXCEEDED','message':j['message']??'Storage\x20quota\x20exceeded','count':j['count'],'limit':j['limit'],'files':j['files']??[],'guidance':QUOTA_GUIDANCE};i!==0xc8&&i!==0xc9&&serverError('upload',i,j);const k={'type':'upload','storage':c,'base_url':b,'address':f,'hash':j['hash'],'url':j['url'],'size':j['size'],'name':j['name']??a['name'],'signed':j['signed'],'deduplicated':j['deduplicated']===!![]};return e['length']>LARGE_FILE_ADVISORY_BYTES&&(k['network_advisory']=NETWORK_ADVISORY),c==='store'&&(k['retention_notice']=FREE_STORE_RETENTION_NOTICE),k;}export async function wipStorageList(a){const {baseUrl:b,storage:c}=resolveBaseUrl(a),{address:d,headers:e}=await signedHeaders(a['account'],'list',null),{status:f,json:g}=await storagePost(b,'/api/list',e,null);if(f!==0xc8)serverError('list',f,g);const h={'type':'storage_list','storage':c,'base_url':b,'address':g['address']??d,'count':g['count'],'limit':g['limit'],'files':g['files']??[]};return c==='store'&&(h['retention_notice']=FREE_STORE_RETENTION_NOTICE),h;}export async function wipStorageDelete(a){const {baseUrl:b,storage:c}=resolveBaseUrl(a),d=a['hash']['toLowerCase']()['replace'](/^sha256:/,'');if(!/^[0-9a-f]{64}$/['test'](d))throw new Error('Invalid\x20hash\x20\x27'+a['hash']+'\x27\x20—\x20expected\x20a\x2064-character\x20hex\x20sha256\x20digest\x20(meta.hash)');const {address:e,headers:f}=await signedHeaders(a['account'],'delete',d),{status:g,json:h}=await storagePost(b,'/api/delete',f,JSON['stringify']({'hash':d}),'application/json');if(g!==0xc8)serverError('delete',g,h);return{'type':'storage_delete','storage':c,'base_url':b,'address':h['address']??e,'deleted':h['deleted']??d,'remaining':h['remaining']};}
@@ -1 +1 @@
1
- import{strictParse,WipOperationsSchema}from'../../schema/index.js';import{generate_wip,verify_wip,sign_wip,wip2html}from'@wowok/wowok';import{analyzeWipDeployment,formatDeployHints}from'../wip-deploy-assist.js';export async function handleWipOperations(a){if(typeof a==='object'&&a!==null&&a['type']==='deploy_assist'){const d=a['wipFilePath'];if(typeof d!=='string')return{'content':[{'type':'text','text':'Error:\x20\x27wipFilePath\x27\x20is\x20required\x20for\x20deploy_assist\x20action'}],'structuredContent':{'result':{'type':'error','error':'\x27wipFilePath\x27\x20is\x20required\x20for\x20deploy_assist\x20action'}}};const e=analyzeWipDeployment(d),f=formatDeployHints(e);return{'content':[{'type':'text','text':f||'No\x20deployment\x20needed.'}],'structuredContent':{'result':{'type':'deploy_assist',...e}}};}const b=strictParse(WipOperationsSchema,a,'wip_file\x20input');let c;switch(b['type']){case'generate':{const g=await generate_wip(b['options'],b['outputPath']);c={'result':{'type':'generate','filePath':g}};break;}case'verify':{const h=analyzeWipDeployment(b['wipFilePath']),i=await verify_wip(b['wipFilePath'],b['hash_equal'],b['requireSignature']),j=h['needs_deployment']||!i['valid']&&h['classification']['type']!=='data_url';if(j){const k=formatDeployHints(h);c={'result':{'type':'verify',...i,'deployment_assistance':h},'deployment_hints':k};}else c={'result':{'type':'verify',...i}};break;}case'sign':{const l=await sign_wip(b['wipFilePath'],b['account'],b['outputPath']);c={'result':{'type':'sign','filePath':l}};break;}case'wip2html':{const m=await wip2html(b['wipPath'],b['options']),n={'type':'wip2html'};Array['isArray'](m)?n['files']=m:n['filePath']=m;c={'result':n};break;}default:throw new Error('Unknown\x20WIP\x20operation\x20type');}return{'content':[{'type':'text','text':JSON['stringify'](c)}],'structuredContent':c};}
1
+ import{strictParse,WipOperationsSchema}from'../../schema/index.js';import{generate_wip,verify_wip,sign_wip,wip2html}from'@wowok/wowok';import{analyzeWipDeployment,formatDeployHints}from'../wip-deploy-assist.js';import{wipStorageUpload,wipStorageList,wipStorageDelete}from'./wip-upload.js';export async function handleWipOperations(a){if(typeof a==='object'&&a!==null&&a['type']==='deploy_assist'){const d=a['wipFilePath'];if(typeof d!=='string')return{'content':[{'type':'text','text':'Error:\x20\x27wipFilePath\x27\x20is\x20required\x20for\x20deploy_assist\x20action'}],'structuredContent':{'result':{'type':'error','error':'\x27wipFilePath\x27\x20is\x20required\x20for\x20deploy_assist\x20action'}}};const e=analyzeWipDeployment(d),f=formatDeployHints(e);return{'content':[{'type':'text','text':f||'No\x20deployment\x20needed.'}],'structuredContent':{'result':{'type':'deploy_assist',...e}}};}const b=strictParse(WipOperationsSchema,a,'wip_file\x20input');let c;switch(b['type']){case'generate':{const g=await generate_wip(b['options'],b['outputPath']);c={'result':{'type':'generate','filePath':g}};break;}case'verify':{const h=analyzeWipDeployment(b['wipFilePath']),i=await verify_wip(b['wipFilePath'],b['hash_equal'],b['requireSignature']),j=h['needs_deployment']||!i['valid']&&h['classification']['type']!=='data_url';if(j){const k=formatDeployHints(h);c={'result':{'type':'verify',...i,'deployment_assistance':h},'deployment_hints':k};}else c={'result':{'type':'verify',...i}};break;}case'sign':{const l=await sign_wip(b['wipFilePath'],b['account'],b['outputPath']);c={'result':{'type':'sign','filePath':l}};break;}case'wip2html':{const m=await wip2html(b['wipPath'],b['options']),n={'type':'wip2html'};Array['isArray'](m)?n['files']=m:n['filePath']=m;c={'result':n};break;}case'upload':{c={'result':await wipStorageUpload(b)};break;}case'storage_list':{c={'result':await wipStorageList(b)};break;}case'storage_delete':{c={'result':await wipStorageDelete(b)};break;}default:throw new Error('Unknown\x20WIP\x20operation\x20type');}return{'content':[{'type':'text','text':JSON['stringify'](c)}],'structuredContent':c};}
@@ -1 +1 @@
1
- import{z}from'zod';import{handleWipOperations}from'../handlers/wip.js';import{handleGuard2File,handleMachineNode2File}from'../handlers/file-export.js';import{strictStatusErrorShape}from'../wrap.js';import{createToolMeta,WipOperationsSchema,WipOperationOutputSchema,Guard2File_InputSchema,Guard2File_OutputWrappedSchema,MachineNode2File_InputSchema,MachineNode2File_OutputWrappedSchema}from'../../schema/index.js';export const FILE_TOOLS=[{'name':'wip_file','handler':handleWipOperations,'config':{'title':'🤝\x20Witness\x20Immutable\x20Promise\x20File\x20Operations','summary':'WIP\x20promise\x20file\x20operations:\x20generate,\x20verify,\x20sign,\x20wip2html.','description':'generate\x20(create\x20WIP\x20files\x20from\x20markdown\x20and\x20images),\x20verify\x20(integrity\x20check),\x20sign\x20(add\x20signatures),\x20or\x20wip2html\x20(convert\x20to\x20HTML).\x0a\x0a⚠️\x20IMPORTANT\x20—\x20On-chain\x20WIP\x20URL\x20requirement:\x20When\x20using\x20a\x20WIP\x20file\x20URL\x20in\x20`service.sales[].wip`\x20(stored\x20on-chain),\x20the\x20URL\x20MUST\x20be\x20publicly\x20reachable.\x20Local\x20file\x20paths\x20(e.g.,\x20\x27C:\x5c\x5cpath\x5c\x5cfile.wip\x27\x20or\x20\x27/home/user/file.wip\x27)\x20are\x20NOT\x20acceptable\x20on-chain\x20—\x20they\x20only\x20work\x20locally\x20and\x20will\x20fail\x20verification\x20for\x20buyers.\x0a\x0aDeployment\x20options\x20for\x20the\x20.wip\x20file:\x0a\x20\x20•\x20GitHub\x20Pages:\x20https://raw.githubusercontent.com/<user>/<repo>/<branch>/<file>.wip\x0a\x20\x20•\x20IPFS:\x20https://ipfs.io/ipfs/<CID>\x20or\x20https://cloudflare-ipfs.com/ipfs/<CID>\x20(upload\x20via\x20pinata.cloud)\x0a\x20\x20•\x20User\x27s\x20own\x20static\x20website\x20URL\x0a\x0aUse\x20type=\x27generate\x27\x20to\x20create\x20the\x20WIP\x20file\x20first,\x20upload\x20it\x20to\x20any\x20of\x20the\x20above,\x20then\x20use\x20the\x20resulting\x20URL\x20in\x20service.sales[].wip.\x0a\x0a💡\x20Schema\x20hint:\x20Use\x20schema_query\x20with\x20action=\x27get\x27\x20and\x20name=\x27wip_file\x27\x20to\x20retrieve\x20the\x20exact\x20parameter\x20schema\x20before\x20calling.','inputSchema':WipOperationsSchema,'outputSchema':z['object']({'result':WipOperationOutputSchema}),'annotations':{'readOnlyHint':![],'destructiveHint':![],'idempotentHint':![],'openWorldHint':![]},'_meta':createToolMeta('operation',['wip','promise','file-generation','verification','signature','local'])}},{'name':'guard2file','handler':handleGuard2File,'config':{'title':'📄\x20Guard\x20to\x20File\x20-\x20Export\x20Guard\x20Definition','summary':'Export\x20guard\x20rules\x20to\x20a\x20local\x20JSON/Markdown\x20file.','description':'Export\x20a\x20Guard\x20object\x27s\x20definition\x20from\x20the\x20blockchain\x20to\x20a\x20local\x20JSON\x20or\x20Markdown\x20file\x20for\x20editing\x20and\x20creating\x20new\x20Guard\x20objects.\x20Note:\x20To\x20query\x20on-chain\x20object\x20information,\x20use\x20the\x20\x27query_toolkit\x27\x20tool\x20instead.\x0a\x0a💡\x20Schema\x20hint:\x20Use\x20schema_query\x20with\x20action=\x27get\x27\x20and\x20name=\x27guard2file\x27\x20to\x20retrieve\x20the\x20exact\x20parameter\x20schema\x20before\x20calling.','inputSchema':Guard2File_InputSchema,'outputSchema':Guard2File_OutputWrappedSchema,'annotations':{'readOnlyHint':!![],'destructiveHint':![],'idempotentHint':!![],'openWorldHint':!![]},'_meta':createToolMeta('generate\x20file',['guard','export','file','json','markdown','on-chain'])},'errorShapeBuilder':strictStatusErrorShape},{'name':'machineNode2file','handler':handleMachineNode2File,'config':{'title':'⚙️\x20Machine\x20Node\x20to\x20File\x20-\x20Export\x20Machine\x20Node\x20Definition','summary':'Export\x20machine\x20nodes\x20to\x20a\x20local\x20JSON/Markdown\x20file.','description':'Export\x20a\x20Machine\x20object\x27s\x20node\x20definition\x20from\x20the\x20blockchain\x20to\x20a\x20local\x20JSON\x20or\x20Markdown\x20file\x20for\x20editing\x20and\x20creating\x20new\x20Machine\x20objects.\x20Note:\x20To\x20query\x20on-chain\x20object\x20information,\x20use\x20the\x20\x27query_toolkit\x27\x20tool\x20instead.\x0a\x0a💡\x20Schema\x20hint:\x20Use\x20schema_query\x20with\x20action=\x27get\x27\x20and\x20name=\x27machineNode2file\x27\x20to\x20retrieve\x20the\x20exact\x20parameter\x20schema\x20before\x20calling.','inputSchema':MachineNode2File_InputSchema,'outputSchema':MachineNode2File_OutputWrappedSchema,'annotations':{'readOnlyHint':!![],'destructiveHint':![],'idempotentHint':!![],'openWorldHint':!![]},'_meta':createToolMeta('generate\x20file',['machine','export','file','json','markdown','on-chain','workflow'])},'errorShapeBuilder':strictStatusErrorShape}];
1
+ import{z}from'zod';import{handleWipOperations}from'../handlers/wip.js';import{handleGuard2File,handleMachineNode2File}from'../handlers/file-export.js';import{strictStatusErrorShape}from'../wrap.js';import{createToolMeta,WipOperationsSchema,WipOperationOutputSchema,Guard2File_InputSchema,Guard2File_OutputWrappedSchema,MachineNode2File_InputSchema,MachineNode2File_OutputWrappedSchema}from'../../schema/index.js';export const FILE_TOOLS=[{'name':'wip_file','handler':handleWipOperations,'config':{'title':'🤝\x20Witness\x20Immutable\x20Promise\x20File\x20Operations','summary':'WIP\x20promise\x20file\x20operations:\x20generate,\x20verify,\x20sign,\x20wip2html,\x20upload/list/delete\x20on\x20wip\x20storage.','description':'generate\x20(create\x20WIP\x20files\x20from\x20markdown\x20and\x20images),\x20verify\x20(integrity\x20check),\x20sign\x20(add\x20signatures),\x20wip2html\x20(convert\x20to\x20HTML),\x20or\x20storage\x20operations:\x20upload\x20/\x20storage_list\x20/\x20storage_delete.\x0a\x0aStorage\x20options\x20for\x20type=\x27upload\x27:\x0a\x20\x20•\x20storage=\x27store\x27\x20(default):\x20official\x20FREE\x20store\x20wip.store.wowok.net\x20—\x20zero\x20setup,\x20files\x20get\x20a\x20public\x20hash-addressed\x20URL\x20(https://wip.store.wowok.net/f/{hash}).\x20Free\x20tier\x20limited\x20to\x2010\x20files\x20per\x20account;\x20when\x20the\x20quota\x20is\x20hit\x20the\x20error\x20returns\x20the\x20stored\x20file\x20list\x20for\x20deletion\x20(use\x20storage_delete).\x20Declaration:\x20files\x20are\x20retained\x20for\x206\x20months\x20(180\x20days);\x20free\x20best-effort\x20service\x20—\x20availability\x20and\x20data\x20survival\x20are\x20not\x20guaranteed\x20(force\x20majeure\x20excepted);\x20expired\x20files\x20are\x20NEVER\x20deleted\x20automatically\x20(manual\x20administrator\x20purge\x20only).\x0a\x20\x20•\x20storage=\x27custom\x27\x20(recommended):\x20your\x20own\x20or\x20any\x20third-party\x20wip-storage-compatible\x20service\x20via\x20customBaseUrl\x20—\x20no\x20store\x20quota,\x20full\x20control,\x20permanent\x20self-managed\x20hosting.\x0a\x0a🌐\x20Network\x20independence:\x20WIP\x20files\x20are\x20OFF-CHAIN\x20—\x20the\x20same\x20public\x20URL\x20and\x20the\x20same\x20stored\x20files\x20work\x20on\x20BOTH\x20testnet\x20and\x20mainnet;\x20storage_list/storage_delete\x20authenticate\x20with\x20the\x20account\x20key\x20and\x20never\x20touch\x20the\x20chain.\x0a\x0a⚠️\x20Large\x20WIP\x20files\x20(multi-MB,\x20image-heavy)\x20are\x20sensitive\x20to\x20network\x20conditions:\x20keep\x20files\x20small\x20(compress\x20images\x20before\x20generate;\x20each\x20image\x20≤\x202MB,\x20total\x20≤\x2010MB),\x20expect\x20longer\x20upload\x20times,\x20retry\x20on\x20transient\x20network\x20failures,\x20and\x20confirm\x20reachability\x20afterwards\x20with\x20type=\x27verify\x27\x20on\x20the\x20returned\x20public\x20URL.\x0a\x0a⚠️\x20IMPORTANT\x20—\x20On-chain\x20WIP\x20URL\x20requirement:\x20When\x20using\x20a\x20WIP\x20file\x20URL\x20in\x20`service.sales[].wip`\x20(stored\x20on-chain),\x20the\x20URL\x20MUST\x20be\x20publicly\x20reachable.\x20Local\x20file\x20paths\x20(e.g.,\x20\x27C:\x5c\x5cpath\x5c\x5cfile.wip\x27\x20or\x20\x27/home/user/file.wip\x27)\x20are\x20NOT\x20acceptable\x20on-chain\x20—\x20they\x20only\x20work\x20locally\x20and\x20will\x20fail\x20verification\x20for\x20buyers.\x0a\x0aDeployment\x20options\x20for\x20the\x20.wip\x20file:\x0a\x20\x20•\x20wip\x20storage\x20service\x20(type=\x27upload\x27)\x20—\x20preferred,\x20gives\x20a\x20stable\x20public\x20URL\x0a\x20\x20•\x20GitHub\x20Pages:\x20https://raw.githubusercontent.com/<user>/<repo>/<branch>/<file>.wip\x0a\x20\x20•\x20IPFS:\x20https://ipfs.io/ipfs/<CID>\x20or\x20https://cloudflare-ipfs.com/ipfs/<CID>\x20(upload\x20via\x20pinata.cloud)\x0a\x20\x20•\x20User\x27s\x20own\x20static\x20website\x20URL\x0a\x0aUse\x20type=\x27generate\x27\x20to\x20create\x20the\x20WIP\x20file,\x20sign\x20it\x20with\x20type=\x27sign\x27,\x20upload\x20with\x20type=\x27upload\x27,\x20then\x20use\x20the\x20resulting\x20URL\x20in\x20service.sales[].wip.\x0a\x0a💡\x20Schema\x20hint:\x20Use\x20schema_query\x20with\x20action=\x27get\x27\x20and\x20name=\x27wip_file\x27\x20to\x20retrieve\x20the\x20exact\x20parameter\x20schema\x20before\x20calling.','inputSchema':WipOperationsSchema,'outputSchema':z['object']({'result':WipOperationOutputSchema}),'annotations':{'readOnlyHint':![],'destructiveHint':![],'idempotentHint':![],'openWorldHint':!![]},'_meta':createToolMeta('operation',['wip','promise','file-generation','verification','signature','upload','storage','wip.store.wowok.net'])}},{'name':'guard2file','handler':handleGuard2File,'config':{'title':'📄\x20Guard\x20to\x20File\x20-\x20Export\x20Guard\x20Definition','summary':'Export\x20guard\x20rules\x20to\x20a\x20local\x20JSON/Markdown\x20file.','description':'Export\x20a\x20Guard\x20object\x27s\x20definition\x20from\x20the\x20blockchain\x20to\x20a\x20local\x20JSON\x20or\x20Markdown\x20file\x20for\x20editing\x20and\x20creating\x20new\x20Guard\x20objects.\x20Note:\x20To\x20query\x20on-chain\x20object\x20information,\x20use\x20the\x20\x27query_toolkit\x27\x20tool\x20instead.\x0a\x0a💡\x20Schema\x20hint:\x20Use\x20schema_query\x20with\x20action=\x27get\x27\x20and\x20name=\x27guard2file\x27\x20to\x20retrieve\x20the\x20exact\x20parameter\x20schema\x20before\x20calling.','inputSchema':Guard2File_InputSchema,'outputSchema':Guard2File_OutputWrappedSchema,'annotations':{'readOnlyHint':!![],'destructiveHint':![],'idempotentHint':!![],'openWorldHint':!![]},'_meta':createToolMeta('generate\x20file',['guard','export','file','json','markdown','on-chain'])},'errorShapeBuilder':strictStatusErrorShape},{'name':'machineNode2file','handler':handleMachineNode2File,'config':{'title':'⚙️\x20Machine\x20Node\x20to\x20File\x20-\x20Export\x20Machine\x20Node\x20Definition','summary':'Export\x20machine\x20nodes\x20to\x20a\x20local\x20JSON/Markdown\x20file.','description':'Export\x20a\x20Machine\x20object\x27s\x20node\x20definition\x20from\x20the\x20blockchain\x20to\x20a\x20local\x20JSON\x20or\x20Markdown\x20file\x20for\x20editing\x20and\x20creating\x20new\x20Machine\x20objects.\x20Note:\x20To\x20query\x20on-chain\x20object\x20information,\x20use\x20the\x20\x27query_toolkit\x27\x20tool\x20instead.\x0a\x0a💡\x20Schema\x20hint:\x20Use\x20schema_query\x20with\x20action=\x27get\x27\x20and\x20name=\x27machineNode2file\x27\x20to\x20retrieve\x20the\x20exact\x20parameter\x20schema\x20before\x20calling.','inputSchema':MachineNode2File_InputSchema,'outputSchema':MachineNode2File_OutputWrappedSchema,'annotations':{'readOnlyHint':!![],'destructiveHint':![],'idempotentHint':!![],'openWorldHint':!![]},'_meta':createToolMeta('generate\x20file',['machine','export','file','json','markdown','on-chain','workflow'])},'errorShapeBuilder':strictStatusErrorShape}];
@@ -1 +1 @@
1
- export function classifyWipPath(a){if(!a||typeof a!=='string')return{'type':'unknown','is_local':![],'is_network':![],'description':'Empty\x20or\x20invalid\x20path'};if(a['startsWith']('data:'))return{'type':'data_url','is_local':![],'is_network':!![],'description':'Data\x20URL\x20—\x20embedded\x20content,\x20globally\x20reachable'};if(a['startsWith']('ipfs://'))return{'type':'ipfs','is_local':![],'is_network':!![],'description':'IPFS\x20URI\x20—\x20resolve\x20via\x20any\x20public\x20gateway'};const b=[/^https?:\/\/ipfs\.io\//i,/^https?:\/\/cloudflare-ipfs\.com\//i,/^https?:\/\/gateway\.pinata\.cloud\//i,/^https?:\/\/dweb\.link\//i,/^https?:\/\/[^/]*pinata\.cloud\//i];if(b['some'](d=>d['test'](a)))return{'type':'ipfs','is_local':![],'is_network':!![],'description':'IPFS\x20HTTP\x20gateway\x20URL\x20—\x20globally\x20reachable'};if(/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\]|0\.0\.0\.0)([:/]|$)/i['test'](a))return{'type':'local_http','is_local':!![],'is_network':![],'description':'Local\x20HTTP\x20URL\x20(localhost/loopback)\x20—\x20reachable\x20only\x20on\x20this\x20machine,\x20NOT\x20by\x20customers'};const c=/^https?:\/\/(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})([:/]|$)/i;if(c['test'](a))return{'type':'local_http','is_local':!![],'is_network':![],'description':'LAN\x20HTTP\x20URL\x20(private\x20IP)\x20—\x20reachable\x20only\x20on\x20the\x20local\x20network,\x20NOT\x20by\x20customers'};if(/^https?:\/\//i['test'](a))return{'type':'http_url','is_local':![],'is_network':!![],'description':'HTTP(S)\x20URL\x20—\x20globally\x20reachable\x20if\x20server\x20returns\x20200'};if(/^[A-Za-z]:[\\/]/['test'](a))return{'type':'local_windows','is_local':!![],'is_network':![],'description':'Windows\x20local\x20path\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};if(a['startsWith']('/'))return{'type':'local_unix','is_local':!![],'is_network':![],'description':'Unix\x20local\x20path\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};if(a['startsWith']('./')||a['startsWith']('../')||a==='.'||a==='..')return{'type':'local_relative','is_local':!![],'is_network':![],'description':'Relative\x20local\x20path\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};if(!a['includes']('://')&&!a['startsWith']('data:'))return{'type':'local_relative','is_local':!![],'is_network':![],'description':'Local\x20file\x20path\x20(no\x20scheme)\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};return{'type':'unknown','is_local':![],'is_network':![],'description':'Unrecognized\x20path\x20format'};}export function getDeployOptions(a){const b=a['replace'](/'/g,'\x27\x5c\x27\x27'),c=a['split'](/[\\/]/)['pop']()||'file.wip';return[{'name':'GitHub\x20Pages\x20(Recommended)','description':'Upload\x20the\x20.wip\x20file\x20to\x20a\x20GitHub\x20repository\x20and\x20serve\x20it\x20via\x20GitHub\x20Pages.\x20'+'Free,\x20stable,\x20HTTPS-enabled,\x20no\x20expiration.','difficulty':'easy','free':!![],'result_url_pattern':'https://<your-username>.github.io/<repo>/<file>.wip','steps':['//\x201.\x20Create\x20a\x20new\x20GitHub\x20repository\x20(e.g.,\x20\x27wowok-wip\x27)\x20via\x20https://github.com/new','//\x202.\x20Make\x20it\x20PUBLIC\x20so\x20the\x20file\x20is\x20world-readable.','//\x203.\x20Copy\x20your\x20local\x20WIP\x20file\x20into\x20the\x20repo:','git\x20clone\x20https://github.com/<your-username>/wowok-wip.git','cp\x20\x27'+b+'\x27\x20wowok-wip/'+c,'cd\x20wowok-wip','git\x20add\x20'+c,'git\x20commit\x20-m\x20\x22Add\x20WIP\x20file\x22','git\x20push\x20origin\x20main','//\x204.\x20Enable\x20GitHub\x20Pages:\x20repo\x20→\x20Settings\x20→\x20Pages\x20→\x20Source\x20→\x20\x27main\x27\x20branch\x20→\x20/(root)\x20→\x20Save','//\x205.\x20Wait\x2030-60\x20seconds\x20for\x20deployment,\x20then\x20verify\x20the\x20URL\x20is\x20reachable:','curl\x20-I\x20https://<your-username>.github.io/wowok-wip/'+c,'//\x206.\x20Update\x20your\x20Service\x20on-chain\x20with\x20the\x20new\x20public\x20URL:','//\x20\x20\x20\x20Call\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27https://...\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'],'notes':['If\x20the\x20repo\x20already\x20has\x20Pages\x20enabled\x20on\x20the\x20main\x20branch,\x20step\x204\x20can\x20be\x20skipped.','GitHub\x20Pages\x20serves\x20files\x20up\x20to\x2025\x20MB\x20—\x20well\x20above\x20typical\x20WIP\x20sizes\x20(<\x201\x20MB).','URL\x20is\x20case-sensitive;\x20ensure\x20the\x20filename\x20in\x20the\x20URL\x20matches\x20exactly.']},{'name':'IPFS\x20via\x20Pinata\x20(Free\x20gateway)','description':'Upload\x20the\x20.wip\x20file\x20to\x20IPFS\x20through\x20Pinata\x27s\x20free\x20gateway.\x20'+'Content-addressed\x20—\x20the\x20CID\x20hash\x20also\x20serves\x20as\x20an\x20integrity\x20check.','difficulty':'medium','free':!![],'result_url_pattern':'https://gateway.pinata.cloud/ipfs/<CID>\x20\x20(or\x20\x20https://ipfs.io/ipfs/<CID>)','steps':['//\x201.\x20Sign\x20up\x20for\x20a\x20free\x20Pinata\x20account\x20at\x20https://app.pinata.cloud/\x20(1\x20GB\x20free\x20storage).','//\x202.\x20Get\x20your\x20API\x20key\x20from\x20https://app.pinata.cloud/keys\x20(generate\x20a\x20new\x20key\x20with\x20\x27pinFileToIPFS\x27\x20scope).','//\x203.\x20Upload\x20your\x20local\x20WIP\x20file\x20via\x20curl:','curl\x20-X\x20POST\x20https://api.pinata.cloud/pinning/pinFileToIPFS\x20\x5c','\x20\x20-H\x20\x22Authorization:\x20Bearer\x20<YOUR_PINATA_API_KEY>\x22\x20\x5c','\x20\x20-F\x20\x22file=@\x27'+b+'\x27\x22','//\x204.\x20Pinata\x20returns\x20JSON\x20with\x20\x27IpfsHash\x27\x20(the\x20CID).\x20Extract\x20it:','//\x20\x20\x20\x20Example\x20response:\x20{\x20\x22IpfsHash\x22:\x20\x22QmXYZ...\x22,\x20\x22PinSize\x22:\x2012345,\x20\x22Timestamp\x22:\x20\x22...\x22\x20}','//\x205.\x20Verify\x20the\x20file\x20is\x20reachable\x20via\x20the\x20public\x20gateway:','curl\x20-I\x20https://gateway.pinata.cloud/ipfs/<CID>','//\x206.\x20(Optional)\x20Use\x20ipfs://<CID>\x20as\x20the\x20wip_url\x20—\x20the\x20SDK\x20resolves\x20it.','//\x207.\x20Update\x20your\x20Service\x20on-chain\x20with\x20the\x20IPFS\x20URL\x20or\x20CID:','//\x20\x20\x20\x20Call\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27https://gateway.pinata.cloud/ipfs/<CID>\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'],'notes':['Pinata\x20free\x20tier:\x201\x20GB\x20storage,\x20100\x20uploads/day\x20—\x20sufficient\x20for\x20WIP\x20files.','For\x20long-term\x20durability,\x20also\x20pin\x20via\x20another\x20gateway\x20(e.g.,\x20nft.storage).','IPFS\x20CIDs\x20are\x20content-addressed\x20—\x20if\x20the\x20file\x20changes,\x20the\x20CID\x20changes.\x20This\x20is\x20a\x20feature,\x20not\x20a\x20bug.']},{'name':'User\x27s\x20own\x20website\x20/\x20static\x20host','description':'If\x20you\x20already\x20operate\x20a\x20website\x20or\x20static\x20host\x20(e.g.,\x20nginx,\x20Vercel,\x20Netlify,\x20Cloudflare\x20Pages),\x20'+'upload\x20the\x20.wip\x20file\x20there\x20and\x20use\x20its\x20public\x20URL.','difficulty':'medium','free':!![],'result_url_pattern':'https://<your-domain>/<path>/<file>.wip','steps':['//\x201.\x20Copy\x20your\x20local\x20WIP\x20file\x20to\x20your\x20web\x20server\x27s\x20static\x20directory:','scp\x20\x27'+b+'\x27\x20user@your-server:/var/www/html/wowok/'+c,'//\x202.\x20Ensure\x20the\x20server\x20sets\x20Content-Type:\x20application/json\x20(or\x20application/octet-stream)\x20for\x20.wip\x20files.','//\x20\x20\x20\x20For\x20nginx,\x20add\x20to\x20your\x20server\x20block:','//\x20\x20\x20\x20\x20\x20\x20\x20location\x20~\x20\x5c.wip$\x20{\x20default_type\x20application/json;\x20}','//\x203.\x20Verify\x20the\x20file\x20is\x20reachable:','curl\x20-I\x20https://<your-domain>/wowok/'+c,'//\x204.\x20Update\x20your\x20Service\x20on-chain\x20with\x20the\x20new\x20public\x20URL:','//\x20\x20\x20\x20Call\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27https://<your-domain>/wowok/<file>.wip\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'],'notes':['Make\x20sure\x20CORS\x20is\x20permissive\x20if\x20the\x20verifier\x20fetches\x20via\x20browser\x20(Access-Control-Allow-Origin:\x20*).','Ensure\x20HTTPS\x20is\x20enabled\x20—\x20most\x20verifiers\x20reject\x20plain\x20HTTP.']},{'name':'Data\x20URL\x20embedding\x20(small\x20files\x20only)','description':'Embed\x20the\x20entire\x20WIP\x20file\x20as\x20a\x20base64\x20data\x20URL\x20directly\x20in\x20the\x20wip_url\x20field.\x20'+'No\x20external\x20hosting\x20required,\x20but\x20on-chain\x20storage\x20cost\x20grows\x20with\x20file\x20size.','difficulty':'easy','free':!![],'result_url_pattern':'data:application/json;base64,<base64-encoded-content>','steps':['//\x201.\x20Encode\x20your\x20local\x20WIP\x20file\x20as\x20a\x20base64\x20data\x20URL:','//\x20\x20\x20\x20On\x20Linux/macOS:','echo\x20\x22data:application/json;base64,$(base64\x20-w0\x20\x27'+b+'\x27)\x22','//\x20\x20\x20\x20On\x20Windows\x20(PowerShell):','$bytes\x20=\x20[System.IO.File]::ReadAllBytes(\x27'+a+'\x27);\x20$b64\x20=\x20[System.Convert]::ToBase64String($bytes);\x20Write-Output\x20\x22data:application/json;base64,$b64\x22','//\x202.\x20Use\x20the\x20resulting\x20data\x20URL\x20as\x20the\x20wip_url\x20field\x20when\x20updating\x20the\x20Service.','//\x203.\x20Note:\x20data\x20URLs\x20are\x20NOT\x20recommended\x20for\x20files\x20>\x2050\x20KB\x20due\x20to\x20on-chain\x20storage\x20cost.'],'notes':['Only\x20suitable\x20for\x20very\x20small\x20WIP\x20files\x20(typically\x20<\x2010\x20KB).','Data\x20URLs\x20cannot\x20be\x20updated\x20without\x20an\x20on-chain\x20transaction\x20—\x20content\x20is\x20literally\x20embedded.','Prefer\x20GitHub\x20Pages\x20or\x20IPFS\x20for\x20files\x20>\x2010\x20KB.']}];}export function analyzeWipDeployment(a){const b=classifyWipPath(a),c=b['is_local'];let d,e=[];if(c)b['type']==='local_http'?d='The\x20WIP\x20URL\x20\x27'+a+'\x27\x20is\x20a\x20'+b['description']+'.\x20'+'It\x20is\x20reachable\x20only\x20from\x20the\x20merchant\x27s\x20own\x20machine/LAN\x20—\x20customers\x20and\x20'+'on-chain\x20verifiers\x20on\x20other\x20machines\x20CANNOT\x20fetch\x20it.\x20Storing\x20it\x20on-chain\x20'+'makes\x20every\x20customer\x20order\x20fail.\x20'+'Deploy\x20the\x20.wip\x20file\x20to\x20a\x20public\x20host\x20(GitHub\x20Pages,\x20IPFS,\x20or\x20your\x20own\x20website)\x20'+'and\x20update\x20the\x20Service\x27s\x20wip_url\x20with\x20the\x20public\x20URL.':d='The\x20WIP\x20path\x20\x27'+a+'\x27\x20is\x20a\x20LOCAL\x20'+b['type']+'\x20path.\x20'+'Local\x20paths\x20stored\x20on-chain\x20are\x20unreachable\x20by\x20customers\x20and\x20verifiers.\x20'+'Deploy\x20the\x20.wip\x20file\x20to\x20a\x20public\x20host\x20(GitHub\x20Pages,\x20IPFS,\x20or\x20your\x20own\x20website)\x20'+'and\x20update\x20the\x20Service\x27s\x20wip_url\x20with\x20the\x20public\x20URL.',e=getDeployOptions(a);else{if(b['type']==='http_url')d='The\x20WIP\x20path\x20is\x20an\x20HTTP(S)\x20URL\x20—\x20verify\x20the\x20server\x20returns\x20200.\x20'+'If\x20the\x20URL\x20returns\x20404/403,\x20the\x20file\x20may\x20have\x20been\x20moved\x20or\x20deleted.',e=[];else{if(b['type']==='ipfs')d='The\x20WIP\x20path\x20is\x20an\x20IPFS\x20URL\x20—\x20verify\x20the\x20gateway\x20is\x20responsive.\x20'+'If\x20the\x20CID\x20is\x20unreachable,\x20the\x20file\x20may\x20have\x20been\x20unpinned.',e=[];else b['type']==='data_url'?(d='The\x20WIP\x20path\x20is\x20a\x20data\x20URL\x20—\x20content\x20is\x20embedded,\x20no\x20deployment\x20needed.',e=[]):(d='Unrecognized\x20WIP\x20path\x20format:\x20\x27'+a+'\x27',e=[]);}}return{'path':a,'classification':b,'needs_deployment':c,'reason':d,'options':e,'remind_update_hash':c};}export function formatDeployHints(a){if(!a['needs_deployment']&&a['options']['length']===0x0)return'';const b=[];b['push']('===\x20WIP\x20Deployment\x20Assistance\x20==='),b['push'](''),b['push']('Path:\x20'+a['path']),b['push']('Type:\x20'+a['classification']['description']),b['push']('Reason:\x20'+a['reason']),b['push']('');if(a['options']['length']>0x0){b['push']('Recommended\x20deployment\x20options:'),b['push']('');for(const c of a['options']){b['push']('▶\x20'+c['name']+'\x20(difficulty:\x20'+c['difficulty']+',\x20free:\x20'+c['free']+')'),b['push']('\x20\x20'+c['description']),b['push']('\x20\x20Resulting\x20URL\x20pattern:\x20'+c['result_url_pattern']),b['push']('\x20\x20Steps:');for(const d of c['steps']){b['push']('\x20\x20\x20\x20'+d);}if(c['notes']&&c['notes']['length']>0x0){b['push']('\x20\x20Notes:');for(const e of c['notes']){b['push']('\x20\x20\x20\x20-\x20'+e);}}b['push']('');}}return a['remind_update_hash']&&(b['push']('⚠️\x20After\x20deploying,\x20compute\x20the\x20new\x20WIP\x20hash\x20and\x20update\x20the\x20Service:'),b['push']('\x20\x201.\x20Re-run\x20wip_file\x20{\x20type:\x20\x27verify\x27,\x20wipFilePath:\x20\x27<new-public-url>\x27\x20}\x20to\x20confirm\x20the\x20file\x20is\x20reachable.'),b['push']('\x20\x202.\x20Extract\x20the\x20meta.hash\x20from\x20the\x20WIP\x20file\x20(or\x20use\x20wip_file\x20{\x20type:\x20\x27verify\x27\x20}\x20result).'),b['push']('\x20\x203.\x20Update\x20the\x20Service\x20on-chain:\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27<new-public-url>\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'),b['push']('')),b['push']('==============================='),b['join']('\x0a');}
1
+ export function classifyWipPath(a){if(!a||typeof a!=='string')return{'type':'unknown','is_local':![],'is_network':![],'description':'Empty\x20or\x20invalid\x20path'};if(a['startsWith']('data:'))return{'type':'data_url','is_local':![],'is_network':!![],'description':'Data\x20URL\x20—\x20embedded\x20content,\x20globally\x20reachable'};if(a['startsWith']('ipfs://'))return{'type':'ipfs','is_local':![],'is_network':!![],'description':'IPFS\x20URI\x20—\x20resolve\x20via\x20any\x20public\x20gateway'};const b=[/^https?:\/\/ipfs\.io\//i,/^https?:\/\/cloudflare-ipfs\.com\//i,/^https?:\/\/gateway\.pinata\.cloud\//i,/^https?:\/\/dweb\.link\//i,/^https?:\/\/[^/]*pinata\.cloud\//i];if(b['some'](d=>d['test'](a)))return{'type':'ipfs','is_local':![],'is_network':!![],'description':'IPFS\x20HTTP\x20gateway\x20URL\x20—\x20globally\x20reachable'};if(/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\]|0\.0\.0\.0)([:/]|$)/i['test'](a))return{'type':'local_http','is_local':!![],'is_network':![],'description':'Local\x20HTTP\x20URL\x20(localhost/loopback)\x20—\x20reachable\x20only\x20on\x20this\x20machine,\x20NOT\x20by\x20customers'};const c=/^https?:\/\/(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})([:/]|$)/i;if(c['test'](a))return{'type':'local_http','is_local':!![],'is_network':![],'description':'LAN\x20HTTP\x20URL\x20(private\x20IP)\x20—\x20reachable\x20only\x20on\x20the\x20local\x20network,\x20NOT\x20by\x20customers'};if(/^https?:\/\//i['test'](a))return{'type':'http_url','is_local':![],'is_network':!![],'description':'HTTP(S)\x20URL\x20—\x20globally\x20reachable\x20if\x20server\x20returns\x20200'};if(/^[A-Za-z]:[\\/]/['test'](a))return{'type':'local_windows','is_local':!![],'is_network':![],'description':'Windows\x20local\x20path\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};if(a['startsWith']('/'))return{'type':'local_unix','is_local':!![],'is_network':![],'description':'Unix\x20local\x20path\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};if(a['startsWith']('./')||a['startsWith']('../')||a==='.'||a==='..')return{'type':'local_relative','is_local':!![],'is_network':![],'description':'Relative\x20local\x20path\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};if(!a['includes']('://')&&!a['startsWith']('data:'))return{'type':'local_relative','is_local':!![],'is_network':![],'description':'Local\x20file\x20path\x20(no\x20scheme)\x20—\x20NOT\x20reachable\x20by\x20customers/AI'};return{'type':'unknown','is_local':![],'is_network':![],'description':'Unrecognized\x20path\x20format'};}export function getDeployOptions(a){const b=a['replace'](/'/g,'\x27\x5c\x27\x27'),c=a['split'](/[\\/]/)['pop']()||'file.wip';return[{'name':'Wowok\x20WIP\x20storage\x20service\x20(Recommended)','description':'Upload\x20the\x20.wip\x20file\x20directly\x20from\x20the\x20MCP\x20with\x20wip_file\x20type=\x27upload\x27.\x20'+'Default\x20is\x20the\x20official\x20FREE\x20store\x20wip.store.wowok.net\x20(limited\x20to\x2010\x20files\x20per\x20account);\x20'+'with\x20storage=\x27custom\x27\x20any\x20self-hosted\x20or\x20third-party\x20wip\x20storage\x20service\x20works\x20(no\x20store\x20quota,\x20full\x20control).','difficulty':'easy','free':!![],'result_url_pattern':'https://wip.store.wowok.net/f/{hash}\x20\x20\x20(or\x20your\x20custom\x20service\x20base\x20URL\x20+\x20/f/{hash})','steps':['//\x201.\x20Generate\x20the\x20WIP\x20file:\x20wip_file\x20{\x20type:\x20\x27generate\x27,\x20options:\x20{\x20markdown_text:\x20\x27...\x27\x20}\x20}','//\x202.\x20Sign\x20it\x20with\x20your\x20account:\x20wip_file\x20{\x20type:\x20\x27sign\x27,\x20wipFilePath:\x20\x27<file>\x27,\x20account:\x20\x27<account>\x27\x20}','//\x203.\x20Upload\x20to\x20the\x20official\x20free\x20store:\x20wip_file\x20{\x20type:\x20\x27upload\x27,\x20wipFilePath:\x20\x27<file>\x27,\x20account:\x20\x27<account>\x27\x20}','//\x20\x20\x20\x20Or\x20use\x20your\x20own\x20/\x20a\x20third-party\x20service:\x20wip_file\x20{\x20type:\x20\x27upload\x27,\x20wipFilePath:\x20\x27<file>\x27,\x20storage:\x20\x27custom\x27,\x20customBaseUrl:\x20\x27https://your-wip-service.example.com\x27\x20}','//\x204.\x20Use\x20the\x20returned\x20URL\x20(base_url\x20+\x20/f/{hash})\x20as\x20the\x20Service\x27s\x20wip_url:','//\x20\x20\x20\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27<public-url>\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}','//\x205.\x20Confirm\x20reachability:\x20wip_file\x20{\x20type:\x20\x27verify\x27,\x20wipFilePath:\x20\x27<public-url>\x27\x20}'],'notes':['Official\x20free\x20store\x20is\x20limited\x20to\x2010\x20files\x20per\x20account\x20—\x20free\x20up\x20space\x20with\x20wip_file\x20type=\x27storage_delete\x27\x20when\x20the\x20quota\x20is\x20hit.','Official\x20free\x20store\x20declaration:\x20files\x20are\x20retained\x20for\x206\x20months\x20(180\x20days);\x20free\x20best-effort\x20service\x20—\x20force\x20majeure\x20excepted;\x20expired\x20files\x20are\x20NEVER\x20deleted\x20automatically\x20(manual\x20admin\x20purge\x20only).\x20For\x20permanent\x20hosting\x20use\x20storage=\x27custom\x27.','The\x20public\x20WIP\x20URL\x20is\x20network-independent:\x20the\x20same\x20file\x20serves\x20buyers\x20on\x20both\x20testnet\x20and\x20mainnet.','Large\x20WIP\x20files\x20(multi-MB,\x20image-heavy)\x20are\x20network-sensitive:\x20compress\x20images\x20before\x20generate\x20and\x20retry\x20transient\x20upload\x20failures.']},{'name':'GitHub\x20Pages','description':'Upload\x20the\x20.wip\x20file\x20to\x20a\x20GitHub\x20repository\x20and\x20serve\x20it\x20via\x20GitHub\x20Pages.\x20'+'Free,\x20stable,\x20HTTPS-enabled,\x20no\x20expiration.','difficulty':'easy','free':!![],'result_url_pattern':'https://<your-username>.github.io/<repo>/<file>.wip','steps':['//\x201.\x20Create\x20a\x20new\x20GitHub\x20repository\x20(e.g.,\x20\x27wowok-wip\x27)\x20via\x20https://github.com/new','//\x202.\x20Make\x20it\x20PUBLIC\x20so\x20the\x20file\x20is\x20world-readable.','//\x203.\x20Copy\x20your\x20local\x20WIP\x20file\x20into\x20the\x20repo:','git\x20clone\x20https://github.com/<your-username>/wowok-wip.git','cp\x20\x27'+b+'\x27\x20wowok-wip/'+c,'cd\x20wowok-wip','git\x20add\x20'+c,'git\x20commit\x20-m\x20\x22Add\x20WIP\x20file\x22','git\x20push\x20origin\x20main','//\x204.\x20Enable\x20GitHub\x20Pages:\x20repo\x20→\x20Settings\x20→\x20Pages\x20→\x20Source\x20→\x20\x27main\x27\x20branch\x20→\x20/(root)\x20→\x20Save','//\x205.\x20Wait\x2030-60\x20seconds\x20for\x20deployment,\x20then\x20verify\x20the\x20URL\x20is\x20reachable:','curl\x20-I\x20https://<your-username>.github.io/wowok-wip/'+c,'//\x206.\x20Update\x20your\x20Service\x20on-chain\x20with\x20the\x20new\x20public\x20URL:','//\x20\x20\x20\x20Call\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27https://...\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'],'notes':['If\x20the\x20repo\x20already\x20has\x20Pages\x20enabled\x20on\x20the\x20main\x20branch,\x20step\x204\x20can\x20be\x20skipped.','GitHub\x20Pages\x20serves\x20files\x20up\x20to\x2025\x20MB\x20—\x20well\x20above\x20typical\x20WIP\x20sizes\x20(<\x201\x20MB).','URL\x20is\x20case-sensitive;\x20ensure\x20the\x20filename\x20in\x20the\x20URL\x20matches\x20exactly.']},{'name':'IPFS\x20via\x20Pinata\x20(Free\x20gateway)','description':'Upload\x20the\x20.wip\x20file\x20to\x20IPFS\x20through\x20Pinata\x27s\x20free\x20gateway.\x20'+'Content-addressed\x20—\x20the\x20CID\x20hash\x20also\x20serves\x20as\x20an\x20integrity\x20check.','difficulty':'medium','free':!![],'result_url_pattern':'https://gateway.pinata.cloud/ipfs/<CID>\x20\x20(or\x20\x20https://ipfs.io/ipfs/<CID>)','steps':['//\x201.\x20Sign\x20up\x20for\x20a\x20free\x20Pinata\x20account\x20at\x20https://app.pinata.cloud/\x20(1\x20GB\x20free\x20storage).','//\x202.\x20Get\x20your\x20API\x20key\x20from\x20https://app.pinata.cloud/keys\x20(generate\x20a\x20new\x20key\x20with\x20\x27pinFileToIPFS\x27\x20scope).','//\x203.\x20Upload\x20your\x20local\x20WIP\x20file\x20via\x20curl:','curl\x20-X\x20POST\x20https://api.pinata.cloud/pinning/pinFileToIPFS\x20\x5c','\x20\x20-H\x20\x22Authorization:\x20Bearer\x20<YOUR_PINATA_API_KEY>\x22\x20\x5c','\x20\x20-F\x20\x22file=@\x27'+b+'\x27\x22','//\x204.\x20Pinata\x20returns\x20JSON\x20with\x20\x27IpfsHash\x27\x20(the\x20CID).\x20Extract\x20it:','//\x20\x20\x20\x20Example\x20response:\x20{\x20\x22IpfsHash\x22:\x20\x22QmXYZ...\x22,\x20\x22PinSize\x22:\x2012345,\x20\x22Timestamp\x22:\x20\x22...\x22\x20}','//\x205.\x20Verify\x20the\x20file\x20is\x20reachable\x20via\x20the\x20public\x20gateway:','curl\x20-I\x20https://gateway.pinata.cloud/ipfs/<CID>','//\x206.\x20(Optional)\x20Use\x20ipfs://<CID>\x20as\x20the\x20wip_url\x20—\x20the\x20SDK\x20resolves\x20it.','//\x207.\x20Update\x20your\x20Service\x20on-chain\x20with\x20the\x20IPFS\x20URL\x20or\x20CID:','//\x20\x20\x20\x20Call\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27https://gateway.pinata.cloud/ipfs/<CID>\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'],'notes':['Pinata\x20free\x20tier:\x201\x20GB\x20storage,\x20100\x20uploads/day\x20—\x20sufficient\x20for\x20WIP\x20files.','For\x20long-term\x20durability,\x20also\x20pin\x20via\x20another\x20gateway\x20(e.g.,\x20nft.storage).','IPFS\x20CIDs\x20are\x20content-addressed\x20—\x20if\x20the\x20file\x20changes,\x20the\x20CID\x20changes.\x20This\x20is\x20a\x20feature,\x20not\x20a\x20bug.']},{'name':'User\x27s\x20own\x20website\x20/\x20static\x20host','description':'If\x20you\x20already\x20operate\x20a\x20website\x20or\x20static\x20host\x20(e.g.,\x20nginx,\x20Vercel,\x20Netlify,\x20Cloudflare\x20Pages),\x20'+'upload\x20the\x20.wip\x20file\x20there\x20and\x20use\x20its\x20public\x20URL.','difficulty':'medium','free':!![],'result_url_pattern':'https://<your-domain>/<path>/<file>.wip','steps':['//\x201.\x20Copy\x20your\x20local\x20WIP\x20file\x20to\x20your\x20web\x20server\x27s\x20static\x20directory:','scp\x20\x27'+b+'\x27\x20user@your-server:/var/www/html/wowok/'+c,'//\x202.\x20Ensure\x20the\x20server\x20sets\x20Content-Type:\x20application/json\x20(or\x20application/octet-stream)\x20for\x20.wip\x20files.','//\x20\x20\x20\x20For\x20nginx,\x20add\x20to\x20your\x20server\x20block:','//\x20\x20\x20\x20\x20\x20\x20\x20location\x20~\x20\x5c.wip$\x20{\x20default_type\x20application/json;\x20}','//\x203.\x20Verify\x20the\x20file\x20is\x20reachable:','curl\x20-I\x20https://<your-domain>/wowok/'+c,'//\x204.\x20Update\x20your\x20Service\x20on-chain\x20with\x20the\x20new\x20public\x20URL:','//\x20\x20\x20\x20Call\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27https://<your-domain>/wowok/<file>.wip\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'],'notes':['Make\x20sure\x20CORS\x20is\x20permissive\x20if\x20the\x20verifier\x20fetches\x20via\x20browser\x20(Access-Control-Allow-Origin:\x20*).','Ensure\x20HTTPS\x20is\x20enabled\x20—\x20most\x20verifiers\x20reject\x20plain\x20HTTP.']},{'name':'Data\x20URL\x20embedding\x20(small\x20files\x20only)','description':'Embed\x20the\x20entire\x20WIP\x20file\x20as\x20a\x20base64\x20data\x20URL\x20directly\x20in\x20the\x20wip_url\x20field.\x20'+'No\x20external\x20hosting\x20required,\x20but\x20on-chain\x20storage\x20cost\x20grows\x20with\x20file\x20size.','difficulty':'easy','free':!![],'result_url_pattern':'data:application/json;base64,<base64-encoded-content>','steps':['//\x201.\x20Encode\x20your\x20local\x20WIP\x20file\x20as\x20a\x20base64\x20data\x20URL:','//\x20\x20\x20\x20On\x20Linux/macOS:','echo\x20\x22data:application/json;base64,$(base64\x20-w0\x20\x27'+b+'\x27)\x22','//\x20\x20\x20\x20On\x20Windows\x20(PowerShell):','$bytes\x20=\x20[System.IO.File]::ReadAllBytes(\x27'+a+'\x27);\x20$b64\x20=\x20[System.Convert]::ToBase64String($bytes);\x20Write-Output\x20\x22data:application/json;base64,$b64\x22','//\x202.\x20Use\x20the\x20resulting\x20data\x20URL\x20as\x20the\x20wip_url\x20field\x20when\x20updating\x20the\x20Service.','//\x203.\x20Note:\x20data\x20URLs\x20are\x20NOT\x20recommended\x20for\x20files\x20>\x2050\x20KB\x20due\x20to\x20on-chain\x20storage\x20cost.'],'notes':['Only\x20suitable\x20for\x20very\x20small\x20WIP\x20files\x20(typically\x20<\x2010\x20KB).','Data\x20URLs\x20cannot\x20be\x20updated\x20without\x20an\x20on-chain\x20transaction\x20—\x20content\x20is\x20literally\x20embedded.','Prefer\x20GitHub\x20Pages\x20or\x20IPFS\x20for\x20files\x20>\x2010\x20KB.']}];}export function analyzeWipDeployment(a){const b=classifyWipPath(a),c=b['is_local'];let d,e=[];if(c)b['type']==='local_http'?d='The\x20WIP\x20URL\x20\x27'+a+'\x27\x20is\x20a\x20'+b['description']+'.\x20'+'It\x20is\x20reachable\x20only\x20from\x20the\x20merchant\x27s\x20own\x20machine/LAN\x20—\x20customers\x20and\x20'+'on-chain\x20verifiers\x20on\x20other\x20machines\x20CANNOT\x20fetch\x20it.\x20Storing\x20it\x20on-chain\x20'+'makes\x20every\x20customer\x20order\x20fail.\x20'+'Deploy\x20the\x20.wip\x20file\x20to\x20a\x20public\x20host\x20(GitHub\x20Pages,\x20IPFS,\x20or\x20your\x20own\x20website)\x20'+'and\x20update\x20the\x20Service\x27s\x20wip_url\x20with\x20the\x20public\x20URL.':d='The\x20WIP\x20path\x20\x27'+a+'\x27\x20is\x20a\x20LOCAL\x20'+b['type']+'\x20path.\x20'+'Local\x20paths\x20stored\x20on-chain\x20are\x20unreachable\x20by\x20customers\x20and\x20verifiers.\x20'+'Deploy\x20the\x20.wip\x20file\x20to\x20a\x20public\x20host\x20(GitHub\x20Pages,\x20IPFS,\x20or\x20your\x20own\x20website)\x20'+'and\x20update\x20the\x20Service\x27s\x20wip_url\x20with\x20the\x20public\x20URL.',e=getDeployOptions(a);else{if(b['type']==='http_url')d='The\x20WIP\x20path\x20is\x20an\x20HTTP(S)\x20URL\x20—\x20verify\x20the\x20server\x20returns\x20200.\x20'+'If\x20the\x20URL\x20returns\x20404/403,\x20the\x20file\x20may\x20have\x20been\x20moved\x20or\x20deleted.',e=[];else{if(b['type']==='ipfs')d='The\x20WIP\x20path\x20is\x20an\x20IPFS\x20URL\x20—\x20verify\x20the\x20gateway\x20is\x20responsive.\x20'+'If\x20the\x20CID\x20is\x20unreachable,\x20the\x20file\x20may\x20have\x20been\x20unpinned.',e=[];else b['type']==='data_url'?(d='The\x20WIP\x20path\x20is\x20a\x20data\x20URL\x20—\x20content\x20is\x20embedded,\x20no\x20deployment\x20needed.',e=[]):(d='Unrecognized\x20WIP\x20path\x20format:\x20\x27'+a+'\x27',e=[]);}}return{'path':a,'classification':b,'needs_deployment':c,'reason':d,'options':e,'remind_update_hash':c};}export function formatDeployHints(a){if(!a['needs_deployment']&&a['options']['length']===0x0)return'';const b=[];b['push']('===\x20WIP\x20Deployment\x20Assistance\x20==='),b['push'](''),b['push']('Path:\x20'+a['path']),b['push']('Type:\x20'+a['classification']['description']),b['push']('Reason:\x20'+a['reason']),b['push']('');if(a['options']['length']>0x0){b['push']('Recommended\x20deployment\x20options:'),b['push']('');for(const c of a['options']){b['push']('▶\x20'+c['name']+'\x20(difficulty:\x20'+c['difficulty']+',\x20free:\x20'+c['free']+')'),b['push']('\x20\x20'+c['description']),b['push']('\x20\x20Resulting\x20URL\x20pattern:\x20'+c['result_url_pattern']),b['push']('\x20\x20Steps:');for(const d of c['steps']){b['push']('\x20\x20\x20\x20'+d);}if(c['notes']&&c['notes']['length']>0x0){b['push']('\x20\x20Notes:');for(const e of c['notes']){b['push']('\x20\x20\x20\x20-\x20'+e);}}b['push']('');}}return a['remind_update_hash']&&(b['push']('⚠️\x20After\x20deploying,\x20compute\x20the\x20new\x20WIP\x20hash\x20and\x20update\x20the\x20Service:'),b['push']('\x20\x201.\x20Re-run\x20wip_file\x20{\x20type:\x20\x27verify\x27,\x20wipFilePath:\x20\x27<new-public-url>\x27\x20}\x20to\x20confirm\x20the\x20file\x20is\x20reachable.'),b['push']('\x20\x202.\x20Extract\x20the\x20meta.hash\x20from\x20the\x20WIP\x20file\x20(or\x20use\x20wip_file\x20{\x20type:\x20\x27verify\x27\x20}\x20result).'),b['push']('\x20\x203.\x20Update\x20the\x20Service\x20on-chain:\x20onchain_operations\x20{\x20operation_type:\x20\x27service\x27,\x20data:\x20{\x20object:\x20\x27<service-id>\x27,\x20sales:\x20{\x20op:\x20\x27set\x27,\x20sales:\x20[{\x20...,\x20wip_url:\x20\x27<new-public-url>\x27,\x20wip_hash:\x20\x27<hash>\x27\x20}]\x20}\x20}\x20}'),b['push']('')),b['push']('==============================='),b['join']('\x0a');}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wowok/agent-mcp",
3
- "version": "3.1.6",
3
+ "version": "3.1.7",
4
4
  "description": "Making It Easy for AI Agents to Communicate, Collaborate, Trade, and Trust.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -54,7 +54,7 @@
54
54
  "license": "Apache-2.0",
55
55
  "dependencies": {
56
56
  "@modelcontextprotocol/server": "^2.0.0",
57
- "@wowok/wowok": "3.1.6",
57
+ "@wowok/wowok": "3.1.7",
58
58
  "lodash": "^4.18.1",
59
59
  "zod": "^4.2.0"
60
60
  },