propelix-cli 0.1.1 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.cjs +260 -2
  2. package/package.json +1 -1
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");
@@ -21083,7 +21340,7 @@ function registerTestCommand(program3) {
21083
21340
 
21084
21341
  // src/index.ts
21085
21342
  var program2 = new Command();
21086
- program2.name("propelix").description("Propelix CLI").version("0.1.1").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("--json", "Output as JSON (deprecated, use --format json)").option("--format <fmt>", "Output format: json (default) | table");
21343
+ program2.name("propelix").description("Propelix CLI").version("0.2.0").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("--json", "Output as JSON (deprecated, use --format json)").option("--format <fmt>", "Output format: json (default) | table");
21087
21344
  program2.hook("preAction", () => {
21088
21345
  if (program2.opts().insecure) {
21089
21346
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
@@ -21096,13 +21353,14 @@ registerAgentCommand(program2);
21096
21353
  registerChannelCommand(program2);
21097
21354
  registerPromptCommand(program2);
21098
21355
  registerConversationCommand(program2);
21356
+ registerExperimentCommand(program2);
21099
21357
  registerLogCommand(program2);
21100
21358
  registerGuardrailCommand(program2);
21101
21359
  registerImageCommand(program2);
21102
21360
  registerChatCommand(program2);
21103
21361
  registerTestCommand(program2);
21104
21362
  program2.command("version").description("Print version number").action(() => {
21105
- console.log("0.1.1");
21363
+ console.log("0.2.0");
21106
21364
  });
21107
21365
  program2.command("whoami").description("Show the currently authenticated user").action(async () => {
21108
21366
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "propelix-cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "CLI for Propelix",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {