@tenderprompt/cli 0.1.9 → 0.1.10
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 +4 -0
- package/dist/index.js +290 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,6 +157,8 @@ tender app analytics export catalog artifact_123 --range 30d --json
|
|
|
157
157
|
tender app analytics export query artifact_123 --spec chart.json --format csv
|
|
158
158
|
|
|
159
159
|
tender app analytics suggestions artifact_123 --range 30d --json
|
|
160
|
+
|
|
161
|
+
tender app analytics charts templates --json
|
|
160
162
|
```
|
|
161
163
|
|
|
162
164
|
Safe write previews:
|
|
@@ -178,6 +180,8 @@ Agents should combine `capabilities --include-catalog` with local source-code
|
|
|
178
180
|
inspection. For example, inspect where the app calls
|
|
179
181
|
`__TP_ANALYTICS.invoke(...)`, propose a chart spec, validate it with
|
|
180
182
|
`analytics query`, and only then create a saved chart.
|
|
183
|
+
Use `charts templates --json` for reusable chart shapes; adapt any placeholders
|
|
184
|
+
to observed events, paths, or promoted property keys before querying or saving.
|
|
181
185
|
|
|
182
186
|
## Safety Model
|
|
183
187
|
|
package/dist/index.js
CHANGED
|
@@ -266,6 +266,7 @@ Commands:
|
|
|
266
266
|
tender app analytics suggestions <app-id> Generate starter chart suggestions
|
|
267
267
|
tender app analytics dashboards <app-id> List or create dashboards
|
|
268
268
|
tender app analytics export <kind> <app-id> Export catalog metadata or query rows
|
|
269
|
+
tender app analytics charts templates Print reusable chart spec templates
|
|
269
270
|
tender app analytics charts create <app-id> Create a saved chart
|
|
270
271
|
|
|
271
272
|
Examples:
|
|
@@ -277,6 +278,7 @@ Examples:
|
|
|
277
278
|
tender app analytics export query artifact_123 --spec chart.json --format csv
|
|
278
279
|
tender app analytics suggestions artifact_123 --range 2026-04-01..2026-04-30 --json
|
|
279
280
|
tender app analytics dashboards artifact_123 --create "Agent dashboard" --json
|
|
281
|
+
tender app analytics charts templates --json
|
|
280
282
|
tender app analytics charts create artifact_123 --dashboard analytics_dashboard_123 --title "Signup funnel" --spec funnel.json --json`;
|
|
281
283
|
}
|
|
282
284
|
function analyticsSummaryHelp() {
|
|
@@ -340,6 +342,16 @@ Examples:
|
|
|
340
342
|
tender app analytics dashboards artifact_123 --create "Agent dashboard" --dry-run --json
|
|
341
343
|
tender app analytics dashboards artifact_123 --create "Agent dashboard" --json`;
|
|
342
344
|
}
|
|
345
|
+
function analyticsChartsTemplatesHelp() {
|
|
346
|
+
return `Usage: tender app analytics charts templates [--json]
|
|
347
|
+
|
|
348
|
+
Print reusable chart spec templates for agents. Adapt templates to observed
|
|
349
|
+
events, paths, and property keys from analytics capabilities before querying or
|
|
350
|
+
saving.
|
|
351
|
+
|
|
352
|
+
Examples:
|
|
353
|
+
tender app analytics charts templates --json`;
|
|
354
|
+
}
|
|
343
355
|
function analyticsChartsCreateHelp() {
|
|
344
356
|
return `Usage: tender app analytics charts create <app-id> --dashboard <dashboard-id> --title <title> --spec <file|-> [--dry-run] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
345
357
|
|
|
@@ -725,6 +737,7 @@ function tenderCliCapabilities() {
|
|
|
725
737
|
when: "When understanding app analytics or creating saved charts.",
|
|
726
738
|
commands: [
|
|
727
739
|
"tender app analytics capabilities <artifact-id> --include-catalog --range 30d --json",
|
|
740
|
+
"tender app analytics charts templates --json",
|
|
728
741
|
"tender app analytics query <artifact-id> --spec chart.json --json",
|
|
729
742
|
"tender app analytics export query <artifact-id> --spec chart.json --format csv",
|
|
730
743
|
"tender app analytics dashboards <artifact-id> --create \"Agent dashboard\" --dry-run --json",
|
|
@@ -782,6 +795,12 @@ function tenderCliCapabilities() {
|
|
|
782
795
|
requiresAuth: true,
|
|
783
796
|
writes: false,
|
|
784
797
|
},
|
|
798
|
+
{
|
|
799
|
+
command: "tender app analytics charts templates --json",
|
|
800
|
+
purpose: "Print reusable chart spec templates for agents to adapt to observed analytics data.",
|
|
801
|
+
requiresAuth: false,
|
|
802
|
+
writes: false,
|
|
803
|
+
},
|
|
785
804
|
],
|
|
786
805
|
security: [
|
|
787
806
|
"Prefer artifact-scoped device tokens.",
|
|
@@ -2555,6 +2574,21 @@ function parseAnalyticsDashboardsArgs(args) {
|
|
|
2555
2574
|
}
|
|
2556
2575
|
return { command: "app analytics dashboards", artifactId, name, dryRun, ...parsed };
|
|
2557
2576
|
}
|
|
2577
|
+
function parseAnalyticsChartsTemplatesArgs(args) {
|
|
2578
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
2579
|
+
return { command: "help", topic: "app analytics charts templates" };
|
|
2580
|
+
}
|
|
2581
|
+
let json = false;
|
|
2582
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
2583
|
+
const arg = args[index];
|
|
2584
|
+
if (arg === "--json") {
|
|
2585
|
+
json = true;
|
|
2586
|
+
continue;
|
|
2587
|
+
}
|
|
2588
|
+
throw new TenderCliUsageError(`Unknown analytics charts templates option: ${arg}`);
|
|
2589
|
+
}
|
|
2590
|
+
return { command: "app analytics charts templates", json };
|
|
2591
|
+
}
|
|
2558
2592
|
function parseAnalyticsExportCatalogArgs(args) {
|
|
2559
2593
|
if (args.includes("--help") || args.includes("-h")) {
|
|
2560
2594
|
return { command: "help", topic: "app analytics export catalog" };
|
|
@@ -2632,6 +2666,244 @@ function parseAnalyticsExportQueryArgs(args) {
|
|
|
2632
2666
|
...parsed,
|
|
2633
2667
|
};
|
|
2634
2668
|
}
|
|
2669
|
+
function analyticsChartTemplates() {
|
|
2670
|
+
return [
|
|
2671
|
+
{
|
|
2672
|
+
id: "daily_custom_events",
|
|
2673
|
+
title: "Daily custom events",
|
|
2674
|
+
visualization: "line",
|
|
2675
|
+
purpose: "Track app-owned business events over time.",
|
|
2676
|
+
usableAsIs: true,
|
|
2677
|
+
adaptWith: [
|
|
2678
|
+
"Use when the catalog has observed custom events.",
|
|
2679
|
+
"Switch the range preset to 7d or 90d when the user's question asks for that window.",
|
|
2680
|
+
],
|
|
2681
|
+
spec: {
|
|
2682
|
+
version: 1,
|
|
2683
|
+
dataset: "events",
|
|
2684
|
+
visualization: "line",
|
|
2685
|
+
metric: { name: "custom_event_count" },
|
|
2686
|
+
groupBy: [{ field: "day" }],
|
|
2687
|
+
filters: [],
|
|
2688
|
+
range: { preset: "30d" },
|
|
2689
|
+
sort: [{ field: "label", direction: "asc" }],
|
|
2690
|
+
limit: 30,
|
|
2691
|
+
},
|
|
2692
|
+
},
|
|
2693
|
+
{
|
|
2694
|
+
id: "top_custom_events",
|
|
2695
|
+
title: "Top custom events",
|
|
2696
|
+
visualization: "bar",
|
|
2697
|
+
purpose: "Show which app-owned events happen most often.",
|
|
2698
|
+
usableAsIs: true,
|
|
2699
|
+
adaptWith: [
|
|
2700
|
+
"Use this before proposing deeper charts so the agent can see the dominant event shape.",
|
|
2701
|
+
],
|
|
2702
|
+
spec: {
|
|
2703
|
+
version: 1,
|
|
2704
|
+
dataset: "events",
|
|
2705
|
+
visualization: "bar",
|
|
2706
|
+
metric: { name: "custom_event_count" },
|
|
2707
|
+
groupBy: [{ field: "event_name" }],
|
|
2708
|
+
filters: [],
|
|
2709
|
+
range: { preset: "30d" },
|
|
2710
|
+
sort: [{ field: "value", direction: "desc" }],
|
|
2711
|
+
limit: 10,
|
|
2712
|
+
},
|
|
2713
|
+
},
|
|
2714
|
+
{
|
|
2715
|
+
id: "top_request_paths",
|
|
2716
|
+
title: "Top request paths",
|
|
2717
|
+
visualization: "bar",
|
|
2718
|
+
purpose: "Find the generated app routes receiving the most traffic.",
|
|
2719
|
+
usableAsIs: true,
|
|
2720
|
+
adaptWith: [
|
|
2721
|
+
"Use only when the capabilities catalog reports request paths.",
|
|
2722
|
+
"Inspect the local source to understand what the busiest routes represent.",
|
|
2723
|
+
],
|
|
2724
|
+
spec: {
|
|
2725
|
+
version: 1,
|
|
2726
|
+
dataset: "events",
|
|
2727
|
+
visualization: "bar",
|
|
2728
|
+
metric: { name: "request_count" },
|
|
2729
|
+
groupBy: [{ field: "path" }],
|
|
2730
|
+
filters: [],
|
|
2731
|
+
range: { preset: "30d" },
|
|
2732
|
+
sort: [{ field: "value", direction: "desc" }],
|
|
2733
|
+
limit: 10,
|
|
2734
|
+
},
|
|
2735
|
+
},
|
|
2736
|
+
{
|
|
2737
|
+
id: "event_funnel_by_name",
|
|
2738
|
+
title: "Event funnel",
|
|
2739
|
+
visualization: "funnel",
|
|
2740
|
+
purpose: "Measure ordered conversion through observed custom event names.",
|
|
2741
|
+
usableAsIs: false,
|
|
2742
|
+
placeholders: {
|
|
2743
|
+
eventNames: ["<start_event>", "<middle_event>", "<conversion_event>"],
|
|
2744
|
+
},
|
|
2745
|
+
adaptWith: [
|
|
2746
|
+
"Replace placeholders with ordered event names from catalog classification or observed events.",
|
|
2747
|
+
"Use only event names observed for the selected app.",
|
|
2748
|
+
"Validate with analytics query before saving because funnel order changes the meaning.",
|
|
2749
|
+
],
|
|
2750
|
+
spec: {
|
|
2751
|
+
version: 1,
|
|
2752
|
+
dataset: "events",
|
|
2753
|
+
visualization: "funnel",
|
|
2754
|
+
metric: { name: "custom_event_count" },
|
|
2755
|
+
groupBy: [{ field: "event_name" }],
|
|
2756
|
+
filters: [
|
|
2757
|
+
{
|
|
2758
|
+
field: "event_name",
|
|
2759
|
+
op: "in",
|
|
2760
|
+
value: ["<start_event>", "<middle_event>", "<conversion_event>"],
|
|
2761
|
+
},
|
|
2762
|
+
],
|
|
2763
|
+
range: { preset: "30d" },
|
|
2764
|
+
sort: [{ field: "label", direction: "asc" }],
|
|
2765
|
+
limit: 3,
|
|
2766
|
+
},
|
|
2767
|
+
},
|
|
2768
|
+
{
|
|
2769
|
+
id: "request_path_funnel",
|
|
2770
|
+
title: "Request path funnel",
|
|
2771
|
+
visualization: "funnel",
|
|
2772
|
+
purpose: "Measure ordered conversion through observed request paths.",
|
|
2773
|
+
usableAsIs: false,
|
|
2774
|
+
placeholders: {
|
|
2775
|
+
paths: ["/<start_path>", "/<middle_path>", "/<conversion_path>"],
|
|
2776
|
+
},
|
|
2777
|
+
adaptWith: [
|
|
2778
|
+
"Use when catalog classification includes a path-based funnel or the source code shows ordered route milestones.",
|
|
2779
|
+
"Replace placeholders with exact observed paths from the selected app.",
|
|
2780
|
+
"Do not include repeated activity routes unless source context says they are milestones.",
|
|
2781
|
+
],
|
|
2782
|
+
spec: {
|
|
2783
|
+
version: 1,
|
|
2784
|
+
dataset: "events",
|
|
2785
|
+
visualization: "funnel",
|
|
2786
|
+
metric: { name: "request_count" },
|
|
2787
|
+
groupBy: [{ field: "path" }],
|
|
2788
|
+
filters: [
|
|
2789
|
+
{
|
|
2790
|
+
field: "path",
|
|
2791
|
+
op: "in",
|
|
2792
|
+
value: ["/<start_path>", "/<middle_path>", "/<conversion_path>"],
|
|
2793
|
+
},
|
|
2794
|
+
],
|
|
2795
|
+
range: { preset: "30d" },
|
|
2796
|
+
sort: [{ field: "label", direction: "asc" }],
|
|
2797
|
+
limit: 3,
|
|
2798
|
+
},
|
|
2799
|
+
},
|
|
2800
|
+
{
|
|
2801
|
+
id: "property_breakdown",
|
|
2802
|
+
title: "Property breakdown",
|
|
2803
|
+
visualization: "bar",
|
|
2804
|
+
purpose: "Compare a promoted dimension property observed in events.",
|
|
2805
|
+
usableAsIs: false,
|
|
2806
|
+
placeholders: {
|
|
2807
|
+
property: "<promoted_dimension_property>",
|
|
2808
|
+
},
|
|
2809
|
+
adaptWith: [
|
|
2810
|
+
"Use a property key promoted by capabilities chartSpec.groupBy, such as property:plan.",
|
|
2811
|
+
"Choose stable categorical properties with enough observations to compare.",
|
|
2812
|
+
],
|
|
2813
|
+
spec: {
|
|
2814
|
+
version: 1,
|
|
2815
|
+
dataset: "events",
|
|
2816
|
+
visualization: "bar",
|
|
2817
|
+
metric: { name: "custom_event_count" },
|
|
2818
|
+
groupBy: [{ field: "property:<promoted_dimension_property>" }],
|
|
2819
|
+
filters: [],
|
|
2820
|
+
range: { preset: "30d" },
|
|
2821
|
+
sort: [{ field: "value", direction: "desc" }],
|
|
2822
|
+
limit: 10,
|
|
2823
|
+
},
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
id: "average_metric_property",
|
|
2827
|
+
title: "Average metric property",
|
|
2828
|
+
visualization: "line",
|
|
2829
|
+
purpose: "Track an observed numeric event property over time.",
|
|
2830
|
+
usableAsIs: false,
|
|
2831
|
+
placeholders: {
|
|
2832
|
+
metric: "avg:<promoted_metric_property>",
|
|
2833
|
+
},
|
|
2834
|
+
adaptWith: [
|
|
2835
|
+
"Use a numeric property key promoted by capabilities chartSpec.metrics.",
|
|
2836
|
+
"Prefer averages for scores, durations, quantities, or ordinal values.",
|
|
2837
|
+
],
|
|
2838
|
+
spec: {
|
|
2839
|
+
version: 1,
|
|
2840
|
+
dataset: "events",
|
|
2841
|
+
visualization: "line",
|
|
2842
|
+
metric: { name: "avg:<promoted_metric_property>" },
|
|
2843
|
+
groupBy: [{ field: "day" }],
|
|
2844
|
+
filters: [],
|
|
2845
|
+
range: { preset: "30d" },
|
|
2846
|
+
sort: [{ field: "label", direction: "asc" }],
|
|
2847
|
+
limit: 30,
|
|
2848
|
+
},
|
|
2849
|
+
},
|
|
2850
|
+
{
|
|
2851
|
+
id: "single_number_total",
|
|
2852
|
+
title: "Single number total",
|
|
2853
|
+
visualization: "number",
|
|
2854
|
+
purpose: "Show one headline count for a selected event or request segment.",
|
|
2855
|
+
usableAsIs: false,
|
|
2856
|
+
placeholders: {
|
|
2857
|
+
eventName: "<event_name>",
|
|
2858
|
+
},
|
|
2859
|
+
adaptWith: [
|
|
2860
|
+
"Use when a dashboard needs a compact KPI card.",
|
|
2861
|
+
"Replace the event filter with an observed conversion or outcome event.",
|
|
2862
|
+
],
|
|
2863
|
+
spec: {
|
|
2864
|
+
version: 1,
|
|
2865
|
+
dataset: "events",
|
|
2866
|
+
visualization: "number",
|
|
2867
|
+
metric: { name: "custom_event_count" },
|
|
2868
|
+
groupBy: [],
|
|
2869
|
+
filters: [{ field: "event_name", op: "=", value: "<event_name>" }],
|
|
2870
|
+
range: { preset: "30d" },
|
|
2871
|
+
sort: [],
|
|
2872
|
+
limit: 1,
|
|
2873
|
+
},
|
|
2874
|
+
},
|
|
2875
|
+
];
|
|
2876
|
+
}
|
|
2877
|
+
function runAnalyticsChartsTemplates(command, io) {
|
|
2878
|
+
const templates = analyticsChartTemplates();
|
|
2879
|
+
const payload = {
|
|
2880
|
+
ok: true,
|
|
2881
|
+
command: command.command,
|
|
2882
|
+
templates,
|
|
2883
|
+
next: [
|
|
2884
|
+
"Run tender app analytics capabilities <artifact-id> --include-catalog --range 30d --json.",
|
|
2885
|
+
"Choose a template and replace placeholders with observed events, paths, or promoted property keys.",
|
|
2886
|
+
"Validate with tender app analytics query <artifact-id> --spec chart.json --json.",
|
|
2887
|
+
"Preview saved writes with tender app analytics dashboards ... --dry-run and charts create ... --dry-run.",
|
|
2888
|
+
],
|
|
2889
|
+
};
|
|
2890
|
+
if (command.json) {
|
|
2891
|
+
io.stdout(JSON.stringify(payload, null, 2));
|
|
2892
|
+
}
|
|
2893
|
+
else {
|
|
2894
|
+
io.stdout([
|
|
2895
|
+
"Analytics chart templates",
|
|
2896
|
+
"",
|
|
2897
|
+
...templates.map((template) => {
|
|
2898
|
+
const marker = template.usableAsIs ? "usable as-is" : "adapt before use";
|
|
2899
|
+
return `- ${template.id}: ${template.title} (${marker})`;
|
|
2900
|
+
}),
|
|
2901
|
+
"",
|
|
2902
|
+
"Use --json to copy full chart specs.",
|
|
2903
|
+
].join("\n"));
|
|
2904
|
+
}
|
|
2905
|
+
return 0;
|
|
2906
|
+
}
|
|
2635
2907
|
function parseAnalyticsChartsCreateArgs(args) {
|
|
2636
2908
|
if (args.includes("--help") || args.includes("-h")) {
|
|
2637
2909
|
return { command: "help", topic: "app analytics charts create" };
|
|
@@ -2781,6 +3053,18 @@ function parseTenderArgs(args) {
|
|
|
2781
3053
|
resourceArgs[3] === "query") {
|
|
2782
3054
|
return parseAnalyticsExportQueryArgs(resourceArgs.slice(4));
|
|
2783
3055
|
}
|
|
3056
|
+
if (resourceArgs[1] === "analytics" &&
|
|
3057
|
+
resourceArgs[2] === "charts" &&
|
|
3058
|
+
resourceArgs[3] === "templates") {
|
|
3059
|
+
return parseAnalyticsChartsTemplatesArgs(resourceArgs.slice(4));
|
|
3060
|
+
}
|
|
3061
|
+
if (resourceArgs[1] === "analytics" &&
|
|
3062
|
+
resourceArgs[2] === "charts" &&
|
|
3063
|
+
(resourceArgs[3] === undefined ||
|
|
3064
|
+
resourceArgs[3] === "--help" ||
|
|
3065
|
+
resourceArgs[3] === "-h")) {
|
|
3066
|
+
return { command: "help", topic: "app analytics charts templates" };
|
|
3067
|
+
}
|
|
2784
3068
|
if (resourceArgs[1] === "analytics" &&
|
|
2785
3069
|
resourceArgs[2] === "charts" &&
|
|
2786
3070
|
resourceArgs[3] === "create") {
|
|
@@ -5503,6 +5787,9 @@ export async function runTenderCli(args, io = {
|
|
|
5503
5787
|
else if (command.topic === "app analytics export query") {
|
|
5504
5788
|
io.stdout(analyticsExportQueryHelp());
|
|
5505
5789
|
}
|
|
5790
|
+
else if (command.topic === "app analytics charts templates") {
|
|
5791
|
+
io.stdout(analyticsChartsTemplatesHelp());
|
|
5792
|
+
}
|
|
5506
5793
|
else if (command.topic === "app analytics charts create") {
|
|
5507
5794
|
io.stdout(analyticsChartsCreateHelp());
|
|
5508
5795
|
}
|
|
@@ -5601,6 +5888,9 @@ export async function runTenderCli(args, io = {
|
|
|
5601
5888
|
if (command.command === "app analytics export query") {
|
|
5602
5889
|
return await runAnalyticsExportQuery(command, io, runtime);
|
|
5603
5890
|
}
|
|
5891
|
+
if (command.command === "app analytics charts templates") {
|
|
5892
|
+
return runAnalyticsChartsTemplates(command, io);
|
|
5893
|
+
}
|
|
5604
5894
|
if (command.command === "app analytics charts create") {
|
|
5605
5895
|
return await runAnalyticsChartsCreate(command, io, runtime);
|
|
5606
5896
|
}
|