wao 0.40.2 → 0.41.0

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 (74) hide show
  1. package/cjs/accounts-web.js +25 -0
  2. package/cjs/accounts.js +38 -0
  3. package/cjs/adaptor-base.js +504 -287
  4. package/cjs/adaptor-cf.js +42 -0
  5. package/cjs/ao-loader.js +1 -1
  6. package/cjs/ao.js +18 -6
  7. package/cjs/aoconnect-base.js +1010 -546
  8. package/cjs/aoconnect-cf.js +24 -0
  9. package/cjs/ar-remote.js +277 -0
  10. package/cjs/armem-base.js +822 -211
  11. package/cjs/armem-cf.js +128 -0
  12. package/cjs/armem.js +11 -5
  13. package/cjs/bar.js +511 -173
  14. package/cjs/car.js +37 -0
  15. package/cjs/cf-env.js +54 -0
  16. package/cjs/cf.js +76 -0
  17. package/cjs/cli.js +12 -6
  18. package/cjs/create.js +1 -1
  19. package/cjs/devs.js +53 -0
  20. package/cjs/dodb.js +116 -0
  21. package/cjs/hb.js +136 -53
  22. package/cjs/hyperbeam.js +85 -44
  23. package/cjs/keygen.js +94 -0
  24. package/cjs/run.js +4 -1
  25. package/cjs/server.js +40 -9
  26. package/cjs/storage-multi.js +525 -0
  27. package/cjs/tgql-d1.js +664 -0
  28. package/cjs/tgql.js +293 -172
  29. package/cjs/workspace/.claude/agents/tester.md +2 -2
  30. package/cjs/workspace/.claude/skills/build/SKILL.md +2 -2
  31. package/cjs/workspace/.claude/skills/test/SKILL.md +3 -2
  32. package/cjs/workspace/CLAUDE.md +2 -2
  33. package/cjs/workspace/README.md +1 -1
  34. package/cjs/workspace/docs/debug.md +9 -4
  35. package/cjs/workspace/docs/hyperbeam-devices.md +50 -1
  36. package/cjs/workspace/package.json +3 -3
  37. package/esm/accounts-web.js +14 -0
  38. package/esm/accounts.js +27 -0
  39. package/esm/adaptor-base.js +129 -31
  40. package/esm/adaptor-cf.js +11 -0
  41. package/esm/ao-loader.js +1 -1
  42. package/esm/ao.js +21 -2
  43. package/esm/aoconnect-base.js +248 -7
  44. package/esm/aoconnect-cf.js +9 -0
  45. package/esm/ar-remote.js +87 -0
  46. package/esm/armem-base.js +304 -53
  47. package/esm/armem-cf.js +67 -0
  48. package/esm/armem.js +7 -2
  49. package/esm/bar.js +126 -16
  50. package/esm/car.js +10 -0
  51. package/esm/cf-env.js +29 -0
  52. package/esm/cf.js +11 -0
  53. package/esm/cli.js +6 -2
  54. package/esm/create.js +1 -1
  55. package/esm/devs.js +15 -0
  56. package/esm/dodb.js +26 -0
  57. package/esm/hb.js +93 -16
  58. package/esm/hyperbeam.js +68 -30
  59. package/esm/keygen.js +47 -0
  60. package/esm/run.js +4 -1
  61. package/esm/server.js +29 -9
  62. package/esm/storage-multi.js +183 -0
  63. package/esm/tgql-d1.js +407 -0
  64. package/esm/tgql.js +29 -10
  65. package/esm/workspace/.claude/agents/tester.md +2 -2
  66. package/esm/workspace/.claude/skills/build/SKILL.md +2 -2
  67. package/esm/workspace/.claude/skills/test/SKILL.md +3 -2
  68. package/esm/workspace/CLAUDE.md +2 -2
  69. package/esm/workspace/README.md +1 -1
  70. package/esm/workspace/docs/debug.md +9 -4
  71. package/esm/workspace/docs/hyperbeam-devices.md +50 -1
  72. package/esm/workspace/package.json +3 -3
  73. package/package.json +10 -3
  74. package/postinstall.cjs +84 -0
@@ -37,12 +37,11 @@ let onRecovery = {}
37
37
  let ongoing = {}
