@akai-workflow-builder/cli-sdk 0.1.3 → 0.1.4
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 +79 -27
- package/dist/define-cli.js +8 -8
- package/dist/define-connection.d.ts +22 -0
- package/dist/define-connection.d.ts.map +1 -0
- package/dist/define-connection.js +193 -0
- package/dist/errors.d.ts +3 -56
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -50
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/types.d.ts +135 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -2
- package/CHANGELOG.md +0 -19
package/README.md
CHANGED
|
@@ -79,6 +79,74 @@ export default defineCLI({
|
|
|
79
79
|
|
|
80
80
|
A full worked example with five read-only tools and a smoke runner lives in the repository under `examples/zendesk/` (not bundled in the published package; see the source tree).
|
|
81
81
|
|
|
82
|
+
### Defining a connection
|
|
83
|
+
|
|
84
|
+
A **connection** is the umbrella identity that groups CLIs sharing one auth surface — e.g. `google` groups Gmail and Sheets. Declare it with `defineConnection`, symmetric to `defineCLI`:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { defineConnection } from '@akai-workflow-builder/cli-sdk';
|
|
88
|
+
|
|
89
|
+
export default defineConnection({
|
|
90
|
+
slug: 'google', // groups CLIs that set connectionSlug: 'google'
|
|
91
|
+
name: 'Google Workspace', // umbrella display name
|
|
92
|
+
vendor: 'Google',
|
|
93
|
+
blurb: 'Gmail, Sheets, Docs, Drive and Calendar in one connection.',
|
|
94
|
+
longDesc: 'Connect once with OAuth; every Google CLI shares the authorization.',
|
|
95
|
+
authKind: 'oauth2',
|
|
96
|
+
oauth: { /* see below */ },
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
CLIs link to it through the **existing** `defineCLI` — set `connectionSlug`:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const gmail = defineCLI({ id: 'gmail', connectionSlug: 'google', summary: '…', tools: { … } });
|
|
104
|
+
const gsheet = defineCLI({ id: 'gsheet', connectionSlug: 'google', summary: '…', tools: { … } });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**When to declare one:** only when ≥2 CLIs share a slug and need a single umbrella identity. A **single-CLI connection needs no `defineConnection`** — its identity comes from that CLI's own metadata (`pdf`, `sandbox` and friends are unchanged).
|
|
108
|
+
|
|
109
|
+
`defineConnection` owns one concern: **identity**. It does not own tool sourcing, OAuth secret glue, or UI cosmetics — those split by source:
|
|
110
|
+
|
|
111
|
+
| Concern | Source |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Identity (name / blurb / longDesc / instructions / vendor / authKind) | `defineConnection` |
|
|
114
|
+
| OAuth shape (authorize/token URLs, scopes, pkce, params, refresh, admin fields) | `defineConnection.oauth` |
|
|
115
|
+
| OAuth secret VALUES, token storage, encryption, refresh hooks | akai-app, keyed by slug |
|
|
116
|
+
| UI cosmetics (hue / mark / logo) | akai-app, keyed by slug |
|
|
117
|
+
|
|
118
|
+
A complete runnable example is in [`examples/google`](./examples/google) — `defineConnection` plus two CLIs (`gmail`, `gsheet`) grouped under it.
|
|
119
|
+
|
|
120
|
+
### OAuth connections
|
|
121
|
+
|
|
122
|
+
When `authKind` is `oauth2` or `oauth-slack`, declare an `oauth` block. **The manifest declares shape; akai-app owns values:**
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
oauth: {
|
|
126
|
+
authorizeUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
127
|
+
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
128
|
+
scopes: [ // OAuth authorize scopes (≥1); distinct from per-CLI vendorScopes
|
|
129
|
+
'https://mail.google.com/',
|
|
130
|
+
'https://www.googleapis.com/auth/drive',
|
|
131
|
+
],
|
|
132
|
+
pkce: true, // Google requires PKCE; defaults to false
|
|
133
|
+
tokenEndpointAuthMethod: 'client_secret_post', // default 'client_secret_basic'
|
|
134
|
+
extraAuthorizeParams: { access_type: 'offline', prompt: 'consent' },
|
|
135
|
+
refreshStrategy: 'cron', // 'cron' (background refresh) | 'jit' (refresh on next use); default 'cron'
|
|
136
|
+
adminFields: [
|
|
137
|
+
{ key: 'GMAIL_CLIENT_ID', label: 'Client ID' },
|
|
138
|
+
{ key: 'GMAIL_CLIENT_SECRET', label: 'Client Secret', secret: true },
|
|
139
|
+
],
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- `scopes` is the connection-level OAuth authorize scope set (≥1) the engine joins onto the authorize URL — distinct from a CLI's per-tool `vendorScopes`.
|
|
144
|
+
- Set `pkce` when the provider requires it; set `extraAuthorizeParams` for static authorize params (Google's `access_type: 'offline'` to get a refresh token); leave `refreshStrategy` at the default `cron` (a background job refreshes the token before it expires) or set `jit` to refresh just-in-time on the next use.
|
|
145
|
+
- `adminFields` declares **which** OAuth-app credentials an admin must enter (env-style `key` + UI `label`). The **VALUES are stored encrypted in akai-app, never in the manifest or the per-tenant image.**
|
|
146
|
+
- Mark a field `secret: true` so akai-app masks the input in the admin form and redacts it from logs.
|
|
147
|
+
|
|
148
|
+
See the `connection-identity` and `define-connection-oauth` migration specs (akai-app `app/connections/migration-specs/`) for per-field guidance.
|
|
149
|
+
|
|
82
150
|
---
|
|
83
151
|
|
|
84
152
|
## Core concepts
|
|
@@ -346,36 +414,9 @@ Each tool branches on `isJson` and uses the structured logger. The folder includ
|
|
|
346
414
|
| `AkaiSecretError` | A `required: true` secret is missing at invocation time — thrown by `buildCtx` |
|
|
347
415
|
| `AkaiPropertyError`| A `required: true` property is missing at invocation time — thrown by `buildCtx` |
|
|
348
416
|
| `AkaiEgressError` | `ctx.fetch` rejected the target |
|
|
349
|
-
| `AkaiToolError` | A handler threw a typed, caller-facing failure — the host maps `kind` to an HTTP status and surfaces the message verbatim |
|
|
350
417
|
|
|
351
418
|
Every error extends `AkaiError`; the runtime maps each to a structured error envelope.
|
|
352
419
|
|
|
353
|
-
### Typed tool errors
|
|
354
|
-
|
|
355
|
-
Throw `AkaiToolError` from a handler to give an expected failure a stable classification and author-vetted wording. The host runtime brand-checks the thrown value by its serialized shape — `{ name: 'AkaiToolError', kind, message, meta? }` — with no SDK dependency, maps `kind` to an HTTP status, and returns `message` to the caller **verbatim**. Keep messages secret-free.
|
|
356
|
-
|
|
357
|
-
```ts
|
|
358
|
-
import { AkaiToolError } from '@akai-workflow-builder/cli-sdk';
|
|
359
|
-
|
|
360
|
-
const res = await ctx.fetch(`https://api.example.com/tickets/${id}`);
|
|
361
|
-
if (res.status === 404) throw AkaiToolError.notFound(`No ticket ${id}`, { id });
|
|
362
|
-
if (res.status === 429) throw AkaiToolError.rateLimited('Slow down', { retryAfterMs: 1000 });
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
Factories — each sets the matching `kind`:
|
|
366
|
-
|
|
367
|
-
| Factory | `kind` | Host status |
|
|
368
|
-
|---|---|---|
|
|
369
|
-
| `AkaiToolError.notFound(msg, meta?)` | `not_found` | 404 |
|
|
370
|
-
| `AkaiToolError.forbidden(msg, meta?)` | `forbidden` | 403 |
|
|
371
|
-
| `AkaiToolError.authExpired(msg, meta?)` | `auth_expired` | 401 |
|
|
372
|
-
| `AkaiToolError.invalidInput(msg, meta?)` | `invalid_input` | 422 |
|
|
373
|
-
| `AkaiToolError.conflict(msg, meta?)` | `conflict` | 409 |
|
|
374
|
-
| `AkaiToolError.rateLimited(msg, meta?)` | `rate_limited` | 429 (retryable) |
|
|
375
|
-
| `AkaiToolError.unavailable(msg, meta?)` | `unavailable` | 503 (retryable) |
|
|
376
|
-
|
|
377
|
-
Untyped throws are classified generically (a 500 with a derived message).
|
|
378
|
-
|
|
379
420
|
---
|
|
380
421
|
|
|
381
422
|
## Troubleshooting
|
|
@@ -396,6 +437,17 @@ Untyped throws are classified generically (a 500 with a derived message).
|
|
|
396
437
|
|
|
397
438
|
---
|
|
398
439
|
|
|
440
|
+
## Changelog
|
|
441
|
+
|
|
442
|
+
### Unreleased
|
|
443
|
+
|
|
444
|
+
- Add `defineConnection` — declare a connection's umbrella identity (`slug`, `name`, `vendor`, `blurb`, `longDesc`, `instructions`, `authKind`) plus its `oauth` shape. Returns a frozen, `WeakSet`-branded `ConnectionDef`. Symmetric to `defineCLI`.
|
|
445
|
+
- Add the `oauth` block: `authorizeUrl`, `tokenUrl`, `scopes`, `pkce`, `tokenEndpointAuthMethod`, `extraAuthorizeParams`, `refreshStrategy`, and `adminFields` (the OAuth-app credentials an admin enters; values stay in akai-app). Validated for valid URLs, non-empty `scopes`, env-style admin keys, and `adminFields` presence when `authKind` is `oauth2`/`oauth-slack`.
|
|
446
|
+
- New exports: `defineConnection`, `isAkaiConnection`, `AkaiConnectionError`, and types `ConnectionSpec`, `ConnectionDef`, `ConnectionOAuthConfig`, `OAuthAdminField`, `ConnectionAuthKind`, `RefreshStrategy`, `TokenEndpointAuthMethod`.
|
|
447
|
+
- New runnable example: `examples/google` (a connection grouping `gmail` + `gsheet`).
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
399
451
|
## License
|
|
400
452
|
|
|
401
453
|
MIT — see [`LICENSE`](./LICENSE).
|
package/dist/define-cli.js
CHANGED
|
@@ -35,6 +35,13 @@ const CLISpecShape = z
|
|
|
35
35
|
error: (issue) => `invalid id ${JSON.stringify(issue.input)}: lowercase letters/digits/hyphens/underscores only, must start with a letter`,
|
|
36
36
|
}),
|
|
37
37
|
name: z.string({ error: 'name is required' }).min(1, { error: 'name is required' }),
|
|
38
|
+
connectionSlug: z
|
|
39
|
+
.string({ error: 'connectionSlug must be a string if provided' })
|
|
40
|
+
.min(1, { error: 'connectionSlug must not be empty if provided' })
|
|
41
|
+
.regex(CLI_ID_RE, {
|
|
42
|
+
error: (issue) => `invalid connectionSlug ${JSON.stringify(issue.input)}: lowercase letters/digits/hyphens/underscores only, must start with a letter`,
|
|
43
|
+
})
|
|
44
|
+
.optional(),
|
|
38
45
|
vendor: z
|
|
39
46
|
.string({ error: 'vendor must be a string if provided' })
|
|
40
47
|
.min(1, { error: 'vendor must not be empty' })
|
|
@@ -89,13 +96,6 @@ const CLISpecShape = z
|
|
|
89
96
|
seen.add(p.key);
|
|
90
97
|
}
|
|
91
98
|
}),
|
|
92
|
-
connectionSlug: z
|
|
93
|
-
.string({ error: 'connectionSlug must be a string if provided' })
|
|
94
|
-
.min(1, { error: 'connectionSlug must not be empty if provided' })
|
|
95
|
-
.regex(CLI_ID_RE, {
|
|
96
|
-
error: (issue) => `invalid connectionSlug ${JSON.stringify(issue.input)}: lowercase letters/digits/hyphens/underscores only, must start with a letter`,
|
|
97
|
-
})
|
|
98
|
-
.optional(),
|
|
99
99
|
vendorScopes: z
|
|
100
100
|
.array(z.string({ error: 'vendorScopes[i] must be a string' }).min(1, { error: 'vendorScopes[i] must not be empty' }), { error: 'vendorScopes must be an array of strings if provided' })
|
|
101
101
|
.optional(),
|
|
@@ -250,10 +250,10 @@ export function defineCLI(spec) {
|
|
|
250
250
|
vendor: v.vendor ?? v.name,
|
|
251
251
|
summary: v.summary,
|
|
252
252
|
...(v.description !== undefined ? { description: v.description } : {}),
|
|
253
|
+
...(v.connectionSlug !== undefined ? { connectionSlug: v.connectionSlug } : {}),
|
|
253
254
|
instructions: Object.freeze([...(v.instructions ?? [])]),
|
|
254
255
|
secrets: frozenSecrets,
|
|
255
256
|
properties: frozenProperties,
|
|
256
|
-
...(v.connectionSlug !== undefined ? { connectionSlug: v.connectionSlug } : {}),
|
|
257
257
|
...(v.vendorScopes !== undefined ? { vendorScopes: Object.freeze([...v.vendorScopes]) } : {}),
|
|
258
258
|
tools: Object.freeze(toolsMap),
|
|
259
259
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ConnectionDef, ConnectionSpec } from './types.js';
|
|
2
|
+
export declare function isAkaiConnection(x: unknown): x is ConnectionDef;
|
|
3
|
+
/**
|
|
4
|
+
* Declare a connection: the umbrella identity that groups CLIs sharing one auth
|
|
5
|
+
* surface (e.g. `google` groups gmail + gsheet). Symmetric to `defineCLI` —
|
|
6
|
+
* returns a frozen, branded `ConnectionDef`.
|
|
7
|
+
*
|
|
8
|
+
* The manifest is the source of truth for IDENTITY (name/blurb/longDesc/
|
|
9
|
+
* instructions/vendor/authKind) and OAuth SHAPE (`oauth` block). It never holds
|
|
10
|
+
* the OAuth glue — client id/secret values, token storage, encryption, refresh
|
|
11
|
+
* hooks — nor UI cosmetics (hue/mark/logo). Those stay in akai-app, keyed by
|
|
12
|
+
* slug, a security boundary that never bakes into a per-tenant image.
|
|
13
|
+
*
|
|
14
|
+
* `defineConnection` is optional: a slug with no connection declaration is a
|
|
15
|
+
* single-CLI connection whose identity comes from its own `defineCLI` metadata.
|
|
16
|
+
* Declare one when ≥2 CLIs share a slug and need a single umbrella identity.
|
|
17
|
+
*
|
|
18
|
+
* CLIs link to a connection through `defineCLI({ connectionSlug: <slug> })` —
|
|
19
|
+
* `defineCLI` is unchanged.
|
|
20
|
+
*/
|
|
21
|
+
export declare function defineConnection(spec: ConnectionSpec): ConnectionDef;
|
|
22
|
+
//# sourceMappingURL=define-connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-connection.d.ts","sourceRoot":"","sources":["../src/define-connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EAEb,cAAc,EAEf,MAAM,YAAY,CAAC;AA4IpB,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,aAAa,CAE/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CA4CpE"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { AkaiConnectionError } from './errors.js';
|
|
3
|
+
const SLUG_RE = /^[a-z][a-z0-9_-]*$/;
|
|
4
|
+
const ADMIN_KEY_RE = /^[A-Z][A-Z0-9_]+$/;
|
|
5
|
+
const OAUTH_KINDS = new Set(['oauth2']);
|
|
6
|
+
const UrlString = z
|
|
7
|
+
.string({ error: 'must be a string' })
|
|
8
|
+
.min(1, { error: 'is required' })
|
|
9
|
+
.refine((val) => {
|
|
10
|
+
try {
|
|
11
|
+
new URL(val);
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}, { error: (issue) => `must be a valid URL (got ${JSON.stringify(issue.input)})` });
|
|
18
|
+
const OAuthAdminFieldShape = z.object({
|
|
19
|
+
key: z
|
|
20
|
+
.string({ error: 'key is required' })
|
|
21
|
+
.min(1, { error: 'key is required' })
|
|
22
|
+
.regex(ADMIN_KEY_RE, {
|
|
23
|
+
error: (issue) => `invalid key ${JSON.stringify(issue.input)}: env-style only ([A-Z][A-Z0-9_]+), e.g. GMAIL_CLIENT_ID`,
|
|
24
|
+
}),
|
|
25
|
+
label: z.string({ error: 'label is required' }).min(1, { error: 'label is required' }),
|
|
26
|
+
secret: z.boolean({ error: 'secret must be a boolean if provided' }).optional(),
|
|
27
|
+
});
|
|
28
|
+
const ConnectionOAuthConfigShape = z.object({
|
|
29
|
+
authorizeUrl: UrlString,
|
|
30
|
+
tokenUrl: UrlString,
|
|
31
|
+
scopes: z
|
|
32
|
+
.array(z.string({ error: 'scopes[i] must be a string' }).min(1, { error: 'scopes[i] must be non-empty' }), {
|
|
33
|
+
error: 'oauth.scopes must be an array of strings',
|
|
34
|
+
})
|
|
35
|
+
.min(1, { error: 'oauth.scopes must declare at least one scope' }),
|
|
36
|
+
pkce: z.boolean({ error: 'pkce must be a boolean if provided' }).optional(),
|
|
37
|
+
tokenEndpointAuthMethod: z
|
|
38
|
+
.enum(['client_secret_post', 'client_secret_basic'], {
|
|
39
|
+
error: 'tokenEndpointAuthMethod must be client_secret_post or client_secret_basic',
|
|
40
|
+
})
|
|
41
|
+
.optional(),
|
|
42
|
+
extraAuthorizeParams: z
|
|
43
|
+
.record(z.string(), z.string(), {
|
|
44
|
+
error: 'extraAuthorizeParams must be a string-to-string map if provided',
|
|
45
|
+
})
|
|
46
|
+
.optional(),
|
|
47
|
+
refreshStrategy: z
|
|
48
|
+
.enum(['cron', 'jit'], {
|
|
49
|
+
error: 'refreshStrategy must be cron or jit',
|
|
50
|
+
})
|
|
51
|
+
.optional(),
|
|
52
|
+
adminFields: z
|
|
53
|
+
.array(OAuthAdminFieldShape, { error: 'oauth.adminFields must be an array' })
|
|
54
|
+
.superRefine((fields, ctx) => {
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
for (let i = 0; i < fields.length; i++) {
|
|
57
|
+
const f = fields[i];
|
|
58
|
+
if (seen.has(f.key)) {
|
|
59
|
+
ctx.addIssue({ code: 'custom', path: [i], message: `duplicate adminFields key: ${f.key}` });
|
|
60
|
+
}
|
|
61
|
+
seen.add(f.key);
|
|
62
|
+
}
|
|
63
|
+
}),
|
|
64
|
+
hasCustomConnectFlow: z.boolean({ error: 'hasCustomConnectFlow must be a boolean if provided' }).optional(),
|
|
65
|
+
});
|
|
66
|
+
const ConnectionSpecShape = z
|
|
67
|
+
.object({
|
|
68
|
+
slug: z
|
|
69
|
+
.string({ error: 'slug is required' })
|
|
70
|
+
.min(1, { error: 'slug is required' })
|
|
71
|
+
.regex(SLUG_RE, {
|
|
72
|
+
error: (issue) => `invalid slug ${JSON.stringify(issue.input)}: lowercase letters/digits/hyphens/underscores only, must start with a letter`,
|
|
73
|
+
}),
|
|
74
|
+
name: z.string({ error: 'name is required' }).min(1, { error: 'name is required' }),
|
|
75
|
+
vendor: z.string({ error: 'vendor is required' }).min(1, { error: 'vendor is required' }),
|
|
76
|
+
blurb: z.string({ error: 'blurb is required' }).min(1, { error: 'blurb is required' }),
|
|
77
|
+
longDesc: z.string({ error: 'longDesc is required' }).min(1, { error: 'longDesc is required' }),
|
|
78
|
+
instructions: z
|
|
79
|
+
.array(z.string({ error: 'instructions[i] must be a string' }), {
|
|
80
|
+
error: 'instructions must be an array of strings if provided',
|
|
81
|
+
})
|
|
82
|
+
.optional(),
|
|
83
|
+
authKind: z.enum(['apiKey', 'oauth2', 'none'], {
|
|
84
|
+
error: 'authKind must be one of apiKey, oauth2, none',
|
|
85
|
+
}),
|
|
86
|
+
oauth: ConnectionOAuthConfigShape.optional(),
|
|
87
|
+
})
|
|
88
|
+
.superRefine((spec, ctx) => {
|
|
89
|
+
if (OAUTH_KINDS.has(spec.authKind)) {
|
|
90
|
+
if (!spec.oauth) {
|
|
91
|
+
ctx.addIssue({
|
|
92
|
+
code: 'custom',
|
|
93
|
+
path: ['oauth'],
|
|
94
|
+
message: `oauth is required when authKind is '${spec.authKind}'`,
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (spec.oauth.adminFields.length < 1) {
|
|
99
|
+
ctx.addIssue({
|
|
100
|
+
code: 'custom',
|
|
101
|
+
path: ['oauth', 'adminFields'],
|
|
102
|
+
message: `oauth.adminFields must declare at least one field when authKind is '${spec.authKind}'`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (spec.oauth !== undefined) {
|
|
107
|
+
ctx.addIssue({
|
|
108
|
+
code: 'custom',
|
|
109
|
+
path: ['oauth'],
|
|
110
|
+
message: `oauth must not be set when authKind is '${spec.authKind}'`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
function throwSpecError(error) {
|
|
115
|
+
const issue = error.issues[0];
|
|
116
|
+
if (!issue)
|
|
117
|
+
throw new AkaiConnectionError('defineConnection: invalid spec');
|
|
118
|
+
const path = issue.path.length > 0 ? `${issue.path.join('.')} — ` : '';
|
|
119
|
+
throw new AkaiConnectionError(`defineConnection: ${path}${issue.message}`, {
|
|
120
|
+
path: issue.path,
|
|
121
|
+
issues: error.issues,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Connections registered by `defineConnection()`. `isAkaiConnection` uses this
|
|
126
|
+
* WeakSet so a hand-crafted `{ __akaiConnection: true, ... }` cannot pose as a
|
|
127
|
+
* connection to the registry loader. The brand on the object remains for
|
|
128
|
+
* human/debug visibility only.
|
|
129
|
+
*/
|
|
130
|
+
const CONNECTION_REGISTRY = new WeakSet();
|
|
131
|
+
export function isAkaiConnection(x) {
|
|
132
|
+
return typeof x === 'object' && x !== null && CONNECTION_REGISTRY.has(x);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Declare a connection: the umbrella identity that groups CLIs sharing one auth
|
|
136
|
+
* surface (e.g. `google` groups gmail + gsheet). Symmetric to `defineCLI` —
|
|
137
|
+
* returns a frozen, branded `ConnectionDef`.
|
|
138
|
+
*
|
|
139
|
+
* The manifest is the source of truth for IDENTITY (name/blurb/longDesc/
|
|
140
|
+
* instructions/vendor/authKind) and OAuth SHAPE (`oauth` block). It never holds
|
|
141
|
+
* the OAuth glue — client id/secret values, token storage, encryption, refresh
|
|
142
|
+
* hooks — nor UI cosmetics (hue/mark/logo). Those stay in akai-app, keyed by
|
|
143
|
+
* slug, a security boundary that never bakes into a per-tenant image.
|
|
144
|
+
*
|
|
145
|
+
* `defineConnection` is optional: a slug with no connection declaration is a
|
|
146
|
+
* single-CLI connection whose identity comes from its own `defineCLI` metadata.
|
|
147
|
+
* Declare one when ≥2 CLIs share a slug and need a single umbrella identity.
|
|
148
|
+
*
|
|
149
|
+
* CLIs link to a connection through `defineCLI({ connectionSlug: <slug> })` —
|
|
150
|
+
* `defineCLI` is unchanged.
|
|
151
|
+
*/
|
|
152
|
+
export function defineConnection(spec) {
|
|
153
|
+
const parsed = ConnectionSpecShape.safeParse(spec);
|
|
154
|
+
if (!parsed.success)
|
|
155
|
+
throwSpecError(parsed.error);
|
|
156
|
+
// Build the def from the parsed (validated) snapshot, NOT from `spec` —
|
|
157
|
+
// re-reading `spec` after validation is TOCTOU-vulnerable to getter/proxy
|
|
158
|
+
// tricks that return different values on second read.
|
|
159
|
+
const v = parsed.data;
|
|
160
|
+
let oauth;
|
|
161
|
+
if (v.authKind === 'oauth2' && v.oauth) {
|
|
162
|
+
const adminFields = Object.freeze(v.oauth.adminFields.map((f) => Object.freeze({ ...f })));
|
|
163
|
+
oauth = Object.freeze({
|
|
164
|
+
authorizeUrl: v.oauth.authorizeUrl,
|
|
165
|
+
tokenUrl: v.oauth.tokenUrl,
|
|
166
|
+
scopes: Object.freeze([...v.oauth.scopes]),
|
|
167
|
+
...(v.oauth.pkce !== undefined ? { pkce: v.oauth.pkce } : {}),
|
|
168
|
+
...(v.oauth.tokenEndpointAuthMethod !== undefined
|
|
169
|
+
? { tokenEndpointAuthMethod: v.oauth.tokenEndpointAuthMethod }
|
|
170
|
+
: {}),
|
|
171
|
+
...(v.oauth.extraAuthorizeParams !== undefined
|
|
172
|
+
? { extraAuthorizeParams: Object.freeze({ ...v.oauth.extraAuthorizeParams }) }
|
|
173
|
+
: {}),
|
|
174
|
+
...(v.oauth.refreshStrategy !== undefined ? { refreshStrategy: v.oauth.refreshStrategy } : {}),
|
|
175
|
+
adminFields,
|
|
176
|
+
...(v.oauth.hasCustomConnectFlow !== undefined ? { hasCustomConnectFlow: v.oauth.hasCustomConnectFlow } : {}),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const def = {
|
|
180
|
+
__akaiConnection: true,
|
|
181
|
+
slug: v.slug,
|
|
182
|
+
name: v.name,
|
|
183
|
+
vendor: v.vendor,
|
|
184
|
+
blurb: v.blurb,
|
|
185
|
+
longDesc: v.longDesc,
|
|
186
|
+
instructions: Object.freeze([...(v.instructions ?? [])]),
|
|
187
|
+
authKind: v.authKind,
|
|
188
|
+
...(oauth !== undefined ? { oauth } : {}),
|
|
189
|
+
};
|
|
190
|
+
Object.freeze(def);
|
|
191
|
+
CONNECTION_REGISTRY.add(def);
|
|
192
|
+
return def;
|
|
193
|
+
}
|
package/dist/errors.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export declare class AkaiError extends Error {
|
|
|
10
10
|
/** Module-load-time spec error (bad call to `tool()` or `defineCLI()`). */
|
|
11
11
|
export declare class AkaiSpecError extends AkaiError {
|
|
12
12
|
}
|
|
13
|
+
/** Module-load-time spec error from a bad call to `defineConnection()`. */
|
|
14
|
+
export declare class AkaiConnectionError extends AkaiSpecError {
|
|
15
|
+
}
|
|
13
16
|
/** Input failed validation (zod parse, unknown flag, missing required arg). */
|
|
14
17
|
export declare class AkaiInputError extends AkaiError {
|
|
15
18
|
}
|
|
@@ -25,60 +28,4 @@ export declare class AkaiPropertyError extends AkaiError {
|
|
|
25
28
|
/** `ctx.safePath` rejected a path that resolves outside the allowed roots. */
|
|
26
29
|
export declare class AkaiPathError extends AkaiError {
|
|
27
30
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Stable, vendor-neutral classification for a caller-facing tool failure.
|
|
30
|
-
*
|
|
31
|
-
* The host runtime maps each `kind` to an HTTP status and surfaces the
|
|
32
|
-
* accompanying `message` to the caller verbatim, so an agent can reason about
|
|
33
|
-
* the failure programmatically (fix the id, ask to be granted access,
|
|
34
|
-
* reconnect, retry) instead of seeing an opaque 500.
|
|
35
|
-
*
|
|
36
|
-
* - `not_found` — host maps to **404**: the entity does not exist or is not
|
|
37
|
-
* visible to this caller. Check the id/URL and that you have access.
|
|
38
|
-
* - `forbidden` — host maps to **403**: the entity exists but the caller lacks
|
|
39
|
-
* permission (not shared, insufficient scope).
|
|
40
|
-
* - `auth_expired` — host maps to **401**: the credential is invalid or expired;
|
|
41
|
-
* reconnect the integration.
|
|
42
|
-
* - `invalid_input` — host maps to **422**: arguments are well-formed but violate
|
|
43
|
-
* a runtime constraint the schema cannot express.
|
|
44
|
-
* - `conflict` — host maps to **409**: the request conflicts with current state
|
|
45
|
-
* (already exists, version mismatch).
|
|
46
|
-
* - `rate_limited` — host maps to **429**: an upstream throttle was hit; retryable.
|
|
47
|
-
* Put a hint in `meta` (e.g. `{ retryAfterMs }`).
|
|
48
|
-
* - `unavailable` — host maps to **503**: upstream is down, timed out, or
|
|
49
|
-
* unreachable; retryable.
|
|
50
|
-
*/
|
|
51
|
-
export type ToolErrorKind = 'not_found' | 'forbidden' | 'auth_expired' | 'invalid_input' | 'conflict' | 'rate_limited' | 'unavailable';
|
|
52
|
-
/**
|
|
53
|
-
* Caller-facing tool failure with a stable, vendor-neutral {@link ToolErrorKind}.
|
|
54
|
-
*
|
|
55
|
-
* Throw this from a tool handler when you want bespoke, author-vetted wording
|
|
56
|
-
* for an expected failure. The host runtime brand-checks the thrown value by its
|
|
57
|
-
* serialized shape — `{ name: 'AkaiToolError', kind, message, meta? }` — so the
|
|
58
|
-
* `name` is pinned to `'AkaiToolError'` in the constructor and survives across
|
|
59
|
-
* package-boundary `instanceof` gaps. On a match the host maps `kind` to an HTTP
|
|
60
|
-
* status and returns `message` to the caller **verbatim**, so the message must be
|
|
61
|
-
* secret-free and safe to expose. Untyped throws are classified generically.
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* throw AkaiToolError.notFound(`No ticket ${id}`, { id });
|
|
65
|
-
*/
|
|
66
|
-
export declare class AkaiToolError extends AkaiError {
|
|
67
|
-
readonly kind: ToolErrorKind;
|
|
68
|
-
constructor(kind: ToolErrorKind, message: string, meta?: Record<string, unknown>);
|
|
69
|
-
/** `invalid_input` → host **422**: args violate a runtime constraint the schema can't express. */
|
|
70
|
-
static invalidInput(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
71
|
-
/** `not_found` → host **404**: the entity doesn't exist or isn't visible to this caller. */
|
|
72
|
-
static notFound(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
73
|
-
/** `forbidden` → host **403**: the entity exists but the caller lacks permission. */
|
|
74
|
-
static forbidden(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
75
|
-
/** `auth_expired` → host **401**: the credential is invalid or expired; reconnect. */
|
|
76
|
-
static authExpired(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
77
|
-
/** `conflict` → host **409**: the request conflicts with current state. */
|
|
78
|
-
static conflict(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
79
|
-
/** `rate_limited` → host **429**: upstream throttle hit; retryable (e.g. `meta.retryAfterMs`). */
|
|
80
|
-
static rateLimited(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
81
|
-
/** `unavailable` → host **503**: upstream down/timed-out/unreachable; retryable. */
|
|
82
|
-
static unavailable(message: string, meta?: Record<string, unknown>): AkaiToolError;
|
|
83
|
-
}
|
|
84
31
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC5B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAK5D;AAED,2EAA2E;AAC3E,qBAAa,aAAc,SAAQ,SAAS;CAAG;AAE/C,+EAA+E;AAC/E,qBAAa,cAAe,SAAQ,SAAS;CAAG;AAEhD,8CAA8C;AAC9C,qBAAa,eAAgB,SAAQ,SAAS;CAAG;AAEjD,sDAAsD;AACtD,qBAAa,eAAgB,SAAQ,SAAS;CAAG;AAEjD,+DAA+D;AAC/D,qBAAa,iBAAkB,SAAQ,SAAS;CAAG;AAGnD,8EAA8E;AAC9E,qBAAa,aAAc,SAAQ,SAAS;CAAG
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC5B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAK5D;AAED,2EAA2E;AAC3E,qBAAa,aAAc,SAAQ,SAAS;CAAG;AAE/C,2EAA2E;AAC3E,qBAAa,mBAAoB,SAAQ,aAAa;CAAG;AAEzD,+EAA+E;AAC/E,qBAAa,cAAe,SAAQ,SAAS;CAAG;AAEhD,8CAA8C;AAC9C,qBAAa,eAAgB,SAAQ,SAAS;CAAG;AAEjD,sDAAsD;AACtD,qBAAa,eAAgB,SAAQ,SAAS;CAAG;AAEjD,+DAA+D;AAC/D,qBAAa,iBAAkB,SAAQ,SAAS;CAAG;AAGnD,8EAA8E;AAC9E,qBAAa,aAAc,SAAQ,SAAS;CAAG"}
|
package/dist/errors.js
CHANGED
|
@@ -14,6 +14,9 @@ export class AkaiError extends Error {
|
|
|
14
14
|
/** Module-load-time spec error (bad call to `tool()` or `defineCLI()`). */
|
|
15
15
|
export class AkaiSpecError extends AkaiError {
|
|
16
16
|
}
|
|
17
|
+
/** Module-load-time spec error from a bad call to `defineConnection()`. */
|
|
18
|
+
export class AkaiConnectionError extends AkaiSpecError {
|
|
19
|
+
}
|
|
17
20
|
/** Input failed validation (zod parse, unknown flag, missing required arg). */
|
|
18
21
|
export class AkaiInputError extends AkaiError {
|
|
19
22
|
}
|
|
@@ -29,53 +32,3 @@ export class AkaiPropertyError extends AkaiError {
|
|
|
29
32
|
/** `ctx.safePath` rejected a path that resolves outside the allowed roots. */
|
|
30
33
|
export class AkaiPathError extends AkaiError {
|
|
31
34
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Caller-facing tool failure with a stable, vendor-neutral {@link ToolErrorKind}.
|
|
34
|
-
*
|
|
35
|
-
* Throw this from a tool handler when you want bespoke, author-vetted wording
|
|
36
|
-
* for an expected failure. The host runtime brand-checks the thrown value by its
|
|
37
|
-
* serialized shape — `{ name: 'AkaiToolError', kind, message, meta? }` — so the
|
|
38
|
-
* `name` is pinned to `'AkaiToolError'` in the constructor and survives across
|
|
39
|
-
* package-boundary `instanceof` gaps. On a match the host maps `kind` to an HTTP
|
|
40
|
-
* status and returns `message` to the caller **verbatim**, so the message must be
|
|
41
|
-
* secret-free and safe to expose. Untyped throws are classified generically.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* throw AkaiToolError.notFound(`No ticket ${id}`, { id });
|
|
45
|
-
*/
|
|
46
|
-
export class AkaiToolError extends AkaiError {
|
|
47
|
-
kind;
|
|
48
|
-
constructor(kind, message, meta) {
|
|
49
|
-
super(message, meta);
|
|
50
|
-
this.name = 'AkaiToolError';
|
|
51
|
-
this.kind = kind;
|
|
52
|
-
}
|
|
53
|
-
/** `invalid_input` → host **422**: args violate a runtime constraint the schema can't express. */
|
|
54
|
-
static invalidInput(message, meta) {
|
|
55
|
-
return new AkaiToolError('invalid_input', message, meta);
|
|
56
|
-
}
|
|
57
|
-
/** `not_found` → host **404**: the entity doesn't exist or isn't visible to this caller. */
|
|
58
|
-
static notFound(message, meta) {
|
|
59
|
-
return new AkaiToolError('not_found', message, meta);
|
|
60
|
-
}
|
|
61
|
-
/** `forbidden` → host **403**: the entity exists but the caller lacks permission. */
|
|
62
|
-
static forbidden(message, meta) {
|
|
63
|
-
return new AkaiToolError('forbidden', message, meta);
|
|
64
|
-
}
|
|
65
|
-
/** `auth_expired` → host **401**: the credential is invalid or expired; reconnect. */
|
|
66
|
-
static authExpired(message, meta) {
|
|
67
|
-
return new AkaiToolError('auth_expired', message, meta);
|
|
68
|
-
}
|
|
69
|
-
/** `conflict` → host **409**: the request conflicts with current state. */
|
|
70
|
-
static conflict(message, meta) {
|
|
71
|
-
return new AkaiToolError('conflict', message, meta);
|
|
72
|
-
}
|
|
73
|
-
/** `rate_limited` → host **429**: upstream throttle hit; retryable (e.g. `meta.retryAfterMs`). */
|
|
74
|
-
static rateLimited(message, meta) {
|
|
75
|
-
return new AkaiToolError('rate_limited', message, meta);
|
|
76
|
-
}
|
|
77
|
-
/** `unavailable` → host **503**: upstream down/timed-out/unreachable; retryable. */
|
|
78
|
-
static unavailable(message, meta) {
|
|
79
|
-
return new AkaiToolError('unavailable', message, meta);
|
|
80
|
-
}
|
|
81
|
-
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export { tool, isAkaiTool, DYNAMIC_EGRESS_PREFIX } from './tool.js';
|
|
2
2
|
export { defineCLI } from './define-cli.js';
|
|
3
3
|
export { filePath, FILE_INPUT_META_KEY } from './file-input.js';
|
|
4
|
+
export { defineConnection, isAkaiConnection } from './define-connection.js';
|
|
4
5
|
export { buildScopedSecrets, buildScopedProperties } from './ctx/secrets.js';
|
|
5
6
|
export type { SecretValues, PropertyValues } from './ctx/secrets.js';
|
|
6
7
|
export { buildCtx } from './ctx/build-ctx.js';
|
|
7
8
|
export type { BuildCtxParams } from './ctx/build-ctx.js';
|
|
8
|
-
export type { AnyToolDef, CLIDef, CLISpec, DynamicEgress, InputOf, NetworkOptions, OutputOf, PropertiesOf, PropertyDecl, SecretDecl, SecretsOf, ToolCtx, ToolDef, ToolLogger, ToolOptions, ToolSpec, } from './types.js';
|
|
9
|
+
export type { AnyToolDef, CLIDef, CLISpec, ConnectionAuthKind, ConnectionDef, ConnectionOAuthConfig, ConnectionSpec, DynamicEgress, InputOf, NetworkOptions, OAuthAdminField, OutputOf, PropertiesOf, PropertyDecl, RefreshStrategy, SecretDecl, SecretsOf, TokenEndpointAuthMethod, ToolCtx, ToolDef, ToolLogger, ToolOptions, ToolSpec, } from './types.js';
|
|
9
10
|
export { createSafePath } from './ctx/safe-path.js';
|
|
10
11
|
export type { SafePath } from './ctx/safe-path.js';
|
|
11
|
-
export { AkaiEgressError, AkaiError, AkaiInputError, AkaiPathError, AkaiPropertyError, AkaiSecretError, AkaiSpecError,
|
|
12
|
-
export type { ToolErrorKind } from './errors.js';
|
|
12
|
+
export { AkaiConnectionError, AkaiEgressError, AkaiError, AkaiInputError, AkaiPathError, AkaiPropertyError, AkaiSecretError, AkaiSpecError, } from './errors.js';
|
|
13
13
|
export { ConnectionManifestSchema, ManifestJSONSchema, SCHEMA_VERSION, toSchema, validateManifest, } from './manifest/index.js';
|
|
14
14
|
export type { ConnectionManifest, DynamicEgressManifest, HttpToolManifest, ManifestProperty, ManifestSecret, NativeToolManifest, SchemaVersion, ToolManifest, } from './manifest/index.js';
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EACV,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,OAAO,EACP,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,SAAS,EACT,OAAO,EACP,OAAO,EACP,UAAU,EACV,WAAW,EACX,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,eAAe,EACf,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EACV,UAAU,EACV,MAAM,EACN,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,OAAO,EACP,cAAc,EACd,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,UAAU,EACV,SAAS,EACT,uBAAuB,EACvB,OAAO,EACP,OAAO,EACP,UAAU,EACV,WAAW,EACX,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,cAAc,EACd,QAAQ,EACR,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,YAAY,GACb,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { tool, isAkaiTool, DYNAMIC_EGRESS_PREFIX } from './tool.js';
|
|
2
2
|
export { defineCLI } from './define-cli.js';
|
|
3
3
|
export { filePath, FILE_INPUT_META_KEY } from './file-input.js';
|
|
4
|
+
export { defineConnection, isAkaiConnection } from './define-connection.js';
|
|
4
5
|
export { buildScopedSecrets, buildScopedProperties } from './ctx/secrets.js';
|
|
5
6
|
export { buildCtx } from './ctx/build-ctx.js';
|
|
6
7
|
export { createSafePath } from './ctx/safe-path.js';
|
|
7
|
-
export { AkaiEgressError, AkaiError, AkaiInputError, AkaiPathError, AkaiPropertyError, AkaiSecretError, AkaiSpecError,
|
|
8
|
+
export { AkaiConnectionError, AkaiEgressError, AkaiError, AkaiInputError, AkaiPathError, AkaiPropertyError, AkaiSecretError, AkaiSpecError, } from './errors.js';
|
|
8
9
|
export { ConnectionManifestSchema, ManifestJSONSchema, SCHEMA_VERSION, toSchema, validateManifest, } from './manifest/index.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -248,4 +248,139 @@ export interface CLISpec {
|
|
|
248
248
|
vendorScopes?: readonly string[];
|
|
249
249
|
tools: Record<string, AnyToolDef>;
|
|
250
250
|
}
|
|
251
|
+
/** The auth kind a connection declares — WHAT auth, never the glue. */
|
|
252
|
+
export type ConnectionAuthKind = 'apiKey' | 'oauth2' | 'none';
|
|
253
|
+
/** The token-endpoint client-auth method used on the OAuth code exchange. */
|
|
254
|
+
export type TokenEndpointAuthMethod = 'client_secret_post' | 'client_secret_basic';
|
|
255
|
+
/** How akai-app refreshes the access token once the connection is live. */
|
|
256
|
+
export type RefreshStrategy = 'cron' | 'jit';
|
|
257
|
+
/**
|
|
258
|
+
* One OAuth-app credential an admin must enter once per tenant (e.g. the OAuth
|
|
259
|
+
* client id / secret).
|
|
260
|
+
*
|
|
261
|
+
* This declares WHICH credential the admin supplies — the VALUE is entered in
|
|
262
|
+
* the akai-app UI and stored encrypted server-side, never in the manifest or
|
|
263
|
+
* the per-tenant image. `adminFields` are distinct from a CLI's `secrets[]`:
|
|
264
|
+
* `secrets[]` are user-facing access tokens / API keys; `adminFields` are the
|
|
265
|
+
* OAuth-app credentials set once by an admin (different lifecycle, storage, UI).
|
|
266
|
+
*/
|
|
267
|
+
export interface OAuthAdminField {
|
|
268
|
+
/**
|
|
269
|
+
* Env-style key the value is stored and looked up under, e.g.
|
|
270
|
+
* `GMAIL_CLIENT_ID`. Must match `[A-Z][A-Z0-9_]+` — it becomes a storage key
|
|
271
|
+
* in akai-app, so non-env-style keys are rejected at `defineConnection()`.
|
|
272
|
+
*/
|
|
273
|
+
readonly key: string;
|
|
274
|
+
/** UI label for the input, e.g. `Client ID`. */
|
|
275
|
+
readonly label: string;
|
|
276
|
+
/**
|
|
277
|
+
* When `true`, akai-app masks the input in the admin form and redacts the
|
|
278
|
+
* value from logs. Default `false`. Set it for any credential that is itself
|
|
279
|
+
* a secret (client secret, signing key).
|
|
280
|
+
*/
|
|
281
|
+
readonly secret?: boolean;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The OAuth shape a connection declares. akai-app reads this from the catalog,
|
|
285
|
+
* loads the `adminFields` values from its own DB at runtime, and runs the flow
|
|
286
|
+
* as a generic OAuth engine.
|
|
287
|
+
*
|
|
288
|
+
* The manifest declares SHAPE only. Client id/secret VALUES, token storage,
|
|
289
|
+
* encryption, and refresh hooks stay in akai-app — a security boundary, never
|
|
290
|
+
* baked into a per-tenant image.
|
|
291
|
+
*/
|
|
292
|
+
export interface ConnectionOAuthConfig {
|
|
293
|
+
/** OAuth authorize endpoint, e.g. `https://accounts.google.com/o/oauth2/v2/auth`. Must be a valid URL. */
|
|
294
|
+
readonly authorizeUrl: string;
|
|
295
|
+
/** OAuth token endpoint, e.g. `https://oauth2.googleapis.com/token`. Must be a valid URL. */
|
|
296
|
+
readonly tokenUrl: string;
|
|
297
|
+
/**
|
|
298
|
+
* The OAuth authorize scope set the connection requests, e.g. the Gmail /
|
|
299
|
+
* Drive / Sheets scope URIs. These are the connection-level handshake scopes
|
|
300
|
+
* the akai-app engine joins onto the authorize URL — distinct from a CLI's
|
|
301
|
+
* per-tool `vendorScopes`. Static per connection (dynamic scope-sets are out
|
|
302
|
+
* of scope); must declare at least one.
|
|
303
|
+
*/
|
|
304
|
+
readonly scopes: readonly string[];
|
|
305
|
+
/** Use PKCE on the authorize/exchange. Default `false`. */
|
|
306
|
+
readonly pkce?: boolean;
|
|
307
|
+
/** Client-auth method on the token exchange. Default `client_secret_basic` (the akai-app engine default). */
|
|
308
|
+
readonly tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
|
|
309
|
+
/**
|
|
310
|
+
* Static extra query params appended to the authorize URL, e.g.
|
|
311
|
+
* `{ access_type: 'offline', prompt: 'consent' }`. A plain string map — dynamic
|
|
312
|
+
* (runtime-conditional) params are out of scope.
|
|
313
|
+
*/
|
|
314
|
+
readonly extraAuthorizeParams?: Record<string, string>;
|
|
315
|
+
/**
|
|
316
|
+
* How akai-app keeps the token fresh. `cron` = a background job refreshes the
|
|
317
|
+
* token before it expires; `jit` = the token is refreshed just-in-time on the
|
|
318
|
+
* next use. These are the two values the akai-app engine branches on. Default
|
|
319
|
+
* `cron`.
|
|
320
|
+
*/
|
|
321
|
+
readonly refreshStrategy?: RefreshStrategy;
|
|
322
|
+
/**
|
|
323
|
+
* The OAuth-app credentials an admin enters once per tenant. Min 1 (the client
|
|
324
|
+
* id; usually id + secret). Declares WHICH credentials are needed — the VALUES
|
|
325
|
+
* are stored encrypted in akai-app, never in the manifest/image.
|
|
326
|
+
*/
|
|
327
|
+
readonly adminFields: readonly OAuthAdminField[];
|
|
328
|
+
/**
|
|
329
|
+
* When `true`, the connection uses a bespoke connect/disconnect flow instead
|
|
330
|
+
* of the generic akai-app OAuth routes (`/api/connections/[slug]/oauth/*`).
|
|
331
|
+
* akai-app uses this to suppress the generic Connect/Disconnect UI and skip
|
|
332
|
+
* the connection in `findOAuth2Connection`, deferring to the custom flow.
|
|
333
|
+
* Default `false`.
|
|
334
|
+
*/
|
|
335
|
+
readonly hasCustomConnectFlow?: boolean;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Spec accepted by `defineConnection()`.
|
|
339
|
+
*
|
|
340
|
+
* A connection is the umbrella identity that groups CLIs sharing one auth
|
|
341
|
+
* surface (e.g. `google` groups gmail + gsheet). It declares the identity that
|
|
342
|
+
* surfaces on the Connections page and the auth kind — never the OAuth glue or
|
|
343
|
+
* UI cosmetics, which stay in akai-app keyed by slug.
|
|
344
|
+
*/
|
|
345
|
+
export interface ConnectionSpec {
|
|
346
|
+
/**
|
|
347
|
+
* Stable connection id. Groups every CLI that declares
|
|
348
|
+
* `defineCLI({ connectionSlug: <slug> })`. Same id-style rule as a CLI id:
|
|
349
|
+
* lowercase letters/digits/hyphens/underscores, must start with a letter.
|
|
350
|
+
*/
|
|
351
|
+
slug: string;
|
|
352
|
+
/** Umbrella display name shown on the connection card and drawer, e.g. `Google Workspace`. */
|
|
353
|
+
name: string;
|
|
354
|
+
/** Vendor name, e.g. `Google`. */
|
|
355
|
+
vendor: string;
|
|
356
|
+
/** Short card text — one line on the Connections list. */
|
|
357
|
+
blurb: string;
|
|
358
|
+
/** Long-form drawer text shown when the connection is opened. */
|
|
359
|
+
longDesc: string;
|
|
360
|
+
/** Optional step-by-step setup notes rendered in the drawer. */
|
|
361
|
+
instructions?: readonly string[];
|
|
362
|
+
/**
|
|
363
|
+
* WHICH auth kind the connection uses. Declares WHAT auth, not the glue — the
|
|
364
|
+
* OAuth handshake (client creds, authorize/token URLs, refresh) stays in
|
|
365
|
+
* akai-app. When `oauth2`, `oauth` is required.
|
|
366
|
+
*/
|
|
367
|
+
authKind: ConnectionAuthKind;
|
|
368
|
+
/**
|
|
369
|
+
* OAuth shape. Required when `authKind` is `oauth2`; ignored otherwise.
|
|
370
|
+
* Declares the shape only — secret VALUES live in akai-app.
|
|
371
|
+
*/
|
|
372
|
+
oauth?: ConnectionOAuthConfig;
|
|
373
|
+
}
|
|
374
|
+
/** A built connection. Opaque to consumers, introspectable by the SDK. Mirrors `CLIDef`. */
|
|
375
|
+
export interface ConnectionDef {
|
|
376
|
+
readonly __akaiConnection: true;
|
|
377
|
+
readonly slug: string;
|
|
378
|
+
readonly name: string;
|
|
379
|
+
readonly vendor: string;
|
|
380
|
+
readonly blurb: string;
|
|
381
|
+
readonly longDesc: string;
|
|
382
|
+
readonly instructions: ReadonlyArray<string>;
|
|
383
|
+
readonly authKind: ConnectionAuthKind;
|
|
384
|
+
readonly oauth?: ConnectionOAuthConfig;
|
|
385
|
+
}
|
|
251
386
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,KAAK,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,MAAM,EAAE,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CAAC;CACpD;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE1C,kEAAkE;AAClE,MAAM,WAAW,WAAW,CAC1B,QAAQ,SAAS,MAAM,GAAG,MAAM,EAChC,WAAW,SAAS,MAAM,GAAG,MAAM;IAEnC,mDAAmD;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,0GAA0G;AAC1G,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO,CACtB,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,MAAM,GAAG,MAAM;IAEzB,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9D,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACjD,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACpD,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C;;;;;;;;OAQG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,oEAAoE;AACpE,MAAM,WAAW,OAAO,CACtB,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,EACjB,QAAQ,SAAS,MAAM,GAAG,MAAM,EAChC,WAAW,SAAS,MAAM,GAAG,MAAM;IAEnC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,sGAAsG;IACtG,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACpC,MAAM,EAAE,OAAO,CAAC;KACjB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB;AAED;;;;;;GAMG;AAEH,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAG3D,gDAAgD;AAChD,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE/E,iDAAiD;AACjD,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEhF,+DAA+D;AAC/D,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEjF,iEAAiE;AACjE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAGpF,mEAAmE;AACnE,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,gGAAgG;IAChG,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACrD,4GAA4G;IAC5G,QAAQ,IAAI,kBAAkB,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,QAAQ,CACvB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,GAAG,SAAS,GAAG,SAAS,EACzC,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,CAAC,SAAS,MAAM,GAAG,KAAK;IAExB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,UAAU,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,EAAE;QACP,OAAO,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,aAAa,CAAA;SAAE,CAAC;QACjE,UAAU,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;QAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;QAC5B,UAAU,EAAE,OAAO,CAAC;QACpB,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,EAAE;QACd,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACjB,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;KACjB,KAAK,OAAO,CAAC,CAAC,SAAS,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;CAChE;AAED,sCAAsC;AACtC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAChC,kGAAkG;IAClG,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACrC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iGAAiG;IACjG,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACnC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akai-workflow-builder/cli-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Authoring SDK for atomic, agent-executable CLIs and tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"akai",
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
"files": [
|
|
29
29
|
"bin",
|
|
30
30
|
"dist",
|
|
31
|
-
"CHANGELOG.md",
|
|
32
31
|
"LICENSE",
|
|
33
32
|
"README.md"
|
|
34
33
|
],
|
package/CHANGELOG.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to `@akai-workflow-builder/cli-sdk` are documented here.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
-
|
|
7
|
-
## [0.1.3]
|
|
8
|
-
|
|
9
|
-
### Added
|
|
10
|
-
|
|
11
|
-
- `AkaiToolError` — a typed, caller-facing tool failure carrying a stable `kind`
|
|
12
|
-
(`not_found` | `forbidden` | `auth_expired` | `invalid_input` | `conflict` |
|
|
13
|
-
`rate_limited` | `unavailable`), `message`, and optional `meta`. Pins
|
|
14
|
-
`name` to `'AkaiToolError'` so the host runtime can brand-check the
|
|
15
|
-
serialized shape (`{ name, kind, message, meta? }`) with no SDK dependency,
|
|
16
|
-
map `kind` to an HTTP status, and surface the message verbatim.
|
|
17
|
-
- Ergonomic static factories on `AkaiToolError`: `notFound`, `forbidden`,
|
|
18
|
-
`authExpired`, `invalidInput`, `conflict`, `rateLimited`, `unavailable`.
|
|
19
|
-
- Exported the `ToolErrorKind` type from the package entrypoint.
|