@mhome/app-facade-protocol 1.71.0 → 1.81.0

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 CHANGED
@@ -20,6 +20,9 @@ identity. Core-to-Node routes and provider runtime models belong to
20
20
  See [resource definition, observation, history and relationship reads](contract/resource-read-v1.md)
21
21
  for shared business reads and the separate UI rendering boundary.
22
22
 
23
+ See [Agent LLM settings](contract/agent-llm-v1.md) for active-mode reads,
24
+ independent saved configuration and Provider Operation boundaries.
25
+
23
26
  ## Business DTO ownership
24
27
 
25
28
  A Facade owns the public business DTO for an operation. Native Agent tools, MCP,
@@ -238,9 +241,12 @@ Business operation permissions are declared once in [the authorization manifest]
238
241
 
239
242
  ## Matter management reads
240
243
 
241
- `/app/matter/device/list` is the management inventory, grouped by Fabric node. It is distinct from the Plugin's Integration enumeration `/matter/device/list`. Its `sourceDeviceId` values identify Plugin projections, not Twin entities. Nodes without projected devices remain visible; `membershipComplete`, `inventoryComplete`, per-node completeness and `errors` describe partial observations. Lists omit endpoints and attribute payloads.
242
-
243
- `/app/matter/fabric/node/detail` accepts 1–20 unique `matterNodeIds`, returning an ordered item result or error for each ID. The request uses string IDs without numeric coercion. See `schema/matter-management.v1.schema.json`. All `/app/matter/` operations execute through the Space's Hub irrespective of scope execution mode. Node removal is a manual UI/CLI capability, not a delegated Agent/MCP tool.
244
+ Matter management uses the generic `/app/plugin/matter/*` transport with an exact
245
+ Space-bound `nodeId`, `version`, and Plugin-owned `payload`. The former
246
+ `/app/matter/*` Facade is retired. Business contracts are published in Core's
247
+ `schema/matter-plugin-management.v1.schema.json`; runtime behavior lives in the
248
+ Integration repository's Matter Plugin. Binding/offline observations come from
249
+ `/app/plugin/enabled/list`, independently of the runtime's status.
244
250
 
245
251
  UI Integration metadata uses `/app/integration/presentation/get`; see
246
252
  [the presentation contract](contract/integration-presentation-v1.md).
@@ -0,0 +1,29 @@
1
+ # Native app screenshot support
2
+
3
+ `/app/client/screenshot/report` accepts `{ "supported": boolean }` and returns
4
+ an empty business object in the standard Facade response. It reports only the
5
+ calling authenticated app connection, in its current Space; caller identity is
6
+ never supplied in the input. Agent, CLI and service callers cannot report for a
7
+ client. Authorization is Space read plus an authenticated, live client binding.
8
+
9
+ Support is ephemeral connection metadata, reset on reconnect. A positive report
10
+ receives a server-derived 90-second expiry. A visible, ready UI renews every
11
+ 30 seconds and withdraws on hide or detach; ordinary socket heartbeats do not
12
+ renew this support lease. An expired report is unavailable even if its daemon
13
+ remains connected. Native clients
14
+ report true only after their installed WebView bridge confirms viewport capture
15
+ support. Web/PWA, messaging and headless clients never report true. Reporting
16
+ support grants no permission to capture; `basic.app.command.getScreenshot` uses
17
+ normal capability authorization and must independently resolve one live client.
18
+
19
+ The command captures the visible MeowLink WebView viewport, including app-owned
20
+ web overlays. It requires the foreground app to display the requested Space.
21
+ It must recheck the session and Space revision around capture and storage, and
22
+ must not bring the app to the foreground or return an older image on failure.
23
+ Native platform overlays, OS UI, other windows and offscreen page content are
24
+ outside the capture. Hardware media composition depends on the platform WebView.
25
+
26
+ The client stores an image through `/app/artifact/put` (at most 1 MiB decoded),
27
+ and returns `{ screenshot: { uri }, capturedAt: { _type: "Timestamp", value } }`.
28
+ Timestamp value is Unix epoch milliseconds, matching the runtime value codec.
29
+ The command's transport budget is 15 seconds; other App commands retain theirs.
@@ -9,13 +9,23 @@ follow the Space execution authority on both local Core and cloud.
9
9
 
10
10
  | Target | Input | Business data |