38
38
 
39
39
  export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
40
- return (mem, { cache, log = false, extensions = {}, hb, variant } = {}) => {
40
+ return (mem, { cache, log = false, extensions = {}, hb, variant, storage, d1, r2, kv, ar_url } = {}) => {
41
41
  const isMem = mem?.__type__ === "mem"
42
42
  if (!isMem) {
43
- let args = { cache }
43
+ let args = { cache, storage, scheduler, d1, r2, kv, ar_url }
44
44
  if (mem?.SU_URL) {
45
- args.scheduler = scheduler
46
45
  args.variant = variant
47
46
  args = mergeLeft(mem, args)
48
47
  }
@@ -78,7 +77,9 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
78
77
  scheduler: "Scheduler",
79
78
  module: "Module",
80
79
  }
81
- for (let v of __tags) v.name = cap[v.name] ?? v.name
80
+ for (let v of __tags) {
81
+ v.name = cap[v.name] ?? v.name
82
+ }
82
83
  return __tags
83
84
  }
84
85
 
@@ -168,6 +169,50 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
168
169
  await ar.postItems(item, su.jwk)
169
170
  }
170
171
 
172
+ // Remote CU — delegate WASM execution to satellite CU
173
+ if (opt._cu_url) {
174
+ const _tags = tags(opt.tags)
175
+ const ext = _tags.Extension || "WeaveDrive"
176
+ let p = {
177
+ _cu_url: opt._cu_url,
178
+ extension: ext,
179
+ format,
180
+ id,
181
+ epochs: [],
182
+ module: mod,
183
+ hash: id,
184
+ memory: null,
185
+ owner,
186
+ height: 0,
187
+ results: [id],
188
+ }
189
+ try {
190
+ const cuResult = await fetch(`${opt._cu_url}/cu/evaluate`, {
191
+ method: "POST",
192
+ headers: { "Content-Type": "application/json" },
193
+ body: JSON.stringify({
194
+ message: id,
195
+ process: id,
196
+ data: opt.data ?? "",
197
+ tags: opt.tags,
198
+ from: owner,
199
+ is_spawn: true,
200
+ }),
201
+ }).then(r => r.json())
202
+ const _msg = {
203
+ ...o(dissoc("signer"), dissoc("memory"))(opt),
204
+ res: cuResult,
205
+ msg: null,
206
+ }
207
+ await mem.set(_msg, "msgs", id)
208
+ } catch (e) {
209
+ console.log("Remote CU spawn error:", e)
210
+ }
211
+ await mem.set(p, "env", id)
212
+ delete ongoing[id]
213
+ return id
214
+ }
215
+
171
216
  const now = Date.now
172
217
  const t = tags(opt.tags)
173
218
  const ext = t.Extension || "WeaveDrive"
@@ -316,6 +361,93 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
316
361
  } else {
317
362
  await ar.postItems(item, su.jwk)
318
363
  }
