@decidio/sdk 0.11.0 → 0.12.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/CHANGELOG.md +63 -1
- package/README.md +18 -9
- package/dist/adapters/_gate.d.ts +18 -1
- package/dist/adapters/_gate.js +34 -27
- package/dist/adapters/langgraph.js +1 -1
- package/dist/adapters/openai.d.ts +11 -4
- package/dist/adapters/openai.js +12 -4
- package/dist/adapters/temporal.d.ts +29 -2
- package/dist/adapters/temporal.js +42 -6
- package/dist/cli.js +131 -32
- package/dist/demo-gate.js +14 -0
- package/dist/errors.js +3 -1
- package/dist/guard.d.ts +5 -0
- package/dist/guard.js +3 -2
- package/dist/index.d.ts +39 -7
- package/dist/index.js +103 -20
- package/dist/inngest.d.ts +5 -0
- package/dist/inngest.js +2 -2
- package/dist/resume.d.ts +52 -2
- package/dist/resume.js +74 -5
- package/dist/signing.d.ts +8 -0
- package/dist/signing.js +6 -0
- package/openapi.yaml +158 -2
- package/package.json +2 -2
package/openapi.yaml
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
openapi: 3.1.0
|
|
6
6
|
info:
|
|
7
7
|
title: Decidio Agent Gate
|
|
8
|
-
version: 0.
|
|
8
|
+
version: 0.12.0 # tracks the SDK release - checked by packages/conformance/manifests.mjs
|
|
9
9
|
description: >
|
|
10
10
|
Authorize an AI-agent action (proceed | route | block), confirm the captured outcome, and
|
|
11
11
|
receive the signed resume webhook when a routed action is decided. Every outcome seals a
|
|
@@ -87,6 +87,15 @@ components:
|
|
|
87
87
|
same requestCommitment AND the same requester, action, amount and scope (the server binds that
|
|
88
88
|
tuple itself) - otherwise 409 IDEMPOTENCY_CONFLICT; an earlier decision is never handed back for a
|
|
89
89
|
changed request.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
SDK 0.12.0 sends one BY DEFAULT beside every requestCommitment: a keyed HMAC over a fresh id for the
|
|
93
|
+
call and the commitment (or over the caller's own key, or an engine's own id for the call - an
|
|
94
|
+
OpenAI tool call id, a Temporal workflow run and activity, an Inngest run), and retries a network
|
|
95
|
+
failure, a 5xx or a non-AGENT_RATE 429 with the SAME key: a retry of a request still waiting is
|
|
96
|
+
answered with the one already waiting, and no retry runs an action twice. (A request is not
|
|
97
|
+
guaranteed single: an auto-approval whose answer is lost on every try, or a keyless request a policy
|
|
98
|
+
blocks, can make a second decision.) Without key material there is no commitment and no key.
|
|
90
99
|
AuthorizeResponse:
|
|
91
100
|
type: object
|
|
92
101
|
required: [decision, decisionId, receiptId]
|
|
@@ -111,14 +120,27 @@ components:
|
|
|
111
120
|
and `receipt` carries only the fields fixed at create. A sealed auto-approval replays as `proceed`
|
|
112
121
|
only when THIS call could itself auto-approve (a verified, replay-protected identity or a trusted
|
|
113
122
|
transport); anything else answers `route` or `block` - ask GET /agent/status for the real state.
|
|
123
|
+
openTwin:
|
|
124
|
+
type: boolean
|
|
125
|
+
description: >
|
|
126
|
+
present (true, beside idempotentReplay) when this KEYLESS request joined the same request from the
|
|
127
|
+
same agent that is still waiting for a person: nothing new was created, counted or summoned, and the
|
|
128
|
+
caller waits on that decision. The request may be shared, so a caller that gives up waiting must not
|
|
129
|
+
withdraw it (the SDKs skip their timeout withdraw after either flag; the server refuses a shared
|
|
130
|
+
withdraw with 409 SHARED_REQUEST).
|
|
114
131
|
StatusResponse:
|
|
115
132
|
type: object
|
|
116
133
|
required: [state]
|
|
134
|
+
description: >
|
|
135
|
+
Reading the status claims NOTHING: a dashboard, the CLI or a second watcher can poll it freely. The run
|
|
136
|
+
that acts on a person's approval collects it with POST /agent/claim/{decisionId}.
|
|
117
137
|
properties:
|
|
118
138
|
state:
|
|
119
139
|
type: string
|
|
120
140
|
enum: [pending, approved, auto_approved, rejected, blocked]
|
|
121
|
-
|
|
141
|
+
decisionId: { type: string }
|
|
142
|
+
receiptId: { type: [string, "null"] }
|
|
143
|
+
reason: { type: [string, "null"], description: the approver's reason, tokenized; never a cleartext name }
|
|
122
144
|
requestCommitment:
|
|
123
145
|
type: [string, "null"]
|
|
124
146
|
description: >
|
|
@@ -126,6 +148,27 @@ components:
|
|
|
126
148
|
sent). The SDK treats an approval as covering the request it is about to run only when this
|
|
127
149
|
equals its own recompute; a gate that returns no commitment for a request the SDK bound is
|
|
128
150
|
refused (commitment_missing), never trusted.
|
|
151
|
+
spent:
|
|
152
|
+
type: boolean
|
|
153
|
+
description: >
|
|
154
|
+
SDK 0.8.0: true once an execution is recorded on this approval - one approval covers one action,
|
|
155
|
+
once. The SDKs refuse to run on a spent approval and ask again.
|
|
156
|
+
grantExpiresAt:
|
|
157
|
+
type: [string, "null"]
|
|
158
|
+
format: date-time
|
|
159
|
+
description: >
|
|
160
|
+
SDK 0.8.0: when a granted decision's approval lapses (its seal's time plus the gate's TTL); null
|
|
161
|
+
otherwise. A granted decision with no expiry has a grant of unknown age, which the SDKs treat as
|
|
162
|
+
expired.
|
|
163
|
+
handedBackAt:
|
|
164
|
+
type: [string, "null"]
|
|
165
|
+
format: date-time
|
|
166
|
+
description: when an idempotent replay handed this granted decision back to a retry (null otherwise)
|
|
167
|
+
claimed:
|
|
168
|
+
type: boolean
|
|
169
|
+
description: >
|
|
170
|
+
SDK 0.12.0: whether a run has collected this person's approval (POST /agent/claim) - never by whom.
|
|
171
|
+
Informational: it claims nothing, and a caller decides a claim only by claiming.
|
|
129
172
|
ConfirmRequest:
|
|
130
173
|
type: object
|
|
131
174
|
required: [decisionId, capturedResponse, source]
|
|
@@ -328,6 +371,119 @@ paths:
|
|
|
328
371
|
check runs BEFORE any lookup, so this response reveals nothing about existence.
|
|
329
372
|
"401": { description: missing/invalid agent token }
|
|
330
373
|
"404": { description: unknown decision }
|
|
374
|
+
/agent/claim/{decisionId}:
|
|
375
|
+
post:
|
|
376
|
+
summary: Collect a person's approval for ONE run, once, right before acting on it (SDK 0.12.0)
|
|
377
|
+
description: >
|
|
378
|
+
Several programs can wait on one approval (callers that asked the same request, a second poller); only
|
|
379
|
+
the run that collects it runs it. The first claim wins. The same claimKey claiming again is the same run
|
|
380
|
+
retrying (a lost answer) and is answered the same, with `again: true`. Any other key is told the
|
|
381
|
+
approval was already used, and asks again. Only a PERSON's approval (state `approved`) is claimed: an
|
|
382
|
+
auto-approval is never shared, so it is NOT_CLAIMABLE, and so are a refusal, a waiting request and a
|
|
383
|
+
GitHub deploy approval (its deploy job uses it). A spent or expired approval is refused before anything
|
|
384
|
+
is written. A person's sign-in cannot claim (people approve, runs claim): it gets the 404. A bound agent
|
|
385
|
+
token claims only its own signed decisions; an unsigned decision is claimable by any agent credential
|
|
386
|
+
of the workspace (founder call 29). The SDKs make the claimKey at random for each run (two workers with
|
|
387
|
+
one key would be one run), retry a network failure or a 5xx with the SAME key, and run only on a 200.
|
|
388
|
+
parameters:
|
|
389
|
+
- name: decisionId
|
|
390
|
+
in: path
|
|
391
|
+
required: true
|
|
392
|
+
schema: { type: string }
|
|
393
|
+
requestBody:
|
|
394
|
+
required: true
|
|
395
|
+
content:
|
|
396
|
+
application/json:
|
|
397
|
+
schema:
|
|
398
|
+
type: object
|
|
399
|
+
required: [claimKey]
|
|
400
|
+
properties:
|
|
401
|
+
claimKey:
|
|
402
|
+
type: string
|
|
403
|
+
pattern: "^[A-Za-z0-9._:-]{16,128}$"
|
|
404
|
+
description: the run's own key; stored only as a keyed digest scoped to this decision
|
|
405
|
+
responses:
|
|
406
|
+
"200":
|
|
407
|
+
description: this run collected the approval - run the action
|
|
408
|
+
content:
|
|
409
|
+
application/json:
|
|
410
|
+
schema:
|
|
411
|
+
type: object
|
|
412
|
+
required: [ok, claimed, decisionId, again]
|
|
413
|
+
properties:
|
|
414
|
+
ok: { type: boolean, enum: [true] }
|
|
415
|
+
claimed: { type: boolean, enum: [true] }
|
|
416
|
+
decisionId: { type: string }
|
|
417
|
+
again: { type: boolean, description: true when the same key claimed again (the same run retrying) }
|
|
418
|
+
"400": { description: "a malformed decision id (INVALID_DECISION_ID) or claimKey (VALIDATION)" }
|
|
419
|
+
"401": { description: missing/invalid agent token }
|
|
420
|
+
"404": { description: unknown decision, one this credential may not claim, or a person's sign-in }
|
|
421
|
+
"409":
|
|
422
|
+
description: >
|
|
423
|
+
Do NOT run. `ALREADY_USED` - another run collected this approval, or it was already used: ask again
|
|
424
|
+
for a new one. `EXPIRED` - the approval lapsed: ask again. `NOT_CLAIMABLE` - not a person's approval
|
|
425
|
+
(still waiting, refused, an auto-approval, or a deploy approval).
|
|
426
|
+
content:
|
|
427
|
+
application/json:
|
|
428
|
+
schema:
|
|
429
|
+
type: object
|
|
430
|
+
properties:
|
|
431
|
+
code: { type: string, enum: [ALREADY_USED, EXPIRED, NOT_CLAIMABLE] }
|
|
432
|
+
decisionId: { type: string }
|
|
433
|
+
state: { type: string, enum: [pending, approved, auto_approved, rejected, blocked] }
|
|
434
|
+
message: { type: string }
|
|
435
|
+
/agent/withdraw/{decisionId}:
|
|
436
|
+
post:
|
|
437
|
+
summary: The requester stopped waiting - close its OPEN routed request as withdrawn (SDK 0.6.4)
|
|
438
|
+
description: >
|
|
439
|
+
The blocking SDK wait calls this when it hits its ceiling, so the queue stops carrying a request nobody
|
|
440
|
+
will act on and a later tap cannot seal "approved" for an action that will never run. A withdrawal only
|
|
441
|
+
ever reduces authority. Only the requester may withdraw: a bound agent token whose agent signed the
|
|
442
|
+
request; everything else is the 404. A withdrawn request reads `rejected` on GET /agent/status. A SHARED
|
|
443
|
+
request is never withdrawn: once another caller joined it (openTwin), the answer is 409 SHARED_REQUEST and
|
|
444
|
+
nothing changes. The SDKs skip the withdraw after an `idempotentReplay` or `openTwin` answer.
|
|
445
|
+
parameters:
|
|
446
|
+
- name: decisionId
|
|
447
|
+
in: path
|
|
448
|
+
required: true
|
|
449
|
+
schema: { type: string }
|
|
450
|
+
requestBody:
|
|
451
|
+
content:
|
|
452
|
+
application/json:
|
|
453
|
+
schema:
|
|
454
|
+
type: object
|
|
455
|
+
properties:
|
|
456
|
+
reason: { type: string, enum: [timeout, cancelled], description: "default timeout" }
|
|
457
|
+
responses:
|
|
458
|
+
"200":
|
|
459
|
+
description: withdrawn
|
|
460
|
+
content:
|
|
461
|
+
application/json:
|
|
462
|
+
schema:
|
|
463
|
+
type: object
|
|
464
|
+
properties:
|
|
465
|
+
ok: { type: boolean }
|
|
466
|
+
withdrawn: { type: boolean, enum: [true] }
|
|
467
|
+
state: { type: string, enum: [rejected] }
|
|
468
|
+
decisionId: { type: string }
|
|
469
|
+
reason: { type: string }
|
|
470
|
+
"400": { description: "a malformed decision id (INVALID_DECISION_ID) or an unknown reason (INVALID_REASON)" }
|
|
471
|
+
"401": { description: missing/invalid agent token }
|
|
472
|
+
"404": { description: unknown decision, or not this requester's own signed request }
|
|
473
|
+
"409":
|
|
474
|
+
description: >
|
|
475
|
+
`NOT_OPEN` - a decision already stands (or it was already withdrawn); `state` is the derived state, so
|
|
476
|
+
an approval that landed in the last moment is honoured. `SHARED_REQUEST` - another caller is waiting on
|
|
477
|
+
this same request; nothing changed (no `state`), and a person still decides it.
|
|
478
|
+
content:
|
|
479
|
+
application/json:
|
|
480
|
+
schema:
|
|
481
|
+
type: object
|
|
482
|
+
properties:
|
|
483
|
+
code: { type: string, enum: [NOT_OPEN, SHARED_REQUEST] }
|
|
484
|
+
state: { type: string, enum: [pending, approved, auto_approved, rejected, blocked] }
|
|
485
|
+
decisionId: { type: string }
|
|
486
|
+
message: { type: string }
|
|
331
487
|
/agent/confirm:
|
|
332
488
|
post:
|
|
333
489
|
summary: >
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decidio/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "One-line approval gate for AI-agent actions. Wrap a risky tool call with guard.protect(); Decidio's policy engine decides proceed | route | block, a human approves routed actions, and every outcome is sealed as a verifiable Authority Receipt.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"prepublishOnly": "npm run typecheck && npm run build && node ../publish-boundary/check.mjs --only @decidio/sdk"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@decidio/verify": "0.
|
|
87
|
+
"@decidio/verify": "0.12.0"
|
|
88
88
|
},
|
|
89
89
|
"author": "OmniTwin Technologies Inc.",
|
|
90
90
|
"bugs": {
|