11
11
  | --- | --- | --- |
12
- | `/app/device/detail/get` | `{ids}` | Existing ordered `items` with `device` definitions, capabilities, group membership, enabled/source metadata; no online or state fields |
12
+ | `/app/device/detail/get` | `{ids}` | Existing ordered `items` with `device` definitions, capabilities, group membership, physical Twin enablement or Group application state, source metadata; no online or state fields |
13
13
  | `/app/device/state/get` | `{ids}` | Ordered `items` with `resource: {entityId, online?, onlineUpdatedAtSec?, latest}` |
14
+ | `/app/widget/list` | `{}` | Summaries: id, name, description, type, tag; Data adds dataType/repeated. No list mode or full-definition catalog |
14
15
  | `/app/widget/detail/get` | `{ids}` | Existing ordered `items` with `widget` configuration; no value, next or nextTimestamp |
15
16
  | `/app/widget/value/get` | `{ids}` | Ordered `items` with `resource: {widgetId, revision, value, next?, nextTimestamp?}` |
16
17
  | `/app/automation/status` | `{ids}` | Ordered `items` with `resource: {automationId, enabled, runnable, running, blocked, lastRunAt}` |
17
18
  | `/app/graph/relations/get` | `{resource: {kind, id}}` | `{resource, relations: [{from, relation, to, capabilityIds?}]}` |
18
19
 
20
+ Device list and detail discriminate status using `group`: physical Devices (`false`)
21
+ always include boolean `active` and omit `applyState`; Groups (`true`) always include
22
+ `applyState` (`applying`, `ready`, `failed`, `deleting`) and omit `active`. Both Full
23
+ and Essential preserve these fields. `active` describes physical Twin enablement,
24
+ not on/off or reachability. Group state comes from its stored definition, never a
25
+ Twin lookup; `ready` confirms application, not member reachability. Group diagnostics
26
+ and application errors are available through Group detail. Device enable/disable
27
+ accepts physical IDs only. This does not add Group enablement or alter lifecycle writes.
28
+
19
29
  Observation batches accept 1–100 IDs, reject blanks, trim and deduplicate preserving
20
30
  request order. Every normalized ID gets `{requestedId, found, resource?}`; missing
21
31
  resources have `found: false, reason: "not_found"`. A known Device with no observations
@@ -73,3 +83,14 @@ Generated Twin program inspection retains its internal `/automation/get`,
73
83
  `/automation/status` and `/automation/info` UI readers. These IDs are not accepted
74
84
  by the shared user-program Automation detail/status contract. User program detail
75
85
  pages use the shared definition, status and graph readers.
