@ory/argus 0.1.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 +134 -0
- package/assets/commands/local-down.md +19 -0
- package/assets/commands/local-up.md +27 -0
- package/assets/skills/auth-setup/SKILL.md +279 -0
- package/assets/skills/local-dev/SKILL.md +206 -0
- package/assets/skills/login-flow/SKILL.md +383 -0
- package/assets/skills/social-login/SKILL.md +312 -0
- package/dist/agent-auth.d.ts +204 -0
- package/dist/agent-auth.js +553 -0
- package/dist/auth-gate.d.ts +71 -0
- package/dist/auth-gate.js +308 -0
- package/dist/auth-store.d.ts +75 -0
- package/dist/auth-store.js +261 -0
- package/dist/auth.d.ts +93 -0
- package/dist/auth.js +323 -0
- package/dist/cli.d.ts +73 -0
- package/dist/cli.js +484 -0
- package/dist/client.d.ts +158 -0
- package/dist/client.js +679 -0
- package/dist/config.d.ts +135 -0
- package/dist/config.js +344 -0
- package/dist/denial.d.ts +79 -0
- package/dist/denial.js +103 -0
- package/dist/dev.d.ts +95 -0
- package/dist/dev.js +514 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +137 -0
- package/dist/local/cli.d.ts +12 -0
- package/dist/local/cli.js +95 -0
- package/dist/local/configs.d.ts +89 -0
- package/dist/local/configs.js +634 -0
- package/dist/local/health.d.ts +32 -0
- package/dist/local/health.js +65 -0
- package/dist/local/index.d.ts +6 -0
- package/dist/local/index.js +38 -0
- package/dist/local/jaeger-main.d.ts +13 -0
- package/dist/local/jaeger-main.js +85 -0
- package/dist/local/jaeger.d.ts +50 -0
- package/dist/local/jaeger.js +162 -0
- package/dist/local/main.d.ts +7 -0
- package/dist/local/main.js +14 -0
- package/dist/local/manager.d.ts +45 -0
- package/dist/local/manager.js +676 -0
- package/dist/local/seed.d.ts +71 -0
- package/dist/local/seed.js +237 -0
- package/dist/logger.d.ts +29 -0
- package/dist/logger.js +139 -0
- package/dist/mcp.d.ts +76 -0
- package/dist/mcp.js +122 -0
- package/dist/otel/exporter.d.ts +17 -0
- package/dist/otel/exporter.js +12 -0
- package/dist/otel/index.d.ts +2 -0
- package/dist/otel/index.js +8 -0
- package/dist/otel/otlp-http.d.ts +116 -0
- package/dist/otel/otlp-http.js +322 -0
- package/dist/registry/cli.d.ts +12 -0
- package/dist/registry/cli.js +76 -0
- package/dist/registry/config.d.ts +23 -0
- package/dist/registry/config.js +80 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.js +21 -0
- package/dist/registry/main.d.ts +7 -0
- package/dist/registry/main.js +14 -0
- package/dist/registry/manager.d.ts +38 -0
- package/dist/registry/manager.js +674 -0
- package/dist/setup.d.ts +118 -0
- package/dist/setup.js +398 -0
- package/dist/skills.d.ts +78 -0
- package/dist/skills.js +264 -0
- package/dist/subject.d.ts +43 -0
- package/dist/subject.js +55 -0
- package/dist/tool-metadata.d.ts +41 -0
- package/dist/tool-metadata.js +127 -0
- package/dist/tracer.d.ts +172 -0
- package/dist/tracer.js +452 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +3 -0
- package/dist/watch-sandbox.d.ts +9 -0
- package/dist/watch-sandbox.js +81 -0
- package/package.json +79 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Span exporter contract.
|
|
4
|
+
*
|
|
5
|
+
* Implementations ship completed TraceSpan records to an external trace
|
|
6
|
+
* sink (OTLP collector, vendor backend, in-process pipeline, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Exporters must never throw. Transport failures, malformed responses,
|
|
9
|
+
* and shutdown races are all swallowed and logged through whatever
|
|
10
|
+
* channel the implementation chooses.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseKeyValueList = exports.buildExportRequest = exports.otlpExporterFromEnv = exports.OtlpHttpExporter = void 0;
|
|
4
|
+
var otlp_http_js_1 = require("./otlp-http.js");
|
|
5
|
+
Object.defineProperty(exports, "OtlpHttpExporter", { enumerable: true, get: function () { return otlp_http_js_1.OtlpHttpExporter; } });
|
|
6
|
+
Object.defineProperty(exports, "otlpExporterFromEnv", { enumerable: true, get: function () { return otlp_http_js_1.otlpExporterFromEnv; } });
|
|
7
|
+
Object.defineProperty(exports, "buildExportRequest", { enumerable: true, get: function () { return otlp_http_js_1.buildExportRequest; } });
|
|
8
|
+
Object.defineProperty(exports, "parseKeyValueList", { enumerable: true, get: function () { return otlp_http_js_1.parseKeyValueList; } });
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTLP/HTTP JSON exporter.
|
|
3
|
+
*
|
|
4
|
+
* Serializes TraceSpan records into the OTLP ExportTraceServiceRequest
|
|
5
|
+
* shape and POSTs them to an OTLP HTTP endpoint as JSON. Works with
|
|
6
|
+
* Jaeger's OTLP receiver, Grafana Tempo, OpenTelemetry Collector,
|
|
7
|
+
* Honeycomb, and any other vendor that accepts OTLP/HTTP.
|
|
8
|
+
*
|
|
9
|
+
* No protobuf dependency — relies on the global `fetch`. The exporter
|
|
10
|
+
* is intentionally side-effect-free: failures are swallowed (callers
|
|
11
|
+
* receive a resolved Promise) so trace export can never break the
|
|
12
|
+
* agent session.
|
|
13
|
+
*
|
|
14
|
+
* Standard env vars consumed by `otlpExporterFromEnv()`:
|
|
15
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT base URL (we append /v1/traces)
|
|
16
|
+
* - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT full traces URL (overrides base)
|
|
17
|
+
* - OTEL_EXPORTER_OTLP_HEADERS `k=v,k=v` pairs
|
|
18
|
+
* - OTEL_EXPORTER_OTLP_TRACES_HEADERS headers specific to traces
|
|
19
|
+
* - OTEL_SERVICE_NAME service.name resource attribute
|
|
20
|
+
* - OTEL_RESOURCE_ATTRIBUTES additional resource attrs
|
|
21
|
+
*/
|
|
22
|
+
import type { SpanExporter } from "./exporter.js";
|
|
23
|
+
import type { TraceSpan } from "../tracer.js";
|
|
24
|
+
export interface OtlpHttpExporterOptions {
|
|
25
|
+
/** Full traces endpoint (e.g. `http://localhost:4318/v1/traces`). */
|
|
26
|
+
endpoint: string;
|
|
27
|
+
/** Additional HTTP headers to send with each request. */
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
/** Resource attributes (service.name, host.name, …) merged into every export. */
|
|
30
|
+
resource?: Record<string, AttributeValue>;
|
|
31
|
+
/** Per-request timeout in milliseconds. Default: 5000. */
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
/** Optional sink for transport errors. Defaults to a no-op. */
|
|
34
|
+
onError?: (err: unknown) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Override the fetch function (used by tests). Defaults to global fetch.
|
|
37
|
+
*/
|
|
38
|
+
fetch?: typeof fetch;
|
|
39
|
+
}
|
|
40
|
+
export declare class OtlpHttpExporter implements SpanExporter {
|
|
41
|
+
private readonly endpoint;
|
|
42
|
+
private readonly headers;
|
|
43
|
+
private readonly resource;
|
|
44
|
+
private readonly timeoutMs;
|
|
45
|
+
private readonly onError;
|
|
46
|
+
private readonly fetchImpl;
|
|
47
|
+
private readonly inFlight;
|
|
48
|
+
constructor(opts: OtlpHttpExporterOptions);
|
|
49
|
+
export(spans: ReadonlyArray<TraceSpan>): Promise<void>;
|
|
50
|
+
private send;
|
|
51
|
+
shutdown(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build an OtlpHttpExporter from process env. Returns undefined when no
|
|
55
|
+
* endpoint is configured.
|
|
56
|
+
*/
|
|
57
|
+
export declare function otlpExporterFromEnv(opts: {
|
|
58
|
+
harness: string;
|
|
59
|
+
hostname?: string;
|
|
60
|
+
user?: string;
|
|
61
|
+
pluginVersion?: string;
|
|
62
|
+
cwd?: string;
|
|
63
|
+
gitBranch?: string;
|
|
64
|
+
gitCommit?: string;
|
|
65
|
+
onError?: (err: unknown) => void;
|
|
66
|
+
env?: NodeJS.ProcessEnv;
|
|
67
|
+
}): OtlpHttpExporter | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Parse the OTel `k=v,k2=v2` env-var format. Values may be URL-encoded.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseKeyValueList(raw: string | undefined): Record<string, string>;
|
|
72
|
+
type AttributeValue = string | number | boolean | null | undefined;
|
|
73
|
+
interface OtlpKeyValue {
|
|
74
|
+
key: string;
|
|
75
|
+
value: OtlpAnyValue;
|
|
76
|
+
}
|
|
77
|
+
interface OtlpAnyValue {
|
|
78
|
+
stringValue?: string;
|
|
79
|
+
intValue?: string;
|
|
80
|
+
doubleValue?: number;
|
|
81
|
+
boolValue?: boolean;
|
|
82
|
+
arrayValue?: {
|
|
83
|
+
values: OtlpAnyValue[];
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
interface OtlpStatus {
|
|
87
|
+
code: 0 | 1 | 2;
|
|
88
|
+
message?: string;
|
|
89
|
+
}
|
|
90
|
+
interface OtlpSpan {
|
|
91
|
+
traceId: string;
|
|
92
|
+
spanId: string;
|
|
93
|
+
parentSpanId?: string;
|
|
94
|
+
name: string;
|
|
95
|
+
kind: number;
|
|
96
|
+
startTimeUnixNano: string;
|
|
97
|
+
endTimeUnixNano: string;
|
|
98
|
+
attributes?: OtlpKeyValue[];
|
|
99
|
+
status?: OtlpStatus;
|
|
100
|
+
}
|
|
101
|
+
interface OtlpResourceSpans {
|
|
102
|
+
resource: {
|
|
103
|
+
attributes: OtlpKeyValue[];
|
|
104
|
+
};
|
|
105
|
+
scopeSpans: Array<{
|
|
106
|
+
scope: {
|
|
107
|
+
name: string;
|
|
108
|
+
};
|
|
109
|
+
spans: OtlpSpan[];
|
|
110
|
+
}>;
|
|
111
|
+
}
|
|
112
|
+
interface OtlpExportRequest {
|
|
113
|
+
resourceSpans: OtlpResourceSpans[];
|
|
114
|
+
}
|
|
115
|
+
export declare function buildExportRequest(spans: ReadonlyArray<TraceSpan>, resource: Record<string, AttributeValue>): OtlpExportRequest;
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OTLP/HTTP JSON exporter.
|
|
4
|
+
*
|
|
5
|
+
* Serializes TraceSpan records into the OTLP ExportTraceServiceRequest
|
|
6
|
+
* shape and POSTs them to an OTLP HTTP endpoint as JSON. Works with
|
|
7
|
+
* Jaeger's OTLP receiver, Grafana Tempo, OpenTelemetry Collector,
|
|
8
|
+
* Honeycomb, and any other vendor that accepts OTLP/HTTP.
|
|
9
|
+
*
|
|
10
|
+
* No protobuf dependency — relies on the global `fetch`. The exporter
|
|
11
|
+
* is intentionally side-effect-free: failures are swallowed (callers
|
|
12
|
+
* receive a resolved Promise) so trace export can never break the
|
|
13
|
+
* agent session.
|
|
14
|
+
*
|
|
15
|
+
* Standard env vars consumed by `otlpExporterFromEnv()`:
|
|
16
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT base URL (we append /v1/traces)
|
|
17
|
+
* - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT full traces URL (overrides base)
|
|
18
|
+
* - OTEL_EXPORTER_OTLP_HEADERS `k=v,k=v` pairs
|
|
19
|
+
* - OTEL_EXPORTER_OTLP_TRACES_HEADERS headers specific to traces
|
|
20
|
+
* - OTEL_SERVICE_NAME service.name resource attribute
|
|
21
|
+
* - OTEL_RESOURCE_ATTRIBUTES additional resource attrs
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.OtlpHttpExporter = void 0;
|
|
25
|
+
exports.otlpExporterFromEnv = otlpExporterFromEnv;
|
|
26
|
+
exports.parseKeyValueList = parseKeyValueList;
|
|
27
|
+
exports.buildExportRequest = buildExportRequest;
|
|
28
|
+
const TRACES_PATH = "/v1/traces";
|
|
29
|
+
const SCOPE_NAME = "ory-agent-plugins";
|
|
30
|
+
class OtlpHttpExporter {
|
|
31
|
+
endpoint;
|
|
32
|
+
headers;
|
|
33
|
+
resource;
|
|
34
|
+
timeoutMs;
|
|
35
|
+
onError;
|
|
36
|
+
fetchImpl;
|
|
37
|
+
inFlight = new Set();
|
|
38
|
+
constructor(opts) {
|
|
39
|
+
this.endpoint = opts.endpoint;
|
|
40
|
+
this.headers = { "content-type": "application/json", ...opts.headers };
|
|
41
|
+
this.resource = opts.resource ?? {};
|
|
42
|
+
this.timeoutMs = opts.timeoutMs ?? 5_000;
|
|
43
|
+
this.onError = opts.onError ?? (() => undefined);
|
|
44
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
45
|
+
}
|
|
46
|
+
export(spans) {
|
|
47
|
+
if (spans.length === 0)
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
if (typeof this.fetchImpl !== "function") {
|
|
50
|
+
this.onError(new Error("global fetch is not available"));
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
}
|
|
53
|
+
const promise = this.send(spans);
|
|
54
|
+
this.inFlight.add(promise);
|
|
55
|
+
promise.finally(() => this.inFlight.delete(promise));
|
|
56
|
+
return promise;
|
|
57
|
+
}
|
|
58
|
+
async send(spans) {
|
|
59
|
+
const payload = buildExportRequest(spans, this.resource);
|
|
60
|
+
const controller = new AbortController();
|
|
61
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
62
|
+
try {
|
|
63
|
+
const response = await this.fetchImpl(this.endpoint, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: this.headers,
|
|
66
|
+
body: JSON.stringify(payload),
|
|
67
|
+
signal: controller.signal,
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
// Drain body so the connection can be reused but ignore the value.
|
|
71
|
+
try {
|
|
72
|
+
await response.text();
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* ignore */
|
|
76
|
+
}
|
|
77
|
+
this.onError(new Error(`OTLP export failed with status ${response.status}`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
this.onError(err);
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
clearTimeout(timer);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async shutdown() {
|
|
88
|
+
// Drain in-flight exports. Subprocess hooks (claude-code, codex,
|
|
89
|
+
// gemini-cli) call process.exit() the instant they hand back stdout —
|
|
90
|
+
// without this drain the OTLP fetch is killed mid-flight and spans
|
|
91
|
+
// never reach the collector even though the NDJSON file already
|
|
92
|
+
// contains them.
|
|
93
|
+
if (this.inFlight.size === 0)
|
|
94
|
+
return;
|
|
95
|
+
await Promise.allSettled([...this.inFlight]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.OtlpHttpExporter = OtlpHttpExporter;
|
|
99
|
+
/**
|
|
100
|
+
* Build an OtlpHttpExporter from process env. Returns undefined when no
|
|
101
|
+
* endpoint is configured.
|
|
102
|
+
*/
|
|
103
|
+
function otlpExporterFromEnv(opts) {
|
|
104
|
+
const env = opts.env ?? process.env;
|
|
105
|
+
const endpoint = resolveEndpoint(env);
|
|
106
|
+
if (!endpoint)
|
|
107
|
+
return undefined;
|
|
108
|
+
const protocol = env.OTEL_EXPORTER_OTLP_PROTOCOL ?? env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
|
|
109
|
+
if (protocol && protocol !== "http/json") {
|
|
110
|
+
opts.onError?.(new Error(`OTEL_EXPORTER_OTLP_PROTOCOL=${protocol} not supported (only http/json). Skipping OTel export.`));
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
const headers = mergeHeaders(parseKeyValueList(env.OTEL_EXPORTER_OTLP_HEADERS), parseKeyValueList(env.OTEL_EXPORTER_OTLP_TRACES_HEADERS));
|
|
114
|
+
const resource = {
|
|
115
|
+
"service.name": env.OTEL_SERVICE_NAME ?? `ory-agent-plugin-${opts.harness}`,
|
|
116
|
+
"service.namespace": "ory.agent_plugins",
|
|
117
|
+
"ory.harness": opts.harness,
|
|
118
|
+
"process.pid": process.pid,
|
|
119
|
+
"process.runtime.name": "nodejs",
|
|
120
|
+
"process.runtime.version": process.version,
|
|
121
|
+
};
|
|
122
|
+
if (opts.hostname)
|
|
123
|
+
resource["host.name"] = opts.hostname;
|
|
124
|
+
if (opts.user)
|
|
125
|
+
resource["host.user"] = opts.user;
|
|
126
|
+
if (opts.pluginVersion) {
|
|
127
|
+
resource["service.version"] = opts.pluginVersion;
|
|
128
|
+
}
|
|
129
|
+
if (opts.cwd)
|
|
130
|
+
resource["process.cwd"] = opts.cwd;
|
|
131
|
+
if (opts.gitBranch)
|
|
132
|
+
resource["ory.git.branch"] = opts.gitBranch;
|
|
133
|
+
if (opts.gitCommit)
|
|
134
|
+
resource["ory.git.commit"] = opts.gitCommit;
|
|
135
|
+
for (const [k, v] of Object.entries(parseKeyValueList(env.OTEL_RESOURCE_ATTRIBUTES))) {
|
|
136
|
+
resource[k] = v;
|
|
137
|
+
}
|
|
138
|
+
return new OtlpHttpExporter({
|
|
139
|
+
endpoint,
|
|
140
|
+
headers,
|
|
141
|
+
resource,
|
|
142
|
+
onError: opts.onError,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// ─── Endpoint / header parsing ─────────────────────────────────────
|
|
146
|
+
function resolveEndpoint(env) {
|
|
147
|
+
const tracesUrl = env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT?.trim();
|
|
148
|
+
if (tracesUrl) {
|
|
149
|
+
// User specified the full traces URL — use as-is.
|
|
150
|
+
return tracesUrl;
|
|
151
|
+
}
|
|
152
|
+
// ORY_OTLP_ENDPOINT is an ORY-prefixed alias used by the dev launcher.
|
|
153
|
+
// Some harnesses (e.g. Claude Code) filter the env they pass to hook
|
|
154
|
+
// subprocesses and drop OTEL_*-prefixed vars, but allow ORY_*-prefixed
|
|
155
|
+
// ones through. The alias lets the launcher hand the OTLP endpoint to
|
|
156
|
+
// the hook process without depending on OTEL_* propagation.
|
|
157
|
+
const base = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim() || env.ORY_OTLP_ENDPOINT?.trim();
|
|
158
|
+
if (!base)
|
|
159
|
+
return undefined;
|
|
160
|
+
return base.replace(/\/+$/, "") + TRACES_PATH;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Parse the OTel `k=v,k2=v2` env-var format. Values may be URL-encoded.
|
|
164
|
+
*/
|
|
165
|
+
function parseKeyValueList(raw) {
|
|
166
|
+
const out = {};
|
|
167
|
+
if (!raw)
|
|
168
|
+
return out;
|
|
169
|
+
for (const pair of raw.split(",")) {
|
|
170
|
+
const trimmed = pair.trim();
|
|
171
|
+
if (!trimmed)
|
|
172
|
+
continue;
|
|
173
|
+
const eq = trimmed.indexOf("=");
|
|
174
|
+
if (eq <= 0)
|
|
175
|
+
continue;
|
|
176
|
+
const key = trimmed.slice(0, eq).trim();
|
|
177
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
178
|
+
if (!key)
|
|
179
|
+
continue;
|
|
180
|
+
out[key] = safeDecodeURIComponent(value);
|
|
181
|
+
}
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
function safeDecodeURIComponent(value) {
|
|
185
|
+
try {
|
|
186
|
+
return decodeURIComponent(value);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function mergeHeaders(...sources) {
|
|
193
|
+
const out = {};
|
|
194
|
+
for (const src of sources) {
|
|
195
|
+
for (const [k, v] of Object.entries(src)) {
|
|
196
|
+
out[k.toLowerCase()] = v;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return out;
|
|
200
|
+
}
|
|
201
|
+
function buildExportRequest(spans, resource) {
|
|
202
|
+
const otlpSpans = spans.map(toOtlpSpan);
|
|
203
|
+
return {
|
|
204
|
+
resourceSpans: [
|
|
205
|
+
{
|
|
206
|
+
resource: { attributes: toAttributes(resource) },
|
|
207
|
+
scopeSpans: [
|
|
208
|
+
{
|
|
209
|
+
scope: { name: SCOPE_NAME },
|
|
210
|
+
spans: otlpSpans,
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function toOtlpSpan(span) {
|
|
218
|
+
// OTLP/HTTP JSON expects 32-hex traceId and 16-hex spanId per the
|
|
219
|
+
// proto3-JSON canonical mapping with hex string encoding (the OTel
|
|
220
|
+
// spec also allows base64; modern collectors and Honeycomb accept
|
|
221
|
+
// hex). Pad short ids with leading zeros.
|
|
222
|
+
const status = toOtlpStatus(span.status);
|
|
223
|
+
const baseAttributes = {
|
|
224
|
+
"ory.event": span.event,
|
|
225
|
+
"ory.span.status": span.status,
|
|
226
|
+
"ory.duration_ms": span.durationMs,
|
|
227
|
+
};
|
|
228
|
+
if (span.sessionId)
|
|
229
|
+
baseAttributes["ory.session_id"] = span.sessionId;
|
|
230
|
+
const flat = flattenAttributes(span.attributes ?? {});
|
|
231
|
+
const attrs = { ...baseAttributes, ...flat };
|
|
232
|
+
return {
|
|
233
|
+
traceId: padHex(span.traceId, 32),
|
|
234
|
+
spanId: padHex(span.spanId, 16),
|
|
235
|
+
...(span.parentSpanId
|
|
236
|
+
? { parentSpanId: padHex(span.parentSpanId, 16) }
|
|
237
|
+
: {}),
|
|
238
|
+
name: span.event,
|
|
239
|
+
kind: 1, // SPAN_KIND_INTERNAL
|
|
240
|
+
startTimeUnixNano: isoToUnixNano(span.startedAt),
|
|
241
|
+
endTimeUnixNano: isoToUnixNano(span.endedAt),
|
|
242
|
+
attributes: toAttributes(attrs),
|
|
243
|
+
...(status ? { status } : {}),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function toOtlpStatus(status) {
|
|
247
|
+
switch (status) {
|
|
248
|
+
case "ok":
|
|
249
|
+
return { code: 1 };
|
|
250
|
+
case "error":
|
|
251
|
+
return { code: 2, message: "error" };
|
|
252
|
+
case "denied":
|
|
253
|
+
return { code: 2, message: "denied" };
|
|
254
|
+
case "skipped":
|
|
255
|
+
return undefined; // STATUS_CODE_UNSET
|
|
256
|
+
default:
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function isoToUnixNano(iso) {
|
|
261
|
+
const ms = Date.parse(iso);
|
|
262
|
+
if (!Number.isFinite(ms))
|
|
263
|
+
return "0";
|
|
264
|
+
// BigInt avoids 2^53 rounding for ns timestamps.
|
|
265
|
+
return (BigInt(ms) * 1000000n).toString();
|
|
266
|
+
}
|
|
267
|
+
function padHex(hex, length) {
|
|
268
|
+
const lower = hex.toLowerCase().replace(/[^0-9a-f]/g, "");
|
|
269
|
+
if (lower.length >= length)
|
|
270
|
+
return lower.slice(-length);
|
|
271
|
+
return lower.padStart(length, "0");
|
|
272
|
+
}
|
|
273
|
+
function toAttributes(source) {
|
|
274
|
+
const out = [];
|
|
275
|
+
for (const [key, value] of Object.entries(source)) {
|
|
276
|
+
const v = toAnyValue(value);
|
|
277
|
+
if (v)
|
|
278
|
+
out.push({ key, value: v });
|
|
279
|
+
}
|
|
280
|
+
return out;
|
|
281
|
+
}
|
|
282
|
+
function toAnyValue(value) {
|
|
283
|
+
if (value === null || value === undefined)
|
|
284
|
+
return undefined;
|
|
285
|
+
if (typeof value === "string")
|
|
286
|
+
return { stringValue: value };
|
|
287
|
+
if (typeof value === "boolean")
|
|
288
|
+
return { boolValue: value };
|
|
289
|
+
if (typeof value === "number") {
|
|
290
|
+
if (Number.isInteger(value)) {
|
|
291
|
+
return { intValue: value.toString() };
|
|
292
|
+
}
|
|
293
|
+
return { doubleValue: value };
|
|
294
|
+
}
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Flatten nested attribute objects into a single-level Record where
|
|
299
|
+
* complex values are JSON-stringified. Keeps OTLP attributes compact
|
|
300
|
+
* and queryable as scalars in vendor backends.
|
|
301
|
+
*/
|
|
302
|
+
function flattenAttributes(attrs) {
|
|
303
|
+
const out = {};
|
|
304
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
305
|
+
if (value === null || value === undefined)
|
|
306
|
+
continue;
|
|
307
|
+
if (typeof value === "string" ||
|
|
308
|
+
typeof value === "number" ||
|
|
309
|
+
typeof value === "boolean") {
|
|
310
|
+
out[key] = value;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
try {
|
|
314
|
+
out[key] = JSON.stringify(value);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
/* skip un-serializable values */
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI interface for the `registry` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* Manages the local npm registry lifecycle.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Run a `registry` subcommand.
|
|
8
|
+
*
|
|
9
|
+
* @param binName - The CLI name for help text
|
|
10
|
+
* @param args - Arguments after "registry"
|
|
11
|
+
*/
|
|
12
|
+
export declare function runRegistryCommand(binName: string, args: string[]): Promise<void>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI interface for the `registry` subcommand.
|
|
4
|
+
*
|
|
5
|
+
* Manages the local npm registry lifecycle.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.runRegistryCommand = runRegistryCommand;
|
|
9
|
+
const manager_js_1 = require("./manager.js");
|
|
10
|
+
/**
|
|
11
|
+
* Run a `registry` subcommand.
|
|
12
|
+
*
|
|
13
|
+
* @param binName - The CLI name for help text
|
|
14
|
+
* @param args - Arguments after "registry"
|
|
15
|
+
*/
|
|
16
|
+
async function runRegistryCommand(binName, args) {
|
|
17
|
+
const [subcommand] = args;
|
|
18
|
+
switch (subcommand) {
|
|
19
|
+
case "start":
|
|
20
|
+
await (0, manager_js_1.registryStart)();
|
|
21
|
+
break;
|
|
22
|
+
case "stop":
|
|
23
|
+
await (0, manager_js_1.registryStop)();
|
|
24
|
+
break;
|
|
25
|
+
case "status":
|
|
26
|
+
await (0, manager_js_1.registryStatus)();
|
|
27
|
+
break;
|
|
28
|
+
case "publish":
|
|
29
|
+
await (0, manager_js_1.registryPublish)();
|
|
30
|
+
break;
|
|
31
|
+
case "clean":
|
|
32
|
+
await (0, manager_js_1.registryClean)();
|
|
33
|
+
break;
|
|
34
|
+
case "npmrc":
|
|
35
|
+
(0, manager_js_1.registryNpmrc)();
|
|
36
|
+
break;
|
|
37
|
+
case "help":
|
|
38
|
+
case "--help":
|
|
39
|
+
case "-h":
|
|
40
|
+
case undefined:
|
|
41
|
+
printRegistryHelp(binName);
|
|
42
|
+
break;
|
|
43
|
+
default:
|
|
44
|
+
console.error(`Unknown registry subcommand: ${subcommand}`);
|
|
45
|
+
printRegistryHelp(binName);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function printRegistryHelp(binName) {
|
|
50
|
+
console.log(`
|
|
51
|
+
${binName} registry — Local npm registry for development
|
|
52
|
+
|
|
53
|
+
Usage:
|
|
54
|
+
${binName} registry <command>
|
|
55
|
+
|
|
56
|
+
Commands:
|
|
57
|
+
start Start the local Verdaccio npm registry (Docker container)
|
|
58
|
+
stop Stop the running registry
|
|
59
|
+
status Show registry status and published packages
|
|
60
|
+
publish Build and publish all workspace packages to the local registry
|
|
61
|
+
clean Stop the registry and remove all data
|
|
62
|
+
npmrc Print registry URL for use in .npmrc or --registry flag
|
|
63
|
+
|
|
64
|
+
The local registry runs Verdaccio in a Docker container (ory-registry)
|
|
65
|
+
on http://localhost:4873. Storage and config live under .ory-dev/registry/
|
|
66
|
+
on the host, bind-mounted into the container. Everything is ephemeral —
|
|
67
|
+
'clean' removes both the container and the on-disk data.
|
|
68
|
+
|
|
69
|
+
Workflow:
|
|
70
|
+
${binName} registry start # Start the registry
|
|
71
|
+
${binName} registry publish # Build and publish all packages
|
|
72
|
+
npm install --registry http://localhost:4873 @ory/claude-code
|
|
73
|
+
${binName} registry stop # Stop when done
|
|
74
|
+
${binName} registry clean # Remove all data
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verdaccio configuration generator.
|
|
3
|
+
*
|
|
4
|
+
* Generates a config file used by the local Verdaccio Docker container.
|
|
5
|
+
* Paths inside the YAML refer to container-internal locations: the
|
|
6
|
+
* registry manager bind-mounts the host's `.ory-dev/registry/storage`
|
|
7
|
+
* directory at `/verdaccio/storage` and the rendered config at
|
|
8
|
+
* `/verdaccio/conf/config.yaml`. Logs go to stdout so `docker logs`
|
|
9
|
+
* surfaces them without needing a writable log volume.
|
|
10
|
+
*/
|
|
11
|
+
export declare const REGISTRY_PORT = 4873;
|
|
12
|
+
export declare const REGISTRY_URL = "http://localhost:4873";
|
|
13
|
+
export declare const REGISTRY_DIR_NAME = ".ory-dev/registry";
|
|
14
|
+
/** Docker image used to run Verdaccio. Pinned to v6 to match prior CLI usage. */
|
|
15
|
+
export declare const REGISTRY_IMAGE = "verdaccio/verdaccio:6";
|
|
16
|
+
/** Container name for the local registry. Distinct from any user-managed Verdaccio. */
|
|
17
|
+
export declare const REGISTRY_CONTAINER = "ory-registry";
|
|
18
|
+
/** Container-internal path where the manager mounts the host storage directory. */
|
|
19
|
+
export declare const REGISTRY_CONTAINER_STORAGE = "/verdaccio/storage";
|
|
20
|
+
/** Container-internal path where the manager mounts the rendered config file. */
|
|
21
|
+
export declare const REGISTRY_CONTAINER_CONFIG = "/verdaccio/conf/config.yaml";
|
|
22
|
+
export declare function verdaccioConfigYaml(): string;
|
|
23
|
+
export declare function npmrcContent(): string;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Verdaccio configuration generator.
|
|
4
|
+
*
|
|
5
|
+
* Generates a config file used by the local Verdaccio Docker container.
|
|
6
|
+
* Paths inside the YAML refer to container-internal locations: the
|
|
7
|
+
* registry manager bind-mounts the host's `.ory-dev/registry/storage`
|
|
8
|
+
* directory at `/verdaccio/storage` and the rendered config at
|
|
9
|
+
* `/verdaccio/conf/config.yaml`. Logs go to stdout so `docker logs`
|
|
10
|
+
* surfaces them without needing a writable log volume.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.REGISTRY_CONTAINER_CONFIG = exports.REGISTRY_CONTAINER_STORAGE = exports.REGISTRY_CONTAINER = exports.REGISTRY_IMAGE = exports.REGISTRY_DIR_NAME = exports.REGISTRY_URL = exports.REGISTRY_PORT = void 0;
|
|
14
|
+
exports.verdaccioConfigYaml = verdaccioConfigYaml;
|
|
15
|
+
exports.npmrcContent = npmrcContent;
|
|
16
|
+
exports.REGISTRY_PORT = 4873;
|
|
17
|
+
exports.REGISTRY_URL = `http://localhost:${exports.REGISTRY_PORT}`;
|
|
18
|
+
exports.REGISTRY_DIR_NAME = ".ory-dev/registry";
|
|
19
|
+
/** Docker image used to run Verdaccio. Pinned to v6 to match prior CLI usage. */
|
|
20
|
+
exports.REGISTRY_IMAGE = "verdaccio/verdaccio:6";
|
|
21
|
+
/** Container name for the local registry. Distinct from any user-managed Verdaccio. */
|
|
22
|
+
exports.REGISTRY_CONTAINER = "ory-registry";
|
|
23
|
+
/** Container-internal path where the manager mounts the host storage directory. */
|
|
24
|
+
exports.REGISTRY_CONTAINER_STORAGE = "/verdaccio/storage";
|
|
25
|
+
/** Container-internal path where the manager mounts the rendered config file. */
|
|
26
|
+
exports.REGISTRY_CONTAINER_CONFIG = "/verdaccio/conf/config.yaml";
|
|
27
|
+
function verdaccioConfigYaml() {
|
|
28
|
+
return `# Auto-generated Verdaccio config for local development.
|
|
29
|
+
# Do not edit — regenerated on each 'registry start'.
|
|
30
|
+
|
|
31
|
+
storage: ${exports.REGISTRY_CONTAINER_STORAGE}
|
|
32
|
+
|
|
33
|
+
auth:
|
|
34
|
+
htpasswd:
|
|
35
|
+
file: ${exports.REGISTRY_CONTAINER_STORAGE}/htpasswd
|
|
36
|
+
# max_users intentionally omitted. Setting any finite value here (even
|
|
37
|
+
# generous ones like 100) causes Verdaccio 6 to short-circuit our dev
|
|
38
|
+
# user's first PUT with 409 "username already registered" before the
|
|
39
|
+
# htpasswd plugin can create it. Defaults to +Inf, which works.
|
|
40
|
+
|
|
41
|
+
uplinks:
|
|
42
|
+
npmjs:
|
|
43
|
+
url: https://registry.npmjs.org/
|
|
44
|
+
cache: false
|
|
45
|
+
|
|
46
|
+
packages:
|
|
47
|
+
"@ory/*":
|
|
48
|
+
access: $all
|
|
49
|
+
publish: $all
|
|
50
|
+
unpublish: $all
|
|
51
|
+
# Locally-published workspace packages (e.g. @ory/argus) are served from
|
|
52
|
+
# storage; everything else under @ory/* (notably @ory/client, a transitive
|
|
53
|
+
# dep) falls through to npmjs. Without this, transitive @ory/client
|
|
54
|
+
# resolution fails with E404 against the local registry.
|
|
55
|
+
proxy: npmjs
|
|
56
|
+
|
|
57
|
+
"**":
|
|
58
|
+
access: $all
|
|
59
|
+
publish: $all
|
|
60
|
+
proxy: npmjs
|
|
61
|
+
|
|
62
|
+
server:
|
|
63
|
+
keepAliveTimeout: 60
|
|
64
|
+
|
|
65
|
+
middlewares:
|
|
66
|
+
audit:
|
|
67
|
+
enabled: true
|
|
68
|
+
|
|
69
|
+
# Stream logs to stdout so 'docker logs ${exports.REGISTRY_CONTAINER}' surfaces them.
|
|
70
|
+
log:
|
|
71
|
+
type: stdout
|
|
72
|
+
format: pretty
|
|
73
|
+
level: warn
|
|
74
|
+
`;
|
|
75
|
+
}
|
|
76
|
+
function npmrcContent() {
|
|
77
|
+
return `registry=${exports.REGISTRY_URL}/
|
|
78
|
+
//localhost:${exports.REGISTRY_PORT}/:_authToken=local-dev-token
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { runRegistryCommand } from "./cli.js";
|
|
2
|
+
export { registryStart, registryStop, registryStatus, registryPublish, registryClean, registryNpmrc, ensureRegistryRunning, publishHarnessToLocal, getLocalRegistryNpmCacheDir, } from "./manager.js";
|
|
3
|
+
export { REGISTRY_PORT, REGISTRY_URL, REGISTRY_DIR_NAME, REGISTRY_IMAGE, REGISTRY_CONTAINER, } from "./config.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REGISTRY_CONTAINER = exports.REGISTRY_IMAGE = exports.REGISTRY_DIR_NAME = exports.REGISTRY_URL = exports.REGISTRY_PORT = exports.getLocalRegistryNpmCacheDir = exports.publishHarnessToLocal = exports.ensureRegistryRunning = exports.registryNpmrc = exports.registryClean = exports.registryPublish = exports.registryStatus = exports.registryStop = exports.registryStart = exports.runRegistryCommand = void 0;
|
|
4
|
+
var cli_js_1 = require("./cli.js");
|
|
5
|
+
Object.defineProperty(exports, "runRegistryCommand", { enumerable: true, get: function () { return cli_js_1.runRegistryCommand; } });
|
|
6
|
+
var manager_js_1 = require("./manager.js");
|
|
7
|
+
Object.defineProperty(exports, "registryStart", { enumerable: true, get: function () { return manager_js_1.registryStart; } });
|
|
8
|
+
Object.defineProperty(exports, "registryStop", { enumerable: true, get: function () { return manager_js_1.registryStop; } });
|
|
9
|
+
Object.defineProperty(exports, "registryStatus", { enumerable: true, get: function () { return manager_js_1.registryStatus; } });
|
|
10
|
+
Object.defineProperty(exports, "registryPublish", { enumerable: true, get: function () { return manager_js_1.registryPublish; } });
|
|
11
|
+
Object.defineProperty(exports, "registryClean", { enumerable: true, get: function () { return manager_js_1.registryClean; } });
|
|
12
|
+
Object.defineProperty(exports, "registryNpmrc", { enumerable: true, get: function () { return manager_js_1.registryNpmrc; } });
|
|
13
|
+
Object.defineProperty(exports, "ensureRegistryRunning", { enumerable: true, get: function () { return manager_js_1.ensureRegistryRunning; } });
|
|
14
|
+
Object.defineProperty(exports, "publishHarnessToLocal", { enumerable: true, get: function () { return manager_js_1.publishHarnessToLocal; } });
|
|
15
|
+
Object.defineProperty(exports, "getLocalRegistryNpmCacheDir", { enumerable: true, get: function () { return manager_js_1.getLocalRegistryNpmCacheDir; } });
|
|
16
|
+
var config_js_1 = require("./config.js");
|
|
17
|
+
Object.defineProperty(exports, "REGISTRY_PORT", { enumerable: true, get: function () { return config_js_1.REGISTRY_PORT; } });
|
|
18
|
+
Object.defineProperty(exports, "REGISTRY_URL", { enumerable: true, get: function () { return config_js_1.REGISTRY_URL; } });
|
|
19
|
+
Object.defineProperty(exports, "REGISTRY_DIR_NAME", { enumerable: true, get: function () { return config_js_1.REGISTRY_DIR_NAME; } });
|
|
20
|
+
Object.defineProperty(exports, "REGISTRY_IMAGE", { enumerable: true, get: function () { return config_js_1.REGISTRY_IMAGE; } });
|
|
21
|
+
Object.defineProperty(exports, "REGISTRY_CONTAINER", { enumerable: true, get: function () { return config_js_1.REGISTRY_CONTAINER; } });
|