@mutagent/cli 0.2.186 → 0.2.188
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/dist/bin/cli.js +223 -177
- package/package.json +3 -3
package/dist/bin/cli.js
CHANGED
|
@@ -37810,11 +37810,117 @@ import chalk64 from "chalk";
|
|
|
37810
37810
|
|
|
37811
37811
|
// src/lib/integration-sources-input.ts
|
|
37812
37812
|
init_errors();
|
|
37813
|
-
|
|
37813
|
+
|
|
37814
|
+
// src/lib/integration-sources-guidance.ts
|
|
37815
|
+
init_errors();
|
|
37816
|
+
var SOURCES = "mutagent integrations sources";
|
|
37817
|
+
var READ_ONLY_CODE = "INTEGRATION_SOURCE_READ_ONLY";
|
|
37818
|
+
function testFailureWords(id, check, status) {
|
|
37819
|
+
const http = status === undefined ? "" : ` (HTTP ${String(status)})`;
|
|
37820
|
+
switch (check) {
|
|
37821
|
+
case "credentials_refused":
|
|
37822
|
+
return {
|
|
37823
|
+
message: `The source refused the stored credentials${http}: check credentials_refused failed.`,
|
|
37824
|
+
fix: `Get new keys from the source platform, then run: ${SOURCES} rotate ${id} … --secret-stdin`
|
|
37825
|
+
};
|
|
37826
|
+
case "unreachable":
|
|
37827
|
+
return {
|
|
37828
|
+
message: "The server could not reach the source host: check unreachable failed.",
|
|
37829
|
+
fix: `Check the host is up and public (${SOURCES} list shows it); if it moved, remove the source and add it again.`
|
|
37830
|
+
};
|
|
37831
|
+
case "http_error":
|
|
37832
|
+
return {
|
|
37833
|
+
message: `The source answered with an error${http}: check http_error failed.`,
|
|
37834
|
+
fix: "Check the source platform is healthy and the host is its API base URL, then test again."
|
|
37835
|
+
};
|
|
37836
|
+
case "invalid_response":
|
|
37837
|
+
return {
|
|
37838
|
+
message: "The host did not answer like the source platform: check invalid_response failed.",
|
|
37839
|
+
fix: "Check --host is the platform API base URL (not a dashboard page), then remove and add the source again."
|
|
37840
|
+
};
|
|
37841
|
+
case "host_refused":
|
|
37842
|
+
return {
|
|
37843
|
+
message: "The source host resolves to an address the server may not call: check host_refused failed.",
|
|
37844
|
+
fix: "Use the public URL of the trace platform: remove the source and add it with a public --host."
|
|
37845
|
+
};
|
|
37846
|
+
default:
|
|
37847
|
+
return {
|
|
37848
|
+
message: `The connection test failed${http}${check === undefined ? "" : `: check ${check} failed`}.`,
|
|
37849
|
+
fix: `Run: ${SOURCES} test ${id} again; if it keeps failing, report it: mutagent feedback send --category bug -m "source test ${check ?? "failed"}"`
|
|
37850
|
+
};
|
|
37851
|
+
}
|
|
37852
|
+
}
|
|
37853
|
+
|
|
37854
|
+
class SourceTestFailedError extends MutagentError {
|
|
37855
|
+
sourceId;
|
|
37856
|
+
check;
|
|
37857
|
+
httpStatus;
|
|
37858
|
+
testedAt;
|
|
37859
|
+
constructor(sourceId, check, httpStatus, testedAt) {
|
|
37860
|
+
const words = testFailureWords(sourceId, check, httpStatus);
|
|
37861
|
+
super("INTEGRATION_SOURCE_TEST_FAILED", words.message, words.fix);
|
|
37862
|
+
this.sourceId = sourceId;
|
|
37863
|
+
this.check = check;
|
|
37864
|
+
this.httpStatus = httpStatus;
|
|
37865
|
+
this.testedAt = testedAt;
|
|
37866
|
+
}
|
|
37867
|
+
toJSON() {
|
|
37868
|
+
return {
|
|
37869
|
+
...super.toJSON(),
|
|
37870
|
+
sourceId: this.sourceId,
|
|
37871
|
+
check: this.check ?? null,
|
|
37872
|
+
...this.httpStatus === undefined ? {} : { status: this.httpStatus },
|
|
37873
|
+
testedAt: this.testedAt
|
|
37874
|
+
};
|
|
37875
|
+
}
|
|
37876
|
+
}
|
|
37877
|
+
function defaultFix(code, ctx) {
|
|
37878
|
+
const id = ctx.id ?? "<id>";
|
|
37879
|
+
const pullId = ctx.pullId ?? "<pullId>";
|
|
37880
|
+
switch (code) {
|
|
37881
|
+
case "INTEGRATION_SOURCE_NOT_FOUND":
|
|
37882
|
+
return `Run: ${SOURCES} list`;
|
|
37883
|
+
case "INTEGRATION_PULL_NOT_FOUND":
|
|
37884
|
+
return `Run: ${SOURCES} pulls ${id}`;
|
|
37885
|
+
case "INTEGRATION_PULL_NOT_READY":
|
|
37886
|
+
return `Wait for the pull to succeed: ${SOURCES} pull-get ${id} ${pullId}`;
|
|
37887
|
+
case "INTEGRATION_PULL_RUNNING":
|
|
37888
|
+
return `Wait for it to finish (${SOURCES} pulls ${id}), then start another.`;
|
|
37889
|
+
case "INTEGRATION_SOURCE_NAME_TAKEN":
|
|
37890
|
+
return `Pick another name with --name (${SOURCES} list shows the names in use).`;
|
|
37891
|
+
case "INTEGRATION_SOURCE_CREDENTIALS_INVALID":
|
|
37892
|
+
return `Pass the credentials the source's kind takes: ${SOURCES} rotate --help`;
|
|
37893
|
+
case "INTEGRATION_SOURCE_CREDENTIALS_UNREADABLE":
|
|
37894
|
+
return `Rotate the credentials, then test again: ${SOURCES} rotate ${id} … --secret-stdin`;
|
|
37895
|
+
case "INTEGRATION_SOURCE_NOT_TESTABLE":
|
|
37896
|
+
case READ_ONLY_CODE:
|
|
37897
|
+
return "OTLP traces arrive by push; there is nothing to test, rotate, pull or delete.";
|
|
37898
|
+
case "INTEGRATION_SOURCE_HOST_INVALID":
|
|
37899
|
+
case "INTEGRATION_SOURCE_HOST_REFUSED":
|
|
37900
|
+
return "Pass --host the public base URL of the platform, e.g. https://cloud.langfuse.com.";
|
|
37901
|
+
case "INTEGRATION_PULL_WINDOW_INVALID":
|
|
37902
|
+
return "Pass --since and --until as ISO-8601 times, --since first.";
|
|
37903
|
+
case "INTEGRATION_SOURCE_ENCRYPTION_UNAVAILABLE":
|
|
37904
|
+
case "INTEGRATION_PULL_STORE_UNAVAILABLE":
|
|
37905
|
+
return "The server is not configured for this: the platform operator must fix it; nothing on this machine can. " + 'Tell the user, or report it: mutagent feedback send --category bug -m "<what failed>"';
|
|
37906
|
+
default:
|
|
37907
|
+
return `Run: ${SOURCES} --help`;
|
|
37908
|
+
}
|
|
37909
|
+
}
|
|
37910
|
+
var OPERATOR_CODES = new Set(["INTEGRATION_SOURCE_ENCRYPTION_UNAVAILABLE", "INTEGRATION_PULL_STORE_UNAVAILABLE"]);
|
|
37911
|
+
function fixFor(code, serverFix, ctx) {
|
|
37912
|
+
if (OPERATOR_CODES.has(code))
|
|
37913
|
+
return defaultFix(code, ctx);
|
|
37914
|
+
return serverFix ?? defaultFix(code, ctx);
|
|
37915
|
+
}
|
|
37916
|
+
|
|
37917
|
+
// src/lib/integration-sources-input.ts
|
|
37918
|
+
var CREATABLE_KINDS = ["langfuse", "openobserve", "dash0"];
|
|
37814
37919
|
var OPENOBSERVE_SIGNALS = ["events", "spans"];
|
|
37920
|
+
var DASH0_DATASET = /^[a-zA-Z0-9_-]{3,26}$/;
|
|
37815
37921
|
var MAX_PULL_LIMIT = 5000;
|
|
37816
37922
|
var MAX_TAGS = 20;
|
|
37817
|
-
var
|
|
37923
|
+
var SOURCES2 = "mutagent integrations sources";
|
|
37818
37924
|
function invalid5(message, fix) {
|
|
37819
37925
|
const error = new ValidationError(message);
|
|
37820
37926
|
error.suggestion = fix;
|
|
@@ -37827,7 +37933,7 @@ function checkLength(flag, value, max) {
|
|
|
37827
37933
|
throw invalid5(`${flag} is longer than ${String(max)} characters.`, `Shorten ${flag}.`);
|
|
37828
37934
|
return value;
|
|
37829
37935
|
}
|
|
37830
|
-
var ADD_HELP = `Run: ${
|
|
37936
|
+
var ADD_HELP = `Run: ${SOURCES2} add --help`;
|
|
37831
37937
|
function indirectSecret(flags, inputs) {
|
|
37832
37938
|
if (flags.secretEnv !== undefined && flags.secretStdin === true) {
|
|
37833
37939
|
throw invalid5("--secret-env and --secret-stdin were both given.", "Pass the secret one way only.");
|
|
@@ -37857,31 +37963,41 @@ function oneSecret(flagName, flagValue, flags, inputs) {
|
|
|
37857
37963
|
function credentialsFor(kind, flags, inputs, verb) {
|
|
37858
37964
|
if (kind === "langfuse") {
|
|
37859
37965
|
if (flags.email !== undefined || flags.password !== undefined || flags.token !== undefined) {
|
|
37860
|
-
throw invalid5("A langfuse source takes --public-key and a secret key, not --email, --password or --token.", `Run: ${
|
|
37966
|
+
throw invalid5("A langfuse source takes --public-key and a secret key, not --email, --password or --token.", `Run: ${SOURCES2} ${verb} --public-key <pk-lf-…> --secret-stdin`);
|
|
37861
37967
|
}
|
|
37862
37968
|
const secretKey = oneSecret("--secret-key", flags.secretKey, flags, inputs);
|
|
37863
37969
|
if (flags.publicKey === undefined || secretKey === undefined) {
|
|
37864
|
-
throw invalid5("A langfuse source needs --public-key and a secret key (--secret-key, --secret-env or --secret-stdin).", `Run: ${
|
|
37970
|
+
throw invalid5("A langfuse source needs --public-key and a secret key (--secret-key, --secret-env or --secret-stdin).", `Run: ${SOURCES2} ${verb} --public-key <pk-lf-…> --secret-stdin`);
|
|
37865
37971
|
}
|
|
37866
37972
|
return { publicKey: checkLength("--public-key", flags.publicKey, 512), secretKey: checkLength("the secret key", secretKey, 512) };
|
|
37867
37973
|
}
|
|
37974
|
+
if (kind === "dash0") {
|
|
37975
|
+
if (flags.publicKey !== undefined || flags.secretKey !== undefined || flags.email !== undefined || flags.password !== undefined) {
|
|
37976
|
+
throw invalid5("A dash0 source takes an auth token (--token), not --public-key, --secret-key, --email or --password.", `Run: ${SOURCES2} ${verb} --secret-env DASH0_AUTH_TOKEN (or --token, or --secret-stdin)`);
|
|
37977
|
+
}
|
|
37978
|
+
const authToken = oneSecret("--token", flags.token, flags, inputs);
|
|
37979
|
+
if (authToken === undefined) {
|
|
37980
|
+
throw invalid5("A dash0 source needs an auth token (--token, --secret-env or --secret-stdin).", `Run: ${SOURCES2} ${verb} --secret-env DASH0_AUTH_TOKEN (or --token, or --secret-stdin)`);
|
|
37981
|
+
}
|
|
37982
|
+
return { authToken: checkLength("the auth token", authToken, 512) };
|
|
37983
|
+
}
|
|
37868
37984
|
if (flags.publicKey !== undefined || flags.secretKey !== undefined) {
|
|
37869
|
-
throw invalid5("An openobserve source takes --email with a password, or a --token; not --public-key or --secret-key.", `Run: ${
|
|
37985
|
+
throw invalid5("An openobserve source takes --email with a password, or a --token; not --public-key or --secret-key.", `Run: ${SOURCES2} ${verb} --token <token> (or --email <email> --secret-stdin)`);
|
|
37870
37986
|
}
|
|
37871
37987
|
if (flags.email !== undefined) {
|
|
37872
37988
|
if (flags.token !== undefined)
|
|
37873
37989
|
throw invalid5("--email and --token were both given.", "Pass --email with a password, or --token alone.");
|
|
37874
37990
|
const password = oneSecret("--password", flags.password, flags, inputs);
|
|
37875
37991
|
if (password === undefined) {
|
|
37876
|
-
throw invalid5("--email needs a password (--password, --secret-env or --secret-stdin).", `Run: ${
|
|
37992
|
+
throw invalid5("--email needs a password (--password, --secret-env or --secret-stdin).", `Run: ${SOURCES2} ${verb} --email <email> --secret-stdin`);
|
|
37877
37993
|
}
|
|
37878
37994
|
return { email: checkLength("--email", flags.email, 512), password: checkLength("the password", password, 512) };
|
|
37879
37995
|
}
|
|
37880
37996
|
if (flags.password !== undefined)
|
|
37881
|
-
throw invalid5("--password needs --email.", `Run: ${
|
|
37997
|
+
throw invalid5("--password needs --email.", `Run: ${SOURCES2} ${verb} --email <email> --secret-stdin`);
|
|
37882
37998
|
const token = oneSecret("--token", flags.token, flags, inputs);
|
|
37883
37999
|
if (token === undefined) {
|
|
37884
|
-
throw invalid5("An openobserve source needs a --token, or --email with a password.", `Run: ${
|
|
38000
|
+
throw invalid5("An openobserve source needs a --token, or --email with a password.", `Run: ${SOURCES2} ${verb} --token <token> (or --email <email> --secret-stdin)`);
|
|
37885
38001
|
}
|
|
37886
38002
|
return { token: checkLength("the token", token, 512) };
|
|
37887
38003
|
}
|
|
@@ -37889,7 +38005,7 @@ function creatableKind(kind) {
|
|
|
37889
38005
|
if (CREATABLE_KINDS.includes(kind))
|
|
37890
38006
|
return kind;
|
|
37891
38007
|
if (kind === "otlp") {
|
|
37892
|
-
throw invalid5("OTLP traces arrive by push through OTLP ingest; there is no OTLP source to add.", `Send traces to the OTLP endpoint; ${
|
|
38008
|
+
throw invalid5("OTLP traces arrive by push through OTLP ingest; there is no OTLP source to add.", `Send traces to the OTLP endpoint; ${SOURCES2} list shows them once they arrive.`);
|
|
37893
38009
|
}
|
|
37894
38010
|
throw invalid5(`Unknown source kind "${kind}". Kinds: ${CREATABLE_KINDS.join(", ")}.`, ADD_HELP);
|
|
37895
38011
|
}
|
|
@@ -37914,12 +38030,12 @@ function refuseKeyOptionsInSandbox(flags, verb) {
|
|
|
37914
38030
|
const given = KEY_OPTIONS2.filter(([field]) => flags[field] !== undefined && flags[field] !== false).map(([, flag]) => flag);
|
|
37915
38031
|
if (given.length === 0)
|
|
37916
38032
|
return;
|
|
37917
|
-
const fix = verb === "add" ? `Run the same ${
|
|
38033
|
+
const fix = verb === "add" ? `Run the same ${SOURCES2} add without ${given.join(", ")}: the answer is a one-time page where the user stores the key.` : "The user changes a stored key in Configuration → Integrations; it is never passed through a cloud session.";
|
|
37918
38034
|
throw new MutagentError("SANDBOX_SCOPE", `Keys aren't passed through a cloud session, and ${given.join(", ")} ${given.length === 1 ? "carries" : "carry"} one. The user stores keys on a one-time page or in Configuration.`, fix);
|
|
37919
38035
|
}
|
|
37920
38036
|
var AT_SIGNS = /@|%40|@/i;
|
|
37921
38037
|
function sandboxHost(raw) {
|
|
37922
|
-
const refuse = () => new MutagentError("SANDBOX_SCOPE", "--host isn't a plain base URL (http or https, no user:password, query or fragment), and a cloud session never passes anything that could carry a key. The user stores keys on a one-time page or in Configuration.", `Run the same ${
|
|
38038
|
+
const refuse = () => new MutagentError("SANDBOX_SCOPE", "--host isn't a plain base URL (http or https, no user:password, query or fragment), and a cloud session never passes anything that could carry a key. The user stores keys on a one-time page or in Configuration.", `Run the same ${SOURCES2} add with --host as the base URL only, e.g. https://cloud.langfuse.com: the answer is a one-time page where the user stores the key.`);
|
|
37923
38039
|
if (AT_SIGNS.test(raw))
|
|
37924
38040
|
throw refuse();
|
|
37925
38041
|
let url;
|
|
@@ -37937,9 +38053,14 @@ function sandboxHost(raw) {
|
|
|
37937
38053
|
function buildSourceBody(kindArg, flags, credentialsOf) {
|
|
37938
38054
|
const kind = creatableKind(kindArg);
|
|
37939
38055
|
if (flags.name === undefined)
|
|
37940
|
-
throw invalid5("--name is required.", `Run: ${
|
|
38056
|
+
throw invalid5("--name is required.", `Run: ${SOURCES2} add ${kind} --name <name> …`);
|
|
37941
38057
|
const name = checkLength("--name", flags.name, 100);
|
|
37942
38058
|
const host = flags.host === undefined ? undefined : checkLength("--host", flags.host, 2048);
|
|
38059
|
+
if (kind !== "dash0" && flags.dataset !== undefined) {
|
|
38060
|
+
throw invalid5(`--dataset is a dash0 setting; a ${kind} source has none.`, ADD_HELP);
|
|
38061
|
+
}
|
|
38062
|
+
if (kind === "dash0")
|
|
38063
|
+
return dash0Body(name, host, flags, () => credentialsOf(kind));
|
|
37943
38064
|
if (kind === "langfuse") {
|
|
37944
38065
|
if (flags.openobserveOrg !== undefined || flags.stream !== undefined || flags.signal !== undefined) {
|
|
37945
38066
|
throw invalid5("--openobserve-org, --stream and --signal are openobserve settings; a langfuse source has none.", ADD_HELP);
|
|
@@ -37948,7 +38069,7 @@ function buildSourceBody(kindArg, flags, credentialsOf) {
|
|
|
37948
38069
|
return { kind, name, ...host === undefined ? {} : { host }, ...credentials === undefined ? {} : { credentials } };
|
|
37949
38070
|
}
|
|
37950
38071
|
if (host === undefined)
|
|
37951
|
-
throw invalid5("An openobserve source needs --host (e.g. https://api.openobserve.ai).", `Run: ${
|
|
38072
|
+
throw invalid5("An openobserve source needs --host (e.g. https://api.openobserve.ai).", `Run: ${SOURCES2} add openobserve --host <url> …`);
|
|
37952
38073
|
const org = flags.openobserveOrg === undefined ? undefined : checkLength("--openobserve-org", flags.openobserveOrg, 128);
|
|
37953
38074
|
const stream = flags.stream === undefined ? undefined : checkLength("--stream", flags.stream, 256);
|
|
37954
38075
|
if (flags.signal !== undefined && !OPENOBSERVE_SIGNALS.includes(flags.signal)) {
|
|
@@ -37965,6 +38086,25 @@ function buildSourceBody(kindArg, flags, credentialsOf) {
|
|
|
37965
38086
|
...credentials === undefined ? {} : { credentials }
|
|
37966
38087
|
};
|
|
37967
38088
|
}
|
|
38089
|
+
function dash0Body(name, host, flags, credentialsOf) {
|
|
38090
|
+
if (flags.openobserveOrg !== undefined || flags.stream !== undefined || flags.signal !== undefined) {
|
|
38091
|
+
throw invalid5("--openobserve-org, --stream and --signal are openobserve settings; a dash0 source has --dataset.", ADD_HELP);
|
|
38092
|
+
}
|
|
38093
|
+
if (host === undefined) {
|
|
38094
|
+
throw invalid5("A dash0 source needs --host, the regional API URL (e.g. https://api.eu-west-1.aws.dash0.com).", `Run: ${SOURCES2} add dash0 --host <api url> …`);
|
|
38095
|
+
}
|
|
38096
|
+
if (flags.dataset !== undefined && !DASH0_DATASET.test(flags.dataset)) {
|
|
38097
|
+
throw invalid5('--dataset must be 3-26 letters, digits, "-" or "_".', "Pass the dataset name from Dash0 Settings → Datasets, or omit --dataset for the default.");
|
|
38098
|
+
}
|
|
38099
|
+
const credentials = credentialsOf();
|
|
38100
|
+
return {
|
|
38101
|
+
kind: "dash0",
|
|
38102
|
+
name,
|
|
38103
|
+
host,
|
|
38104
|
+
...flags.dataset === undefined ? {} : { dataset: flags.dataset },
|
|
38105
|
+
...credentials === undefined ? {} : { credentials }
|
|
38106
|
+
};
|
|
38107
|
+
}
|
|
37968
38108
|
function instant(flag, value) {
|
|
37969
38109
|
const ms = /^\d{4}-\d{2}-\d{2}/.test(value) ? Date.parse(value) : Number.NaN;
|
|
37970
38110
|
if (Number.isNaN(ms))
|
|
@@ -38001,7 +38141,7 @@ function buildPullBody(flags) {
|
|
|
38001
38141
|
function requireRemoveConsent(id, opts) {
|
|
38002
38142
|
if (opts.force === true || opts.yes === true)
|
|
38003
38143
|
return;
|
|
38004
|
-
throw new MutagentError("CONFIRMATION_REQUIRED", `Removing trace source ${id} needs --force: its stored credentials, pulls and pulled traces are deleted.`, `Confirm with the user, then re-run: ${
|
|
38144
|
+
throw new MutagentError("CONFIRMATION_REQUIRED", `Removing trace source ${id} needs --force: its stored credentials, pulls and pulled traces are deleted.`, `Confirm with the user, then re-run: ${SOURCES2} remove ${id} --force`);
|
|
38005
38145
|
}
|
|
38006
38146
|
function isVirtualRow(raw) {
|
|
38007
38147
|
if (raw === undefined)
|
|
@@ -38010,108 +38150,9 @@ function isVirtualRow(raw) {
|
|
|
38010
38150
|
return raw.virtual;
|
|
38011
38151
|
return raw.kind === "otlp";
|
|
38012
38152
|
}
|
|
38013
|
-
var READ_ONLY_CODE = "INTEGRATION_SOURCE_READ_ONLY";
|
|
38014
38153
|
function readOnlyRefusal(id) {
|
|
38015
38154
|
return new MutagentError(READ_ONLY_CODE, `${id} is OTLP ingest, a read-only source: OTLP traces arrive by push.`, "This row is derived from OTLP ingest: it lists while traces arrive and has nothing to rotate, test, pull or delete. " + "Its traces are already on the platform.");
|
|
38016
38155
|
}
|
|
38017
|
-
function testFailureWords(id, check, status) {
|
|
38018
|
-
const http = status === undefined ? "" : ` (HTTP ${String(status)})`;
|
|
38019
|
-
switch (check) {
|
|
38020
|
-
case "credentials_refused":
|
|
38021
|
-
return {
|
|
38022
|
-
message: `The source refused the stored credentials${http}: check credentials_refused failed.`,
|
|
38023
|
-
fix: `Get new keys from the source platform, then run: ${SOURCES} rotate ${id} … --secret-stdin`
|
|
38024
|
-
};
|
|
38025
|
-
case "unreachable":
|
|
38026
|
-
return {
|
|
38027
|
-
message: "The server could not reach the source host: check unreachable failed.",
|
|
38028
|
-
fix: `Check the host is up and public (${SOURCES} list shows it); if it moved, remove the source and add it again.`
|
|
38029
|
-
};
|
|
38030
|
-
case "http_error":
|
|
38031
|
-
return {
|
|
38032
|
-
message: `The source answered with an error${http}: check http_error failed.`,
|
|
38033
|
-
fix: "Check the source platform is healthy and the host is its API base URL, then test again."
|
|
38034
|
-
};
|
|
38035
|
-
case "invalid_response":
|
|
38036
|
-
return {
|
|
38037
|
-
message: "The host did not answer like the source platform: check invalid_response failed.",
|
|
38038
|
-
fix: "Check --host is the platform API base URL (not a dashboard page), then remove and add the source again."
|
|
38039
|
-
};
|
|
38040
|
-
case "host_refused":
|
|
38041
|
-
return {
|
|
38042
|
-
message: "The source host resolves to an address the server may not call: check host_refused failed.",
|
|
38043
|
-
fix: "Use the public URL of the trace platform: remove the source and add it with a public --host."
|
|
38044
|
-
};
|
|
38045
|
-
default:
|
|
38046
|
-
return {
|
|
38047
|
-
message: `The connection test failed${http}${check === undefined ? "" : `: check ${check} failed`}.`,
|
|
38048
|
-
fix: `Run: ${SOURCES} test ${id} again; if it keeps failing, report it: mutagent feedback send --category bug -m "source test ${check ?? "failed"}"`
|
|
38049
|
-
};
|
|
38050
|
-
}
|
|
38051
|
-
}
|
|
38052
|
-
|
|
38053
|
-
class SourceTestFailedError extends MutagentError {
|
|
38054
|
-
sourceId;
|
|
38055
|
-
check;
|
|
38056
|
-
httpStatus;
|
|
38057
|
-
testedAt;
|
|
38058
|
-
constructor(sourceId, check, httpStatus, testedAt) {
|
|
38059
|
-
const words = testFailureWords(sourceId, check, httpStatus);
|
|
38060
|
-
super("INTEGRATION_SOURCE_TEST_FAILED", words.message, words.fix);
|
|
38061
|
-
this.sourceId = sourceId;
|
|
38062
|
-
this.check = check;
|
|
38063
|
-
this.httpStatus = httpStatus;
|
|
38064
|
-
this.testedAt = testedAt;
|
|
38065
|
-
}
|
|
38066
|
-
toJSON() {
|
|
38067
|
-
return {
|
|
38068
|
-
...super.toJSON(),
|
|
38069
|
-
sourceId: this.sourceId,
|
|
38070
|
-
check: this.check ?? null,
|
|
38071
|
-
...this.httpStatus === undefined ? {} : { status: this.httpStatus },
|
|
38072
|
-
testedAt: this.testedAt
|
|
38073
|
-
};
|
|
38074
|
-
}
|
|
38075
|
-
}
|
|
38076
|
-
function defaultFix(code, ctx) {
|
|
38077
|
-
const id = ctx.id ?? "<id>";
|
|
38078
|
-
const pullId = ctx.pullId ?? "<pullId>";
|
|
38079
|
-
switch (code) {
|
|
38080
|
-
case "INTEGRATION_SOURCE_NOT_FOUND":
|
|
38081
|
-
return `Run: ${SOURCES} list`;
|
|
38082
|
-
case "INTEGRATION_PULL_NOT_FOUND":
|
|
38083
|
-
return `Run: ${SOURCES} pulls ${id}`;
|
|
38084
|
-
case "INTEGRATION_PULL_NOT_READY":
|
|
38085
|
-
return `Wait for the pull to succeed: ${SOURCES} pull-get ${id} ${pullId}`;
|
|
38086
|
-
case "INTEGRATION_PULL_RUNNING":
|
|
38087
|
-
return `Wait for it to finish (${SOURCES} pulls ${id}), then start another.`;
|
|
38088
|
-
case "INTEGRATION_SOURCE_NAME_TAKEN":
|
|
38089
|
-
return `Pick another name with --name (${SOURCES} list shows the names in use).`;
|
|
38090
|
-
case "INTEGRATION_SOURCE_CREDENTIALS_INVALID":
|
|
38091
|
-
return `Pass the credentials the source's kind takes: ${SOURCES} rotate --help`;
|
|
38092
|
-
case "INTEGRATION_SOURCE_CREDENTIALS_UNREADABLE":
|
|
38093
|
-
return `Rotate the credentials, then test again: ${SOURCES} rotate ${id} … --secret-stdin`;
|
|
38094
|
-
case "INTEGRATION_SOURCE_NOT_TESTABLE":
|
|
38095
|
-
case READ_ONLY_CODE:
|
|
38096
|
-
return "OTLP traces arrive by push; there is nothing to test, rotate, pull or delete.";
|
|
38097
|
-
case "INTEGRATION_SOURCE_HOST_INVALID":
|
|
38098
|
-
case "INTEGRATION_SOURCE_HOST_REFUSED":
|
|
38099
|
-
return "Pass --host the public base URL of the platform, e.g. https://cloud.langfuse.com.";
|
|
38100
|
-
case "INTEGRATION_PULL_WINDOW_INVALID":
|
|
38101
|
-
return "Pass --since and --until as ISO-8601 times, --since first.";
|
|
38102
|
-
case "INTEGRATION_SOURCE_ENCRYPTION_UNAVAILABLE":
|
|
38103
|
-
case "INTEGRATION_PULL_STORE_UNAVAILABLE":
|
|
38104
|
-
return "The server is not configured for this: the platform operator must fix it; nothing on this machine can. " + 'Tell the user, or report it: mutagent feedback send --category bug -m "<what failed>"';
|
|
38105
|
-
default:
|
|
38106
|
-
return `Run: ${SOURCES} --help`;
|
|
38107
|
-
}
|
|
38108
|
-
}
|
|
38109
|
-
var OPERATOR_CODES = new Set(["INTEGRATION_SOURCE_ENCRYPTION_UNAVAILABLE", "INTEGRATION_PULL_STORE_UNAVAILABLE"]);
|
|
38110
|
-
function fixFor(code, serverFix, ctx) {
|
|
38111
|
-
if (OPERATOR_CODES.has(code))
|
|
38112
|
-
return defaultFix(code, ctx);
|
|
38113
|
-
return serverFix ?? defaultFix(code, ctx);
|
|
38114
|
-
}
|
|
38115
38156
|
|
|
38116
38157
|
// src/lib/integrations-api.ts
|
|
38117
38158
|
init_config();
|
|
@@ -38321,7 +38362,7 @@ init_output();
|
|
|
38321
38362
|
// src/commands/integrations/shared.ts
|
|
38322
38363
|
init_errors();
|
|
38323
38364
|
import { readFileSync as readFileSync24 } from "fs";
|
|
38324
|
-
var
|
|
38365
|
+
var SOURCES3 = "mutagent integrations sources";
|
|
38325
38366
|
function isJsonMode2(command) {
|
|
38326
38367
|
return Boolean(command.optsWithGlobals().json);
|
|
38327
38368
|
}
|
|
@@ -38363,7 +38404,7 @@ async function findWritableSource(conn, id) {
|
|
|
38363
38404
|
return found;
|
|
38364
38405
|
}
|
|
38365
38406
|
function sourceNotFound(id) {
|
|
38366
|
-
return new MutagentError("INTEGRATION_SOURCE_NOT_FOUND", `No trace source ${id} in this workspace.`, `Run: ${
|
|
38407
|
+
return new MutagentError("INTEGRATION_SOURCE_NOT_FOUND", `No trace source ${id} in this workspace.`, `Run: ${SOURCES3} list`);
|
|
38367
38408
|
}
|
|
38368
38409
|
function readStdin2() {
|
|
38369
38410
|
if (process.stdin.isTTY) {
|
|
@@ -38418,15 +38459,15 @@ function pullView(p) {
|
|
|
38418
38459
|
function pullNext(id, p) {
|
|
38419
38460
|
const status = p.status;
|
|
38420
38461
|
if (status === "running") {
|
|
38421
|
-
return { note: "Still running.", next: [`${
|
|
38462
|
+
return { note: "Still running.", next: [`${SOURCES3} pull-get ${id} ${p.id} --json`] };
|
|
38422
38463
|
}
|
|
38423
38464
|
if (status === "failed") {
|
|
38424
38465
|
return {
|
|
38425
38466
|
note: `Failed: ${p.errorCode ?? "no reason recorded"}. Test the source, then pull again.`,
|
|
38426
|
-
next: [`${
|
|
38467
|
+
next: [`${SOURCES3} test ${id} --json`, `${SOURCES3} pull ${id} --json`]
|
|
38427
38468
|
};
|
|
38428
38469
|
}
|
|
38429
|
-
const read = [`${
|
|
38470
|
+
const read = [`${SOURCES3} pull-manifest ${id} ${p.id} --json`, `${SOURCES3} pull-traces ${id} ${p.id} --out traces.jsonl`];
|
|
38430
38471
|
if (p.complete === false) {
|
|
38431
38472
|
const why = p.truncated ? `truncated (${p.truncationCause ?? "cause not recorded"})` : "short of the source total";
|
|
38432
38473
|
return { note: `Succeeded but incomplete: ${why}. Do not treat these traces as the whole window.`, next: read };
|
|
@@ -38436,9 +38477,9 @@ function pullNext(id, p) {
|
|
|
38436
38477
|
function registerPull(sources) {
|
|
38437
38478
|
sources.command("pull").description("Start a pull of a source's traces into UniTF on the server").argument("<id>", "The source id").option("--since <time>", "Window start, ISO-8601 (omit for open)").option("--until <time>", "Window end, ISO-8601 (omit for open)").option("--limit <n>", "At most this many traces, 1-5000 (server default 500)").option("--agent-name <name>", "Only traces of this agent").option("--session-id <id>", "Only traces of this session").option("--tag <tag>", "Only traces with this tag (repeatable, at most 20)", (v, acc = []) => [...acc, v]).addHelpText("after", `
|
|
38438
38479
|
Examples:
|
|
38439
|
-
${chalk64.dim("$")} ${
|
|
38440
|
-
${chalk64.dim("$")} ${
|
|
38441
|
-
${chalk64.dim("$")} ${
|
|
38480
|
+
${chalk64.dim("$")} ${SOURCES3} pull src_123
|
|
38481
|
+
${chalk64.dim("$")} ${SOURCES3} pull src_123 --since 2026-09-01T00:00:00Z --until 2026-09-02T00:00:00Z --limit 1000
|
|
38482
|
+
${chalk64.dim("$")} ${SOURCES3} pull src_123 --agent-name support-bot --tag prod --tag eu --json
|
|
38442
38483
|
|
|
38443
38484
|
Starts the pull and returns at once (status running). Poll it with pull-get; once it has
|
|
38444
38485
|
succeeded, read pull-manifest and pull-traces. One running pull per source. A throttled or
|
|
@@ -38454,7 +38495,7 @@ AI Agent Directive:
|
|
|
38454
38495
|
await findWritableSource(conn, id);
|
|
38455
38496
|
const started = await conn.call((i) => i.startIntegrationSourcePull({ id, body }), { id });
|
|
38456
38497
|
const links = pullLinks(id, started.id);
|
|
38457
|
-
const next = [`${
|
|
38498
|
+
const next = [`${SOURCES3} pull-get ${id} ${started.id} --json`];
|
|
38458
38499
|
if (isJson) {
|
|
38459
38500
|
const directive = sourceDirective({
|
|
38460
38501
|
template: "integration_pull_started",
|
|
@@ -38475,8 +38516,8 @@ AI Agent Directive:
|
|
|
38475
38516
|
function registerPulls(sources) {
|
|
38476
38517
|
sources.command("pulls").description("A source's pulls, newest first (at most 50; kept 90 days)").argument("<id>", "The source id").addHelpText("after", `
|
|
38477
38518
|
Examples:
|
|
38478
|
-
${chalk64.dim("$")} ${
|
|
38479
|
-
${chalk64.dim("$")} ${
|
|
38519
|
+
${chalk64.dim("$")} ${SOURCES3} pulls src_123
|
|
38520
|
+
${chalk64.dim("$")} ${SOURCES3} pulls src_123 --json
|
|
38480
38521
|
|
|
38481
38522
|
AI Agent Directive:
|
|
38482
38523
|
Reading is free. --json returns { pulls, count }.
|
|
@@ -38490,7 +38531,7 @@ AI Agent Directive:
|
|
|
38490
38531
|
return;
|
|
38491
38532
|
}
|
|
38492
38533
|
if (list.items.length === 0) {
|
|
38493
|
-
console.log(chalk64.gray(`No pulls. Start one: ${
|
|
38534
|
+
console.log(chalk64.gray(`No pulls. Start one: ${SOURCES3} pull ${id}`));
|
|
38494
38535
|
return;
|
|
38495
38536
|
}
|
|
38496
38537
|
new OutputFormatter("table").output(list.items.map((p) => ({
|
|
@@ -38506,8 +38547,8 @@ AI Agent Directive:
|
|
|
38506
38547
|
function registerPullGet(sources) {
|
|
38507
38548
|
sources.command("pull-get").description("One pull: its status, counts and coverage").argument("<id>", "The source id").argument("<pullId>", "The pull id (from pull or pulls)").addHelpText("after", `
|
|
38508
38549
|
Examples:
|
|
38509
|
-
${chalk64.dim("$")} ${
|
|
38510
|
-
${chalk64.dim("$")} ${
|
|
38550
|
+
${chalk64.dim("$")} ${SOURCES3} pull-get src_123 pull_456
|
|
38551
|
+
${chalk64.dim("$")} ${SOURCES3} pull-get src_123 pull_456 --json
|
|
38511
38552
|
|
|
38512
38553
|
AI Agent Directive:
|
|
38513
38554
|
Reading is free: poll it while status is running. --json returns { pull, note, next, _links }.
|
|
@@ -38535,8 +38576,8 @@ AI Agent Directive:
|
|
|
38535
38576
|
function registerPullManifest(sources) {
|
|
38536
38577
|
sources.command("pull-manifest").description("A pull's unitf@0.1 manifest: what the JSONL holds and how completely").argument("<id>", "The source id").argument("<pullId>", "The pull id").addHelpText("after", `
|
|
38537
38578
|
Examples:
|
|
38538
|
-
${chalk64.dim("$")} ${
|
|
38539
|
-
${chalk64.dim("$")} ${
|
|
38579
|
+
${chalk64.dim("$")} ${SOURCES3} pull-manifest src_123 pull_456
|
|
38580
|
+
${chalk64.dim("$")} ${SOURCES3} pull-manifest src_123 pull_456 --json
|
|
38540
38581
|
|
|
38541
38582
|
Available once the pull has succeeded (INTEGRATION_PULL_NOT_READY before).
|
|
38542
38583
|
|
|
@@ -38609,8 +38650,8 @@ var stdoutSink = {
|
|
|
38609
38650
|
function registerPullTraces(sources) {
|
|
38610
38651
|
sources.command("pull-traces").description("Stream a pull's UniTF JSONL to stdout, or to a file with --out").argument("<id>", "The source id").argument("<pullId>", "The pull id").option("-o, --out <file>", "Write the JSONL to this file instead of stdout").addHelpText("after", `
|
|
38611
38652
|
Examples:
|
|
38612
|
-
${chalk64.dim("$")} ${
|
|
38613
|
-
${chalk64.dim("$")} ${
|
|
38653
|
+
${chalk64.dim("$")} ${SOURCES3} pull-traces src_123 pull_456 > traces.jsonl
|
|
38654
|
+
${chalk64.dim("$")} ${SOURCES3} pull-traces src_123 pull_456 --out traces.jsonl --json
|
|
38614
38655
|
|
|
38615
38656
|
One UniTF 0.1 trace per line, streamed as it arrives. Available once the pull has succeeded.
|
|
38616
38657
|
--json: without --out, stdout is the JSONL unchanged (each line is already JSON; nothing
|
|
@@ -38672,7 +38713,7 @@ function shellQuote3(value) {
|
|
|
38672
38713
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
38673
38714
|
}
|
|
38674
38715
|
function rerunCommand(body) {
|
|
38675
|
-
const parts = [`${
|
|
38716
|
+
const parts = [`${SOURCES3} add ${shellQuote3(String(body.kind))}`, `--name ${shellQuote3(String(body.name))}`];
|
|
38676
38717
|
if (typeof body.host === "string")
|
|
38677
38718
|
parts.push(`--host ${shellQuote3(body.host)}`);
|
|
38678
38719
|
if (typeof body.org === "string")
|
|
@@ -38681,6 +38722,8 @@ function rerunCommand(body) {
|
|
|
38681
38722
|
parts.push(`--stream ${shellQuote3(body.stream)}`);
|
|
38682
38723
|
if (typeof body.signal === "string")
|
|
38683
38724
|
parts.push(`--signal ${shellQuote3(body.signal)}`);
|
|
38725
|
+
if (typeof body.dataset === "string")
|
|
38726
|
+
parts.push(`--dataset ${shellQuote3(body.dataset)}`);
|
|
38684
38727
|
return parts.join(" ");
|
|
38685
38728
|
}
|
|
38686
38729
|
function printSecretRequired(isJson, detail, rerun) {
|
|
@@ -38712,7 +38755,7 @@ function secretInputs(flags) {
|
|
|
38712
38755
|
return inputs;
|
|
38713
38756
|
}
|
|
38714
38757
|
function addCredentialOptions(cmd) {
|
|
38715
|
-
return cmd.option("--public-key <key>", "langfuse: the public key (pk-lf-…)").option("--secret-key <key>", "langfuse: the secret key (sk-lf-…); prefer --secret-stdin or --secret-env").option("--email <email>", "openobserve: the user email, with a password").option("--password <password>", "openobserve: the password for --email; prefer --secret-stdin or --secret-env").option("--token <token>", 'openobserve: an issued token ("Basic …", "Bearer …" or base64), instead of --email').option("--secret-env <VAR>", "Read the kind's secret (secret key, password or token) from this environment variable").option("--secret-stdin", "Read the kind's secret from stdin (a trailing newline is dropped)");
|
|
38758
|
+
return cmd.option("--public-key <key>", "langfuse: the public key (pk-lf-…)").option("--secret-key <key>", "langfuse: the secret key (sk-lf-…); prefer --secret-stdin or --secret-env").option("--email <email>", "openobserve: the user email, with a password").option("--password <password>", "openobserve: the password for --email; prefer --secret-stdin or --secret-env").option("--token <token>", 'openobserve: an issued token ("Basic …", "Bearer …" or base64), instead of --email; dash0: the auth token (auth_…)').option("--secret-env <VAR>", "Read the kind's secret (secret key, password or token) from this environment variable").option("--secret-stdin", "Read the kind's secret from stdin (a trailing newline is dropped)");
|
|
38716
38759
|
}
|
|
38717
38760
|
function row4(s) {
|
|
38718
38761
|
const lastTest = s.readOnly ? s.ingest ? `latest trace ${s.ingest.latestTraceAt}` : "—" : s.lastTest ? `${s.lastTest.outcome}${s.lastTest.code ? ` (${s.lastTest.code})` : ""}` : "never";
|
|
@@ -38727,8 +38770,8 @@ function row4(s) {
|
|
|
38727
38770
|
function registerList8(sources) {
|
|
38728
38771
|
sources.command("list").alias("ls").description("Trace sources in the workspace, newest first").addHelpText("after", `
|
|
38729
38772
|
Examples:
|
|
38730
|
-
${chalk66.dim("$")} ${
|
|
38731
|
-
${chalk66.dim("$")} ${
|
|
38773
|
+
${chalk66.dim("$")} ${SOURCES3} list
|
|
38774
|
+
${chalk66.dim("$")} ${SOURCES3} list --json
|
|
38732
38775
|
|
|
38733
38776
|
Credentials are never returned; each source names its current ones by credentialRef.
|
|
38734
38777
|
A row marked read-only is OTLP ingest: it lists while OTLP traces arrive (latest trace
|
|
@@ -38746,7 +38789,7 @@ AI Agent Directive:
|
|
|
38746
38789
|
return;
|
|
38747
38790
|
}
|
|
38748
38791
|
if (all.length === 0) {
|
|
38749
|
-
console.log(chalk66.gray(`No trace sources. Connect one: ${
|
|
38792
|
+
console.log(chalk66.gray(`No trace sources. Connect one: ${SOURCES3} add langfuse --name <name> --public-key <pk> --secret-stdin`));
|
|
38750
38793
|
return;
|
|
38751
38794
|
}
|
|
38752
38795
|
new OutputFormatter("table").output(all.map(row4));
|
|
@@ -38754,18 +38797,20 @@ AI Agent Directive:
|
|
|
38754
38797
|
});
|
|
38755
38798
|
}
|
|
38756
38799
|
function registerAdd(sources) {
|
|
38757
|
-
addCredentialOptions(sources.command("add").description("Connect a Langfuse or
|
|
38800
|
+
addCredentialOptions(sources.command("add").description("Connect a Langfuse, OpenObserve or Dash0 trace source (credentials are write-only)").argument("<kind>", "langfuse | openobserve | dash0").option("--name <name>", "A name, unique in the workspace (1-100 characters)").option("--host <url>", "Base URL: langfuse default https://cloud.langfuse.com; required for openobserve; dash0: the regional API URL").option("--openobserve-org <org>", `openobserve: organization id, the model's org (default "default"); not the global --org`).option("--stream <stream>", 'openobserve: stream name (default "default")').option("--signal <signal>", "openobserve: events | spans (omit to detect it from the rows)").option("--dataset <dataset>", "dash0: the dataset to read (omit for the organization's default)")).addHelpText("after", `
|
|
38758
38801
|
Examples:
|
|
38759
|
-
${chalk66.dim("$")} pass show langfuse/sk | ${
|
|
38760
|
-
${chalk66.dim("$")} ${
|
|
38761
|
-
${chalk66.dim("$")} ${
|
|
38762
|
-
${chalk66.dim("$")} ${
|
|
38763
|
-
|
|
38764
|
-
|
|
38802
|
+
${chalk66.dim("$")} pass show langfuse/sk | ${SOURCES3} add langfuse --name prod --public-key pk-lf-… --secret-stdin
|
|
38803
|
+
${chalk66.dim("$")} ${SOURCES3} add langfuse --name self-hosted --host https://langfuse.example.com --public-key pk-lf-… --secret-env LANGFUSE_SECRET_KEY
|
|
38804
|
+
${chalk66.dim("$")} ${SOURCES3} add openobserve --name oo --host https://api.openobserve.ai --openobserve-org acme --email ops@acme.com --secret-stdin
|
|
38805
|
+
${chalk66.dim("$")} ${SOURCES3} add openobserve --name oo --host http://oo.internal.example:5080 --secret-env OO_TOKEN --json
|
|
38806
|
+
${chalk66.dim("$")} ${SOURCES3} add dash0 --name dash0 --host https://api.eu-west-1.aws.dash0.com --dataset production --secret-env DASH0_AUTH_TOKEN
|
|
38807
|
+
|
|
38808
|
+
The secret (langfuse secret key; openobserve password with --email, or token without; dash0
|
|
38809
|
+
auth token, from Settings → Auth Tokens, with --host from Settings → Endpoints → API) comes
|
|
38765
38810
|
from its flag, from --secret-env <VAR>, or from stdin with --secret-stdin: exactly one. A flag
|
|
38766
38811
|
leaves it in your shell history. Credentials are write-only: no output ever shows them.
|
|
38767
38812
|
The host must be a public http(s) base URL. OTLP traces arrive by push; there is no otlp kind to add.
|
|
38768
|
-
Next: ${
|
|
38813
|
+
Next: ${SOURCES3} test <id>.
|
|
38769
38814
|
|
|
38770
38815
|
In a cloud sandbox:
|
|
38771
38816
|
Keys never go through the session: every key option (--public-key, --secret-key,
|
|
@@ -38801,7 +38846,7 @@ ${WRITE_DIRECTIVE}
|
|
|
38801
38846
|
return;
|
|
38802
38847
|
}
|
|
38803
38848
|
const links = sourceLinks(view.id);
|
|
38804
|
-
const next = [`${
|
|
38849
|
+
const next = [`${SOURCES3} test ${view.id} --json`, `${SOURCES3} pull ${view.id} --json`];
|
|
38805
38850
|
if (isJson) {
|
|
38806
38851
|
const directive = sourceDirective({ template: "integration_source_added", title: `Trace Source Added — ${view.name}`, fields: sourceFields(view), links, next });
|
|
38807
38852
|
new OutputFormatter("json").output({ success: true, source: view, _links: links, _directive: directive });
|
|
@@ -38809,7 +38854,7 @@ ${WRITE_DIRECTIVE}
|
|
|
38809
38854
|
return;
|
|
38810
38855
|
}
|
|
38811
38856
|
console.log(chalk66.green(`✓ Added ${view.kind} source ${view.name} (id: ${view.id})`));
|
|
38812
|
-
console.log(` Next: ${
|
|
38857
|
+
console.log(` Next: ${SOURCES3} test ${view.id}`);
|
|
38813
38858
|
});
|
|
38814
38859
|
});
|
|
38815
38860
|
}
|
|
@@ -38824,8 +38869,8 @@ async function createSource(body, sandbox) {
|
|
|
38824
38869
|
function registerRemove(sources) {
|
|
38825
38870
|
sources.command("remove").description("Delete a trace source, its credentials, its pulls and their output").argument("<id>", "The source id (from list)").option("-f, --force", "Required: confirms the delete (every mode; there is no prompt)").option("-y, --yes", "Same as --force").addHelpText("after", `
|
|
38826
38871
|
Examples:
|
|
38827
|
-
${chalk66.dim("$")} ${
|
|
38828
|
-
${chalk66.dim("$")} ${
|
|
38872
|
+
${chalk66.dim("$")} ${SOURCES3} remove src_123 --force
|
|
38873
|
+
${chalk66.dim("$")} ${SOURCES3} remove src_123 --force --json
|
|
38829
38874
|
|
|
38830
38875
|
Destructive: without -f/--force (or --yes) it refuses and sends nothing, in a terminal
|
|
38831
38876
|
or not, with --json or not. There is no confirmation prompt. Removing a source that is
|
|
@@ -38847,7 +38892,7 @@ AI Agent Directive:
|
|
|
38847
38892
|
title: `Trace Source Removed — ${id}`,
|
|
38848
38893
|
fields: { sourceId: id },
|
|
38849
38894
|
links,
|
|
38850
|
-
next: [`${
|
|
38895
|
+
next: [`${SOURCES3} list --json`]
|
|
38851
38896
|
});
|
|
38852
38897
|
new OutputFormatter("json").output({ success: true, removedId: id, _links: links, _directive: directive });
|
|
38853
38898
|
echoDirectiveToStderr(directive);
|
|
@@ -38860,8 +38905,8 @@ AI Agent Directive:
|
|
|
38860
38905
|
function registerTest2(sources) {
|
|
38861
38906
|
sources.command("test").description("Test a source's connection with its stored credentials").argument("<id>", "The source id").addHelpText("after", `
|
|
38862
38907
|
Examples:
|
|
38863
|
-
${chalk66.dim("$")} ${
|
|
38864
|
-
${chalk66.dim("$")} ${
|
|
38908
|
+
${chalk66.dim("$")} ${SOURCES3} test src_123
|
|
38909
|
+
${chalk66.dim("$")} ${SOURCES3} test src_123 --json
|
|
38865
38910
|
|
|
38866
38911
|
One authenticated request from the server to the source; the outcome is recorded as the
|
|
38867
38912
|
source's last test. A failed test exits 1 and names the check that failed:
|
|
@@ -38900,14 +38945,15 @@ In a cloud sandbox:
|
|
|
38900
38945
|
function registerRotate(sources) {
|
|
38901
38946
|
addCredentialOptions(sources.command("rotate").description("Replace a source's credentials (the key version goes up, the last test is cleared)").argument("<id>", "The source id")).addHelpText("after", `
|
|
38902
38947
|
Examples:
|
|
38903
|
-
${chalk66.dim("$")} pass show langfuse/sk | ${
|
|
38904
|
-
${chalk66.dim("$")} ${
|
|
38905
|
-
${chalk66.dim("$")} ${
|
|
38948
|
+
${chalk66.dim("$")} pass show langfuse/sk | ${SOURCES3} rotate src_123 --public-key pk-lf-… --secret-stdin
|
|
38949
|
+
${chalk66.dim("$")} ${SOURCES3} rotate src_456 --secret-env OO_TOKEN --json
|
|
38950
|
+
${chalk66.dim("$")} ${SOURCES3} rotate src_456 --email ops@acme.com --secret-stdin
|
|
38906
38951
|
|
|
38907
38952
|
Takes the credentials the source's kind takes (it reads the source's kind first): langfuse
|
|
38908
|
-
--public-key and a secret key; openobserve --email and a password, or a token
|
|
38953
|
+
--public-key and a secret key; openobserve --email and a password, or a token; dash0 an auth
|
|
38954
|
+
token. The secret
|
|
38909
38955
|
comes from its flag, --secret-env <VAR> or --secret-stdin. Credentials are write-only.
|
|
38910
|
-
Next: ${
|
|
38956
|
+
Next: ${SOURCES3} test <id>.
|
|
38911
38957
|
|
|
38912
38958
|
${WRITE_DIRECTIVE}
|
|
38913
38959
|
`).action(async (id, flags, command) => {
|
|
@@ -38923,7 +38969,7 @@ ${WRITE_DIRECTIVE}
|
|
|
38923
38969
|
const rotated = await conn.call((i) => i.rotateIntegrationSourceCredentials({ id, body: { credentials } }), { id });
|
|
38924
38970
|
const view = sourceView(rotated, undefined);
|
|
38925
38971
|
const links = sourceLinks(id);
|
|
38926
|
-
const next = [`${
|
|
38972
|
+
const next = [`${SOURCES3} test ${id} --json`];
|
|
38927
38973
|
if (isJson) {
|
|
38928
38974
|
const directive = sourceDirective({ template: "integration_source_rotated", title: `Credentials Rotated — ${view.name}`, fields: sourceFields(view), links, next });
|
|
38929
38975
|
new OutputFormatter("json").output({ success: true, source: view, _links: links, _directive: directive });
|
|
@@ -38931,7 +38977,7 @@ ${WRITE_DIRECTIVE}
|
|
|
38931
38977
|
return;
|
|
38932
38978
|
}
|
|
38933
38979
|
console.log(chalk66.green(`✓ Rotated the credentials of ${view.name} (key version ${String(view.keyVersion)})`));
|
|
38934
|
-
console.log(` Next: ${
|
|
38980
|
+
console.log(` Next: ${SOURCES3} test ${id}`);
|
|
38935
38981
|
});
|
|
38936
38982
|
});
|
|
38937
38983
|
}
|
|
@@ -38946,21 +38992,21 @@ function registerSourceVerbs(sources) {
|
|
|
38946
38992
|
// src/commands/integrations/index.ts
|
|
38947
38993
|
init_errors();
|
|
38948
38994
|
function createSourcesCommand() {
|
|
38949
|
-
const sources = new Command27("sources").description("Trace sources (Langfuse, OpenObserve): connect, test, rotate, and pull traces into UniTF");
|
|
38995
|
+
const sources = new Command27("sources").description("Trace sources (Langfuse, OpenObserve, Dash0): connect, test, rotate, and pull traces into UniTF");
|
|
38950
38996
|
registerSourceVerbs(sources);
|
|
38951
38997
|
registerPullVerbs(sources);
|
|
38952
38998
|
sources.addHelpText("after", `
|
|
38953
38999
|
Examples:
|
|
38954
|
-
${chalk67.dim("$")} ${
|
|
38955
|
-
${chalk67.dim("$")} pass show langfuse/sk | ${
|
|
38956
|
-
${chalk67.dim("$")} ${
|
|
38957
|
-
${chalk67.dim("$")} ${
|
|
38958
|
-
${chalk67.dim("$")} ${
|
|
38959
|
-
${chalk67.dim("$")} ${
|
|
38960
|
-
${chalk67.dim("$")} ${
|
|
38961
|
-
${chalk67.dim("$")} ${
|
|
38962
|
-
${chalk67.dim("$")} ${
|
|
38963
|
-
${chalk67.dim("$")} ${
|
|
39000
|
+
${chalk67.dim("$")} ${SOURCES3} list
|
|
39001
|
+
${chalk67.dim("$")} pass show langfuse/sk | ${SOURCES3} add langfuse --name prod --public-key pk-lf-… --secret-stdin
|
|
39002
|
+
${chalk67.dim("$")} ${SOURCES3} test <id>
|
|
39003
|
+
${chalk67.dim("$")} ${SOURCES3} rotate <id> --public-key pk-lf-… --secret-env LANGFUSE_SECRET_KEY
|
|
39004
|
+
${chalk67.dim("$")} ${SOURCES3} remove <id> --force
|
|
39005
|
+
${chalk67.dim("$")} ${SOURCES3} pull <id> [--since <iso>] [--until <iso>] [--limit <n>] [--agent-name <n>] [--session-id <s>] [--tag <t>]…
|
|
39006
|
+
${chalk67.dim("$")} ${SOURCES3} pulls <id>
|
|
39007
|
+
${chalk67.dim("$")} ${SOURCES3} pull-get <id> <pullId>
|
|
39008
|
+
${chalk67.dim("$")} ${SOURCES3} pull-manifest <id> <pullId>
|
|
39009
|
+
${chalk67.dim("$")} ${SOURCES3} pull-traces <id> <pullId> [--out <file>]
|
|
38964
39010
|
|
|
38965
39011
|
Credentials are write-only: they are stored encrypted and no command ever prints them.
|
|
38966
39012
|
A secret comes from its flag, from --secret-env <VAR>, or from stdin with --secret-stdin.
|
|
@@ -38970,12 +39016,12 @@ or 'mutagent workspaces use'.
|
|
|
38970
39016
|
${EXIT_CODES_LINE}
|
|
38971
39017
|
|
|
38972
39018
|
AI Agent Directive:
|
|
38973
|
-
1. Read first: '${
|
|
39019
|
+
1. Read first: '${SOURCES3} list --json'. Reads need no confirmation.
|
|
38974
39020
|
2. add, rotate, remove and pull are writes: confirm with the user, then run them
|
|
38975
39021
|
(remove with --force).
|
|
38976
39022
|
3. Never ask the user to paste a secret into the chat. Have them run the command in
|
|
38977
39023
|
their own terminal with --secret-stdin (piped) or --secret-env <VAR>.
|
|
38978
|
-
4. Before trusting pulled traces, check '${
|
|
39024
|
+
4. Before trusting pulled traces, check '${SOURCES3} pull-manifest <id> <pullId> --json'
|
|
38979
39025
|
coverage.complete.
|
|
38980
39026
|
5. On an error, run the command in suggestedAction once; never retry blind. When the
|
|
38981
39027
|
fix names the platform operator, tell the user: it cannot be fixed from here.
|
|
@@ -38987,17 +39033,17 @@ function createIntegrationsCommand() {
|
|
|
38987
39033
|
integrations.addCommand(createSourcesCommand());
|
|
38988
39034
|
integrations.addHelpText("after", `
|
|
38989
39035
|
Groups:
|
|
38990
|
-
sources Trace sources (Langfuse, OpenObserve) and pulls of their traces into UniTF
|
|
39036
|
+
sources Trace sources (Langfuse, OpenObserve, Dash0) and pulls of their traces into UniTF
|
|
38991
39037
|
|
|
38992
39038
|
Deploy targets are not available yet: the platform has not built them, so there is no
|
|
38993
39039
|
command for them. Messaging (GitHub, Slack, events, runs) lives in 'mutagent gateway'.
|
|
38994
39040
|
|
|
38995
39041
|
Examples:
|
|
38996
|
-
${chalk67.dim("$")} ${
|
|
38997
|
-
${chalk67.dim("$")} ${
|
|
39042
|
+
${chalk67.dim("$")} ${SOURCES3} list
|
|
39043
|
+
${chalk67.dim("$")} ${SOURCES3} --help
|
|
38998
39044
|
|
|
38999
39045
|
AI Agent Directive:
|
|
39000
|
-
Start with '${
|
|
39046
|
+
Start with '${SOURCES3} list --json'. Do not look for a targets command; there is none yet.
|
|
39001
39047
|
`);
|
|
39002
39048
|
return integrations;
|
|
39003
39049
|
}
|
|
@@ -44627,4 +44673,4 @@ if (process.env.CLI_VERSION) {
|
|
|
44627
44673
|
}
|
|
44628
44674
|
runCli(process.argv.slice(2), cliVersion);
|
|
44629
44675
|
|
|
44630
|
-
//# debugId=
|
|
44676
|
+
//# debugId=B287580A222D152F64756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutagent/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.188",
|
|
4
4
|
"description": "Bun-native CLI for the MutagenT AI platform - auth, provider config, and lifecycle-tool installer for AI-native workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@inquirer/prompts": "^8.7.2",
|
|
48
|
-
"@mutagent/sdk": "0.12.
|
|
48
|
+
"@mutagent/sdk": "0.12.1",
|
|
49
49
|
"@sinclair/typebox": "^0.34.0",
|
|
50
50
|
"chalk": "^5.3.0",
|
|
51
51
|
"commander": "^12.1.0",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"bugs": {
|
|
95
95
|
"url": "https://docs.mutagent.io/support"
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "b21ed2f3d10b3550178a6717a0be81278710640f"
|
|
98
98
|
}
|