@withbuddi/buddi 0.1.0-pre.22 → 0.1.0-pre.24
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/README.md +10 -7
- package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/cli/dist/commands.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/commands.js +30 -1
- package/node_modules/@buddi/cli/dist/commands.js.map +1 -1
- package/node_modules/@buddi/cli/dist/doctor-probes.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/doctor-probes.js +1 -0
- package/node_modules/@buddi/cli/dist/doctor-probes.js.map +1 -1
- package/node_modules/@buddi/cli/dist/doctor.d.ts +2 -0
- package/node_modules/@buddi/cli/dist/doctor.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/doctor.js +7 -0
- package/node_modules/@buddi/cli/dist/doctor.js.map +1 -1
- package/node_modules/@buddi/cli/dist/main.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/main.js +2 -1
- package/node_modules/@buddi/cli/dist/main.js.map +1 -1
- package/node_modules/@buddi/cli/dist/plugins-toggle.d.ts +9 -0
- package/node_modules/@buddi/cli/dist/plugins-toggle.d.ts.map +1 -0
- package/node_modules/@buddi/cli/dist/plugins-toggle.js +20 -0
- package/node_modules/@buddi/cli/dist/plugins-toggle.js.map +1 -0
- package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/core/dist/agents/catalog.d.ts +37 -2
- package/node_modules/@buddi/core/dist/agents/catalog.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/agents/catalog.js +49 -11
- package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
- package/node_modules/@buddi/core/dist/home.d.ts +30 -1
- package/node_modules/@buddi/core/dist/home.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/home.js +1 -1
- package/node_modules/@buddi/core/dist/home.js.map +1 -1
- package/node_modules/@buddi/core/dist/host/build.d.ts +7 -0
- package/node_modules/@buddi/core/dist/host/build.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/host/build.js +51 -4
- package/node_modules/@buddi/core/dist/host/build.js.map +1 -1
- package/node_modules/@buddi/core/dist/host/http.d.ts +32 -0
- package/node_modules/@buddi/core/dist/host/http.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/host/http.js +102 -2
- package/node_modules/@buddi/core/dist/host/http.js.map +1 -1
- package/node_modules/@buddi/core/dist/host/types.d.ts +8 -0
- package/node_modules/@buddi/core/dist/host/types.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/index.d.ts +1 -0
- package/node_modules/@buddi/core/dist/index.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/index.js +1 -0
- package/node_modules/@buddi/core/dist/index.js.map +1 -1
- package/node_modules/@buddi/core/dist/learning/announce.d.ts +1 -1
- package/node_modules/@buddi/core/dist/notifications/focus.d.ts +42 -0
- package/node_modules/@buddi/core/dist/notifications/focus.d.ts.map +1 -0
- package/node_modules/@buddi/core/dist/notifications/focus.js +150 -0
- package/node_modules/@buddi/core/dist/notifications/focus.js.map +1 -0
- package/node_modules/@buddi/core/dist/notifications/index.d.ts +1 -0
- package/node_modules/@buddi/core/dist/notifications/index.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/index.js +1 -0
- package/node_modules/@buddi/core/dist/notifications/index.js.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/notify.d.ts +66 -7
- package/node_modules/@buddi/core/dist/notifications/notify.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/notify.js +123 -38
- package/node_modules/@buddi/core/dist/notifications/notify.js.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/store.d.ts +6 -4
- package/node_modules/@buddi/core/dist/notifications/store.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/store.js +24 -23
- package/node_modules/@buddi/core/dist/notifications/store.js.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/types.d.ts +46 -3
- package/node_modules/@buddi/core/dist/notifications/types.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/notifications/types.js +12 -0
- package/node_modules/@buddi/core/dist/notifications/types.js.map +1 -1
- package/node_modules/@buddi/core/dist/pages.d.ts +186 -6
- package/node_modules/@buddi/core/dist/pages.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/pages.js +232 -13
- package/node_modules/@buddi/core/dist/pages.js.map +1 -1
- package/node_modules/@buddi/core/dist/plugin/author.d.ts +42 -0
- package/node_modules/@buddi/core/dist/plugin/author.d.ts.map +1 -0
- package/node_modules/@buddi/core/dist/plugin/author.js +77 -0
- package/node_modules/@buddi/core/dist/plugin/author.js.map +1 -0
- package/node_modules/@buddi/core/dist/plugin/index.d.ts +7 -3
- package/node_modules/@buddi/core/dist/plugin/index.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/plugin/index.js +3 -0
- package/node_modules/@buddi/core/dist/plugin/index.js.map +1 -1
- package/node_modules/@buddi/core/dist/plugin/version.d.ts +1 -1
- package/node_modules/@buddi/core/dist/plugin/version.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/plugin/version.js +1 -1
- package/node_modules/@buddi/core/dist/plugin/version.js.map +1 -1
- package/node_modules/@buddi/core/dist/plugins/record.d.ts +8 -0
- package/node_modules/@buddi/core/dist/plugins/record.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/plugins/record.js +17 -0
- package/node_modules/@buddi/core/dist/plugins/record.js.map +1 -1
- package/node_modules/@buddi/core/dist/plugins/types.d.ts +7 -0
- package/node_modules/@buddi/core/dist/plugins/types.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/plugins/types.js.map +1 -1
- package/node_modules/@buddi/core/dist/registry.d.ts +11 -0
- package/node_modules/@buddi/core/dist/registry.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/registry.js +47 -6
- package/node_modules/@buddi/core/dist/registry.js.map +1 -1
- package/node_modules/@buddi/core/dist/scheduler/materialize.js +1 -1
- package/node_modules/@buddi/core/dist/scheduler/missions.d.ts +10 -0
- package/node_modules/@buddi/core/dist/scheduler/missions.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/scheduler/missions.js +29 -1
- package/node_modules/@buddi/core/dist/scheduler/missions.js.map +1 -1
- package/node_modules/@buddi/core/dist/scheduler/types.d.ts +7 -0
- package/node_modules/@buddi/core/dist/scheduler/types.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/scheduler/types.js +1 -0
- package/node_modules/@buddi/core/dist/scheduler/types.js.map +1 -1
- package/node_modules/@buddi/core/dist/secrets/destinations.d.ts +2 -0
- package/node_modules/@buddi/core/dist/secrets/destinations.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/secrets/destinations.js +6 -0
- package/node_modules/@buddi/core/dist/secrets/destinations.js.map +1 -1
- package/node_modules/@buddi/core/dist/tools.d.ts +8 -0
- package/node_modules/@buddi/core/dist/tools.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/tools.js.map +1 -1
- package/node_modules/@buddi/core/dist/views.d.ts +178 -3
- package/node_modules/@buddi/core/dist/views.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/views.js +56 -1
- package/node_modules/@buddi/core/dist/views.js.map +1 -1
- package/node_modules/@buddi/core/migrations/051_notification_focus.sql +20 -0
- package/node_modules/@buddi/core/migrations/052_mission_paused_reason.sql +6 -0
- package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalog.d.ts +7 -0
- package/node_modules/@buddi/gateway/dist/agents/catalog.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalog.js +18 -1
- package/node_modules/@buddi/gateway/dist/agents/catalog.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/starter-team.d.ts +2 -0
- package/node_modules/@buddi/gateway/dist/agents/starter-team.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/starter-team.js +8 -3
- package/node_modules/@buddi/gateway/dist/agents/starter-team.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/index.d.ts +1 -1
- package/node_modules/@buddi/gateway/dist/index.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/index.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions-cli.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions-cli.js +6 -3
- package/node_modules/@buddi/gateway/dist/missions-cli.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/approve.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/approve.js +9 -2
- package/node_modules/@buddi/gateway/dist/plugins/approve.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/index.d.ts +1 -0
- package/node_modules/@buddi/gateway/dist/plugins/index.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/index.js +1 -0
- package/node_modules/@buddi/gateway/dist/plugins/index.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/live.d.ts +42 -0
- package/node_modules/@buddi/gateway/dist/plugins/live.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/plugins/live.js +81 -0
- package/node_modules/@buddi/gateway/dist/plugins/live.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/plugins/load.d.ts +5 -0
- package/node_modules/@buddi/gateway/dist/plugins/load.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/load.js +10 -1
- package/node_modules/@buddi/gateway/dist/plugins/load.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/provenance.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/provenance.js +10 -3
- package/node_modules/@buddi/gateway/dist/plugins/provenance.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/scaffold.d.ts +8 -0
- package/node_modules/@buddi/gateway/dist/plugins/scaffold.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/scaffold.js +46 -7
- package/node_modules/@buddi/gateway/dist/plugins/scaffold.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts +6 -1
- package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/stage.js +3 -1
- package/node_modules/@buddi/gateway/dist/plugins/stage.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/toggle.d.ts +37 -0
- package/node_modules/@buddi/gateway/dist/plugins/toggle.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/plugins/toggle.js +110 -0
- package/node_modules/@buddi/gateway/dist/plugins/toggle.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/plugins-cli.d.ts +61 -6
- package/node_modules/@buddi/gateway/dist/plugins-cli.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins-cli.js +247 -20
- package/node_modules/@buddi/gateway/dist/plugins-cli.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/serve.js +3 -3
- package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/speech-cli.d.ts +13 -0
- package/node_modules/@buddi/gateway/dist/speech-cli.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/speech-cli.js +40 -1
- package/node_modules/@buddi/gateway/dist/speech-cli.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/focus.d.ts +27 -0
- package/node_modules/@buddi/gateway/dist/telegram/focus.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/telegram/focus.js +72 -0
- package/node_modules/@buddi/gateway/dist/telegram/focus.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/telegram/main.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/main.js +1 -0
- package/node_modules/@buddi/gateway/dist/telegram/main.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts +2 -0
- package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/surface.js +24 -1
- package/node_modules/@buddi/gateway/dist/telegram/surface.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/tips/rules.d.ts +2 -0
- package/node_modules/@buddi/gateway/dist/tips/rules.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/tips/rules.js +10 -0
- package/node_modules/@buddi/gateway/dist/tips/rules.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/agent-offers.js +1 -1
- package/node_modules/@buddi/gateway/dist/web/agent-offers.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/folders.d.ts +23 -0
- package/node_modules/@buddi/gateway/dist/web/folders.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/folders.js +100 -0
- package/node_modules/@buddi/gateway/dist/web/folders.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/market.d.ts +111 -0
- package/node_modules/@buddi/gateway/dist/web/market.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/market.js +347 -0
- package/node_modules/@buddi/gateway/dist/web/market.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/notifications.d.ts +8 -1
- package/node_modules/@buddi/gateway/dist/web/notifications.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/notifications.js +23 -1
- package/node_modules/@buddi/gateway/dist/web/notifications.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/plugins.d.ts +38 -3
- package/node_modules/@buddi/gateway/dist/web/plugins.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/plugins.js +73 -5
- package/node_modules/@buddi/gateway/dist/web/plugins.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/profile.d.ts +2 -0
- package/node_modules/@buddi/gateway/dist/web/profile.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/profile.js +2 -1
- package/node_modules/@buddi/gateway/dist/web/profile.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/rail.d.ts +33 -0
- package/node_modules/@buddi/gateway/dist/web/rail.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/rail.js +45 -0
- package/node_modules/@buddi/gateway/dist/web/rail.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/read.d.ts +46 -0
- package/node_modules/@buddi/gateway/dist/web/read.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/read.js +78 -2
- package/node_modules/@buddi/gateway/dist/web/read.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/server.js +68 -6
- package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/svg.d.ts +23 -0
- package/node_modules/@buddi/gateway/dist/web/svg.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/svg.js +125 -0
- package/node_modules/@buddi/gateway/dist/web/svg.js.map +1 -0
- package/node_modules/@buddi/gateway/src/agents/starter/planner/agent.md +2 -2
- package/node_modules/@buddi/gateway/src/agents/starter/planner/skills/writing-the-morning-brief.md +18 -11
- package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-mcp/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-memory/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-web/dist/.tsbuildinfo +1 -1
- package/node_modules/@hono/node-server/README.md +21 -10
- package/node_modules/@hono/node-server/dist/early-hints.cjs +1 -1
- package/node_modules/@hono/node-server/dist/early-hints.mjs +1 -1
- package/node_modules/@hono/node-server/dist/index.cjs +41 -19
- package/node_modules/@hono/node-server/dist/index.mjs +42 -20
- package/node_modules/@hono/node-server/dist/serve-static.cjs +1 -0
- package/node_modules/@hono/node-server/dist/serve-static.d.cts +2 -1
- package/node_modules/@hono/node-server/dist/serve-static.d.mts +2 -1
- package/node_modules/@hono/node-server/dist/serve-static.mjs +1 -0
- package/node_modules/@hono/node-server/package.json +3 -2
- package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/language/language.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/serve-static/index.js +1 -0
- package/node_modules/hono/dist/middleware/language/language.js +1 -1
- package/node_modules/hono/dist/middleware/serve-static/index.js +1 -0
- package/node_modules/hono/dist/types/middleware/serve-static/index.d.ts +2 -0
- package/node_modules/hono/package.json +1 -1
- package/package.json +2 -2
- package/packages/cli/dist/.tsbuildinfo +1 -1
- package/packages/cli/dist/commands.d.ts.map +1 -1
- package/packages/cli/dist/commands.js +30 -1
- package/packages/cli/dist/commands.js.map +1 -1
- package/packages/cli/dist/doctor-probes.d.ts.map +1 -1
- package/packages/cli/dist/doctor-probes.js +1 -0
- package/packages/cli/dist/doctor-probes.js.map +1 -1
- package/packages/cli/dist/doctor.d.ts +2 -0
- package/packages/cli/dist/doctor.d.ts.map +1 -1
- package/packages/cli/dist/doctor.js +7 -0
- package/packages/cli/dist/doctor.js.map +1 -1
- package/packages/cli/dist/main.d.ts.map +1 -1
- package/packages/cli/dist/main.js +2 -1
- package/packages/cli/dist/main.js.map +1 -1
- package/packages/cli/dist/plugins-toggle.d.ts +9 -0
- package/packages/cli/dist/plugins-toggle.d.ts.map +1 -0
- package/packages/cli/dist/plugins-toggle.js +20 -0
- package/packages/cli/dist/plugins-toggle.js.map +1 -0
- package/packages/core/dist/.tsbuildinfo +1 -1
- package/packages/core/dist/agents/catalog.d.ts +37 -2
- package/packages/core/dist/agents/catalog.d.ts.map +1 -1
- package/packages/core/dist/agents/catalog.js +49 -11
- package/packages/core/dist/agents/catalog.js.map +1 -1
- package/packages/core/dist/home.d.ts +30 -1
- package/packages/core/dist/home.d.ts.map +1 -1
- package/packages/core/dist/home.js +1 -1
- package/packages/core/dist/home.js.map +1 -1
- package/packages/core/dist/host/build.d.ts +7 -0
- package/packages/core/dist/host/build.d.ts.map +1 -1
- package/packages/core/dist/host/build.js +51 -4
- package/packages/core/dist/host/build.js.map +1 -1
- package/packages/core/dist/host/http.d.ts +32 -0
- package/packages/core/dist/host/http.d.ts.map +1 -1
- package/packages/core/dist/host/http.js +102 -2
- package/packages/core/dist/host/http.js.map +1 -1
- package/packages/core/dist/host/types.d.ts +8 -0
- package/packages/core/dist/host/types.d.ts.map +1 -1
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +1 -0
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/learning/announce.d.ts +1 -1
- package/packages/core/dist/notifications/focus.d.ts +42 -0
- package/packages/core/dist/notifications/focus.d.ts.map +1 -0
- package/packages/core/dist/notifications/focus.js +150 -0
- package/packages/core/dist/notifications/focus.js.map +1 -0
- package/packages/core/dist/notifications/index.d.ts +1 -0
- package/packages/core/dist/notifications/index.d.ts.map +1 -1
- package/packages/core/dist/notifications/index.js +1 -0
- package/packages/core/dist/notifications/index.js.map +1 -1
- package/packages/core/dist/notifications/notify.d.ts +66 -7
- package/packages/core/dist/notifications/notify.d.ts.map +1 -1
- package/packages/core/dist/notifications/notify.js +123 -38
- package/packages/core/dist/notifications/notify.js.map +1 -1
- package/packages/core/dist/notifications/store.d.ts +6 -4
- package/packages/core/dist/notifications/store.d.ts.map +1 -1
- package/packages/core/dist/notifications/store.js +24 -23
- package/packages/core/dist/notifications/store.js.map +1 -1
- package/packages/core/dist/notifications/types.d.ts +46 -3
- package/packages/core/dist/notifications/types.d.ts.map +1 -1
- package/packages/core/dist/notifications/types.js +12 -0
- package/packages/core/dist/notifications/types.js.map +1 -1
- package/packages/core/dist/pages.d.ts +186 -6
- package/packages/core/dist/pages.d.ts.map +1 -1
- package/packages/core/dist/pages.js +232 -13
- package/packages/core/dist/pages.js.map +1 -1
- package/packages/core/dist/plugin/author.d.ts +42 -0
- package/packages/core/dist/plugin/author.d.ts.map +1 -0
- package/packages/core/dist/plugin/author.js +77 -0
- package/packages/core/dist/plugin/author.js.map +1 -0
- package/packages/core/dist/plugin/index.d.ts +7 -3
- package/packages/core/dist/plugin/index.d.ts.map +1 -1
- package/packages/core/dist/plugin/index.js +3 -0
- package/packages/core/dist/plugin/index.js.map +1 -1
- package/packages/core/dist/plugin/version.d.ts +1 -1
- package/packages/core/dist/plugin/version.d.ts.map +1 -1
- package/packages/core/dist/plugin/version.js +1 -1
- package/packages/core/dist/plugin/version.js.map +1 -1
- package/packages/core/dist/plugins/record.d.ts +8 -0
- package/packages/core/dist/plugins/record.d.ts.map +1 -1
- package/packages/core/dist/plugins/record.js +17 -0
- package/packages/core/dist/plugins/record.js.map +1 -1
- package/packages/core/dist/plugins/types.d.ts +7 -0
- package/packages/core/dist/plugins/types.d.ts.map +1 -1
- package/packages/core/dist/plugins/types.js.map +1 -1
- package/packages/core/dist/registry.d.ts +11 -0
- package/packages/core/dist/registry.d.ts.map +1 -1
- package/packages/core/dist/registry.js +47 -6
- package/packages/core/dist/registry.js.map +1 -1
- package/packages/core/dist/scheduler/materialize.js +1 -1
- package/packages/core/dist/scheduler/missions.d.ts +10 -0
- package/packages/core/dist/scheduler/missions.d.ts.map +1 -1
- package/packages/core/dist/scheduler/missions.js +29 -1
- package/packages/core/dist/scheduler/missions.js.map +1 -1
- package/packages/core/dist/scheduler/types.d.ts +7 -0
- package/packages/core/dist/scheduler/types.d.ts.map +1 -1
- package/packages/core/dist/scheduler/types.js +1 -0
- package/packages/core/dist/scheduler/types.js.map +1 -1
- package/packages/core/dist/secrets/destinations.d.ts +2 -0
- package/packages/core/dist/secrets/destinations.d.ts.map +1 -1
- package/packages/core/dist/secrets/destinations.js +6 -0
- package/packages/core/dist/secrets/destinations.js.map +1 -1
- package/packages/core/dist/tools.d.ts +8 -0
- package/packages/core/dist/tools.d.ts.map +1 -1
- package/packages/core/dist/tools.js.map +1 -1
- package/packages/core/dist/views.d.ts +178 -3
- package/packages/core/dist/views.d.ts.map +1 -1
- package/packages/core/dist/views.js +56 -1
- package/packages/core/dist/views.js.map +1 -1
- package/packages/core/migrations/051_notification_focus.sql +20 -0
- package/packages/core/migrations/052_mission_paused_reason.sql +6 -0
- package/packages/gateway/dist/.tsbuildinfo +1 -1
- package/packages/gateway/dist/agents/catalog.d.ts +7 -0
- package/packages/gateway/dist/agents/catalog.d.ts.map +1 -1
- package/packages/gateway/dist/agents/catalog.js +18 -1
- package/packages/gateway/dist/agents/catalog.js.map +1 -1
- package/packages/gateway/dist/agents/starter-team.d.ts +2 -0
- package/packages/gateway/dist/agents/starter-team.d.ts.map +1 -1
- package/packages/gateway/dist/agents/starter-team.js +8 -3
- package/packages/gateway/dist/agents/starter-team.js.map +1 -1
- package/packages/gateway/dist/index.d.ts +1 -1
- package/packages/gateway/dist/index.d.ts.map +1 -1
- package/packages/gateway/dist/index.js.map +1 -1
- package/packages/gateway/dist/missions-cli.d.ts.map +1 -1
- package/packages/gateway/dist/missions-cli.js +6 -3
- package/packages/gateway/dist/missions-cli.js.map +1 -1
- package/packages/gateway/dist/plugins/approve.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/approve.js +9 -2
- package/packages/gateway/dist/plugins/approve.js.map +1 -1
- package/packages/gateway/dist/plugins/index.d.ts +1 -0
- package/packages/gateway/dist/plugins/index.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/index.js +1 -0
- package/packages/gateway/dist/plugins/index.js.map +1 -1
- package/packages/gateway/dist/plugins/live.d.ts +42 -0
- package/packages/gateway/dist/plugins/live.d.ts.map +1 -0
- package/packages/gateway/dist/plugins/live.js +81 -0
- package/packages/gateway/dist/plugins/live.js.map +1 -0
- package/packages/gateway/dist/plugins/load.d.ts +5 -0
- package/packages/gateway/dist/plugins/load.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/load.js +10 -1
- package/packages/gateway/dist/plugins/load.js.map +1 -1
- package/packages/gateway/dist/plugins/provenance.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/provenance.js +10 -3
- package/packages/gateway/dist/plugins/provenance.js.map +1 -1
- package/packages/gateway/dist/plugins/scaffold.d.ts +8 -0
- package/packages/gateway/dist/plugins/scaffold.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/scaffold.js +46 -7
- package/packages/gateway/dist/plugins/scaffold.js.map +1 -1
- package/packages/gateway/dist/plugins/stage.d.ts +6 -1
- package/packages/gateway/dist/plugins/stage.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/stage.js +3 -1
- package/packages/gateway/dist/plugins/stage.js.map +1 -1
- package/packages/gateway/dist/plugins/toggle.d.ts +37 -0
- package/packages/gateway/dist/plugins/toggle.d.ts.map +1 -0
- package/packages/gateway/dist/plugins/toggle.js +110 -0
- package/packages/gateway/dist/plugins/toggle.js.map +1 -0
- package/packages/gateway/dist/plugins-cli.d.ts +61 -6
- package/packages/gateway/dist/plugins-cli.d.ts.map +1 -1
- package/packages/gateway/dist/plugins-cli.js +247 -20
- package/packages/gateway/dist/plugins-cli.js.map +1 -1
- package/packages/gateway/dist/serve.js +3 -3
- package/packages/gateway/dist/serve.js.map +1 -1
- package/packages/gateway/dist/speech-cli.d.ts +13 -0
- package/packages/gateway/dist/speech-cli.d.ts.map +1 -1
- package/packages/gateway/dist/speech-cli.js +40 -1
- package/packages/gateway/dist/speech-cli.js.map +1 -1
- package/packages/gateway/dist/telegram/focus.d.ts +27 -0
- package/packages/gateway/dist/telegram/focus.d.ts.map +1 -0
- package/packages/gateway/dist/telegram/focus.js +72 -0
- package/packages/gateway/dist/telegram/focus.js.map +1 -0
- package/packages/gateway/dist/telegram/main.d.ts.map +1 -1
- package/packages/gateway/dist/telegram/main.js +1 -0
- package/packages/gateway/dist/telegram/main.js.map +1 -1
- package/packages/gateway/dist/telegram/surface.d.ts +2 -0
- package/packages/gateway/dist/telegram/surface.d.ts.map +1 -1
- package/packages/gateway/dist/telegram/surface.js +24 -1
- package/packages/gateway/dist/telegram/surface.js.map +1 -1
- package/packages/gateway/dist/tips/rules.d.ts +2 -0
- package/packages/gateway/dist/tips/rules.d.ts.map +1 -1
- package/packages/gateway/dist/tips/rules.js +10 -0
- package/packages/gateway/dist/tips/rules.js.map +1 -1
- package/packages/gateway/dist/web/agent-offers.js +1 -1
- package/packages/gateway/dist/web/agent-offers.js.map +1 -1
- package/packages/gateway/dist/web/folders.d.ts +23 -0
- package/packages/gateway/dist/web/folders.d.ts.map +1 -0
- package/packages/gateway/dist/web/folders.js +100 -0
- package/packages/gateway/dist/web/folders.js.map +1 -0
- package/packages/gateway/dist/web/market.d.ts +111 -0
- package/packages/gateway/dist/web/market.d.ts.map +1 -0
- package/packages/gateway/dist/web/market.js +347 -0
- package/packages/gateway/dist/web/market.js.map +1 -0
- package/packages/gateway/dist/web/notifications.d.ts +8 -1
- package/packages/gateway/dist/web/notifications.d.ts.map +1 -1
- package/packages/gateway/dist/web/notifications.js +23 -1
- package/packages/gateway/dist/web/notifications.js.map +1 -1
- package/packages/gateway/dist/web/plugins.d.ts +38 -3
- package/packages/gateway/dist/web/plugins.d.ts.map +1 -1
- package/packages/gateway/dist/web/plugins.js +73 -5
- package/packages/gateway/dist/web/plugins.js.map +1 -1
- package/packages/gateway/dist/web/profile.d.ts +2 -0
- package/packages/gateway/dist/web/profile.d.ts.map +1 -1
- package/packages/gateway/dist/web/profile.js +2 -1
- package/packages/gateway/dist/web/profile.js.map +1 -1
- package/packages/gateway/dist/web/rail.d.ts +33 -0
- package/packages/gateway/dist/web/rail.d.ts.map +1 -0
- package/packages/gateway/dist/web/rail.js +45 -0
- package/packages/gateway/dist/web/rail.js.map +1 -0
- package/packages/gateway/dist/web/read.d.ts +46 -0
- package/packages/gateway/dist/web/read.d.ts.map +1 -1
- package/packages/gateway/dist/web/read.js +78 -2
- package/packages/gateway/dist/web/read.js.map +1 -1
- package/packages/gateway/dist/web/server.d.ts.map +1 -1
- package/packages/gateway/dist/web/server.js +68 -6
- package/packages/gateway/dist/web/server.js.map +1 -1
- package/packages/gateway/dist/web/svg.d.ts +23 -0
- package/packages/gateway/dist/web/svg.d.ts.map +1 -0
- package/packages/gateway/dist/web/svg.js +125 -0
- package/packages/gateway/dist/web/svg.js.map +1 -0
- package/packages/gateway/src/agents/starter/planner/agent.md +2 -2
- package/packages/gateway/src/agents/starter/planner/skills/writing-the-morning-brief.md +18 -11
- package/packages/install/dist/.tsbuildinfo +1 -1
- package/packages/runtime/dist/.tsbuildinfo +1 -1
- package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
- package/packages/tools/browser/dist/.tsbuildinfo +1 -1
- package/packages/tools/email/dist/.tsbuildinfo +1 -1
- package/packages/tools/host/dist/.tsbuildinfo +1 -1
- package/packages/tools/mcp/dist/.tsbuildinfo +1 -1
- package/packages/tools/memory/dist/.tsbuildinfo +1 -1
- package/packages/tools/web/dist/.tsbuildinfo +1 -1
- package/packages/web/dist/assets/index-C-NAQ_MT.css +1 -0
- package/packages/web/dist/assets/index-DzFS39N3.js +125 -0
- package/packages/web/dist/assets/{lottie_light-BCNsQpt8.js → lottie_light-D7STH9tF.js} +1 -1
- package/packages/web/dist/build.json +1 -1
- package/packages/web/dist/index.html +2 -2
- package/packages/web/dist/precache.json +4 -4
- package/packages/web/dist/sw.js +8 -1
- package/packages/web/dist/assets/index-CBEdA2dN.js +0 -125
- package/packages/web/dist/assets/index-Ddp9egOQ.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders.d.ts","sourceRoot":"","sources":["../../src/web/folders.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,iEAAiE;AACjE,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,mDAAmD;IACnD,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAOrD;AAeD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,UAAU,CAkD/E"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /api/plugins/folders?path=<absolute path>` — the folders on the
|
|
3
|
+
* gateway's machine, for "A directory I built".
|
|
4
|
+
*
|
|
5
|
+
* The page cannot browse the machine buddi runs on (a browser's own folder
|
|
6
|
+
* picker gives no path, and the browser may be on a phone), so this lists one
|
|
7
|
+
* folder's subfolders by name and says which of them hold a package.json. It
|
|
8
|
+
* starts at the owner's home directory and refuses anything outside it, the
|
|
9
|
+
* way the folder the owner builds a plugin in always is. Hidden folders are
|
|
10
|
+
* left out of the list; a path that names one explicitly is still answered,
|
|
11
|
+
* because the owner typed it.
|
|
12
|
+
*
|
|
13
|
+
* Names and one existence check each: nothing is read, nothing is written,
|
|
14
|
+
* and nothing leaves the machine.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readdirSync, realpathSync, statSync } from 'node:fs';
|
|
17
|
+
import { homedir } from 'node:os';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
/** More than this in one folder and the list says it stopped. */
|
|
20
|
+
export const MAX_FOLDERS = 500;
|
|
21
|
+
/** The owner's home directory: `HOME` as the gateway was started, else the OS's. */
|
|
22
|
+
export function homeOf(env) {
|
|
23
|
+
const home = env.HOME?.trim() || homedir();
|
|
24
|
+
try {
|
|
25
|
+
return realpathSync(home);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return path.resolve(home);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function inside(root, candidate) {
|
|
32
|
+
const rel = path.relative(root, candidate);
|
|
33
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
34
|
+
}
|
|
35
|
+
function isDirectory(full) {
|
|
36
|
+
try {
|
|
37
|
+
return statSync(full).isDirectory();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function pluginFoldersRoute(env, url) {
|
|
44
|
+
const home = homeOf(env);
|
|
45
|
+
const asked = url.searchParams.get('path')?.trim() || home;
|
|
46
|
+
if (!path.isAbsolute(asked)) {
|
|
47
|
+
return { status: 400, body: { error: 'Give the whole path, starting at /.' } };
|
|
48
|
+
}
|
|
49
|
+
let real;
|
|
50
|
+
try {
|
|
51
|
+
real = realpathSync(path.resolve(asked));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return { status: 404, body: { error: `There is no folder at ${asked}.` } };
|
|
55
|
+
}
|
|
56
|
+
// Checked after links are followed: a link out of the home directory is outside it.
|
|
57
|
+
if (!inside(home, real)) {
|
|
58
|
+
return { status: 403, body: { error: 'Only folders inside your home directory are listed here.' } };
|
|
59
|
+
}
|
|
60
|
+
if (!isDirectory(real)) {
|
|
61
|
+
return { status: 400, body: { error: `${asked} is a file, not a folder.` } };
|
|
62
|
+
}
|
|
63
|
+
let names;
|
|
64
|
+
try {
|
|
65
|
+
names = readdirSync(real);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const code = err.code;
|
|
69
|
+
return {
|
|
70
|
+
status: 403,
|
|
71
|
+
body: { error: code === 'EACCES' || code === 'EPERM' ? `buddi may not read ${real}.` : `${real} could not be read.` },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const folders = [];
|
|
75
|
+
for (const name of names.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }))) {
|
|
76
|
+
if (name.startsWith('.'))
|
|
77
|
+
continue;
|
|
78
|
+
const full = path.join(real, name);
|
|
79
|
+
if (!isDirectory(full))
|
|
80
|
+
continue;
|
|
81
|
+
// A link that leads out of the home directory is not offered as a way in.
|
|
82
|
+
try {
|
|
83
|
+
if (!inside(home, realpathSync(full)))
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
folders.push({ name, path: full, plugin: existsSync(path.join(full, 'package.json')) });
|
|
90
|
+
}
|
|
91
|
+
const view = {
|
|
92
|
+
path: real,
|
|
93
|
+
parent: real === home ? null : path.dirname(real),
|
|
94
|
+
home,
|
|
95
|
+
folders: folders.slice(0, MAX_FOLDERS),
|
|
96
|
+
...(folders.length > MAX_FOLDERS ? { truncated: true } : {}),
|
|
97
|
+
};
|
|
98
|
+
return { status: 200, body: view };
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=folders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders.js","sourceRoot":"","sources":["../../src/web/folders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,iEAAiE;AACjE,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAoB/B,oFAAoF;AACpF,MAAM,UAAU,MAAM,CAAC,GAAsB;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,SAAiB;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAsB,EAAE,GAAQ;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAC3D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,qCAAqC,EAAE,EAAE,CAAC;IACjF,CAAC;IACD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,yBAAyB,KAAK,GAAG,EAAE,EAAE,CAAC;IAC7E,CAAC;IACD,oFAAoF;IACpF,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,0DAA0D,EAAE,EAAE,CAAC;IACtG,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,2BAA2B,EAAE,EAAE,CAAC;IAC/E,CAAC;IACD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,OAAO;YACL,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,sBAAsB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,qBAAqB,EAAE;SACtH,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;QAChG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,0EAA0E;QAC1E,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;gBAAE,SAAS;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QACjD,IAAI;QACJ,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;QACtC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtE,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type InstalledPlugin } from '@buddi/core';
|
|
3
|
+
import { type RouteReply } from './plugins.js';
|
|
4
|
+
export declare const MARKET_ORIGIN = "https://withbuddi.com";
|
|
5
|
+
/** How long a fetched list is trusted before Browse asks again. The pictures keep a day. */
|
|
6
|
+
export declare const MARKET_TTL_MS: number;
|
|
7
|
+
export declare const MARKET_ASSET_TTL_MS: number;
|
|
8
|
+
export declare const MARKET_TIMEOUT_MS = 10000;
|
|
9
|
+
export declare const MARKET_CATEGORIES: readonly ["days", "money", "home", "voice", "work", "other"];
|
|
10
|
+
/**
|
|
11
|
+
* One listing. Only what Browse relies on is checked; every other field the
|
|
12
|
+
* site writes is kept as it came, so a newer index still reaches the page.
|
|
13
|
+
*/
|
|
14
|
+
declare const entrySchema: z.ZodObject<{
|
|
15
|
+
name: z.ZodString;
|
|
16
|
+
npm: z.ZodString;
|
|
17
|
+
version: z.ZodString;
|
|
18
|
+
title: z.ZodString;
|
|
19
|
+
summary: z.ZodString;
|
|
20
|
+
category: z.ZodCatch<z.ZodEnum<["days", "money", "home", "voice", "work", "other"]>>;
|
|
21
|
+
trust: z.ZodEnum<["by-buddi", "reviewed"]>;
|
|
22
|
+
pricing: z.ZodCatch<z.ZodObject<{
|
|
23
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
24
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
25
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
26
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
27
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
28
|
+
}, z.ZodTypeAny, "passthrough">>>;
|
|
29
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
30
|
+
name: z.ZodString;
|
|
31
|
+
npm: z.ZodString;
|
|
32
|
+
version: z.ZodString;
|
|
33
|
+
title: z.ZodString;
|
|
34
|
+
summary: z.ZodString;
|
|
35
|
+
category: z.ZodCatch<z.ZodEnum<["days", "money", "home", "voice", "work", "other"]>>;
|
|
36
|
+
trust: z.ZodEnum<["by-buddi", "reviewed"]>;
|
|
37
|
+
pricing: z.ZodCatch<z.ZodObject<{
|
|
38
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
39
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
40
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
41
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
42
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
43
|
+
}, z.ZodTypeAny, "passthrough">>>;
|
|
44
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
45
|
+
name: z.ZodString;
|
|
46
|
+
npm: z.ZodString;
|
|
47
|
+
version: z.ZodString;
|
|
48
|
+
title: z.ZodString;
|
|
49
|
+
summary: z.ZodString;
|
|
50
|
+
category: z.ZodCatch<z.ZodEnum<["days", "money", "home", "voice", "work", "other"]>>;
|
|
51
|
+
trust: z.ZodEnum<["by-buddi", "reviewed"]>;
|
|
52
|
+
pricing: z.ZodCatch<z.ZodObject<{
|
|
53
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
54
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
55
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
56
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
57
|
+
kind: z.ZodEnum<["free", "paid", "subscription"]>;
|
|
58
|
+
}, z.ZodTypeAny, "passthrough">>>;
|
|
59
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
60
|
+
export type MarketEntry = z.infer<typeof entrySchema>;
|
|
61
|
+
export interface MarketIndex {
|
|
62
|
+
generatedAt?: string;
|
|
63
|
+
plugins: MarketEntry[];
|
|
64
|
+
}
|
|
65
|
+
export interface MarketDeps {
|
|
66
|
+
env: NodeJS.ProcessEnv;
|
|
67
|
+
log: (line: string) => void;
|
|
68
|
+
/** Injected by tests that want no socket at all; the gateway uses the global. */
|
|
69
|
+
fetch?: typeof fetch;
|
|
70
|
+
now?: () => Date;
|
|
71
|
+
}
|
|
72
|
+
/** For tests: forget the in-memory copies. */
|
|
73
|
+
export declare function resetMarketCache(): void;
|
|
74
|
+
export declare function marketFile(env: NodeJS.ProcessEnv): string;
|
|
75
|
+
export declare function marketUrl(env: NodeJS.ProcessEnv): string;
|
|
76
|
+
/** The index as buddi keeps it: shape checked, bad entries left out and said so. */
|
|
77
|
+
export declare function parseMarketIndex(value: unknown, log?: (line: string) => void): MarketIndex;
|
|
78
|
+
export declare function annotateMarket(plugins: readonly MarketEntry[], record: readonly InstalledPlugin[]): Array<Record<string, unknown>>;
|
|
79
|
+
/** Where every listing's files live; nothing outside it is fetched for the page. */
|
|
80
|
+
export declare const MARKET_ASSET_PREFIX = "https://withbuddi.com/plugins/";
|
|
81
|
+
/** A screenshot is a few hundred kilobytes; this is room and no more. */
|
|
82
|
+
export declare const MAX_ASSET_BYTES: number;
|
|
83
|
+
/** The URL, when it is a listing's file; `undefined` for anything else. */
|
|
84
|
+
export declare function marketAssetUrl(env: NodeJS.ProcessEnv, raw: string | null | undefined): URL | undefined;
|
|
85
|
+
interface Asset {
|
|
86
|
+
bytes: Buffer;
|
|
87
|
+
type: string;
|
|
88
|
+
fetchedAt: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* One listing's file: from the copy beside the index while it is under a day
|
|
92
|
+
* old, else fetched and kept. A fetch that fails with a copy on hand answers
|
|
93
|
+
* the copy; with none, it throws.
|
|
94
|
+
*/
|
|
95
|
+
export declare function marketAsset(deps: MarketDeps, url: URL): Promise<Asset>;
|
|
96
|
+
/** A reply that is a file rather than JSON. */
|
|
97
|
+
export interface AssetReply {
|
|
98
|
+
status: number;
|
|
99
|
+
body?: unknown;
|
|
100
|
+
bytes?: Buffer;
|
|
101
|
+
type?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* `GET /api/market/asset?url=<a listing's file>` — a screenshot for the
|
|
105
|
+
* detail sheet. An SVG goes out only as the sanitiser re-wrote it.
|
|
106
|
+
*/
|
|
107
|
+
export declare function marketAssetRoute(deps: MarketDeps, url: URL): Promise<AssetReply>;
|
|
108
|
+
/** `GET /api/market[?refresh=1]`. */
|
|
109
|
+
export declare function marketRoute(deps: MarketDeps, url: URL): Promise<RouteReply>;
|
|
110
|
+
export {};
|
|
111
|
+
//# sourceMappingURL=market.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"market.d.ts","sourceRoot":"","sources":["../../src/web/market.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAG3E,eAAO,MAAM,aAAa,0BAA0B,CAAC;AACrD,4FAA4F;AAC5F,eAAO,MAAM,aAAa,QAAiB,CAAC;AAC5C,eAAO,MAAM,mBAAmB,QAAsB,CAAC;AACvD,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,eAAO,MAAM,iBAAiB,8DAA+D,CAAC;AAE9F;;;GAGG;AACH,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAcD,CAAC;AASjB,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAOD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAKD,8CAA8C;AAC9C,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAEzD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAGxD;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAe,GAAG,WAAW,CAYpG;AA2DD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,MAAM,EAAE,SAAS,eAAe,EAAE,GACjC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWhC;AAMD,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,mCAA8B,CAAC;AAC/D,yEAAyE;AACzE,eAAO,MAAM,eAAe,QAAkB,CAAC;AAgB/C,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,CAatG;AAED,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AA6CD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAY5E;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAgBtF;AAgBD,qCAAqC;AACrC,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAwCjF"}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /api/market` — the plugin list from withbuddi.com, for Browse.
|
|
3
|
+
*
|
|
4
|
+
* The page never reaches the internet itself: it asks this route, and this
|
|
5
|
+
* route fetches `<origin>/plugins/index.json` only when it is asked — which is
|
|
6
|
+
* when the owner opens the Browse tab. Nothing fetches it at start or on a
|
|
7
|
+
* timer. It is one of the few things that leave the machine, and the docs list
|
|
8
|
+
* it as that: "the plugin list from withbuddi.com, when you open Browse".
|
|
9
|
+
*
|
|
10
|
+
* The answer is kept a day, in memory and on disk under the data directory, so
|
|
11
|
+
* opening Browse twice does not ask twice. A fetch that fails with a copy on
|
|
12
|
+
* hand answers the copy, marked `stale`; one that fails with nothing answers
|
|
13
|
+
* an empty list and the sentence, still with a 200, because "withbuddi.com did
|
|
14
|
+
* not answer" is something the page shows, not an error in the gateway.
|
|
15
|
+
*
|
|
16
|
+
* Each entry is annotated against the installed record: `installed` when a
|
|
17
|
+
* plugin of that npm name (or buddi name) is here, `update` when the listed
|
|
18
|
+
* version is newer, and `usesWords` in the same words the staged card uses.
|
|
19
|
+
* Nothing about installing changes: Install on the page stages the spec, and
|
|
20
|
+
* the staged card and its approvals are the ones every install goes through.
|
|
21
|
+
*
|
|
22
|
+
* The listings' pictures come through here too: `GET /api/market/asset?url=`
|
|
23
|
+
* fetches a file under `https://withbuddi.com/plugins/` (a screenshot) and
|
|
24
|
+
* keeps it beside the index, so the page never reaches the internet itself.
|
|
25
|
+
* Each listing's icon is read the same way while the list is answered and
|
|
26
|
+
* passed on as `iconSvg`, sanitised to plain shapes (`svg.ts`), so the page can
|
|
27
|
+
* draw it inline in the colour of its tile. Both happen only on the way to
|
|
28
|
+
* Browse, which is already the one time the market is asked anything.
|
|
29
|
+
*/
|
|
30
|
+
import { createHash } from 'node:crypto';
|
|
31
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
32
|
+
import path from 'node:path';
|
|
33
|
+
import { z } from 'zod';
|
|
34
|
+
import { compareVersions, resolveDataDir } from '@buddi/core';
|
|
35
|
+
import { installedRecord, usesWords } from './plugins.js';
|
|
36
|
+
import { sanitizeIconSvg } from './svg.js';
|
|
37
|
+
export const MARKET_ORIGIN = 'https://withbuddi.com';
|
|
38
|
+
/** How long a fetched list is trusted before Browse asks again. The pictures keep a day. */
|
|
39
|
+
export const MARKET_TTL_MS = 60 * 60 * 1000;
|
|
40
|
+
export const MARKET_ASSET_TTL_MS = 24 * 60 * 60 * 1000;
|
|
41
|
+
export const MARKET_TIMEOUT_MS = 10_000;
|
|
42
|
+
export const MARKET_CATEGORIES = ['days', 'money', 'home', 'voice', 'work', 'other'];
|
|
43
|
+
/**
|
|
44
|
+
* One listing. Only what Browse relies on is checked; every other field the
|
|
45
|
+
* site writes is kept as it came, so a newer index still reaches the page.
|
|
46
|
+
*/
|
|
47
|
+
const entrySchema = z
|
|
48
|
+
.object({
|
|
49
|
+
name: z.string().min(1),
|
|
50
|
+
npm: z.string().min(1),
|
|
51
|
+
version: z.string().min(1),
|
|
52
|
+
title: z.string().min(1),
|
|
53
|
+
summary: z.string(),
|
|
54
|
+
category: z.enum(MARKET_CATEGORIES).catch('other'),
|
|
55
|
+
trust: z.enum(['by-buddi', 'reviewed']),
|
|
56
|
+
pricing: z
|
|
57
|
+
.object({ kind: z.enum(['free', 'paid', 'subscription']) })
|
|
58
|
+
.passthrough()
|
|
59
|
+
.catch({ kind: 'free' }),
|
|
60
|
+
})
|
|
61
|
+
.passthrough();
|
|
62
|
+
const indexSchema = z
|
|
63
|
+
.object({
|
|
64
|
+
generatedAt: z.string().optional(),
|
|
65
|
+
plugins: z.array(z.unknown()),
|
|
66
|
+
})
|
|
67
|
+
.passthrough();
|
|
68
|
+
/** Keyed by the file on disk, so two data directories never share a copy. */
|
|
69
|
+
const memory = new Map();
|
|
70
|
+
/** For tests: forget the in-memory copies. */
|
|
71
|
+
export function resetMarketCache() {
|
|
72
|
+
memory.clear();
|
|
73
|
+
}
|
|
74
|
+
export function marketFile(env) {
|
|
75
|
+
return path.join(resolveDataDir(env), 'market', 'index.json');
|
|
76
|
+
}
|
|
77
|
+
export function marketUrl(env) {
|
|
78
|
+
const origin = env.BUDDI_MARKET_URL?.trim() || MARKET_ORIGIN;
|
|
79
|
+
return `${origin.replace(/\/+$/, '')}/plugins/index.json`;
|
|
80
|
+
}
|
|
81
|
+
/** The index as buddi keeps it: shape checked, bad entries left out and said so. */
|
|
82
|
+
export function parseMarketIndex(value, log = () => { }) {
|
|
83
|
+
const index = indexSchema.parse(value);
|
|
84
|
+
const plugins = [];
|
|
85
|
+
for (const raw of index.plugins) {
|
|
86
|
+
const parsed = entrySchema.safeParse(raw);
|
|
87
|
+
if (parsed.success)
|
|
88
|
+
plugins.push(parsed.data);
|
|
89
|
+
else {
|
|
90
|
+
const name = typeof raw?.name === 'string' ? raw.name : '?';
|
|
91
|
+
log(`market: left out the listing "${name}": ${parsed.error.issues[0]?.message ?? 'not a listing'}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { ...index, plugins };
|
|
95
|
+
}
|
|
96
|
+
function readDisk(file) {
|
|
97
|
+
try {
|
|
98
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
99
|
+
if (typeof parsed.fetchedAt !== 'string')
|
|
100
|
+
return undefined;
|
|
101
|
+
return { fetchedAt: parsed.fetchedAt, index: parseMarketIndex(parsed.index) };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function writeDisk(file, cached, log) {
|
|
108
|
+
try {
|
|
109
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
110
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
111
|
+
writeFileSync(tmp, `${JSON.stringify(cached, null, 2)}\n`);
|
|
112
|
+
renameSync(tmp, file);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
// The copy in memory still answers; a day's cache on disk is a convenience.
|
|
116
|
+
log(`market: could not keep the list on disk: ${err instanceof Error ? err.message : String(err)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function fetchIndex(deps) {
|
|
120
|
+
const doFetch = deps.fetch ?? fetch;
|
|
121
|
+
const url = marketUrl(deps.env);
|
|
122
|
+
const response = await doFetch(url, {
|
|
123
|
+
signal: AbortSignal.timeout(MARKET_TIMEOUT_MS),
|
|
124
|
+
headers: { accept: 'application/json' },
|
|
125
|
+
});
|
|
126
|
+
if (!response.ok)
|
|
127
|
+
throw new Error(`${url} answered ${response.status}`);
|
|
128
|
+
return parseMarketIndex(await response.json(), deps.log);
|
|
129
|
+
}
|
|
130
|
+
function reason(err) {
|
|
131
|
+
if (err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')) {
|
|
132
|
+
return `it did not answer within ${MARKET_TIMEOUT_MS / 1000} seconds`;
|
|
133
|
+
}
|
|
134
|
+
if (err instanceof z.ZodError)
|
|
135
|
+
return 'what it answered is not a plugin list';
|
|
136
|
+
const cause = err instanceof Error && err.cause instanceof Error ? `: ${err.cause.message}` : '';
|
|
137
|
+
return `${err instanceof Error ? err.message : String(err)}${cause}`;
|
|
138
|
+
}
|
|
139
|
+
/** Which installed record, if any, is this listing. */
|
|
140
|
+
function installedAs(entry, record) {
|
|
141
|
+
return record.find((plugin) => plugin.name === entry.name || (plugin.source.kind === 'registry' && plugin.source.name === entry.npm));
|
|
142
|
+
}
|
|
143
|
+
/** The areas a listing reaches, from its claims, in the staged card's words. */
|
|
144
|
+
function listedUses(entry) {
|
|
145
|
+
const claims = entry.claims;
|
|
146
|
+
const uses = claims?.package?.uses ?? claims?.manifest?.uses;
|
|
147
|
+
return Array.isArray(uses) ? uses : [];
|
|
148
|
+
}
|
|
149
|
+
export function annotateMarket(plugins, record) {
|
|
150
|
+
return plugins.map((entry) => {
|
|
151
|
+
const here = installedAs(entry, record);
|
|
152
|
+
const newer = here !== undefined && (compareVersions(entry.version, here.version) ?? 0) > 0;
|
|
153
|
+
return {
|
|
154
|
+
...entry,
|
|
155
|
+
usesWords: usesWords(listedUses(entry)),
|
|
156
|
+
...(here === undefined ? {} : { installed: { version: here.version, name: here.name } }),
|
|
157
|
+
...(newer ? { update: entry.version } : {}),
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/* ------------------------------------------------------------------ *
|
|
162
|
+
* The listings' files: icons and screenshots
|
|
163
|
+
* ------------------------------------------------------------------ */
|
|
164
|
+
/** Where every listing's files live; nothing outside it is fetched for the page. */
|
|
165
|
+
export const MARKET_ASSET_PREFIX = `${MARKET_ORIGIN}/plugins/`;
|
|
166
|
+
/** A screenshot is a few hundred kilobytes; this is room and no more. */
|
|
167
|
+
export const MAX_ASSET_BYTES = 5 * 1024 * 1024;
|
|
168
|
+
/** What a listing's file may be. Anything else is not passed on. */
|
|
169
|
+
const ASSET_TYPES = new Set(['image/webp', 'image/png', 'image/jpeg', 'image/gif', 'image/svg+xml']);
|
|
170
|
+
/**
|
|
171
|
+
* The prefixes a file may be fetched from: withbuddi.com's, and the origin
|
|
172
|
+
* `BUDDI_MARKET_URL` names when set (a staging copy of the site), whose own
|
|
173
|
+
* files sit at the same place under it.
|
|
174
|
+
*/
|
|
175
|
+
function assetPrefixes(env) {
|
|
176
|
+
const configured = env.BUDDI_MARKET_URL?.trim();
|
|
177
|
+
const prefixes = [MARKET_ASSET_PREFIX];
|
|
178
|
+
if (configured)
|
|
179
|
+
prefixes.push(`${configured.replace(/\/+$/, '')}/plugins/`);
|
|
180
|
+
return [...new Set(prefixes)];
|
|
181
|
+
}
|
|
182
|
+
/** The URL, when it is a listing's file; `undefined` for anything else. */
|
|
183
|
+
export function marketAssetUrl(env, raw) {
|
|
184
|
+
if (!raw)
|
|
185
|
+
return undefined;
|
|
186
|
+
let url;
|
|
187
|
+
try {
|
|
188
|
+
url = new URL(raw);
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
// Parsed, so `..` and encoded dots are resolved before the prefix is checked.
|
|
194
|
+
if (url.username || url.password || url.search || url.hash)
|
|
195
|
+
return undefined;
|
|
196
|
+
return assetPrefixes(env).some((prefix) => url.href.startsWith(prefix)) && url.href.length > url.origin.length + '/plugins/'.length
|
|
197
|
+
? url
|
|
198
|
+
: undefined;
|
|
199
|
+
}
|
|
200
|
+
function assetPaths(env, url) {
|
|
201
|
+
const key = createHash('sha256').update(url.href).digest('hex');
|
|
202
|
+
const dir = path.join(path.dirname(marketFile(env)), 'assets');
|
|
203
|
+
return { bytes: path.join(dir, key), meta: path.join(dir, `${key}.json`) };
|
|
204
|
+
}
|
|
205
|
+
function readAsset(env, url) {
|
|
206
|
+
try {
|
|
207
|
+
const files = assetPaths(env, url);
|
|
208
|
+
const meta = JSON.parse(readFileSync(files.meta, 'utf8'));
|
|
209
|
+
if (meta.url !== url.href || typeof meta.type !== 'string' || typeof meta.fetchedAt !== 'string')
|
|
210
|
+
return undefined;
|
|
211
|
+
return { bytes: readFileSync(files.bytes), type: meta.type, fetchedAt: meta.fetchedAt };
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function writeAsset(env, url, asset, log) {
|
|
218
|
+
try {
|
|
219
|
+
const files = assetPaths(env, url);
|
|
220
|
+
mkdirSync(path.dirname(files.bytes), { recursive: true });
|
|
221
|
+
const tmp = `${files.bytes}.${process.pid}.tmp`;
|
|
222
|
+
writeFileSync(tmp, asset.bytes);
|
|
223
|
+
renameSync(tmp, files.bytes);
|
|
224
|
+
writeFileSync(files.meta, `${JSON.stringify({ url: url.href, type: asset.type, fetchedAt: asset.fetchedAt })}\n`);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
log(`market: could not keep ${url.href} on disk: ${err instanceof Error ? err.message : String(err)}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async function fetchAsset(deps, url) {
|
|
231
|
+
const doFetch = deps.fetch ?? fetch;
|
|
232
|
+
const response = await doFetch(url.href, { signal: AbortSignal.timeout(MARKET_TIMEOUT_MS), redirect: 'error' });
|
|
233
|
+
if (!response.ok)
|
|
234
|
+
throw new Error(`${url.href} answered ${response.status}`);
|
|
235
|
+
const type = (response.headers.get('content-type') ?? '').split(';')[0]?.trim().toLowerCase() ?? '';
|
|
236
|
+
if (!ASSET_TYPES.has(type))
|
|
237
|
+
throw new Error(`${url.href} is not a picture (${type || 'no type'})`);
|
|
238
|
+
const declared = Number(response.headers.get('content-length') ?? '0');
|
|
239
|
+
if (declared > MAX_ASSET_BYTES)
|
|
240
|
+
throw new Error(`${url.href} is larger than a listing's picture should be`);
|
|
241
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
242
|
+
if (bytes.length > MAX_ASSET_BYTES)
|
|
243
|
+
throw new Error(`${url.href} is larger than a listing's picture should be`);
|
|
244
|
+
return { bytes, type };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* One listing's file: from the copy beside the index while it is under a day
|
|
248
|
+
* old, else fetched and kept. A fetch that fails with a copy on hand answers
|
|
249
|
+
* the copy; with none, it throws.
|
|
250
|
+
*/
|
|
251
|
+
export async function marketAsset(deps, url) {
|
|
252
|
+
const now = deps.now ?? (() => new Date());
|
|
253
|
+
const kept = readAsset(deps.env, url);
|
|
254
|
+
if (kept && now().getTime() - Date.parse(kept.fetchedAt) < MARKET_ASSET_TTL_MS)
|
|
255
|
+
return kept;
|
|
256
|
+
try {
|
|
257
|
+
const asset = { ...(await fetchAsset(deps, url)), fetchedAt: now().toISOString() };
|
|
258
|
+
writeAsset(deps.env, url, asset, deps.log);
|
|
259
|
+
return asset;
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
if (kept)
|
|
263
|
+
return kept;
|
|
264
|
+
throw err;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* `GET /api/market/asset?url=<a listing's file>` — a screenshot for the
|
|
269
|
+
* detail sheet. An SVG goes out only as the sanitiser re-wrote it.
|
|
270
|
+
*/
|
|
271
|
+
export async function marketAssetRoute(deps, url) {
|
|
272
|
+
const target = marketAssetUrl(deps.env, url.searchParams.get('url'));
|
|
273
|
+
if (!target)
|
|
274
|
+
return { status: 400, body: { error: `Only a listing's own files, under ${MARKET_ASSET_PREFIX}, come through here.` } };
|
|
275
|
+
let asset;
|
|
276
|
+
try {
|
|
277
|
+
asset = await marketAsset(deps, target);
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
deps.log(`market: fetching ${target.href} failed: ${reason(err)}`);
|
|
281
|
+
return { status: 502, body: { error: `buddi could not fetch that picture from withbuddi.com: ${reason(err)}` } };
|
|
282
|
+
}
|
|
283
|
+
if (asset.type === 'image/svg+xml') {
|
|
284
|
+
const svg = sanitizeIconSvg(asset.bytes.toString('utf8'));
|
|
285
|
+
if (svg === undefined)
|
|
286
|
+
return { status: 415, body: { error: 'That picture is not one buddi will draw.' } };
|
|
287
|
+
return { status: 200, bytes: Buffer.from(svg), type: asset.type };
|
|
288
|
+
}
|
|
289
|
+
return { status: 200, bytes: asset.bytes, type: asset.type };
|
|
290
|
+
}
|
|
291
|
+
/** A listing's icon, as markup the page may draw inline; `undefined` when there is none it will draw. */
|
|
292
|
+
async function iconSvgOf(deps, entry) {
|
|
293
|
+
const icon = entry.icon;
|
|
294
|
+
const url = typeof icon === 'string' ? marketAssetUrl(deps.env, icon) : undefined;
|
|
295
|
+
if (!url)
|
|
296
|
+
return undefined;
|
|
297
|
+
try {
|
|
298
|
+
const asset = await marketAsset(deps, url);
|
|
299
|
+
return asset.type === 'image/svg+xml' ? sanitizeIconSvg(asset.bytes.toString('utf8')) : undefined;
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
deps.log(`market: the icon of "${entry.name}" was left out: ${reason(err)}`);
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/** `GET /api/market[?refresh=1]`. */
|
|
307
|
+
export async function marketRoute(deps, url) {
|
|
308
|
+
const now = deps.now ?? (() => new Date());
|
|
309
|
+
const file = marketFile(deps.env);
|
|
310
|
+
const refresh = url.searchParams.get('refresh') === '1';
|
|
311
|
+
let cached = memory.get(file) ?? readDisk(file);
|
|
312
|
+
if (cached !== undefined)
|
|
313
|
+
memory.set(file, cached);
|
|
314
|
+
const fresh = cached !== undefined && now().getTime() - Date.parse(cached.fetchedAt) < MARKET_TTL_MS;
|
|
315
|
+
let stale = false;
|
|
316
|
+
if (refresh || !fresh) {
|
|
317
|
+
try {
|
|
318
|
+
const index = await fetchIndex(deps);
|
|
319
|
+
cached = { fetchedAt: now().toISOString(), index };
|
|
320
|
+
memory.set(file, cached);
|
|
321
|
+
writeDisk(file, cached, deps.log);
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
const why = reason(err);
|
|
325
|
+
deps.log(`market: fetching the plugin list failed: ${why}`);
|
|
326
|
+
if (cached === undefined) {
|
|
327
|
+
return {
|
|
328
|
+
status: 200,
|
|
329
|
+
body: { plugins: [], unavailable: `buddi could not reach withbuddi.com: ${why}` },
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
stale = true;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const { plugins: record } = installedRecord(deps.env);
|
|
336
|
+
const listed = cached.index.plugins;
|
|
337
|
+
const icons = await Promise.all(listed.map((entry) => iconSvgOf(deps, entry)));
|
|
338
|
+
return {
|
|
339
|
+
status: 200,
|
|
340
|
+
body: {
|
|
341
|
+
fetchedAt: cached.fetchedAt,
|
|
342
|
+
...(stale ? { stale: true } : {}),
|
|
343
|
+
plugins: annotateMarket(listed, record).map((entry, i) => icons[i] === undefined ? entry : { ...entry, iconSvg: icons[i] }),
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=market.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"market.js","sourceRoot":"","sources":["../../src/web/market.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* GET /api/notifications/settings the settings, and the channels there are
|
|
8
8
|
* PUT /api/notifications/settings the whole settings value, replaced
|
|
9
9
|
* POST /api/notifications/test { channel } one line through that channel, now
|
|
10
|
+
* GET /api/notifications/focus the focus in force now, or null
|
|
11
|
+
* PUT /api/notifications/focus { mode, duration } switch it; mode `normal` turns it off
|
|
10
12
|
* POST /api/presence { state } `active` every 30 s while the page is
|
|
11
13
|
* visible and focused; `away` on blur or hide
|
|
12
14
|
*
|
|
@@ -14,7 +16,7 @@
|
|
|
14
16
|
* stream is per conversation and opened only while a chat is on screen, and
|
|
15
17
|
* the owner is present on Home and Settings too.
|
|
16
18
|
*/
|
|
17
|
-
import { type Queryable } from '@buddi/core';
|
|
19
|
+
import { type NotifyDeps, type Queryable } from '@buddi/core';
|
|
18
20
|
export interface NotificationsRouteReply {
|
|
19
21
|
status: number;
|
|
20
22
|
body: unknown;
|
|
@@ -33,4 +35,9 @@ export declare const TEST_MESSAGE_TITLE = "A test from buddi. This is where your
|
|
|
33
35
|
* never shows in the last twenty or waits for the morning.
|
|
34
36
|
*/
|
|
35
37
|
export declare function testChannelRoute(body: Record<string, unknown>, now: Date): Promise<NotificationsRouteReply>;
|
|
38
|
+
/**
|
|
39
|
+
* The owner menu's Focus: what is on now, or a switch to a mode for a
|
|
40
|
+
* duration (`1h`, `3h`, `tomorrow`, `indefinite`); `normal` turns it off.
|
|
41
|
+
*/
|
|
42
|
+
export declare function focusRoute(pool: Queryable, deps: NotifyDeps, method: 'GET' | 'PUT', body?: unknown): Promise<NotificationsRouteReply>;
|
|
36
43
|
//# sourceMappingURL=notifications.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/web/notifications.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/web/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAWL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAGpH;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAI5G;AAED,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,KAAK,GAAG,KAAK,EACrB,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,uBAAuB,CAAC,CAOlC;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAK/H;AAED,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,gEAAgE,CAAC;AAEhG;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAQjH;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,KAAK,GAAG,KAAK,EACrB,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,uBAAuB,CAAC,CAalC"}
|