@hyperdrive.bot/fleet-server 0.3.148 → 0.3.149

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/server/server/agent/tools/paseo-tools.d.ts +9 -0
  2. package/dist/server/server/agent/tools/paseo-tools.js +76 -1
  3. package/dist/server/server/agent/tools/read-only-surface.d.ts +7 -0
  4. package/dist/server/server/agent/tools/read-only-surface.js +8 -0
  5. package/dist/server/server/bootstrap.js +71 -1
  6. package/dist/server/server/exports.d.ts +2 -0
  7. package/dist/server/server/exports.js +6 -0
  8. package/dist/server/server/ingestion/subscriptions/notification-prompt.d.ts +83 -0
  9. package/dist/server/server/ingestion/subscriptions/notification-prompt.js +96 -0
  10. package/dist/server/server/ingestion/subscriptions/notifier.d.ts +96 -0
  11. package/dist/server/server/ingestion/subscriptions/notifier.js +209 -0
  12. package/dist/server/server/ingestion/subscriptions/pending-store.d.ts +111 -0
  13. package/dist/server/server/ingestion/subscriptions/pending-store.js +254 -0
  14. package/dist/server/server/ingestion/subscriptions/poller.d.ts +73 -0
  15. package/dist/server/server/ingestion/subscriptions/poller.js +168 -0
  16. package/dist/server/server/ingestion/subscriptions/reader.d.ts +39 -0
  17. package/dist/server/server/ingestion/subscriptions/reader.js +30 -0
  18. package/dist/server/server/ingestion/subscriptions/store.d.ts +35 -0
  19. package/dist/server/server/ingestion/subscriptions/store.js +82 -0
  20. package/dist/server/web-ui/_expo/static/js/web/{index-88d5f130a09403b86ae8c8c5fd1f97d4.js → index-8747c529e5cb02149fe51570f7cb697b.js} +4 -4
  21. package/dist/server/web-ui/_expo/static/js/web/index-8747c529e5cb02149fe51570f7cb697b.js.br +0 -0
  22. package/dist/server/web-ui/_expo/static/js/web/index-8747c529e5cb02149fe51570f7cb697b.js.gz +0 -0
  23. package/dist/server/web-ui/_expo/static/js/web/{index-88d5f130a09403b86ae8c8c5fd1f97d4.js.map.br → index-8747c529e5cb02149fe51570f7cb697b.js.map.br} +0 -0
  24. package/dist/server/web-ui/_expo/static/js/web/{index-88d5f130a09403b86ae8c8c5fd1f97d4.js.map.gz → index-8747c529e5cb02149fe51570f7cb697b.js.map.gz} +0 -0
  25. package/dist/server/web-ui/index.html +1 -1
  26. package/dist/server/web-ui/index.html.br +0 -0
  27. package/dist/server/web-ui/index.html.gz +0 -0
  28. package/package.json +6 -6
  29. package/dist/server/web-ui/_expo/static/js/web/index-88d5f130a09403b86ae8c8c5fd1f97d4.js.br +0 -0
  30. package/dist/server/web-ui/_expo/static/js/web/index-88d5f130a09403b86ae8c8c5fd1f97d4.js.gz +0 -0
