palmier 0.7.3 → 0.7.4
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 +26 -16
- package/dist/device-capabilities.d.ts +9 -0
- package/dist/device-capabilities.js +36 -0
- package/dist/mcp-tools.js +55 -38
- package/dist/pwa/assets/index-BirmfPUC.js +118 -0
- package/dist/pwa/assets/{web-Dwi8DLNK.js → web-Dc9-IiRD.js} +1 -1
- package/dist/pwa/assets/{web-SlBB3mP3.js → web-_b3Dvcvz.js} +1 -1
- package/dist/pwa/index.html +1 -1
- package/dist/pwa/service-worker.js +1 -1
- package/dist/rpc-handler.js +19 -4
- package/dist/transports/http-transport.js +1 -1
- package/package.json +1 -1
- package/palmier-server/pwa/src/components/HostMenu.tsx +125 -11
- package/palmier-server/pwa/src/constants.ts +1 -1
- package/palmier-server/server/src/index.ts +17 -12
- package/palmier-server/server/src/routes/device.ts +4 -4
- package/palmier-server/spec.md +2 -2
- package/src/device-capabilities.ts +55 -0
- package/src/mcp-tools.ts +54 -36
- package/src/rpc-handler.ts +19 -4
- package/src/transports/http-transport.ts +1 -1
- package/dist/location-device.d.ts +0 -8
- package/dist/location-device.js +0 -32
- package/dist/pwa/assets/index-CPIqbV9-.js +0 -118
- package/src/location-device.ts +0 -35
package/src/mcp-tools.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StringCodec, type NatsConnection } from "nats";
|
|
2
2
|
import { registerPending } from "./pending-requests.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getCapabilityDevice } from "./device-capabilities.js";
|
|
4
4
|
import { getNotifications } from "./notification-store.js";
|
|
5
5
|
import { getSmsMessages } from "./sms-store.js";
|
|
6
6
|
import type { HostConfig } from "./types.js";
|
|
@@ -170,14 +170,14 @@ const deviceGeolocationTool: ToolDefinition = {
|
|
|
170
170
|
async handler(_args, ctx) {
|
|
171
171
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
172
172
|
|
|
173
|
-
const
|
|
174
|
-
if (!
|
|
173
|
+
const device = getCapabilityDevice("location");
|
|
174
|
+
if (!device) throw new ToolError("No device has location access enabled", 400);
|
|
175
175
|
|
|
176
176
|
const sc = StringCodec();
|
|
177
177
|
|
|
178
178
|
const ackReply = await ctx.nc.request(
|
|
179
179
|
`host.${ctx.config.hostId}.fcm.geolocation`,
|
|
180
|
-
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken:
|
|
180
|
+
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken })),
|
|
181
181
|
{ timeout: 5_000 },
|
|
182
182
|
);
|
|
183
183
|
const ack = JSON.parse(sc.decode(ackReply.data)) as { ok?: boolean; error?: string };
|
|
@@ -218,11 +218,14 @@ const readContactsTool: ToolDefinition = {
|
|
|
218
218
|
async handler(_args, ctx) {
|
|
219
219
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
220
220
|
|
|
221
|
+
const device = getCapabilityDevice("contacts");
|
|
222
|
+
if (!device) throw new ToolError("No device has contacts access enabled", 400);
|
|
223
|
+
|
|
221
224
|
const sc = StringCodec();
|
|
222
225
|
|
|
223
226
|
const ackReply = await ctx.nc.request(
|
|
224
227
|
`host.${ctx.config.hostId}.fcm.contacts`,
|
|
225
|
-
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, action: "read" })),
|
|
228
|
+
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken, action: "read" })),
|
|
226
229
|
{ timeout: 5_000 },
|
|
227
230
|
);
|
|
228
231
|
const ack = JSON.parse(sc.decode(ackReply.data)) as { ok?: boolean; error?: string };
|
|
@@ -268,6 +271,9 @@ const createContactTool: ToolDefinition = {
|
|
|
268
271
|
async handler(args, ctx) {
|
|
269
272
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
270
273
|
|
|
274
|
+
const device = getCapabilityDevice("contacts");
|
|
275
|
+
if (!device) throw new ToolError("No device has contacts access enabled", 400);
|
|
276
|
+
|
|
271
277
|
const { name, phone, email } = args as { name: string; phone?: string; email?: string };
|
|
272
278
|
if (!name) throw new ToolError("name is required", 400);
|
|
273
279
|
|
|
@@ -276,7 +282,7 @@ const createContactTool: ToolDefinition = {
|
|
|
276
282
|
const ackReply = await ctx.nc.request(
|
|
277
283
|
`host.${ctx.config.hostId}.fcm.contacts`,
|
|
278
284
|
sc.encode(JSON.stringify({
|
|
279
|
-
hostId: ctx.config.hostId, requestId: ctx.sessionId,
|
|
285
|
+
hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken,
|
|
280
286
|
action: "create", name, phone, email,
|
|
281
287
|
})),
|
|
282
288
|
{ timeout: 5_000 },
|
|
@@ -323,13 +329,16 @@ const readCalendarTool: ToolDefinition = {
|
|
|
323
329
|
async handler(args, ctx) {
|
|
324
330
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
325
331
|
|
|
332
|
+
const device = getCapabilityDevice("calendar");
|
|
333
|
+
if (!device) throw new ToolError("No device has calendar access enabled", 400);
|
|
334
|
+
|
|
326
335
|
const { startDate, endDate } = args as { startDate?: number; endDate?: number };
|
|
327
336
|
const sc = StringCodec();
|
|
328
337
|
|
|
329
338
|
const ackReply = await ctx.nc.request(
|
|
330
339
|
`host.${ctx.config.hostId}.fcm.calendar`,
|
|
331
340
|
sc.encode(JSON.stringify({
|
|
332
|
-
hostId: ctx.config.hostId, requestId: ctx.sessionId,
|
|
341
|
+
hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken,
|
|
333
342
|
action: "read",
|
|
334
343
|
...(startDate ? { startDate: String(startDate) } : {}),
|
|
335
344
|
...(endDate ? { endDate: String(endDate) } : {}),
|
|
@@ -381,6 +390,9 @@ const createCalendarEventTool: ToolDefinition = {
|
|
|
381
390
|
async handler(args, ctx) {
|
|
382
391
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
383
392
|
|
|
393
|
+
const device = getCapabilityDevice("calendar");
|
|
394
|
+
if (!device) throw new ToolError("No device has calendar access enabled", 400);
|
|
395
|
+
|
|
384
396
|
const { title, startTime, endTime, location, description } = args as {
|
|
385
397
|
title: string; startTime: number; endTime: number; location?: string; description?: string;
|
|
386
398
|
};
|
|
@@ -391,7 +403,7 @@ const createCalendarEventTool: ToolDefinition = {
|
|
|
391
403
|
const ackReply = await ctx.nc.request(
|
|
392
404
|
`host.${ctx.config.hostId}.fcm.calendar`,
|
|
393
405
|
sc.encode(JSON.stringify({
|
|
394
|
-
hostId: ctx.config.hostId, requestId: ctx.sessionId,
|
|
406
|
+
hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken,
|
|
395
407
|
action: "create",
|
|
396
408
|
title, startTime: String(startTime), endTime: String(endTime),
|
|
397
409
|
...(location ? { location } : {}),
|
|
@@ -424,7 +436,7 @@ const createCalendarEventTool: ToolDefinition = {
|
|
|
424
436
|
};
|
|
425
437
|
|
|
426
438
|
const sendSmsTool: ToolDefinition = {
|
|
427
|
-
name: "send-sms",
|
|
439
|
+
name: "send-sms-message",
|
|
428
440
|
description: [
|
|
429
441
|
"Send an SMS message from the user's mobile device.",
|
|
430
442
|
"Blocks until the device responds (up to 30 seconds).",
|
|
@@ -441,6 +453,9 @@ const sendSmsTool: ToolDefinition = {
|
|
|
441
453
|
async handler(args, ctx) {
|
|
442
454
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
443
455
|
|
|
456
|
+
const device = getCapabilityDevice("sms");
|
|
457
|
+
if (!device) throw new ToolError("No device has SMS access enabled", 400);
|
|
458
|
+
|
|
444
459
|
const { to, body } = args as { to: string; body: string };
|
|
445
460
|
if (!to || !body) throw new ToolError("to and body are required", 400);
|
|
446
461
|
|
|
@@ -449,7 +464,7 @@ const sendSmsTool: ToolDefinition = {
|
|
|
449
464
|
const ackReply = await ctx.nc.request(
|
|
450
465
|
`host.${ctx.config.hostId}.fcm.sms`,
|
|
451
466
|
sc.encode(JSON.stringify({
|
|
452
|
-
hostId: ctx.config.hostId, requestId: ctx.sessionId,
|
|
467
|
+
hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken,
|
|
453
468
|
action: "send", to, body,
|
|
454
469
|
})),
|
|
455
470
|
{ timeout: 5_000 },
|
|
@@ -478,44 +493,41 @@ const sendSmsTool: ToolDefinition = {
|
|
|
478
493
|
},
|
|
479
494
|
};
|
|
480
495
|
|
|
481
|
-
const
|
|
482
|
-
name: "
|
|
496
|
+
const sendAlertTool: ToolDefinition = {
|
|
497
|
+
name: "send-alert",
|
|
483
498
|
description: [
|
|
484
|
-
"
|
|
499
|
+
"Send an alert to the user's mobile device with an alarm sound and full-screen popup.",
|
|
500
|
+
"Use this to urgently get the user's attention. The device will play an alarm sound and show a full-screen dialog even on the lock screen.",
|
|
485
501
|
"Blocks until the device responds (up to 30 seconds).",
|
|
486
502
|
'Response: `{"ok": true}` on success, or `{"error": "..."}` on failure.',
|
|
487
503
|
],
|
|
488
504
|
inputSchema: {
|
|
489
505
|
type: "object",
|
|
490
506
|
properties: {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
label: { type: "string", description: "Alarm label" },
|
|
494
|
-
days: {
|
|
495
|
-
type: "array",
|
|
496
|
-
items: { type: "number" },
|
|
497
|
-
description: "Recurring days (1=Sun, 2=Mon, ..., 7=Sat). Omit for one-time.",
|
|
498
|
-
},
|
|
507
|
+
title: { type: "string", description: "Alert title" },
|
|
508
|
+
description: { type: "string", description: "Alert description/details" },
|
|
499
509
|
},
|
|
500
|
-
required: ["
|
|
510
|
+
required: ["title"],
|
|
501
511
|
},
|
|
502
512
|
async handler(args, ctx) {
|
|
503
513
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
504
514
|
|
|
505
|
-
const
|
|
506
|
-
if (
|
|
515
|
+
const device = getCapabilityDevice("alert");
|
|
516
|
+
if (!device) throw new ToolError("No device has alert access enabled", 400);
|
|
517
|
+
|
|
518
|
+
const { title, description } = args as { title: string; description?: string };
|
|
519
|
+
if (!title) throw new ToolError("title is required", 400);
|
|
507
520
|
|
|
508
521
|
const sc = StringCodec();
|
|
509
522
|
|
|
510
|
-
const payload: Record<string,
|
|
511
|
-
hostId: ctx.config.hostId, requestId: ctx.sessionId,
|
|
512
|
-
|
|
523
|
+
const payload: Record<string, string> = {
|
|
524
|
+
hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken,
|
|
525
|
+
title,
|
|
513
526
|
};
|
|
514
|
-
if (
|
|
515
|
-
if (days?.length) payload.days = days.join(",");
|
|
527
|
+
if (description) payload.description = description;
|
|
516
528
|
|
|
517
529
|
const ackReply = await ctx.nc.request(
|
|
518
|
-
`host.${ctx.config.hostId}.fcm.
|
|
530
|
+
`host.${ctx.config.hostId}.fcm.alert`,
|
|
519
531
|
sc.encode(JSON.stringify(payload)),
|
|
520
532
|
{ timeout: 5_000 },
|
|
521
533
|
);
|
|
@@ -523,7 +535,7 @@ const setAlarmTool: ToolDefinition = {
|
|
|
523
535
|
if (ack.error) throw new ToolError(ack.error, 502);
|
|
524
536
|
|
|
525
537
|
const responsePromise = new Promise<string>((resolve, reject) => {
|
|
526
|
-
const sub = ctx.nc!.subscribe(`host.${ctx.config.hostId}.
|
|
538
|
+
const sub = ctx.nc!.subscribe(`host.${ctx.config.hostId}.alert.${ctx.sessionId}`, { max: 1 });
|
|
527
539
|
const timer = setTimeout(() => {
|
|
528
540
|
sub.unsubscribe();
|
|
529
541
|
reject(new ToolError("Device did not respond within 30 seconds", 504));
|
|
@@ -557,11 +569,14 @@ const readBatteryTool: ToolDefinition = {
|
|
|
557
569
|
async handler(_args, ctx) {
|
|
558
570
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
559
571
|
|
|
572
|
+
const device = getCapabilityDevice("battery");
|
|
573
|
+
if (!device) throw new ToolError("No device has battery access enabled", 400);
|
|
574
|
+
|
|
560
575
|
const sc = StringCodec();
|
|
561
576
|
|
|
562
577
|
const ackReply = await ctx.nc.request(
|
|
563
578
|
`host.${ctx.config.hostId}.fcm.battery`,
|
|
564
|
-
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId })),
|
|
579
|
+
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken })),
|
|
565
580
|
{ timeout: 5_000 },
|
|
566
581
|
);
|
|
567
582
|
const ack = JSON.parse(sc.decode(ackReply.data)) as { ok?: boolean; error?: string };
|
|
@@ -605,6 +620,9 @@ const setRingerModeTool: ToolDefinition = {
|
|
|
605
620
|
async handler(args, ctx) {
|
|
606
621
|
if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
|
|
607
622
|
|
|
623
|
+
const device = getCapabilityDevice("dnd");
|
|
624
|
+
if (!device) throw new ToolError("No device has Do Not Disturb control enabled", 400);
|
|
625
|
+
|
|
608
626
|
const { mode } = args as { mode: string };
|
|
609
627
|
if (!["normal", "vibrate", "silent"].includes(mode)) throw new ToolError("mode must be 'normal', 'vibrate', or 'silent'", 400);
|
|
610
628
|
|
|
@@ -612,7 +630,7 @@ const setRingerModeTool: ToolDefinition = {
|
|
|
612
630
|
|
|
613
631
|
const ackReply = await ctx.nc.request(
|
|
614
632
|
`host.${ctx.config.hostId}.fcm.ringer`,
|
|
615
|
-
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, mode })),
|
|
633
|
+
sc.encode(JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.sessionId, fcmToken: device.fcmToken, mode })),
|
|
616
634
|
{ timeout: 5_000 },
|
|
617
635
|
);
|
|
618
636
|
const ack = JSON.parse(sc.decode(ackReply.data)) as { ok?: boolean; error?: string };
|
|
@@ -639,7 +657,7 @@ const setRingerModeTool: ToolDefinition = {
|
|
|
639
657
|
},
|
|
640
658
|
};
|
|
641
659
|
|
|
642
|
-
export const agentTools: ToolDefinition[] = [notifyTool, requestInputTool, requestConfirmationTool, deviceGeolocationTool, readContactsTool, createContactTool, readCalendarTool, createCalendarEventTool, sendSmsTool,
|
|
660
|
+
export const agentTools: ToolDefinition[] = [notifyTool, requestInputTool, requestConfirmationTool, deviceGeolocationTool, readContactsTool, createContactTool, readCalendarTool, createCalendarEventTool, sendSmsTool, sendAlertTool, readBatteryTool, setRingerModeTool];
|
|
643
661
|
export const agentToolMap = new Map<string, ToolDefinition>(agentTools.map((t) => [t.name, t]));
|
|
644
662
|
|
|
645
663
|
// ── MCP Resources ─────────────────────────────────────────────────────
|
|
@@ -671,14 +689,14 @@ const deviceNotificationsResource: ResourceDefinition = {
|
|
|
671
689
|
};
|
|
672
690
|
|
|
673
691
|
const deviceSmsResource: ResourceDefinition = {
|
|
674
|
-
uri: "sms://device",
|
|
692
|
+
uri: "sms-messages://device",
|
|
675
693
|
name: "Device SMS",
|
|
676
694
|
description: [
|
|
677
695
|
"Get recent SMS messages from the user's Android device.",
|
|
678
696
|
"Response: JSON array of message objects with `id`, `sender`, `body`, `timestamp`.",
|
|
679
697
|
],
|
|
680
698
|
mimeType: "application/json",
|
|
681
|
-
restPath: "/sms",
|
|
699
|
+
restPath: "/sms-messages",
|
|
682
700
|
read: getSmsMessages,
|
|
683
701
|
};
|
|
684
702
|
|
package/src/rpc-handler.ts
CHANGED
|
@@ -11,7 +11,7 @@ import crossSpawn from "cross-spawn";
|
|
|
11
11
|
import { getAgent } from "./agents/agent.js";
|
|
12
12
|
import { validateClient } from "./client-store.js";
|
|
13
13
|
import { publishHostEvent } from "./events.js";
|
|
14
|
-
import {
|
|
14
|
+
import { getCapabilityDevice, setCapabilityDevice, clearCapabilityDevice, type DeviceCapability } from "./device-capabilities.js";
|
|
15
15
|
import { currentVersion, performUpdate } from "./update-checker.js";
|
|
16
16
|
import { parseReportFiles, parseTaskOutcome, stripPalmierMarkers } from "./commands/run.js";
|
|
17
17
|
import type { HostConfig, ParsedTask, RpcMessage, ConversationMessage } from "./types.js";
|
|
@@ -163,7 +163,7 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
163
163
|
switch (request.method) {
|
|
164
164
|
case "task.list": {
|
|
165
165
|
const tasks = listTasks(config.projectRoot);
|
|
166
|
-
const locDevice =
|
|
166
|
+
const locDevice = getCapabilityDevice("location");
|
|
167
167
|
return {
|
|
168
168
|
tasks: tasks.map((task) => flattenTask(task)),
|
|
169
169
|
agents: config.agents ?? [],
|
|
@@ -652,12 +652,27 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
652
652
|
const params = request.params as { fcmToken: string };
|
|
653
653
|
if (!params.fcmToken) return { error: "fcmToken is required" };
|
|
654
654
|
const clientToken = request.clientToken ?? "";
|
|
655
|
-
|
|
655
|
+
setCapabilityDevice("location", clientToken, params.fcmToken);
|
|
656
656
|
return { ok: true };
|
|
657
657
|
}
|
|
658
658
|
|
|
659
659
|
case "device.location.disable": {
|
|
660
|
-
|
|
660
|
+
clearCapabilityDevice("location");
|
|
661
|
+
return { ok: true };
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
case "device.capability.enable": {
|
|
665
|
+
const params = request.params as { capability: DeviceCapability; fcmToken: string };
|
|
666
|
+
if (!params.capability || !params.fcmToken) return { error: "capability and fcmToken are required" };
|
|
667
|
+
const clientToken = request.clientToken ?? "";
|
|
668
|
+
setCapabilityDevice(params.capability, clientToken, params.fcmToken);
|
|
669
|
+
return { ok: true };
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
case "device.capability.disable": {
|
|
673
|
+
const params = request.params as { capability: DeviceCapability };
|
|
674
|
+
if (!params.capability) return { error: "capability is required" };
|
|
675
|
+
clearCapabilityDevice(params.capability);
|
|
661
676
|
return { ok: true };
|
|
662
677
|
}
|
|
663
678
|
|
|
@@ -125,7 +125,7 @@ export async function startHttpTransport(
|
|
|
125
125
|
|
|
126
126
|
// Wire up resource change listeners
|
|
127
127
|
onNotificationsChanged(() => broadcastResourceUpdated("notifications://device"));
|
|
128
|
-
onSmsChanged(() => broadcastResourceUpdated("sms://device"));
|
|
128
|
+
onSmsChanged(() => broadcastResourceUpdated("sms-messages://device"));
|
|
129
129
|
|
|
130
130
|
// If a pairing code is provided, pre-register it
|
|
131
131
|
if (pairingCode) {
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export interface LocationDevice {
|
|
2
|
-
clientToken: string;
|
|
3
|
-
fcmToken: string;
|
|
4
|
-
}
|
|
5
|
-
export declare function getLocationDevice(): LocationDevice | null;
|
|
6
|
-
export declare function setLocationDevice(clientToken: string, fcmToken: string): void;
|
|
7
|
-
export declare function clearLocationDevice(): void;
|
|
8
|
-
//# sourceMappingURL=location-device.d.ts.map
|
package/dist/location-device.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import { CONFIG_DIR } from "./config.js";
|
|
4
|
-
const LOCATION_FILE = path.join(CONFIG_DIR, "location-device.json");
|
|
5
|
-
export function getLocationDevice() {
|
|
6
|
-
try {
|
|
7
|
-
if (!fs.existsSync(LOCATION_FILE))
|
|
8
|
-
return null;
|
|
9
|
-
const raw = fs.readFileSync(LOCATION_FILE, "utf-8");
|
|
10
|
-
const data = JSON.parse(raw);
|
|
11
|
-
if (!data.clientToken || !data.fcmToken)
|
|
12
|
-
return null;
|
|
13
|
-
return data;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
export function setLocationDevice(clientToken, fcmToken) {
|
|
20
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
21
|
-
fs.writeFileSync(LOCATION_FILE, JSON.stringify({ clientToken, fcmToken }, null, 2), "utf-8");
|
|
22
|
-
}
|
|
23
|
-
export function clearLocationDevice() {
|
|
24
|
-
try {
|
|
25
|
-
if (fs.existsSync(LOCATION_FILE))
|
|
26
|
-
fs.unlinkSync(LOCATION_FILE);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
// ignore
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=location-device.js.map
|