@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.
- package/.pi/extensions/android-tools.ts +146 -15
- package/dist/adapters/agent-gateway-client.d.ts +37 -0
- package/dist/adapters/agent-gateway-client.js +45 -0
- package/dist/adapters/agent-gateway-client.js.map +1 -1
- package/dist/adapters/agentcore-pi.d.ts +22 -0
- package/dist/adapters/agentcore-pi.js +48 -0
- package/dist/adapters/agentcore-pi.js.map +1 -1
- package/dist/adapters/device-android-adb.d.ts +47 -0
- package/dist/adapters/device-android-adb.js +50 -0
- package/dist/adapters/device-android-adb.js.map +1 -1
- package/dist/adapters/device-desktop.d.ts +12 -0
- package/dist/adapters/device-desktop.js +31 -0
- package/dist/adapters/device-desktop.js.map +1 -1
- package/dist/adapters/identity-file.d.ts +33 -5
- package/dist/adapters/identity-file.js +52 -6
- package/dist/adapters/identity-file.js.map +1 -1
- package/dist/agent-runtime/adapters/base.d.ts +20 -0
- package/dist/agent-runtime/adapters/base.js.map +1 -1
- package/dist/agent-runtime/agent-runner.d.ts +4 -2
- package/dist/agent-runtime/agent-runner.js.map +1 -1
- package/dist/agent-runtime/core.d.ts +60 -0
- package/dist/agent-runtime/core.js +190 -9
- package/dist/agent-runtime/core.js.map +1 -1
- package/dist/agent-runtime/feedback.d.ts +56 -0
- package/dist/agent-runtime/feedback.js +54 -0
- package/dist/agent-runtime/feedback.js.map +1 -0
- package/dist/agent-runtime/index.d.ts +1 -0
- package/dist/agent-runtime/index.js +1 -0
- package/dist/agent-runtime/index.js.map +1 -1
- package/dist/agent-runtime/plan-executor.js +24 -0
- package/dist/agent-runtime/plan-executor.js.map +1 -1
- package/dist/agent-runtime/planner/base.d.ts +10 -0
- package/dist/agent-runtime/planner/base.js.map +1 -1
- package/dist/agent-runtime/planner/llm-planner.js +1 -0
- package/dist/agent-runtime/planner/llm-planner.js.map +1 -1
- package/dist/agent-runtime/planner/prompts.d.ts +3 -0
- package/dist/agent-runtime/planner/prompts.js +12 -0
- package/dist/agent-runtime/planner/prompts.js.map +1 -1
- package/dist/agent-runtime/reflection.d.ts +25 -6
- package/dist/agent-runtime/reflection.js +64 -22
- package/dist/agent-runtime/reflection.js.map +1 -1
- package/dist/agent-runtime/reflectors/policy.d.ts +10 -4
- package/dist/agent-runtime/reflectors/policy.js +19 -6
- package/dist/agent-runtime/reflectors/policy.js.map +1 -1
- package/dist/agent-runtime/shortcuts/fs-store.d.ts +41 -0
- package/dist/agent-runtime/shortcuts/fs-store.js +122 -0
- package/dist/agent-runtime/shortcuts/fs-store.js.map +1 -0
- package/dist/agent-runtime/shortcuts/in-memory-store.d.ts +20 -0
- package/dist/agent-runtime/shortcuts/in-memory-store.js +64 -0
- package/dist/agent-runtime/shortcuts/in-memory-store.js.map +1 -0
- package/dist/agent-runtime/shortcuts/index.d.ts +10 -0
- package/dist/agent-runtime/shortcuts/index.js +10 -0
- package/dist/agent-runtime/shortcuts/index.js.map +1 -0
- package/dist/agent-runtime/shortcuts/types.d.ts +69 -0
- package/dist/agent-runtime/shortcuts/types.js +17 -0
- package/dist/agent-runtime/shortcuts/types.js.map +1 -0
- package/dist/app/agent-host.d.ts +83 -0
- package/dist/app/agent-host.js +345 -32
- package/dist/app/agent-host.js.map +1 -1
- package/dist/app/session-manager.d.ts +33 -4
- package/dist/app/session-manager.js +27 -5
- package/dist/app/session-manager.js.map +1 -1
- package/dist/bootstrap.js +187 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/config/loader.js +22 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +118 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/fleet/adapters/process/node-process-manager.js +97 -17
- package/dist/fleet/adapters/process/node-process-manager.js.map +1 -1
- package/dist/fleet/adapters/state/beeos-cli-store.d.ts +75 -9
- package/dist/fleet/adapters/state/beeos-cli-store.js +201 -17
- package/dist/fleet/adapters/state/beeos-cli-store.js.map +1 -1
- package/dist/fleet/domain/device.d.ts +9 -0
- package/dist/fleet/domain/device.js.map +1 -1
- package/dist/fleet/domain/fsm.js +34 -0
- package/dist/fleet/domain/fsm.js.map +1 -1
- package/dist/fleet/installer/spawn-env.d.ts +3 -0
- package/dist/fleet/installer/spawn-env.js +186 -3
- package/dist/fleet/installer/spawn-env.js.map +1 -1
- package/dist/fleet/state/state-json.d.ts +116 -0
- package/dist/fleet/state/state-json.js +87 -0
- package/dist/fleet/state/state-json.js.map +1 -0
- package/dist/fleet/supervisor.js +14 -2
- package/dist/fleet/supervisor.js.map +1 -1
- package/dist/inbound/acp/handlers/session.js.map +1 -1
- package/dist/mcp-client/client.d.ts +6 -0
- package/dist/mcp-client/client.js +11 -0
- package/dist/mcp-client/client.js.map +1 -1
- package/dist/mcp-client/runtime.d.ts +13 -0
- package/dist/orchestrator-system-prompt.d.ts +26 -0
- package/dist/orchestrator-system-prompt.js +118 -2
- package/dist/orchestrator-system-prompt.js.map +1 -1
- package/dist/pi-context.d.ts +50 -0
- package/dist/pi-context.js.map +1 -1
- package/dist/ports/device.d.ts +18 -0
- package/dist/resources/augmenter.d.ts +48 -0
- package/dist/resources/augmenter.js +126 -0
- package/dist/resources/augmenter.js.map +1 -0
- package/dist/resources/cache.d.ts +57 -0
- package/dist/resources/cache.js +107 -0
- package/dist/resources/cache.js.map +1 -0
- package/dist/resources/index.d.ts +17 -0
- package/dist/resources/index.js +15 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/lifecycle/disk-pressure.d.ts +75 -0
- package/dist/resources/lifecycle/disk-pressure.js +148 -0
- package/dist/resources/lifecycle/disk-pressure.js.map +1 -0
- package/dist/resources/lifecycle/index.d.ts +7 -0
- package/dist/resources/lifecycle/index.js +7 -0
- package/dist/resources/lifecycle/index.js.map +1 -0
- package/dist/resources/lifecycle/manager.d.ts +38 -0
- package/dist/resources/lifecycle/manager.js +205 -0
- package/dist/resources/lifecycle/manager.js.map +1 -0
- package/dist/resources/lifecycle/sweeper.d.ts +36 -0
- package/dist/resources/lifecycle/sweeper.js +179 -0
- package/dist/resources/lifecycle/sweeper.js.map +1 -0
- package/dist/resources/lifecycle/types.d.ts +180 -0
- package/dist/resources/lifecycle/types.js +46 -0
- package/dist/resources/lifecycle/types.js.map +1 -0
- package/dist/resources/parsers.d.ts +28 -0
- package/dist/resources/parsers.js +88 -0
- package/dist/resources/parsers.js.map +1 -0
- package/dist/resources/registry.d.ts +47 -0
- package/dist/resources/registry.js +107 -0
- package/dist/resources/registry.js.map +1 -0
- package/dist/resources/resolvers/beeos-file-resolver.d.ts +62 -0
- package/dist/resources/resolvers/beeos-file-resolver.js +109 -0
- package/dist/resources/resolvers/beeos-file-resolver.js.map +1 -0
- package/dist/resources/resolvers/errors.d.ts +11 -0
- package/dist/resources/resolvers/errors.js +23 -0
- package/dist/resources/resolvers/errors.js.map +1 -0
- package/dist/resources/resolvers/mime-table.d.ts +41 -0
- package/dist/resources/resolvers/mime-table.js +92 -0
- package/dist/resources/resolvers/mime-table.js.map +1 -0
- package/dist/resources/resolvers/url-resolver.d.ts +85 -0
- package/dist/resources/resolvers/url-resolver.js +495 -0
- package/dist/resources/resolvers/url-resolver.js.map +1 -0
- package/dist/resources/shortcut-facade.d.ts +51 -0
- package/dist/resources/shortcut-facade.js +72 -0
- package/dist/resources/shortcut-facade.js.map +1 -0
- package/dist/resources/telemetry.d.ts +52 -0
- package/dist/resources/telemetry.js +59 -0
- package/dist/resources/telemetry.js.map +1 -0
- package/dist/resources/types.d.ts +249 -0
- package/dist/resources/types.js +29 -0
- package/dist/resources/types.js.map +1 -0
- package/dist/shortcuts/builtins/download-to-device.d.ts +83 -0
- package/dist/shortcuts/builtins/download-to-device.js +125 -0
- package/dist/shortcuts/builtins/download-to-device.js.map +1 -0
- package/dist/shortcuts/builtins/find-app-package.d.ts +79 -0
- package/dist/shortcuts/builtins/find-app-package.js +168 -0
- package/dist/shortcuts/builtins/find-app-package.js.map +1 -0
- package/dist/shortcuts/builtins/index.d.ts +32 -0
- package/dist/shortcuts/builtins/index.js +37 -0
- package/dist/shortcuts/builtins/index.js.map +1 -0
- package/dist/shortcuts/builtins/open-deeplink.d.ts +68 -0
- package/dist/shortcuts/builtins/open-deeplink.js +142 -0
- package/dist/shortcuts/builtins/open-deeplink.js.map +1 -0
- package/dist/shortcuts/builtins/set-clipboard.d.ts +65 -0
- package/dist/shortcuts/builtins/set-clipboard.js +112 -0
- package/dist/shortcuts/builtins/set-clipboard.js.map +1 -0
- package/dist/shortcuts/index.d.ts +11 -0
- package/dist/shortcuts/index.js +11 -0
- package/dist/shortcuts/index.js.map +1 -0
- package/dist/shortcuts/registry.d.ts +56 -0
- package/dist/shortcuts/registry.js +70 -0
- package/dist/shortcuts/registry.js.map +1 -0
- package/dist/shortcuts/router.d.ts +91 -0
- package/dist/shortcuts/router.js +158 -0
- package/dist/shortcuts/router.js.map +1 -0
- package/dist/shortcuts/types.d.ts +219 -0
- package/dist/shortcuts/types.js +46 -0
- package/dist/shortcuts/types.js.map +1 -0
- package/package.json +3 -3
- package/dist/agent-runtime/skills/sqlite-store.d.ts +0 -60
- package/dist/agent-runtime/skills/sqlite-store.js +0 -234
- package/dist/agent-runtime/skills/sqlite-store.js.map +0 -1
- package/dist/test-lan-autoglm.d.ts +0 -7
- package/dist/test-lan-autoglm.js +0 -46
- package/dist/test-lan-autoglm.js.map +0 -1
- package/dist/test-mem-breakdown.d.ts +0 -1
- package/dist/test-mem-breakdown.js +0 -103
- package/dist/test-mem-breakdown.js.map +0 -1
- package/dist/test-mem.d.ts +0 -1
- package/dist/test-mem.js +0 -60
- package/dist/test-mem.js.map +0 -1
- package/dist/test-mobile-use.d.ts +0 -1
- package/dist/test-mobile-use.js +0 -18
- package/dist/test-mobile-use.js.map +0 -1
- package/dist/test-screenshot-loop.d.ts +0 -1
- package/dist/test-screenshot-loop.js +0 -43
- package/dist/test-screenshot-loop.js.map +0 -1
- package/dist/test-screenshot.d.ts +0 -1
- package/dist/test-screenshot.js +0 -10
- package/dist/test-screenshot.js.map +0 -1
- package/dist/test-ui-xml-dump.d.ts +0 -15
- package/dist/test-ui-xml-dump.js +0 -49
- 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":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AA+BtD,MAAM,OAAO,0BAA0B;IACpB,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IACvC,MAAM,CAAkB;IACzC;;;;OAIG;IACK,QAAQ,GAAkB,IAAI,CAAC;IAEvC,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,UAAU,CAAC,MAAc,EAAE,KAAoB;QAC7C,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO;QAC9C,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACjE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,4DAA4D;QAC5D,iEAAiE;QACjE,kEAAkE;QAClE,+DAA+D;QAC/D,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,uBAAuB,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAc;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,yDAAyD;YACzD,qDAAqD;YACrD,8DAA8D;YAC9D,eAAe;YACf,IAAI,KAAK,CAAC,IAAI;gBAAE,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO;QACT,CAAC;QACD,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAEnB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,6DAA6D;YAC7D,sDAAsD;YACtD,sCAAsC;YACtC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAEvE,+DAA+D;QAC/D,8DAA8D;QAC9D,gEAAgE;QAChE,gCAAgC;QAChC,IAAI,WAAW,GAAyB,IAAI,CAAC;QAC7C,MAAM,IAAI,GAAG,GAAkB,EAAE;YAC/B,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;oBAC5D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC5B,CAAC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,WAAW,CAAC;QACrB,CAAC,CAAC;QACF,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAElB,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,8CAA8C;YAC9C,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,4DAA4D;QAC5D,gEAAgE;QAChE,8DAA8D;QAC9D,iCAAiC;QACjC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,KAAK,IAAI,EAAE,CAAC;QACd,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,CAAC;QACpB,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC5C,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;YAC1B,CAAC;YACD,IAAI,KAAK,CAAC,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,2EAA2E;IAEnE,KAAK,CAAC,cAAc;QAC1B,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAChD,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;QACxE,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,KAAe,EAAE,SAAmB;QAC5D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,4DAA4D;YAC5D,2DAA2D;YAC3D,gCAAgC;YAChC,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,IAAI,GAAgB,CAAC;QACrB,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAClC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,EAC5B,uEAAuE,CACxE,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;YAC7C,8DAA8D;YAC9D,iDAAiD;YACjD,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,qEAAqE;QACrE,iEAAiE;QACjE,4DAA4D;QAC5D,gEAAgE;QAChE,4BAA4B;QAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;QAC9E,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,EAC5B,wCAAwC,CACzC,CAAC;QACJ,CAAC;QAED,8DAA8D;QAC9D,kEAAkE;QAClE,6CAA6C;QAC7C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,GAAG,CAAC,cAAc,CACtB,2EAA2E,CAAC,EAAE,CAC/E,CAAC;YACJ,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CACnB,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,EAC9B,mDAAmD,CACpD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,kEAAkE;QAClE,4DAA4D;QAC5D,mCAAmC;QACnC,KAAK,MAAM,CAAC,IAAI,SAAS;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QAE5D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAC9B,sCAAsC,CACvC,CAAC;IACJ,CAAC;CACF;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AACzC,CAAC;AAED,SAAS,SAAS,CAAC,CAAU;IAC3B,IAAI,CAAC,YAAY,KAAK;QAAE,OAAO,CAAC,CAAC,OAAO,CAAC;IACzC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -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
|
+
}
|