@beeos-ai/device-agent 0.4.2 → 0.5.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 (181) hide show
  1. package/.pi/extensions/android-tools.ts +146 -15
  2. package/LICENSE +201 -0
  3. package/dist/adapters/agent-gateway-client.d.ts +37 -0
  4. package/dist/adapters/agent-gateway-client.js +45 -0
  5. package/dist/adapters/agent-gateway-client.js.map +1 -1
  6. package/dist/adapters/agentcore-pi.d.ts +22 -0
  7. package/dist/adapters/agentcore-pi.js +48 -0
  8. package/dist/adapters/agentcore-pi.js.map +1 -1
  9. package/dist/adapters/device-android-adb.d.ts +47 -0
  10. package/dist/adapters/device-android-adb.js +50 -0
  11. package/dist/adapters/device-android-adb.js.map +1 -1
  12. package/dist/adapters/device-desktop.d.ts +12 -0
  13. package/dist/adapters/device-desktop.js +31 -0
  14. package/dist/adapters/device-desktop.js.map +1 -1
  15. package/dist/agent-runtime/adapters/base.d.ts +20 -0
  16. package/dist/agent-runtime/adapters/base.js.map +1 -1
  17. package/dist/agent-runtime/agent-runner.d.ts +4 -2
  18. package/dist/agent-runtime/agent-runner.js.map +1 -1
  19. package/dist/agent-runtime/core.d.ts +60 -0
  20. package/dist/agent-runtime/core.js +190 -9
  21. package/dist/agent-runtime/core.js.map +1 -1
  22. package/dist/agent-runtime/feedback.d.ts +56 -0
  23. package/dist/agent-runtime/feedback.js +54 -0
  24. package/dist/agent-runtime/feedback.js.map +1 -0
  25. package/dist/agent-runtime/index.d.ts +1 -0
  26. package/dist/agent-runtime/index.js +1 -0
  27. package/dist/agent-runtime/index.js.map +1 -1
  28. package/dist/agent-runtime/plan-executor.js +24 -0
  29. package/dist/agent-runtime/plan-executor.js.map +1 -1
  30. package/dist/agent-runtime/planner/base.d.ts +10 -0
  31. package/dist/agent-runtime/planner/base.js.map +1 -1
  32. package/dist/agent-runtime/planner/llm-planner.js +1 -0
  33. package/dist/agent-runtime/planner/llm-planner.js.map +1 -1
  34. package/dist/agent-runtime/planner/prompts.d.ts +3 -0
  35. package/dist/agent-runtime/planner/prompts.js +12 -0
  36. package/dist/agent-runtime/planner/prompts.js.map +1 -1
  37. package/dist/agent-runtime/reflection.d.ts +25 -6
  38. package/dist/agent-runtime/reflection.js +64 -22
  39. package/dist/agent-runtime/reflection.js.map +1 -1
  40. package/dist/agent-runtime/reflectors/policy.d.ts +10 -4
  41. package/dist/agent-runtime/reflectors/policy.js +19 -6
  42. package/dist/agent-runtime/reflectors/policy.js.map +1 -1
  43. package/dist/agent-runtime/shortcuts/fs-store.d.ts +41 -0
  44. package/dist/agent-runtime/shortcuts/fs-store.js +122 -0
  45. package/dist/agent-runtime/shortcuts/fs-store.js.map +1 -0
  46. package/dist/agent-runtime/shortcuts/in-memory-store.d.ts +20 -0
  47. package/dist/agent-runtime/shortcuts/in-memory-store.js +64 -0
  48. package/dist/agent-runtime/shortcuts/in-memory-store.js.map +1 -0
  49. package/dist/agent-runtime/shortcuts/index.d.ts +10 -0
  50. package/dist/agent-runtime/shortcuts/index.js +10 -0
  51. package/dist/agent-runtime/shortcuts/index.js.map +1 -0
  52. package/dist/agent-runtime/shortcuts/types.d.ts +69 -0
  53. package/dist/agent-runtime/shortcuts/types.js +17 -0
  54. package/dist/agent-runtime/shortcuts/types.js.map +1 -0
  55. package/dist/app/agent-host.d.ts +83 -0
  56. package/dist/app/agent-host.js +345 -32
  57. package/dist/app/agent-host.js.map +1 -1
  58. package/dist/app/session-manager.d.ts +33 -4
  59. package/dist/app/session-manager.js +27 -5
  60. package/dist/app/session-manager.js.map +1 -1
  61. package/dist/bootstrap.js +187 -3
  62. package/dist/bootstrap.js.map +1 -1
  63. package/dist/config/loader.js +22 -0
  64. package/dist/config/loader.js.map +1 -1
  65. package/dist/config/schema.d.ts +18 -0
  66. package/dist/config/schema.js +118 -0
  67. package/dist/config/schema.js.map +1 -1
  68. package/dist/inbound/acp/handlers/session.js.map +1 -1
  69. package/dist/mcp-client/client.d.ts +6 -0
  70. package/dist/mcp-client/client.js +11 -0
  71. package/dist/mcp-client/client.js.map +1 -1
  72. package/dist/mcp-client/runtime.d.ts +13 -0
  73. package/dist/orchestrator-system-prompt.d.ts +26 -0
  74. package/dist/orchestrator-system-prompt.js +118 -2
  75. package/dist/orchestrator-system-prompt.js.map +1 -1
  76. package/dist/pi-context.d.ts +50 -0
  77. package/dist/pi-context.js.map +1 -1
  78. package/dist/ports/device.d.ts +18 -0
  79. package/dist/resources/augmenter.d.ts +48 -0
  80. package/dist/resources/augmenter.js +126 -0
  81. package/dist/resources/augmenter.js.map +1 -0
  82. package/dist/resources/cache.d.ts +57 -0
  83. package/dist/resources/cache.js +107 -0
  84. package/dist/resources/cache.js.map +1 -0
  85. package/dist/resources/index.d.ts +17 -0
  86. package/dist/resources/index.js +15 -0
  87. package/dist/resources/index.js.map +1 -0
  88. package/dist/resources/lifecycle/disk-pressure.d.ts +75 -0
  89. package/dist/resources/lifecycle/disk-pressure.js +148 -0
  90. package/dist/resources/lifecycle/disk-pressure.js.map +1 -0
  91. package/dist/resources/lifecycle/index.d.ts +7 -0
  92. package/dist/resources/lifecycle/index.js +7 -0
  93. package/dist/resources/lifecycle/index.js.map +1 -0
  94. package/dist/resources/lifecycle/manager.d.ts +38 -0
  95. package/dist/resources/lifecycle/manager.js +205 -0
  96. package/dist/resources/lifecycle/manager.js.map +1 -0
  97. package/dist/resources/lifecycle/sweeper.d.ts +36 -0
  98. package/dist/resources/lifecycle/sweeper.js +179 -0
  99. package/dist/resources/lifecycle/sweeper.js.map +1 -0
  100. package/dist/resources/lifecycle/types.d.ts +180 -0
  101. package/dist/resources/lifecycle/types.js +46 -0
  102. package/dist/resources/lifecycle/types.js.map +1 -0
  103. package/dist/resources/parsers.d.ts +28 -0
  104. package/dist/resources/parsers.js +88 -0
  105. package/dist/resources/parsers.js.map +1 -0
  106. package/dist/resources/registry.d.ts +47 -0
  107. package/dist/resources/registry.js +107 -0
  108. package/dist/resources/registry.js.map +1 -0
  109. package/dist/resources/resolvers/beeos-file-resolver.d.ts +62 -0
  110. package/dist/resources/resolvers/beeos-file-resolver.js +109 -0
  111. package/dist/resources/resolvers/beeos-file-resolver.js.map +1 -0
  112. package/dist/resources/resolvers/errors.d.ts +11 -0
  113. package/dist/resources/resolvers/errors.js +23 -0
  114. package/dist/resources/resolvers/errors.js.map +1 -0
  115. package/dist/resources/resolvers/mime-table.d.ts +41 -0
  116. package/dist/resources/resolvers/mime-table.js +92 -0
  117. package/dist/resources/resolvers/mime-table.js.map +1 -0
  118. package/dist/resources/resolvers/url-resolver.d.ts +85 -0
  119. package/dist/resources/resolvers/url-resolver.js +495 -0
  120. package/dist/resources/resolvers/url-resolver.js.map +1 -0
  121. package/dist/resources/shortcut-facade.d.ts +51 -0
  122. package/dist/resources/shortcut-facade.js +72 -0
  123. package/dist/resources/shortcut-facade.js.map +1 -0
  124. package/dist/resources/telemetry.d.ts +52 -0
  125. package/dist/resources/telemetry.js +59 -0
  126. package/dist/resources/telemetry.js.map +1 -0
  127. package/dist/resources/types.d.ts +249 -0
  128. package/dist/resources/types.js +29 -0
  129. package/dist/resources/types.js.map +1 -0
  130. package/dist/shortcuts/builtins/download-to-device.d.ts +83 -0
  131. package/dist/shortcuts/builtins/download-to-device.js +125 -0
  132. package/dist/shortcuts/builtins/download-to-device.js.map +1 -0
  133. package/dist/shortcuts/builtins/find-app-package.d.ts +79 -0
  134. package/dist/shortcuts/builtins/find-app-package.js +168 -0
  135. package/dist/shortcuts/builtins/find-app-package.js.map +1 -0
  136. package/dist/shortcuts/builtins/index.d.ts +32 -0
  137. package/dist/shortcuts/builtins/index.js +37 -0
  138. package/dist/shortcuts/builtins/index.js.map +1 -0
  139. package/dist/shortcuts/builtins/open-deeplink.d.ts +68 -0
  140. package/dist/shortcuts/builtins/open-deeplink.js +142 -0
  141. package/dist/shortcuts/builtins/open-deeplink.js.map +1 -0
  142. package/dist/shortcuts/builtins/set-clipboard.d.ts +65 -0
  143. package/dist/shortcuts/builtins/set-clipboard.js +112 -0
  144. package/dist/shortcuts/builtins/set-clipboard.js.map +1 -0
  145. package/dist/shortcuts/index.d.ts +11 -0
  146. package/dist/shortcuts/index.js +11 -0
  147. package/dist/shortcuts/index.js.map +1 -0
  148. package/dist/shortcuts/registry.d.ts +56 -0
  149. package/dist/shortcuts/registry.js +70 -0
  150. package/dist/shortcuts/registry.js.map +1 -0
  151. package/dist/shortcuts/router.d.ts +91 -0
  152. package/dist/shortcuts/router.js +158 -0
  153. package/dist/shortcuts/router.js.map +1 -0
  154. package/dist/shortcuts/types.d.ts +219 -0
  155. package/dist/shortcuts/types.js +46 -0
  156. package/dist/shortcuts/types.js.map +1 -0
  157. package/package.json +24 -25
  158. package/dist/agent-runtime/skills/sqlite-store.d.ts +0 -60
  159. package/dist/agent-runtime/skills/sqlite-store.js +0 -234
  160. package/dist/agent-runtime/skills/sqlite-store.js.map +0 -1
  161. package/dist/test-lan-autoglm.d.ts +0 -7
  162. package/dist/test-lan-autoglm.js +0 -46
  163. package/dist/test-lan-autoglm.js.map +0 -1
  164. package/dist/test-mem-breakdown.d.ts +0 -1
  165. package/dist/test-mem-breakdown.js +0 -103
  166. package/dist/test-mem-breakdown.js.map +0 -1
  167. package/dist/test-mem.d.ts +0 -1
  168. package/dist/test-mem.js +0 -60
  169. package/dist/test-mem.js.map +0 -1
  170. package/dist/test-mobile-use.d.ts +0 -1
  171. package/dist/test-mobile-use.js +0 -18
  172. package/dist/test-mobile-use.js.map +0 -1
  173. package/dist/test-screenshot-loop.d.ts +0 -1
  174. package/dist/test-screenshot-loop.js +0 -43
  175. package/dist/test-screenshot-loop.js.map +0 -1
  176. package/dist/test-screenshot.d.ts +0 -1
  177. package/dist/test-screenshot.js +0 -10
  178. package/dist/test-screenshot.js.map +0 -1
  179. package/dist/test-ui-xml-dump.d.ts +0 -15
  180. package/dist/test-ui-xml-dump.js +0 -49
  181. package/dist/test-ui-xml-dump.js.map +0 -1
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Filesystem-backed `ShortcutMemoryStore` — minimal Phase 3
3
+ * implementation per ADR 001.
4
+ *
5
+ * Layout (under `<root>/`, defaults to
6
+ * `~/.beeos/device-agent/shortcuts/`):
7
+ *
8
+ * <root>/index.json — single JSON file mapping
9
+ * "<taskPattern>::<shortcutId>" →
10
+ * ShortcutMemoryRecord.
11
+ *
12
+ * We deliberately use a single index file (not one-file-per-record)
13
+ * because Phase 3 is write-only telemetry and the catalogue is
14
+ * 4 shortcuts. The file is rewritten atomically (tmp + rename) on
15
+ * every increment to keep the on-disk view consistent for the
16
+ * future matcher.
17
+ *
18
+ * Concurrency:
19
+ * The bootstrap process creates one `FsShortcutMemoryStore` per
20
+ * device-agent process. Cross-process locking is out of scope for
21
+ * Phase 3 — nothing reads-modifies the index outside the agent.
22
+ */
23
+ import { promises as fs } from "node:fs";
24
+ import * as path from "node:path";
25
+ import { homedir } from "node:os";
26
+ const INDEX_FILE = "index.json";
27
+ function defaultRoot() {
28
+ return path.join(homedir(), ".beeos", "device-agent", "shortcuts");
29
+ }
30
+ function recordKey(taskPattern, shortcutId) {
31
+ return `${taskPattern}::${shortcutId}`;
32
+ }
33
+ export class FsShortcutMemoryStore {
34
+ root;
35
+ cache = null;
36
+ /** Serialise concurrent writes within the same process. */
37
+ writeChain = Promise.resolve();
38
+ constructor(opts = {}) {
39
+ this.root = opts.root ?? defaultRoot();
40
+ }
41
+ async recordSuccess(taskPattern, shortcutId) {
42
+ return this.mutate(taskPattern, shortcutId, (rec, now) => {
43
+ rec.successCount += 1;
44
+ rec.totalCount += 1;
45
+ rec.lastUpdatedAt = now;
46
+ });
47
+ }
48
+ async recordFailure(taskPattern, shortcutId, code) {
49
+ return this.mutate(taskPattern, shortcutId, (rec, now) => {
50
+ rec.failCountByCode[code] = (rec.failCountByCode[code] ?? 0) + 1;
51
+ rec.totalCount += 1;
52
+ rec.lastUpdatedAt = now;
53
+ });
54
+ }
55
+ async get(taskPattern, shortcutId) {
56
+ const idx = await this.loadIndex();
57
+ return idx[recordKey(taskPattern, shortcutId)];
58
+ }
59
+ async list() {
60
+ const idx = await this.loadIndex();
61
+ return Object.values(idx);
62
+ }
63
+ /* ---------------------------------------------------------------- */
64
+ /* internals */
65
+ /* ---------------------------------------------------------------- */
66
+ async loadIndex() {
67
+ if (this.cache)
68
+ return this.cache;
69
+ try {
70
+ const raw = await fs.readFile(path.join(this.root, INDEX_FILE), "utf8");
71
+ this.cache = JSON.parse(raw);
72
+ }
73
+ catch (e) {
74
+ const err = e;
75
+ if (err.code !== "ENOENT") {
76
+ // Corruption / parse error — start fresh rather than crash. The
77
+ // store is telemetry, the agent must keep running.
78
+ this.cache = {};
79
+ return this.cache;
80
+ }
81
+ this.cache = {};
82
+ }
83
+ return this.cache;
84
+ }
85
+ async writeIndex() {
86
+ if (!this.cache)
87
+ return;
88
+ await fs.mkdir(this.root, { recursive: true });
89
+ const finalPath = path.join(this.root, INDEX_FILE);
90
+ const tmpPath = `${finalPath}.tmp-${process.pid}-${Date.now()}`;
91
+ await fs.writeFile(tmpPath, JSON.stringify(this.cache, null, 2), "utf8");
92
+ await fs.rename(tmpPath, finalPath);
93
+ }
94
+ mutate(taskPattern, shortcutId, update) {
95
+ const next = this.writeChain.then(async () => {
96
+ const now = Date.now();
97
+ const idx = await this.loadIndex();
98
+ const key = recordKey(taskPattern, shortcutId);
99
+ let rec = idx[key];
100
+ if (!rec) {
101
+ rec = {
102
+ taskPattern,
103
+ shortcutId,
104
+ successCount: 0,
105
+ failCountByCode: {},
106
+ totalCount: 0,
107
+ createdAt: now,
108
+ lastUpdatedAt: now,
109
+ };
110
+ idx[key] = rec;
111
+ }
112
+ update(rec, now);
113
+ await this.writeIndex();
114
+ });
115
+ // Swallow errors on the chain so a single failed write doesn't
116
+ // poison every subsequent one. Each `next` promise still rejects
117
+ // for the caller that triggered it.
118
+ this.writeChain = next.catch(() => undefined);
119
+ return next;
120
+ }
121
+ }
122
+ //# sourceMappingURL=fs-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-store.js","sourceRoot":"","sources":["../../../src/agent-runtime/shortcuts/fs-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * In-memory `ShortcutMemoryStore` — used by tests and as the default
3
+ * before the bootstrap layer optionally swaps in a `FsShortcutMemoryStore`.
4
+ *
5
+ * Storage layout:
6
+ * `Map<key, ShortcutMemoryRecord>` where `key = "<taskPattern>::<shortcutId>"`.
7
+ *
8
+ * The store is intentionally tiny — Phase 3 is "telemetry-only" per
9
+ * the plan. Compaction, eviction, and concurrency safety are out of
10
+ * scope; tests confirm the pure-counter semantics.
11
+ */
12
+ import type { ShortcutMemoryRecord, ShortcutMemoryStore } from "./types.js";
13
+ import type { ShortcutErrorCode } from "../../shortcuts/types.js";
14
+ export declare class InMemoryShortcutMemoryStore implements ShortcutMemoryStore {
15
+ private readonly entries;
16
+ recordSuccess(taskPattern: string, shortcutId: string): Promise<void>;
17
+ recordFailure(taskPattern: string, shortcutId: string, code: ShortcutErrorCode): Promise<void>;
18
+ get(taskPattern: string, shortcutId: string): Promise<ShortcutMemoryRecord | undefined>;
19
+ list(): Promise<ShortcutMemoryRecord[]>;
20
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * In-memory `ShortcutMemoryStore` — used by tests and as the default
3
+ * before the bootstrap layer optionally swaps in a `FsShortcutMemoryStore`.
4
+ *
5
+ * Storage layout:
6
+ * `Map<key, ShortcutMemoryRecord>` where `key = "<taskPattern>::<shortcutId>"`.
7
+ *
8
+ * The store is intentionally tiny — Phase 3 is "telemetry-only" per
9
+ * the plan. Compaction, eviction, and concurrency safety are out of
10
+ * scope; tests confirm the pure-counter semantics.
11
+ */
12
+ function recordKey(taskPattern, shortcutId) {
13
+ return `${taskPattern}::${shortcutId}`;
14
+ }
15
+ export class InMemoryShortcutMemoryStore {
16
+ entries = new Map();
17
+ async recordSuccess(taskPattern, shortcutId) {
18
+ const now = Date.now();
19
+ const key = recordKey(taskPattern, shortcutId);
20
+ const existing = this.entries.get(key);
21
+ if (existing) {
22
+ existing.successCount += 1;
23
+ existing.totalCount += 1;
24
+ existing.lastUpdatedAt = now;
25
+ return;
26
+ }
27
+ this.entries.set(key, {
28
+ taskPattern,
29
+ shortcutId,
30
+ successCount: 1,
31
+ failCountByCode: {},
32
+ totalCount: 1,
33
+ createdAt: now,
34
+ lastUpdatedAt: now,
35
+ });
36
+ }
37
+ async recordFailure(taskPattern, shortcutId, code) {
38
+ const now = Date.now();
39
+ const key = recordKey(taskPattern, shortcutId);
40
+ const existing = this.entries.get(key);
41
+ if (existing) {
42
+ existing.failCountByCode[code] = (existing.failCountByCode[code] ?? 0) + 1;
43
+ existing.totalCount += 1;
44
+ existing.lastUpdatedAt = now;
45
+ return;
46
+ }
47
+ this.entries.set(key, {
48
+ taskPattern,
49
+ shortcutId,
50
+ successCount: 0,
51
+ failCountByCode: { [code]: 1 },
52
+ totalCount: 1,
53
+ createdAt: now,
54
+ lastUpdatedAt: now,
55
+ });
56
+ }
57
+ async get(taskPattern, shortcutId) {
58
+ return this.entries.get(recordKey(taskPattern, shortcutId));
59
+ }
60
+ async list() {
61
+ return Array.from(this.entries.values());
62
+ }
63
+ }
64
+ //# sourceMappingURL=in-memory-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-store.js","sourceRoot":"","sources":["../../../src/agent-runtime/shortcuts/in-memory-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,SAAS,SAAS,CAAC,WAAmB,EAAE,UAAkB;IACxD,OAAO,GAAG,WAAW,KAAK,UAAU,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,OAAO,2BAA2B;IACrB,OAAO,GAAG,IAAI,GAAG,EAAgC,CAAC;IAEnE,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,UAAkB;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC;YAC3B,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;YACzB,QAAQ,CAAC,aAAa,GAAG,GAAG,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;YACpB,WAAW;YACX,UAAU;YACV,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,GAAG;YACd,aAAa,EAAE,GAAG;SACnB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,WAAmB,EACnB,UAAkB,EAClB,IAAuB;QAEvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3E,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;YACzB,QAAQ,CAAC,aAAa,GAAG,GAAG,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;YACpB,WAAW;YACX,UAAU;YACV,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAC9B,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,GAAG;YACd,aAAa,EAAE,GAAG;SACnB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CACP,WAAmB,EACnB,UAAkB;QAElB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Phase 3 — Shortcut Memory Store barrel.
3
+ *
4
+ * Per ADR 001, this module is intentionally separate from
5
+ * `src/agent-runtime/skills/`. Use the in-memory store in tests; the
6
+ * filesystem store ships as the bootstrap default.
7
+ */
8
+ export type { ShortcutMemoryRecord, ShortcutMemoryStore, ShortcutOutcome, } from "./types.js";
9
+ export { InMemoryShortcutMemoryStore } from "./in-memory-store.js";
10
+ export { FsShortcutMemoryStore, type FsShortcutMemoryStoreOptions, } from "./fs-store.js";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Phase 3 — Shortcut Memory Store barrel.
3
+ *
4
+ * Per ADR 001, this module is intentionally separate from
5
+ * `src/agent-runtime/skills/`. Use the in-memory store in tests; the
6
+ * filesystem store ships as the bootstrap default.
7
+ */
8
+ export { InMemoryShortcutMemoryStore } from "./in-memory-store.js";
9
+ export { FsShortcutMemoryStore, } from "./fs-store.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent-runtime/shortcuts/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EACL,qBAAqB,GAEtB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Phase 3 — Shortcut Memory Store types.
3
+ *
4
+ * Per ADR 001 (Shortcut Memory Store: Bypass `SkillCacheStore`), the
5
+ * shortcut memory store is **separate** from the existing skill cache.
6
+ * It only records counter primitives (`recordSuccess`,
7
+ * `recordFailure`) keyed by `(taskPattern, shortcutId)` — no
8
+ * `appPackage`, no GUI action sequence, no embedding search.
9
+ *
10
+ * Recall ("which shortcut should I prefer for this task?") is
11
+ * deliberately deferred to a future ADR. The 4-shortcut catalogue is
12
+ * small enough that the orchestrator's static system prompt
13
+ * (`orchestrator-system-prompt.ts`) covers selection without a
14
+ * runtime matcher.
15
+ */
16
+ import type { ShortcutErrorCode } from "../../shortcuts/types.js";
17
+ /** Discriminated outcome — mirrors `ShortcutResult` but counter-shaped. */
18
+ export type ShortcutOutcome = {
19
+ ok: true;
20
+ } | {
21
+ ok: false;
22
+ code: ShortcutErrorCode;
23
+ };
24
+ /**
25
+ * One per (taskPattern, shortcutId) pair. The `taskPattern` is a
26
+ * caller-supplied digest of the task — typically the prompt's first
27
+ * 80 chars normalised; the store doesn't impose a schema beyond
28
+ * "string". Phase 3+ may add normalisation helpers when the matcher
29
+ * lands.
30
+ */
31
+ export interface ShortcutMemoryRecord {
32
+ taskPattern: string;
33
+ shortcutId: string;
34
+ successCount: number;
35
+ failCountByCode: Record<string, number>;
36
+ /** Sum of all counter increments — convenience for sorting. */
37
+ totalCount: number;
38
+ /** Wallclock ms of the last increment. */
39
+ lastUpdatedAt: number;
40
+ /** Wallclock ms of the first increment. */
41
+ createdAt: number;
42
+ }
43
+ /**
44
+ * Write-only audit log surface. Phase 3 keeps `ShortcutMemoryStore`
45
+ * intentionally narrow so callers can swap in-memory ↔ filesystem
46
+ * implementations without touching production code. A future
47
+ * `MatcherEvolver` may consume these records read-only via
48
+ * `top(taskPattern)` once the catalogue grows.
49
+ */
50
+ export interface ShortcutMemoryStore {
51
+ /** Increment the success counter for `(taskPattern, shortcutId)`. */
52
+ recordSuccess(taskPattern: string, shortcutId: string): Promise<void>;
53
+ /**
54
+ * Increment the failure counter, bucketed by error code. The error
55
+ * vocabulary is the closed-set `ShortcutErrorCode` so consumers can
56
+ * query "how often does `set_clipboard` hit `permission_denied`?".
57
+ */
58
+ recordFailure(taskPattern: string, shortcutId: string, code: ShortcutErrorCode): Promise<void>;
59
+ /**
60
+ * Read the record for `(taskPattern, shortcutId)`. Returns
61
+ * `undefined` when the pair has never been written.
62
+ */
63
+ get(taskPattern: string, shortcutId: string): Promise<ShortcutMemoryRecord | undefined>;
64
+ /**
65
+ * Enumerate every record. Used by the future matcher; Phase 3 callers
66
+ * mostly use it for diagnostics / tests.
67
+ */
68
+ list(): Promise<ShortcutMemoryRecord[]>;
69
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Phase 3 — Shortcut Memory Store types.
3
+ *
4
+ * Per ADR 001 (Shortcut Memory Store: Bypass `SkillCacheStore`), the
5
+ * shortcut memory store is **separate** from the existing skill cache.
6
+ * It only records counter primitives (`recordSuccess`,
7
+ * `recordFailure`) keyed by `(taskPattern, shortcutId)` — no
8
+ * `appPackage`, no GUI action sequence, no embedding search.
9
+ *
10
+ * Recall ("which shortcut should I prefer for this task?") is
11
+ * deliberately deferred to a future ADR. The 4-shortcut catalogue is
12
+ * small enough that the orchestrator's static system prompt
13
+ * (`orchestrator-system-prompt.ts`) covers selection without a
14
+ * runtime matcher.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/agent-runtime/shortcuts/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
@@ -22,6 +22,21 @@ import type { IAgentCore } from "../ports/agent-core.js";
22
22
  import type { AgentEventListener, AgentHost, SubmitTaskOptions, SubmittedTask } from "../ports/agent-host.js";
23
23
  import type { IDeviceIdentity } from "../ports/identity.js";
24
24
  import type { DeviceManager } from "./device-manager.js";
25
+ import type { IMcpRuntime } from "../mcp-client/runtime.js";
26
+ import { ResourceResolutionCache, ResourceResolverRegistry, type DiskPressureGuard, type ResourceLifecycleManager, type TaskContextAugmenter } from "../resources/index.js";
27
+ export interface AgentHostResourceConfig {
28
+ /** Master switch — when false, the entire layer is short-circuited. */
29
+ enabled: boolean;
30
+ /** Per-resource hard cap on body bytes. */
31
+ maxBytes: number;
32
+ /** Per-resource fetch timeout. */
33
+ timeoutMs: number;
34
+ /** URL schemes the URL resolver will accept. */
35
+ allowedSchemes: readonly string[];
36
+ /** Refuse to fetch URLs that DNS-resolve to private/loopback IPs. */
37
+ denyPrivateIp: boolean;
38
+ }
39
+ export declare const DEFAULT_RESOURCE_CONFIG: AgentHostResourceConfig;
25
40
  export interface AgentHostOptions {
26
41
  agent: IAgentCore;
27
42
  devices: DeviceManager;
@@ -31,6 +46,50 @@ export interface AgentHostOptions {
31
46
  defaultMaxSteps?: number;
32
47
  /** Override notice throttle (ms). Tests pin this to 0 to disable. */
33
48
  noticeWarnThrottleMs?: number;
49
+ /**
50
+ * Optional resolver registry. When omitted, the layer is
51
+ * short-circuited and `prompt` flows through to `IAgentCore.run`
52
+ * unchanged (legacy passthrough).
53
+ */
54
+ resourceResolver?: ResourceResolverRegistry;
55
+ /**
56
+ * Process-wide resolution cache (SHA-256(url) → ResolvedAsset).
57
+ * Optional — when omitted, every resolve goes to the network.
58
+ */
59
+ resourceCache?: ResourceResolutionCache;
60
+ /**
61
+ * Augmenter that injects "Resources prepared: …" preamble into the
62
+ * task before it reaches the agent core. Defaults to the standard
63
+ * `ResourceContextAugmenter` when omitted.
64
+ */
65
+ resourceAugmenter?: TaskContextAugmenter;
66
+ /**
67
+ * MCP runtime resolver (callback so an ACP `device/select` reflects
68
+ * immediately). Required for resource resolution to work — without
69
+ * it, the layer logs a `cache_validation_miss`-equivalent and falls
70
+ * back to the original prompt.
71
+ */
72
+ mcpProvider?: () => IMcpRuntime;
73
+ /**
74
+ * Feature-flag config — see `DEFAULT_RESOURCE_CONFIG`. The host
75
+ * owns evaluation of `enabled` so callers can hot-swap behaviour
76
+ * without rebuilding the registry.
77
+ */
78
+ resourceConfig?: AgentHostResourceConfig;
79
+ /**
80
+ * Phase 1.5 lifecycle manager (L1 per-task ephemeral cleanup).
81
+ * Optional — when omitted the host runs without per-task GC,
82
+ * matching pre-1.5 behaviour. Bootstrap wires
83
+ * `FsResourceLifecycleManager` for production runs.
84
+ */
85
+ lifecycle?: ResourceLifecycleManager;
86
+ /**
87
+ * Phase 1.5 disk-pressure guard (L3). Threaded through to the
88
+ * `ResolverContext` so the URL resolver can consult it just before
89
+ * `fileWrite`. Optional — when omitted the resolver behaves
90
+ * exactly as it did pre-1.5.
91
+ */
92
+ diskPressure?: DiskPressureGuard;
34
93
  }
35
94
  export declare class AgentHostImpl implements AgentHost {
36
95
  readonly agent: IAgentCore;
@@ -41,12 +100,36 @@ export declare class AgentHostImpl implements AgentHost {
41
100
  private readonly noticeWarnThrottleMs;
42
101
  private readonly listeners;
43
102
  private readonly tasks;
103
+ private readonly resourceResolver?;
104
+ private readonly resourceCache?;
105
+ private readonly resourceAugmenter;
106
+ private readonly resourceConfig;
107
+ private readonly mcpProvider?;
108
+ private readonly lifecycle?;
109
+ private readonly diskPressure?;
44
110
  constructor(opts: AgentHostOptions);
45
111
  on(listener: AgentEventListener): () => void;
46
112
  submitTask(prompt: string, opts?: SubmitTaskOptions): SubmittedTask;
47
113
  cancel(taskId: string): boolean;
48
114
  cancelAll(): Promise<void>;
49
115
  private runOne;
116
+ /**
117
+ * Resolve every resource referenced by the task prompt and return
118
+ * the augmented prompt (or the original prompt if resolution is
119
+ * disabled / unavailable / yielded zero assets). Each resolution
120
+ * surface as a `task:tool` event with `name = "resolve_resource"`
121
+ * and `start | update | end` lifecycle so the UI can render a
122
+ * download progress card. Failures degrade silently to the original
123
+ * prompt — the agent must remain functional even when the network
124
+ * is flaky or the URL points at a 404.
125
+ */
126
+ private resolveAndAugment;
127
+ /**
128
+ * Resolve a single ref by dispatching to the first matching resolver
129
+ * registered on `this.resourceResolver`. Mirrors the registry's
130
+ * private `pick` logic without re-parsing the task.
131
+ */
132
+ private resolveOne;
50
133
  /**
51
134
  * Translate a structured runtime error into a `task:notice` for the
52
135
  * UI, throttling non-fatal warnings so a 5xx retry storm doesn't