@@ -0,0 +1,168 @@
1
+ import { scanMatchedSourceItems, windowStartFor } from "../backfill.js";
2
+ /** How often the poller reads its sources. */
3
+ export const DEFAULT_POLL_INTERVAL_MS = 300000;
4
+ /**
5
+ * How far back each poll reads.
6
+ *
7
+ * Wider than the interval on purpose: a daemon that was asleep, or a source
8
+ * whose aggregator buffer filled late, would otherwise leave a hole no later
9
+ * poll ever covers. Re-reading an item is free, because `PendingItemStore.append`
10
+ * ignores one whose `contentHash` is unchanged.
11
+ */
12
+ export const POLL_WINDOW_DAYS = 1;
13
+ /**
14
+ * Reads each subscribed source ONCE per tick and fans the result out to every
15
+ * filter, and through them to every subscriber.
16
+ *
17
+ * The shape exists because of a measured cost: today two filters armed on one
18
+ * source cause two independent `listItems` walks, with no cache and no shared
19
+ * scan. With N subscribers that is N reads of the same aggregator buffer per
20
+ * window. Matching is pure string comparison over a dotted path, so fanning out
21
+ * in memory costs CPU while reading costs network, rate limit and latency.
22
+ * One read, many matches.
23
+ *
24
+ * It owns its own timer and touches the schedule engine not at all. A
25
+ * subscription is not a schedule: it must survive its target being archived,
26
+ * and `sweepOrphanedSchedules` would complete it terminally at the next boot.
27
+ */
28
+ export class SubscriptionPoller {
29
+ constructor(options) {
30
+ this.timer = null;
31
+ /** Single-flight. A slow aggregator must not let two ticks overlap. */
32
+ this.running = false;
33
+ this.options = options;
34
+ this.intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
35
+ this.now = options.now ?? (() => Date.now());
36
+ }
37
+ start() {
38
+ if (this.timer)
39
+ return;
40
+ this.timer = setInterval(() => {
41
+ void this.tick().catch((error) => {
42
+ this.options.logger.warn({ err: error }, "Subscription poll tick failed");
43
+ });
44
+ }, this.intervalMs);
45
+ // Never keep the process alive for a poll.
46
+ this.timer.unref?.();
47
+ this.options.logger.info({ intervalMs: this.intervalMs }, "Subscription poller started");
48
+ }
49
+ stop() {
50
+ if (!this.timer)
51
+ return;
52
+ clearInterval(this.timer);
53
+ this.timer = null;
54
+ }
55
+ /**
56
+ * One pass: read every subscribed source once, match, notify, then drain.
57
+ *
58
+ * The drain at the end is what makes a notice held back by `busy` or
59
+ * `debounced` eventually go out even when the source has gone quiet.
60
+ */
61
+ async tick() {
62
+ if (this.running) {
63
+ return { sourcesRead: 0, filtersMatched: 0, notified: 0 };
64
+ }
65
+ this.running = true;
66
+ try {
67
+ return await this.runTick();
68
+ }
69
+ finally {
70
+ this.running = false;
71
+ }
72
+ }
73
+ async runTick() {
74
+ const { subscriptions, filterResolver, sourceStore, gatewayResolver, logger } = this.options;
75
+ const armed = (await subscriptions.list()).filter((s) => s.status === "armed");
76
+ const summary = { sourcesRead: 0, filtersMatched: 0, notified: 0 };
77
+ if (armed.length === 0) {
78
+ return summary;
79
+ }
80
+ // Resolve the distinct filters once. Several subscribers commonly share one.
81
+ const filters = new Map();
82
+ for (const subscription of armed) {
83
+ if (filters.has(subscription.filterId))
84
+ continue;
85
+ const filter = await filterResolver(subscription.filterId);
86
+ if (!filter) {
87
+ logger.warn({ subscriptionId: subscription.id, filterId: subscription.filterId }, "Subscription points at a filter that no longer exists");
88
+ continue;
89
+ }
90
+ if (filter.status !== "armed")
91
+ continue;
92
+ filters.set(filter.id, filter);
93
+ }
94
+ // Group by source: this is the line that turns N reads into one.
95
+ const bySource = new Map();
96
+ for (const filter of filters.values()) {
97
+ const list = bySource.get(filter.sourceId);
98
+ if (list)
99
+ list.push(filter);
100
+ else
101
+ bySource.set(filter.sourceId, [filter]);
102
+ }
103
+ const now = this.now();
104
+ for (const [sourceId, sourceFilters] of bySource) {
105
+ const source = await sourceStore.get(sourceId);
106
+ if (!source) {
107
+ logger.warn({ sourceId }, "Subscribed filter points at a source that no longer exists");
108
+ continue;
109
+ }
110
+ let gateway;
111
+ try {
112
+ gateway = gatewayResolver(source.kind);
113
+ }
114
+ catch (error) {
115
+ logger.warn({ err: error, sourceId, kind: source.kind }, "No gateway for source kind");
116
+ continue;
117
+ }
118
+ for (const filter of sourceFilters) {
119
+ try {
120
+ const { matched } = await scanMatchedSourceItems({
121
+ filter,
122
+ gateway,
123
+ externalUserId: source.externalUserId,
124
+ accountId: source.externalAccountId ?? "",
125
+ // Freshness is the pending store's job, keyed per subscriber, so
126
+ // this read deliberately answers "already handled?" with null for
127
+ // everything. Asking the shared ledger here would be a second,
128
+ // filter-wide answer to a question that is per subscription.
129
+ ledger: { get: () => Promise.resolve(null) },
130
+ sinceMs: windowStartFor(now, POLL_WINDOW_DAYS),
131
+ now: () => now,
132
+ });
133
+ summary.filtersMatched += 1;
134
+ if (matched.length === 0)
135
+ continue;
136
+ const results = await this.options.notifier.notifyForFilter(filter, matched);
137
+ summary.notified += results.filter((result) => result.outcome === "sent").length;
138
+ }
139
+ catch (error) {
140
+ // A failing filter must not abandon its siblings on the same read.
141
+ logger.warn({ err: error, filterId: filter.id, sourceId }, "Subscription scan failed");
142
+ }
143
+ }
144
+ summary.sourcesRead += 1;
145
+ }
146
+ const drained = await this.options.notifier.deliverAllPending();
147
+ summary.notified += drained.filter((result) => result.outcome === "sent").length;
148
+ // Retention runs on the TICK, not only at boot. Sweeping only at startup
149
+ // makes real retention `max(uptime, ttl)`, so a daemon up for forty days
150
+ // holds forty days of payloads while the docstring promises seven. That
151
+ // TTL is one of the three things containing a credential at rest, so it
152
+ // cannot depend on how often the process restarts. `IngestionService` does
153
+ // the same on its own health timer.
154
+ await this.sweep().catch((error) => {
155
+ this.options.logger.warn({ err: error }, "Subscription payload sweep failed");
156
+ });
157
+ return summary;
158
+ }
159
+ /** Delete pending payloads past their TTL. Called at boot, beside the other sweeps. */
160
+ async sweep() {
161
+ const removed = await this.options.pending.sweepExpired(this.now());
162
+ if (removed > 0) {
163
+ this.options.logger.info({ removed }, "Swept expired subscription payloads");
164
+ }
165
+ return removed;
166
+ }
167
+ }
168
+ //# sourceMappingURL=poller.js.map
@@ -0,0 +1,39 @@
1
+ import type { StoredSubscription } from "@hyperdrive.bot/fleet-protocol/ingestion/subscription-types";
2
+ import type { PendingItem, PendingItemStore } from "./pending-store.js";
3
+ import type { SubscriptionStore } from "./store.js";
4
+ /**
5
+ * The READ half of subscriptions, and the only half a model ever holds.
6
+ *
7
+ * Deliberately not the notifier and not the stores themselves. A tool catalog
8
+ * that could arm a subscription, or trigger a delivery, would put the delivery
9
+ * policy inside a model's reach; this interface cannot do either. It exists as
10
+ * an interface rather than a concrete class so the tool layer depends on three
11
+ * methods instead of on the ingestion module.
12
+ */
13
+ export interface SubscriptionReader {
14
+ /**
15
+ * Subscriptions the CALLER owns, never the daemon's whole set.
16
+ *
17
+ * `callerAgentId` is not decoration. Without it this is an enumeration step:
18
+ * one session lists every subscription on the box, reads another session's
19
+ * agent id, and then reads that session's stored payloads, credentials
20
+ * included. "A local MCP tool" means every agent on this daemon, which is
21
+ * not the same thing as the owner.
22
+ */
23
+ list(callerAgentId: string | undefined): Promise<StoredSubscription[]>;
24
+ get(subscriptionId: string, callerAgentId: string | undefined): Promise<StoredSubscription | null>;
25
+ /**
26
+ * Stored items for the given keys, payload included.
27
+ *
28
+ * This is the ONLY path by which a persisted payload leaves the daemon, and
29
+ * it is a local MCP call: no client RPC exposes it. Keys that are not held
30
+ * are simply absent from the result, the same contract `resolveMatchedItems`
31
+ * already has, so a caller sees a shorter list rather than an exception.
32
+ */
33
+ resolveItems(subscriptionId: string, itemKeys: readonly string[], callerAgentId: string | undefined): Promise<PendingItem[]>;
34
+ }
35
+ export declare function createSubscriptionReader(deps: {
36
+ subscriptions: SubscriptionStore;
37
+ pending: PendingItemStore;
38
+ }): SubscriptionReader;
39
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1,30 @@
1
+ export function createSubscriptionReader(deps) {
2
+ /**
3
+ * Fails CLOSED when the caller is unknown.
4
+ *
5
+ * An absent `callerAgentId` means the tool catalog was built without a
6
+ * caller identity, and the safe reading of "I do not know who is asking" is
7
+ * "you own nothing", not "you own everything".
8
+ */
9
+ const owns = (subscription, callerAgentId) => callerAgentId !== undefined && subscription.agentId === callerAgentId;
10
+ return {
11
+ list: async (callerAgentId) => (await deps.subscriptions.list()).filter((subscription) => owns(subscription, callerAgentId)),
12
+ get: async (subscriptionId, callerAgentId) => {
13
+ const subscription = await deps.subscriptions.get(subscriptionId);
14
+ if (!subscription || !owns(subscription, callerAgentId))
15
+ return null;
16
+ return subscription;
17
+ },
18
+ resolveItems: async (subscriptionId, itemKeys, callerAgentId) => {
19
+ // A subscription that no longer exists, or that belongs to someone else,
20
+ // resolves to nothing. Both answer the same way on purpose: a caller
21
+ // must not be able to tell "no such subscription" from "not yours" and
22
+ // use the difference to enumerate.
23
+ const subscription = await deps.subscriptions.get(subscriptionId);
24
+ if (!subscription || !owns(subscription, callerAgentId))
25
+ return [];
26
+ return deps.pending.resolve(subscriptionId, itemKeys);
27
+ },
28
+ };
29
+ }
30
+ //# sourceMappingURL=reader.js.map
@@ -0,0 +1,35 @@
1
+ import { type StoredSubscription } from "@hyperdrive.bot/fleet-protocol/ingestion/subscription-types";
2
+ /**
3
+ * File-backed persistence for session subscriptions, one JSON file per
4
+ * subscription under `dir` (the caller supplies `join(paseoHome, "subscriptions")`).
5
+ *
6
+ * Structurally identical to `SourceStore` and `ScheduleStore`, deliberately: a
7
+ * third shape here would be a third set of atomicity and parse bugs to find.
8
+ *
9
+ * `StoredSubscriptionSchema` is strict and `list()` is readdir + Promise.all, so
10
+ * ONE unparseable file rejects the whole array. That is the same trade the
11
+ * source store makes, and it carries the same obligation: every field added to
12
+ * the schema later must carry `.default(...)`, or records written before it
13
+ * existed stop parsing and every subscription silently disappears. There is no
14
+ * migration step. `accountLabel` on `StoredSourceSchema` is the precedent.
15
+ */
16
+ export declare class SubscriptionStore {
17
+ private readonly dir;
18
+ constructor(dir: string);
19
+ private filePath;
20
+ private ensureDir;
21
+ list(): Promise<StoredSubscription[]>;
22
+ get(id: string): Promise<StoredSubscription | null>;
23
+ /**
24
+ * Every armed subscription pointing at `filterId`.
25
+ *
26
+ * The fan-out read. A filter with three armed subscribers returns three
27
+ * records here, and each one is notified on its own budget: this is the
28
+ * function that makes one filter serve many sessions.
29
+ */
30
+ listArmedForFilter(filterId: string): Promise<StoredSubscription[]>;
31
+ create(subscription: Omit<StoredSubscription, "id">): Promise<StoredSubscription>;
32
+ put(subscription: StoredSubscription): Promise<void>;
33
+ delete(id: string): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,82 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { mkdir, readFile, readdir, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { StoredSubscriptionSchema, } from "@hyperdrive.bot/fleet-protocol/ingestion/subscription-types";
5
+ import { writeJsonFileAtomic } from "../../atomic-file.js";
6
+ function generateSubscriptionId() {
7
+ return randomBytes(4).toString("hex");
8
+ }
9
+ /**
10
+ * File-backed persistence for session subscriptions, one JSON file per
11
+ * subscription under `dir` (the caller supplies `join(paseoHome, "subscriptions")`).
12
+ *
13
+ * Structurally identical to `SourceStore` and `ScheduleStore`, deliberately: a
14
+ * third shape here would be a third set of atomicity and parse bugs to find.
15
+ *
16
+ * `StoredSubscriptionSchema` is strict and `list()` is readdir + Promise.all, so
17
+ * ONE unparseable file rejects the whole array. That is the same trade the
18
+ * source store makes, and it carries the same obligation: every field added to
19
+ * the schema later must carry `.default(...)`, or records written before it
20
+ * existed stop parsing and every subscription silently disappears. There is no
21
+ * migration step. `accountLabel` on `StoredSourceSchema` is the precedent.
22
+ */
23
+ export class SubscriptionStore {
24
+ constructor(dir) {
25
+ this.dir = dir;
26
+ }
27
+ filePath(id) {
28
+ return join(this.dir, `${id}.json`);
29
+ }
30
+ async ensureDir() {
31
+ await mkdir(this.dir, { recursive: true });
32
+ }
33
+ async list() {
34
+ await this.ensureDir();
35
+ const entries = await readdir(this.dir, { withFileTypes: true });
36
+ const subscriptions = await Promise.all(entries
37
+ .filter((entry) => entry.isFile() && entry.name.endsWith(".json"))
38
+ .map(async (entry) => {
39
+ const content = await readFile(join(this.dir, entry.name), "utf-8");
40
+ return StoredSubscriptionSchema.parse(JSON.parse(content));
41
+ }));
42
+ return subscriptions.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
43
+ }
44
+ async get(id) {
45
+ await this.ensureDir();
46
+ try {
47
+ const content = await readFile(this.filePath(id), "utf-8");
48
+ return StoredSubscriptionSchema.parse(JSON.parse(content));
49
+ }
50
+ catch (error) {
51
+ if (error.code === "ENOENT") {
52
+ return null;
53
+ }
54
+ throw error;
55
+ }
56
+ }
57
+ /**
58
+ * Every armed subscription pointing at `filterId`.
59
+ *
60
+ * The fan-out read. A filter with three armed subscribers returns three
61
+ * records here, and each one is notified on its own budget: this is the
62
+ * function that makes one filter serve many sessions.
63
+ */
64
+ async listArmedForFilter(filterId) {
65
+ const all = await this.list();
66
+ return all.filter((subscription) => subscription.filterId === filterId && subscription.status === "armed");
67
+ }
68
+ async create(subscription) {
69
+ const created = { ...subscription, id: generateSubscriptionId() };
70
+ await this.put(created);
71
+ return created;
72
+ }
73
+ async put(subscription) {
74
+ await this.ensureDir();
75
+ await writeJsonFileAtomic(this.filePath(subscription.id), subscription);
76
+ }
77
+ async delete(id) {
78
+ await this.ensureDir();
79
+ await rm(this.filePath(id), { force: true });
80
+ }
81
+ }
82
+ //# sourceMappingURL=store.js.map
@@ -849,7 +849,7 @@ __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,"__esModule",{v
849
849
  __d(function(g,r,i,a,m,e,d){"use strict";var t=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.shouldAppendSitemap=u,e.shouldAppendNotFound=s,e.getRootStackRouteNames=function(){const t=[n.INTERNAL_SLOT_NAME];s()&&t.push(n.NOT_FOUND_ROUTE_NAME);u()&&t.push(n.SITEMAP_ROUTE_NAME);return t};const o=t(r(d[0])),n=r(d[1]);function u(){const t=o.default.expoConfig?.extra?.router;return!1!==t?.sitemap}function s(){const t=o.default.expoConfig?.extra?.router;return!1!==t?.notFound}},717,[718,721]);
850
850
  __d(function(g,r,i,a,m,_e,d){"use strict";function e(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(_e,'__esModule',{value:!0}),Object.defineProperty(_e,"default",{enumerable:!0,get:function(){return N}}),Object.defineProperty(_e,"AppOwnership",{enumerable:!0,get:function(){return l.AppOwnership}}),Object.defineProperty(_e,"ExecutionEnvironment",{enumerable:!0,get:function(){return l.ExecutionEnvironment}}),Object.defineProperty(_e,"UserInterfaceIdiom",{enumerable:!0,get:function(){return l.UserInterfaceIdiom}});var n=e(r(d[0])),t=r(d[1]);r(d[2]);var u=e(r(d[3])),l=r(d[4]),o=e(r(d[5]));o.default||console.warn("No native ExponentConstants module found, are you sure the expo-constants's module is linked properly?");const s=(0,t.requireOptionalNativeModule)('ExpoUpdates');let f=null;if(s){let e;s.manifest?e=s.manifest:s.manifestString&&(e=JSON.parse(s.manifestString)),e&&Object.keys(e).length>0&&(f=e)}let c=null;if(u.default.EXDevLauncher){let e;u.default.EXDevLauncher.manifestString&&(e=JSON.parse(u.default.EXDevLauncher.manifestString)),e&&Object.keys(e).length>0&&(c=e)}let p=null;if(o.default&&o.default.manifest){const e=o.default.manifest;p='string'==typeof e?JSON.parse(e):e}let b=f??c??p;const E=o.default||{},{appOwnership:O}=E,x=(0,n.default)(E,["name","appOwnership"]),v=Object.assign({},x,{appOwnership:O??null});function _(e){return!h(e)}function h(e){return'metadata'in e}function S(e=!1){if(!b){const e=null===b?'null':'undefined';if(x.executionEnvironment,l.ExecutionEnvironment.Bare,x.executionEnvironment===l.ExecutionEnvironment.StoreClient||x.executionEnvironment===l.ExecutionEnvironment.Standalone)throw new t.CodedError('ERR_CONSTANTS_MANIFEST_UNAVAILABLE',`Constants.manifest is ${e}, must be an object.`)}return b}Object.defineProperties(v,{__unsafeNoWarnManifest:{get(){const e=S(!0);return e&&_(e)?e:null},enumerable:!1},__unsafeNoWarnManifest2:{get(){const e=S(!0);return e&&h(e)?e:null},enumerable:!1},manifest:{get(){const e=S();return e&&_(e)?e:null},enumerable:!0},manifest2:{get(){const e=S();return e&&h(e)?e:null},enumerable:!0},expoConfig:{get(){const e=S(!0);return e?s&&s.isEmbeddedLaunch?p:h(e)?e.extra?.expoClient??null:_(e)?e:null:null},enumerable:!0},expoGoConfig:{get(){const e=S(!0);return e?h(e)?e.extra?.expoGo??null:_(e)?e:null:null},enumerable:!0},easConfig:{get(){const e=S(!0);return e?h(e)?e.extra?.eas??null:_(e)?e:null:null},enumerable:!0},__rawManifest_TEST:{get:()=>b,set(e){b=e},enumerable:!1}});var N=v},718,[35,4,25,637,719,720]);
851
851
  __d(function(g,r,i,a,m,e,d){"use strict";var t,n,o;Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"AppOwnership",{enumerable:!0,get:function(){return t}}),Object.defineProperty(e,"ExecutionEnvironment",{enumerable:!0,get:function(){return n}}),Object.defineProperty(e,"UserInterfaceIdiom",{enumerable:!0,get:function(){return o}}),(function(t){t.Expo="expo"})(t||(t={})),(function(t){t.Bare="bare",t.Standalone="standalone",t.StoreClient="storeClient"})(n||(n={})),(function(t){t.Handset="handset",t.Tablet="tablet",t.Desktop="desktop",t.TV="tv",t.Unsupported="unsupported"})(o||(o={}))},719,[]);
852
- __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return s}});var t=r(d[0]);const n=(Date.now()+'-'+Math.floor(1e9*Math.random())).toString();function o(){if('undefined'!=typeof navigator&&'string'==typeof navigator.userAgent){const t=navigator.userAgent.toLowerCase();if(t.includes('edge'))return'Edge';if(t.includes('edg'))return'Chromium Edge';if(t.includes('opr')&&'opr'in window&&window.opr)return'Opera';if(t.includes('chrome')&&'chrome'in window&&window.chrome)return'Chrome';if(t.includes('trident'))return'IE';if(t.includes('firefox'))return'Firefox';if(t.includes('safari'))return'Safari'}}var s={get appOwnership(){return null},get executionEnvironment(){return t.ExecutionEnvironment.Bare},get sessionId(){return n},get isHeadless(){return'undefined'==typeof navigator||/\bHeadlessChrome\//.test(navigator.userAgent)},get expoVersion(){return this.manifest.sdkVersion||null},get linkingUri(){return'undefined'!=typeof location?location.origin:''},get expoRuntimeVersion(){return this.expoVersion},get deviceName(){return o()},get systemFonts(){return[]},get statusBarHeight(){return 0},get deviceYearClass(){return null},get manifest(){return"{\"name\":\"Paseo\",\"slug\":\"paseo-hyperdrive\",\"version\":\"0.3.148\",\"orientation\":\"portrait\",\"icon\":\"./assets/images/icon.png\",\"scheme\":\"paseo\",\"userInterfaceStyle\":\"automatic\",\"newArchEnabled\":true,\"web\":{\"output\":\"single\",\"favicon\":\"./assets/images/favicon.png\",\"shortName\":\"Paseo\",\"orientation\":\"portrait\",\"name\":\"Paseo\"},\"autolinking\":{\"searchPaths\":[\"../../node_modules\",\"./node_modules\"]},\"experiments\":{\"typedRoutes\":true,\"reactCompiler\":true,\"autolinkingModuleResolution\":true},\"extra\":{\"router\":{},\"eas\":{\"build\":{\"experimental\":{\"ios\":{\"appExtensions\":[{\"bundleIdentifier\":\"bot.hyperdrive.paseo.AgentActivity\",\"targetName\":\"AgentActivity\"}]}}}}},\"sdkVersion\":\"54.0.0\",\"platforms\":[\"ios\",\"android\",\"web\"]}"},get manifest2(){return null},get experienceUrl(){return'undefined'!=typeof location?location.origin:''},get debugMode(){return!1},getWebViewUserAgentAsync:async()=>'undefined'!=typeof navigator?navigator.userAgent:null}},720,[719]);
852
+ __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return s}});var t=r(d[0]);const n=(Date.now()+'-'+Math.floor(1e9*Math.random())).toString();function o(){if('undefined'!=typeof navigator&&'string'==typeof navigator.userAgent){const t=navigator.userAgent.toLowerCase();if(t.includes('edge'))return'Edge';if(t.includes('edg'))return'Chromium Edge';if(t.includes('opr')&&'opr'in window&&window.opr)return'Opera';if(t.includes('chrome')&&'chrome'in window&&window.chrome)return'Chrome';if(t.includes('trident'))return'IE';if(t.includes('firefox'))return'Firefox';if(t.includes('safari'))return'Safari'}}var s={get appOwnership(){return null},get executionEnvironment(){return t.ExecutionEnvironment.Bare},get sessionId(){return n},get isHeadless(){return'undefined'==typeof navigator||/\bHeadlessChrome\//.test(navigator.userAgent)},get expoVersion(){return this.manifest.sdkVersion||null},get linkingUri(){return'undefined'!=typeof location?location.origin:''},get expoRuntimeVersion(){return this.expoVersion},get deviceName(){return o()},get systemFonts(){return[]},get statusBarHeight(){return 0},get deviceYearClass(){return null},get manifest(){return"{\"name\":\"Paseo\",\"slug\":\"paseo-hyperdrive\",\"version\":\"0.3.149\",\"orientation\":\"portrait\",\"icon\":\"./assets/images/icon.png\",\"scheme\":\"paseo\",\"userInterfaceStyle\":\"automatic\",\"newArchEnabled\":true,\"web\":{\"output\":\"single\",\"favicon\":\"./assets/images/favicon.png\",\"shortName\":\"Paseo\",\"orientation\":\"portrait\",\"name\":\"Paseo\"},\"autolinking\":{\"searchPaths\":[\"../../node_modules\",\"./node_modules\"]},\"experiments\":{\"typedRoutes\":true,\"reactCompiler\":true,\"autolinkingModuleResolution\":true},\"extra\":{\"router\":{},\"eas\":{\"build\":{\"experimental\":{\"ios\":{\"appExtensions\":[{\"bundleIdentifier\":\"bot.hyperdrive.paseo.AgentActivity\",\"targetName\":\"AgentActivity\"}]}}}}},\"sdkVersion\":\"54.0.0\",\"platforms\":[\"ios\",\"android\",\"web\"]}"},get manifest2(){return null},get experienceUrl(){return'undefined'!=typeof location?location.origin:''},get debugMode(){return!1},getWebViewUserAgentAsync:async()=>'undefined'!=typeof navigator?navigator.userAgent:null}},720,[719]);
853
853
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SITEMAP_ROUTE_NAME=e.NOT_FOUND_ROUTE_NAME=e.INTERNAL_SLOT_NAME=void 0,e.INTERNAL_SLOT_NAME='__root',e.NOT_FOUND_ROUTE_NAME='+not-found',e.SITEMAP_ROUTE_NAME='_sitemap'},721,[]);
854
854
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.resolveHref=void 0,e.resolveHrefStringWithSegments=function(t,{segments:n=[],params:s={}}={},{relativeToDirectory:o}={}){if(t.startsWith('.')){let c=n?.map(t=>{if(!t.startsWith('['))return t;if(t.startsWith('[...')){t=t.slice(4,-1);const n=s[t];return Array.isArray(n)?n.join('/'):n?.split(',')?.join('/')??''}return t=t.slice(1,-1),s[t]}).filter(Boolean).join('/')??'/';o&&(c=`${c}/`);const f=new URL(t,`http://hostname/${c}`);t=`${f.pathname}${f.search}`}return t};function t(t,s){for(const[o,c=""]of Object.entries(s)){const f=`[${o}]`,l=`[...${o}]`;if(t.includes(f))t=t.replace(f,n(c));else{if(!t.includes(l))continue;t=t.replace(l,n(c))}delete s[o]}return{pathname:t,params:s}}function n(t){return Array.isArray(t)?t.map(t=>n(t)).join('/'):encodeURIComponent(t.toString())}function s(t){return Object.entries(t).filter(([,t])=>null!=t).map(([t,n])=>`${t}=${encodeURIComponent(n.toString())}`).join('&')}e.resolveHref=n=>{if('string'==typeof n)return(0,e.resolveHref)({pathname:n});const o=n.pathname??'';if(!n?.params)return o;const{pathname:c,params:f}=t(o,Object.assign({},n.params)),l=s(f);return c+(l?`?${l}`:'')}},722,[]);
855
855
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isRoutePreloadedInStack=function(t,o){if(!t||'stack'!==t.type)return!1;return t.preloadedRoutes.some(t=>t.key===o.key)}},723,[]);
@@ -15057,7 +15057,7 @@ __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{v
15057
15057
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"decodeOfferFragmentPayload",{enumerable:!0,get:function(){return n.decodeOfferFragmentPayload}}),Object.defineProperty(e,"buildDaemonWebSocketUrl",{enumerable:!0,get:function(){return t.buildDaemonWebSocketUrl}}),Object.defineProperty(e,"deriveLabelFromEndpoint",{enumerable:!0,get:function(){return t.deriveLabelFromEndpoint}}),Object.defineProperty(e,"extractHostPortFromWebSocketUrl",{enumerable:!0,get:function(){return t.extractHostPortFromWebSocketUrl}}),Object.defineProperty(e,"normalizeHostPort",{enumerable:!0,get:function(){return t.normalizeHostPort}}),Object.defineProperty(e,"parseConnectionUri",{enumerable:!0,get:function(){return t.parseConnectionUri}}),Object.defineProperty(e,"parseHostPort",{enumerable:!0,get:function(){return t.parseHostPort}}),Object.defineProperty(e,"serializeConnectionUri",{enumerable:!0,get:function(){return t.serializeConnectionUri}}),Object.defineProperty(e,"serializeConnectionUriForStorage",{enumerable:!0,get:function(){return t.serializeConnectionUriForStorage}}),Object.defineProperty(e,"shouldUseTlsForDefaultHostedRelay",{enumerable:!0,get:function(){return t.shouldUseTlsForDefaultHostedRelay}}),e.buildRelayWebSocketUrl=function(n){return(0,t.buildRelayWebSocketUrl)(Object.assign({},n,{role:"client"}))};var t=r(d[0]),n=r(d[1])},3412,[3392,3413]);
15058
15058
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"ConnectionOfferV2Schema",{enumerable:!0,get:function(){return t}}),Object.defineProperty(e,"ConnectionOfferSchema",{enumerable:!0,get:function(){return o}}),e.decodeOfferFragmentPayload=l,e.parseConnectionOfferFromUrl=function(n){const t=f(n);if(!t)return null;const c=l(t);return o.parse(c)};var n=r(d[0]);const t=n.z.object({v:n.z.literal(2),serverId:n.z.string().min(1),daemonPublicKeyB64:n.z.string().min(1),relay:n.z.object({endpoint:n.z.string().min(1),useTls:n.z.boolean().optional()})}),o=t;function c(n){const t=n.replace(/-/g,"+").replace(/_/g,"/"),o=t.padEnd(t.length+(4-t.length%4)%4,"="),c=globalThis.atob(o),l=Uint8Array.from(c,n=>n.charCodeAt(0));return new TextDecoder("utf-8",{fatal:!0}).decode(l)}function l(n){const t=c(n);return JSON.parse(t)}const u="#offer=";function f(n){const t=n.trim();if(!t)return null;const o=t.indexOf(u);if(-1===o)return null;const c=t.slice(o+u.length).trim();return c.length>0?c:null}},3413,[3285]);
15059
15059
  __d(function(g,r,i,a,m,_e,d){"use strict";function e(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(_e,'__esModule',{value:!0}),_e.resolveAppVersion=function(){const e=u(t.default?.version);if(e)return e;const o=u(n.default.expoConfig?.version);if(o)return o;const f=u(n.default.manifest?.version);if(f)return f;return null};var n=e(r(d[0])),t=e(r(d[1]));function u(e){if("string"!=typeof e)return null;const n=e.trim();return 0===n.length?null:n}},3414,[718,3415]);
15060
- __d(function(e,t,r,a,o,i,n){o.exports={name:"@hyperdrive.bot/fleet-app",version:"0.3.148",private:!0,main:"index.ts",scripts:{start:"npm run start:expo","start:expo":"cross-env APP_VARIANT=development expo start","reset-project":"node ./scripts/reset-project.js","build:terminal-webview":"node ./scripts/build-terminal-webview-html.mjs","eas-build-post-install":"npm --prefix ../.. run build:app-deps && npm run build:terminal-webview",android:"npm run android:development","android:development":"npm --prefix ../.. run build:client && cross-env APP_VARIANT=development expo prebuild --platform android --non-interactive && cross-env APP_VARIANT=development expo run:android --variant=debug","android:production":"npm --prefix ../.. run build:client && cross-env APP_VARIANT=production expo prebuild --platform android --non-interactive && cross-env APP_VARIANT=production expo run:android --variant=release","android:release":"npm run android:production","android:clear":"node -e \"require('node:fs').rmSync('android', { recursive: true, force: true })\"",ios:"npm --prefix ../.. run build:client && expo run:ios","ios:release":"npm --prefix ../.. run build:client && expo run:ios --configuration Release",web:"npm --prefix ../.. run build:client && concurrently --kill-others --names protocol,client,expo --prefix-colors yellow,blue,magenta \"npm --prefix ../.. run watch:protocol\" \"npm --prefix ../.. run watch:client\" \"npm run web:expo\"","web:expo":"expo start --web",lint:"expo lint",typecheck:"tsgo --noEmit",test:"vitest run","test:browser":"vitest run --project browser","test:e2e":"playwright test --project='Desktop Chrome'","test:e2e:reels":"cross-env NODE_ENV=development playwright test --config playwright.reels.config.ts","test:e2e:real":"cross-env E2E_FORK_PASEO_HOME_FROM=../../.dev/paseo-home playwright test --project=real-provider","test:e2e:ui":"playwright test --ui","test:coverage":"vitest run --project unit --coverage",build:"npm run build:web","build:web":"npm --prefix ../.. run build:app-deps && expo export --platform web --source-maps","profile:workspace-tabs":"node ./scripts/profile-workspace-tabs.mjs","deploy:web":"npm run build:web && wrangler pages deploy dist --project-name paseo-app --branch main"},dependencies:{"@bacons/apple-targets":"4.0.6","@datadog/browser-rum":"^6.23.0","@datadog/browser-rum-react":"^6.23.0","@datadog/mobile-react-native":"^2.7.0","@datadog/mobile-react-native-session-replay":"^2.14.8","@dnd-kit/core":"^6.3.1","@dnd-kit/sortable":"^10.0.0","@dnd-kit/utilities":"^3.2.2","@expo/image-utils":"0.8.8","@expo/plist":"0.4.9","@expo/prebuild-config":"54.0.8","@floating-ui/react-native":"^0.10.7","@gorhom/bottom-sheet":"^5.2.14","@gorhom/portal":"^1.0.14","@hyperdrive.bot/fleet-client":"*","@hyperdrive.bot/fleet-expo-two-way-audio":"*","@hyperdrive.bot/fleet-extension-sdk":"*","@hyperdrive.bot/fleet-highlight":"*","@react-native-async-storage/async-storage":"2.2.0","@react-native-masked-view/masked-view":"^0.3.2","@react-native/normalize-colors":"^0.81.5","@react-navigation/native":"^7.1.8","@sentry/electron":"^6.11.0","@sentry/react-native":"^6.20.0","@tanstack/react-query":"^5.90.11","@tanstack/react-virtual":"^3.13.21","@xterm/addon-clipboard":"^0.3.0-beta.213","@xterm/addon-fit":"^0.12.0-beta.213","@xterm/addon-image":"^0.10.0-beta.213","@xterm/addon-ligatures":"0.11.0-beta.213","@xterm/addon-search":"^0.17.0-beta.213","@xterm/addon-unicode11":"^0.10.0-beta.213","@xterm/addon-web-links":"^0.13.0-beta.213","@xterm/addon-webgl":"^0.20.0-beta.212","@xterm/xterm":"^6.1.0-beta.213",buffer:"^6.0.3",expo:"^54.0.18","expo-asset":"~12.0.12","expo-audio":"~1.0.13","expo-background-fetch":"~14.0.9","expo-build-properties":"^1.0.9","expo-camera":"~17.0.10","expo-clipboard":"~8.0.7","expo-constants":"~18.0.9","expo-crypto":"^15.0.8","expo-dev-client":"^6.0.15","expo-document-picker":"~14.0.8","expo-file-system":"~19.0.17","expo-haptics":"~15.0.7","expo-image":"~3.0.10","expo-image-manipulator":"~14.0.8","expo-image-picker":"^17.0.8","expo-keep-awake":"^15.0.7","expo-linking":"~8.0.8","expo-localization":"~17.0.9","expo-notifications":"^0.32.16","expo-router":"~6.0.13","expo-sharing":"^14.0.8","expo-speech":"~14.0.8","expo-speech-recognition":"^56.0.1","expo-splash-screen":"~31.0.10","expo-system-ui":"~6.0.7","expo-task-manager":"~14.0.9","expo-video":"~3.0.16","fast-deep-equal":"^3.1.3",htmlparser2:"^12.0.0",i18next:"^26.3.0","lucide-react-native":"^0.546.0","markdown-it":"^10.0.0","mnemonic-id":"^3.2.7","posthog-js":"^1.431.2","posthog-react-native":"^4.72.0",qrcode:"^1.5.4",react:"19.1.0","react-dom":"19.1.0","react-i18next":"^17.0.8","react-native":"0.81.5","react-native-draggable-flatlist":"^4.0.3","react-native-edge-to-edge":"^1.7.0","react-native-gesture-handler":"~2.28.0","react-native-keyboard-controller":"^1.21.7","react-native-markdown-display":"^7.0.2","react-native-nitro-modules":"0.35.5","react-native-reanimated":"~4.3.1","react-native-safe-area-context":"~5.6.0","react-native-screens":"~4.16.0","react-native-svg":"^15.14.0","react-native-uitextview":"^2.2.0","react-native-unistyles":"^3.2.4","react-native-web":"~0.21.0","react-native-webview":"^13.16.0","react-native-worklets":"~0.8.3","tiny-invariant":"^1.3.3","use-sync-external-store":"^1.6.0",zod:"^4.4.3",zustand:"^5.0.9"},devDependencies:{"@playwright/test":"^1.56.1","@testing-library/dom":"^10.4.1","@testing-library/react":"^16.3.2","@types/chai":"^5.2.2","@types/markdown-it":"^14.1.2","@types/qrcode":"^1.5.6","@types/react":"~19.2.0","@types/ws":"^8.18.1","@vitest/browser":"^4.1.7","@vitest/browser-playwright":"^4.1.7","@vitest/coverage-v8":"^4.1.7","@xterm/headless":"^6.1.0-beta.213",dotenv:"^17.2.3",eslint:"^9.25.0","eslint-config-expo":"~10.0.0",jsdom:"^20.0.3","material-icon-theme":"^5.32.0",playwright:"^1.56.1","serve-sim":"^0.1.40",typescript:"~5.9.2",vitest:"^4.1.6",wrangler:"^4.105.0",ws:"^8.20.0"}}},3415,[]);
15060
+ __d(function(e,t,r,a,o,i,n){o.exports={name:"@hyperdrive.bot/fleet-app",version:"0.3.149",private:!0,main:"index.ts",scripts:{start:"npm run start:expo","start:expo":"cross-env APP_VARIANT=development expo start","reset-project":"node ./scripts/reset-project.js","build:terminal-webview":"node ./scripts/build-terminal-webview-html.mjs","eas-build-post-install":"npm --prefix ../.. run build:app-deps && npm run build:terminal-webview",android:"npm run android:development","android:development":"npm --prefix ../.. run build:client && cross-env APP_VARIANT=development expo prebuild --platform android --non-interactive && cross-env APP_VARIANT=development expo run:android --variant=debug","android:production":"npm --prefix ../.. run build:client && cross-env APP_VARIANT=production expo prebuild --platform android --non-interactive && cross-env APP_VARIANT=production expo run:android --variant=release","android:release":"npm run android:production","android:clear":"node -e \"require('node:fs').rmSync('android', { recursive: true, force: true })\"",ios:"npm --prefix ../.. run build:client && expo run:ios","ios:release":"npm --prefix ../.. run build:client && expo run:ios --configuration Release",web:"npm --prefix ../.. run build:client && concurrently --kill-others --names protocol,client,expo --prefix-colors yellow,blue,magenta \"npm --prefix ../.. run watch:protocol\" \"npm --prefix ../.. run watch:client\" \"npm run web:expo\"","web:expo":"expo start --web",lint:"expo lint",typecheck:"tsgo --noEmit",test:"vitest run","test:browser":"vitest run --project browser","test:e2e":"playwright test --project='Desktop Chrome'","test:e2e:reels":"cross-env NODE_ENV=development playwright test --config playwright.reels.config.ts","test:e2e:real":"cross-env E2E_FORK_PASEO_HOME_FROM=../../.dev/paseo-home playwright test --project=real-provider","test:e2e:ui":"playwright test --ui","test:coverage":"vitest run --project unit --coverage",build:"npm run build:web","build:web":"npm --prefix ../.. run build:app-deps && expo export --platform web --source-maps","profile:workspace-tabs":"node ./scripts/profile-workspace-tabs.mjs","deploy:web":"npm run build:web && wrangler pages deploy dist --project-name paseo-app --branch main"},dependencies:{"@bacons/apple-targets":"4.0.6","@datadog/browser-rum":"^6.23.0","@datadog/browser-rum-react":"^6.23.0","@datadog/mobile-react-native":"^2.7.0","@datadog/mobile-react-native-session-replay":"^2.14.8","@dnd-kit/core":"^6.3.1","@dnd-kit/sortable":"^10.0.0","@dnd-kit/utilities":"^3.2.2","@expo/image-utils":"0.8.8","@expo/plist":"0.4.9","@expo/prebuild-config":"54.0.8","@floating-ui/react-native":"^0.10.7","@gorhom/bottom-sheet":"^5.2.14","@gorhom/portal":"^1.0.14","@hyperdrive.bot/fleet-client":"*","@hyperdrive.bot/fleet-expo-two-way-audio":"*","@hyperdrive.bot/fleet-extension-sdk":"*","@hyperdrive.bot/fleet-highlight":"*","@react-native-async-storage/async-storage":"2.2.0","@react-native-masked-view/masked-view":"^0.3.2","@react-native/normalize-colors":"^0.81.5","@react-navigation/native":"^7.1.8","@sentry/electron":"^6.11.0","@sentry/react-native":"^6.20.0","@tanstack/react-query":"^5.90.11","@tanstack/react-virtual":"^3.13.21","@xterm/addon-clipboard":"^0.3.0-beta.213","@xterm/addon-fit":"^0.12.0-beta.213","@xterm/addon-image":"^0.10.0-beta.213","@xterm/addon-ligatures":"0.11.0-beta.213","@xterm/addon-search":"^0.17.0-beta.213","@xterm/addon-unicode11":"^0.10.0-beta.213","@xterm/addon-web-links":"^0.13.0-beta.213","@xterm/addon-webgl":"^0.20.0-beta.212","@xterm/xterm":"^6.1.0-beta.213",buffer:"^6.0.3",expo:"^54.0.18","expo-asset":"~12.0.12","expo-audio":"~1.0.13","expo-background-fetch":"~14.0.9","expo-build-properties":"^1.0.9","expo-camera":"~17.0.10","expo-clipboard":"~8.0.7","expo-constants":"~18.0.9","expo-crypto":"^15.0.8","expo-dev-client":"^6.0.15","expo-document-picker":"~14.0.8","expo-file-system":"~19.0.17","expo-haptics":"~15.0.7","expo-image":"~3.0.10","expo-image-manipulator":"~14.0.8","expo-image-picker":"^17.0.8","expo-keep-awake":"^15.0.7","expo-linking":"~8.0.8","expo-localization":"~17.0.9","expo-notifications":"^0.32.16","expo-router":"~6.0.13","expo-sharing":"^14.0.8","expo-speech":"~14.0.8","expo-speech-recognition":"^56.0.1","expo-splash-screen":"~31.0.10","expo-system-ui":"~6.0.7","expo-task-manager":"~14.0.9","expo-video":"~3.0.16","fast-deep-equal":"^3.1.3",htmlparser2:"^12.0.0",i18next:"^26.3.0","lucide-react-native":"^0.546.0","markdown-it":"^10.0.0","mnemonic-id":"^3.2.7","posthog-js":"^1.431.2","posthog-react-native":"^4.72.0",qrcode:"^1.5.4",react:"19.1.0","react-dom":"19.1.0","react-i18next":"^17.0.8","react-native":"0.81.5","react-native-draggable-flatlist":"^4.0.3","react-native-edge-to-edge":"^1.7.0","react-native-gesture-handler":"~2.28.0","react-native-keyboard-controller":"^1.21.7","react-native-markdown-display":"^7.0.2","react-native-nitro-modules":"0.35.5","react-native-reanimated":"~4.3.1","react-native-safe-area-context":"~5.6.0","react-native-screens":"~4.16.0","react-native-svg":"^15.14.0","react-native-uitextview":"^2.2.0","react-native-unistyles":"^3.2.4","react-native-web":"~0.21.0","react-native-webview":"^13.16.0","react-native-worklets":"~0.8.3","tiny-invariant":"^1.3.3","use-sync-external-store":"^1.6.0",zod:"^4.4.3",zustand:"^5.0.9"},devDependencies:{"@playwright/test":"^1.56.1","@testing-library/dom":"^10.4.1","@testing-library/react":"^16.3.2","@types/chai":"^5.2.2","@types/markdown-it":"^14.1.2","@types/qrcode":"^1.5.6","@types/react":"~19.2.0","@types/ws":"^8.18.1","@vitest/browser":"^4.1.7","@vitest/browser-playwright":"^4.1.7","@vitest/coverage-v8":"^4.1.7","@xterm/headless":"^6.1.0-beta.213",dotenv:"^17.2.3",eslint:"^9.25.0","eslint-config-expo":"~10.0.0",jsdom:"^20.0.3","material-icon-theme":"^5.32.0",playwright:"^1.56.1","serve-sim":"^0.1.40",typescript:"~5.9.2",vitest:"^4.1.6",wrangler:"^4.105.0",ws:"^8.20.0"}}},3415,[]);
15061
15061
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.shouldUseDesktopDaemon=function(){return(0,n.isElectronRuntime)()},e.getDesktopDaemonStatus=async function(){return c(await(0,t.invokeDesktopCommand)("desktop_daemon_status"))},e.startDesktopDaemon=async function(){return c(await(0,t.invokeDesktopCommand)("start_desktop_daemon"))},e.stopDesktopDaemon=async function(n="manual_ipc"){return c(await(0,t.invokeDesktopCommand)("stop_desktop_daemon",{reason:n}))},e.restartDesktopDaemon=async function(){return c(await(0,t.invokeDesktopCommand)("restart_desktop_daemon"))},e.getDesktopDaemonLogs=async function(){return p(await(0,t.invokeDesktopCommand)("desktop_daemon_logs"))},e.getDesktopDaemonPairing=async function(){return k(await(0,t.invokeDesktopCommand)("desktop_daemon_pairing"))},e.getCliDaemonStatus=async function(){const n=await(0,t.invokeDesktopCommand)("cli_daemon_status");if("string"!=typeof n)throw new Error("Unexpected CLI daemon status response.");return n},e.listenToLocalTransportEvents=async function(t){const u=(0,n.getDesktopHost)()?.events?.on;if("function"!=typeof u)throw new Error("Desktop events API is unavailable.");const c=await u("local-daemon-transport-event",n=>{o(n)&&t({sessionId:s(n.sessionId)??"",kind:s(n.kind)??"error",text:s(n.text),binaryBase64:s(n.binaryBase64),code:l(n.code),reason:s(n.reason),error:s(n.error)})});return"function"==typeof c?c:()=>{}},e.openLocalTransportSession=async function(n){const o=await(0,t.invokeDesktopCommand)("open_local_daemon_transport",n);if("string"!=typeof o||0===o.trim().length)throw new Error("Unexpected local transport session response.");return o},e.sendLocalTransportMessage=async function(n){await(0,t.invokeDesktopCommand)("send_local_daemon_transport_message",Object.assign({sessionId:n.sessionId},n.text?{text:n.text}:{},n.binaryBase64?{binaryBase64:n.binaryBase64}:{}))},e.closeLocalTransportSession=async function(n){await(0,t.invokeDesktopCommand)("close_local_daemon_transport",{sessionId:n})},e.getCliInstallStatus=async function(){return f(await(0,t.invokeDesktopCommand)("get_cli_install_status"))},e.installCli=async function(){return f(await(0,t.invokeDesktopCommand)("install_cli"))},e.getSkillsStatus=async function(){return y(await(0,t.invokeDesktopCommand)("get_skills_status"))},e.installSkills=async function(){return y(await(0,t.invokeDesktopCommand)("install_skills"))},e.updateSkills=async function(){return y(await(0,t.invokeDesktopCommand)("update_skills"))},e.uninstallSkills=async function(){return y(await(0,t.invokeDesktopCommand)("uninstall_skills"))};var n=r(d[0]),t=r(d[1]);function o(n){return"object"==typeof n&&null!==n}function s(n){return"string"==typeof n&&n.trim().length>0?n:null}function l(n){return"number"==typeof n&&Number.isFinite(n)?n:null}function u(n){const t=s(n)?.toLowerCase();switch(t){case"starting":return"starting";case"running":return"running";case"errored":case"error":return"errored";default:return"stopped"}}function c(n){if(!o(n))throw new Error("Unexpected desktop daemon status response.");return{serverId:s(n.serverId)??"",status:u(n.status),listen:s(n.listen),hostname:s(n.hostname),pid:l(n.pid),home:s(n.home)??"",version:s(n.version),desktopManaged:!0===n.desktopManaged,error:s(n.error)}}function p(n){if(!o(n))throw new Error("Unexpected desktop daemon logs response.");return{logPath:s(n.logPath)??"",contents:"string"==typeof n.contents?n.contents:""}}function k(n){if(!o(n))throw new Error("Unexpected desktop daemon pairing response.");return{relayEnabled:!0===n.relayEnabled,url:s(n.url),qr:s(n.qr)}}function f(n){if(!o(n))throw new Error("Unexpected install status response.");return{installed:!0===n.installed}}function w(n){switch(n){case"not-installed":case"up-to-date":case"drift":return n;default:throw new Error(`Unexpected skills status state: ${String(n)}`)}}function _(n){if(!o(n))throw new Error("Unexpected skill op response.");const t=s(n.name);if(!t)throw new Error("Skill op missing name.");switch(n.kind){case"add":return{kind:"add",name:t};case"update":return{kind:"update",name:t};case"delete":return{kind:"delete",name:t};default:throw new Error(`Unexpected skill op kind: ${String(n.kind)}`)}}function y(n){if(!o(n))throw new Error("Unexpected skills status response.");const t=Array.isArray(n.ops)?n.ops.map(_):[];return{state:w(n.state),ops:t}}},3416,[3417,3419]);
15062
15062
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.getDesktopHost=n,e.isElectronRuntime=o,e.isElectronRuntimeMac=function(){if(!o())return!1;if("undefined"==typeof navigator)return!1;const t=n()?.platform?.toLowerCase();if("darwin"===t||"mac"===t||"macos"===t)return!0;const u=navigator.userAgent;return u.includes("Mac OS")||u.includes("Macintosh")},r(d[0]);var t=r(d[1]);function n(){return(0,t.getElectronHost)()}function o(){return null!==n()}},3417,[25,3418]);
15063
15063
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.getElectronHost=function(){if("undefined"==typeof window)return null;const t=window.paseoDesktop;if(!t||"object"!=typeof t)return null;return t}},3418,[]);
@@ -16708,5 +16708,5 @@ __d(function(g,r,_i,a,_m,_e,d){"use strict";var e,t=r(d[0]),n=this&&this.__creat
16708
16708
  __r(694);
16709
16709
  __r(341);
16710
16710
  __r(0);
16711
- //# sourceMappingURL=/_expo/static/js/web/index-88d5f130a09403b86ae8c8c5fd1f97d4.js.map
16712
- //# debugId=2a8807c7-1707-460c-8db1-4c2a7bfcc6c6
16711
+ //# sourceMappingURL=/_expo/static/js/web/index-8747c529e5cb02149fe51570f7cb697b.js.map
16712
+ //# debugId=a3c3235e-e5a8-4c16-a365-7e143904df6d
@@ -191,6 +191,6 @@
191
191
  <body>
192
192
  <noscript>You need to enable JavaScript to run this app.</noscript>
193
193
  <div id="root"></div>
194
- <script src="/_expo/static/js/web/index-88d5f130a09403b86ae8c8c5fd1f97d4.js" defer></script>
194
+ <script src="/_expo/static/js/web/index-8747c529e5cb02149fe51570f7cb697b.js" defer></script>
195
195
  </body>
196
196
  </html>
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperdrive.bot/fleet-server",
3
- "version": "0.3.148",
3
+ "version": "0.3.149",
4
4
  "description": "Paseo backend server",
5
5
  "license": "Apache-2.0",
6
6
  "files": [
@@ -66,11 +66,11 @@
66
66
  "@agentclientprotocol/sdk": "^0.17.1",
67
67
  "@anthropic-ai/claude-agent-sdk": "^0.3.195",
68
68
  "@anthropic-ai/sdk": "^0.104.2",
69
- "@hyperdrive.bot/fleet-client": "0.3.148",
70
- "@hyperdrive.bot/fleet-extension-sdk": "0.3.148",
71
- "@hyperdrive.bot/fleet-highlight": "0.3.148",
72
- "@hyperdrive.bot/fleet-protocol": "0.3.148",
73
- "@hyperdrive.bot/fleet-relay": "0.3.148",
69
+ "@hyperdrive.bot/fleet-client": "0.3.149",
70
+ "@hyperdrive.bot/fleet-extension-sdk": "0.3.149",
71
+ "@hyperdrive.bot/fleet-highlight": "0.3.149",
72
+ "@hyperdrive.bot/fleet-protocol": "0.3.149",
73
+ "@hyperdrive.bot/fleet-relay": "0.3.149",
74
74
  "@isaacs/ttlcache": "^2.1.4",
75
75
  "@modelcontextprotocol/sdk": "^1.20.1",
76
76
  "@opencode-ai/sdk": "1.2.6",