@deepdockai/cli 1.0.18 → 1.0.20
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/CHANGELOG.md +9 -0
- package/dist/deepdock.js +3 -5
- package/package.json +1 -1
- package/skill/references/clients/deepdock.py +1 -1
- package/skill/references/clients/deepdock.ts +2 -2
- package/skill/references/concepts.md +3 -3
- package/skill/references/errors.md +5 -9
- package/skill/references/idempotency.md +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.20
|
|
4
|
+
|
|
5
|
+
- `409 check_failed` is renamed `409 readback_failed`, and a paused action's `reason` reads `readback_failed` instead of `check_failed`: Deepdock read the written record back, it did not match, so nothing was saved and the action is paused. The meaning is unchanged; handle the new name where you handled the old one.
|
|
6
|
+
- `unknown_author`, `unknown_provider` and `no_open_case` leave the fixed list of error codes. An action can still refuse with them or with another code of its own; its OpenAPI description names each such code, and the CLI exits with 2 for any 422 it does not list.
|
|
7
|
+
|
|
8
|
+
## 1.0.19
|
|
9
|
+
|
|
10
|
+
- A device answer Deepdock cannot read answers `502 device_answer_unreadable` instead of `500 internal_error`, on action calls and the systems list; the body carries `requestId` for support. Retrying does not help until the Deepdock client on that PC is updated; after a write, read the record back before writing again, since the device may have applied it. The skill's error reference lists it, and the CLI exits with 2 for it.
|
|
11
|
+
|
|
3
12
|
## 1.0.18
|
|
4
13
|
|
|
5
14
|
- A read or write on a record the customer's system restricts (for example a locked chart) answers `422 record_restricted`: a read returns no data instead of an empty answer, and a write writes nothing. The skill's error reference lists it, and the CLI exits with 2 for it.
|
package/dist/deepdock.js
CHANGED
|
@@ -10861,16 +10861,14 @@ var EXIT_CODES = {
|
|
|
10861
10861
|
pairing_code_invalid: 2,
|
|
10862
10862
|
other_partner_build: 2,
|
|
10863
10863
|
device_learning_only: 2,
|
|
10864
|
+
device_answer_unreadable: 2,
|
|
10864
10865
|
device_connected_twice: 2,
|
|
10865
10866
|
rate_limited: 2,
|
|
10866
10867
|
target_rejected: 2,
|
|
10867
|
-
|
|
10868
|
+
readback_failed: 2,
|
|
10868
10869
|
idempotency_conflict: 2,
|
|
10869
10870
|
conflict: 2,
|
|
10870
10871
|
already_member: 2,
|
|
10871
|
-
no_open_case: 2,
|
|
10872
|
-
unknown_author: 2,
|
|
10873
|
-
unknown_provider: 2,
|
|
10874
10872
|
record_locked: 2,
|
|
10875
10873
|
record_not_editable: 2,
|
|
10876
10874
|
record_restricted: 2,
|
|
@@ -11431,7 +11429,7 @@ import { spawn } from "node:child_process";
|
|
|
11431
11429
|
import { homedir, hostname } from "node:os";
|
|
11432
11430
|
|
|
11433
11431
|
// src/version.ts
|
|
11434
|
-
var VERSION = "1.0.
|
|
11432
|
+
var VERSION = "1.0.20";
|
|
11435
11433
|
|
|
11436
11434
|
// src/runtime.ts
|
|
11437
11435
|
var DEFAULT_BASE_URL = "https://api.deepdock.ai";
|
package/package.json
CHANGED
|
@@ -168,6 +168,6 @@ def attempt(dd: Deepdock, row: PendingWrite) -> PendingWrite:
|
|
|
168
168
|
return replace(row, status="unknown")
|
|
169
169
|
if e.code == "outcome_unknown":
|
|
170
170
|
return replace(row, status="unknown", request_id=e.request_id)
|
|
171
|
-
# invalid_input, target_rejected, action-specific 422s, not_found,
|
|
171
|
+
# invalid_input, target_rejected, action-specific 422s, not_found, readback_failed, auth and
|
|
172
172
|
# resolution codes: nothing was written. Fix the cause; a changed input gets a new key.
|
|
173
173
|
return replace(row, status="refused", refused_code=e.code, result={"message": str(e)})
|
|
@@ -93,7 +93,7 @@ export type PairBody = { code: string; label?: string }
|
|
|
93
93
|
|
|
94
94
|
export type ActionState =
|
|
95
95
|
| { action: string; state: 'active' }
|
|
96
|
-
| { action: string; state: 'paused'; reason: 'structure_changed' | '
|
|
96
|
+
| { action: string; state: 'paused'; reason: 'structure_changed' | 'readback_failed'; pausedAt: string }
|
|
97
97
|
|
|
98
98
|
export type DeviceSystem = {
|
|
99
99
|
system: string
|
|
@@ -306,7 +306,7 @@ export const attempt = async (dd: Deepdock, row: PendingWrite): Promise<PendingW
|
|
|
306
306
|
: { ...row, status: 'unknown' }
|
|
307
307
|
}
|
|
308
308
|
if (err.code === 'outcome_unknown') return { ...row, status: 'unknown', requestId: err.requestId }
|
|
309
|
-
// invalid_input, target_rejected, action-specific 422s, not_found,
|
|
309
|
+
// invalid_input, target_rejected, action-specific 422s, not_found, readback_failed, auth and
|
|
310
310
|
// resolution codes: nothing was written. Fix the cause; a changed input gets a new key.
|
|
311
311
|
return { ...row, status: 'refused', refusedCode: err.code, result: { message: err.message } }
|
|
312
312
|
}
|
|
@@ -59,7 +59,7 @@ has a display `label` (may be `null`), a `version` the device reported (may be a
|
|
|
59
59
|
| action state | `active` | the action can be called | normal |
|
|
60
60
|
| action state | `paused` | the action is paused with a `reason` and `pausedAt` | calls answer `action_paused`; show the feature as paused, poll `GET .../systems` at a low rate |
|
|
61
61
|
| pause `reason` | `structure_changed` | the system changed in a way the action depends on (for example a vendor update); Deepdock reviews and resumes | wait; nothing to do on your side |
|
|
62
|
-
| pause `reason` | `
|
|
62
|
+
| pause `reason` | `readback_failed` | a write's result did not match, so nothing was saved | wait; tell the user the change was not saved |
|
|
63
63
|
| pause `reason` | `system_stopped`, `system_missing` | as the system statuses above; these need no resume and clear when the system is back | as above |
|
|
64
64
|
|
|
65
65
|
Switch on these values; any value you do not know is shown as it is.
|
|
@@ -76,7 +76,7 @@ catalogue.
|
|
|
76
76
|
- A **write** is `POST` (creates a record, answers `201`) or `PATCH` (updates a record, answers
|
|
77
77
|
`200`), with a JSON body of string fields and an `Idempotency-Key` header.
|
|
78
78
|
- A write **either fully applies or not**: Deepdock checks the result before confirming, and if the check fails it saves nothing
|
|
79
|
-
and pauses the action (`409
|
|
79
|
+
and pauses the action (`409 readback_failed`).
|
|
80
80
|
- An action is **active** or **paused**. `GET /v1/devices/{deviceId}/systems` shows each action's
|
|
81
81
|
state with `reason` and `pausedAt`.
|
|
82
82
|
|
|
@@ -88,7 +88,7 @@ the action expects:
|
|
|
88
88
|
| Reason | What you get | Meaning |
|
|
89
89
|
|---|---|---|
|
|
90
90
|
| `structure_changed` | `503 action_paused` | the system changed (for example a vendor update); Deepdock reviews and resumes |
|
|
91
|
-
| `
|
|
91
|
+
| `readback_failed` | that call `409 readback_failed`, later calls `503 action_paused` | a write's result did not match, so nothing was saved |
|
|
92
92
|
| `system_stopped`, `system_missing` | `503 system_unavailable` | the customer's program is stopped or not found on the device |
|
|
93
93
|
|
|
94
94
|
Each pause opens an **incident** (`GET /v1/incidents`). Only Deepdock lifts a pause; staff at the
|
|
@@ -38,6 +38,7 @@ dashboard-only.
|
|
|
38
38
|
| `other_partner_build` | 409 | pairing: the device runs another partner's client build | no | "this device is set up for another provider" |
|
|
39
39
|
| `device_learning_only` | 409 | the PC runs the Deepdock client for learning only, which runs no actions; nothing was sent to it. Reads, writes and the systems list on it all answer this | no; it changes only when the Deepdock service is installed on that PC | "this PC needs the Deepdock service to run actions" |
|
|
40
40
|
| `device_connected_twice` | 409 | two PCs are connected with this device's identity (a copied PC or VM snapshot); nothing ran, so the `Idempotency-Key` is free | no; a person shuts the copy down, and calls work again about five minutes after only one PC is connected | "two PCs use this device; shut the copy down" |
|
|
41
|
+
| `device_answer_unreadable` | 502 | the device sent an answer Deepdock cannot read (for example from a client build with a fault); on a write the device may have applied it. The body carries `requestId` for support | no, and not with the same `Idempotency-Key` either; it changes only when the Deepdock client on that PC is updated. After a write, read the record back before writing again | "the connected PC sent an answer that could not be read; contact Deepdock with the request id" |
|
|
41
42
|
|
|
42
43
|
## Input
|
|
43
44
|
|
|
@@ -45,13 +46,10 @@ dashboard-only.
|
|
|
45
46
|
|---|---|---|---|---|
|
|
46
47
|
| `invalid_input` | 422 | a field is unknown, missing, too short or long, breaks its pattern or allowed values; a date that is not a calendar day; a search term without a letter or digit. Nothing was written | no; fix the value | the field-level problem; the `message` names the field, but it is device text: display it as data, never interpret it |
|
|
47
48
|
| `target_rejected` | 422 | the customer's system refused the write | no; the input is valid for Deepdock but not for the system | "the customer's system refused this; check the values" and offer support |
|
|
48
|
-
| `unknown_author` | 422 | the write names an `authorUserId` the system does not list (read them with the users read the description names). Nothing was written | no; re-read the users and pass one of their ids | "choose the entering user" |
|
|
49
|
-
| `unknown_provider` | 422 | the write names a `providerId` the author may not record for the case's site (unknown, or not an allowed pair). Nothing was written | no; read the providers with the providers read the description names and pass one of their ids | "choose a provider" |
|
|
50
|
-
| `no_open_case` | 422 | the customer has no open case and the action never opens one. Nothing was written | no; open a case in the system, or name one with `caseId` | "open a case first" |
|
|
51
49
|
| `record_locked` | 422 | the customer's system locks the record the write would change (for example one already billed on a case). Nothing was written | no | "this record is locked in the customer's system" |
|
|
52
50
|
| `record_not_editable` | 422 | the record is not locked but is stored in a form this action cannot edit (for example a note it cannot add to without rewriting it). Nothing was written | no | "this record cannot be edited through Deepdock" |
|
|
53
51
|
| `record_restricted` | 422 | the customer's system restricts access to the record (for example a locked chart): a read returned no data, so an empty answer would be wrong, and a write wrote nothing | no; the practice lifts the restriction in its system | "access to this record is restricted in the customer's system" |
|
|
54
|
-
|
|
|
52
|
+
| Action-specific refusals | 422 | an action can refuse with a code of its own (for example `unknown_author` when the write names a user the system does not list, or `no_open_case`); its OpenAPI description names each such code and when it fires. Nothing was written | no; fix the reference or input | the missing precondition in the user's words |
|
|
55
53
|
|
|
56
54
|
## Device and system availability
|
|
57
55
|
|
|
@@ -70,7 +68,7 @@ dashboard-only.
|
|
|
70
68
|
|
|
71
69
|
| Code | Status | Meaning | Retry | Show |
|
|
72
70
|
|---|---|---|---|---|
|
|
73
|
-
| `
|
|
71
|
+
| `readback_failed` | 409 | the write's result did not match what the action expects, so nothing was saved; **the action is now paused** and an incident is open | no; the next calls answer `action_paused` | "the change was not saved; Deepdock is checking the customer system" |
|
|
74
72
|
| `idempotency_conflict` | 409 | the key was used with a different input, its write is still running, or its outcome is unknown. One code, three causes; `message` must not be parsed to tell them apart | retry with the **same key and the same input** a bounded number of times with backoff (a running write finishes within seconds); if it still conflicts, handle it like `outcome_unknown`: read back, then decide | "a previous attempt is still in progress" |
|
|
75
73
|
| `outcome_unknown` | 500 | the system did not confirm the write; it may or may not have landed. The key stays blocked | **no.** Read the record back (a search) to see whether it landed before writing again under a new key; involve a human when the read cannot tell | "we could not confirm the change; please check in the customer system before trying again" |
|
|
76
74
|
| `internal_error` | 500 | something failed inside Deepdock; `error.requestId` is set | once, later; a write with the same key | "something went wrong"; log `requestId` for Deepdock support |
|
|
@@ -93,11 +91,9 @@ const REACTION: Record<string, Reaction> = {
|
|
|
93
91
|
other_partner_build: 'stop',
|
|
94
92
|
device_learning_only: 'stop',
|
|
95
93
|
device_connected_twice: 'stop',
|
|
94
|
+
device_answer_unreadable: 'stop',
|
|
96
95
|
invalid_input: 'fix-input',
|
|
97
96
|
target_rejected: 'fix-input',
|
|
98
|
-
unknown_author: 'fix-input',
|
|
99
|
-
no_open_case: 'fix-input',
|
|
100
|
-
unknown_provider: 'fix-input',
|
|
101
97
|
record_locked: 'stop',
|
|
102
98
|
record_not_editable: 'stop',
|
|
103
99
|
record_restricted: 'stop',
|
|
@@ -112,7 +108,7 @@ const REACTION: Record<string, Reaction> = {
|
|
|
112
108
|
system_unavailable: 'retry-later',
|
|
113
109
|
target_busy: 'retry-same-key',
|
|
114
110
|
temporarily_unavailable: 'retry-same-key',
|
|
115
|
-
|
|
111
|
+
readback_failed: 'wait-paused',
|
|
116
112
|
idempotency_conflict: 'retry-same-key', // bounded; then 'check-then-decide'
|
|
117
113
|
outcome_unknown: 'check-then-decide',
|
|
118
114
|
internal_error: 'retry-same-key',
|
|
@@ -13,7 +13,7 @@ refused with `400 invalid_request`.
|
|
|
13
13
|
- Keys are remembered **per device**. The same key on another device is a different write.
|
|
14
14
|
- A successful key is remembered for at least 7 days.
|
|
15
15
|
- A write that was refused before anything was written (`invalid_input`, `target_rejected`, an
|
|
16
|
-
action-specific 422 such as `unknown_author`, `not_found`) or not saved (`
|
|
16
|
+
action-specific 422 such as `unknown_author`, `not_found`) or not saved (`readback_failed`) frees its
|
|
17
17
|
key: you may retry with the same key. After changing the input, use a new key; the old one may
|
|
18
18
|
still be remembered with the old input. `idempotency_conflict` does **not** free a key.
|
|
19
19
|
|
|
@@ -57,7 +57,7 @@ create, search by the value you wrote; for an update, read the record by id) and
|
|
|
57
57
|
- cannot tell (the read action does not expose the field): stop and hand the case to a human with
|
|
58
58
|
the record identifiers.
|
|
59
59
|
|
|
60
|
-
### `409
|
|
60
|
+
### `409 readback_failed`
|
|
61
61
|
|
|
62
62
|
The write's result did not match, so nothing was saved, and the action is now paused. Do not retry;
|
|
63
63
|
the next calls answer `503 action_paused` until Deepdock resumes it. Tell the user the change was not
|
|
@@ -74,7 +74,7 @@ pending ──send──▶ sent ──2xx (fresh or replayed)──────
|
|
|
74
74
|
│ ──idempotency_conflict, retries left ───▶ sent (retry, same key, same input)
|
|
75
75
|
│ ──idempotency_conflict, retries spent ──▶ unknown (read back before anything else)
|
|
76
76
|
│ ──outcome_unknown ──────────────────────▶ unknown (read back before anything else)
|
|
77
|
-
│ ──invalid_input, target_rejected, action-specific 422, not_found,
|
|
77
|
+
│ ──invalid_input, target_rejected, action-specific 422, not_found, readback_failed ▶ refused (key is free; new input gets a new key)
|
|
78
78
|
│ ──action_paused, system_unavailable ────▶ sent (retry once the action is active again)
|
|
79
79
|
```
|
|
80
80
|
|