364
+
365
+ // Remote CU — delegate WASM execution to satellite CU
366
+ if (p._cu_url) {
367
+ try {
368
+ let evalData = _opt?.data ?? ""
369
+ let evalTags = _opt?.tags
370
+ let evalFrom = _opt?.from ?? opt.from
371
+ if (_opt?.item) {
372
+ const decoded = base64url.decode(_opt.item.data)
373
+ evalData = typeof decoded === "string" ? decoded : Buffer.from(decoded).toString("utf-8")
374
+ evalTags = _opt.item.tags
375
+ const t = tags(evalTags)
376
+ if (t["From-Process"]) evalFrom = t["From-Process"]
377
+ if (!evalFrom) {
378
+ evalFrom = await arweave.wallets.jwkToAddress({
379
+ kty: "RSA", n: _opt.item.owner, e: "AQAB",
380
+ })
381
+ }
382
+ }
383
+ // Cranked messages use MU addr as From for AOS trust
384
+ if (_opt?.for) evalFrom = mu.addr
385
+ const cuResult = await fetch(`${p._cu_url}/cu/evaluate`, {
386
+ method: "POST",
387
+ headers: { "Content-Type": "application/json" },
388
+ body: JSON.stringify({
389
+ message: opt.message,
390
+ process: opt.process,
391
+ data: evalData,
392
+ tags: evalTags,
393
+ from: evalFrom,
394
+ }),
395
+ }).then(r => r.json())
396
+ p.results.push(opt.message)
397
+ await mem.set(p, "env", opt.process)
398
+ const _msg = { ...dissoc("signer", _opt), res: cuResult, msg: null }
399
+ await mem.set(_msg, "msgs", opt.message)
400
+ // Route outbox from CU response
401
+ for (const v of cuResult?.Messages ?? []) {
402
+ const envExists = await mem.get("env", v.Target)
403
+ if (envExists) {
404
+ await message({
405
+ for: opt.message,
406
+ process: v.Target,
407
+ tags: v.Tags,
408
+ data: v.Data,
409
+ signer: mu.signer,
410
+ from: opt.process,
411
+ target: v.Target,
412
+ })
413
+ } else if (mem._remote) {
414
+ // Forward to main AR's MU for routing
415
+ const fwdTags = buildTags(null, mergeLeft(tags(v.Tags), {
416
+ "Data-Protocol": "ao",
417
+ Variant: variant ?? "ao.TN.1",
418
+ Type: "Message",
419
+ "From-Process": opt.process,
420
+ "Pushed-For": opt.message,
421
+ }))
422
+ await record({
423
+ for: opt.message,
424
+ tags: fwdTags,
425
+ data: v.Data,
426
+ signer: mu.signer,
427
+ from: opt.process,
428
+ target: v.Target,
429
+ })
430
+ }
431
+ }
432
+ for (const v of cuResult?.Spawns ?? []) {
433
+ const __tags = tags(v.Tags)
434
+ await spawn({
435
+ for: opt.message,
436
+ module: __tags.Module,
437
+ scheduler,
438
+ tags: v.Tags,
439
+ data: v.Data,
440
+ from: __tags["From-Process"],
441
+ signer: mu.signer,
442
+ })
443
+ }
444
+ return id
445
+ } catch (e) {
446
+ console.log("Remote CU assign error:", e)
447
+ return null
448
+ }
449
+ }
450
+
319
451
  try {
320
452
  let data = _opt.data ?? ""
321
453
  let _tags = _opt.tags
@@ -333,6 +465,9 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
333
465
  })
334
466
  }
335
467
  }
468
+ // Cranked messages (inter-process) use MU addr as From for AOS trust
469
+ // From-Process tag still tracks the originating process
470
+ if (_opt.for) from = mu.addr
336
471
  // check: is owner=mu.addr right?
337
472
  const _owner = opt.message_item?.owner
338
473
  ? toAddr(opt.message_item.owner)
@@ -352,7 +487,7 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
352
487
  spawn: (await mem.getTx(p.id))?.item,
353
488
  module: await mem.getTx(mod),
354
489
  })
355
- mem.env[opt.process].handle = p.handle
490
+ if (mem.env[opt.process]) mem.env[opt.process].handle = p.handle
356
491
  }
357
492
  if (p.compressed) {
358
493
  const start = Date.now()
@@ -486,6 +621,25 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
486
621
  } catch (e) {
487
622
  console.log(e)
488
623
  }
624
+ } else if (mem._remote) {
625
+ // Remote mode: forward to main AR's MU for routing
626
+ try {
627
+ const di = await ar.dataitem({
628
+ data: v.Data ?? "",
629
+ signer: mu.signer,
630
+ tags: mergeLeft(tags(v.Tags), {
631
+ "Data-Protocol": "ao",
632
+ Variant: variant ?? "ao.TN.1",
633
+ Type: "Message",
634
+ "From-Process": opt.process,
635
+ "Pushed-For": opt.message,
636
+ }),
637
+ target: v.Target,
638
+ })
639
+ await mem._remote.postMU(di.item.getRaw())
640
+ } catch (e) {
641
+ console.log("Remote MU forward error:", e)
642
+ }
489
643
  } else {
490
644
  await record({
491
645
  for: opt.message,
@@ -608,7 +762,7 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
608
762
  spawn: (await mem.getTx(p.id))?.item,
609
763
  module: await mem.getTx(mod),
610
764
  })
611
- mem.env[opt.process].handle = p.handle
765
+ if (mem.env[opt.process]) mem.env[opt.process].handle = p.handle
612
766
  }
