@beeos-ai/device-agent 0.4.3 → 0.5.1

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 (200) hide show
  1. package/.pi/extensions/android-tools.ts +146 -15
  2. package/dist/adapters/agent-gateway-client.d.ts +37 -0
  3. package/dist/adapters/agent-gateway-client.js +45 -0
  4. package/dist/adapters/agent-gateway-client.js.map +1 -1
  5. package/dist/adapters/agentcore-pi.d.ts +22 -0
  6. package/dist/adapters/agentcore-pi.js +48 -0
  7. package/dist/adapters/agentcore-pi.js.map +1 -1
  8. package/dist/adapters/device-android-adb.d.ts +47 -0
  9. package/dist/adapters/device-android-adb.js +50 -0
  10. package/dist/adapters/device-android-adb.js.map +1 -1
  11. package/dist/adapters/device-desktop.d.ts +12 -0
  12. package/dist/adapters/device-desktop.js +31 -0
  13. package/dist/adapters/device-desktop.js.map +1 -1
  14. package/dist/adapters/identity-file.d.ts +33 -5
  15. package/dist/adapters/identity-file.js +52 -6
  16. package/dist/adapters/identity-file.js.map +1 -1
  17. package/dist/agent-runtime/adapters/base.d.ts +20 -0
  18. package/dist/agent-runtime/adapters/base.js.map +1 -1
  19. package/dist/agent-runtime/agent-runner.d.ts +4 -2
  20. package/dist/agent-runtime/agent-runner.js.map +1 -1
  21. package/dist/agent-runtime/core.d.ts +60 -0
  22. package/dist/agent-runtime/core.js +190 -9
  23. package/dist/agent-runtime/core.js.map +1 -1
  24. package/dist/agent-runtime/feedback.d.ts +56 -0
  25. package/dist/agent-runtime/feedback.js +54 -0
  26. package/dist/agent-runtime/feedback.js.map +1 -0
  27. package/dist/agent-runtime/index.d.ts +1 -0
  28. package/dist/agent-runtime/index.js +1 -0
  29. package/dist/agent-runtime/index.js.map +1 -1
  30. package/dist/agent-runtime/plan-executor.js +24 -0
  31. package/dist/agent-runtime/plan-executor.js.map +1 -1
  32. package/dist/agent-runtime/planner/base.d.ts +10 -0
  33. package/dist/agent-runtime/planner/base.js.map +1 -1
  34. package/dist/agent-runtime/planner/llm-planner.js +1 -0
  35. package/dist/agent-runtime/planner/llm-planner.js.map +1 -1
  36. package/dist/agent-runtime/planner/prompts.d.ts +3 -0
  37. package/dist/agent-runtime/planner/prompts.js +12 -0
  38. package/dist/agent-runtime/planner/prompts.js.map +1 -1
  39. package/dist/agent-runtime/reflection.d.ts +25 -6
  40. package/dist/agent-runtime/reflection.js +64 -22
  41. package/dist/agent-runtime/reflection.js.map +1 -1
  42. package/dist/agent-runtime/reflectors/policy.d.ts +10 -4
  43. package/dist/agent-runtime/reflectors/policy.js +19 -6
  44. package/dist/agent-runtime/reflectors/policy.js.map +1 -1
  45. package/dist/agent-runtime/shortcuts/fs-store.d.ts +41 -0
  46. package/dist/agent-runtime/shortcuts/fs-store.js +122 -0
  47. package/dist/agent-runtime/shortcuts/fs-store.js.map +1 -0
  48. package/dist/agent-runtime/shortcuts/in-memory-store.d.ts +20 -0
  49. package/dist/agent-runtime/shortcuts/in-memory-store.js +64 -0
  50. package/dist/agent-runtime/shortcuts/in-memory-store.js.map +1 -0
  51. package/dist/agent-runtime/shortcuts/index.d.ts +10 -0
  52. package/dist/agent-runtime/shortcuts/index.js +10 -0
  53. package/dist/agent-runtime/shortcuts/index.js.map +1 -0
  54. package/dist/agent-runtime/shortcuts/types.d.ts +69 -0
  55. package/dist/agent-runtime/shortcuts/types.js +17 -0
  56. package/dist/agent-runtime/shortcuts/types.js.map +1 -0
  57. package/dist/app/agent-host.d.ts +83 -0
  58. package/dist/app/agent-host.js +345 -32
  59. package/dist/app/agent-host.js.map +1 -1
  60. package/dist/app/session-manager.d.ts +33 -4
  61. package/dist/app/session-manager.js +27 -5
  62. package/dist/app/session-manager.js.map +1 -1
  63. package/dist/bootstrap.js +187 -3
  64. package/dist/bootstrap.js.map +1 -1
  65. package/dist/config/loader.js +22 -0
  66. package/dist/config/loader.js.map +1 -1
  67. package/dist/config/schema.d.ts +18 -0
  68. package/dist/config/schema.js +118 -0
  69. package/dist/config/schema.js.map +1 -1
  70. package/dist/fleet/adapters/process/node-process-manager.js +97 -17
  71. package/dist/fleet/adapters/process/node-process-manager.js.map +1 -1
  72. package/dist/fleet/adapters/state/beeos-cli-store.d.ts +75 -9
  73. package/dist/fleet/adapters/state/beeos-cli-store.js +201 -17
  74. package/dist/fleet/adapters/state/beeos-cli-store.js.map +1 -1
  75. package/dist/fleet/domain/device.d.ts +9 -0
  76. package/dist/fleet/domain/device.js.map +1 -1
  77. package/dist/fleet/domain/fsm.js +34 -0
  78. package/dist/fleet/domain/fsm.js.map +1 -1
  79. package/dist/fleet/installer/spawn-env.d.ts +3 -0
  80. package/dist/fleet/installer/spawn-env.js +186 -3
  81. package/dist/fleet/installer/spawn-env.js.map +1 -1
  82. package/dist/fleet/state/state-json.d.ts +116 -0
  83. package/dist/fleet/state/state-json.js +87 -0
  84. package/dist/fleet/state/state-json.js.map +1 -0
  85. package/dist/fleet/supervisor.js +14 -2
  86. package/dist/fleet/supervisor.js.map +1 -1
  87. package/dist/inbound/acp/handlers/session.js.map +1 -1
  88. package/dist/mcp-client/client.d.ts +6 -0
  89. package/dist/mcp-client/client.js +11 -0
  90. package/dist/mcp-client/client.js.map +1 -1
  91. package/dist/mcp-client/runtime.d.ts +13 -0
  92. package/dist/orchestrator-system-prompt.d.ts +26 -0
  93. package/dist/orchestrator-system-prompt.js +118 -2
  94. package/dist/orchestrator-system-prompt.js.map +1 -1
  95. package/dist/pi-context.d.ts +50 -0
  96. package/dist/pi-context.js.map +1 -1
  97. package/dist/ports/device.d.ts +18 -0
  98. package/dist/resources/augmenter.d.ts +48 -0
  99. package/dist/resources/augmenter.js +126 -0
  100. package/dist/resources/augmenter.js.map +1 -0
  101. package/dist/resources/cache.d.ts +57 -0
  102. package/dist/resources/cache.js +107 -0
  103. package/dist/resources/cache.js.map +1 -0
  104. package/dist/resources/index.d.ts +17 -0
  105. package/dist/resources/index.js +15 -0
  106. package/dist/resources/index.js.map +1 -0
  107. package/dist/resources/lifecycle/disk-pressure.d.ts +75 -0
  108. package/dist/resources/lifecycle/disk-pressure.js +148 -0
  109. package/dist/resources/lifecycle/disk-pressure.js.map +1 -0
  110. package/dist/resources/lifecycle/index.d.ts +7 -0
  111. package/dist/resources/lifecycle/index.js +7 -0
  112. package/dist/resources/lifecycle/index.js.map +1 -0
  113. package/dist/resources/lifecycle/manager.d.ts +38 -0
  114. package/dist/resources/lifecycle/manager.js +205 -0
  115. package/dist/resources/lifecycle/manager.js.map +1 -0
  116. package/dist/resources/lifecycle/sweeper.d.ts +36 -0
  117. package/dist/resources/lifecycle/sweeper.js +179 -0
  118. package/dist/resources/lifecycle/sweeper.js.map +1 -0
  119. package/dist/resources/lifecycle/types.d.ts +180 -0
  120. package/dist/resources/lifecycle/types.js +46 -0
  121. package/dist/resources/lifecycle/types.js.map +1 -0
  122. package/dist/resources/parsers.d.ts +28 -0
  123. package/dist/resources/parsers.js +88 -0
  124. package/dist/resources/parsers.js.map +1 -0
  125. package/dist/resources/registry.d.ts +47 -0
  126. package/dist/resources/registry.js +107 -0
  127. package/dist/resources/registry.js.map +1 -0
  128. package/dist/resources/resolvers/beeos-file-resolver.d.ts +62 -0
  129. package/dist/resources/resolvers/beeos-file-resolver.js +109 -0
  130. package/dist/resources/resolvers/beeos-file-resolver.js.map +1 -0
  131. package/dist/resources/resolvers/errors.d.ts +11 -0
  132. package/dist/resources/resolvers/errors.js +23 -0
  133. package/dist/resources/resolvers/errors.js.map +1 -0
  134. package/dist/resources/resolvers/mime-table.d.ts +41 -0
  135. package/dist/resources/resolvers/mime-table.js +92 -0
  136. package/dist/resources/resolvers/mime-table.js.map +1 -0
  137. package/dist/resources/resolvers/url-resolver.d.ts +85 -0
  138. package/dist/resources/resolvers/url-resolver.js +495 -0
  139. package/dist/resources/resolvers/url-resolver.js.map +1 -0
  140. package/dist/resources/shortcut-facade.d.ts +51 -0
  141. package/dist/resources/shortcut-facade.js +72 -0
  142. package/dist/resources/shortcut-facade.js.map +1 -0
  143. package/dist/resources/telemetry.d.ts +52 -0
  144. package/dist/resources/telemetry.js +59 -0
  145. package/dist/resources/telemetry.js.map +1 -0
  146. package/dist/resources/types.d.ts +249 -0
  147. package/dist/resources/types.js +29 -0
  148. package/dist/resources/types.js.map +1 -0
  149. package/dist/shortcuts/builtins/download-to-device.d.ts +83 -0
  150. package/dist/shortcuts/builtins/download-to-device.js +125 -0
  151. package/dist/shortcuts/builtins/download-to-device.js.map +1 -0
  152. package/dist/shortcuts/builtins/find-app-package.d.ts +79 -0
  153. package/dist/shortcuts/builtins/find-app-package.js +168 -0
  154. package/dist/shortcuts/builtins/find-app-package.js.map +1 -0
  155. package/dist/shortcuts/builtins/index.d.ts +32 -0
  156. package/dist/shortcuts/builtins/index.js +37 -0
  157. package/dist/shortcuts/builtins/index.js.map +1 -0
  158. package/dist/shortcuts/builtins/open-deeplink.d.ts +68 -0
  159. package/dist/shortcuts/builtins/open-deeplink.js +142 -0
  160. package/dist/shortcuts/builtins/open-deeplink.js.map +1 -0
  161. package/dist/shortcuts/builtins/set-clipboard.d.ts +65 -0
  162. package/dist/shortcuts/builtins/set-clipboard.js +112 -0
  163. package/dist/shortcuts/builtins/set-clipboard.js.map +1 -0
  164. package/dist/shortcuts/index.d.ts +11 -0
  165. package/dist/shortcuts/index.js +11 -0
  166. package/dist/shortcuts/index.js.map +1 -0
  167. package/dist/shortcuts/registry.d.ts +56 -0
  168. package/dist/shortcuts/registry.js +70 -0
  169. package/dist/shortcuts/registry.js.map +1 -0
  170. package/dist/shortcuts/router.d.ts +91 -0
  171. package/dist/shortcuts/router.js +158 -0
  172. package/dist/shortcuts/router.js.map +1 -0
  173. package/dist/shortcuts/types.d.ts +219 -0
  174. package/dist/shortcuts/types.js +46 -0
  175. package/dist/shortcuts/types.js.map +1 -0
  176. package/package.json +3 -3
  177. package/dist/agent-runtime/skills/sqlite-store.d.ts +0 -60
  178. package/dist/agent-runtime/skills/sqlite-store.js +0 -234
  179. package/dist/agent-runtime/skills/sqlite-store.js.map +0 -1
  180. package/dist/test-lan-autoglm.d.ts +0 -7
  181. package/dist/test-lan-autoglm.js +0 -46
  182. package/dist/test-lan-autoglm.js.map +0 -1
  183. package/dist/test-mem-breakdown.d.ts +0 -1
  184. package/dist/test-mem-breakdown.js +0 -103
  185. package/dist/test-mem-breakdown.js.map +0 -1
  186. package/dist/test-mem.d.ts +0 -1
  187. package/dist/test-mem.js +0 -60
  188. package/dist/test-mem.js.map +0 -1
  189. package/dist/test-mobile-use.d.ts +0 -1
  190. package/dist/test-mobile-use.js +0 -18
  191. package/dist/test-mobile-use.js.map +0 -1
  192. package/dist/test-screenshot-loop.d.ts +0 -1
  193. package/dist/test-screenshot-loop.js +0 -43
  194. package/dist/test-screenshot-loop.js.map +0 -1
  195. package/dist/test-screenshot.d.ts +0 -1
  196. package/dist/test-screenshot.js +0 -10
  197. package/dist/test-screenshot.js.map +0 -1
  198. package/dist/test-ui-xml-dump.d.ts +0 -15
  199. package/dist/test-ui-xml-dump.js +0 -49
  200. package/dist/test-ui-xml-dump.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/resources/lifecycle/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Resource Lifecycle — L2 (background TTL sweep).
