apcore-a2a 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -1
- package/dist/cli.d.ts +63 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +279 -38
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +71 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/openapi-backend.d.ts +203 -0
- package/dist/openapi-backend.d.ts.map +1 -0
- package/dist/openapi-backend.js +453 -0
- package/dist/openapi-backend.js.map +1 -0
- package/dist/server/factory.d.ts.map +1 -1
- package/dist/server/factory.js +10 -12
- package/dist/server/factory.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ Built on [`@a2a-js/sdk`](https://www.npmjs.com/package/@a2a-js/sdk) and [Express
|
|
|
32
32
|
- **JWT authentication** — tokens bridged to apcore's Identity context
|
|
33
33
|
- **A2A Explorer UI** — browser UI for discovering and testing skills, with auth bar and cURL generation
|
|
34
34
|
- **Built-in client** — `A2AClient` for calling remote A2A agents
|
|
35
|
+
- **OpenAPI backend** — point the adapter at an OpenAPI 3.0/3.1 document and every operation becomes an A2A Skill, proxied over HTTP, with no apcore project on the other end
|
|
35
36
|
- **CLI support** — `npx apcore-a2a serve` for zero-code startup
|
|
36
37
|
- **Pluggable storage** — swap in Redis or PostgreSQL via the `TaskStore` interface
|
|
37
38
|
- **Observability** — `/health`, `/metrics` endpoints
|
|
@@ -40,7 +41,15 @@ Built on [`@a2a-js/sdk`](https://www.npmjs.com/package/@a2a-js/sdk) and [Express
|
|
|
40
41
|
## Requirements
|
|
41
42
|
|
|
42
43
|
- Node.js >= 18.0.0
|
|
43
|
-
- `apcore-js` >= 0.
|
|
44
|
+
- `apcore-js` >= 0.30.0
|
|
45
|
+
- `apcore-toolkit` >= 0.11.1
|
|
46
|
+
|
|
47
|
+
> **OpenAPI backend.** No extra install. The backend needs apcore-toolkit's
|
|
48
|
+
> `OpenAPIScanner`, `loadSpec` and `HTTPProxyRegistryWriter`, all of which ship in
|
|
49
|
+
> the `apcore-toolkit` dependency above and use the global `fetch` available on
|
|
50
|
+
> Node 18+ — so this package declares no `openapi` optional dependency. (The
|
|
51
|
+
> Python distribution declares an `apcore-a2a[openapi]` extra because there the
|
|
52
|
+
> same three pieces sit behind `apcore-toolkit[http-proxy]`.)
|
|
44
53
|
|
|
45
54
|
---
|
|
46
55
|
|
|
@@ -80,6 +89,68 @@ npx apcore-a2a serve --extensions-dir ./extensions --port 3000 --explorer --metr
|
|
|
80
89
|
npx apcore-a2a serve --extensions-dir ./extensions --auth-type bearer --auth-key mysecret
|
|
81
90
|
```
|
|
82
91
|
|
|
92
|
+
### Serve an OpenAPI document as A2A Skills
|
|
93
|
+
|
|
94
|
+
Point the adapter at an OpenAPI 3.0/3.1 document and every operation becomes a
|
|
95
|
+
skill, proxied over HTTP to the API that published it. No apcore project required
|
|
96
|
+
on the other end.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npx apcore-a2a serve \
|
|
100
|
+
--from-openapi https://petstore3.swagger.io/api/v3/openapi.json \
|
|
101
|
+
--openapi-prefix petstore \
|
|
102
|
+
--openapi-header "X-Api-Key: $PETSTORE_SPEC_KEY" \
|
|
103
|
+
--openapi-no-deprecated
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { openapiBackend, serve } from "apcore-a2a";
|
|
108
|
+
|
|
109
|
+
const registry = await openapiBackend("https://api.example.com/openapi.json", {
|
|
110
|
+
prefix: "petstore", // prepended to every derived module ID
|
|
111
|
+
baseUrl: "https://api.example.com", // defaults to servers[0].url
|
|
112
|
+
include: "pets\\..*", // scanner filters
|
|
113
|
+
timeout: 30, // SPEC-FETCH timeout, in SECONDS
|
|
114
|
+
headers: { "X-Api-Key": process.env.PETSTORE_SPEC_KEY! }, // spec fetch only
|
|
115
|
+
authHeaderFactory: () => ({ Authorization: `Bearer ${mintToken()}` }), // proxied calls
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
serve(registry);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Or configure it entirely through the Config Bus:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
apcore-a2a:
|
|
125
|
+
openapi:
|
|
126
|
+
spec: "https://api.example.com/openapi.json" # URL, or a path resolved against Config.projectRoot
|
|
127
|
+
base_url: "https://api.example.com"
|
|
128
|
+
prefix: petstore
|
|
129
|
+
include: "pets.*"
|
|
130
|
+
exclude: "*.internal.*"
|
|
131
|
+
include_deprecated: false
|
|
132
|
+
acknowledge_unapproved_writes: false
|
|
133
|
+
timeout: 30.0 # spec fetch, seconds — never the per-call proxy timeout
|
|
134
|
+
headers:
|
|
135
|
+
X-Api-Key: "${PETSTORE_SPEC_KEY}"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Three things are worth knowing before pointing this at a production API:
|
|
139
|
+
|
|
140
|
+
- **Write operations reach the PUBLIC Agent Card.** apcore-toolkit infers
|
|
141
|
+
annotations from the HTTP method and never infers `requiresApproval`, so a
|
|
142
|
+
`POST /charges` is annotated exactly like a `POST /echo` and appears on
|
|
143
|
+
`/.well-known/agent-card.json`, a route that is auth-exempt by design. The
|
|
144
|
+
backend logs a warning naming that exposure; close it with an ACL rule carrying
|
|
145
|
+
`approval: required` (which also withholds the skill from the public card), or
|
|
146
|
+
record the decision with `acknowledge_unapproved_writes: true`.
|
|
147
|
+
- **`headers` authenticate the spec fetch only.** They are never forwarded to
|
|
148
|
+
proxied calls: a document is often public while the API behind it is not.
|
|
149
|
+
Per-request credentials belong in `authHeaderFactory`.
|
|
150
|
+
- **ACL targets move when the upstream renames an operation.** Set `prefix` and
|
|
151
|
+
write the catch-all deny against the prefix (`targets: ["petstore.*"]`), not
|
|
152
|
+
against operation names.
|
|
153
|
+
|
|
83
154
|
### Call a remote A2A Agent
|
|
84
155
|
|
|
85
156
|
Use the built-in client to discover and invoke any A2A-compliant agent:
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,67 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
/**
|
|
4
|
+
* The `values` half of a `parseArgs` result under `strict: false`.
|
|
5
|
+
*
|
|
6
|
+
* Wider than the flag table suggests on purpose: with `strict: false` node
|
|
7
|
+
* accepts `--metrics=x` for a boolean and repeats for a non-`multiple` option,
|
|
8
|
+
* so every entry may arrive as a string, a boolean, or an array of either.
|
|
9
|
+
*/
|
|
10
|
+
type CliValues = Record<string, string | boolean | (string | boolean)[] | undefined>;
|
|
11
|
+
/**
|
|
12
|
+
* Exit `2` — a usage error. The command line itself is wrong.
|
|
13
|
+
*
|
|
14
|
+
* Distinguished from {@link fail} because retrying an exit-2 command unchanged
|
|
15
|
+
* will always fail, while an exit-1 command may succeed once the directory,
|
|
16
|
+
* config or network it named is fixed. That is a difference a supervisor or CI
|
|
17
|
+
* job can act on, and this SDK previously collapsed both onto `1` — losing a
|
|
18
|
+
* distinction Python's argparse and Rust's clap each provide for free.
|
|
19
|
+
*
|
|
20
|
+
* `2` rather than some other number because it is what argparse, clap and GNU
|
|
21
|
+
* getopt all use for a usage fault, so the three bindings agree with each other
|
|
22
|
+
* and with the tools around them.
|
|
23
|
+
*/
|
|
24
|
+
export declare function failUsage(message: string): never;
|
|
2
25
|
export declare function resolveAuthKey(authKey?: string): string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Parse `serve`'s argv.
|
|
28
|
+
*
|
|
29
|
+
* Split out of {@link main} so the flag surface is reachable without starting a
|
|
30
|
+
* server: the `--openapi-no-deprecated` contract is half in this table (no
|
|
31
|
+
* `default`) and half in {@link mergeOpenapiSettings} (the presence check), and
|
|
32
|
+
* either half alone silently reverses a config `include_deprecated: false`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseCliArgs(args?: string[]): ReturnType<typeof parseArgs>;
|
|
3
35
|
export declare function main(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Parse repeated `--openapi-header "Key: Value"` flags into a header map.
|
|
38
|
+
*
|
|
39
|
+
* These authenticate the **spec fetch only**. They are deliberately not reused
|
|
40
|
+
* for proxied calls: a document is often public while the API behind it is not,
|
|
41
|
+
* and broadcasting a spec-read key on every skill invocation would be a
|
|
42
|
+
* privilege escalation the operator never wrote down.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseOpenapiHeaders(raw: string[] | undefined): Record<string, string> | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the OpenAPI backend settings: CLI flags over the Config Bus.
|
|
47
|
+
*
|
|
48
|
+
* Implements the precedence the feature spec states — **an explicit CLI flag
|
|
49
|
+
* beats the `apcore-a2a.openapi` Config Bus section, which beats the default** —
|
|
50
|
+
* and implements it PER KEY, not per source. Choosing the whole source by
|
|
51
|
+
* whoever named `spec` would make a `--openapi-prefix` alongside a
|
|
52
|
+
* config-declared `spec` a silent no-op: the same shape as the apcore-mcp
|
|
53
|
+
* `--openapi-header` defect this project filed upstream (apcore-mcp-rust#8).
|
|
54
|
+
*
|
|
55
|
+
* The returned mapping is in the Config Bus's own snake_case, so it can be
|
|
56
|
+
* handed straight to `buildOpenapiBackendFromConfig` — which is also what makes
|
|
57
|
+
* `timeout`, `include`, `exclude` and `acknowledge_unapproved_writes` reachable
|
|
58
|
+
* from a running server: none of them has a CLI flag, and before this the
|
|
59
|
+
* section had no reader anywhere in `src/`.
|
|
60
|
+
*
|
|
61
|
+
* Returns `null` when neither route yields a `spec`, which is the ordinary "no
|
|
62
|
+
* OpenAPI configured" outcome rather than an error. A section that is not a
|
|
63
|
+
* mapping is returned UNCHANGED — see below.
|
|
64
|
+
*/
|
|
65
|
+
export declare function mergeOpenapiSettings(values: CliValues): Promise<unknown>;
|
|
66
|
+
export {};
|
|
4
67
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAqDtC;;;;;;GAMG;AACH,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC;AAarF;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAEhD;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYnE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CA6C1E;AAwDD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B1C;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAS,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAmBpC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAuC9E"}
|
package/dist/cli.js
CHANGED
|
@@ -9,9 +9,27 @@ apcore-a2a - A2A Protocol Server for apcore modules
|
|
|
9
9
|
|
|
10
10
|
Usage:
|
|
11
11
|
apcore-a2a serve --extensions-dir <path> [options]
|
|
12
|
+
apcore-a2a serve --from-openapi <url|path> [options]
|
|
12
13
|
|
|
13
|
-
Required:
|
|
14
|
+
Required (at least one backend source):
|
|
14
15
|
--extensions-dir <path> Path to apcore extensions directory
|
|
16
|
+
--from-openapi <url|path> OpenAPI 3.0/3.1 document to serve as A2A Skills.
|
|
17
|
+
Combine with --extensions-dir only when
|
|
18
|
+
--openapi-prefix is also given
|
|
19
|
+
|
|
20
|
+
An apcore-a2a.openapi.spec in your apcore config counts as a backend source
|
|
21
|
+
too, so neither flag is required when the config file names one.
|
|
22
|
+
|
|
23
|
+
OpenAPI backend options (each overrides the matching apcore-a2a.openapi key;
|
|
24
|
+
keys with no flag -- timeout, headers, acknowledge_unapproved_writes -- are
|
|
25
|
+
configured there):
|
|
26
|
+
--openapi-base-url <url> Base URL for proxied calls (default: servers[0].url)
|
|
27
|
+
--openapi-prefix <string> Prefix for every derived module ID
|
|
28
|
+
--openapi-include <regex> Scanner include filter
|
|
29
|
+
--openapi-exclude <regex> Scanner exclude filter
|
|
30
|
+
--openapi-header <K:V> Header for the SPEC FETCH only, repeatable.
|
|
31
|
+
Never forwarded to proxied calls
|
|
32
|
+
--openapi-no-deprecated Skip operations marked deprecated: true
|
|
15
33
|
|
|
16
34
|
Options:
|
|
17
35
|
--host <address> Bind host (default: 127.0.0.1)
|
|
@@ -34,10 +52,32 @@ Options:
|
|
|
34
52
|
--help Show this help
|
|
35
53
|
`);
|
|
36
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Exit `1` — a configuration or runtime error.
|
|
57
|
+
*
|
|
58
|
+
* The command line was well-formed; the environment it named was not. A
|
|
59
|
+
* supervisor may retry these, because the world can become ready.
|
|
60
|
+
*/
|
|
37
61
|
function fail(message, exitCode = 1) {
|
|
38
62
|
console.error(`Error: ${message}`);
|
|
39
63
|
process.exit(exitCode);
|
|
40
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Exit `2` — a usage error. The command line itself is wrong.
|
|
67
|
+
*
|
|
68
|
+
* Distinguished from {@link fail} because retrying an exit-2 command unchanged
|
|
69
|
+
* will always fail, while an exit-1 command may succeed once the directory,
|
|
70
|
+
* config or network it named is fixed. That is a difference a supervisor or CI
|
|
71
|
+
* job can act on, and this SDK previously collapsed both onto `1` — losing a
|
|
72
|
+
* distinction Python's argparse and Rust's clap each provide for free.
|
|
73
|
+
*
|
|
74
|
+
* `2` rather than some other number because it is what argparse, clap and GNU
|
|
75
|
+
* getopt all use for a usage fault, so the three bindings agree with each other
|
|
76
|
+
* and with the tools around them.
|
|
77
|
+
*/
|
|
78
|
+
export function failUsage(message) {
|
|
79
|
+
return fail(message, 2);
|
|
80
|
+
}
|
|
41
81
|
export function resolveAuthKey(authKey) {
|
|
42
82
|
if (authKey) {
|
|
43
83
|
try {
|
|
@@ -52,37 +92,113 @@ export function resolveAuthKey(authKey) {
|
|
|
52
92
|
}
|
|
53
93
|
return process.env.APCORE_JWT_SECRET;
|
|
54
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Parse `serve`'s argv.
|
|
97
|
+
*
|
|
98
|
+
* Split out of {@link main} so the flag surface is reachable without starting a
|
|
99
|
+
* server: the `--openapi-no-deprecated` contract is half in this table (no
|
|
100
|
+
* `default`) and half in {@link mergeOpenapiSettings} (the presence check), and
|
|
101
|
+
* either half alone silently reverses a config `include_deprecated: false`.
|
|
102
|
+
*/
|
|
103
|
+
export function parseCliArgs(args) {
|
|
104
|
+
const config = {
|
|
105
|
+
options: {
|
|
106
|
+
"extensions-dir": { type: "string" },
|
|
107
|
+
"from-openapi": { type: "string" },
|
|
108
|
+
"openapi-base-url": { type: "string" },
|
|
109
|
+
"openapi-prefix": { type: "string" },
|
|
110
|
+
"openapi-include": { type: "string" },
|
|
111
|
+
"openapi-exclude": { type: "string" },
|
|
112
|
+
"openapi-header": { type: "string", multiple: true },
|
|
113
|
+
// Deliberately NO `default: false`. `mergeOpenapiSettings` has to tell
|
|
114
|
+
// "not passed" from "passed", because a `false` default would make an
|
|
115
|
+
// absent flag overwrite a config `include_deprecated: false` with `true`
|
|
116
|
+
// — an unpassed flag silently reversing a setting the operator wrote.
|
|
117
|
+
// Same reason the Python binding uses `default=None`.
|
|
118
|
+
"openapi-no-deprecated": { type: "boolean" },
|
|
119
|
+
host: { type: "string", default: "127.0.0.1" },
|
|
120
|
+
port: { type: "string", default: "8000" },
|
|
121
|
+
name: { type: "string" },
|
|
122
|
+
description: { type: "string" },
|
|
123
|
+
"version-str": { type: "string" },
|
|
124
|
+
url: { type: "string" },
|
|
125
|
+
"auth-type": { type: "string" },
|
|
126
|
+
"auth-key": { type: "string" },
|
|
127
|
+
"auth-issuer": { type: "string" },
|
|
128
|
+
"auth-audience": { type: "string" },
|
|
129
|
+
"push-notifications": { type: "boolean", default: false },
|
|
130
|
+
explorer: { type: "boolean", default: false },
|
|
131
|
+
"cors-origins": { type: "string" },
|
|
132
|
+
"execution-timeout": { type: "string", default: "300" },
|
|
133
|
+
"log-level": { type: "string", default: "info" },
|
|
134
|
+
metrics: { type: "boolean", default: false },
|
|
135
|
+
version: { type: "boolean", default: false },
|
|
136
|
+
help: { type: "boolean", default: false },
|
|
137
|
+
},
|
|
138
|
+
allowPositionals: true,
|
|
139
|
+
strict: false,
|
|
140
|
+
};
|
|
141
|
+
// `args: undefined` is NOT the same as omitting it — node's own default
|
|
142
|
+
// (`process.argv` minus the execPath and script) knows about `node --` and
|
|
143
|
+
// single-executable builds, and re-deriving it here would drop that.
|
|
144
|
+
const parsed = args === undefined ? parseArgs(config) : parseArgs({ ...config, args });
|
|
145
|
+
rejectUnknownArguments(parsed, Object.keys(config.options));
|
|
146
|
+
return parsed;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Refuse an argument the flag table does not define.
|
|
150
|
+
*
|
|
151
|
+
* `strict: false` is kept deliberately — it is what lets this CLI tolerate
|
|
152
|
+
* `--metrics=x` for a boolean and a repeat of a non-`multiple` option, both of
|
|
153
|
+
* which `strict: true` would turn into throws — but node's tolerance extends to
|
|
154
|
+
* *unknown* flags too, and there it is not tolerance, it is silence.
|
|
155
|
+
*
|
|
156
|
+
* Measured before this check existed, with a one-letter typo:
|
|
157
|
+
*
|
|
158
|
+
* ```
|
|
159
|
+
* apcore-a2a serve --extensions-dir ./ext --openapi-exclde 'secret.*'
|
|
160
|
+
* values: { "openapi-exclde": true, ... } ← the flag became a boolean
|
|
161
|
+
* positionals: [ "serve", "secret.*" ] ← its value became a positional
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* The exclusion silently did not apply, and every operation it was meant to hold
|
|
165
|
+
* back was scanned, registered, and published to the **public** Agent Card — a
|
|
166
|
+
* route served without authentication and built to be crawled. The server
|
|
167
|
+
* started and reported success.
|
|
168
|
+
*
|
|
169
|
+
* Python's argparse (`unrecognized arguments`) and Rust's clap (`unexpected
|
|
170
|
+
* argument ... found`) both refuse this and exit 2; TypeScript was the only
|
|
171
|
+
* binding that did not, so the tolerant behaviour was never portable — the same
|
|
172
|
+
* argv already failed on the other two.
|
|
173
|
+
*
|
|
174
|
+
* Note argparse additionally accepts unambiguous *abbreviations*, so
|
|
175
|
+
* `--openapi-exclud` is a legal spelling there. That is an argparse feature, not
|
|
176
|
+
* a parity requirement: clap does not do it either, and this check is only about
|
|
177
|
+
* spellings no binding recognises.
|
|
178
|
+
*/
|
|
179
|
+
function rejectUnknownArguments(parsed, known) {
|
|
180
|
+
const unknown = Object.keys(parsed.values).filter((key) => !known.includes(key));
|
|
181
|
+
if (unknown.length > 0) {
|
|
182
|
+
failUsage(`unrecognized argument${unknown.length > 1 ? "s" : ""}: ` +
|
|
183
|
+
`${unknown.map((k) => `--${k}`).join(", ")}. Run with --help for the flag list`);
|
|
184
|
+
}
|
|
185
|
+
// A stray positional is the same mistake seen from the other side: the value
|
|
186
|
+
// of a misspelled flag lands here, so reporting only the flag would leave the
|
|
187
|
+
// operator wondering where their argument went.
|
|
188
|
+
const strays = parsed.positionals.slice(1);
|
|
189
|
+
if (strays.length > 0) {
|
|
190
|
+
failUsage(`unexpected argument${strays.length > 1 ? "s" : ""}: ${strays.join(", ")}. ` +
|
|
191
|
+
"Run with --help for the flag list");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
55
194
|
export async function main() {
|
|
56
195
|
let parsed;
|
|
57
196
|
try {
|
|
58
|
-
parsed =
|
|
59
|
-
options: {
|
|
60
|
-
"extensions-dir": { type: "string" },
|
|
61
|
-
host: { type: "string", default: "127.0.0.1" },
|
|
62
|
-
port: { type: "string", default: "8000" },
|
|
63
|
-
name: { type: "string" },
|
|
64
|
-
description: { type: "string" },
|
|
65
|
-
"version-str": { type: "string" },
|
|
66
|
-
url: { type: "string" },
|
|
67
|
-
"auth-type": { type: "string" },
|
|
68
|
-
"auth-key": { type: "string" },
|
|
69
|
-
"auth-issuer": { type: "string" },
|
|
70
|
-
"auth-audience": { type: "string" },
|
|
71
|
-
"push-notifications": { type: "boolean", default: false },
|
|
72
|
-
explorer: { type: "boolean", default: false },
|
|
73
|
-
"cors-origins": { type: "string" },
|
|
74
|
-
"execution-timeout": { type: "string", default: "300" },
|
|
75
|
-
"log-level": { type: "string", default: "info" },
|
|
76
|
-
metrics: { type: "boolean", default: false },
|
|
77
|
-
version: { type: "boolean", default: false },
|
|
78
|
-
help: { type: "boolean", default: false },
|
|
79
|
-
},
|
|
80
|
-
allowPositionals: true,
|
|
81
|
-
strict: false,
|
|
82
|
-
});
|
|
197
|
+
parsed = parseCliArgs();
|
|
83
198
|
}
|
|
84
199
|
catch (e) {
|
|
85
|
-
|
|
200
|
+
// A parseArgs throw is an unknown flag or a missing value: a usage fault.
|
|
201
|
+
failUsage(String(e));
|
|
86
202
|
}
|
|
87
203
|
const { values, positionals } = parsed;
|
|
88
204
|
if (values.help) {
|
|
@@ -101,24 +217,149 @@ export async function main() {
|
|
|
101
217
|
}
|
|
102
218
|
await runServe(values);
|
|
103
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Parse repeated `--openapi-header "Key: Value"` flags into a header map.
|
|
222
|
+
*
|
|
223
|
+
* These authenticate the **spec fetch only**. They are deliberately not reused
|
|
224
|
+
* for proxied calls: a document is often public while the API behind it is not,
|
|
225
|
+
* and broadcasting a spec-read key on every skill invocation would be a
|
|
226
|
+
* privilege escalation the operator never wrote down.
|
|
227
|
+
*/
|
|
228
|
+
export function parseOpenapiHeaders(raw) {
|
|
229
|
+
if (!raw || raw.length === 0)
|
|
230
|
+
return undefined;
|
|
231
|
+
const headers = {};
|
|
232
|
+
for (const entry of raw) {
|
|
233
|
+
const separator = entry.indexOf(":");
|
|
234
|
+
// The separator index alone is not the test. `separator <= 0` rejects ":v"
|
|
235
|
+
// but ACCEPTS " :v" — the colon is at index 1 — and the `.trim()` below then
|
|
236
|
+
// yields an EMPTY header name. Python checks `not key.strip()` and Rust
|
|
237
|
+
// `key.trim().is_empty()`; both reject, so the key is trimmed first and
|
|
238
|
+
// judged afterwards.
|
|
239
|
+
const key = separator > 0 ? entry.slice(0, separator).trim() : "";
|
|
240
|
+
if (!key) {
|
|
241
|
+
// Never echo the value back: the whole point of the flag is that it may
|
|
242
|
+
// carry a credential.
|
|
243
|
+
failUsage(`--openapi-header must be "Key: Value" (got an entry with no ':' or no key)`);
|
|
244
|
+
}
|
|
245
|
+
headers[key] = entry.slice(separator + 1).trim();
|
|
246
|
+
}
|
|
247
|
+
return headers;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Resolve the OpenAPI backend settings: CLI flags over the Config Bus.
|
|
251
|
+
*
|
|
252
|
+
* Implements the precedence the feature spec states — **an explicit CLI flag
|
|
253
|
+
* beats the `apcore-a2a.openapi` Config Bus section, which beats the default** —
|
|
254
|
+
* and implements it PER KEY, not per source. Choosing the whole source by
|
|
255
|
+
* whoever named `spec` would make a `--openapi-prefix` alongside a
|
|
256
|
+
* config-declared `spec` a silent no-op: the same shape as the apcore-mcp
|
|
257
|
+
* `--openapi-header` defect this project filed upstream (apcore-mcp-rust#8).
|
|
258
|
+
*
|
|
259
|
+
* The returned mapping is in the Config Bus's own snake_case, so it can be
|
|
260
|
+
* handed straight to `buildOpenapiBackendFromConfig` — which is also what makes
|
|
261
|
+
* `timeout`, `include`, `exclude` and `acknowledge_unapproved_writes` reachable
|
|
262
|
+
* from a running server: none of them has a CLI flag, and before this the
|
|
263
|
+
* section had no reader anywhere in `src/`.
|
|
264
|
+
*
|
|
265
|
+
* Returns `null` when neither route yields a `spec`, which is the ordinary "no
|
|
266
|
+
* OpenAPI configured" outcome rather than an error. A section that is not a
|
|
267
|
+
* mapping is returned UNCHANGED — see below.
|
|
268
|
+
*/
|
|
269
|
+
export async function mergeOpenapiSettings(values) {
|
|
270
|
+
// Imported lazily so `--help` and `--version` never pay for loading apcore's
|
|
271
|
+
// Config, mirroring the Python binding's function-local import.
|
|
272
|
+
const { getA2aSetting } = await import("./config.js");
|
|
273
|
+
const section = getA2aSetting("openapi");
|
|
274
|
+
// A section that is not a mapping is passed through untouched, so that
|
|
275
|
+
// `buildOpenapiBackendFromConfig` reports it by name ("apcore-a2a.openapi
|
|
276
|
+
// must be a mapping."). Discarding it instead would turn the typo
|
|
277
|
+
// `openapi: ./spec.json` — a mapping's one key written as the whole value —
|
|
278
|
+
// into "a backend source is required", which sends the operator hunting for a
|
|
279
|
+
// missing flag rather than at the line they wrote. Follows the Rust binding,
|
|
280
|
+
// which diverged from the Python reference here for this reason.
|
|
281
|
+
if (section !== undefined && (typeof section !== "object" || Array.isArray(section))) {
|
|
282
|
+
return section;
|
|
283
|
+
}
|
|
284
|
+
const merged = {
|
|
285
|
+
...(section ?? {}),
|
|
286
|
+
};
|
|
287
|
+
// Only a flag the operator actually passed is overlaid. Every OpenAPI flag is
|
|
288
|
+
// `undefined` when absent precisely so that "absent" stays distinguishable
|
|
289
|
+
// from "explicitly set to a falsy value".
|
|
290
|
+
const overlay = {
|
|
291
|
+
spec: values["from-openapi"],
|
|
292
|
+
base_url: values["openapi-base-url"],
|
|
293
|
+
prefix: values["openapi-prefix"],
|
|
294
|
+
include: values["openapi-include"],
|
|
295
|
+
exclude: values["openapi-exclude"],
|
|
296
|
+
headers: parseOpenapiHeaders(values["openapi-header"]),
|
|
297
|
+
};
|
|
298
|
+
if (values["openapi-no-deprecated"] !== undefined) {
|
|
299
|
+
overlay.include_deprecated = !values["openapi-no-deprecated"];
|
|
300
|
+
}
|
|
301
|
+
for (const [key, value] of Object.entries(overlay)) {
|
|
302
|
+
if (value !== undefined && value !== null)
|
|
303
|
+
merged[key] = value;
|
|
304
|
+
}
|
|
305
|
+
return merged.spec ? merged : null;
|
|
306
|
+
}
|
|
307
|
+
/** The `spec` of merged settings, when they are a mapping that names one. */
|
|
308
|
+
function specOf(openapi) {
|
|
309
|
+
if (typeof openapi !== "object" || openapi === null)
|
|
310
|
+
return undefined;
|
|
311
|
+
const spec = openapi.spec;
|
|
312
|
+
return typeof spec === "string" ? spec : undefined;
|
|
313
|
+
}
|
|
104
314
|
async function runServe(values) {
|
|
105
315
|
const extensionsDir = values["extensions-dir"];
|
|
106
|
-
|
|
107
|
-
|
|
316
|
+
// A backend source may also come from the Config Bus, so the usage check has
|
|
317
|
+
// to consult it — otherwise a valid `apcore-a2a.openapi.spec` in the config
|
|
318
|
+
// file would be rejected for naming no flag.
|
|
319
|
+
const openapi = await mergeOpenapiSettings(values);
|
|
320
|
+
if (!extensionsDir && !openapi) {
|
|
321
|
+
failUsage("one of --extensions-dir or --from-openapi is required " +
|
|
322
|
+
"(or an apcore-a2a.openapi.spec in your apcore config)");
|
|
323
|
+
}
|
|
324
|
+
const { Registry } = await import("apcore-js");
|
|
325
|
+
let registry;
|
|
326
|
+
if (extensionsDir) {
|
|
327
|
+
const resolved = resolve(extensionsDir);
|
|
328
|
+
if (!existsSync(resolved)) {
|
|
329
|
+
fail(`Extensions directory not found: ${resolved}`);
|
|
330
|
+
}
|
|
331
|
+
if (!statSync(resolved).isDirectory()) {
|
|
332
|
+
fail(`Not a directory: ${resolved}`);
|
|
333
|
+
}
|
|
334
|
+
registry = new Registry({ extensionsDir: resolved });
|
|
108
335
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
fail(`Extensions directory not found: ${resolved}`);
|
|
336
|
+
else {
|
|
337
|
+
registry = new Registry();
|
|
112
338
|
}
|
|
113
|
-
if (
|
|
114
|
-
|
|
339
|
+
if (openapi) {
|
|
340
|
+
const { buildOpenapiBackendFromConfig } = await import("./openapi-backend.js");
|
|
341
|
+
try {
|
|
342
|
+
// The merged mapping, not the raw flags: this is the one route that reads
|
|
343
|
+
// `timeout` and `acknowledge_unapproved_writes`, applies the documented
|
|
344
|
+
// defaults, and resolves a relative `spec` against `Config.projectRoot`
|
|
345
|
+
// rather than the process CWD (FR-OAS-004 AC 5).
|
|
346
|
+
registry =
|
|
347
|
+
(await buildOpenapiBackendFromConfig(openapi, {
|
|
348
|
+
registry,
|
|
349
|
+
// `prefix` is mandatory in a mixed deployment: the scanner
|
|
350
|
+
// deduplicates within one scan only and knows nothing about the
|
|
351
|
+
// project modules already in the registry.
|
|
352
|
+
hasOtherBackendSource: !!extensionsDir,
|
|
353
|
+
})) ?? registry;
|
|
354
|
+
}
|
|
355
|
+
catch (e) {
|
|
356
|
+
// The resolved spec location may appear here; the fetch headers never do.
|
|
357
|
+
fail(`OpenAPI backend: ${e instanceof Error ? e.message : String(e)}`);
|
|
358
|
+
}
|
|
115
359
|
}
|
|
116
|
-
// Load registry
|
|
117
|
-
const { Registry } = await import("apcore-js");
|
|
118
|
-
const registry = new Registry({ extensionsDir: resolved });
|
|
119
360
|
const modules = registry.list();
|
|
120
361
|
if (modules.length === 0) {
|
|
121
|
-
fail(`No modules discovered in ${
|
|
362
|
+
fail(`No modules discovered in ${specOf(openapi) ?? extensionsDir}`);
|
|
122
363
|
}
|
|
123
364
|
console.log(`Discovered ${modules.length} module(s): ${modules.join(", ")}`);
|
|
124
365
|
// Build auth
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config namespace registration and resolution for `apcore-a2a`.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Python binding's `apcore_a2a._config`. It lives in its own module
|
|
5
|
+
* rather than in `server/factory.ts` because the CLI has to read the
|
|
6
|
+
* `apcore-a2a.openapi` section *before* it builds a Registry, and therefore long
|
|
7
|
+
* before anything in the server stack is imported — pulling in the factory (and
|
|
8
|
+
* with it express and the whole A2A SDK) just to register a namespace would put
|
|
9
|
+
* the entire server on the startup path of `apcore-a2a serve --help`.
|
|
10
|
+
*
|
|
11
|
+
* Registration must happen from exactly ONE place: apcore's
|
|
12
|
+
* `Config.registerNamespace` throws `ConfigNamespaceDuplicateError` on a second
|
|
13
|
+
* call for the same name, so a second registration site would crash the process
|
|
14
|
+
* at import time rather than being ignored.
|
|
15
|
+
*/
|
|
16
|
+
export declare const A2A_NAMESPACE = "apcore-a2a";
|
|
17
|
+
export declare const A2A_ENV_PREFIX = "APCORE_A2A";
|
|
18
|
+
/** The registered namespace defaults (stable in apcore-js >= 0.22.0). */
|
|
19
|
+
export declare const A2A_DEFAULTS: Record<string, unknown>;
|
|
20
|
+
/**
|
|
21
|
+
* Register the `apcore-a2a` config namespace. Safe to call repeatedly.
|
|
22
|
+
*
|
|
23
|
+
* The already-registered case is detected rather than caught: swallowing every
|
|
24
|
+
* exception here would also swallow a genuine `ConfigEnvPrefixConflictError`
|
|
25
|
+
* from another package claiming `APCORE_A2A`, which is a misconfiguration the
|
|
26
|
+
* operator needs to see.
|
|
27
|
+
*/
|
|
28
|
+
export declare function registerA2aNamespace(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve one `apcore-a2a` namespace setting through apcore's Config.
|
|
31
|
+
*
|
|
32
|
+
* Delegates to `Config.load` so that values from an apcore config file and
|
|
33
|
+
* `APCORE_A2A_*` environment overrides are applied by apcore itself (namespace
|
|
34
|
+
* mode), exactly like the other apcore bindings. Falls back to `fallback` when
|
|
35
|
+
* the key is unset.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getA2aSetting(key: string, fallback?: unknown): unknown;
|
|
38
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,eAAO,MAAM,aAAa,eAAe,CAAC;AAC1C,eAAO,MAAM,cAAc,eAAe,CAAC;AAE3C,yEAAyE;AACzE,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAoBhD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAO3C;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAMtE"}
|