sinfactura-types 1.10.7 → 1.10.8
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/cjs/socket.js +76 -2
- package/dist/mercadolibre.d.ts +0 -60
- package/dist/print.d.ts +35 -1
- package/dist/socket.d.ts +116 -4
- package/dist/socket.js +74 -1
- package/package.json +1 -1
package/dist/cjs/socket.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* Management API → client. Nothing posts to a connection directly.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.isSocketKeepAlive = exports.SOCKET_KEEPALIVE = exports.SOCKET_AUTH_FAIL_REASONS = exports.LIVE_CLIENT_SOCKET_ACTIONS = exports.CLIENT_SOCKET_ACTIONS = exports.isSocketAction = exports.SOCKET_ACTIONS = void 0;
|
|
25
|
+
exports.isSocketKeepAlive = exports.SOCKET_KEEPALIVE = exports.SOCKET_AUTH_FAIL_REASONS = exports.LIVE_CLIENT_SOCKET_ACTIONS = exports.CLIENT_SOCKET_ACTIONS = exports.DESTRUCTIVE_AGENT_COMMANDS = exports.isAgentCommand = exports.AGENT_COMMANDS = exports.isSocketAction = exports.SOCKET_ACTIONS = void 0;
|
|
26
26
|
/* -------------------------------------------------------------------------- */
|
|
27
27
|
/* Server → client data frames */
|
|
28
28
|
/* -------------------------------------------------------------------------- */
|
|
@@ -109,6 +109,18 @@ exports.SOCKET_ACTIONS = [
|
|
|
109
109
|
// operator's pause toggle (api#2028). Payload is `PrintersActiveData`.
|
|
110
110
|
// Full replacement, never a delta; both unknowns fail OPEN (see that type).
|
|
111
111
|
'printers_active',
|
|
112
|
+
// BE → agent, scoped to ONE agent's own connections (like `printers_active`,
|
|
113
|
+
// never fanned to the store): run a local diagnostic/recovery action
|
|
114
|
+
// (print#224). Payload is `AgentCommandData`.
|
|
115
|
+
//
|
|
116
|
+
// ⚠️ NOT understood by any released agent. The agent routes inbound frames
|
|
117
|
+
// through a closed control-frame switch (`request_printers`,
|
|
118
|
+
// `printers_active`) and then a 4-member print-job enum; anything else lands
|
|
119
|
+
// in its "Unhandled frame" warn and is never executed or acknowledged. As of
|
|
120
|
+
// v2.2.2 that includes this action — print#224's agent lane must add the case
|
|
121
|
+
// before a producer can rely on it. Publishing it here first is deliberate, so
|
|
122
|
+
// all three lanes build against one `.d.ts`.
|
|
123
|
+
'agent_command',
|
|
112
124
|
// Operations / operator surfaces.
|
|
113
125
|
'logs',
|
|
114
126
|
'maintenance',
|
|
@@ -121,6 +133,55 @@ exports.SOCKET_ACTIONS = [
|
|
|
121
133
|
const isSocketAction = (value) => typeof value === 'string' && exports.SOCKET_ACTIONS.includes(value);
|
|
122
134
|
exports.isSocketAction = isSocketAction;
|
|
123
135
|
/* -------------------------------------------------------------------------- */
|
|
136
|
+
/* Agent diagnostic commands (print#224) */
|
|
137
|
+
/* -------------------------------------------------------------------------- */
|
|
138
|
+
/**
|
|
139
|
+
* The remote-triggerable diagnostic actions, in the agent's OWN spelling.
|
|
140
|
+
*
|
|
141
|
+
* **Kebab-case, verbatim from the agent's `DiagnosticActionId`** (print#223,
|
|
142
|
+
* shipped v2.2.2) — not the snake_case the rest of this file's ACTION names use.
|
|
143
|
+
* That is a deliberate trade. `sinfactura/print` does not depend on this package,
|
|
144
|
+
* so any renaming here has to be re-implemented as a mapping table on the agent
|
|
145
|
+
* side, where a drift is invisible to both ends until an operator reports that a
|
|
146
|
+
* button does nothing. Passing the agent's own ids through untouched removes the
|
|
147
|
+
* mapping layer entirely: the BE forwards a string the agent already keys on.
|
|
148
|
+
* The frame's ACTION (`agent_command`) stays snake_case like its siblings; this
|
|
149
|
+
* is the payload vocabulary, a different namespace.
|
|
150
|
+
*
|
|
151
|
+
* A command the agent does not recognise is safe by construction — its
|
|
152
|
+
* `runDiagnosticAction` returns a structured "unknown command" result instead of
|
|
153
|
+
* throwing — so an older agent degrades to a visible failure, not a crash.
|
|
154
|
+
*
|
|
155
|
+
* Two members of the originally-proposed set are absent on purpose:
|
|
156
|
+
*
|
|
157
|
+
* - **`view-logs`** exists on the agent but is not remotely meaningful. It opens
|
|
158
|
+
* the log FOLDER on the agent's own machine and resolves `ok: true`, so a
|
|
159
|
+
* remote operator would read "logs delivered" while a window opened on an
|
|
160
|
+
* unattended PC. Shipping logs BACK to the backend is a genuinely different
|
|
161
|
+
* capability that the agent does not have; it needs its own contract.
|
|
162
|
+
* - **`test_print`** is not an agent-local action at all. The backend dispatches
|
|
163
|
+
* a real job to an explicit printer (api#2041, shipped), so routing it through
|
|
164
|
+
* here would be a second way to do one thing — and the agent would reject it as
|
|
165
|
+
* an unknown command.
|
|
166
|
+
*/
|
|
167
|
+
exports.AGENT_COMMANDS = ['redetect-printers', 'reconnect-socket', 'flush-acks', 'clear-queue'];
|
|
168
|
+
/** Runtime guard — narrows an untrusted string to a known command. */
|
|
169
|
+
const isAgentCommand = (value) => typeof value === 'string' && exports.AGENT_COMMANDS.includes(value);
|
|
170
|
+
exports.isAgentCommand = isAgentCommand;
|
|
171
|
+
/**
|
|
172
|
+
* Commands that destroy operator data and MUST be confirmed before dispatch.
|
|
173
|
+
*
|
|
174
|
+
* Mirrors the agent's own `destructive` flag. The agent deliberately does not
|
|
175
|
+
* prompt inside `run()` — its confirmation lives in the DOM layer, which a remote
|
|
176
|
+
* trigger never reaches — so the "are you sure?" is the CALLER's job. For a
|
|
177
|
+
* remote command that means the app, before it asks the backend to dispatch.
|
|
178
|
+
*
|
|
179
|
+
* `clear-queue` deletes queued work that then never prints. print#235 (agent
|
|
180
|
+
* v2.2.3) stopped it destroying in-flight ACKs, but queued jobs are still lost,
|
|
181
|
+
* and the operator who loses them is not the one who pressed the button.
|
|
182
|
+
*/
|
|
183
|
+
exports.DESTRUCTIVE_AGENT_COMMANDS = ['clear-queue'];
|
|
184
|
+
/* -------------------------------------------------------------------------- */
|
|
124
185
|
/* Client → server frames */
|
|
125
186
|
/* -------------------------------------------------------------------------- */
|
|
126
187
|
/**
|
|
@@ -141,6 +202,14 @@ exports.isSocketAction = isSocketAction;
|
|
|
141
202
|
* shipped in 1.10.x, but the action string was never added to these two arrays —
|
|
142
203
|
* so `isClientSocketAction`-style checks and exhaustive switches keyed off
|
|
143
204
|
* `ClientSocketAction` silently excluded a live action. Corrected in 1.10.5.
|
|
205
|
+
*
|
|
206
|
+
* `agent_command_result` is declared but **NOT live** (print#224, 1.10.8): no
|
|
207
|
+
* `$default` union entry or handler exists for it yet, so the api answers it with
|
|
208
|
+
* `400 Invalid message`. It is in this array — the full vocabulary — and out of
|
|
209
|
+
* `LIVE_CLIENT_SOCKET_ACTIONS` below, which is exactly the distinction the two
|
|
210
|
+
* arrays exist to carry. Do not "fix the inconsistency" by adding it there; that
|
|
211
|
+
* is the inverse of the 1.10.5 bug, and it would tell a consumer the frame is
|
|
212
|
+
* accepted when it is rejected.
|
|
144
213
|
*/
|
|
145
214
|
exports.CLIENT_SOCKET_ACTIONS = [
|
|
146
215
|
'auth',
|
|
@@ -149,8 +218,13 @@ exports.CLIENT_SOCKET_ACTIONS = [
|
|
|
149
218
|
'ack',
|
|
150
219
|
'register_printers',
|
|
151
220
|
'export_local_rules',
|
|
221
|
+
'agent_command_result',
|
|
152
222
|
];
|
|
153
|
-
/**
|
|
223
|
+
/**
|
|
224
|
+
* Client→server actions the backend accepts **today** — a strict subset of
|
|
225
|
+
* `CLIENT_SOCKET_ACTIONS`. Anything declared but absent here is published ahead
|
|
226
|
+
* of its handler and will be rejected `400 Invalid message` on the wire.
|
|
227
|
+
*/
|
|
154
228
|
exports.LIVE_CLIENT_SOCKET_ACTIONS = [
|
|
155
229
|
'auth',
|
|
156
230
|
'logs',
|
package/dist/mercadolibre.d.ts
CHANGED
|
@@ -70,66 +70,6 @@ declare global {
|
|
|
70
70
|
currency: string;
|
|
71
71
|
paidAt?: number;
|
|
72
72
|
}
|
|
73
|
-
type GtinRequirementTag = "not_required" | "conditional_required" | "new_required";
|
|
74
|
-
interface MlAttribute {
|
|
75
|
-
id: string;
|
|
76
|
-
name?: string;
|
|
77
|
-
value_id?: string;
|
|
78
|
-
value_name?: string;
|
|
79
|
-
attribute_group_id?: string;
|
|
80
|
-
attribute_group_name?: string;
|
|
81
|
-
}
|
|
82
|
-
interface MlRequiredAttribute {
|
|
83
|
-
id: string;
|
|
84
|
-
name?: string;
|
|
85
|
-
required: boolean;
|
|
86
|
-
tags?: string[];
|
|
87
|
-
}
|
|
88
|
-
interface MlCategoryPrediction {
|
|
89
|
-
domainName: string;
|
|
90
|
-
categoryId: string;
|
|
91
|
-
categoryName: string;
|
|
92
|
-
attributes: MlAttribute[];
|
|
93
|
-
requiredAttributes: MlRequiredAttribute[];
|
|
94
|
-
immediatePayment?: "required" | "optional";
|
|
95
|
-
maxTitleLength?: number;
|
|
96
|
-
gtinRequirement: GtinRequirementTag;
|
|
97
|
-
}
|
|
98
|
-
interface MlCategoryCandidate {
|
|
99
|
-
domainId?: string;
|
|
100
|
-
domainName: string;
|
|
101
|
-
categoryId: string;
|
|
102
|
-
categoryName: string;
|
|
103
|
-
}
|
|
104
|
-
interface PublishPrediction extends MlCategoryPrediction {
|
|
105
|
-
isUpMigrated: boolean;
|
|
106
|
-
candidates: MlCategoryCandidate[];
|
|
107
|
-
}
|
|
108
|
-
interface MlCategoryAttributeSchema {
|
|
109
|
-
categoryId: string;
|
|
110
|
-
requiredAttributes: MlRequiredAttribute[];
|
|
111
|
-
gtinRequirement: GtinRequirementTag;
|
|
112
|
-
maxTitleLength?: number;
|
|
113
|
-
immediatePayment?: "required" | "optional";
|
|
114
|
-
}
|
|
115
|
-
interface MlPublishRequest {
|
|
116
|
-
productId: string;
|
|
117
|
-
categoryId: string;
|
|
118
|
-
attributes: MlAttribute[];
|
|
119
|
-
listingTypeId: string;
|
|
120
|
-
saleTerms?: Record<string, unknown>[];
|
|
121
|
-
pictures?: {
|
|
122
|
-
url: string;
|
|
123
|
-
}[];
|
|
124
|
-
description?: string;
|
|
125
|
-
}
|
|
126
|
-
interface MlPublishResponse {
|
|
127
|
-
productId: string;
|
|
128
|
-
itemId: string;
|
|
129
|
-
userProductId?: string;
|
|
130
|
-
isUpMigrated: boolean;
|
|
131
|
-
status: "linked";
|
|
132
|
-
}
|
|
133
73
|
interface MlFieldError {
|
|
134
74
|
field: string;
|
|
135
75
|
code?: string;
|
package/dist/print.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
declare global {
|
|
2
2
|
type PrintJobState = 'queued' | 'sent' | 'printed' | 'error';
|
|
3
3
|
type PrintContentType = 'pdf_uri' | 'pdf_base64' | 'raw_uri' | 'raw_base64';
|
|
4
|
+
/**
|
|
5
|
+
* A raw (non-PDF) control language a printer can be sent.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately NOT encoded into `PrintContentType`: that field says how the
|
|
8
|
+
* bytes ARRIVE (`raw_uri` vs `raw_base64`), not what dialect they are, and the
|
|
9
|
+
* two axes are independent — every format is transportable both ways. Widening
|
|
10
|
+
* `PrintContentType` to `raw_zpl_base64`-style members would multiply out to a
|
|
11
|
+
* member per (format × transport) pair and break every existing consumer that
|
|
12
|
+
* switches on it.
|
|
13
|
+
*/
|
|
14
|
+
type PrintRawFormat = 'zpl' | 'escpos';
|
|
4
15
|
interface PrintOptions {
|
|
5
16
|
bin?: string;
|
|
6
17
|
collate?: boolean;
|
|
@@ -157,6 +168,29 @@ declare global {
|
|
|
157
168
|
* survive a re-registration that omits it. `false` = do not route jobs here.
|
|
158
169
|
*/
|
|
159
170
|
active: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Raw control languages the OPERATOR declares this device understands.
|
|
173
|
+
* BE-owned and operator-set, exactly like `active` — never agent-reported.
|
|
174
|
+
*
|
|
175
|
+
* ⚠️ **Absent or empty means REFUSE all raw content.** This is the one field
|
|
176
|
+
* in the printer registry where absence is a "no" rather than a "not
|
|
177
|
+
* reported", and it inverts `PrintPrinterCapabilities`' core rule on purpose
|
|
178
|
+
* (`api/stacks/services/printRules.ts`: "Absent capabilities = not reported —
|
|
179
|
+
* accept everything"). That default is right for `paper`/`bins`/`dpis`, where
|
|
180
|
+
* guessing wrong wastes one job. Here, guessing wrong sends a ZPL stream to a
|
|
181
|
+
* laser printer, which does not error — it renders every command as text and
|
|
182
|
+
* puts a ream through the machine until someone physically cancels it. The
|
|
183
|
+
* spooler accepts the bytes, the agent ACKs `printed`, and the BE records
|
|
184
|
+
* success. So it cannot live in `capabilities`, or the next person to "fix
|
|
185
|
+
* the inconsistency" reopens the hole.
|
|
186
|
+
*
|
|
187
|
+
* It is also not something the agent could report honestly: it can read a
|
|
188
|
+
* driver string (`ZDesigner ZD420`), but a generic driver, a renamed queue or
|
|
189
|
+
* a shared network printer defeats that heuristic. And an agent-reported
|
|
190
|
+
* field is overwritten on every re-registration — the same bug `active` is
|
|
191
|
+
* shaped to avoid, with a worse outcome than an un-paused printer.
|
|
192
|
+
*/
|
|
193
|
+
rawFormats?: PrintRawFormat[];
|
|
160
194
|
/** ms epoch of the last `register_printers` report that included this printer. */
|
|
161
195
|
reportedAt: number;
|
|
162
196
|
/**
|
|
@@ -177,7 +211,7 @@ declare global {
|
|
|
177
211
|
* wholesale would silently reset the operator's per-printer pause toggle on
|
|
178
212
|
* every agent restart.
|
|
179
213
|
*/
|
|
180
|
-
type PrintPrinterReport = Omit<PrintPrinter, 'agentId' | 'active' | 'reportedAt' | 'online'>;
|
|
214
|
+
type PrintPrinterReport = Omit<PrintPrinter, 'agentId' | 'active' | 'reportedAt' | 'online' | 'rawFormats'>;
|
|
181
215
|
/**
|
|
182
216
|
* payload of the agent → BE `register_printers` WSS frame. ⚠️ That frame is
|
|
183
217
|
* **FLAT** — `{ action, printers }`, NOT `{ action, data }` (api#2017); this type
|
package/dist/socket.d.ts
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* (`wsPostStore`). A client must ignore actions it does not own rather than
|
|
35
35
|
* assume it receives all of them.
|
|
36
36
|
*/
|
|
37
|
-
export declare const SOCKET_ACTIONS: readonly ["account", "baskets", "brands", "cash", "categories", "customers", "globals", "invoices", "literals", "orders", "products", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "favorites", "account-delete", "baskets-delete", "log-delete", "notifications", "support-message", "whatsapp-message", "payment_received", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "print_rules_changed", "printers_active", "logs", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded"];
|
|
37
|
+
export declare const SOCKET_ACTIONS: readonly ["account", "baskets", "brands", "cash", "categories", "customers", "globals", "invoices", "literals", "orders", "products", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "favorites", "account-delete", "baskets-delete", "log-delete", "notifications", "support-message", "whatsapp-message", "payment_received", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "print_rules_changed", "printers_active", "agent_command", "logs", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded"];
|
|
38
38
|
/** Union of every server→client data-frame action. */
|
|
39
39
|
export type SocketAction = (typeof SOCKET_ACTIONS)[number];
|
|
40
40
|
/** Runtime guard — narrows an untrusted string to a known action. */
|
|
@@ -50,6 +50,106 @@ export interface SocketMessage<T = unknown> {
|
|
|
50
50
|
action: SocketAction;
|
|
51
51
|
data: T;
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* The remote-triggerable diagnostic actions, in the agent's OWN spelling.
|
|
55
|
+
*
|
|
56
|
+
* **Kebab-case, verbatim from the agent's `DiagnosticActionId`** (print#223,
|
|
57
|
+
* shipped v2.2.2) — not the snake_case the rest of this file's ACTION names use.
|
|
58
|
+
* That is a deliberate trade. `sinfactura/print` does not depend on this package,
|
|
59
|
+
* so any renaming here has to be re-implemented as a mapping table on the agent
|
|
60
|
+
* side, where a drift is invisible to both ends until an operator reports that a
|
|
61
|
+
* button does nothing. Passing the agent's own ids through untouched removes the
|
|
62
|
+
* mapping layer entirely: the BE forwards a string the agent already keys on.
|
|
63
|
+
* The frame's ACTION (`agent_command`) stays snake_case like its siblings; this
|
|
64
|
+
* is the payload vocabulary, a different namespace.
|
|
65
|
+
*
|
|
66
|
+
* A command the agent does not recognise is safe by construction — its
|
|
67
|
+
* `runDiagnosticAction` returns a structured "unknown command" result instead of
|
|
68
|
+
* throwing — so an older agent degrades to a visible failure, not a crash.
|
|
69
|
+
*
|
|
70
|
+
* Two members of the originally-proposed set are absent on purpose:
|
|
71
|
+
*
|
|
72
|
+
* - **`view-logs`** exists on the agent but is not remotely meaningful. It opens
|
|
73
|
+
* the log FOLDER on the agent's own machine and resolves `ok: true`, so a
|
|
74
|
+
* remote operator would read "logs delivered" while a window opened on an
|
|
75
|
+
* unattended PC. Shipping logs BACK to the backend is a genuinely different
|
|
76
|
+
* capability that the agent does not have; it needs its own contract.
|
|
77
|
+
* - **`test_print`** is not an agent-local action at all. The backend dispatches
|
|
78
|
+
* a real job to an explicit printer (api#2041, shipped), so routing it through
|
|
79
|
+
* here would be a second way to do one thing — and the agent would reject it as
|
|
80
|
+
* an unknown command.
|
|
81
|
+
*/
|
|
82
|
+
export declare const AGENT_COMMANDS: readonly ["redetect-printers", "reconnect-socket", "flush-acks", "clear-queue"];
|
|
83
|
+
/** Union of every remote-triggerable diagnostic command. */
|
|
84
|
+
export type AgentCommand = (typeof AGENT_COMMANDS)[number];
|
|
85
|
+
/** Runtime guard — narrows an untrusted string to a known command. */
|
|
86
|
+
export declare const isAgentCommand: (value: unknown) => value is AgentCommand;
|
|
87
|
+
/**
|
|
88
|
+
* Commands that destroy operator data and MUST be confirmed before dispatch.
|
|
89
|
+
*
|
|
90
|
+
* Mirrors the agent's own `destructive` flag. The agent deliberately does not
|
|
91
|
+
* prompt inside `run()` — its confirmation lives in the DOM layer, which a remote
|
|
92
|
+
* trigger never reaches — so the "are you sure?" is the CALLER's job. For a
|
|
93
|
+
* remote command that means the app, before it asks the backend to dispatch.
|
|
94
|
+
*
|
|
95
|
+
* `clear-queue` deletes queued work that then never prints. print#235 (agent
|
|
96
|
+
* v2.2.3) stopped it destroying in-flight ACKs, but queued jobs are still lost,
|
|
97
|
+
* and the operator who loses them is not the one who pressed the button.
|
|
98
|
+
*/
|
|
99
|
+
export declare const DESTRUCTIVE_AGENT_COMMANDS: readonly AgentCommand[];
|
|
100
|
+
/**
|
|
101
|
+
* `data` payload of the BE → agent `agent_command` frame — nested,
|
|
102
|
+
* `{ action: 'agent_command', data: AgentCommandData }`, like every other
|
|
103
|
+
* server→client frame.
|
|
104
|
+
*
|
|
105
|
+
* Declared here rather than beside `PrintersActiveData` in `print.ts` because it
|
|
106
|
+
* references `AgentCommand`, which is derived from the runtime `AGENT_COMMANDS`
|
|
107
|
+
* array above; re-declaring the vocabulary as an ambient type would give it two
|
|
108
|
+
* sources that drift independently.
|
|
109
|
+
*/
|
|
110
|
+
export interface AgentCommandData {
|
|
111
|
+
command: AgentCommand;
|
|
112
|
+
/**
|
|
113
|
+
* The target agent. Advisory for the agent itself — the BE has already scoped
|
|
114
|
+
* delivery to that agent's connections — but carried so the agent can drop a
|
|
115
|
+
* frame that reached it through a mis-scoped broadcast rather than acting on
|
|
116
|
+
* another machine's instruction.
|
|
117
|
+
*/
|
|
118
|
+
agentId: string;
|
|
119
|
+
/**
|
|
120
|
+
* Stable per-dispatch id. **Required, never optional.**
|
|
121
|
+
*
|
|
122
|
+
* The wss `$default` route has a bare Lambda integration and no route
|
|
123
|
+
* response, so a frame the agent sends can never fail visibly to it. Delivery
|
|
124
|
+
* therefore has to be idempotent-and-repeatable rather than once-and-hope,
|
|
125
|
+
* and a re-dispatch needs a stable id for the agent to deduplicate on and for
|
|
126
|
+
* the backend to match a late result against.
|
|
127
|
+
*/
|
|
128
|
+
commandId: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Agent → BE outcome of one `agent_command`.
|
|
132
|
+
*
|
|
133
|
+
* ⚠️ **A report, not an acknowledgement of delivery.** The agent cannot observe
|
|
134
|
+
* whether the backend received this frame (see `commandId`), so "did the command
|
|
135
|
+
* work" is a question the BACKEND answers by reconciling its own dispatch state —
|
|
136
|
+
* never one the agent can settle by sending this.
|
|
137
|
+
*
|
|
138
|
+
* Note that `ok: false` is not necessarily a failure of the action: the agent
|
|
139
|
+
* guards every command with a 3s per-action cooldown and an in-flight lock, and
|
|
140
|
+
* a refusal from either returns `ok: false` with an operator-facing message
|
|
141
|
+
* ("Esperá unos segundos…"). Surface `message`; do not translate `ok: false`
|
|
142
|
+
* into "the agent is broken".
|
|
143
|
+
*/
|
|
144
|
+
export interface SocketAgentCommandResultMessage {
|
|
145
|
+
action: 'agent_command_result';
|
|
146
|
+
/** Echoes `AgentCommandData.commandId` — the only way to match a result to its dispatch. */
|
|
147
|
+
commandId: string;
|
|
148
|
+
ok: boolean;
|
|
149
|
+
/** Operator-facing, Spanish voseo, always non-empty. Produced by the agent. */
|
|
150
|
+
message: string;
|
|
151
|
+
[key: string]: unknown;
|
|
152
|
+
}
|
|
53
153
|
/**
|
|
54
154
|
* The client-driven actions the WSS `$default` route accepts.
|
|
55
155
|
*
|
|
@@ -68,11 +168,23 @@ export interface SocketMessage<T = unknown> {
|
|
|
68
168
|
* shipped in 1.10.x, but the action string was never added to these two arrays —
|
|
69
169
|
* so `isClientSocketAction`-style checks and exhaustive switches keyed off
|
|
70
170
|
* `ClientSocketAction` silently excluded a live action. Corrected in 1.10.5.
|
|
171
|
+
*
|
|
172
|
+
* `agent_command_result` is declared but **NOT live** (print#224, 1.10.8): no
|
|
173
|
+
* `$default` union entry or handler exists for it yet, so the api answers it with
|
|
174
|
+
* `400 Invalid message`. It is in this array — the full vocabulary — and out of
|
|
175
|
+
* `LIVE_CLIENT_SOCKET_ACTIONS` below, which is exactly the distinction the two
|
|
176
|
+
* arrays exist to carry. Do not "fix the inconsistency" by adding it there; that
|
|
177
|
+
* is the inverse of the 1.10.5 bug, and it would tell a consumer the frame is
|
|
178
|
+
* accepted when it is rejected.
|
|
71
179
|
*/
|
|
72
|
-
export declare const CLIENT_SOCKET_ACTIONS: readonly ["auth", "logs", "heartbeat", "ack", "register_printers", "export_local_rules"];
|
|
180
|
+
export declare const CLIENT_SOCKET_ACTIONS: readonly ["auth", "logs", "heartbeat", "ack", "register_printers", "export_local_rules", "agent_command_result"];
|
|
73
181
|
/** Union of every client→server action. */
|
|
74
182
|
export type ClientSocketAction = (typeof CLIENT_SOCKET_ACTIONS)[number];
|
|
75
|
-
/**
|
|
183
|
+
/**
|
|
184
|
+
* Client→server actions the backend accepts **today** — a strict subset of
|
|
185
|
+
* `CLIENT_SOCKET_ACTIONS`. Anything declared but absent here is published ahead
|
|
186
|
+
* of its handler and will be rejected `400 Invalid message` on the wire.
|
|
187
|
+
*/
|
|
76
188
|
export declare const LIVE_CLIENT_SOCKET_ACTIONS: readonly ["auth", "logs", "heartbeat", "ack", "register_printers", "export_local_rules"];
|
|
77
189
|
/** Authenticate the connection. Must be the first frame; see `AuthAckFrame`. */
|
|
78
190
|
export interface SocketAuthMessage {
|
|
@@ -167,7 +279,7 @@ export interface SocketExportLocalRulesMessage {
|
|
|
167
279
|
[key: string]: unknown;
|
|
168
280
|
}
|
|
169
281
|
/** Any client→server JSON frame. */
|
|
170
|
-
export type ClientSocketMessage = SocketAuthMessage | SocketLogsMessage | SocketHeartbeatMessage | SocketAckMessage | SocketRegisterPrintersMessage | SocketExportLocalRulesMessage;
|
|
282
|
+
export type ClientSocketMessage = SocketAuthMessage | SocketLogsMessage | SocketHeartbeatMessage | SocketAckMessage | SocketRegisterPrintersMessage | SocketExportLocalRulesMessage | SocketAgentCommandResultMessage;
|
|
171
283
|
/**
|
|
172
284
|
* Why the backend refused the handshake (api#977 / app#1353).
|
|
173
285
|
*
|
package/dist/socket.js
CHANGED
|
@@ -106,6 +106,18 @@ export const SOCKET_ACTIONS = [
|
|
|
106
106
|
// operator's pause toggle (api#2028). Payload is `PrintersActiveData`.
|
|
107
107
|
// Full replacement, never a delta; both unknowns fail OPEN (see that type).
|
|
108
108
|
'printers_active',
|
|
109
|
+
// BE → agent, scoped to ONE agent's own connections (like `printers_active`,
|
|
110
|
+
// never fanned to the store): run a local diagnostic/recovery action
|
|
111
|
+
// (print#224). Payload is `AgentCommandData`.
|
|
112
|
+
//
|
|
113
|
+
// ⚠️ NOT understood by any released agent. The agent routes inbound frames
|
|
114
|
+
// through a closed control-frame switch (`request_printers`,
|
|
115
|
+
// `printers_active`) and then a 4-member print-job enum; anything else lands
|
|
116
|
+
// in its "Unhandled frame" warn and is never executed or acknowledged. As of
|
|
117
|
+
// v2.2.2 that includes this action — print#224's agent lane must add the case
|
|
118
|
+
// before a producer can rely on it. Publishing it here first is deliberate, so
|
|
119
|
+
// all three lanes build against one `.d.ts`.
|
|
120
|
+
'agent_command',
|
|
109
121
|
// Operations / operator surfaces.
|
|
110
122
|
'logs',
|
|
111
123
|
'maintenance',
|
|
@@ -117,6 +129,54 @@ export const SOCKET_ACTIONS = [
|
|
|
117
129
|
/** Runtime guard — narrows an untrusted string to a known action. */
|
|
118
130
|
export const isSocketAction = (value) => typeof value === 'string' && SOCKET_ACTIONS.includes(value);
|
|
119
131
|
/* -------------------------------------------------------------------------- */
|
|
132
|
+
/* Agent diagnostic commands (print#224) */
|
|
133
|
+
/* -------------------------------------------------------------------------- */
|
|
134
|
+
/**
|
|
135
|
+
* The remote-triggerable diagnostic actions, in the agent's OWN spelling.
|
|
136
|
+
*
|
|
137
|
+
* **Kebab-case, verbatim from the agent's `DiagnosticActionId`** (print#223,
|
|
138
|
+
* shipped v2.2.2) — not the snake_case the rest of this file's ACTION names use.
|
|
139
|
+
* That is a deliberate trade. `sinfactura/print` does not depend on this package,
|
|
140
|
+
* so any renaming here has to be re-implemented as a mapping table on the agent
|
|
141
|
+
* side, where a drift is invisible to both ends until an operator reports that a
|
|
142
|
+
* button does nothing. Passing the agent's own ids through untouched removes the
|
|
143
|
+
* mapping layer entirely: the BE forwards a string the agent already keys on.
|
|
144
|
+
* The frame's ACTION (`agent_command`) stays snake_case like its siblings; this
|
|
145
|
+
* is the payload vocabulary, a different namespace.
|
|
146
|
+
*
|
|
147
|
+
* A command the agent does not recognise is safe by construction — its
|
|
148
|
+
* `runDiagnosticAction` returns a structured "unknown command" result instead of
|
|
149
|
+
* throwing — so an older agent degrades to a visible failure, not a crash.
|
|
150
|
+
*
|
|
151
|
+
* Two members of the originally-proposed set are absent on purpose:
|
|
152
|
+
*
|
|
153
|
+
* - **`view-logs`** exists on the agent but is not remotely meaningful. It opens
|
|
154
|
+
* the log FOLDER on the agent's own machine and resolves `ok: true`, so a
|
|
155
|
+
* remote operator would read "logs delivered" while a window opened on an
|
|
156
|
+
* unattended PC. Shipping logs BACK to the backend is a genuinely different
|
|
157
|
+
* capability that the agent does not have; it needs its own contract.
|
|
158
|
+
* - **`test_print`** is not an agent-local action at all. The backend dispatches
|
|
159
|
+
* a real job to an explicit printer (api#2041, shipped), so routing it through
|
|
160
|
+
* here would be a second way to do one thing — and the agent would reject it as
|
|
161
|
+
* an unknown command.
|
|
162
|
+
*/
|
|
163
|
+
export const AGENT_COMMANDS = ['redetect-printers', 'reconnect-socket', 'flush-acks', 'clear-queue'];
|
|
164
|
+
/** Runtime guard — narrows an untrusted string to a known command. */
|
|
165
|
+
export const isAgentCommand = (value) => typeof value === 'string' && AGENT_COMMANDS.includes(value);
|
|
166
|
+
/**
|
|
167
|
+
* Commands that destroy operator data and MUST be confirmed before dispatch.
|
|
168
|
+
*
|
|
169
|
+
* Mirrors the agent's own `destructive` flag. The agent deliberately does not
|
|
170
|
+
* prompt inside `run()` — its confirmation lives in the DOM layer, which a remote
|
|
171
|
+
* trigger never reaches — so the "are you sure?" is the CALLER's job. For a
|
|
172
|
+
* remote command that means the app, before it asks the backend to dispatch.
|
|
173
|
+
*
|
|
174
|
+
* `clear-queue` deletes queued work that then never prints. print#235 (agent
|
|
175
|
+
* v2.2.3) stopped it destroying in-flight ACKs, but queued jobs are still lost,
|
|
176
|
+
* and the operator who loses them is not the one who pressed the button.
|
|
177
|
+
*/
|
|
178
|
+
export const DESTRUCTIVE_AGENT_COMMANDS = ['clear-queue'];
|
|
179
|
+
/* -------------------------------------------------------------------------- */
|
|
120
180
|
/* Client → server frames */
|
|
121
181
|
/* -------------------------------------------------------------------------- */
|
|
122
182
|
/**
|
|
@@ -137,6 +197,14 @@ export const isSocketAction = (value) => typeof value === 'string' && SOCKET_ACT
|
|
|
137
197
|
* shipped in 1.10.x, but the action string was never added to these two arrays —
|
|
138
198
|
* so `isClientSocketAction`-style checks and exhaustive switches keyed off
|
|
139
199
|
* `ClientSocketAction` silently excluded a live action. Corrected in 1.10.5.
|
|
200
|
+
*
|
|
201
|
+
* `agent_command_result` is declared but **NOT live** (print#224, 1.10.8): no
|
|
202
|
+
* `$default` union entry or handler exists for it yet, so the api answers it with
|
|
203
|
+
* `400 Invalid message`. It is in this array — the full vocabulary — and out of
|
|
204
|
+
* `LIVE_CLIENT_SOCKET_ACTIONS` below, which is exactly the distinction the two
|
|
205
|
+
* arrays exist to carry. Do not "fix the inconsistency" by adding it there; that
|
|
206
|
+
* is the inverse of the 1.10.5 bug, and it would tell a consumer the frame is
|
|
207
|
+
* accepted when it is rejected.
|
|
140
208
|
*/
|
|
141
209
|
export const CLIENT_SOCKET_ACTIONS = [
|
|
142
210
|
'auth',
|
|
@@ -145,8 +213,13 @@ export const CLIENT_SOCKET_ACTIONS = [
|
|
|
145
213
|
'ack',
|
|
146
214
|
'register_printers',
|
|
147
215
|
'export_local_rules',
|
|
216
|
+
'agent_command_result',
|
|
148
217
|
];
|
|
149
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* Client→server actions the backend accepts **today** — a strict subset of
|
|
220
|
+
* `CLIENT_SOCKET_ACTIONS`. Anything declared but absent here is published ahead
|
|
221
|
+
* of its handler and will be rejected `400 Invalid message` on the wire.
|
|
222
|
+
*/
|
|
150
223
|
export const LIVE_CLIENT_SOCKET_ACTIONS = [
|
|
151
224
|
'auth',
|
|
152
225
|
'logs',
|