@bobfrankston/msgapidefs 0.1.40 → 0.1.42
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/.commitmsg +9 -0
- package/README.md +47 -2
- package/msgapi-plan.md +3 -1
- package/msgapidefs.d.ts +194 -0
- package/msgapidefs.js +8 -0
- package/msgapidefs.ts +31 -0
- package/npmchanges.md +6 -0
- package/package.json +1 -1
- package/tsconfig.json +2 -2
package/.commitmsg
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Add msgapi.dns.lookup; document that udp host may be a hostname
|
|
2
|
+
|
|
3
|
+
- `dns?: { lookup(hostname, { family?, timeoutMs? }) }` with `MsgDnsAddress` /
|
|
4
|
+
`MsgDnsLookupOptions`. Resolves to [{address, family}] (v4 first, never empty) or
|
|
5
|
+
rejects with error.code 'ENOTFOUND' / 'ETIMEOUT'. msger + msga; msgview on demand.
|
|
6
|
+
- udp.send / udp.sendReceive: `host` documented as IP literal OR hostname, resolved in
|
|
7
|
+
the host by the same resolver. (The hosts always resolved names; it was undocumented.)
|
|
8
|
+
- README: DNS section + platform matrix row; msgapi-plan.md status rows.
|
|
9
|
+
Requirements: msgx/dnsrequest.md (2026-09-17, Claude Code at Bob's direction).
|
package/README.md
CHANGED
|
@@ -135,8 +135,10 @@ nothing about capability.
|
|
|
135
135
|
| `shell.open()` | ❌ | ❌ | ✅ | Android: Intent.ACTION_VIEW; Windows: ShellExecute |
|
|
136
136
|
| `shell.showInFolder()` | ❌ | ❌ | ❌ | Defined in interface, not yet implemented |
|
|
137
137
|
| `shell.trash()` | ❌ | ❌ | ❌ | Defined in interface, not yet implemented |
|
|
138
|
+
| **DNS** | | | | **`window.msgapi.dns.*`** (added 2026-09-17) |
|
|
139
|
+
| `dns.lookup()` | ❌ | ✅ | ✅ | Rust `ToSocketAddrs` (getaddrinfo) / C# `System.Net.Dns`; 2 s default timeout, 30 s cache. msger after 0.1.431, msga 1.5.53+. msgview: on demand |
|
|
138
140
|
| **UDP Networking** | | | | **`window.msgapi.udp.*`** |
|
|
139
|
-
| `udp.send()` | ✅ | ✅ | ✅ | Node dgram / Rust UdpSocket / C# UdpClient |
|
|
141
|
+
| `udp.send()` | ✅ | ✅ | ✅ | Node dgram / Rust UdpSocket / C# UdpClient. `host` = IP **or hostname** |
|
|
140
142
|
| `udp.listen()` | ✅ | ✅ | ✅ | Background receive loop in all hosts |
|
|
141
143
|
| `udp.sendReceive()` | ✅ | ✅ | ✅ | Send + wait with timeout |
|
|
142
144
|
| `udp.broadcast()` | ✅ | ✅ | ✅ | 255.255.255.255 broadcast |
|
|
@@ -216,7 +218,21 @@ for (const e of exits) {
|
|
|
216
218
|
|
|
217
219
|
Interpreting common reasons: `LowMemory` = killed by the low-memory killer; `Anr` = main thread hung; `Crash`/`CrashNative` = unhandled exception / native crash; `Freezer` = app was frozen (Android 12+ cached-app freezing — UDP listeners silently suspended, app not actually dead); `UserRequested` = swiped away from recents; `PackageUpdated` = replaced by an APK update; `Signaled` = killed by signal (check `description`).
|
|
218
220
|
|
|
219
|
-
msga also logs new exit records via MsgALog at startup when `LOGGING=true` in msga.env (`Previous exit: ...`), deduplicated across runs via a `lastSeenExitTimestamp` preference. See [msga/exit-diagnostics.md](../msga/exit-diagnostics.md) for the full design notes.
|
|
221
|
+
msga also logs new exit records via MsgALog at startup when `LOGGING=true` in msga.env (`Previous exit: ...`), deduplicated across runs via a `lastSeenExitTimestamp` preference, plus one `Relaunched <gap> after previous exit: ...` line per start (held until logging is turned on). See [msga/exit-diagnostics.md](../msga/exit-diagnostics.md) for the full design notes.
|
|
222
|
+
|
|
223
|
+
**Staying alive / coming back** (msga Android; other hosts resolve `'n/a'`):
|
|
224
|
+
|
|
225
|
+
- `diag.getInstallInfo()` - Returns `MsgInstallInfo`: `installer` / `selfInstalled` (whether the next update can be silent), `canDrawOverlays`, `canInstallPackages`, `isHomeApp` (1.5.52+), `sdkInt`.
|
|
226
|
+
- `diag.requestHome()` - Make msga the device's **Home app**. Android relaunches the Home app after *any* process death — self-update, System WebView update, crash, low-memory kill — with no other permission. On Android 10+ this shows the system's own one-button "Set as default Home app?" confirmation and resolves `'granted'` / `'denied'`; older Android opens the Home-settings list (`'opened'`). `'already'` if it is Home already. Recommended one-time step for a wall panel; a web app can offer it whenever `isHomeApp` is false. (msga 1.5.52+)
|
|
227
|
+
- `diag.requestOverlay()` - Opens the "Display over other apps" settings page (`'already'` / `'opened'`). The older alternative: with the grant, the post-self-update relaunch is allowed to reach the foreground, but it does nothing for a WebView-update kill. Prefer `requestHome()`.
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
// Panel setup: one tap, Android's own dialog
|
|
231
|
+
const info = await window.msgapi?.diag?.getInstallInfo?.();
|
|
232
|
+
if (info && info.isHomeApp === false) {
|
|
233
|
+
const r = await window.msgapi.diag.requestHome(); // 'granted' | 'denied' | 'opened' | ...
|
|
234
|
+
}
|
|
235
|
+
```
|
|
220
236
|
|
|
221
237
|
### Window Control
|
|
222
238
|
|
|
@@ -247,10 +263,39 @@ Direct path operations (give the webview full filesystem access — msga only cu
|
|
|
247
263
|
|
|
248
264
|
> **Note:** File system operations are currently implemented only in msga. msger and msgview do not yet have `window.msgapi.fs` — these hosts have their own internal fs mechanisms but have not wired them to the msgapi interface.
|
|
249
265
|
|
|
266
|
+
### DNS
|
|
267
|
+
|
|
268
|
+
Page script cannot resolve a hostname — a browser resolves names only inside its own requests and
|
|
269
|
+
never hands the address back. The host can. (Added 2026-09-17 by Claude Code; requirements in
|
|
270
|
+
[../dnsrequest.md](../dnsrequest.md).)
|
|
271
|
+
|
|
272
|
+
- `dns.lookup(hostname, { family?, timeoutMs? })` - Resolves to `[{ address, family }]`, IPv4 first,
|
|
273
|
+
**never empty**; rejects otherwise. `family` (4 | 6) restricts the answer. `timeoutMs` defaults to 2000.
|
|
274
|
+
An IP literal resolves to itself.
|
|
275
|
+
- Rejections carry `error.code`: `'ENOTFOUND'` (no such name, or no address of the requested family)
|
|
276
|
+
or `'ETIMEOUT'` (resolver silent for `timeoutMs`). The message names the hostname and the resolver's reason.
|
|
277
|
+
- Answers are cached in the host for 30 s (the platform resolvers do not expose the record TTL).
|
|
278
|
+
"No such host" is cached the same way (a cold negative lookup was measured at ~2.1 s on Windows — without
|
|
279
|
+
this every command to a vanished name would wait out the timeout before the caller's IP fallback);
|
|
280
|
+
a timeout is not an answer and is never cached. A cached name answers instantly, so `timeoutMs` only bounds an uncached lookup.
|
|
281
|
+
- Absent (`window.msgapi?.dns?.lookup` undefined) in a plain browser, msgview, and older hosts —
|
|
282
|
+
callers fall back to the address they already have.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const found = await window.msgapi?.dns?.lookup('wiz_7c47f4.aaz.lt').catch(() => null);
|
|
286
|
+
const ip = found?.[0].address ?? fallbackIp;
|
|
287
|
+
```
|
|
288
|
+
|
|
250
289
|
### UDP Networking
|
|
251
290
|
|
|
252
291
|
Native UDP socket access — no WebSocket proxy needed when running inside a msgapi host.
|
|
253
292
|
|
|
293
|
+
`host` in `udp.send` / `udp.sendReceive` is an IP literal **or a hostname**. A hostname is resolved in
|
|
294
|
+
the host process by the same resolver as `dns.lookup` (timeout, cache) before the datagram leaves; one
|
|
295
|
+
that does not resolve rejects with `error.code` `'ENOTFOUND'` / `'ETIMEOUT'`. (Both hosts always
|
|
296
|
+
resolved names here — the platform send calls do it — but it was undocumented and had no timeout,
|
|
297
|
+
cache or typed error before 2026-09-17.) Sockets are IPv4; a name with only IPv6 addresses rejects in msga.
|
|
298
|
+
|
|
254
299
|
- `udp.send(host, port, data)` - Send UDP packet to specific host
|
|
255
300
|
- `udp.listen(port, callback)` - Listen for incoming UDP packets (returns `{close()}` handle)
|
|
256
301
|
- `udp.sendReceive(host, port, data, timeoutMs?)` - Send and wait for response
|
package/msgapi-plan.md
CHANGED
|
@@ -40,8 +40,10 @@ Shared planning document for msgapi across implementations:
|
|
|
40
40
|
| shell.open() | ❌ | ❌ | ✅ | Android: Intent.ACTION_VIEW; Windows: ShellExecute |
|
|
41
41
|
| shell.showInFolder() | ❌ | ❌ | ❌ | Defined in interface, not yet implemented |
|
|
42
42
|
| shell.trash() | ❌ | ❌ | ❌ | Defined in interface, not yet implemented |
|
|
43
|
+
| **DNS** (2026-09-17) |
|
|
44
|
+
| dns.lookup() | ❌ | ✅ | ✅ | getaddrinfo via Rust std / C# System.Net.Dns; 2 s timeout, 30 s cache, ENOTFOUND/ETIMEOUT codes. See README. |
|
|
43
45
|
| **UDP** |
|
|
44
|
-
| udp.send() | ✅ | ✅ | ✅ | Node dgram / Rust UdpSocket / C# UdpClient |
|
|
46
|
+
| udp.send() | ✅ | ✅ | ✅ | Node dgram / Rust UdpSocket / C# UdpClient. host = IP or hostname (msger/msga share the dns.lookup resolver) |
|
|
45
47
|
| udp.listen() | ✅ | ✅ | ✅ | Background receive loop in all hosts |
|
|
46
48
|
| udp.sendReceive() | ✅ | ✅ | ✅ | Send + wait with timeout |
|
|
47
49
|
| udp.broadcast() | ✅ | ✅ | ✅ | 255.255.255.255 broadcast |
|
package/msgapidefs.d.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
export interface MsgResult {
|
|
2
|
+
button: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
form?: Record<string, any>;
|
|
5
|
+
closed?: boolean;
|
|
6
|
+
dismissed?: boolean;
|
|
7
|
+
timeout?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface FileInfo {
|
|
10
|
+
name: string;
|
|
11
|
+
path: string;
|
|
12
|
+
isDir: boolean;
|
|
13
|
+
size: number;
|
|
14
|
+
modified?: string;
|
|
15
|
+
created?: string;
|
|
16
|
+
attributes?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface FileDialogOptions {
|
|
19
|
+
title?: string;
|
|
20
|
+
defaultFilename?: string;
|
|
21
|
+
filters?: Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
extensions: string[];
|
|
24
|
+
}>;
|
|
25
|
+
defaultPath?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SelectedFile {
|
|
28
|
+
name: string;
|
|
29
|
+
path: string;
|
|
30
|
+
content: string;
|
|
31
|
+
}
|
|
32
|
+
export type MsgHost = 'msga' | 'msger' | 'msgview';
|
|
33
|
+
export type MsgPlatform = 'android' | 'windows' | 'linux' | 'macos';
|
|
34
|
+
export type AutoUpdateMode = 'auto' | 'check' | 'off';
|
|
35
|
+
export type LoggingMode = 'msga' | 'msgapi' | 'on' | 'off' | 'none';
|
|
36
|
+
export interface MsgHostInfo {
|
|
37
|
+
host: MsgHost;
|
|
38
|
+
version: string;
|
|
39
|
+
platform: MsgPlatform;
|
|
40
|
+
appName?: string;
|
|
41
|
+
updateUrl?: string;
|
|
42
|
+
apkUrl?: string;
|
|
43
|
+
localIp?: string;
|
|
44
|
+
localMask?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface MsgApkInfo {
|
|
47
|
+
name: string;
|
|
48
|
+
url: string;
|
|
49
|
+
description: string;
|
|
50
|
+
icon: string;
|
|
51
|
+
file: string;
|
|
52
|
+
sizeMB: number;
|
|
53
|
+
built: string;
|
|
54
|
+
default?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface MsgExitInfo {
|
|
57
|
+
timestamp: number;
|
|
58
|
+
reason: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
importance?: string;
|
|
61
|
+
pss?: number;
|
|
62
|
+
rss?: number;
|
|
63
|
+
processName?: string;
|
|
64
|
+
pid?: number;
|
|
65
|
+
status?: number;
|
|
66
|
+
stateSummary?: string;
|
|
67
|
+
trace?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface MsgVersionInfo {
|
|
70
|
+
version: string;
|
|
71
|
+
buildDate: string;
|
|
72
|
+
apks: MsgApkInfo[];
|
|
73
|
+
}
|
|
74
|
+
/** Why an update prompted, and whether the post-update relaunch can reach the foreground.
|
|
75
|
+
* Android permits a silent self-update only when the updating app is the installer of record, so
|
|
76
|
+
* a browser or adb sideload makes the NEXT update prompt (selfInstalled false). Separately, a
|
|
77
|
+
* background process may not start an activity without canDrawOverlays, which is why a silent
|
|
78
|
+
* update can leave the user on the home screen. */
|
|
79
|
+
export interface MsgInstallInfo {
|
|
80
|
+
package: string;
|
|
81
|
+
installer: string;
|
|
82
|
+
selfInstalled: boolean;
|
|
83
|
+
canDrawOverlays: boolean;
|
|
84
|
+
canInstallPackages: boolean;
|
|
85
|
+
isHomeApp?: boolean;
|
|
86
|
+
sdkInt: number;
|
|
87
|
+
}
|
|
88
|
+
/** Handle returned by udp.listen(). send/broadcast leave from this listener's own socket, so the
|
|
89
|
+
* device's reply arrives back at this listener rather than at whichever one registered first.
|
|
90
|
+
* send/broadcast are optional: msga builds before 1.5.45 return a handle with only close(). */
|
|
91
|
+
export interface UdpListenHandle {
|
|
92
|
+
close(): void;
|
|
93
|
+
send?(host: string, port: number, data: string | Uint8Array): Promise<void>;
|
|
94
|
+
broadcast?(port: number, data: string | Uint8Array): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/** One address from dns.lookup(). */
|
|
97
|
+
export interface MsgDnsAddress {
|
|
98
|
+
address: string;
|
|
99
|
+
family: 4 | 6;
|
|
100
|
+
}
|
|
101
|
+
/** Options for dns.lookup(). */
|
|
102
|
+
export interface MsgDnsLookupOptions {
|
|
103
|
+
family?: 4 | 6;
|
|
104
|
+
timeoutMs?: number;
|
|
105
|
+
}
|
|
106
|
+
export interface MsgAPI {
|
|
107
|
+
version?: string;
|
|
108
|
+
updateUrl?: string;
|
|
109
|
+
info?: MsgHostInfo;
|
|
110
|
+
setLogging?(value?: LoggingMode, name?: string): LoggingMode;
|
|
111
|
+
setAutoUpdate?(value?: AutoUpdateMode): AutoUpdateMode;
|
|
112
|
+
installUpdate?(url: string): Promise<void>;
|
|
113
|
+
getNetworkInfo?(): Promise<{
|
|
114
|
+
localIp: string;
|
|
115
|
+
localMask: string;
|
|
116
|
+
}>;
|
|
117
|
+
diag?: {
|
|
118
|
+
getExitReasons(max?: number): Promise<MsgExitInfo[]>;
|
|
119
|
+
getInstallInfo?(): Promise<MsgInstallInfo>;
|
|
120
|
+
requestOverlay?(): Promise<'already' | 'opened' | 'n/a'>;
|
|
121
|
+
requestHome?(): Promise<'already' | 'granted' | 'denied' | 'opened' | 'n/a'>;
|
|
122
|
+
};
|
|
123
|
+
toggleFullscreen(): void;
|
|
124
|
+
setFullscreen(enabled: boolean): void;
|
|
125
|
+
minimize(): void;
|
|
126
|
+
maximize(): void;
|
|
127
|
+
setSize(width: number, height: number): void;
|
|
128
|
+
setPosition(x: number, y: number): void;
|
|
129
|
+
setAlwaysOnTop(enabled: boolean): void;
|
|
130
|
+
close(result?: Partial<MsgResult>): void;
|
|
131
|
+
fs?: {
|
|
132
|
+
selectFile(options?: FileDialogOptions): Promise<SelectedFile | null>;
|
|
133
|
+
selectFiles(options?: FileDialogOptions): Promise<SelectedFile[]>;
|
|
134
|
+
saveFileAs(content: string, defaultFilename?: string, options?: FileDialogOptions): Promise<string | null>;
|
|
135
|
+
selectFolder(options?: FileDialogOptions): Promise<string | null>;
|
|
136
|
+
read(path: string, options?: {
|
|
137
|
+
encoding?: 'utf8' | 'base64' | 'binary';
|
|
138
|
+
}): Promise<string | Uint8Array>;
|
|
139
|
+
readAsDataUrl(path: string, mimeType?: string): Promise<string>;
|
|
140
|
+
write(path: string, content: string): Promise<void>;
|
|
141
|
+
list(path: string): Promise<FileInfo[]>;
|
|
142
|
+
exists(path: string): Promise<boolean>;
|
|
143
|
+
delete(path: string): Promise<void>;
|
|
144
|
+
};
|
|
145
|
+
dns?: {
|
|
146
|
+
/** Resolve a hostname in the host process. Resolves to at least one address (v4 first), or
|
|
147
|
+
* REJECTS — never an empty success. The Error's `code` is 'ENOTFOUND' (no such name / no
|
|
148
|
+
* address of the requested family) or 'ETIMEOUT' (resolver did not answer within timeoutMs);
|
|
149
|
+
* the message names the hostname and the resolver's reason. An IP literal resolves to itself.
|
|
150
|
+
* Answers are cached in the host for ~30 s. msger after 0.1.431, msga 1.5.53+. */
|
|
151
|
+
lookup(hostname: string, opts?: MsgDnsLookupOptions): Promise<MsgDnsAddress[]>;
|
|
152
|
+
};
|
|
153
|
+
udp?: {
|
|
154
|
+
send(host: string, port: number, data: string | Uint8Array): Promise<void>;
|
|
155
|
+
listen(port: number, callback: (data: Uint8Array, sender: {
|
|
156
|
+
host: string;
|
|
157
|
+
port: number;
|
|
158
|
+
}) => void): Promise<UdpListenHandle>;
|
|
159
|
+
sendReceive(host: string, port: number, data: string | Uint8Array, timeoutMs?: number): Promise<Uint8Array>;
|
|
160
|
+
broadcast(port: number, data: string | Uint8Array): Promise<void>;
|
|
161
|
+
};
|
|
162
|
+
tcp?: {
|
|
163
|
+
connect(host: string, port: number, tls: boolean): Promise<number>;
|
|
164
|
+
write(streamId: number, data: string): Promise<void>;
|
|
165
|
+
onData(streamId: number, callback: (data: string) => void): void;
|
|
166
|
+
onClose(streamId: number, callback: (hadError: boolean) => void): void;
|
|
167
|
+
onError(streamId: number, callback: (message: string) => void): void;
|
|
168
|
+
upgradeTLS(streamId: number, servername: string): Promise<void>;
|
|
169
|
+
close(streamId: number): void;
|
|
170
|
+
};
|
|
171
|
+
http?: {
|
|
172
|
+
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
173
|
+
};
|
|
174
|
+
shell?: {
|
|
175
|
+
exec(command: string, args?: string[], options?: {
|
|
176
|
+
cwd?: string;
|
|
177
|
+
timeout?: number;
|
|
178
|
+
stdin?: string;
|
|
179
|
+
encoding?: 'utf8' | 'base64';
|
|
180
|
+
}): Promise<{
|
|
181
|
+
stdout: string;
|
|
182
|
+
stderr: string;
|
|
183
|
+
exitCode: number;
|
|
184
|
+
}>;
|
|
185
|
+
open(path: string): Promise<void>;
|
|
186
|
+
showInFolder(path: string): Promise<void>;
|
|
187
|
+
trash(path: string): Promise<void>;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
declare global {
|
|
191
|
+
interface Window {
|
|
192
|
+
msgapi?: MsgAPI;
|
|
193
|
+
}
|
|
194
|
+
}
|
package/msgapidefs.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// TypeScript definitions for the msgapi JavaScript API
|
|
2
|
+
// Type-safe access to msgapi's window control, file system, shell, and UDP features
|
|
3
|
+
// Used by msgview, msger, and msga. See README.md for docs.
|
|
4
|
+
//
|
|
5
|
+
// ⚠️ SECURITY: msgapi gives full native OS access (filesystem, processes, networking).
|
|
6
|
+
// Intended ONLY for trusted apps — native apps written as web pages. Do not expose to untrusted content.
|
|
7
|
+
// ⚠️ EXPERIMENTAL: APIs are experimental and subject to change.
|
|
8
|
+
export {};
|
package/msgapidefs.ts
CHANGED
|
@@ -101,6 +101,7 @@ export interface MsgInstallInfo {
|
|
|
101
101
|
selfInstalled: boolean; // true => next update can be silent
|
|
102
102
|
canDrawOverlays: boolean; // true => post-update relaunch is allowed to foreground
|
|
103
103
|
canInstallPackages: boolean;// "Install unknown apps" for this app
|
|
104
|
+
isHomeApp?: boolean; // true => msga is the device's Home app: Android relaunches it after ANY process death (msga 1.5.52+)
|
|
104
105
|
sdkInt: number;
|
|
105
106
|
}
|
|
106
107
|
|
|
@@ -113,6 +114,18 @@ export interface UdpListenHandle {
|
|
|
113
114
|
broadcast?(port: number, data: string | Uint8Array): Promise<void>;
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
/** One address from dns.lookup(). */
|
|
118
|
+
export interface MsgDnsAddress {
|
|
119
|
+
address: string; // Literal address, e.g. "172.20.1.42" or "fe80::1"
|
|
120
|
+
family: 4 | 6;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Options for dns.lookup(). */
|
|
124
|
+
export interface MsgDnsLookupOptions {
|
|
125
|
+
family?: 4 | 6; // Restrict the answer to one family; default = both, v4 first
|
|
126
|
+
timeoutMs?: number; // Bounded wait for the resolver (default 2000)
|
|
127
|
+
}
|
|
128
|
+
|
|
116
129
|
export interface MsgAPI {
|
|
117
130
|
|
|
118
131
|
version?: string; // Host app version (e.g. "1.3.0") — semver string, compare numerically not lexicographically
|
|
@@ -134,6 +147,7 @@ export interface MsgAPI {
|
|
|
134
147
|
getExitReasons(max?: number): Promise<MsgExitInfo[]>; // Previous-run exit records, newest first (default max 5). msga Android 11+ only; [] elsewhere.
|
|
135
148
|
getInstallInfo?(): Promise<MsgInstallInfo>; // Installer of record + permission state (msga 1.5.48+)
|
|
136
149
|
requestOverlay?(): Promise<'already' | 'opened' | 'n/a'>; // Open the Display-over-other-apps settings page
|
|
150
|
+
requestHome?(): Promise<'already' | 'granted' | 'denied' | 'opened' | 'n/a'>; // Make msga the Home app: system one-button confirmation (Android 10+), settings list before. Home app = automatic relaunch after self-update / WebView update / crash. msga 1.5.52+
|
|
137
151
|
};
|
|
138
152
|
|
|
139
153
|
// ── Window Control ──────────────────────────────────────────
|
|
@@ -162,8 +176,25 @@ export interface MsgAPI {
|
|
|
162
176
|
delete(path: string): Promise<void>; // Delete file or directory (requires allowFs)
|
|
163
177
|
};
|
|
164
178
|
|
|
179
|
+
// ── DNS ─────────────────────────────────────────────────────
|
|
180
|
+
// 2026-09-17 — Claude Code (Fable 5.1), at Bob's direction (dnsrequest.md). Page script cannot
|
|
181
|
+
// resolve a name itself; the host can. Absent (plain browser, older host) = "not available":
|
|
182
|
+
// callers fall back to the address they already have.
|
|
183
|
+
|
|
184
|
+
dns?: {
|
|
185
|
+
/** Resolve a hostname in the host process. Resolves to at least one address (v4 first), or
|
|
186
|
+
* REJECTS — never an empty success. The Error's `code` is 'ENOTFOUND' (no such name / no
|
|
187
|
+
* address of the requested family) or 'ETIMEOUT' (resolver did not answer within timeoutMs);
|
|
188
|
+
* the message names the hostname and the resolver's reason. An IP literal resolves to itself.
|
|
189
|
+
* Answers are cached in the host for ~30 s. msger after 0.1.431, msga 1.5.53+. */
|
|
190
|
+
lookup(hostname: string, opts?: MsgDnsLookupOptions): Promise<MsgDnsAddress[]>;
|
|
191
|
+
};
|
|
192
|
+
|
|
165
193
|
// ── UDP Networking ──────────────────────────────────────────
|
|
166
194
|
// Native UDP — no httpudp WebSocket proxy needed
|
|
195
|
+
// `host` is an IP literal OR a hostname. A hostname is resolved in the host process (same
|
|
196
|
+
// resolver, timeout and cache as dns.lookup) before the datagram leaves; one that does not
|
|
197
|
+
// resolve rejects with code 'ENOTFOUND' / 'ETIMEOUT' so the caller can fall back to an address.
|
|
167
198
|
|
|
168
199
|
udp?: {
|
|
169
200
|
send(host: string, port: number, data: string | Uint8Array): Promise<void>; // Send UDP packet to host:port
|
package/npmchanges.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# npm Publish Changes
|
|
2
|
+
|
|
3
|
+
## v0.1.41 — 2026-09-14
|
|
4
|
+
|
|
5
|
+
diag.requestHome() and MsgInstallInfo.isHomeApp (msga 1.5.52): make msga the device's Home app via Android's own confirmation dialog so relaunch after self-update / WebView update / crash is automatic; README Diagnostics documents getInstallInfo/requestHome/requestOverlay and the per-start "Relaunched <gap>" log line.
|
|
6
|
+
|
package/package.json
CHANGED
package/tsconfig.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"types": ["node"],
|
|
4
4
|
"target": "ES2020",
|
|
5
|
-
"module": "
|
|
5
|
+
"module": "NodeNext",
|
|
6
6
|
"lib": ["ES2020", "DOM"],
|
|
7
7
|
"declaration": true,
|
|
8
8
|
"outDir": ".",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"esModuleInterop": true,
|
|
12
12
|
"skipLibCheck": true,
|
|
13
13
|
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"moduleResolution": "
|
|
14
|
+
"moduleResolution": "NodeNext",
|
|
15
15
|
"newLine": "lf"
|
|
16
16
|
},
|
|
17
17
|
"include": ["msgapidefs.ts"],
|