@introspection-sdk/introspection-node 0.13.0 → 0.14.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/.turbo/turbo-build.log +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +12 -2
- package/dist/client.js.map +1 -1
- package/dist/dev-target.d.ts +54 -0
- package/dist/dev-target.d.ts.map +1 -0
- package/dist/dev-target.js +71 -0
- package/dist/dev-target.js.map +1 -0
- package/package.json +21 -21
- package/src/client.ts +13 -2
- package/src/dev-target.ts +79 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> @introspection-sdk/introspection-node@0.
|
|
2
|
+
> @introspection-sdk/introspection-node@0.14.0 build /home/runner/work/introspection-js-sdk/introspection-js-sdk/packages/introspection-node
|
|
3
3
|
> tsc
|
|
4
4
|
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAuB,KAAK,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAuB,KAAK,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGxE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,mBAAmB;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,oBAAoB,CAAC;IAEtD;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,cAAc,GAAG,uBAAuB,CAAC;IAE/D;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;gBAEjB,OAAO,GAAE,0BAA+B;IA0CpD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;WACU,kBAAkB,CAC7B,MAAM,EAAE,yBAAyB,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3D,OAAO,CAAC,mBAAmB,CAAC;IAS/B,wCAAwC;IAClC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKhC"}
|
package/dist/client.js
CHANGED
|
@@ -17,6 +17,7 @@ import { HttpClient } from "./http.js";
|
|
|
17
17
|
import { attachRuntimes, } from "./resources/runtimes.js";
|
|
18
18
|
import { attachExperiments, } from "./resources/experiments.js";
|
|
19
19
|
import { attachRecipes } from "./resources/recipes.js";
|
|
20
|
+
import { DEV_TARGET_HEADER, resolveDevTarget } from "./dev-target.js";
|
|
20
21
|
/**
|
|
21
22
|
* Introspection REST client.
|
|
22
23
|
*
|
|
@@ -61,20 +62,29 @@ export class IntrospectionClient {
|
|
|
61
62
|
constructor(options = {}) {
|
|
62
63
|
const token = options.token || process.env.INTROSPECTION_TOKEN || "";
|
|
63
64
|
const advanced = options.advanced || {};
|
|
64
|
-
this.advancedOptions = advanced;
|
|
65
65
|
const baseApiUrl = advanced.baseApiUrl ||
|
|
66
66
|
process.env.INTROSPECTION_BASE_API_URL ||
|
|
67
67
|
"https://api.introspection.dev";
|
|
68
68
|
if (!token) {
|
|
69
69
|
sdkLogger.warn("IntrospectionClient: No token provided. REST calls will fail.");
|
|
70
70
|
}
|
|
71
|
+
// INTROSPECTION_DEV_TARGET rides every request as a header so it reaches
|
|
72
|
+
// the paths a runner cannot: a bare `POST /v1/tasks` with a dev API key
|
|
73
|
+
// mints its JWT from the key row and has no per-request claim to carry.
|
|
74
|
+
// Merged first, so an explicit `additionalHeaders` entry still wins, and
|
|
75
|
+
// stored on advancedOptions so the Runner's own DP client inherits it.
|
|
76
|
+
const devTarget = resolveDevTarget();
|
|
77
|
+
const additionalHeaders = devTarget
|
|
78
|
+
? { [DEV_TARGET_HEADER]: devTarget, ...advanced.additionalHeaders }
|
|
79
|
+
: advanced.additionalHeaders;
|
|
80
|
+
this.advancedOptions = { ...advanced, additionalHeaders };
|
|
71
81
|
// CP HTTP client — talks to the customer-facing API with the customer
|
|
72
82
|
// API key. Runners get their own HttpClient instances pointed at the
|
|
73
83
|
// `deployment.endpoint` returned by `/v1/runtimes/{id}/run`.
|
|
74
84
|
this.cpHttp = new HttpClient({
|
|
75
85
|
apiUrl: baseApiUrl,
|
|
76
86
|
token,
|
|
77
|
-
additionalHeaders:
|
|
87
|
+
additionalHeaders: this.advancedOptions.additionalHeaders,
|
|
78
88
|
fetch: advanced.fetch,
|
|
79
89
|
});
|
|
80
90
|
this.runtimes = attachRuntimes(this, this.cpHttp);
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAkC,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,cAAc,GAGf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,GAGlB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,aAAa,EAAmB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development-target resolution — which `introspection dev` server this
|
|
3
|
+
* process's tasks should reach.
|
|
4
|
+
*
|
|
5
|
+
* Two developers can run `introspection dev` against one shared Runtime. A
|
|
6
|
+
* task created by a shared application credential carries no developer, so the
|
|
7
|
+
* platform cannot tell their machines apart; the caller names one instead.
|
|
8
|
+
* `introspection dev` prints the value to set:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* serving as: roland
|
|
12
|
+
* for your app: INTROSPECTION_DEV_TARGET=roland
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Carried as a header rather than on the runner's `caller` payload: `caller`
|
|
16
|
+
* is descriptive metadata the platform never acts on, and a target is a
|
|
17
|
+
* per-request selector the platform does act on. Keeping them apart is what
|
|
18
|
+
* lets `caller` stay a free-form bag, and it is the only transport that
|
|
19
|
+
* reaches a bare `POST /v1/tasks` with a dev API key, whose JWT is minted from
|
|
20
|
+
* the key row with no per-request input path.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately env-only, with no `os.userInfo()` fallback. Defaulting to the
|
|
23
|
+
* local username would be zero-config on a laptop and wrong everywhere else: a
|
|
24
|
+
* process running in a shared development deployment under an account like
|
|
25
|
+
* `node` would silently name a machine nobody is serving and fail closed,
|
|
26
|
+
* where today it reaches the one connected dev server. The CLI defaults to the
|
|
27
|
+
* username because it is naming *itself* and always runs on the developer's
|
|
28
|
+
* machine; this names *someone else's* machine and can run anywhere.
|
|
29
|
+
*
|
|
30
|
+
* Inert outside development: the Data Plane consults a target only on the
|
|
31
|
+
* development pin path, so a stray value in staging or production is ignored.
|
|
32
|
+
*/
|
|
33
|
+
/** Header carrying the target on requests that have no runner to ride. */
|
|
34
|
+
export declare const DEV_TARGET_HEADER = "x-introspection-dev-target";
|
|
35
|
+
/** The env var `introspection dev` prints and both the CLI and SDK read. */
|
|
36
|
+
export declare const DEV_TARGET_ENV = "INTROSPECTION_DEV_TARGET";
|
|
37
|
+
/**
|
|
38
|
+
* The development target for this process, or `undefined` when unset.
|
|
39
|
+
*
|
|
40
|
+
* Percent-encoded, because the value becomes an HTTP header and a header is
|
|
41
|
+
* bytes: a login name like `andré` is not transmissible as-is, and a runtime
|
|
42
|
+
* that lets it through sends latin-1 bytes the server would read back as a
|
|
43
|
+
* different string. Encoding here is lossless and costs nothing for the
|
|
44
|
+
* ordinary ASCII name, which encodes to itself.
|
|
45
|
+
*
|
|
46
|
+
* Safe to send encoded because the Data Plane decodes before it normalizes,
|
|
47
|
+
* so `andré` and `andr%C3%A9` land on the same target as the `--as andré`
|
|
48
|
+
* the CLI advertises over protobuf, where no encoding is needed.
|
|
49
|
+
*
|
|
50
|
+
* Read through `globalThis.process` so the module stays importable from
|
|
51
|
+
* non-Node runtimes that share this package's build.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveDevTarget(): string | undefined;
|
|
54
|
+
//# sourceMappingURL=dev-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-target.d.ts","sourceRoot":"","sources":["../src/dev-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,+BAA+B,CAAC;AAE9D,4EAA4E;AAC5E,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAkBzD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAOrD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development-target resolution — which `introspection dev` server this
|
|
3
|
+
* process's tasks should reach.
|
|
4
|
+
*
|
|
5
|
+
* Two developers can run `introspection dev` against one shared Runtime. A
|
|
6
|
+
* task created by a shared application credential carries no developer, so the
|
|
7
|
+
* platform cannot tell their machines apart; the caller names one instead.
|
|
8
|
+
* `introspection dev` prints the value to set:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* serving as: roland
|
|
12
|
+
* for your app: INTROSPECTION_DEV_TARGET=roland
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Carried as a header rather than on the runner's `caller` payload: `caller`
|
|
16
|
+
* is descriptive metadata the platform never acts on, and a target is a
|
|
17
|
+
* per-request selector the platform does act on. Keeping them apart is what
|
|
18
|
+
* lets `caller` stay a free-form bag, and it is the only transport that
|
|
19
|
+
* reaches a bare `POST /v1/tasks` with a dev API key, whose JWT is minted from
|
|
20
|
+
* the key row with no per-request input path.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately env-only, with no `os.userInfo()` fallback. Defaulting to the
|
|
23
|
+
* local username would be zero-config on a laptop and wrong everywhere else: a
|
|
24
|
+
* process running in a shared development deployment under an account like
|
|
25
|
+
* `node` would silently name a machine nobody is serving and fail closed,
|
|
26
|
+
* where today it reaches the one connected dev server. The CLI defaults to the
|
|
27
|
+
* username because it is naming *itself* and always runs on the developer's
|
|
28
|
+
* machine; this names *someone else's* machine and can run anywhere.
|
|
29
|
+
*
|
|
30
|
+
* Inert outside development: the Data Plane consults a target only on the
|
|
31
|
+
* development pin path, so a stray value in staging or production is ignored.
|
|
32
|
+
*/
|
|
33
|
+
/** Header carrying the target on requests that have no runner to ride. */
|
|
34
|
+
export const DEV_TARGET_HEADER = "x-introspection-dev-target";
|
|
35
|
+
/** The env var `introspection dev` prints and both the CLI and SDK read. */
|
|
36
|
+
export const DEV_TARGET_ENV = "INTROSPECTION_DEV_TARGET";
|
|
37
|
+
/**
|
|
38
|
+
* Percent-encode to RFC 3986, so the three SDKs put identical bytes on the
|
|
39
|
+
* wire for the same target.
|
|
40
|
+
*
|
|
41
|
+
* `encodeURIComponent` leaves `!'()*` alone where Python's `quote(safe="")`
|
|
42
|
+
* and the Rust client encode them. The Data Plane decodes before it
|
|
43
|
+
* normalizes, so either form routes — but a header that differs by which
|
|
44
|
+
* client sent it is a debugging trap for no benefit.
|
|
45
|
+
*/
|
|
46
|
+
function encodeTarget(value) {
|
|
47
|
+
return encodeURIComponent(value).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The development target for this process, or `undefined` when unset.
|
|
51
|
+
*
|
|
52
|
+
* Percent-encoded, because the value becomes an HTTP header and a header is
|
|
53
|
+
* bytes: a login name like `andré` is not transmissible as-is, and a runtime
|
|
54
|
+
* that lets it through sends latin-1 bytes the server would read back as a
|
|
55
|
+
* different string. Encoding here is lossless and costs nothing for the
|
|
56
|
+
* ordinary ASCII name, which encodes to itself.
|
|
57
|
+
*
|
|
58
|
+
* Safe to send encoded because the Data Plane decodes before it normalizes,
|
|
59
|
+
* so `andré` and `andr%C3%A9` land on the same target as the `--as andré`
|
|
60
|
+
* the CLI advertises over protobuf, where no encoding is needed.
|
|
61
|
+
*
|
|
62
|
+
* Read through `globalThis.process` so the module stays importable from
|
|
63
|
+
* non-Node runtimes that share this package's build.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveDevTarget() {
|
|
66
|
+
const env = globalThis.process?.env;
|
|
67
|
+
const raw = env?.[DEV_TARGET_ENV];
|
|
68
|
+
const trimmed = raw?.trim();
|
|
69
|
+
return trimmed ? encodeTarget(trimmed) : undefined;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=dev-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-target.js","sourceRoot":"","sources":["../src/dev-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,iBAAiB,GAAG,4BAA4B,CAAC;AAE9D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAEzD;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,OAAO,CACtC,UAAU,EACV,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CACxD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GACP,UACD,CAAC,OAAO,EAAE,GAAG,CAAC;IACf,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC;IAC5B,OAAO,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@introspection-sdk/introspection-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Introspection observability SDK for Node.js",
|
|
6
6
|
"engines": {
|
|
@@ -32,29 +32,29 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
36
|
-
"@anthropic-ai/sdk": "^0.
|
|
35
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.220",
|
|
36
|
+
"@anthropic-ai/sdk": "^0.115.0",
|
|
37
37
|
"@earendil-works/pi-agent-core": "^0.80.10",
|
|
38
38
|
"@earendil-works/pi-ai": "^0.80.10",
|
|
39
|
-
"@google/genai": "^2.
|
|
39
|
+
"@google/genai": "^2.13.0",
|
|
40
40
|
"@langchain/core": "^1.2.3",
|
|
41
|
-
"@mastra/core": "^1.
|
|
42
|
-
"@mastra/observability": "^1.16.
|
|
41
|
+
"@mastra/core": "^1.52.1",
|
|
42
|
+
"@mastra/observability": "^1.16.2",
|
|
43
43
|
"@openai/agents": "^0.13.5",
|
|
44
|
-
"@opentelemetry/api-logs": "^0.
|
|
45
|
-
"@opentelemetry/context-async-hooks": "^2.
|
|
46
|
-
"@opentelemetry/core": "^2.
|
|
47
|
-
"@opentelemetry/exporter-logs-otlp-proto": "^0.
|
|
48
|
-
"@opentelemetry/exporter-trace-otlp-proto": "^0.
|
|
49
|
-
"@opentelemetry/resources": "^2.
|
|
50
|
-
"@opentelemetry/sdk-logs": "^0.
|
|
51
|
-
"@opentelemetry/sdk-trace-base": "^2.
|
|
52
|
-
"@opentelemetry/sdk-trace-node": "^2.
|
|
44
|
+
"@opentelemetry/api-logs": "^0.221.0",
|
|
45
|
+
"@opentelemetry/context-async-hooks": "^2.10.0",
|
|
46
|
+
"@opentelemetry/core": "^2.10.0",
|
|
47
|
+
"@opentelemetry/exporter-logs-otlp-proto": "^0.221.0",
|
|
48
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.221.0",
|
|
49
|
+
"@opentelemetry/resources": "^2.10.0",
|
|
50
|
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
51
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
52
|
+
"@opentelemetry/sdk-trace-node": "^2.10.0",
|
|
53
53
|
"@opentelemetry/semantic-conventions": "^1.43.0",
|
|
54
54
|
"@types/node": "^22.20.1",
|
|
55
|
-
"ai": "^6.0.
|
|
55
|
+
"ai": "^6.0.235",
|
|
56
56
|
"eslint": "^9.39.5",
|
|
57
|
-
"openai": "^6.
|
|
57
|
+
"openai": "^6.49.0",
|
|
58
58
|
"typescript": "5.9.3",
|
|
59
59
|
"@repo/eslint-config": "0.0.0",
|
|
60
60
|
"@repo/typescript-config": "0.0.0"
|
|
@@ -139,10 +139,10 @@
|
|
|
139
139
|
"@opentelemetry/api": "^1.9.1",
|
|
140
140
|
"https-proxy-agent": "^7.0.6",
|
|
141
141
|
"proxy-from-env": "^2.1.0",
|
|
142
|
-
"@introspection-sdk/http": "0.
|
|
143
|
-
"@introspection-sdk/
|
|
144
|
-
"@introspection-sdk/introspection-proxy": "0.
|
|
145
|
-
"@introspection-sdk/
|
|
142
|
+
"@introspection-sdk/http": "0.14.0",
|
|
143
|
+
"@introspection-sdk/introspection-pi": "0.14.0",
|
|
144
|
+
"@introspection-sdk/introspection-proxy": "0.14.0",
|
|
145
|
+
"@introspection-sdk/types": "0.14.0"
|
|
146
146
|
},
|
|
147
147
|
"scripts": {
|
|
148
148
|
"lint": "eslint . --max-warnings 0",
|
package/src/client.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
type ExperimentsApi,
|
|
29
29
|
} from "./resources/experiments.js";
|
|
30
30
|
import { attachRecipes, type RecipesApi } from "./resources/recipes.js";
|
|
31
|
+
import { DEV_TARGET_HEADER, resolveDevTarget } from "./dev-target.js";
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Introspection REST client.
|
|
@@ -77,7 +78,6 @@ export class IntrospectionClient {
|
|
|
77
78
|
constructor(options: IntrospectionClientOptions = {}) {
|
|
78
79
|
const token = options.token || process.env.INTROSPECTION_TOKEN || "";
|
|
79
80
|
const advanced = options.advanced || {};
|
|
80
|
-
this.advancedOptions = advanced;
|
|
81
81
|
const baseApiUrl =
|
|
82
82
|
advanced.baseApiUrl ||
|
|
83
83
|
process.env.INTROSPECTION_BASE_API_URL ||
|
|
@@ -89,13 +89,24 @@ export class IntrospectionClient {
|
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// INTROSPECTION_DEV_TARGET rides every request as a header so it reaches
|
|
93
|
+
// the paths a runner cannot: a bare `POST /v1/tasks` with a dev API key
|
|
94
|
+
// mints its JWT from the key row and has no per-request claim to carry.
|
|
95
|
+
// Merged first, so an explicit `additionalHeaders` entry still wins, and
|
|
96
|
+
// stored on advancedOptions so the Runner's own DP client inherits it.
|
|
97
|
+
const devTarget = resolveDevTarget();
|
|
98
|
+
const additionalHeaders = devTarget
|
|
99
|
+
? { [DEV_TARGET_HEADER]: devTarget, ...advanced.additionalHeaders }
|
|
100
|
+
: advanced.additionalHeaders;
|
|
101
|
+
this.advancedOptions = { ...advanced, additionalHeaders };
|
|
102
|
+
|
|
92
103
|
// CP HTTP client — talks to the customer-facing API with the customer
|
|
93
104
|
// API key. Runners get their own HttpClient instances pointed at the
|
|
94
105
|
// `deployment.endpoint` returned by `/v1/runtimes/{id}/run`.
|
|
95
106
|
this.cpHttp = new HttpClient({
|
|
96
107
|
apiUrl: baseApiUrl,
|
|
97
108
|
token,
|
|
98
|
-
additionalHeaders:
|
|
109
|
+
additionalHeaders: this.advancedOptions.additionalHeaders,
|
|
99
110
|
fetch: advanced.fetch,
|
|
100
111
|
});
|
|
101
112
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development-target resolution — which `introspection dev` server this
|
|
3
|
+
* process's tasks should reach.
|
|
4
|
+
*
|
|
5
|
+
* Two developers can run `introspection dev` against one shared Runtime. A
|
|
6
|
+
* task created by a shared application credential carries no developer, so the
|
|
7
|
+
* platform cannot tell their machines apart; the caller names one instead.
|
|
8
|
+
* `introspection dev` prints the value to set:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* serving as: roland
|
|
12
|
+
* for your app: INTROSPECTION_DEV_TARGET=roland
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Carried as a header rather than on the runner's `caller` payload: `caller`
|
|
16
|
+
* is descriptive metadata the platform never acts on, and a target is a
|
|
17
|
+
* per-request selector the platform does act on. Keeping them apart is what
|
|
18
|
+
* lets `caller` stay a free-form bag, and it is the only transport that
|
|
19
|
+
* reaches a bare `POST /v1/tasks` with a dev API key, whose JWT is minted from
|
|
20
|
+
* the key row with no per-request input path.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately env-only, with no `os.userInfo()` fallback. Defaulting to the
|
|
23
|
+
* local username would be zero-config on a laptop and wrong everywhere else: a
|
|
24
|
+
* process running in a shared development deployment under an account like
|
|
25
|
+
* `node` would silently name a machine nobody is serving and fail closed,
|
|
26
|
+
* where today it reaches the one connected dev server. The CLI defaults to the
|
|
27
|
+
* username because it is naming *itself* and always runs on the developer's
|
|
28
|
+
* machine; this names *someone else's* machine and can run anywhere.
|
|
29
|
+
*
|
|
30
|
+
* Inert outside development: the Data Plane consults a target only on the
|
|
31
|
+
* development pin path, so a stray value in staging or production is ignored.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/** Header carrying the target on requests that have no runner to ride. */
|
|
35
|
+
export const DEV_TARGET_HEADER = "x-introspection-dev-target";
|
|
36
|
+
|
|
37
|
+
/** The env var `introspection dev` prints and both the CLI and SDK read. */
|
|
38
|
+
export const DEV_TARGET_ENV = "INTROSPECTION_DEV_TARGET";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Percent-encode to RFC 3986, so the three SDKs put identical bytes on the
|
|
42
|
+
* wire for the same target.
|
|
43
|
+
*
|
|
44
|
+
* `encodeURIComponent` leaves `!'()*` alone where Python's `quote(safe="")`
|
|
45
|
+
* and the Rust client encode them. The Data Plane decodes before it
|
|
46
|
+
* normalizes, so either form routes — but a header that differs by which
|
|
47
|
+
* client sent it is a debugging trap for no benefit.
|
|
48
|
+
*/
|
|
49
|
+
function encodeTarget(value: string): string {
|
|
50
|
+
return encodeURIComponent(value).replace(
|
|
51
|
+
/[!'()*]/g,
|
|
52
|
+
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The development target for this process, or `undefined` when unset.
|
|
58
|
+
*
|
|
59
|
+
* Percent-encoded, because the value becomes an HTTP header and a header is
|
|
60
|
+
* bytes: a login name like `andré` is not transmissible as-is, and a runtime
|
|
61
|
+
* that lets it through sends latin-1 bytes the server would read back as a
|
|
62
|
+
* different string. Encoding here is lossless and costs nothing for the
|
|
63
|
+
* ordinary ASCII name, which encodes to itself.
|
|
64
|
+
*
|
|
65
|
+
* Safe to send encoded because the Data Plane decodes before it normalizes,
|
|
66
|
+
* so `andré` and `andr%C3%A9` land on the same target as the `--as andré`
|
|
67
|
+
* the CLI advertises over protobuf, where no encoding is needed.
|
|
68
|
+
*
|
|
69
|
+
* Read through `globalThis.process` so the module stays importable from
|
|
70
|
+
* non-Node runtimes that share this package's build.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveDevTarget(): string | undefined {
|
|
73
|
+
const env = (
|
|
74
|
+
globalThis as { process?: { env?: Record<string, string | undefined> } }
|
|
75
|
+
).process?.env;
|
|
76
|
+
const raw = env?.[DEV_TARGET_ENV];
|
|
77
|
+
const trimmed = raw?.trim();
|
|
78
|
+
return trimmed ? encodeTarget(trimmed) : undefined;
|
|
79
|
+
}
|