613
767
  if (p.compressed) {
614
768
  const start = Date.now()
@@ -738,6 +892,92 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
738
892
  return { recovered: count, pid, success }
739
893
  }
740
894
 
895
+ // Satellite CU evaluate: WASM execution only, no DataItem creation or AR posting.
896
+ // Used by cu_post_evaluate on remote CU workers.
897
+ const evaluate = async ({
898
+ message: msgId,
899
+ process: pid,
900
+ data,
901
+ tags: msgTags,
902
+ from,
903
+ is_spawn,
904
+ module: modId,
905
+ scheduler: sch,
906
+ }) => {
907
+ if (is_spawn) {
908
+ const mod = modId || tags(msgTags || []).Module
909
+ if (!mod) throw Error("module missing for evaluate spawn")
910
+ const { mod: resolvedMod, wasm, format } = await mem.getWasm(mod)
911
+ const _tags = tags(msgTags || [])
912
+ const ext = _tags.Extension || "WeaveDrive"
913
+ const wdrive = extensions[ext]
914
+ const spawnTx = await mem.getTx(pid)
915
+ const moduleTx = await mem.getTx(resolvedMod)
916
+ const handle = await AoLoader(wasm, {
917
+ format,
918
+ WeaveDrive: wdrive,
919
+ spawn: spawnTx?.item ?? spawnTx ?? null,
920
+ module: moduleTx,
921
+ })
922
+ const owner = from || mu.addr
923
+ let p = {
924
+ extension: ext,
925
+ format,
926
+ id: pid,
927
+ epochs: [],
928
+ handle,
929
+ module: resolvedMod,
930
+ hash: pid,
931
+ memory: null,
932
+ owner,
933
+ height: 0,
934
+ results: [pid],
935
+ }
936
+ let bootData = ""
937
+ if (_tags["On-Boot"] === "Data") bootData = data ?? ""
938
+ else bootData = data ?? ""
939
+ const msg = await genMsg(pid, p, bootData, msgTags || [], owner, owner, true)
940
+ const _env = await genEnv({ pid, owner, module: resolvedMod })
941
+ const res = await handle(null, msg, _env)
942
+ p.memory = res.Memory
943
+ delete res.Memory
944
+ await mem.set({ tags: msgTags, data, res, msg }, "msgs", pid)
945
+ await mem.set(p, "env", pid)
946
+ return res
947
+ }
948
+
949
+ // Message evaluation with state update
950
+ const p = await mem.get("env", pid)
951
+ if (!p) throw Error(`process ${pid} not found on satellite CU`)
952
+ if (!p.handle) {
953
+ const { format, mod, wasm } = await mem.getWasm(p.module)
954
+ const wdrive = extensions[p.extension]
955
+ const spawnTx = await mem.getTx(p.id)
956
+ const moduleTx = await mem.getTx(mod)
957
+ p.handle = await AoLoader(wasm, {
958
+ format,
959
+ WeaveDrive: wdrive,
960
+ spawn: spawnTx?.item ?? spawnTx ?? null,
961
+ module: moduleTx,
962
+ })
963
+ }
964
+ if (p.compressed) {
965
+ p.memory = mem.decompress(p.memory, p.original_size)
966
+ p.compressed = false
967
+ }
968
+ p.height += 1
969
+ const owner = from || mu.addr
970
+ const msg = await genMsg(msgId, p, data ?? "", msgTags || [], owner, owner)
971
+ const _env = await genEnv({ pid, owner: p.owner, module: p.module })
972
+ const res = await p.handle(p.memory, msg, _env)
973
+ p.memory = res.Memory
974
+ delete res.Memory
975
+ p.results.push(msgId)
976
+ await mem.set(p, "env", pid)
977
+ await mem.set({ tags: msgTags, data, from, res, msg }, "msgs", msgId)
978
+ return res
979
+ }
980
+
741
981
  const result = async opt => {
742
982
  return (await mem.get("msgs", opt.message))?.res
743
983
  }
@@ -828,7 +1068,7 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
828
1068
  spawn: (await mem.getTx(p.id)).item,