86
+
87
+ ## Widget presentation
88
+
89
+ Widget detail uses an explicit public definition DTO on Core and cloud, including
90
+ revision and a boolean repeated flag. It excludes runtime value/next/nextTimestamp.
91
+ Essential omits displayName/global/baseId/steps/stepUnits; editable constraints,
92
+ options and complete Circadian schedules remain. Full preserves the full definition DTO.
93
+ History timestamps are epoch seconds; nextTimestamp and explicitly typed Timestamp
94
+ values are epoch milliseconds in Full. Essential presents these dates in the Home
95
+ IANA timezone, with UTC fallback for missing/invalid timezone configuration. Numeric
96
+ values, Duration values and schedule wall-clock times are not inferred to be dates.
@@ -0,0 +1,340 @@
1
+ {
2
+ "valid": [
3
+ {
4
+ "type": "ListProvidersInput",
5
+ "value": {}
6
+ },
7
+ {
8
+ "type": "ListProvidersInput",
9
+ "value": {
10
+ "llmMode": "local"
11
+ }
12
+ },
13
+ {
14
+ "type": "GetProviderInput",
15
+ "value": {
16
+ "llmMode": "local",
17
+ "provider": "local_example"
18
+ }
19
+ },
20
+ {
21
+ "type": "ProviderList",
22
+ "value": {
23
+ "llmMode": "cloud",
24
+ "providers": [
25
+ {
26
+ "provider": "cloud_example",
27
+ "displayName": "Example",
28
+ "runtime": "cloud",
29
+ "modelSource": "catalog",
30
+ "authKind": "none",
31
+ "useCases": [
32
+ "chat"
33
+ ],
34
+ "allowedAgentModes": {
35
+ "chat": [
36
+ "cloud"
37
+ ]
38
+ },
39
+ "providerMetadata": null,
40
+ "configuration": null
41
+ }
42
+ ],
43
+ "providerModels": [
44
+ {
45
+ "provider": "cloud_example",
46
+ "models": [
47
+ {
48
+ "id": "chat-example",
49
+ "displayName": "Example Chat",
50
+ "modelType": "llm",
51
+ "available": true,
52
+ "deprecated": false,
53
+ "successor": null,
54
+ "supportsTools": true,
55
+ "supportsVision": false,
56
+ "contextWindowTokens": 128000,
57
+ "inputModalities": [
58
+ "text"
59
+ ],
60
+ "outputModalities": [
61
+ "text"
62
+ ],
63
+ "chatConfig": {
64
+ "temperatureDefault": null
65
+ },
66
+ "generationControls": {
67
+ "temperature": false,
68
+ "thinking": false,
69
+ "fastMode": false
70
+ },
71
+ "metadata": null
72
+ }
73
+ ]
74
+ }
75
+ ]
76
+ }
77
+ },
78
+ {
79
+ "type": "ProviderList",
80
+ "value": {
81
+ "llmMode": "local",
82
+ "providers": [
83
+ {
84
+ "provider": "local_example",
85
+ "displayName": "Example",
86
+ "runtime": "local",
87
+ "modelSource": "catalog",
88
+ "authKind": "api_key",
89
+ "useCases": [
90
+ "chat"
91
+ ],
92
+ "allowedAgentModes": {
93
+ "chat": [
94
+ "local"
95
+ ]
96
+ },
97
+ "providerMetadata": null,
98
+ "configuration": {
99
+ "requiresCredential": true,
100
+ "hasCredential": true,
101
+ "ready": false,
102
+ "status": "unavailable",
103
+ "statusLabel": "Unavailable",
104
+ "reason": "Retry discovery",
105
+ "nodeType": null,
106
+ "nodeBound": null,
107
+ "nodeOnline": null,
108
+ "accountId": null,
109
+ "expiresAtMs": null,
110
+ "metadata": {
111
+ "region": "example",
112
+ "credentialProfile": null,
113
+ "workspaceId": null
114
+ },
115
+ "supportedUseCases": [],
116
+ "readinessByUseCase": {
117
+ "chat": {
118
+ "ready": false,
119
+ "modelCount": 0,
120
+ "reason": "Retry discovery"
121
+ }
122
+ }
123
+ }
124
+ }
125
+ ],
126
+ "providerModels": [
127
+ {
128
+ "provider": "local_example",
129
+ "models": []
130
+ }
131
+ ]
132
+ }
133
+ },
134
+ {
135
+ "type": "Summary",
136
+ "value": {
137
+ "llmMode": "cloud",
138
+ "providers": [
139
+ {
140
+ "provider": "cloud_example",
141
+ "displayName": "Example",
142
+ "runtime": "cloud",
143
+ "modelSource": "catalog",
144
+ "authKind": "none",
145
+ "useCases": [
146
+ "chat"
147
+ ],
148
+ "allowedAgentModes": {
149
+ "chat": [
150
+ "cloud"
151
+ ]
152
+ },
153
+ "providerMetadata": null,
154
+ "configuration": null
155
+ }
156
+ ],
157
+ "providerModels": [
158
+ {
159
+ "provider": "cloud_example",
160
+ "models": [
161
+ {
162
+ "id": "chat-example",
163
+ "displayName": "Example Chat",
164
+ "modelType": "llm",
165
+ "available": true,
166
+ "deprecated": false,
167
+ "successor": null,
168
+ "supportsTools": true,
169
+ "supportsVision": false,
170
+ "contextWindowTokens": 128000,
171
+ "inputModalities": [
172
+ "text"
173
+ ],
174
+ "outputModalities": [
175
+ "text"
176
+ ],
177
+ "chatConfig": {
178
+ "temperatureDefault": null
179
+ },
180
+ "generationControls": {
181
+ "temperature": false,
182
+ "thinking": false,
183
+ "fastMode": false
184
+ },
185
+ "metadata": null
186
+ }
187
+ ]
188
+ }
189
+ ],
190
+ "effectiveMappings": [
191
+ {
192
+ "temperature": null,
193
+ "reasoningEffort": null,
194
+ "thinking": null,
195
+ "fastMode": null,
196
+ "useCase": "chat",
197
+ "agentModelMode": "auto",
198
+ "provider": "cloud_example",
199
+ "model": "chat-example",
200
+ "source": "default",
201
+ "configuredModel": "chat-example"
202
+ }
203
+ ],
204
+ "defaultProviders": [
205
+ {
206
+ "useCase": "chat",
207
+ "llmMode": "cloud",
208
+ "provider": "cloud_example",
209
+ "updatedAtMs": 0
210
+ }
211
+ ],
212
+ "llmUseCases": [
213
+ {
214
+ "useCase": "chat",
215
+ "displayName": "Chat",
216
+ "description": null,
217
+ "ownerType": null,
218
+ "ownerId": null,
219
+ "executionUseCase": null,
220
+ "configurable": true,
221
+ "active": true,
222
+ "modes": [
223
+ {
224
+ "mode": "auto",
225
+ "displayName": "Auto",
226
+ "description": null,
227
+ "requirements": {
228
+ "modelType": "llm",
229
+ "requiredInputModalities": [
230
+ "text"
231
+ ],
232
+ "optionalInputModalities": [],
233
+ "requiredOutputModalities": [
234
+ "text"
235
+ ],
236
+ "preferredFeatures": []
237
+ }
238
+ }
239
+ ],
240
+ "updatedAtMs": null,
241
+ "lastSeenAtMs": null
242
+ }
243
+ ]
244
+ }
245
+ },
246
+ {
247
+ "type": "ProviderDetail",
248
+ "value": {
249
+ "llmMode": "local",
250
+ "provider": {
251
+ "provider": "local_example",
252
+ "displayName": "Example",
253
+ "runtime": "local",
254
+ "modelSource": "catalog",
255
+ "authKind": "api_key",
256
+ "useCases": [
257
+ "chat"
258
+ ],
259
+ "allowedAgentModes": {
260
+ "chat": [
261
+ "local"
262
+ ]
263
+ },
264
+ "providerMetadata": null,
265
+ "configuration": {
266
+ "requiresCredential": true,
267
+ "hasCredential": true,
268
+ "ready": false,
269
+ "status": "unavailable",
270
+ "statusLabel": "Unavailable",
271
+ "reason": "Retry discovery",
272
+ "nodeType": null,
273
+ "nodeBound": null,
274
+ "nodeOnline": null,
275
+ "accountId": null,
276
+ "expiresAtMs": null,
277
+ "metadata": {
278
+ "region": "example",
279
+ "credentialProfile": null,
280
+ "workspaceId": null
281
+ },
282
+ "supportedUseCases": [],
283
+ "readinessByUseCase": {
284
+ "chat": {
285
+ "ready": false,
286
+ "modelCount": 0,
287
+ "reason": "Retry discovery"
288
+ }
289
+ }
290
+ }
291
+ },
292
+ "models": []
293
+ }
294
+ }
295
+ ],
296
+ "invalid": [
297
+ {
298
+ "type": "ListProvidersInput",
299
+ "value": {
300
+ "llmMode": "auto"
301
+ }
302
+ },
303
+ {
304
+ "type": "GetProviderInput",
305
+ "value": {
306
+ "provider": "local_example"
307
+ }
308
+ },
309
+ {
310
+ "type": "ProviderConfiguration",
311
+ "value": {
312
+ "requiresCredential": true,
313
+ "hasCredential": true,
314
+ "ready": false,
315
+ "status": "unavailable",
316
+ "statusLabel": "Unavailable",
317
+ "reason": "Retry discovery",
318
+ "nodeType": null,
319
+ "nodeBound": null,
320
+ "nodeOnline": null,
321
+ "accountId": null,
322
+ "expiresAtMs": null,
323
+ "metadata": {
324
+ "region": "example",
325
+ "credentialProfile": null,
326
+ "workspaceId": null
327
+ },
328
+ "supportedUseCases": [],
329
+ "readinessByUseCase": {
330
+ "chat": {
331
+ "ready": false,
332
+ "modelCount": 0,
333
+ "reason": "Retry discovery"
334
+ }
335
+ },
336
+ "apiKey": "must-never-cross-boundary"
337
+ }
338
+ }
339
+ ]
340
+ }
@@ -1,6 +1,6 @@
1
1
  [
2
2
  {
3
- "name": "owner:/app/device/brief/list",
3
+ "name": "owner:/app/device/list",
4
4
  "principal": {
5
5
  "kind": "user",
6
6
  "userId": "owner"
@@ -8,7 +8,7 @@
8
8
  "memberRole": "OWNER",
9
9
  "tenantId": "tenant",
10
10
  "scopeId": "space",
11
- "target": "/app/device/brief/list",
11
+ "target": "/app/device/list",
12
12
  "allowed": true
13
13
  },
14
14
  {
@@ -84,7 +84,7 @@
84
84
  "allowed": false
85
85
  },
86
86
  {
87
- "name": "member:/app/device/brief/list",
87
+ "name": "member:/app/device/list",
88
88
  "principal": {
89
89
  "kind": "user",
90
90
  "userId": "member"
@@ -92,7 +92,7 @@
92
92
  "memberRole": "MEMBER",
93
93
  "tenantId": "tenant",
94
94
  "scopeId": "space",
95
- "target": "/app/device/brief/list",
95
+ "target": "/app/device/list",
96
96
  "allowed": true
97
97
  },
98
98
  {
@@ -168,7 +168,7 @@
168
168
  "allowed": false
169
169
  },
170
170
  {
171
- "name": "removed:/app/device/brief/list",
171
+ "name": "removed:/app/device/list",
172
172
  "principal": {
173
173
  "kind": "user",
174
174
  "userId": "former"
@@ -176,7 +176,7 @@
176
176
  "memberRole": null,
177
177
  "tenantId": "tenant",
178
178
  "scopeId": "space",
179
- "target": "/app/device/brief/list",
179
+ "target": "/app/device/list",
180
180
  "allowed": false
181
181
  },
182
182
  {
@@ -252,7 +252,7 @@
252
252
  "allowed": false
253
253
  },
254
254
  {
255
- "name": "space:/app/device/brief/list",
255
+ "name": "space:/app/device/list",
256
256
  "principal": {
257
257
  "kind": "space",
258
258
  "tenantId": "tenant",
@@ -261,7 +261,7 @@
261
261
  "memberRole": null,
262
262
  "tenantId": "tenant",
263
263
  "scopeId": "space",
264
- "target": "/app/device/brief/list",
264
+ "target": "/app/device/list",
265
265
  "allowed": true
266
266
  },
267
267
  {
@@ -343,7 +343,7 @@
343
343
  "allowed": false
344
344
  },
345
345
  {
346
- "name": "space-cannot-borrow-owner:/app/device/brief/list",
346
+ "name": "space-cannot-borrow-owner:/app/device/list",
347
347
  "principal": {
348
348
  "kind": "space",
349
349
  "tenantId": "tenant",
@@ -352,7 +352,7 @@
352
352
  "memberRole": "OWNER",
353
353
  "tenantId": "tenant",
354
354
  "scopeId": "space",
355
- "target": "/app/device/brief/list",
355
+ "target": "/app/device/list",
356
356
  "allowed": true
357
357
  },
358
358
  {
@@ -434,7 +434,7 @@
434
434
  "allowed": false
435
435
  },
436
436
  {
437
- "name": "foreign-space:/app/device/brief/list",
437
+ "name": "foreign-space:/app/device/list",
438
438
  "principal": {
439
439
  "kind": "space",
440
440
  "tenantId": "tenant",
@@ -443,7 +443,7 @@
443
443
  "memberRole": null,
444
444
  "tenantId": "tenant",
445
445
  "scopeId": "space",
446
- "target": "/app/device/brief/list",
446
+ "target": "/app/device/list",
447
447
  "allowed": false
448
448
  },
449
449
  {
@@ -525,7 +525,7 @@
525
525
  "allowed": false
526
526
  },
527
527
  {
528
- "name": "foreign-tenant:/app/device/brief/list",
528
+ "name": "foreign-tenant:/app/device/list",
529
529
  "principal": {
530
530
  "kind": "space",
531
531
  "tenantId": "other",
@@ -534,7 +534,7 @@
534
534
  "memberRole": null,
535
535
  "tenantId": "tenant",
536
536
  "scopeId": "space",
537
- "target": "/app/device/brief/list",
537
+ "target": "/app/device/list",
538
538
  "allowed": false
539
539
  },
540
540
  {