propelix-cli 0.1.1 → 0.3.0-dev1
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/index.cjs +278 -3
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -19614,6 +19614,13 @@ function outputTable(columns, rows) {
|
|
|
19614
19614
|
function output(data, format, tableConfig) {
|
|
19615
19615
|
if (format === "table" && tableConfig) {
|
|
19616
19616
|
outputTable(tableConfig.columns, tableConfig.rows);
|
|
19617
|
+
if (data && typeof data === "object" && "total" in data && typeof data.total === "number") {
|
|
19618
|
+
const shown = tableConfig.rows.length;
|
|
19619
|
+
if (data.total > shown) {
|
|
19620
|
+
console.log(import_chalk2.default.dim(`
|
|
19621
|
+
Showing ${shown} of ${data.total} results. Use --limit and --offset to paginate.`));
|
|
19622
|
+
}
|
|
19623
|
+
}
|
|
19617
19624
|
} else {
|
|
19618
19625
|
outputJSON(data);
|
|
19619
19626
|
}
|
|
@@ -19976,6 +19983,136 @@ var CREATE_CHAT_MESSAGE_MUTATION = `
|
|
|
19976
19983
|
}
|
|
19977
19984
|
}
|
|
19978
19985
|
`;
|
|
19986
|
+
var EXPERIMENTS_QUERY = `
|
|
19987
|
+
query Experiments($pagination: PaginationInput, $filter: ExperimentFilter!) {
|
|
19988
|
+
experiments(pagination: $pagination, filter: $filter) {
|
|
19989
|
+
items {
|
|
19990
|
+
id
|
|
19991
|
+
title
|
|
19992
|
+
description
|
|
19993
|
+
project { id }
|
|
19994
|
+
creator { id firstName }
|
|
19995
|
+
startTime
|
|
19996
|
+
endTime
|
|
19997
|
+
variations
|
|
19998
|
+
result
|
|
19999
|
+
createdAt
|
|
20000
|
+
updatedAt
|
|
20001
|
+
cancelledAt
|
|
20002
|
+
}
|
|
20003
|
+
total
|
|
20004
|
+
}
|
|
20005
|
+
}
|
|
20006
|
+
`;
|
|
20007
|
+
var EXPERIMENT_QUERY = `
|
|
20008
|
+
query Experiment($id: ID!) {
|
|
20009
|
+
experiment(id: $id) {
|
|
20010
|
+
id
|
|
20011
|
+
title
|
|
20012
|
+
description
|
|
20013
|
+
project { id }
|
|
20014
|
+
creator { id firstName }
|
|
20015
|
+
startTime
|
|
20016
|
+
endTime
|
|
20017
|
+
variations
|
|
20018
|
+
result
|
|
20019
|
+
createdAt
|
|
20020
|
+
updatedAt
|
|
20021
|
+
cancelledAt
|
|
20022
|
+
controlVariationAgentVersions {
|
|
20023
|
+
agentName
|
|
20024
|
+
promptVersionName
|
|
20025
|
+
}
|
|
20026
|
+
testVariationAgentVersions {
|
|
20027
|
+
agentName
|
|
20028
|
+
promptVersionName
|
|
20029
|
+
}
|
|
20030
|
+
}
|
|
20031
|
+
}
|
|
20032
|
+
`;
|
|
20033
|
+
var EXPERIMENT_MESSAGE_RESPONSE_COMPARISONS_QUERY = `
|
|
20034
|
+
query GetExperimentMessageResponseComparisons(
|
|
20035
|
+
$experimentID: ID!
|
|
20036
|
+
$pagination: PaginationInput
|
|
20037
|
+
$filter: ExperimentMessageResponseComparisonFilter
|
|
20038
|
+
) {
|
|
20039
|
+
experimentMessageResponseComparisons(experimentID: $experimentID, pagination: $pagination, filter: $filter) {
|
|
20040
|
+
items {
|
|
20041
|
+
id
|
|
20042
|
+
experiment { id }
|
|
20043
|
+
targetMessage {
|
|
20044
|
+
id
|
|
20045
|
+
conversationID
|
|
20046
|
+
body
|
|
20047
|
+
authorType
|
|
20048
|
+
authorInfo { name }
|
|
20049
|
+
createdAt
|
|
20050
|
+
}
|
|
20051
|
+
testResponse {
|
|
20052
|
+
id
|
|
20053
|
+
variation
|
|
20054
|
+
runProjectResult
|
|
20055
|
+
finalAgentName
|
|
20056
|
+
metricsData
|
|
20057
|
+
logID
|
|
20058
|
+
createdAt
|
|
20059
|
+
}
|
|
20060
|
+
controlResponse {
|
|
20061
|
+
id
|
|
20062
|
+
variation
|
|
20063
|
+
runProjectResult
|
|
20064
|
+
finalAgentName
|
|
20065
|
+
metricsData
|
|
20066
|
+
logID
|
|
20067
|
+
createdAt
|
|
20068
|
+
}
|
|
20069
|
+
comparisonResult
|
|
20070
|
+
createdAt
|
|
20071
|
+
updatedAt
|
|
20072
|
+
}
|
|
20073
|
+
total
|
|
20074
|
+
}
|
|
20075
|
+
}
|
|
20076
|
+
`;
|
|
20077
|
+
var EXPERIMENT_MESSAGE_RESPONSE_COMPARISON_QUERY = `
|
|
20078
|
+
query GetExperimentMessageResponseComparison($experimentMessageResponseComparisonID: ID!) {
|
|
20079
|
+
experimentMessageResponseComparison(experimentMessageResponseComparisonID: $experimentMessageResponseComparisonID) {
|
|
20080
|
+
id
|
|
20081
|
+
experiment { id title }
|
|
20082
|
+
targetMessage {
|
|
20083
|
+
id
|
|
20084
|
+
conversationID
|
|
20085
|
+
body
|
|
20086
|
+
authorType
|
|
20087
|
+
authorInfo { name }
|
|
20088
|
+
imageURLs
|
|
20089
|
+
fileAttachments { url name mimeType }
|
|
20090
|
+
createdAt
|
|
20091
|
+
}
|
|
20092
|
+
testResponse {
|
|
20093
|
+
id
|
|
20094
|
+
variation
|
|
20095
|
+
runProjectResult
|
|
20096
|
+
finalAgentName
|
|
20097
|
+
metricsData
|
|
20098
|
+
logID
|
|
20099
|
+
createdAt
|
|
20100
|
+
}
|
|
20101
|
+
controlResponse {
|
|
20102
|
+
id
|
|
20103
|
+
variation
|
|
20104
|
+
runProjectResult
|
|
20105
|
+
finalAgentName
|
|
20106
|
+
metricsData
|
|
20107
|
+
logID
|
|
20108
|
+
createdAt
|
|
20109
|
+
}
|
|
20110
|
+
comparisonResult
|
|
20111
|
+
createdAt
|
|
20112
|
+
updatedAt
|
|
20113
|
+
}
|
|
20114
|
+
}
|
|
20115
|
+
`;
|
|
19979
20116
|
var CLEAR_CHAT_MESSAGES_MUTATION = `
|
|
19980
20117
|
mutation ClearChatMessages {
|
|
19981
20118
|
clearChatMessages
|
|
@@ -20468,6 +20605,126 @@ function registerConversationCommand(program3) {
|
|
|
20468
20605
|
});
|
|
20469
20606
|
}
|
|
20470
20607
|
|
|
20608
|
+
// src/commands/experiment.ts
|
|
20609
|
+
var EVALUATION_CATEGORIES = [
|
|
20610
|
+
"SubsetAndConsistent",
|
|
20611
|
+
"SupersetAndConsistent",
|
|
20612
|
+
"SameDetailsAsExpert",
|
|
20613
|
+
"DisagreementBetweenAnswers",
|
|
20614
|
+
"DifferencesDontMatter"
|
|
20615
|
+
];
|
|
20616
|
+
function experimentStatus(exp) {
|
|
20617
|
+
if (exp.cancelledAt) return "cancelled";
|
|
20618
|
+
if (exp.endTime) return "completed";
|
|
20619
|
+
if (exp.startTime) return "running";
|
|
20620
|
+
return "pending";
|
|
20621
|
+
}
|
|
20622
|
+
function registerExperimentCommand(program3) {
|
|
20623
|
+
const experiment = program3.command("experiment").description("Experiment (shadow test) operations");
|
|
20624
|
+
experiment.command("list").description("List experiments for the current project").option("--limit <n>", "Max results").option("--offset <n>", "Skip results").option("--date-from <ISO>", "Filter from date (ISO 8601)").option("--date-to <ISO>", "Filter to date (ISO 8601)").option("--from-file <path>", "Load params from JSON file").action(async (cmdOpts) => {
|
|
20625
|
+
try {
|
|
20626
|
+
const parentOpts = program3.opts();
|
|
20627
|
+
const opts = mergeFromFile(cmdOpts, cmdOpts.fromFile);
|
|
20628
|
+
const config = requireConfig(parentOpts);
|
|
20629
|
+
const projectID = requireProjectID(config);
|
|
20630
|
+
const client = createGraphQLClient(config);
|
|
20631
|
+
const filter = { projectID };
|
|
20632
|
+
if (opts.dateFrom && opts.dateTo) {
|
|
20633
|
+
filter.createdAtRange = [opts.dateFrom, opts.dateTo];
|
|
20634
|
+
} else if (opts.dateFrom) {
|
|
20635
|
+
filter.createdAtRange = [opts.dateFrom, (/* @__PURE__ */ new Date()).toISOString()];
|
|
20636
|
+
} else if (opts.dateTo) {
|
|
20637
|
+
filter.createdAtRange = [(/* @__PURE__ */ new Date(0)).toISOString(), opts.dateTo];
|
|
20638
|
+
}
|
|
20639
|
+
const data = await client.request(EXPERIMENTS_QUERY, {
|
|
20640
|
+
pagination: toPagination(opts),
|
|
20641
|
+
filter
|
|
20642
|
+
});
|
|
20643
|
+
output(data.experiments, parentOpts.format, {
|
|
20644
|
+
columns: ["id", "title", "status", "createdAt"],
|
|
20645
|
+
rows: data.experiments.items.map((e) => ({
|
|
20646
|
+
id: e.id,
|
|
20647
|
+
title: e.title,
|
|
20648
|
+
status: experimentStatus(e),
|
|
20649
|
+
createdAt: e.createdAt
|
|
20650
|
+
}))
|
|
20651
|
+
});
|
|
20652
|
+
} catch (error) {
|
|
20653
|
+
handleError(error);
|
|
20654
|
+
}
|
|
20655
|
+
});
|
|
20656
|
+
experiment.command("get").description("Get experiment detail").argument("<id>", "Experiment ID").action(async (id) => {
|
|
20657
|
+
try {
|
|
20658
|
+
const parentOpts = program3.opts();
|
|
20659
|
+
const config = requireConfig(parentOpts);
|
|
20660
|
+
const client = createGraphQLClient(config);
|
|
20661
|
+
const data = await client.request(EXPERIMENT_QUERY, { id });
|
|
20662
|
+
output(data.experiment, parentOpts.format);
|
|
20663
|
+
} catch (error) {
|
|
20664
|
+
handleError(error);
|
|
20665
|
+
}
|
|
20666
|
+
});
|
|
20667
|
+
const comparison = experiment.command("comparison").description("Message response comparison operations");
|
|
20668
|
+
comparison.command("list").description("List message response comparisons for an experiment").argument("<experiment-id>", "Experiment ID").option("--limit <n>", "Max results").option("--offset <n>", "Skip results").option("--evaluation-category <cat>", "Filter by evaluation category").addHelpText("after", `
|
|
20669
|
+
Valid evaluation categories: ${EVALUATION_CATEGORIES.join(", ")}`).option("--has-images <bool>", "Filter comparisons with/without images (true|false)").option("--has-file-attachments <bool>", "Filter comparisons with/without file attachments (true|false)").option("--has-failed-tool-calls <bool>", "Filter comparisons with/without failed tool calls (true|false)").option("--from-file <path>", "Load params from JSON file").action(async (experimentID, cmdOpts) => {
|
|
20670
|
+
try {
|
|
20671
|
+
const parentOpts = program3.opts();
|
|
20672
|
+
const opts = mergeFromFile(cmdOpts, cmdOpts.fromFile);
|
|
20673
|
+
const config = requireConfig(parentOpts);
|
|
20674
|
+
const client = createGraphQLClient(config);
|
|
20675
|
+
const filter = {};
|
|
20676
|
+
if (opts.evaluationCategory) {
|
|
20677
|
+
const cat = opts.evaluationCategory;
|
|
20678
|
+
if (!EVALUATION_CATEGORIES.includes(cat)) {
|
|
20679
|
+
throw new Error(
|
|
20680
|
+
`Invalid evaluation category: "${cat}". Must be one of: ${EVALUATION_CATEGORIES.join(", ")}`
|
|
20681
|
+
);
|
|
20682
|
+
}
|
|
20683
|
+
filter.evaluationCategory = cat;
|
|
20684
|
+
}
|
|
20685
|
+
if (opts.hasImages !== void 0) filter.hasImages = opts.hasImages === "true";
|
|
20686
|
+
if (opts.hasFileAttachments !== void 0) filter.hasFileAttachments = opts.hasFileAttachments === "true";
|
|
20687
|
+
if (opts.hasFailedToolCalls !== void 0) filter.hasFailedToolCalls = opts.hasFailedToolCalls === "true";
|
|
20688
|
+
const data = await client.request(EXPERIMENT_MESSAGE_RESPONSE_COMPARISONS_QUERY, {
|
|
20689
|
+
experimentID,
|
|
20690
|
+
pagination: toPagination(opts),
|
|
20691
|
+
filter: Object.keys(filter).length > 0 ? filter : void 0
|
|
20692
|
+
});
|
|
20693
|
+
const comparisons = data.experimentMessageResponseComparisons;
|
|
20694
|
+
output(comparisons, parentOpts.format, {
|
|
20695
|
+
columns: ["id", "category", "controlAgent", "testAgent", "messagePreview", "createdAt"],
|
|
20696
|
+
rows: comparisons.items.map((c) => ({
|
|
20697
|
+
id: c.id,
|
|
20698
|
+
category: c.comparisonResult?.category ?? "",
|
|
20699
|
+
controlAgent: c.controlResponse?.finalAgentName ?? "",
|
|
20700
|
+
testAgent: c.testResponse?.finalAgentName ?? "",
|
|
20701
|
+
messagePreview: truncate(c.targetMessage?.body ?? "", 60),
|
|
20702
|
+
createdAt: c.createdAt
|
|
20703
|
+
}))
|
|
20704
|
+
});
|
|
20705
|
+
} catch (error) {
|
|
20706
|
+
handleError(error);
|
|
20707
|
+
}
|
|
20708
|
+
});
|
|
20709
|
+
comparison.command("get").description("Get a single message response comparison detail").argument("<comparison-id>", "Comparison ID").action(async (comparisonID) => {
|
|
20710
|
+
try {
|
|
20711
|
+
const parentOpts = program3.opts();
|
|
20712
|
+
const config = requireConfig(parentOpts);
|
|
20713
|
+
const client = createGraphQLClient(config);
|
|
20714
|
+
const data = await client.request(EXPERIMENT_MESSAGE_RESPONSE_COMPARISON_QUERY, {
|
|
20715
|
+
experimentMessageResponseComparisonID: comparisonID
|
|
20716
|
+
});
|
|
20717
|
+
output(data.experimentMessageResponseComparison, parentOpts.format);
|
|
20718
|
+
} catch (error) {
|
|
20719
|
+
handleError(error);
|
|
20720
|
+
}
|
|
20721
|
+
});
|
|
20722
|
+
}
|
|
20723
|
+
function truncate(text, max) {
|
|
20724
|
+
if (text.length <= max) return text;
|
|
20725
|
+
return text.slice(0, max - 3) + "...";
|
|
20726
|
+
}
|
|
20727
|
+
|
|
20471
20728
|
// src/commands/guardrail.ts
|
|
20472
20729
|
function registerGuardrailCommand(program3) {
|
|
20473
20730
|
const guard = program3.command("guardrail").description("Guard rail operations");
|
|
@@ -21081,13 +21338,30 @@ function registerTestCommand(program3) {
|
|
|
21081
21338
|
});
|
|
21082
21339
|
}
|
|
21083
21340
|
|
|
21341
|
+
// src/lib/proxy.ts
|
|
21342
|
+
function setupProxy(proxyUrl) {
|
|
21343
|
+
if (proxyUrl) {
|
|
21344
|
+
process.env.HTTPS_PROXY = proxyUrl;
|
|
21345
|
+
process.env.HTTP_PROXY = proxyUrl;
|
|
21346
|
+
}
|
|
21347
|
+
const effectiveProxy = proxyUrl || process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy;
|
|
21348
|
+
if (!effectiveProxy) {
|
|
21349
|
+
return;
|
|
21350
|
+
}
|
|
21351
|
+
const { EnvHttpProxyAgent, setGlobalDispatcher } = require("undici");
|
|
21352
|
+
const agent = new EnvHttpProxyAgent();
|
|
21353
|
+
setGlobalDispatcher(agent);
|
|
21354
|
+
}
|
|
21355
|
+
|
|
21084
21356
|
// src/index.ts
|
|
21085
21357
|
var program2 = new Command();
|
|
21086
|
-
program2.name("propelix").description("Propelix CLI").version("0.
|
|
21358
|
+
program2.name("propelix").description("Propelix CLI").version("0.3.0-dev1").option("--base-url <url>", "API base URL (default: https://propelix.ai)").option("--token <token>", "Auth token (overrides stored config)").option("--project-id <id>", "Project ID (overrides stored config)").option("--insecure", "Disable TLS certificate verification (for local dev)").option("--proxy <url>", "HTTP(S) proxy URL (overrides HTTPS_PROXY / HTTP_PROXY env vars)").option("--json", "Output as JSON (deprecated, use --format json)").option("--format <fmt>", "Output format: json (default) | table");
|
|
21087
21359
|
program2.hook("preAction", () => {
|
|
21088
|
-
|
|
21360
|
+
const globalOpts = program2.opts();
|
|
21361
|
+
if (globalOpts.insecure) {
|
|
21089
21362
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
21090
21363
|
}
|
|
21364
|
+
setupProxy(globalOpts.proxy);
|
|
21091
21365
|
});
|
|
21092
21366
|
registerAuthCommand(program2);
|
|
21093
21367
|
registerConfigCommand(program2);
|
|
@@ -21096,13 +21370,14 @@ registerAgentCommand(program2);
|
|
|
21096
21370
|
registerChannelCommand(program2);
|
|
21097
21371
|
registerPromptCommand(program2);
|
|
21098
21372
|
registerConversationCommand(program2);
|
|
21373
|
+
registerExperimentCommand(program2);
|
|
21099
21374
|
registerLogCommand(program2);
|
|
21100
21375
|
registerGuardrailCommand(program2);
|
|
21101
21376
|
registerImageCommand(program2);
|
|
21102
21377
|
registerChatCommand(program2);
|
|
21103
21378
|
registerTestCommand(program2);
|
|
21104
21379
|
program2.command("version").description("Print version number").action(() => {
|
|
21105
|
-
console.log("0.
|
|
21380
|
+
console.log("0.3.0-dev1");
|
|
21106
21381
|
});
|
|
21107
21382
|
program2.command("whoami").description("Show the currently authenticated user").action(async () => {
|
|
21108
21383
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "propelix-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-dev1",
|
|
4
4
|
"description": "CLI for Propelix",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"commander": "^12.1.0",
|
|
15
15
|
"graphql-request": "^7.1.2",
|
|
16
16
|
"gray-matter": "^4.0.3",
|
|
17
|
-
"ora": "^5.4.1"
|
|
17
|
+
"ora": "^5.4.1",
|
|
18
|
+
"undici": "^6.19.8"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
21
|
"tsup": "^8.3.5",
|