829
1069
  module: await mem.getTx(mod),
830
1070
  })
831
- mem.env[opt.process].handle = p.handle
1071
+ if (mem.env[opt.process]) mem.env[opt.process].handle = p.handle
832
1072
  }
833
1073
  if (p.compressed) {
834
1074
  const start = Date.now()
@@ -844,6 +1084,7 @@ export default ({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem } = {}) => {
844
1084
  return null
845
1085
  },
846
1086
  recover,
1087
+ evaluate,
847
1088
  mem,
848
1089
  }
849
1090
  }
@@ -0,0 +1,9 @@
1
+ import "./cf-env.js"
2
+ import base from "./aoconnect-base.js"
3
+ import AR from "./car.js"
4
+ import { mu, su, cu, acc } from "./cf.js"
5
+ import AoLoader from "./ao-loader.js"
6
+ import ArMem from "./armem-cf.js"
7
+ const scheduler = "_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA"
8
+
9
+ export const connect = base({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem })
@@ -0,0 +1,87 @@
1
+ export default class RemoteAR {
2
+ constructor(ar_url) {
3
+ this.url = ar_url.replace(/\/$/, "")
4
+ }
5
+
6
+ async data(id) {
7
+ const res = await fetch(`${this.url}/ar/${id}`)
8
+ if (!res.ok) return null
9
+ return new Uint8Array(await res.arrayBuffer())
10
+ }
11
+
12
+ async getTx(id) {
13
+ const query = `{ transactions(ids: ["${id}"]) {
14
+ edges { node { id owner { address key } recipient tags { name value }
15
+ anchor signature data { size type } block { id height timestamp } } }
16
+ } }`
17
+ const res = await fetch(`${this.url}/ar/graphql`, {
18
+ method: "POST",
19
+ headers: { "Content-Type": "application/json" },
20
+ body: JSON.stringify({ query }),
21
+ })
22
+ const json = await res.json()
23
+ const node = json?.data?.transactions?.edges?.[0]?.node
24
+ if (!node) return null
25
+ return {
26
+ id: node.id,
27
+ owner: node.owner?.address,
28
+ _owner_key: node.owner?.key,
29
+ recipient: node.recipient,
30
+ tags: node.tags,
31
+ anchor: node.anchor,
32
+ signature: node.signature,
33
+ _data: node.data,
34
+ block: node.block?.id,
35
+ }
36
+ }
37
+
38
+ async postTx(tx) {
39
+ const res = await fetch(`${this.url}/ar/${tx.id || "tx"}`, {
40
+ method: "POST",
41
+ headers: { "Content-Type": "application/json" },
42
+ body: JSON.stringify(tx),
43
+ })
44
+ return await res.json()
45
+ }
46
+
47
+ async postMU(rawDataItem) {
48
+ const res = await fetch(`${this.url}/mu`, {
49
+ method: "POST",
50
+ headers: { "Content-Type": "application/octet-stream" },
51
+ body: rawDataItem,
52
+ })
53
+ return await res.json()
54
+ }
55
+
56
+ async getHeight() {
57
+ const res = await fetch(`${this.url}/ar/`)
58
+ const json = await res.json()
59
+ return json.height ?? 0
60
+ }
61
+
62
+ async getAnchor() {
63
+ const res = await fetch(`${this.url}/ar/tx_anchor`)
64
+ return await res.text()
65
+ }
66
+
67
+ async graphql(query, variables) {
68
+ const res = await fetch(`${this.url}/ar/graphql`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({ query, variables }),
72
+ })
73
+ return await res.json()
74
+ }
75
+
76
+ async findSU(schedulerAddr) {
77
+ const query = `{ transactions(
78
+ owners: ["${schedulerAddr}"],
79
+ tags: [{ name: "Type", values: ["Scheduler-Location"] }],
80
+ first: 1, sort: HEIGHT_DESC
81
+ ) { edges { node { tags { name value } } } } }`
82
+ const json = await this.graphql(query)
83
+ const tags = json?.data?.transactions?.edges?.[0]?.node?.tags ?? []
84
+ const urlTag = tags.find(t => t.name === "Url")
85
+ return urlTag?.value ?? null
86
+ }
87
+ }