@elizaos/plugin-phone 2.0.3-beta.2 → 2.0.3-beta.3
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/dist/companion/components/Chat.d.ts +14 -0
- package/dist/companion/components/Chat.d.ts.map +1 -0
- package/dist/companion/components/Chat.js +195 -0
- package/dist/companion/components/Chat.js.map +1 -0
- package/dist/companion/components/Pairing.d.ts +9 -0
- package/dist/companion/components/Pairing.d.ts.map +1 -0
- package/dist/companion/components/Pairing.js +175 -0
- package/dist/companion/components/Pairing.js.map +1 -0
- package/dist/companion/components/PhoneCompanionApp.d.ts +9 -0
- package/dist/companion/components/PhoneCompanionApp.d.ts.map +1 -0
- package/dist/companion/components/PhoneCompanionApp.js +174 -0
- package/dist/companion/components/PhoneCompanionApp.js.map +1 -0
- package/dist/companion/components/RemoteSession.d.ts +9 -0
- package/dist/companion/components/RemoteSession.d.ts.map +1 -0
- package/dist/companion/components/RemoteSession.js +382 -0
- package/dist/companion/components/RemoteSession.js.map +1 -0
- package/dist/companion/components/index.d.ts +5 -0
- package/dist/companion/components/index.d.ts.map +1 -0
- package/dist/companion/components/index.js +11 -0
- package/dist/companion/components/index.js.map +1 -0
- package/dist/companion/index.d.ts +14 -0
- package/dist/companion/index.d.ts.map +1 -0
- package/dist/companion/index.js +12 -0
- package/dist/companion/index.js.map +1 -0
- package/dist/companion/services/eliza-intent.d.ts +63 -0
- package/dist/companion/services/eliza-intent.d.ts.map +1 -0
- package/dist/companion/services/eliza-intent.js +52 -0
- package/dist/companion/services/eliza-intent.js.map +1 -0
- package/dist/companion/services/env.d.ts +11 -0
- package/dist/companion/services/env.d.ts.map +1 -0
- package/dist/companion/services/env.js +20 -0
- package/dist/companion/services/env.js.map +1 -0
- package/dist/companion/services/index.d.ts +14 -0
- package/dist/companion/services/index.d.ts.map +1 -0
- package/dist/companion/services/index.js +29 -0
- package/dist/companion/services/index.js.map +1 -0
- package/dist/companion/services/intent-bridge.d.ts +11 -0
- package/dist/companion/services/intent-bridge.d.ts.map +1 -0
- package/dist/companion/services/intent-bridge.js +15 -0
- package/dist/companion/services/intent-bridge.js.map +1 -0
- package/dist/companion/services/logger.d.ts +14 -0
- package/dist/companion/services/logger.d.ts.map +1 -0
- package/dist/companion/services/logger.js +50 -0
- package/dist/companion/services/logger.js.map +1 -0
- package/dist/companion/services/navigation.d.ts +17 -0
- package/dist/companion/services/navigation.d.ts.map +1 -0
- package/dist/companion/services/navigation.js +104 -0
- package/dist/companion/services/navigation.js.map +1 -0
- package/dist/companion/services/push.d.ts +27 -0
- package/dist/companion/services/push.d.ts.map +1 -0
- package/dist/companion/services/push.js +101 -0
- package/dist/companion/services/push.js.map +1 -0
- package/dist/companion/services/session-client.d.ts +114 -0
- package/dist/companion/services/session-client.d.ts.map +1 -0
- package/dist/companion/services/session-client.js +197 -0
- package/dist/companion/services/session-client.js.map +1 -0
- package/dist/components/PhoneAppView.d.ts +18 -0
- package/dist/components/PhoneAppView.d.ts.map +1 -0
- package/dist/components/PhoneAppView.helpers.d.ts +12 -0
- package/dist/components/PhoneAppView.helpers.d.ts.map +1 -0
- package/dist/components/PhoneAppView.helpers.js +44 -0
- package/dist/components/PhoneAppView.helpers.js.map +1 -0
- package/dist/components/PhoneAppView.interact.d.ts +2 -0
- package/dist/components/PhoneAppView.interact.d.ts.map +1 -0
- package/dist/components/PhoneAppView.interact.js +63 -0
- package/dist/components/PhoneAppView.interact.js.map +1 -0
- package/dist/components/PhoneAppView.js +566 -0
- package/dist/components/PhoneAppView.js.map +1 -0
- package/dist/components/PhoneSpatialView.d.ts +43 -0
- package/dist/components/PhoneSpatialView.d.ts.map +1 -0
- package/dist/components/PhoneSpatialView.js +180 -0
- package/dist/components/PhoneSpatialView.js.map +1 -0
- package/dist/components/PhoneView.d.ts +13 -0
- package/dist/components/PhoneView.d.ts.map +1 -0
- package/dist/components/PhoneView.js +161 -0
- package/dist/components/PhoneView.js.map +1 -0
- package/dist/components/phone-app.d.ts +13 -0
- package/dist/components/phone-app.d.ts.map +1 -0
- package/dist/components/phone-app.js +20 -0
- package/dist/components/phone-app.js.map +1 -0
- package/dist/components/phone-view-bundle.d.ts +3 -0
- package/dist/components/phone-view-bundle.d.ts.map +1 -0
- package/dist/components/phone-view-bundle.js +7 -0
- package/dist/components/phone-view-bundle.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +17 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +48 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/call-log.d.ts +11 -0
- package/dist/providers/call-log.d.ts.map +1 -0
- package/dist/providers/call-log.js +66 -0
- package/dist/providers/call-log.js.map +1 -0
- package/dist/register-companion-page.d.ts +13 -0
- package/dist/register-companion-page.d.ts.map +1 -0
- package/dist/register-companion-page.js +12 -0
- package/dist/register-companion-page.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +21 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +9 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +11 -0
- package/dist/register.js.map +1 -0
- package/dist/twilio.d.ts +33 -0
- package/dist/twilio.d.ts.map +1 -0
- package/dist/twilio.js +238 -0
- package/dist/twilio.js.map +1 -0
- package/dist/ui.d.ts +8 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +23 -0
- package/dist/ui.js.map +1 -0
- package/dist/views/bundle.js +407 -0
- package/dist/views/bundle.js.map +1 -0
- package/dist/views/dist-Cd2YtKy4.js +270 -0
- package/dist/views/dist-Cd2YtKy4.js.map +1 -0
- package/dist/views/web-TGRkTsa8.js +58 -0
- package/dist/views/web-TGRkTsa8.js.map +1 -0
- package/package.json +9 -8
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PhoneSpatialView - the phone surface authored once with the spatial
|
|
3
|
+
* vocabulary, so it renders correctly wherever it is displayed:
|
|
4
|
+
*
|
|
5
|
+
* - GUI / XR - mounted in `<SpatialSurface>` (DOM; XR scales up).
|
|
6
|
+
* - TUI - rendered to real terminal lines by the agent terminal, via
|
|
7
|
+
* `registerSpatialTerminalView` (see `register-terminal-view.ts`).
|
|
8
|
+
*
|
|
9
|
+
* It is purely presentational (a snapshot + an action callback in, primitives
|
|
10
|
+
* out) and imports only the cross-modality primitives plus a type-only view of
|
|
11
|
+
* the native call log, so it is safe to render in the Node agent process where
|
|
12
|
+
* the terminal lives (no Capacitor runtime import).
|
|
13
|
+
*/
|
|
14
|
+
import type { CallLogEntry } from "@elizaos/capacitor-phone";
|
|
15
|
+
export interface PhoneCallRow {
|
|
16
|
+
id: string;
|
|
17
|
+
/** Display name: cached contact name, else the number. */
|
|
18
|
+
name: string;
|
|
19
|
+
number: string;
|
|
20
|
+
/** Pre-formatted relative/short time. */
|
|
21
|
+
when: string;
|
|
22
|
+
direction: "incoming" | "outgoing" | "missed" | "voicemail" | "unknown";
|
|
23
|
+
}
|
|
24
|
+
export interface PhoneSnapshot {
|
|
25
|
+
callReady: boolean;
|
|
26
|
+
dialed: string;
|
|
27
|
+
calls: PhoneCallRow[];
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
error?: string | null;
|
|
30
|
+
}
|
|
31
|
+
/** Map a native call-log entry to the presentational row shape. */
|
|
32
|
+
export declare function toPhoneCallRow(entry: CallLogEntry, when: string): PhoneCallRow;
|
|
33
|
+
export interface PhoneSpatialViewProps {
|
|
34
|
+
snapshot: PhoneSnapshot;
|
|
35
|
+
/**
|
|
36
|
+
* Dispatched action ids: `key:<digit>` (digit, `*`, `#`, or `+`), `call`,
|
|
37
|
+
* `open-dialer`, `backspace`, `contacts`, `call-number:<number>` (place a
|
|
38
|
+
* call to a recent-call row), `refresh`.
|
|
39
|
+
*/
|
|
40
|
+
onAction?: (action: string) => void;
|
|
41
|
+
}
|
|
42
|
+
export declare function PhoneSpatialView({ snapshot, onAction, }: PhoneSpatialViewProps): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
//# sourceMappingURL=PhoneSpatialView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhoneSpatialView.d.ts","sourceRoot":"","sources":["../../src/components/PhoneSpatialView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAY7D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;CACzE;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAgCD,mEAAmE;AACnE,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,GACX,YAAY,CA+Bd;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,aAAa,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,QAAQ,GACT,EAAE,qBAAqB,2CA+HvB"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
Divider,
|
|
6
|
+
HStack,
|
|
7
|
+
List,
|
|
8
|
+
Text,
|
|
9
|
+
VStack
|
|
10
|
+
} from "@elizaos/ui/spatial";
|
|
11
|
+
const DIAL_KEYS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"];
|
|
12
|
+
function directionTone(direction) {
|
|
13
|
+
switch (direction) {
|
|
14
|
+
case "missed":
|
|
15
|
+
return "danger";
|
|
16
|
+
case "incoming":
|
|
17
|
+
return "success";
|
|
18
|
+
case "outgoing":
|
|
19
|
+
return "primary";
|
|
20
|
+
default:
|
|
21
|
+
return "muted";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function directionMark(direction) {
|
|
25
|
+
switch (direction) {
|
|
26
|
+
case "missed":
|
|
27
|
+
return "x";
|
|
28
|
+
case "incoming":
|
|
29
|
+
return "<";
|
|
30
|
+
case "outgoing":
|
|
31
|
+
return ">";
|
|
32
|
+
case "voicemail":
|
|
33
|
+
return "o";
|
|
34
|
+
default:
|
|
35
|
+
return ".";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function toPhoneCallRow(entry, when) {
|
|
39
|
+
const type = String(entry.type ?? "").toLowerCase();
|
|
40
|
+
let direction;
|
|
41
|
+
switch (type) {
|
|
42
|
+
case "incoming":
|
|
43
|
+
case "answered_externally":
|
|
44
|
+
direction = "incoming";
|
|
45
|
+
break;
|
|
46
|
+
case "outgoing":
|
|
47
|
+
direction = "outgoing";
|
|
48
|
+
break;
|
|
49
|
+
case "missed":
|
|
50
|
+
case "rejected":
|
|
51
|
+
case "blocked":
|
|
52
|
+
direction = "missed";
|
|
53
|
+
break;
|
|
54
|
+
case "voicemail":
|
|
55
|
+
direction = "voicemail";
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
direction = "unknown";
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
id: entry.id,
|
|
62
|
+
name: entry.cachedName?.trim() || entry.number || "Unknown",
|
|
63
|
+
number: entry.number ?? "",
|
|
64
|
+
when,
|
|
65
|
+
direction
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function PhoneSpatialView({
|
|
69
|
+
snapshot,
|
|
70
|
+
onAction
|
|
71
|
+
}) {
|
|
72
|
+
const dispatch = (action) => () => onAction?.(action);
|
|
73
|
+
return /* @__PURE__ */ jsxs(Card, { gap: 1, padding: 1, children: [
|
|
74
|
+
/* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
|
|
75
|
+
/* @__PURE__ */ jsx(
|
|
76
|
+
Text,
|
|
77
|
+
{
|
|
78
|
+
style: "caption",
|
|
79
|
+
tone: snapshot.callReady ? "success" : "danger",
|
|
80
|
+
grow: 1,
|
|
81
|
+
children: snapshot.callReady ? "call-ready" : "call-blocked"
|
|
82
|
+
}
|
|
83
|
+
),
|
|
84
|
+
/* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", children: snapshot.loading ? "loading" : `${snapshot.calls.length} recent` })
|
|
85
|
+
] }),
|
|
86
|
+
snapshot.error ? /* @__PURE__ */ jsx(Text, { tone: "danger", style: "caption", children: snapshot.error }) : null,
|
|
87
|
+
/* @__PURE__ */ jsx(Divider, { label: "dialer" }),
|
|
88
|
+
/* @__PURE__ */ jsx(Text, { style: "subheading", align: "center", children: snapshot.dialed || " " }),
|
|
89
|
+
/* @__PURE__ */ jsx(HStack, { gap: 1, wrap: true, justify: "center", children: DIAL_KEYS.map((k) => /* @__PURE__ */ jsx(
|
|
90
|
+
Button,
|
|
91
|
+
{
|
|
92
|
+
variant: "outline",
|
|
93
|
+
tone: "default",
|
|
94
|
+
width: 5,
|
|
95
|
+
agent: `key-${k}`,
|
|
96
|
+
onPress: dispatch(`key:${k}`),
|
|
97
|
+
children: k
|
|
98
|
+
},
|
|
99
|
+
k
|
|
100
|
+
)) }),
|
|
101
|
+
/* @__PURE__ */ jsxs(HStack, { gap: 1, wrap: true, children: [
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
Button,
|
|
104
|
+
{
|
|
105
|
+
variant: "outline",
|
|
106
|
+
tone: "default",
|
|
107
|
+
width: 5,
|
|
108
|
+
agent: "plus",
|
|
109
|
+
onPress: dispatch("key:+"),
|
|
110
|
+
children: "+"
|
|
111
|
+
}
|
|
112
|
+
),
|
|
113
|
+
/* @__PURE__ */ jsx(Button, { grow: 1, agent: "call", onPress: dispatch("call"), children: "Call" }),
|
|
114
|
+
/* @__PURE__ */ jsx(
|
|
115
|
+
Button,
|
|
116
|
+
{
|
|
117
|
+
variant: "outline",
|
|
118
|
+
tone: "default",
|
|
119
|
+
grow: 1,
|
|
120
|
+
agent: "open-dialer",
|
|
121
|
+
onPress: dispatch("open-dialer"),
|
|
122
|
+
children: "Open dialer"
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
/* @__PURE__ */ jsx(
|
|
126
|
+
Button,
|
|
127
|
+
{
|
|
128
|
+
variant: "ghost",
|
|
129
|
+
tone: "danger",
|
|
130
|
+
agent: "backspace",
|
|
131
|
+
onPress: dispatch("backspace"),
|
|
132
|
+
children: "Del"
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
] }),
|
|
136
|
+
/* @__PURE__ */ jsx(HStack, { gap: 1, justify: "center", children: /* @__PURE__ */ jsx(
|
|
137
|
+
Button,
|
|
138
|
+
{
|
|
139
|
+
variant: "ghost",
|
|
140
|
+
tone: "default",
|
|
141
|
+
agent: "contacts",
|
|
142
|
+
onPress: dispatch("contacts"),
|
|
143
|
+
children: "Contacts"
|
|
144
|
+
}
|
|
145
|
+
) }),
|
|
146
|
+
/* @__PURE__ */ jsx(Divider, { label: "recent" }),
|
|
147
|
+
snapshot.calls.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, children: snapshot.calls.slice(0, 8).map((call) => /* @__PURE__ */ jsxs(
|
|
148
|
+
HStack,
|
|
149
|
+
{
|
|
150
|
+
gap: 1,
|
|
151
|
+
align: "center",
|
|
152
|
+
agent: `call-${call.id}`,
|
|
153
|
+
children: [
|
|
154
|
+
/* @__PURE__ */ jsx(Text, { tone: directionTone(call.direction), children: directionMark(call.direction) }),
|
|
155
|
+
/* @__PURE__ */ jsxs(VStack, { gap: 0, grow: 1, children: [
|
|
156
|
+
/* @__PURE__ */ jsx(Text, { bold: true, wrap: false, children: call.name }),
|
|
157
|
+
call.name !== call.number ? /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", wrap: false, children: call.number }) : null
|
|
158
|
+
] }),
|
|
159
|
+
/* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", children: call.when }),
|
|
160
|
+
/* @__PURE__ */ jsx(
|
|
161
|
+
Button,
|
|
162
|
+
{
|
|
163
|
+
variant: "ghost",
|
|
164
|
+
tone: "primary",
|
|
165
|
+
agent: `call:${call.id}`,
|
|
166
|
+
onPress: dispatch(`call-number:${call.number}`),
|
|
167
|
+
children: "Call"
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
call.id
|
|
173
|
+
)) })
|
|
174
|
+
] });
|
|
175
|
+
}
|
|
176
|
+
export {
|
|
177
|
+
PhoneSpatialView,
|
|
178
|
+
toPhoneCallRow
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=PhoneSpatialView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/PhoneSpatialView.tsx"],"sourcesContent":["/**\n * PhoneSpatialView - the phone surface authored once with the spatial\n * vocabulary, so it renders correctly wherever it is displayed:\n *\n * - GUI / XR - mounted in `<SpatialSurface>` (DOM; XR scales up).\n * - TUI - rendered to real terminal lines by the agent terminal, via\n * `registerSpatialTerminalView` (see `register-terminal-view.ts`).\n *\n * It is purely presentational (a snapshot + an action callback in, primitives\n * out) and imports only the cross-modality primitives plus a type-only view of\n * the native call log, so it is safe to render in the Node agent process where\n * the terminal lives (no Capacitor runtime import).\n */\n\nimport type { CallLogEntry } from \"@elizaos/capacitor-phone\";\nimport {\n Button,\n Card,\n Divider,\n HStack,\n List,\n type SpatialTone,\n Text,\n VStack,\n} from \"@elizaos/ui/spatial\";\n\nexport interface PhoneCallRow {\n id: string;\n /** Display name: cached contact name, else the number. */\n name: string;\n number: string;\n /** Pre-formatted relative/short time. */\n when: string;\n direction: \"incoming\" | \"outgoing\" | \"missed\" | \"voicemail\" | \"unknown\";\n}\n\nexport interface PhoneSnapshot {\n callReady: boolean;\n dialed: string;\n calls: PhoneCallRow[];\n loading?: boolean;\n error?: string | null;\n}\n\nconst DIAL_KEYS = [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"*\", \"0\", \"#\"];\n\nfunction directionTone(direction: PhoneCallRow[\"direction\"]): SpatialTone {\n switch (direction) {\n case \"missed\":\n return \"danger\";\n case \"incoming\":\n return \"success\";\n case \"outgoing\":\n return \"primary\";\n default:\n return \"muted\";\n }\n}\n\nfunction directionMark(direction: PhoneCallRow[\"direction\"]): string {\n switch (direction) {\n case \"missed\":\n return \"x\";\n case \"incoming\":\n return \"<\";\n case \"outgoing\":\n return \">\";\n case \"voicemail\":\n return \"o\";\n default:\n return \".\";\n }\n}\n\n/** Map a native call-log entry to the presentational row shape. */\nexport function toPhoneCallRow(\n entry: CallLogEntry,\n when: string,\n): PhoneCallRow {\n const type = String(entry.type ?? \"\").toLowerCase();\n // Collapse the native call-log types down to the four directions the row\n // renders: rejected/blocked read as missed, answered_externally as incoming.\n let direction: PhoneCallRow[\"direction\"];\n switch (type) {\n case \"incoming\":\n case \"answered_externally\":\n direction = \"incoming\";\n break;\n case \"outgoing\":\n direction = \"outgoing\";\n break;\n case \"missed\":\n case \"rejected\":\n case \"blocked\":\n direction = \"missed\";\n break;\n case \"voicemail\":\n direction = \"voicemail\";\n break;\n default:\n direction = \"unknown\";\n }\n return {\n id: entry.id,\n name: entry.cachedName?.trim() || entry.number || \"Unknown\",\n number: entry.number ?? \"\",\n when,\n direction,\n };\n}\n\nexport interface PhoneSpatialViewProps {\n snapshot: PhoneSnapshot;\n /**\n * Dispatched action ids: `key:<digit>` (digit, `*`, `#`, or `+`), `call`,\n * `open-dialer`, `backspace`, `contacts`, `call-number:<number>` (place a\n * call to a recent-call row), `refresh`.\n */\n onAction?: (action: string) => void;\n}\n\nexport function PhoneSpatialView({\n snapshot,\n onAction,\n}: PhoneSpatialViewProps) {\n const dispatch = (action: string) => () => onAction?.(action);\n return (\n <Card gap={1} padding={1}>\n <HStack gap={1} align=\"center\">\n <Text\n style=\"caption\"\n tone={snapshot.callReady ? \"success\" : \"danger\"}\n grow={1}\n >\n {snapshot.callReady ? \"call-ready\" : \"call-blocked\"}\n </Text>\n <Text style=\"caption\" tone=\"muted\">\n {snapshot.loading ? \"loading\" : `${snapshot.calls.length} recent`}\n </Text>\n </HStack>\n\n {snapshot.error ? (\n <Text tone=\"danger\" style=\"caption\">\n {snapshot.error}\n </Text>\n ) : null}\n\n <Divider label=\"dialer\" />\n <Text style=\"subheading\" align=\"center\">\n {snapshot.dialed || \" \"}\n </Text>\n <HStack gap={1} wrap justify=\"center\">\n {DIAL_KEYS.map((k) => (\n <Button\n key={k}\n variant=\"outline\"\n tone=\"default\"\n width={5}\n agent={`key-${k}`}\n onPress={dispatch(`key:${k}`)}\n >\n {k}\n </Button>\n ))}\n </HStack>\n <HStack gap={1} wrap>\n <Button\n variant=\"outline\"\n tone=\"default\"\n width={5}\n agent=\"plus\"\n onPress={dispatch(\"key:+\")}\n >\n +\n </Button>\n <Button grow={1} agent=\"call\" onPress={dispatch(\"call\")}>\n Call\n </Button>\n <Button\n variant=\"outline\"\n tone=\"default\"\n grow={1}\n agent=\"open-dialer\"\n onPress={dispatch(\"open-dialer\")}\n >\n Open dialer\n </Button>\n <Button\n variant=\"ghost\"\n tone=\"danger\"\n agent=\"backspace\"\n onPress={dispatch(\"backspace\")}\n >\n Del\n </Button>\n </HStack>\n <HStack gap={1} justify=\"center\">\n <Button\n variant=\"ghost\"\n tone=\"default\"\n agent=\"contacts\"\n onPress={dispatch(\"contacts\")}\n >\n Contacts\n </Button>\n </HStack>\n\n <Divider label=\"recent\" />\n {snapshot.calls.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n None\n </Text>\n ) : (\n <List gap={0}>\n {snapshot.calls.slice(0, 8).map((call) => (\n <HStack\n key={call.id}\n gap={1}\n align=\"center\"\n agent={`call-${call.id}`}\n >\n <Text tone={directionTone(call.direction)}>\n {directionMark(call.direction)}\n </Text>\n <VStack gap={0} grow={1}>\n <Text bold wrap={false}>\n {call.name}\n </Text>\n {call.name !== call.number ? (\n <Text style=\"caption\" tone=\"muted\" wrap={false}>\n {call.number}\n </Text>\n ) : null}\n </VStack>\n <Text style=\"caption\" tone=\"muted\">\n {call.when}\n </Text>\n <Button\n variant=\"ghost\"\n tone=\"primary\"\n agent={`call:${call.id}`}\n onPress={dispatch(`call-number:${call.number}`)}\n >\n Call\n </Button>\n </HStack>\n ))}\n </List>\n )}\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PhoneView — the single GUI/XR data wrapper for the Phone surface.
|
|
3
|
+
*
|
|
4
|
+
* It owns the live Android data (call-log fetch, dialer state, pending-number
|
|
5
|
+
* handoff, place-call / open-dialer / Contacts-link actions) and renders the
|
|
6
|
+
* one presentational {@link PhoneSpatialView} inside a {@link SpatialSurface}.
|
|
7
|
+
* Omitting the `modality` prop lets `SpatialSurface` auto-detect GUI vs XR via
|
|
8
|
+
* `window.__elizaXRContext`, so the SAME component serves both surfaces. The
|
|
9
|
+
* TUI surface renders the same `PhoneSpatialView` through the terminal registry
|
|
10
|
+
* (see `register-terminal-view.tsx`).
|
|
11
|
+
*/
|
|
12
|
+
export declare function PhoneView(): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=PhoneView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhoneView.d.ts","sourceRoot":"","sources":["../../src/components/PhoneView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA+CH,wBAAgB,SAAS,4CA0IxB"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Phone } from "@elizaos/capacitor-phone";
|
|
3
|
+
import { consumePendingPhoneNumber } from "@elizaos/ui/app-navigate-view";
|
|
4
|
+
import { SpatialSurface } from "@elizaos/ui/spatial";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { normalizeNumber } from "./PhoneAppView.helpers.js";
|
|
7
|
+
import {
|
|
8
|
+
PhoneSpatialView,
|
|
9
|
+
toPhoneCallRow
|
|
10
|
+
} from "./PhoneSpatialView.js";
|
|
11
|
+
function formatWhen(epochMs) {
|
|
12
|
+
const date = new Date(epochMs);
|
|
13
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
14
|
+
const now = /* @__PURE__ */ new Date();
|
|
15
|
+
const sameDay = date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate();
|
|
16
|
+
if (sameDay) {
|
|
17
|
+
return date.toLocaleTimeString(void 0, {
|
|
18
|
+
hour: "2-digit",
|
|
19
|
+
minute: "2-digit"
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return date.toLocaleString(void 0, {
|
|
23
|
+
month: "short",
|
|
24
|
+
day: "numeric",
|
|
25
|
+
hour: "2-digit",
|
|
26
|
+
minute: "2-digit"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function openContacts() {
|
|
30
|
+
if (typeof window === "undefined") return;
|
|
31
|
+
window.dispatchEvent(
|
|
32
|
+
new CustomEvent("eliza:navigate:view", {
|
|
33
|
+
detail: { viewId: "contacts", viewPath: "/contacts" }
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function PhoneView() {
|
|
38
|
+
const [dialed, setDialed] = useState("");
|
|
39
|
+
const [callReady, setCallReady] = useState(false);
|
|
40
|
+
const [calls, setCalls] = useState([]);
|
|
41
|
+
const [loading, setLoading] = useState(false);
|
|
42
|
+
const [error, setError] = useState(null);
|
|
43
|
+
const refreshCalls = useCallback(async () => {
|
|
44
|
+
setLoading(true);
|
|
45
|
+
setError(null);
|
|
46
|
+
try {
|
|
47
|
+
const status = await Phone.requestPermissions().catch(() => null);
|
|
48
|
+
if (status && status.phone !== "granted") {
|
|
49
|
+
setCalls([]);
|
|
50
|
+
setCallReady(false);
|
|
51
|
+
setError(
|
|
52
|
+
"Phone access is needed for recent calls and dialing. Grant it in your device settings, then retry."
|
|
53
|
+
);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const [phoneStatus, { calls: fetched }] = await Promise.all([
|
|
57
|
+
Phone.getStatus().catch(() => null),
|
|
58
|
+
Phone.listRecentCalls({ limit: 50 })
|
|
59
|
+
]);
|
|
60
|
+
setCallReady(phoneStatus?.canPlaceCalls ?? true);
|
|
61
|
+
setCalls(
|
|
62
|
+
fetched.map((entry) => toPhoneCallRow(entry, formatWhen(entry.date)))
|
|
63
|
+
);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
66
|
+
setCalls([]);
|
|
67
|
+
setCallReady(false);
|
|
68
|
+
} finally {
|
|
69
|
+
setLoading(false);
|
|
70
|
+
}
|
|
71
|
+
}, []);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
const pending = consumePendingPhoneNumber();
|
|
74
|
+
if (pending) {
|
|
75
|
+
setError(null);
|
|
76
|
+
setDialed(pending);
|
|
77
|
+
}
|
|
78
|
+
}, []);
|
|
79
|
+
const autoLoadedRef = useRef(false);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (!autoLoadedRef.current) {
|
|
82
|
+
autoLoadedRef.current = true;
|
|
83
|
+
void refreshCalls();
|
|
84
|
+
}
|
|
85
|
+
const interval = setInterval(() => {
|
|
86
|
+
void refreshCalls();
|
|
87
|
+
}, 2e4);
|
|
88
|
+
return () => clearInterval(interval);
|
|
89
|
+
}, [refreshCalls]);
|
|
90
|
+
const placeCall = useCallback(async (number) => {
|
|
91
|
+
const normalized = normalizeNumber(number);
|
|
92
|
+
if (!normalized) {
|
|
93
|
+
setError("Enter a number to call.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
setError(null);
|
|
97
|
+
try {
|
|
98
|
+
await Phone.placeCall({ number: normalized });
|
|
99
|
+
} catch (err) {
|
|
100
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
101
|
+
}
|
|
102
|
+
}, []);
|
|
103
|
+
const openDialer = useCallback(async () => {
|
|
104
|
+
const number = normalizeNumber(dialed);
|
|
105
|
+
setError(null);
|
|
106
|
+
try {
|
|
107
|
+
await Phone.openDialer(number ? { number } : void 0);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
110
|
+
}
|
|
111
|
+
}, [dialed]);
|
|
112
|
+
const onAction = useCallback(
|
|
113
|
+
(action) => {
|
|
114
|
+
if (action.startsWith("key:")) {
|
|
115
|
+
const key = action.slice(4);
|
|
116
|
+
setError(null);
|
|
117
|
+
if (key === "+") {
|
|
118
|
+
setDialed((prev) => prev.length === 0 ? "+" : prev);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
setDialed((prev) => `${prev}${key}`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (action.startsWith("call-number:")) {
|
|
125
|
+
void placeCall(action.slice("call-number:".length));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
switch (action) {
|
|
129
|
+
case "call":
|
|
130
|
+
void placeCall(dialed);
|
|
131
|
+
return;
|
|
132
|
+
case "open-dialer":
|
|
133
|
+
void openDialer();
|
|
134
|
+
return;
|
|
135
|
+
case "backspace":
|
|
136
|
+
setError(null);
|
|
137
|
+
setDialed((prev) => prev.slice(0, -1));
|
|
138
|
+
return;
|
|
139
|
+
case "contacts":
|
|
140
|
+
openContacts();
|
|
141
|
+
return;
|
|
142
|
+
case "refresh":
|
|
143
|
+
void refreshCalls();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
[dialed, openDialer, placeCall, refreshCalls]
|
|
148
|
+
);
|
|
149
|
+
const snapshot = {
|
|
150
|
+
callReady,
|
|
151
|
+
dialed,
|
|
152
|
+
calls,
|
|
153
|
+
loading,
|
|
154
|
+
error
|
|
155
|
+
};
|
|
156
|
+
return /* @__PURE__ */ jsx(SpatialSurface, { children: /* @__PURE__ */ jsx(PhoneSpatialView, { snapshot, onAction }) });
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
PhoneView
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=PhoneView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/PhoneView.tsx"],"sourcesContent":["/**\n * PhoneView — the single GUI/XR data wrapper for the Phone surface.\n *\n * It owns the live Android data (call-log fetch, dialer state, pending-number\n * handoff, place-call / open-dialer / Contacts-link actions) and renders the\n * one presentational {@link PhoneSpatialView} inside a {@link SpatialSurface}.\n * Omitting the `modality` prop lets `SpatialSurface` auto-detect GUI vs XR via\n * `window.__elizaXRContext`, so the SAME component serves both surfaces. The\n * TUI surface renders the same `PhoneSpatialView` through the terminal registry\n * (see `register-terminal-view.tsx`).\n */\n\nimport { Phone } from \"@elizaos/capacitor-phone\";\nimport { consumePendingPhoneNumber } from \"@elizaos/ui/app-navigate-view\";\nimport { SpatialSurface } from \"@elizaos/ui/spatial\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { normalizeNumber } from \"./PhoneAppView.helpers.js\";\nimport {\n type PhoneCallRow,\n type PhoneSnapshot,\n PhoneSpatialView,\n toPhoneCallRow,\n} from \"./PhoneSpatialView.js\";\n\n/** Short relative/absolute timestamp for a recent-call row. */\nfunction formatWhen(epochMs: number): string {\n const date = new Date(epochMs);\n if (Number.isNaN(date.getTime())) return \"\";\n const now = new Date();\n const sameDay =\n date.getFullYear() === now.getFullYear() &&\n date.getMonth() === now.getMonth() &&\n date.getDate() === now.getDate();\n if (sameDay) {\n return date.toLocaleTimeString(undefined, {\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n }\n return date.toLocaleString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/** Open the separate Contacts view via the navigation bus. */\nfunction openContacts(): void {\n if (typeof window === \"undefined\") return;\n window.dispatchEvent(\n new CustomEvent(\"eliza:navigate:view\", {\n detail: { viewId: \"contacts\", viewPath: \"/contacts\" },\n }),\n );\n}\n\nexport function PhoneView() {\n const [dialed, setDialed] = useState(\"\");\n const [callReady, setCallReady] = useState(false);\n const [calls, setCalls] = useState<PhoneCallRow[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const refreshCalls = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const status = await Phone.requestPermissions().catch(() => null);\n if (status && status.phone !== \"granted\") {\n setCalls([]);\n setCallReady(false);\n setError(\n \"Phone access is needed for recent calls and dialing. Grant it in your device settings, then retry.\",\n );\n return;\n }\n const [phoneStatus, { calls: fetched }] = await Promise.all([\n Phone.getStatus().catch(() => null),\n Phone.listRecentCalls({ limit: 50 }),\n ]);\n setCallReady(phoneStatus?.canPlaceCalls ?? true);\n setCalls(\n fetched.map((entry) => toPhoneCallRow(entry, formatWhen(entry.date))),\n );\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setCalls([]);\n setCallReady(false);\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Seed the dialer from a cross-view handoff (e.g. a Contacts \"Call\" control).\n // Single-shot: the number is consumed so a later plain navigation does not\n // re-seed a stale value.\n useEffect(() => {\n const pending = consumePendingPhoneNumber();\n if (pending) {\n setError(null);\n setDialed(pending);\n }\n }, []);\n\n // Load the recent-calls log on mount, then keep it fresh with a quiet 20s\n // poll. Torn down on unmount.\n const autoLoadedRef = useRef(false);\n useEffect(() => {\n if (!autoLoadedRef.current) {\n autoLoadedRef.current = true;\n void refreshCalls();\n }\n const interval = setInterval(() => {\n void refreshCalls();\n }, 20_000);\n return () => clearInterval(interval);\n }, [refreshCalls]);\n\n const placeCall = useCallback(async (number: string) => {\n const normalized = normalizeNumber(number);\n if (!normalized) {\n setError(\"Enter a number to call.\");\n return;\n }\n setError(null);\n try {\n await Phone.placeCall({ number: normalized });\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n }\n }, []);\n\n const openDialer = useCallback(async () => {\n const number = normalizeNumber(dialed);\n setError(null);\n try {\n await Phone.openDialer(number ? { number } : undefined);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n }\n }, [dialed]);\n\n const onAction = useCallback(\n (action: string) => {\n if (action.startsWith(\"key:\")) {\n const key = action.slice(4);\n setError(null);\n if (key === \"+\") {\n // Leading + only when the input is empty (international dialing).\n setDialed((prev) => (prev.length === 0 ? \"+\" : prev));\n return;\n }\n setDialed((prev) => `${prev}${key}`);\n return;\n }\n if (action.startsWith(\"call-number:\")) {\n void placeCall(action.slice(\"call-number:\".length));\n return;\n }\n switch (action) {\n case \"call\":\n void placeCall(dialed);\n return;\n case \"open-dialer\":\n void openDialer();\n return;\n case \"backspace\":\n setError(null);\n setDialed((prev) => prev.slice(0, -1));\n return;\n case \"contacts\":\n openContacts();\n return;\n case \"refresh\":\n void refreshCalls();\n return;\n }\n },\n [dialed, openDialer, placeCall, refreshCalls],\n );\n\n const snapshot: PhoneSnapshot = {\n callReady,\n dialed,\n calls,\n loading,\n error,\n };\n\n return (\n <SpatialSurface>\n <PhoneSpatialView snapshot={snapshot} onAction={onAction} />\n </SpatialSurface>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phone overlay app definition + registration.
|
|
3
|
+
*
|
|
4
|
+
* Registered by the phone side-effect entry only on Android;
|
|
5
|
+
* other platforms intentionally skip registration so the app does not appear
|
|
6
|
+
* in the catalog where it cannot function.
|
|
7
|
+
*/
|
|
8
|
+
import { type OverlayApp } from "@elizaos/ui";
|
|
9
|
+
export declare const PHONE_APP_NAME = "@elizaos/plugin-phone";
|
|
10
|
+
export declare const phoneApp: OverlayApp;
|
|
11
|
+
/** Register the Phone app with the overlay app registry. */
|
|
12
|
+
export declare function registerPhoneApp(): void;
|
|
13
|
+
//# sourceMappingURL=phone-app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone-app.d.ts","sourceRoot":"","sources":["../../src/components/phone-app.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAsB,MAAM,aAAa,CAAC;AAElE,eAAO,MAAM,cAAc,0BAA0B,CAAC;AAEtD,eAAO,MAAM,QAAQ,EAAE,UAStB,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { registerOverlayApp } from "@elizaos/ui";
|
|
2
|
+
const PHONE_APP_NAME = "@elizaos/plugin-phone";
|
|
3
|
+
const phoneApp = {
|
|
4
|
+
name: PHONE_APP_NAME,
|
|
5
|
+
displayName: "Phone",
|
|
6
|
+
description: "Dialer, recent calls, and contact calling for Android",
|
|
7
|
+
category: "system",
|
|
8
|
+
icon: null,
|
|
9
|
+
androidOnly: true,
|
|
10
|
+
loader: () => import("./PhoneAppView.js").then((m) => ({ default: m.PhoneAppView }))
|
|
11
|
+
};
|
|
12
|
+
function registerPhoneApp() {
|
|
13
|
+
registerOverlayApp(phoneApp);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
PHONE_APP_NAME,
|
|
17
|
+
phoneApp,
|
|
18
|
+
registerPhoneApp
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=phone-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/phone-app.ts"],"sourcesContent":["/**\n * Phone overlay app definition + registration.\n *\n * Registered by the phone side-effect entry only on Android;\n * other platforms intentionally skip registration so the app does not appear\n * in the catalog where it cannot function.\n */\n\nimport { type OverlayApp, registerOverlayApp } from \"@elizaos/ui\";\n\nexport const PHONE_APP_NAME = \"@elizaos/plugin-phone\";\n\nexport const phoneApp: OverlayApp = {\n name: PHONE_APP_NAME,\n displayName: \"Phone\",\n description: \"Dialer, recent calls, and contact calling for Android\",\n category: \"system\",\n icon: null,\n androidOnly: true,\n loader: () =>\n import(\"./PhoneAppView.js\").then((m) => ({ default: m.PhoneAppView })),\n};\n\n/** Register the Phone app with the overlay app registry. */\nexport function registerPhoneApp(): void {\n registerOverlayApp(phoneApp);\n}\n"],"mappings":"AAQA,SAA0B,0BAA0B;AAE7C,MAAM,iBAAiB;AAEvB,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,MAAM;AAAA,EACN,aAAa;AAAA,EACb,QAAQ,MACN,OAAO,mBAAmB,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE;AACzE;AAGO,SAAS,mBAAyB;AACvC,qBAAmB,QAAQ;AAC7B;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone-view-bundle.d.ts","sourceRoot":"","sources":["../../src/components/phone-view-bundle.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/phone-view-bundle.ts"],"sourcesContent":["// Vite view-bundle entry. Re-exports the unified spatial view component plus\n// the `interact` capability handler so the built bundle (dist/views/bundle.js)\n// exposes the named exports the view loader reads (`PhoneView`, `interact`).\n// Kept separate from PhoneView.tsx so that file exports only React components\n// and stays Fast-Refresh-compatible in dev.\n\nexport { interact } from \"./PhoneAppView.interact.js\";\nexport { PhoneView } from \"./PhoneView.js\";\n"],"mappings":"AAMA,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry for @elizaos/plugin-phone.
|
|
3
|
+
*
|
|
4
|
+
* Two surfaces ship in this package:
|
|
5
|
+
* - The Android phone overlay (dialer, recent-calls, contacts pane) backed
|
|
6
|
+
* by `@elizaos/capacitor-phone`.
|
|
7
|
+
* - The Phone Companion — Capacitor pairing + chat-mirror + remote-session
|
|
8
|
+
* surface that runs alongside (or in place of) the desktop UI.
|
|
9
|
+
*
|
|
10
|
+
* Both surfaces are exported from the package barrel; hosts choose what they
|
|
11
|
+
* render without importing package subpaths.
|
|
12
|
+
*/
|
|
13
|
+
export { PhoneCompanionApp } from "./companion/components/PhoneCompanionApp.js";
|
|
14
|
+
export * from "./companion/index.js";
|
|
15
|
+
export * from "./companion/services/index.js";
|
|
16
|
+
export { PhoneAppView } from "./components/PhoneAppView.js";
|
|
17
|
+
export { PhoneView } from "./components/PhoneView.js";
|
|
18
|
+
export { PHONE_APP_NAME, phoneApp, registerPhoneApp, } from "./components/phone-app.js";
|
|
19
|
+
export { appPhonePlugin, default } from "./plugin.js";
|
|
20
|
+
export { phoneCallLogProvider } from "./providers/call-log.js";
|
|
21
|
+
export * from "./register.js";
|
|
22
|
+
export * from "./register-companion-page.js";
|
|
23
|
+
export * from "./twilio.js";
|
|
24
|
+
export * from "./ui.js";
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EACL,cAAc,EACd,QAAQ,EACR,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,cAAc,eAAe,CAAC;AAC9B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PhoneCompanionApp } from "./companion/components/PhoneCompanionApp.js";
|
|
2
|
+
export * from "./companion/index.js";
|
|
3
|
+
export * from "./companion/services/index.js";
|
|
4
|
+
import { PhoneAppView } from "./components/PhoneAppView.js";
|
|
5
|
+
import { PhoneView } from "./components/PhoneView.js";
|
|
6
|
+
import {
|
|
7
|
+
PHONE_APP_NAME,
|
|
8
|
+
phoneApp,
|
|
9
|
+
registerPhoneApp
|
|
10
|
+
} from "./components/phone-app.js";
|
|
11
|
+
import { appPhonePlugin, default as default2 } from "./plugin.js";
|
|
12
|
+
import { phoneCallLogProvider } from "./providers/call-log.js";
|
|
13
|
+
export * from "./register.js";
|
|
14
|
+
export * from "./register-companion-page.js";
|
|
15
|
+
export * from "./twilio.js";
|
|
16
|
+
export * from "./ui.js";
|
|
17
|
+
export {
|
|
18
|
+
PHONE_APP_NAME,
|
|
19
|
+
PhoneAppView,
|
|
20
|
+
PhoneCompanionApp,
|
|
21
|
+
PhoneView,
|
|
22
|
+
appPhonePlugin,
|
|
23
|
+
default2 as default,
|
|
24
|
+
phoneApp,
|
|
25
|
+
phoneCallLogProvider,
|
|
26
|
+
registerPhoneApp
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Public entry for @elizaos/plugin-phone.\n *\n * Two surfaces ship in this package:\n * - The Android phone overlay (dialer, recent-calls, contacts pane) backed\n * by `@elizaos/capacitor-phone`.\n * - The Phone Companion — Capacitor pairing + chat-mirror + remote-session\n * surface that runs alongside (or in place of) the desktop UI.\n *\n * Both surfaces are exported from the package barrel; hosts choose what they\n * render without importing package subpaths.\n */\n\nexport { PhoneCompanionApp } from \"./companion/components/PhoneCompanionApp.js\";\nexport * from \"./companion/index.js\";\nexport * from \"./companion/services/index.js\";\nexport { PhoneAppView } from \"./components/PhoneAppView.js\";\nexport { PhoneView } from \"./components/PhoneView.js\";\nexport {\n PHONE_APP_NAME,\n phoneApp,\n registerPhoneApp,\n} from \"./components/phone-app.js\";\nexport { appPhonePlugin, default } from \"./plugin.js\";\nexport { phoneCallLogProvider } from \"./providers/call-log.js\";\nexport * from \"./register.js\";\nexport * from \"./register-companion-page.js\";\nexport * from \"./twilio.js\";\nexport * from \"./ui.js\";\n"],"mappings":"AAaA,SAAS,yBAAyB;AAClC,cAAc;AACd,cAAc;AACd,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB,WAAAA,gBAAe;AACxC,SAAS,4BAA4B;AACrC,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":["default"]}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* elizaOS runtime plugin for the Phone app: exposes a read-only phoneCallLog
|
|
3
|
+
* provider for recent-calls context. Outbound calls are owned by the canonical
|
|
4
|
+
* VOICE_CALL action; the Android dialer implementation remains internal until
|
|
5
|
+
* it is wired as a VOICE_CALL provider. The agent
|
|
6
|
+
* Android adapter applies hosted-app session gating when this package's
|
|
7
|
+
* `/plugin` export is registered.
|
|
8
|
+
*
|
|
9
|
+
* Also declares the Phone Companion (Capacitor pairing/chat-mirror surface)
|
|
10
|
+
* via `app.navTabs`, so the app shell can resolve and mount it dynamically
|
|
11
|
+
* when the companion bundle runs alongside the desktop UI.
|
|
12
|
+
*/
|
|
13
|
+
import type { Plugin } from "@elizaos/core";
|
|
14
|
+
export declare const appPhonePlugin: Plugin;
|
|
15
|
+
export default appPhonePlugin;
|
|
16
|
+
export { phoneCallLogProvider } from "./providers/call-log";
|
|
17
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,eAAO,MAAM,cAAc,EAAE,MA0C5B,CAAC;AAEF,eAAe,cAAc,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
|