3
+ *
4
+ * Runs on a fixed interval; deletes any file under the sandbox dirs
5
+ * matching `beeos_*` whose mtime is older than `sweepAgeHours`.
6
+ *
7
+ * Why this layer is independent from L1:
8
+ * L1 misses anytime the daemon dies between `agent.run()` returning
9
+ * and the L1 timer firing — `kill -9`, OOM, machine reboot, plist
10
+ * `bootout`, … L2 is the safety net that walks the same tree on a
11
+ * timer and wipes orphans regardless of which task originally pushed
12
+ * them. The two layers cooperate because they target the SAME
13
+ * sandbox directory and the SAME `beeos_` filename prefix.
14
+ *
15
+ * Why we go through `find … -delete` (and not Node's fs.rm):
16
+ * The files live on the device at `/sdcard/...`, accessible only
17
+ * over `adb shell` / the MCP `executeCommand` channel. We have no
18
+ * FUSE mount, no network filesystem; the only thing we can do is
19
+ * issue a shell command. `find` is in BusyBox/toybox on every
20
+ * Android shipping in the last decade, and `-mmin` + `-delete` are
21
+ * universal flags.
22
+ */
23
+ import type { LifecycleWiring, ResourceLifecycleSweeper } from "./types.js";
24
+ export declare class FsResourceLifecycleSweeper implements ResourceLifecycleSweeper {
25
+ private readonly wiring;
26
+ private timer;
27
+ /** Set during a sweep so we never run two in parallel. */
28
+ private inFlight;
29
+ private platform;
30
+ constructor(wiring: LifecycleWiring);
31
+ start(): void;
32
+ stop(): Promise<void>;
33
+ sweepNow(): Promise<number>;
34
+ private detectPlatform;
35
+ private doSweep;
36
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Resource Lifecycle — L2 (background TTL sweep).
3
+ *
4
+ * Runs on a fixed interval; deletes any file under the sandbox dirs
5
+ * matching `beeos_*` whose mtime is older than `sweepAgeHours`.
6
+ *
7
+ * Why this layer is independent from L1:
8
+ * L1 misses anytime the daemon dies between `agent.run()` returning
9
+ * and the L1 timer firing — `kill -9`, OOM, machine reboot, plist
10
+ * `bootout`, … L2 is the safety net that walks the same tree on a
11
+ * timer and wipes orphans regardless of which task originally pushed
12
+ * them. The two layers cooperate because they target the SAME
13
+ * sandbox directory and the SAME `beeos_` filename prefix.
14
+ *
15
+ * Why we go through `find … -delete` (and not Node's fs.rm):
16
+ * The files live on the device at `/sdcard/...`, accessible only
17
+ * over `adb shell` / the MCP `executeCommand` channel. We have no
18
+ * FUSE mount, no network filesystem; the only thing we can do is
19
+ * issue a shell command. `find` is in BusyBox/toybox on every
20
+ * Android shipping in the last decade, and `-mmin` + `-delete` are
21
+ * universal flags.
22
+ */
23
+ /**
24
+ * Image / video / audio / Download — the four well-known dirs the
25
+ * Android adapter routes downloads into. The sandbox subdir gets
26
+ * appended to each at sweep time so a single sweep covers every
27
+ * MIME bucket.
28
+ *
29
+ * If a future adapter adds a new bucket (`/sdcard/Books`, say),
30
+ * extend this list — no other change needed for the sweeper.
31
+ */
32
+ const ANDROID_SANDBOX_ROOTS = [
33
+ "/sdcard/Pictures",
34
+ "/sdcard/Movies",
35
+ "/sdcard/Music",
36
+ "/sdcard/Download",
37
+ ];
38
+ export class FsResourceLifecycleSweeper {
39
+ wiring;
40
+ timer = null;
41
+ /** Set during a sweep so we never run two in parallel. */
42
+ inFlight = null;
43
+ platform = null;
44
+ constructor(wiring) {
45
+ this.wiring = wiring;
46
+ }
47
+ start() {
48
+ if (this.wiring.config.mode === "off")
49
+ return;
50
+ if (this.timer)
51
+ return;
52
+ const intervalMs = Math.max(1, this.wiring.config.sweepIntervalMinutes) * 60 * 1000;
53
+ this.timer = setInterval(() => {
54
+ // Fire-and-forget — sweep failures are logged inside `sweepNow`.
55
+ void this.sweepNow().catch((e) => {
56
+ this.wiring.log.warn({ err: errString(e) }, "lifecycle.sweeper: scheduled sweep threw");
57
+ });
58
+ }, intervalMs);
59
+ if (typeof this.timer.unref === "function") {
60
+ this.timer.unref();
61
+ }
62
+ this.wiring.log.info({
63
+ mode: this.wiring.config.mode,
64
+ intervalMinutes: this.wiring.config.sweepIntervalMinutes,
65
+ ageHours: this.wiring.config.sweepAgeHours,
66
+ sandboxSubdir: this.wiring.config.sandboxSubdir,
67
+ }, "lifecycle.sweeper: started");
68
+ }
69
+ async stop() {
70
+ if (this.timer) {
71
+ clearInterval(this.timer);
72
+ this.timer = null;
73
+ }
74
+ // Allow an in-flight sweep to finish so its `executeCommand`
75
+ // promises resolve before we tell the caller "stopped".
76
+ if (this.inFlight) {
77
+ try {
78
+ await this.inFlight;
79
+ }
80
+ catch {
81
+ /* already logged */
82
+ }
83
+ }
84
+ }
85
+ async sweepNow() {
86
+ if (this.inFlight)
87
+ return this.inFlight;
88
+ this.inFlight = this.doSweep().finally(() => {
89
+ this.inFlight = null;
90
+ });
91
+ return this.inFlight;
92
+ }
93
+ // ── Internals ───────────────────────────────────────────────────────────
94
+ async detectPlatform() {
95
+ if (this.platform !== null)
96
+ return this.platform;
97
+ try {
98
+ const info = await this.wiring.device.getInfo();
99
+ this.platform = (info.os ?? info.type ?? "").toString().toLowerCase();
100
+ }
101
+ catch {
102
+ this.platform = "";
103
+ }
104
+ return this.platform;
105
+ }
106
+ async doSweep() {
107
+ if (this.wiring.config.mode === "off")
108
+ return 0;
109
+ const platform = await this.detectPlatform();
110
+ if (platform !== "android")
111
+ return 0;
112
+ let mcp;
113
+ try {
114
+ mcp = this.wiring.mcpProvider();
115
+ }
116
+ catch (e) {
117
+ this.wiring.log.warn({ err: errString(e) }, "lifecycle.sweeper: mcpProvider() threw");
118
+ return 0;
119
+ }
120
+ if (typeof mcp.executeCommand !== "function")
121
+ return 0;
122
+ const subdir = this.wiring.config.sandboxSubdir.replace(/^\/+|\/+$/g, "");
123
+ const ageMinutes = Math.max(0, this.wiring.config.sweepAgeHours) * 60;
124
+ let totalDeleted = 0;
125
+ for (const root of ANDROID_SANDBOX_ROOTS) {
126
+ const dir = subdir ? `${root}/${subdir}` : root;
127
+ // The `[ -d "$dir" ]` guard avoids spamming logs with "No such
128
+ // file or directory" the first time the agent boots on a fresh
129
+ // device that hasn't downloaded anything yet.
130
+ // We list files first so we know how many got deleted (find
131
+ // -delete on busybox doesn't echo names).
132
+ const listCmd = `[ -d ${shellQuote(dir)} ] || exit 0; ` +
133
+ `find ${shellQuote(dir)} -maxdepth 1 -type f -name 'beeos_*' -mmin +${ageMinutes} -print 2>/dev/null || true`;
134
+ let stdout = "";
135
+ try {
136
+ const r = await mcp.executeCommand(listCmd);
137
+ stdout = (r.stdout ?? "").trim();
138
+ }
139
+ catch (e) {
140
+ this.wiring.log.warn({ dir, err: errString(e) }, "lifecycle.sweeper: list step failed");
141
+ continue;
142
+ }
143
+ if (!stdout)
144
+ continue;
145
+ const targets = stdout.split(/\r?\n/).filter(Boolean);
146
+ // Issue one batched `rm -f` per directory so we don't burn a
147
+ // full shell roundtrip per file on a big backlog.
148
+ // No MediaScanner broadcast here: these are 24h+ orphans, the
149
+ // gallery long ago dropped their thumbnails, and a per-file
150
+ // `am broadcast` on a 100+ backlog would burn several seconds
151
+ // of shell roundtrips for no observable user benefit. L1 keeps
152
+ // its broadcast because freshly-deleted files might still be
153
+ // open in a picker preview.
154
+ const rmCmd = targets.map((p) => `rm -f ${shellQuote(p)}`).join(" ; ") + " ; :";
155
+ try {
156
+ await mcp.executeCommand(rmCmd);
157
+ }
158
+ catch (e) {
159
+ this.wiring.log.warn({ dir, count: targets.length, err: errString(e) }, "lifecycle.sweeper: rm batch failed");
160
+ continue;
161
+ }
162
+ this.wiring.log.info({ dir, count: targets.length, ageHours: this.wiring.config.sweepAgeHours }, "lifecycle.sweeper: swept dir");
163
+ totalDeleted += targets.length;
164
+ }
165
+ if (totalDeleted > 0) {
166
+ this.wiring.log.info({ totalDeleted, ageHours: this.wiring.config.sweepAgeHours }, "lifecycle.sweeper: pass complete");
167
+ }
168
+ return totalDeleted;
169
+ }
170
+ }
171
+ function shellQuote(s) {
172
+ return `'${s.replace(/'/g, "'\\''")}'`;
173
+ }
174
+ function errString(e) {
175
+ if (e instanceof Error)
176
+ return e.message;
177
+ return String(e);
178
+ }
179
+ //# sourceMappingURL=sweeper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweeper.js","sourceRoot":"","sources":["../../../src/resources/lifecycle/sweeper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Resource Lifecycle — type contracts for the three-layer GC.
3
+ *
4
+ * The Resource Resolution Layer must land URL-derived bytes on the
5
+ * device's external storage so platform-native pickers (Photos,
6
+ * Gallery, WeChat moments composer, …) can index them via MediaStore.
7
+ * Once a single task has finished — i.e. the picker has copied the
8
+ * file into the consuming app's sandbox via `ContentProvider.openInputStream`
9
+ * — the original device-side file is dead weight.
10
+ *
11
+ * Without explicit reclamation a long-running daemon would accumulate
12
+ * gigabytes of orphan resources. We model this as a classic three-layer
13
+ * garbage collector, mirroring the structure of any robust resource
14
+ * manager (Linux page cache, browser HTTP cache, JVM GC):
15
+ *
16
+ * L1 — per-task ephemeral cleanup
17
+ * Happy-path tracking. Each task has a finite lifetime; when
18
+ * `agent.run()` returns / throws / aborts, schedule a delete
19
+ * of every fresh resource the task pushed (plus a small grace
20
+ * window so async picker uploads finish first).
21
+ *
22
+ * L2 — background TTL sweep
23
+ * Crash / kill -9 / unclean shutdown safety net. Runs on a
24
+ * timer; deletes any `beeos_*` file under the sandbox root
25
+ * whose mtime is older than `sweepAgeHours`.
26
+ *
27
+ * L3 — disk-pressure adaptive sweep
28
+ * Per-write check that prevents the agent from filling the
29
+ * device's external storage. Triggers a force-sweep when
30
+ * free space drops below `diskMinFreeMb`; rejects the resolve
31
+ * with `disk_pressure` if free space stays below
32
+ * `diskCriticalFreeMb` after sweeping.
33
+ *
34
+ * Each layer fail-softs to the next: L1 misses (crash / no finally) →
35
+ * L2 catches; L2 misses (daemon never idle, sweeper paused) → L3
36
+ * catches. Stacked, they are asymptotically complete.
37
+ *
38
+ * Why this lives next to `resources/` and not in `app/`:
39
+ * - the lifecycle is **about** resources (their identity, their
40
+ * storage path, their cache invalidation contract).
41
+ * - the AgentHost only needs to call `trackFresh(taskId, asset)` and
42
+ * `onTaskEnd(taskId)` — it does not need to know about sweeps,
43
+ * TTLs, or `df`/`find` shell commands.
44
+ */
45
+ import type { IDevice } from "../../ports/device.js";
46
+ import type { IMcpRuntime } from "../../mcp-client/runtime.js";
47
+ import type { ResolvedAsset, ResolverLogger } from "../types.js";
48
+ import type { ResourceResolutionCache } from "../cache.js";
49
+ /**
50
+ * Cleanup policy for fresh per-task resources.
51
+ *
52
+ * - `ephemeral` — when a task ends, schedule a delayed delete of
53
+ * every fresh resource it pushed. This is the
54
+ * default; `app sandbox` already has its own copy
55
+ * and the original file is no longer addressable.
56
+ * - `persistent` — never delete from L1. The user wants resources
57
+ * to remain in the gallery until L2 / L3 reclaims
58
+ * them on age / pressure grounds.
59
+ * - `off` — disable the entire lifecycle subsystem. L2/L3
60
+ * don't run either. Useful for diagnostics or
61
+ * deployments where the agent shares /sdcard with
62
+ * long-lived user data the operator hand-manages.
63
+ */
64
+ export type LifecycleMode = "ephemeral" | "persistent" | "off";
65
+ /**
66
+ * Static configuration consumed by the lifecycle subsystem. Loaded
67
+ * from `[resources.lifecycle]` in the user config; sane defaults
68
+ * defined alongside the schema in `config/schema.ts`.
69
+ */
70
+ export interface ResourceLifecycleConfig {
71
+ /** Cleanup policy. See {@link LifecycleMode}. */
72
+ readonly mode: LifecycleMode;
73
+ /**
74
+ * Subdirectory under each well-known dir (`/sdcard/Pictures/<sub>`,
75
+ * `/sdcard/Movies/<sub>`, …) the lifecycle is allowed to wipe. The
76
+ * **same** value MUST be passed to the device adapter (or the
77
+ * sweeper would scan a different directory than the resolver writes
78
+ * into). The host fans this single config knob out to both layers
79
+ * at bootstrap time.
80
+ */
81
+ readonly sandboxSubdir: string;
82
+ /**
83
+ * Grace window between `task:end` and the actual L1 `rm`. Some
84
+ * pickers (e.g. WeChat) keep an async upload running for a couple
85
+ * of seconds after the user taps Send; deleting too eagerly causes
86
+ * the upload to fail with `FileNotFoundException`. 60s is a safe
87
+ * default — well above any picker's observed window, well below
88
+ * the L2 TTL.
89
+ */
90
+ readonly perTaskDeleteDelaySec: number;
91
+ /** Cadence of the L2 background sweeper. */
92
+ readonly sweepIntervalMinutes: number;
93
+ /** Files older than this are considered orphans by L2. */
94
+ readonly sweepAgeHours: number;
95
+ /**
96
+ * If `df` reports free MB below this threshold, L3 forces a sweep
97
+ * before letting the resolver write. Free space is checked AFTER
98
+ * the sweep too (see `diskCriticalFreeMb`).
99
+ */
100
+ readonly diskMinFreeMb: number;
101
+ /**
102
+ * If free MB is *still* below this after the L3 force-sweep, the
103
+ * resolve is rejected with `disk_pressure`. By convention should be
104
+ * less than `diskMinFreeMb` so the two thresholds form a hysteresis
105
+ * band; misordering only causes extra rejections, never data loss.
106
+ */
107
+ readonly diskCriticalFreeMb: number;
108
+ }
109
+ /**
110
+ * L1 — per-task lifecycle manager.
111
+ *
112
+ * `trackFresh` records a fresh asset that the running task created
113
+ * (cache hits MUST NOT be tracked: those belong to whichever earlier
114
+ * task originally fetched them, and the cache layer already handles
115
+ * staleness via `validateAlive`).
116
+ *
117
+ * `onTaskEnd` is called from `AgentHost.runOne`'s `finally` clause.
118
+ * The manager schedules the actual delete after
119
+ * `perTaskDeleteDelaySec`, which is also when the cache key is
120
+ * invalidated and MediaScanner is poked so the gallery view drops
121
+ * the thumbnail.
122
+ *
123
+ * `flushPending` is a shutdown helper that fires every still-armed
124
+ * timer immediately, so SIGTERM doesn't leak orphan files.
125
+ */
126
+ export interface ResourceLifecycleManager {
127
+ /**
128
+ * Record a fresh asset created by the named task. Cache hits MUST
129
+ * NOT call this — only assets returned by a real network resolve.
130
+ */
131
+ trackFresh(taskId: string, asset: ResolvedAsset): void;
132
+ /**
133
+ * Schedule cleanup for every asset registered against `taskId`.
134
+ * Idempotent — calling twice for the same id is a no-op (e.g. when
135
+ * `runOne` retries `finally` because of a thrown listener).
136
+ */
137
+ onTaskEnd(taskId: string): Promise<void>;
138
+ /**
139
+ * Best-effort: fire every pending L1 timer NOW (used by the SIGTERM
140
+ * shutdown hook). Returns once all `executeCommand` round-trips
141
+ * settled.
142
+ */
143
+ flushPending(): Promise<void>;
144
+ }
145
+ /**
146
+ * L2 — background TTL sweeper. Owned by bootstrap; started after
147
+ * the agent is ready, stopped on shutdown.
148
+ */
149
+ export interface ResourceLifecycleSweeper {
150
+ /** Begin periodic sweeps. Idempotent; calling start twice is a no-op. */
151
+ start(): void;
152
+ /** Cancel the timer; in-flight sweep is allowed to finish. */
153
+ stop(): Promise<void>;
154
+ /**
155
+ * Run a sweep right now (used by L3 force-sweep + tests). Resolves
156
+ * with the number of files deleted so callers can decide whether
157
+ * to retry the failed write.
158
+ */
159
+ sweepNow(): Promise<number>;
160
+ }
161
+ /**
162
+ * Wiring blob the bootstrap hands the lifecycle implementations.
163
+ *
164
+ * Kept as a discrete struct so tests can construct managers without
165
+ * spinning up a real device or MCP. `device` is used only for
166
+ * platform detection (the entire lifecycle is a no-op on non-Android
167
+ * because MediaStore + /sdcard semantics are Android-specific).
168
+ */
169
+ export interface LifecycleWiring {
170
+ /** Active device, used to detect platform. */
171
+ readonly device: IDevice;
172
+ /** Live MCP runtime resolver — the same callback the AgentHost uses. */
173
+ readonly mcpProvider: () => IMcpRuntime;
174
+ /** Resource cache — invalidated when L1 deletes a tracked asset. */
175
+ readonly cache?: ResourceResolutionCache;
176
+ /** Structured logger (typically a child of the bootstrap logger). */
177
+ readonly log: ResolverLogger;
178
+ /** Static configuration (from `[resources.lifecycle]`). */
179
+ readonly config: ResourceLifecycleConfig;
180
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Resource Lifecycle — type contracts for the three-layer GC.
3
+ *
4
+ * The Resource Resolution Layer must land URL-derived bytes on the
5
+ * device's external storage so platform-native pickers (Photos,
6
+ * Gallery, WeChat moments composer, …) can index them via MediaStore.
7
+ * Once a single task has finished — i.e. the picker has copied the
8
+ * file into the consuming app's sandbox via `ContentProvider.openInputStream`
9
+ * — the original device-side file is dead weight.
10
+ *
11
+ * Without explicit reclamation a long-running daemon would accumulate
12
+ * gigabytes of orphan resources. We model this as a classic three-layer
13
+ * garbage collector, mirroring the structure of any robust resource
14
+ * manager (Linux page cache, browser HTTP cache, JVM GC):
15
+ *
16
+ * L1 — per-task ephemeral cleanup
17
+ * Happy-path tracking. Each task has a finite lifetime; when
18
+ * `agent.run()` returns / throws / aborts, schedule a delete
19
+ * of every fresh resource the task pushed (plus a small grace
20
+ * window so async picker uploads finish first).
21
+ *
22
+ * L2 — background TTL sweep
23
+ * Crash / kill -9 / unclean shutdown safety net. Runs on a
24
+ * timer; deletes any `beeos_*` file under the sandbox root
25
+ * whose mtime is older than `sweepAgeHours`.
26
+ *
27
+ * L3 — disk-pressure adaptive sweep
28
+ * Per-write check that prevents the agent from filling the
29
+ * device's external storage. Triggers a force-sweep when
30
+ * free space drops below `diskMinFreeMb`; rejects the resolve
31
+ * with `disk_pressure` if free space stays below
32
+ * `diskCriticalFreeMb` after sweeping.
33
+ *
34
+ * Each layer fail-softs to the next: L1 misses (crash / no finally) →
35
+ * L2 catches; L2 misses (daemon never idle, sweeper paused) → L3
36
+ * catches. Stacked, they are asymptotically complete.
37
+ *
38
+ * Why this lives next to `resources/` and not in `app/`:
39
+ * - the lifecycle is **about** resources (their identity, their
40
+ * storage path, their cache invalidation contract).
41
+ * - the AgentHost only needs to call `trackFresh(taskId, asset)` and
42
+ * `onTaskEnd(taskId)` — it does not need to know about sweeps,
43
+ * TTLs, or `df`/`find` shell commands.
44
+ */
45
+ export {};
46
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/resources/lifecycle/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Resource Parsers — extract `ResourceRef`s from a free-form task string.
3
+ *
4
+ * The Phase 1 implementation ships a single, conservative URL parser.
5
+ * Adding new parsers (file://, data:, geo:) is a matter of dropping a
6
+ * new module beside this one and registering it in the host bootstrap.
7
+ *
8
+ * Conservative: we deliberately avoid shipping liberal regexes that
9
+ * match every-string-with-a-dot. False positives here translate into
10
+ * unwanted network calls during the resolve phase, which (a) burn
11
+ * SSRF allow-list checks, (b) confuse the augmenter ("Resources
12
+ * prepared: <some random word>"), and (c) slow down every task.
13
+ */
14
+ import type { ResourceParser, ResourceRef } from "./types.js";
15
+ export declare class UrlParser implements ResourceParser {
16
+ readonly name = "url";
17
+ parse(task: string): ResourceRef[];
18
+ }
19
+ export declare class BeeosFileParser implements ResourceParser {
20
+ readonly name = "beeos-file";
21
+ parse(task: string): ResourceRef[];
22
+ }
23
+ /**
24
+ * Convenience: build the default parser set used by the AgentHost
25
+ * registry. Exported so tests / alternate hosts can swap individual
26
+ * parsers without rebuilding the list.
27
+ */
28
+ export declare function defaultParsers(): ResourceParser[];
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Resource Parsers — extract `ResourceRef`s from a free-form task string.
3
+ *
4
+ * The Phase 1 implementation ships a single, conservative URL parser.
5
+ * Adding new parsers (file://, data:, geo:) is a matter of dropping a
6
+ * new module beside this one and registering it in the host bootstrap.
7
+ *
8
+ * Conservative: we deliberately avoid shipping liberal regexes that
9
+ * match every-string-with-a-dot. False positives here translate into
10
+ * unwanted network calls during the resolve phase, which (a) burn
11
+ * SSRF allow-list checks, (b) confuse the augmenter ("Resources
12
+ * prepared: <some random word>"), and (c) slow down every task.
13
+ */
14
+ /**
15
+ * Match plain http/https URLs anywhere in a task string.
16
+ *
17
+ * Kept intentionally close to the RFC 3986 reserved-characters set so
18
+ * we don't accidentally absorb trailing punctuation. The negative
19
+ * look-behind for `[a-zA-Z]` after the scheme prevents matching
20
+ * `mailto:foo@http://x` style edge cases.
21
+ */
22
+ const URL_RE = /\bhttps?:\/\/[^\s<>"'\u3000\u00A0`]+/giu;
23
+ /**
24
+ * Trailing punctuation that we strip — these are commonly part of the
25
+ * surrounding sentence rather than the URL itself ("see https://x.y/z.").
26
+ */
27
+ const TRAILING_PUNCT_RE = /[)\].,;:!?'"`]+$/u;
28
+ export class UrlParser {
29
+ name = "url";
30
+ parse(task) {
31
+ if (!task)
32
+ return [];
33
+ const seen = new Set();
34
+ const out = [];
35
+ const matches = task.matchAll(URL_RE);
36
+ for (const m of matches) {
37
+ const raw = m[0];
38
+ const cleaned = raw.replace(TRAILING_PUNCT_RE, "");
39
+ if (!cleaned)
40
+ continue;
41
+ if (seen.has(cleaned))
42
+ continue;
43
+ seen.add(cleaned);
44
+ out.push({ kind: "url", url: cleaned });
45
+ }
46
+ return out;
47
+ }
48
+ }
49
+ /**
50
+ * Match `beeos-file://<fileId>` URIs. The web UI emits these for every
51
+ * file the user uploads through the chat input; the
52
+ * `normalizePrompt` step appends each `resource_link.uri` to the prompt
53
+ * verbatim, so the URI shows up here as plain text.
54
+ *
55
+ * `fileId` is constrained to a conservative URL-safe character class to
56
+ * keep false positives (e.g. matching unrelated `beeos-file://` substrings
57
+ * embedded in user prose) from flooding the resolve queue. The web UI
58
+ * generates fileIds that are alphanumeric + dash/underscore (UUID-shaped
59
+ * or random ids), all of which match `[A-Za-z0-9_-]+`.
60
+ */
61
+ const BEEOS_FILE_RE = /\bbeeos-file:\/\/([A-Za-z0-9_-]+)\b/giu;
62
+ export class BeeosFileParser {
63
+ name = "beeos-file";
64
+ parse(task) {
65
+ if (!task)
66
+ return [];
67
+ const seen = new Set();
68
+ const out = [];
69
+ const matches = task.matchAll(BEEOS_FILE_RE);
70
+ for (const m of matches) {
71
+ const fileId = m[1];
72
+ if (!fileId || seen.has(fileId))
73
+ continue;
74
+ seen.add(fileId);
75
+ out.push({ kind: "beeos-file", fileId });
76
+ }
77
+ return out;
78
+ }
79
+ }
80
+ /**
81
+ * Convenience: build the default parser set used by the AgentHost
82
+ * registry. Exported so tests / alternate hosts can swap individual
83
+ * parsers without rebuilding the list.
84
+ */
85
+ export function defaultParsers() {
86
+ return [new UrlParser(), new BeeosFileParser()];
87
+ }
88
+ //# sourceMappingURL=parsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/resources/parsers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,yCAAyC,CAAC;AAEzD;;;GAGG;AACH,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAE9C,MAAM,OAAO,SAAS;IACX,IAAI,GAAG,KAAK,CAAC;IAEtB,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,GAAG,GAAkB,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACjB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,SAAS;YAChC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,aAAa,GAAG,wCAAwC,CAAC;AAE/D,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,YAAY,CAAC;IAE7B,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,GAAG,GAAkB,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC7C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAC1C,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,IAAI,SAAS,EAAE,EAAE,IAAI,eAAe,EAAE,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Resource Resolver Registry — owns the parser/resolver dispatch and
3
+ * the `resolveAll(task)` orchestration entry point.
4
+ *
5
+ * Lifecycle:
6
+ * 1. Bootstrap constructs one registry per AgentHost.
7
+ * 2. AgentHost.submitTask calls `parseAll(prompt)` to extract refs.
8
+ * 3. For each ref, registry picks the first matching `ResourceResolver`
9
+ * and delegates resolution. Parallel where possible.
10
+ * 4. Failures are isolated: one bad URL must not poison the rest of
11
+ * the task. The host falls back to the original prompt only when
12
+ * every resolution failed (or zero refs were found).
13
+ *
14
+ * The registry stays explicit about its dependencies (`ResolverContext`)
15
+ * so unit tests can wire it up without bootstrap.
16
+ */
17
+ import type { ResolvedAsset, ResolverContext, ResourceParser, ResourceRef, ResourceResolver } from "./types.js";
18
+ export interface ResolveAllResult {
19
+ /** Successfully resolved assets. */
20
+ assets: ResolvedAsset[];
21
+ /** Per-ref errors (parallel array; one entry per failed ref). */
22
+ errors: {
23
+ ref: ResourceRef;
24
+ error: Error;
25
+ }[];
26
+ /** Refs the registry chose to skip (e.g. no resolver matched). */
27
+ skipped: ResourceRef[];
28
+ }
29
+ export interface ResolverRegistryOptions {
30
+ parsers: ResourceParser[];
31
+ resolvers: ResourceResolver[];
32
+ }
33
+ export declare class ResourceResolverRegistry {
34
+ private readonly parsers;
35
+ private readonly resolvers;
36
+ constructor(opts: ResolverRegistryOptions);
37
+ /** Run every registered parser; deduplicate by JSON-canonical key. */
38
+ parseAll(task: string): ResourceRef[];
39
+ /**
40
+ * Resolve every ref present in the task. Returns successfully
41
+ * resolved assets; failures are surfaced via the `errors` array but
42
+ * never thrown — the AgentHost is responsible for falling back to
43
+ * the original prompt when no asset survived.
44
+ */
45
+ resolveAll(task: string, ctx: ResolverContext): Promise<ResolveAllResult>;
46
+ private pick;
47
+ }