@thinkingai/ae-cli 6.0.52 → 6.0.54
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 +35 -10
- package/README.zh.md +32 -10
- package/bin/ae-cli.js +6 -1
- package/cli-installation-guide.md +91 -0
- package/dist/{auth-XZNXFRJS.js → auth-MBWRZTB6.js} +171 -13
- package/dist/automation-NWWVLWG2.js +459 -0
- package/dist/{capability-RJZ4KRGP.js → capability-7SSN6PNZ.js} +11 -6
- package/dist/chunk-4655PUNX.js +43 -0
- package/dist/{chunk-4NRCTUZJ.js → chunk-5XJYLEVC.js} +4 -4
- package/dist/{chunk-JOCDD4ON.js → chunk-7QXISROD.js} +1 -1
- package/dist/{chunk-EQ255HKO.js → chunk-AP7YP2NX.js} +2 -2
- package/dist/{chunk-DVMLWQD4.js → chunk-CT7QDJS6.js} +2 -2
- package/dist/chunk-D6ACFILC.js +56 -0
- package/dist/{chunk-HFGZGYCG.js → chunk-EOYSKMXN.js} +264 -10
- package/dist/{chunk-57RRFUEZ.js → chunk-FMNNGNYO.js} +43 -8
- package/dist/{chunk-7XGFSUOM.js → chunk-GIK6EDUG.js} +291 -84
- package/dist/{chunk-WEPZ5M3Z.js → chunk-HBLK3ZHW.js} +7 -4
- package/dist/chunk-HVHR4SCP.js +133 -0
- package/dist/{chunk-DX5CDO34.js → chunk-KFNMQTZI.js} +580 -214
- package/dist/{chunk-HBGADCKA.js → chunk-PLE722AJ.js} +28 -11
- package/dist/chunk-RK6GLDGI.js +27 -0
- package/dist/{chunk-V2NUHPXF.js → chunk-S6M42KND.js} +1 -1
- package/dist/{chunk-7FTTULED.js → chunk-UQ77JXYH.js} +7 -3
- package/dist/{chunk-MAPZ7VB6.js → chunk-WNGFSIOB.js} +20 -1
- package/dist/{chunk-L2QUIZTS.js → chunk-ZIQWCZTS.js} +3 -3
- package/dist/{community-report-client-CU22W53K.js → community-report-client-PEERQCX2.js} +1 -1
- package/dist/{config-XO3LI3SA.js → config-FF6YVJKI.js} +29 -10
- package/dist/context-YAE3QXP3.js +136 -0
- package/dist/{data-integration-HNGUKFIC.js → data-integration-HESZET7E.js} +6 -6
- package/dist/index.js +169 -55
- package/dist/{local-data-upload-client-GTRIT64F.js → local-data-upload-client-TWMHFLUA.js} +1 -1
- package/dist/memory-62BJOULV.js +580 -0
- package/dist/{metadata-JAQW7KGZ.js → metadata-7CUMWIB4.js} +7 -7
- package/dist/{model-RNPQXIBI.js → model-SBV2JFJI.js} +9 -5
- package/dist/{personal-semantic-preference-QCZ2IZTK.js → personal-semantic-preference-6SRCYPGE.js} +119 -11
- package/dist/{project-semantic-64JURXKF.js → project-semantic-YYEM4OSU.js} +7 -7
- package/dist/{sync-O45NXEQY.js → sync-SU33KYX7.js} +12 -8
- package/dist/{te-agent-K5MSPNHJ.js → te-agent-F5QBZSQA.js} +423 -494
- package/dist/{te-analysis-KQKCAI5H.js → te-analysis-U4I2W2WC.js} +1090 -67
- package/dist/{te-community-4OYU3BDA.js → te-community-PFLDLPP4.js} +3 -3
- package/dist/{te-dataops-NFIPB6FX.js → te-dataops-FOQSRIAZ.js} +644 -276
- package/dist/{te-engage-HSVSRW22.js → te-engage-ZX76CNAB.js} +6 -6
- package/dist/{te-kb-3TS73NO6.js → te-kb-MHDOST62.js} +666 -244
- package/dist/{te-system-STMHLS5J.js → te-system-J2FQF5ER.js} +6 -6
- package/dist/{te-team-3I5AOX3N.js → te-team-5UOZPTU3.js} +6 -6
- package/dist/things-VPPXXLHB.js +1091 -0
- package/dist/{update-RZXLPCRH.js → update-EEUTEI6R.js} +59 -51
- package/dist/workspace-O3EEIYQM.js +554 -0
- package/package.json +30 -11
- package/skills/ae-agent/SKILL.md +95 -140
- package/skills/ae-agent/references/add-model.md +1 -1
- package/skills/ae-agent/references/create-agent.md +1 -1
- package/skills/ae-agent/references/find-archived-conversations.md +12 -5
- package/skills/ae-agent/references/get-agent.md +1 -1
- package/skills/ae-agent/references/list-agents.md +2 -2
- package/skills/ae-agent/references/list-models.md +2 -2
- package/skills/ae-agent/references/notification.md +40 -0
- package/skills/ae-agent/references/restore-conversation.md +3 -1
- package/skills/ae-analysis/SKILL.md +76 -15
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +2 -0
- package/skills/ae-analysis/references/ai_models/event.md +6 -1
- package/skills/ae-analysis/references/ai_models/funnel.md +12 -4
- package/skills/ae-analysis/references/ai_models/heat_map.md +23 -0
- package/skills/ae-analysis/references/ai_models/interval.md +24 -0
- package/skills/ae-analysis/references/ai_models/path.md +20 -0
- package/skills/ae-analysis/references/ai_models/prop_analysis.md +2 -0
- package/skills/ae-analysis/references/ai_models/rank_list.md +30 -0
- package/skills/ae-analysis/references/ai_models/retention.md +45 -1
- package/skills/ae-analysis/references/ai_models/revenue.md +20 -2
- package/skills/ae-analysis/references/ai_models/tag.md +2 -0
- package/skills/ae-analysis/references/ai_models.md +96 -0
- package/skills/ae-analysis/references/analysis_data_retrieval.md +4 -0
- package/skills/ae-analysis/references/asset_batch_info_export.md +10 -0
- package/skills/ae-analysis/references/asset_batch_sql_export.md +13 -1
- package/skills/ae-analysis/references/asset_export.md +12 -1
- package/skills/ae-analysis/references/asset_list.md +1 -0
- package/skills/ae-analysis/references/asset_search.md +11 -5
- package/skills/ae-analysis/references/bi_panel_list.md +1 -1
- package/skills/ae-analysis/references/catalog_list.md +1 -1
- package/skills/ae-analysis/references/collaboration.md +48 -0
- package/skills/ae-analysis/references/command_index.md +26 -17
- package/skills/ae-analysis/references/dashboard_list.md +4 -4
- package/skills/ae-analysis/references/dashboard_move.md +21 -0
- package/skills/ae-analysis/references/dashboard_report_add.md +2 -0
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/dashboard_report_get.md +19 -0
- package/skills/ae-analysis/references/dashboard_report_update.md +27 -0
- package/skills/ae-analysis/references/dashboard_update.md +1 -1
- package/skills/ae-analysis/references/event_export.md +3 -1
- package/skills/ae-analysis/references/event_report_presentation.md +76 -0
- package/skills/ae-analysis/references/feedback_submit.md +37 -0
- package/skills/ae-analysis/references/governance_recommendation_auto_review.md +71 -0
- package/skills/ae-analysis/references/governance_recommendation_export.md +11 -0
- package/skills/ae-analysis/references/metadata_resolution.md +18 -3
- package/skills/ae-analysis/references/metric_export.md +3 -1
- package/skills/ae-analysis/references/metric_list.md +1 -1
- package/skills/ae-analysis/references/operation_record_export.md +10 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +2 -2
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +6 -4
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +5 -3
- package/skills/ae-analysis/references/personal_semantic_preference_review.md +9 -0
- package/skills/ae-analysis/references/personal_semantic_preference_review_list.md +7 -0
- package/skills/ae-analysis/references/personal_semantic_preference_submit.md +7 -0
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +91 -32
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +99 -1
- package/skills/ae-analysis/references/property_export.md +3 -1
- package/skills/ae-analysis/references/report_create.md +17 -3
- package/skills/ae-analysis/references/report_data_export.md +6 -0
- package/skills/ae-analysis/references/report_get.md +7 -1
- package/skills/ae-analysis/references/report_list.md +5 -5
- package/skills/ae-analysis/references/report_update.md +20 -3
- package/skills/ae-analysis/references/sql_table_columns.md +4 -4
- package/skills/ae-analysis/references/sql_table_list.md +5 -5
- package/skills/ae-analysis/references/system_query_monitor_overview.md +2 -0
- package/skills/ae-analysis/references/system_query_task_cancel.md +2 -0
- package/skills/ae-analysis/references/system_query_task_export.md +6 -2
- package/skills/ae-analysis/references/system_query_task_get.md +2 -0
- package/skills/ae-analysis/references/system_query_task_list.md +7 -3
- package/skills/ae-analysis/references/system_query_task_options.md +2 -2
- package/skills/ae-analysis/references/system_query_task_realtime_list.md +15 -0
- package/skills/ae-analysis/references/user_cluster_models.md +8 -0
- package/skills/ae-analysis/references/user_tag_create.md +7 -1
- package/skills/ae-analysis/references/user_tag_get.md +1 -1
- package/skills/ae-analysis/references/user_tag_models.md +20 -2
- package/skills/ae-analysis/references/user_tag_refresh.md +1 -1
- package/skills/ae-analysis/references/user_tag_update.md +2 -2
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-empty-skeleton.mjs +105 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +669 -29
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +21 -8
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-rules.md +28 -10
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-schema.md +66 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +285 -24
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs +262 -30
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/plan-kb-source-sync.mjs +1 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/precompiled-source.mjs +46 -2
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/prepare-compile-schema.mjs +64 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/refresh-state-parts.mjs +91 -0
- package/skills/ae-automation/SKILL.md +16 -0
- package/skills/ae-automation/references/cli.md +53 -0
- package/skills/ae-automation/references/command_index.md +17 -0
- package/skills/ae-capability/SKILL.md +73 -2
- package/skills/ae-capability/references/collaboration.md +48 -0
- package/skills/ae-community/SKILL.md +5 -1
- package/skills/ae-community/references/collaboration.md +48 -0
- package/skills/ae-current-context/SKILL.md +3 -2
- package/skills/ae-data-integration/SKILL.md +4 -0
- package/skills/ae-data-integration/references/collaboration.md +48 -0
- package/skills/ae-dataops/SKILL.md +54 -74
- package/skills/ae-dataops/references/collaboration.md +48 -0
- package/skills/ae-dataops/references/dataops-backfill.md +23 -18
- package/skills/ae-dataops/references/dataops-flow-create.md +74 -23
- package/skills/ae-dataops/references/dataops-flow-monitor.md +45 -13
- package/skills/ae-dataops/references/dataops-integration.md +57 -30
- package/skills/ae-dataops/references/dataops-query.md +21 -4
- package/skills/ae-dataops/references/dataops-table.md +143 -11
- package/skills/ae-engage/SKILL.md +21 -6
- package/skills/ae-engage/references/channel-mgmt.md +3 -3
- package/skills/ae-engage/references/collaboration.md +48 -0
- package/skills/ae-engage/references/scene-config-channel.md +4 -4
- package/skills/ae-generate-tracking-plan/SKILL.md +4 -0
- package/skills/ae-generate-tracking-plan/references/collaboration.md +48 -0
- package/skills/ae-kb/SKILL.md +70 -12
- package/skills/ae-kb/references/analysis-workflow.md +73 -36
- package/skills/ae-kb/references/collaboration.md +48 -0
- package/skills/ae-kb/references/query-workflow.md +67 -33
- package/skills/ae-kb/references/schema-import.md +32 -0
- package/skills/ae-kb/references/source-mutations.md +6 -4
- package/skills/ae-kb/references/text-sources.md +53 -0
- package/skills/ae-kb-discovery/SKILL.md +8 -3
- package/skills/ae-kb-discovery/references/collaboration.md +48 -0
- package/skills/ae-metadata/SKILL.md +20 -12
- package/skills/ae-metadata/references/collaboration.md +48 -0
- package/skills/ae-team/SKILL.md +23 -17
- package/skills/ae-things/SKILL.md +85 -0
- package/skills/ae-things/references/cli.md +103 -0
- package/skills/ae-things-progress/SKILL.md +43 -0
- package/skills/ae-things-review/SKILL.md +42 -0
- package/skills/ae-workspace/SKILL.md +43 -0
- package/skills/ae-workspace/references/commands.md +51 -0
- package/dist/chunk-E2JKXMVO.js +0 -29
- package/dist/context-IFJI3LIT.js +0 -46
- package/dist/memory-QGPSNCQS.js +0 -892
- package/skills/ae-agent/references/create-automation.md +0 -125
- package/skills/ae-agent/references/list-automations.md +0 -56
- package/skills/ae-agent/references/update-automation.md +0 -107
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
waitForAnalysisRun,
|
|
8
8
|
withAsyncArtifactLifecycle,
|
|
9
9
|
withInterruptSignal
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HBLK3ZHW.js";
|
|
11
11
|
import {
|
|
12
12
|
createCapabilityCommand,
|
|
13
13
|
definitionIntentSnapshotFlag,
|
|
14
14
|
modelDefinitionIntentSnapshotFlag
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ZIQWCZTS.js";
|
|
16
16
|
import {
|
|
17
17
|
registerCapabilityGatewayRoute,
|
|
18
18
|
resolveGatewayDomain
|
|
@@ -23,22 +23,25 @@ import {
|
|
|
23
23
|
dryRunCapability,
|
|
24
24
|
executeCapability,
|
|
25
25
|
executeCapabilityWithEnvelope,
|
|
26
|
+
readCliAgentContext,
|
|
26
27
|
requestCapabilityGateway,
|
|
27
28
|
requestCapabilityGatewayWithEnvelope,
|
|
29
|
+
runWithCliAgentContext,
|
|
28
30
|
uploadInputFile,
|
|
29
|
-
validateCapability
|
|
30
|
-
|
|
31
|
+
validateCapability,
|
|
32
|
+
validateCapabilityWithEnvelope
|
|
33
|
+
} from "./chunk-EOYSKMXN.js";
|
|
31
34
|
import {
|
|
32
35
|
withOutputMetadata
|
|
33
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-KFNMQTZI.js";
|
|
34
37
|
import "./chunk-Y74WTIKJ.js";
|
|
35
38
|
import {
|
|
36
39
|
getCliToken
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
40
|
+
} from "./chunk-GIK6EDUG.js";
|
|
41
|
+
import "./chunk-UQ77JXYH.js";
|
|
39
42
|
import {
|
|
40
43
|
CliValidationError
|
|
41
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-WNGFSIOB.js";
|
|
42
45
|
|
|
43
46
|
// src/commands/te-analysis/capability-shared.ts
|
|
44
47
|
var ANALYSIS_GATEWAY_CLI_SERVICES = /* @__PURE__ */ new Set(["project", "system"]);
|
|
@@ -148,7 +151,7 @@ var sqlTableUsageFlag = {
|
|
|
148
151
|
name: "usage",
|
|
149
152
|
type: "string",
|
|
150
153
|
required: false,
|
|
151
|
-
desc: "Authorized table set: analysis (default) or
|
|
154
|
+
desc: "Authorized table set: analysis (default), tag_cluster for SQL tags/clusters, or sql_datatable for SQL-built data tables. Use the same usage for list and columns."
|
|
152
155
|
};
|
|
153
156
|
var reportListLimitFlag = {
|
|
154
157
|
name: "limit",
|
|
@@ -288,7 +291,7 @@ function certificationScopeInput(ctx) {
|
|
|
288
291
|
}
|
|
289
292
|
return value;
|
|
290
293
|
}
|
|
291
|
-
function dashboardReportDataInput(ctx) {
|
|
294
|
+
function dashboardReportDataInput(ctx, includeCache = true) {
|
|
292
295
|
return compactInput({
|
|
293
296
|
...projectInput(ctx),
|
|
294
297
|
dashboard_id: ctx.num("dashboard-id"),
|
|
@@ -299,7 +302,7 @@ function dashboardReportDataInput(ctx) {
|
|
|
299
302
|
cluster_query_scope: optionalString(ctx, "cluster-query-scope"),
|
|
300
303
|
slave_cluster_id: optionalString(ctx, "slave-cluster-id"),
|
|
301
304
|
zone_offset: optionalNumber(ctx, "zone-offset"),
|
|
302
|
-
use_cache: optionalBoolean(ctx, "use-cache"),
|
|
305
|
+
...includeCache ? { use_cache: optionalBoolean(ctx, "use-cache") } : {},
|
|
303
306
|
request_id: optionalString(ctx, "request-id"),
|
|
304
307
|
preview_rows: optionalNumber(ctx, "preview-rows"),
|
|
305
308
|
timeout_seconds: optionalNumber(ctx, "timeout-seconds"),
|
|
@@ -756,6 +759,7 @@ var metadataEventExport = createAnalysisMetaCapabilityCommand({
|
|
|
756
759
|
queriesFlag,
|
|
757
760
|
fieldsFlag,
|
|
758
761
|
{ name: "authenticated-only", type: "boolean", required: false, desc: "When true, export only authenticated events." },
|
|
762
|
+
certificationScopeFlag,
|
|
759
763
|
metadataExportOutputFlag
|
|
760
764
|
],
|
|
761
765
|
risk: "read",
|
|
@@ -764,7 +768,8 @@ var metadataEventExport = createAnalysisMetaCapabilityCommand({
|
|
|
764
768
|
...projectInput(ctx),
|
|
765
769
|
queries: optionalQueries(ctx),
|
|
766
770
|
fields: optionalJson(ctx, "fields"),
|
|
767
|
-
authenticated_only: optionalBoolean(ctx, "authenticated-only")
|
|
771
|
+
authenticated_only: optionalBoolean(ctx, "authenticated-only"),
|
|
772
|
+
certification_scope: certificationScopeInput(ctx)
|
|
768
773
|
}),
|
|
769
774
|
postProcess: metadataExportPostProcess("event", "events")
|
|
770
775
|
});
|
|
@@ -947,6 +952,7 @@ var metadataPropertyExport = createAnalysisMetaCapabilityCommand({
|
|
|
947
952
|
queriesFlag,
|
|
948
953
|
fieldsFlag,
|
|
949
954
|
{ name: "authenticated-only", type: "boolean", required: false, desc: "When true, export only authenticated properties." },
|
|
955
|
+
certificationScopeFlag,
|
|
950
956
|
metadataExportOutputFlag
|
|
951
957
|
],
|
|
952
958
|
risk: "read",
|
|
@@ -958,7 +964,8 @@ var metadataPropertyExport = createAnalysisMetaCapabilityCommand({
|
|
|
958
964
|
event_name: optionalString(ctx, "event-name"),
|
|
959
965
|
queries: optionalQueries(ctx),
|
|
960
966
|
fields: optionalJson(ctx, "fields"),
|
|
961
|
-
authenticated_only: optionalBoolean(ctx, "authenticated-only")
|
|
967
|
+
authenticated_only: optionalBoolean(ctx, "authenticated-only"),
|
|
968
|
+
certification_scope: certificationScopeInput(ctx)
|
|
962
969
|
}),
|
|
963
970
|
postProcess: metadataExportPostProcess("property", "properties")
|
|
964
971
|
});
|
|
@@ -1350,6 +1357,7 @@ var metadataMetricExport = createAnalysisMetaCapabilityCommand({
|
|
|
1350
1357
|
queriesFlag,
|
|
1351
1358
|
fieldsFlag,
|
|
1352
1359
|
{ name: "authenticated-only", type: "boolean", required: false, desc: "When true, export only authenticated metrics." },
|
|
1360
|
+
certificationScopeFlag,
|
|
1353
1361
|
metadataExportOutputFlag
|
|
1354
1362
|
],
|
|
1355
1363
|
risk: "read",
|
|
@@ -1359,7 +1367,8 @@ var metadataMetricExport = createAnalysisMetaCapabilityCommand({
|
|
|
1359
1367
|
ignore_authentication: optionalBoolean(ctx, "ignore-authentication"),
|
|
1360
1368
|
queries: optionalQueries(ctx),
|
|
1361
1369
|
fields: optionalJson(ctx, "fields"),
|
|
1362
|
-
authenticated_only: optionalBoolean(ctx, "authenticated-only")
|
|
1370
|
+
authenticated_only: optionalBoolean(ctx, "authenticated-only"),
|
|
1371
|
+
certification_scope: certificationScopeInput(ctx)
|
|
1363
1372
|
}),
|
|
1364
1373
|
postProcess: metadataExportPostProcess("metric", "metrics")
|
|
1365
1374
|
});
|
|
@@ -1500,13 +1509,13 @@ var ownTypesFlag = {
|
|
|
1500
1509
|
var requiredQueriesFlag = {
|
|
1501
1510
|
...queriesFlag,
|
|
1502
1511
|
required: true,
|
|
1503
|
-
desc: "Required JSON array of 1 to 20 keyword filters. For first-pass asset discovery, use one broad search without --asset-types
|
|
1512
|
+
desc: "Required JSON array of 1 to 20 keyword filters. For first-pass asset discovery, use one broad search without --asset-types and request a large page; when has_more is true and no strong candidate is present, continue with next_offset before narrowing or rewriting keywords."
|
|
1504
1513
|
};
|
|
1505
1514
|
var analysisAssetSearch = createAnalysisCapabilityCommand({
|
|
1506
1515
|
resource: "asset",
|
|
1507
1516
|
command: "search",
|
|
1508
1517
|
capabilityId: "analysis.asset.search",
|
|
1509
|
-
description: "Search
|
|
1518
|
+
description: "Search readable saved analysis assets by keyword, including shared read-only and editable dashboards and reports. Results are ranked before pagination by match quality, certification, recent heat/users, and governance impact. Omit --asset-types for first-pass discovery.",
|
|
1510
1519
|
flags: [
|
|
1511
1520
|
projectIdFlag,
|
|
1512
1521
|
requiredQueriesFlag,
|
|
@@ -1635,7 +1644,16 @@ var statusFlag = { name: "status", type: "json", required: false, desc: "Operati
|
|
|
1635
1644
|
var sortFieldFlag = { name: "sort-field", type: "string", required: false, desc: "Sort field." };
|
|
1636
1645
|
var sortOrderFlag = { name: "sort-order", type: "string", required: false, desc: "Sort order: asc or desc." };
|
|
1637
1646
|
var recordIdFlag = { name: "record-id", type: "number", required: false, desc: "Operation record ID." };
|
|
1647
|
+
var governanceExportFlags = (format) => [
|
|
1648
|
+
requestIdFlag,
|
|
1649
|
+
{ ...artifactFormatFlag, desc: `Artifact format: ${format}. This capability supports only ${format}.` },
|
|
1650
|
+
{ ...asyncTimeoutSecondsFlag, max: 7200, desc: "Async export runtime in seconds. Default: 3600, max: 7200." }
|
|
1651
|
+
];
|
|
1652
|
+
var governanceExportFields = ["request_id", "format", "timeout_seconds"];
|
|
1638
1653
|
var readers = {
|
|
1654
|
+
request_id: (ctx) => optionalString(ctx, "request-id"),
|
|
1655
|
+
format: (ctx) => optionalString(ctx, "artifact-format"),
|
|
1656
|
+
timeout_seconds: (ctx) => optionalNumber(ctx, "timeout-seconds"),
|
|
1639
1657
|
node_id: (ctx) => optionalString(ctx, "node-id"),
|
|
1640
1658
|
resource_id: (ctx) => optionalString(ctx, "resource-id"),
|
|
1641
1659
|
resource_type: (ctx) => optionalString(ctx, "resource-type"),
|
|
@@ -2238,6 +2256,722 @@ var metadataGovernanceRecommendationSubmit = createAnalysisMetaCapabilityCommand
|
|
|
2238
2256
|
})
|
|
2239
2257
|
});
|
|
2240
2258
|
|
|
2259
|
+
// src/commands/te-analysis/meta/governance-recommendation/auto-review.ts
|
|
2260
|
+
import { randomUUID } from "crypto";
|
|
2261
|
+
var windowDaysFlag3 = {
|
|
2262
|
+
name: "window-days",
|
|
2263
|
+
type: "number",
|
|
2264
|
+
required: false,
|
|
2265
|
+
min: 1,
|
|
2266
|
+
max: 365,
|
|
2267
|
+
desc: "Usage window in days for the recommendation batch. Default: 90."
|
|
2268
|
+
};
|
|
2269
|
+
var limitFlag4 = {
|
|
2270
|
+
name: "limit",
|
|
2271
|
+
type: "number",
|
|
2272
|
+
required: false,
|
|
2273
|
+
min: 1,
|
|
2274
|
+
max: 100,
|
|
2275
|
+
desc: "Maximum hot dashboard evidence packages selected before automatic asset review. Omit for CLI bounded expansion over top-20/top-50/top-100; pass explicitly for a fixed diagnostic scope."
|
|
2276
|
+
};
|
|
2277
|
+
var GOVERNANCE_RECOMMENDATION_AUTO_REVIEW_HELP = [
|
|
2278
|
+
"Automatic asset certification contract:",
|
|
2279
|
+
"- Use this command only when the user explicitly asks to automatically review or automatically certify recommended assets.",
|
|
2280
|
+
"- Do not call this command for a plain recommendation request.",
|
|
2281
|
+
"- Do not call this command when the user asks to submit recommendations to the review page.",
|
|
2282
|
+
"- The command first validates project config agent_auto_asset_certification_enabled and project_semantic_enable. If disabled, report the returned config error and stop before collecting recommendations.",
|
|
2283
|
+
"- When --limit is omitted, the CLI performs the same bounded expansion used by recurring page-review jobs: inspect top-20 pending material, then top-50/top-100 only when pending assets or pending dashboard branches are insufficient.",
|
|
2284
|
+
"- Expansion is read-only. The CLI Agent builds automatic decisions once from the final selected material, then submits those decisions for execution and audit.",
|
|
2285
|
+
"- When --limit is explicitly provided, respect that scope and do not expand it.",
|
|
2286
|
+
"- Automatic review only certifies eligible asset candidates from the current recommendation batch. It does not create recommended metrics.",
|
|
2287
|
+
"- CLI Agent blocks semantic duplicates, copy-like assets, synonym properties and ambiguous close definitions; every duplicate skip must name the conflicting asset targets.",
|
|
2288
|
+
"- The result includes manual_review_handoff for assets still uncertified after automatic review. Use it only when the user later asks to submit those assets to the review page.",
|
|
2289
|
+
"- For that later page submission, build the review packet from manual_review_handoff.page_review_items and relations so skipped assets keep their dashboard/report parent context; manual_review_handoff.items remains the exact unapproved review workload.",
|
|
2290
|
+
"- Automatic decisions are recorded for audit. Page-visible reasons must be reviewer-readable Chinese; keep raw source/rule codes only in debug exports.",
|
|
2291
|
+
"- Returned SKIP decisions mean the asset remains for manual review; do not describe skipped items as certified."
|
|
2292
|
+
].join("\n");
|
|
2293
|
+
var AUTO_REVIEW_CAPABILITY_ID = "metadata.governance_recommendation.auto_review";
|
|
2294
|
+
var EXPORT_CAPABILITY_ID = "metadata.governance_recommendation.export";
|
|
2295
|
+
var SUBMIT_CAPABILITY_ID = "metadata.governance_recommendation.submit";
|
|
2296
|
+
var DEFAULT_LIMIT = 20;
|
|
2297
|
+
var EXPANSION_LIMITS = [20, 50, 100];
|
|
2298
|
+
var MIN_PENDING_ASSETS = 10;
|
|
2299
|
+
var MIN_PENDING_WORK_UNITS = 3;
|
|
2300
|
+
var AUTO_REVIEW_DECISION_LIMIT = 100;
|
|
2301
|
+
var AUTO_REVIEW_MIN_HEAT = 50;
|
|
2302
|
+
var AUTO_REVIEW_MIN_USERS = 5;
|
|
2303
|
+
var AUTO_REVIEW_MIN_IMPACT = 2;
|
|
2304
|
+
var metadataGovernanceRecommendationAutoReview = {
|
|
2305
|
+
service: "analysis-meta",
|
|
2306
|
+
resource: "governance-recommendation",
|
|
2307
|
+
command: "auto-review",
|
|
2308
|
+
capabilityId: AUTO_REVIEW_CAPABILITY_ID,
|
|
2309
|
+
description: "Automatically review and certify eligible recommended assets when the project switch is enabled.",
|
|
2310
|
+
helpText: GOVERNANCE_RECOMMENDATION_AUTO_REVIEW_HELP,
|
|
2311
|
+
flags: [projectIdFlag, windowDaysFlag3, limitFlag4],
|
|
2312
|
+
risk: "write",
|
|
2313
|
+
preflight: (ctx) => {
|
|
2314
|
+
autoReviewInput(ctx);
|
|
2315
|
+
},
|
|
2316
|
+
validateInput: async (ctx) => validateCapability(
|
|
2317
|
+
ctx.host(),
|
|
2318
|
+
gatewayDomain(),
|
|
2319
|
+
AUTO_REVIEW_CAPABILITY_ID,
|
|
2320
|
+
autoReviewInput(ctx)
|
|
2321
|
+
),
|
|
2322
|
+
dryRun: async (ctx) => dryRunCapability(
|
|
2323
|
+
ctx.host(),
|
|
2324
|
+
gatewayDomain(),
|
|
2325
|
+
AUTO_REVIEW_CAPABILITY_ID,
|
|
2326
|
+
autoReviewInput(ctx)
|
|
2327
|
+
),
|
|
2328
|
+
execute: async (ctx) => withAutoReviewAgentContext(async () => {
|
|
2329
|
+
const input = autoReviewInput(ctx);
|
|
2330
|
+
if (hasExplicitLimit(ctx)) {
|
|
2331
|
+
await validateCapabilityWithEnvelope(ctx.host(), gatewayDomain(), AUTO_REVIEW_CAPABILITY_ID, input);
|
|
2332
|
+
const finalExport = await exportRecommendationMaterial(ctx, input, numberValue(input.limit) || DEFAULT_LIMIT);
|
|
2333
|
+
const result2 = await executeCliAgentAutoReview(ctx, input, finalExport.data);
|
|
2334
|
+
return withOutputMetadata({
|
|
2335
|
+
...record(result2.data),
|
|
2336
|
+
manual_review_handoff: buildManualReviewHandoff(result2.data, finalExport.data)
|
|
2337
|
+
}, result2.meta);
|
|
2338
|
+
}
|
|
2339
|
+
const plan = await planBoundedExpansion(ctx, input);
|
|
2340
|
+
const expansion = plan.expansion;
|
|
2341
|
+
const finalInput = { ...input, limit: expansion.final_limit };
|
|
2342
|
+
const result = await executeCliAgentAutoReview(ctx, finalInput, plan.finalExport);
|
|
2343
|
+
if (result.data && typeof result.data === "object" && !Array.isArray(result.data)) {
|
|
2344
|
+
return withOutputMetadata({
|
|
2345
|
+
...result.data,
|
|
2346
|
+
auto_review_expansion: expansion,
|
|
2347
|
+
manual_review_handoff: buildManualReviewHandoff(result.data, plan.finalExport)
|
|
2348
|
+
}, result.meta);
|
|
2349
|
+
}
|
|
2350
|
+
return withOutputMetadata(result.data, result.meta);
|
|
2351
|
+
})
|
|
2352
|
+
};
|
|
2353
|
+
async function withAutoReviewAgentContext(run) {
|
|
2354
|
+
const inherited = readCliAgentContext();
|
|
2355
|
+
return runWithCliAgentContext({
|
|
2356
|
+
agent_session_id: inherited.agent_session_id || randomUUID(),
|
|
2357
|
+
agent_turn_id: inherited.agent_turn_id || randomUUID()
|
|
2358
|
+
}, run);
|
|
2359
|
+
}
|
|
2360
|
+
function autoReviewInput(ctx) {
|
|
2361
|
+
return compactInput({
|
|
2362
|
+
...projectInput(ctx),
|
|
2363
|
+
window_days: optionalNumber(ctx, "window-days"),
|
|
2364
|
+
limit: optionalNumber(ctx, "limit")
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
function gatewayDomain() {
|
|
2368
|
+
return resolveGatewayDomain("analysis-meta", "analysis");
|
|
2369
|
+
}
|
|
2370
|
+
function hasExplicitLimit(ctx) {
|
|
2371
|
+
return typeof ctx.has === "function" ? ctx.has("limit") : ctx.str("limit") !== "";
|
|
2372
|
+
}
|
|
2373
|
+
async function executeCliAgentAutoReview(ctx, input, exportResult) {
|
|
2374
|
+
const review = buildCliAgentAutoReview(input, exportResult);
|
|
2375
|
+
if (review.decisions.length === 0) {
|
|
2376
|
+
return {
|
|
2377
|
+
data: {
|
|
2378
|
+
...review.base,
|
|
2379
|
+
total: 0,
|
|
2380
|
+
applied: 0,
|
|
2381
|
+
recorded: 0,
|
|
2382
|
+
failed: 0,
|
|
2383
|
+
items: []
|
|
2384
|
+
},
|
|
2385
|
+
meta: {}
|
|
2386
|
+
};
|
|
2387
|
+
}
|
|
2388
|
+
const submitted = await executeCapabilityWithEnvelope(ctx.host(), gatewayDomain(), SUBMIT_CAPABILITY_ID, {
|
|
2389
|
+
...input,
|
|
2390
|
+
run_id: review.runId,
|
|
2391
|
+
snapshot_hash: review.snapshotHash,
|
|
2392
|
+
topic_id: "agent_auto_asset_certification",
|
|
2393
|
+
topic_name: "Agent \u81EA\u52A8\u8BA4\u8BC1\u8D44\u4EA7",
|
|
2394
|
+
decisions: review.decisions
|
|
2395
|
+
});
|
|
2396
|
+
const submittedData = record(submitted.data);
|
|
2397
|
+
return {
|
|
2398
|
+
data: {
|
|
2399
|
+
...review.base,
|
|
2400
|
+
total: submittedData.total,
|
|
2401
|
+
applied: submittedData.applied,
|
|
2402
|
+
recorded: submittedData.recorded,
|
|
2403
|
+
failed: submittedData.failed,
|
|
2404
|
+
items: autoReviewItemsWithDisplayReason(submittedData.items)
|
|
2405
|
+
},
|
|
2406
|
+
meta: submitted.meta
|
|
2407
|
+
};
|
|
2408
|
+
}
|
|
2409
|
+
async function planBoundedExpansion(ctx, input) {
|
|
2410
|
+
await validateCapabilityWithEnvelope(ctx.host(), gatewayDomain(), AUTO_REVIEW_CAPABILITY_ID, {
|
|
2411
|
+
...input,
|
|
2412
|
+
limit: DEFAULT_LIMIT
|
|
2413
|
+
});
|
|
2414
|
+
const attempts = [];
|
|
2415
|
+
let finalExport = {};
|
|
2416
|
+
let finalLimit = DEFAULT_LIMIT;
|
|
2417
|
+
let stopReason = "top_100_inspected";
|
|
2418
|
+
for (const limit of EXPANSION_LIMITS) {
|
|
2419
|
+
const exported = await exportRecommendationMaterial(ctx, input, limit);
|
|
2420
|
+
finalExport = exported.data;
|
|
2421
|
+
const summary = summarizeExport(exported.data, limit);
|
|
2422
|
+
attempts.push(summary);
|
|
2423
|
+
finalLimit = limit;
|
|
2424
|
+
const pendingAssets = numberValue(summary.pending_asset_candidates);
|
|
2425
|
+
const pendingWorkUnits = numberValue(summary.pending_work_units);
|
|
2426
|
+
const hasMore = summary.has_more === true;
|
|
2427
|
+
if (pendingAssets >= MIN_PENDING_ASSETS && pendingWorkUnits >= MIN_PENDING_WORK_UNITS) {
|
|
2428
|
+
stopReason = "sufficient_pending_scope";
|
|
2429
|
+
break;
|
|
2430
|
+
}
|
|
2431
|
+
if (!hasMore) {
|
|
2432
|
+
stopReason = "dashboard_pool_exhausted";
|
|
2433
|
+
break;
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
return {
|
|
2437
|
+
expansion: {
|
|
2438
|
+
strategy: "bounded_hot_dashboard_expansion",
|
|
2439
|
+
initial_limit: DEFAULT_LIMIT,
|
|
2440
|
+
final_limit: finalLimit,
|
|
2441
|
+
inspected_limits: attempts.map((attempt) => attempt.dashboard_limit),
|
|
2442
|
+
min_pending_asset_candidates: MIN_PENDING_ASSETS,
|
|
2443
|
+
min_pending_work_units: MIN_PENDING_WORK_UNITS,
|
|
2444
|
+
attempts,
|
|
2445
|
+
stop_reason: stopReason,
|
|
2446
|
+
write_policy: "single_auto_review_execute_after_read_only_expansion"
|
|
2447
|
+
},
|
|
2448
|
+
finalExport
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2451
|
+
function exportRecommendationMaterial(ctx, input, limit) {
|
|
2452
|
+
return executeCapabilityWithEnvelope(
|
|
2453
|
+
ctx.host(),
|
|
2454
|
+
gatewayDomain(),
|
|
2455
|
+
EXPORT_CAPABILITY_ID,
|
|
2456
|
+
compactInput({ ...input, limit, include_completed: false })
|
|
2457
|
+
);
|
|
2458
|
+
}
|
|
2459
|
+
function summarizeExport(result, requestedLimit) {
|
|
2460
|
+
const data = record(result);
|
|
2461
|
+
const workUnits = array(data.work_units);
|
|
2462
|
+
const coverage = record(data.coverage);
|
|
2463
|
+
const pendingAssetCandidates = countPendingAssetCandidates(workUnits);
|
|
2464
|
+
return {
|
|
2465
|
+
dashboard_limit: numberValue(data.dashboard_limit) || requestedLimit,
|
|
2466
|
+
run_id: stringValue(data.run_id),
|
|
2467
|
+
snapshot_hash: stringValue(data.snapshot_hash),
|
|
2468
|
+
selected_dashboards: numberValue(coverage.selected_dashboards),
|
|
2469
|
+
returned_work_units: workUnits.length,
|
|
2470
|
+
pending_work_units: workUnits.filter((unit) => numberValue(record(unit).actionable_count) > 0).length,
|
|
2471
|
+
pending_asset_candidates: pendingAssetCandidates,
|
|
2472
|
+
has_more: coverage.has_more === true
|
|
2473
|
+
};
|
|
2474
|
+
}
|
|
2475
|
+
function countPendingAssetCandidates(workUnits) {
|
|
2476
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2477
|
+
for (const unit of workUnits) {
|
|
2478
|
+
for (const candidate of array(record(unit).asset_candidates)) {
|
|
2479
|
+
const item = record(candidate);
|
|
2480
|
+
if (item.actionable !== true || item.action_state !== "PENDING") {
|
|
2481
|
+
continue;
|
|
2482
|
+
}
|
|
2483
|
+
const type = stringValue(item.resource_type);
|
|
2484
|
+
const key = stringValue(item.resource_key);
|
|
2485
|
+
if (type && key) {
|
|
2486
|
+
seen.add(`${type}|${key}`);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
return seen.size;
|
|
2491
|
+
}
|
|
2492
|
+
function buildCliAgentAutoReview(input, exportResult) {
|
|
2493
|
+
const exported = record(exportResult);
|
|
2494
|
+
const material = record(exported.review_material_package);
|
|
2495
|
+
const candidates = array(material.candidate_assets).map(record);
|
|
2496
|
+
const runId = `rec_auto_${randomUUID().replace(/-/g, "")}`;
|
|
2497
|
+
const snapshotHash = stringValue(exported.snapshot_hash);
|
|
2498
|
+
const semanticConflicts = semanticDuplicateConflicts(candidates);
|
|
2499
|
+
const decisions = [];
|
|
2500
|
+
let approved = 0;
|
|
2501
|
+
let skipped = 0;
|
|
2502
|
+
let overflow = 0;
|
|
2503
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2504
|
+
for (const candidate of candidates) {
|
|
2505
|
+
const target = record(candidate.target_ref);
|
|
2506
|
+
const type = stringValue(target.type);
|
|
2507
|
+
const key = stringValue(target.key);
|
|
2508
|
+
if (!type || !key || !seen.add(`${type}|${key}`)) continue;
|
|
2509
|
+
if (candidate.actionable !== true || candidate.action_state !== "PENDING") continue;
|
|
2510
|
+
if (decisions.length >= AUTO_REVIEW_DECISION_LIMIT) {
|
|
2511
|
+
overflow++;
|
|
2512
|
+
continue;
|
|
2513
|
+
}
|
|
2514
|
+
const verdict = cliAgentAutoReviewVerdict(candidate, semanticConflicts.get(`${type}|${key}`));
|
|
2515
|
+
if (verdict.decision === "APPROVE") approved++;
|
|
2516
|
+
else skipped++;
|
|
2517
|
+
decisions.push({
|
|
2518
|
+
item_type: "asset",
|
|
2519
|
+
decision: verdict.decision,
|
|
2520
|
+
resource_type: type,
|
|
2521
|
+
resource_key: key,
|
|
2522
|
+
evidence_hash: candidate.evidence_hash,
|
|
2523
|
+
reason: verdict.reason
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
return {
|
|
2527
|
+
runId,
|
|
2528
|
+
snapshotHash,
|
|
2529
|
+
decisions,
|
|
2530
|
+
base: {
|
|
2531
|
+
schema_version: "1.0",
|
|
2532
|
+
run_id: runId,
|
|
2533
|
+
project_id: input.project_id ?? exported.project_id,
|
|
2534
|
+
window_days: input.window_days ?? exported.window_days,
|
|
2535
|
+
dashboard_limit: input.limit ?? exported.dashboard_limit,
|
|
2536
|
+
snapshot_hash: snapshotHash,
|
|
2537
|
+
rule_version: "agent_auto_asset_certification_v1",
|
|
2538
|
+
config_key: "agent_auto_asset_certification_enabled",
|
|
2539
|
+
semantic_config_key: "project_semantic_enable",
|
|
2540
|
+
auto_approved: approved,
|
|
2541
|
+
skipped,
|
|
2542
|
+
overflow
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
function cliAgentAutoReviewVerdict(candidate, semanticConflict) {
|
|
2547
|
+
if (semanticConflict) {
|
|
2548
|
+
return {
|
|
2549
|
+
decision: "SKIP",
|
|
2550
|
+
reason: autoReviewReason(`semantic_duplicate_targets=${encodeReasonPayload(semanticConflict)}`)
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2553
|
+
if (listIncludes(candidate.conflict_risks, "same_evidence_rejected_before")) {
|
|
2554
|
+
return {
|
|
2555
|
+
decision: "SKIP",
|
|
2556
|
+
reason: autoReviewReason("same_evidence_rejected_before")
|
|
2557
|
+
};
|
|
2558
|
+
}
|
|
2559
|
+
if (array(candidate.source_evidence).length === 0 && candidate.recommendation_role !== "source_dashboard") {
|
|
2560
|
+
return {
|
|
2561
|
+
decision: "SKIP",
|
|
2562
|
+
reason: autoReviewReason("source_evidence_missing")
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
const heat = numberValue(candidate.heat_count90d);
|
|
2566
|
+
const users = numberValue(candidate.user_count90d);
|
|
2567
|
+
const impact = numberValue(candidate.impact_degree);
|
|
2568
|
+
const matched = [];
|
|
2569
|
+
if (heat >= AUTO_REVIEW_MIN_HEAT) matched.push(`heat_count90d>=${AUTO_REVIEW_MIN_HEAT}`);
|
|
2570
|
+
if (users >= AUTO_REVIEW_MIN_USERS) matched.push(`user_count90d>=${AUTO_REVIEW_MIN_USERS}`);
|
|
2571
|
+
if (impact > AUTO_REVIEW_MIN_IMPACT) matched.push(`impact_degree>${AUTO_REVIEW_MIN_IMPACT}.0`);
|
|
2572
|
+
if (matched.length === 0) {
|
|
2573
|
+
return {
|
|
2574
|
+
decision: "SKIP",
|
|
2575
|
+
reason: autoReviewReason(`signals_below_threshold: heat_count90d=${heat}, user_count90d=${users}, impact_degree=${impact}`)
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
return {
|
|
2579
|
+
decision: "APPROVE",
|
|
2580
|
+
reason: autoReviewReason(`matched=${matched.join(",")}; role=${stringValue(candidate.recommendation_role) ?? "asset"}`)
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
2583
|
+
function autoReviewReason(reason) {
|
|
2584
|
+
return `source=AGENT_AUTO_REVIEW; rule_version=agent_auto_asset_certification_v1; ${reason}`;
|
|
2585
|
+
}
|
|
2586
|
+
function autoReviewItemsWithDisplayReason(items) {
|
|
2587
|
+
return array(items).map((value) => {
|
|
2588
|
+
const item = record(value);
|
|
2589
|
+
const copy = {
|
|
2590
|
+
...item,
|
|
2591
|
+
semantic_duplicate_targets: semanticDuplicateTargetsFromReason(stringValue(item.reason) ?? "")
|
|
2592
|
+
};
|
|
2593
|
+
if (item.decision !== "APPROVE") {
|
|
2594
|
+
copy.display_reason = autoReviewDisplayReason(item);
|
|
2595
|
+
}
|
|
2596
|
+
return copy;
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
function semanticDuplicateConflicts(candidates) {
|
|
2600
|
+
const result = /* @__PURE__ */ new Map();
|
|
2601
|
+
const comparable = candidates.map((candidate) => comparableAsset(candidate)).filter((candidate) => !!candidate);
|
|
2602
|
+
for (const candidate of comparable) {
|
|
2603
|
+
if (candidate.actionable !== true || candidate.actionState !== "PENDING") continue;
|
|
2604
|
+
const matches = [];
|
|
2605
|
+
for (const other of comparable) {
|
|
2606
|
+
if (candidate.assetKey === other.assetKey) continue;
|
|
2607
|
+
const basis = semanticDuplicateBasis(candidate, other);
|
|
2608
|
+
if (basis) matches.push({ asset: other, basis });
|
|
2609
|
+
}
|
|
2610
|
+
if (!matches.length) continue;
|
|
2611
|
+
matches.sort((left, right) => duplicateRank(right.asset) - duplicateRank(left.asset));
|
|
2612
|
+
const targets = matches.slice(0, 3).map(({ asset, basis }) => ({
|
|
2613
|
+
target_ref: { type: asset.type, key: asset.key },
|
|
2614
|
+
display_name: asset.displayName,
|
|
2615
|
+
resource_type: asset.type,
|
|
2616
|
+
resource_key: asset.key,
|
|
2617
|
+
authentication_status: asset.authenticationStatus,
|
|
2618
|
+
action_state: asset.actionState,
|
|
2619
|
+
reason: duplicateBasisText(basis)
|
|
2620
|
+
}));
|
|
2621
|
+
result.set(candidate.assetKey, {
|
|
2622
|
+
targets,
|
|
2623
|
+
basis: Array.from(new Set(matches.map((match) => match.basis))).map(duplicateBasisText)
|
|
2624
|
+
});
|
|
2625
|
+
}
|
|
2626
|
+
return result;
|
|
2627
|
+
}
|
|
2628
|
+
function comparableAsset(candidate) {
|
|
2629
|
+
const target = record(candidate.target_ref);
|
|
2630
|
+
const type = stringValue(target.type);
|
|
2631
|
+
const key = stringValue(target.key);
|
|
2632
|
+
if (!type || !key) return void 0;
|
|
2633
|
+
const displayName = stringValue(candidate.display_name) ?? key;
|
|
2634
|
+
const evidence = record(candidate.evidence_snapshot);
|
|
2635
|
+
const evidenceAsset = record(evidence.asset);
|
|
2636
|
+
const description = stringValue(record(candidate.evidence_snapshot).description) ?? stringValue(evidenceAsset.description) ?? stringValue(candidate.description) ?? "";
|
|
2637
|
+
return {
|
|
2638
|
+
assetKey: `${type}|${key}`,
|
|
2639
|
+
type,
|
|
2640
|
+
key,
|
|
2641
|
+
displayName,
|
|
2642
|
+
description,
|
|
2643
|
+
authenticationStatus: numberValue(evidenceAsset.authentication_status ?? candidate.authentication_status),
|
|
2644
|
+
actionState: stringValue(candidate.action_state) ?? "",
|
|
2645
|
+
actionable: candidate.actionable === true,
|
|
2646
|
+
normalizedName: normalizeSemanticText(displayName || key),
|
|
2647
|
+
canonicalName: canonicalDuplicateText(displayName || key),
|
|
2648
|
+
aliasName: aliasDuplicateText(displayName || key),
|
|
2649
|
+
normalizedDescription: normalizeSemanticText(description),
|
|
2650
|
+
heat: numberValue(candidate.heat_count90d),
|
|
2651
|
+
users: numberValue(candidate.user_count90d),
|
|
2652
|
+
impact: numberValue(candidate.impact_degree)
|
|
2653
|
+
};
|
|
2654
|
+
}
|
|
2655
|
+
function semanticDuplicateBasis(left, right) {
|
|
2656
|
+
if (!left.normalizedName || !right.normalizedName) return void 0;
|
|
2657
|
+
if (left.normalizedName.length >= 3 && left.normalizedName === right.normalizedName) return "same_display_name";
|
|
2658
|
+
if (left.canonicalName.length >= 3 && left.canonicalName === right.canonicalName) return "copy_or_suffix_variant";
|
|
2659
|
+
if (left.aliasName.length >= 3 && left.aliasName === right.aliasName && relatedAssetTypes(left.type, right.type)) {
|
|
2660
|
+
return "business_alias_equivalent";
|
|
2661
|
+
}
|
|
2662
|
+
if (left.normalizedDescription.length >= 6 && left.normalizedDescription === right.normalizedDescription) {
|
|
2663
|
+
return "same_description";
|
|
2664
|
+
}
|
|
2665
|
+
return void 0;
|
|
2666
|
+
}
|
|
2667
|
+
function relatedAssetTypes(left, right) {
|
|
2668
|
+
if (left === right) return true;
|
|
2669
|
+
return left.endsWith("_prop") && right.endsWith("_prop");
|
|
2670
|
+
}
|
|
2671
|
+
function duplicateRank(asset) {
|
|
2672
|
+
return (asset.authenticationStatus === 1 ? 1e5 : 0) + (asset.actionState === "AUTHENTICATED" ? 5e4 : 0) + asset.heat + asset.users * 10 + asset.impact * 100;
|
|
2673
|
+
}
|
|
2674
|
+
function normalizeSemanticText(value) {
|
|
2675
|
+
return value.toLowerCase().replace(/[\s_\-—–/\\|::,,.。"'`【】\[\]()(){}<>《》]/g, "").trim();
|
|
2676
|
+
}
|
|
2677
|
+
function canonicalDuplicateText(value) {
|
|
2678
|
+
return normalizeSemanticText(value).replace(/(副本|复制|拷贝|备份|copy|backup|bak|test|测试|临时|tmp)+$/g, "").replace(/v\d+$/g, "").replace(/\d+$/g, "");
|
|
2679
|
+
}
|
|
2680
|
+
function aliasDuplicateText(value) {
|
|
2681
|
+
return canonicalDuplicateText(value).replace(/(公司|企业|客户|客戶|client|customer|company|account)/g, "\u5BA2\u6237").replace(/(项目|工程|project)/g, "\u9879\u76EE").replace(/(用户|玩家|会员|user|player|member)/g, "\u7528\u6237");
|
|
2682
|
+
}
|
|
2683
|
+
function duplicateBasisText(value) {
|
|
2684
|
+
switch (value) {
|
|
2685
|
+
case "same_display_name":
|
|
2686
|
+
return "\u8D44\u4EA7\u540D\u79F0\u4E00\u81F4";
|
|
2687
|
+
case "copy_or_suffix_variant":
|
|
2688
|
+
return "\u540D\u79F0\u4EC5\u5B58\u5728\u526F\u672C\u3001\u7248\u672C\u6216\u4E34\u65F6\u540E\u7F00\u5DEE\u5F02";
|
|
2689
|
+
case "business_alias_equivalent":
|
|
2690
|
+
return "\u4E1A\u52A1\u5BF9\u8C61\u8868\u8FF0\u76F8\u8FD1\uFF0C\u53EF\u80FD\u662F\u540C\u4E49\u5C5E\u6027\u6216\u76F8\u8FD1\u53E3\u5F84";
|
|
2691
|
+
case "same_description":
|
|
2692
|
+
return "\u8D44\u4EA7\u63CF\u8FF0\u4E00\u81F4";
|
|
2693
|
+
default:
|
|
2694
|
+
return value;
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
function encodeReasonPayload(value) {
|
|
2698
|
+
return Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
|
|
2699
|
+
}
|
|
2700
|
+
function decodeReasonPayload(value) {
|
|
2701
|
+
try {
|
|
2702
|
+
return record(JSON.parse(Buffer.from(value, "base64url").toString("utf8")));
|
|
2703
|
+
} catch {
|
|
2704
|
+
return {};
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
function semanticDuplicateTargetsFromReason(reason) {
|
|
2708
|
+
const encoded = /semantic_duplicate_targets=([A-Za-z0-9_-]+)/.exec(reason)?.[1];
|
|
2709
|
+
if (!encoded) return [];
|
|
2710
|
+
return array(decodeReasonPayload(encoded).targets);
|
|
2711
|
+
}
|
|
2712
|
+
function listIncludes(value, expected) {
|
|
2713
|
+
return array(value).some((item) => item === expected);
|
|
2714
|
+
}
|
|
2715
|
+
function buildManualReviewHandoff(autoReviewResult, exportResult) {
|
|
2716
|
+
const result = record(autoReviewResult);
|
|
2717
|
+
const exported = record(exportResult);
|
|
2718
|
+
const material = record(exported.review_material_package);
|
|
2719
|
+
const decisions = decisionsByAsset(result.items);
|
|
2720
|
+
const candidates = array(material.candidate_assets);
|
|
2721
|
+
const relations = array(material.relations).map(record);
|
|
2722
|
+
const handoffItems = [];
|
|
2723
|
+
const approved = /* @__PURE__ */ new Set();
|
|
2724
|
+
for (const decision of decisions.values()) {
|
|
2725
|
+
if (decision.decision === "APPROVE" && decision.landing_status === "APPLIED") {
|
|
2726
|
+
approved.add(decision.assetKey);
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
const autoCertifiedItems = buildAutoCertifiedItems(decisions, candidates);
|
|
2730
|
+
for (const value of candidates) {
|
|
2731
|
+
const candidate = record(value);
|
|
2732
|
+
const target = record(candidate.target_ref);
|
|
2733
|
+
const type = stringValue(target.type);
|
|
2734
|
+
const key = stringValue(target.key);
|
|
2735
|
+
if (!type || !key) {
|
|
2736
|
+
continue;
|
|
2737
|
+
}
|
|
2738
|
+
const assetKey = `${type}|${key}`;
|
|
2739
|
+
if (approved.has(assetKey)) {
|
|
2740
|
+
continue;
|
|
2741
|
+
}
|
|
2742
|
+
const decision = decisions.get(assetKey);
|
|
2743
|
+
const actionable = candidate.actionable === true;
|
|
2744
|
+
if (!decision && !actionable) {
|
|
2745
|
+
continue;
|
|
2746
|
+
}
|
|
2747
|
+
const reviewReason = decision ? manualReviewReason(decision, candidate) : "\u672C\u6B21\u81EA\u52A8\u8BA4\u8BC1\u672A\u4EA7\u751F\u660E\u786E\u7ED3\u8BBA\uFF0C\u53EF\u80FD\u662F\u5019\u9009\u8D44\u4EA7\u8D85\u51FA\u672C\u6B21\u81EA\u52A8\u8BA4\u8BC1\u5904\u7406\u4E0A\u9650\u6216\u88AB\u53BB\u91CD\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u3002";
|
|
2748
|
+
handoffItems.push({
|
|
2749
|
+
...candidate,
|
|
2750
|
+
auto_review_decision: decision ? decision.raw : {
|
|
2751
|
+
decision: "NOT_REVIEWED",
|
|
2752
|
+
reason: reviewReason
|
|
2753
|
+
},
|
|
2754
|
+
semantic_duplicate_targets: decision ? array(decision.raw.semantic_duplicate_targets) : [],
|
|
2755
|
+
manual_review_reason: reviewReason
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2758
|
+
const pageReviewItems = buildPageReviewItems(handoffItems, candidates, relations, decisions);
|
|
2759
|
+
const pageReviewIds = new Set(pageReviewItems.map((item) => stringValue(item.client_item_id)).filter(Boolean));
|
|
2760
|
+
return {
|
|
2761
|
+
schema_version: "1.0",
|
|
2762
|
+
handoff_type: "auto_review_uncertified_assets_to_page_review",
|
|
2763
|
+
project_id: result.project_id ?? exported.project_id,
|
|
2764
|
+
source_auto_review_run_id: result.run_id,
|
|
2765
|
+
source_export_run_id: exported.run_id,
|
|
2766
|
+
snapshot_hash: exported.snapshot_hash ?? result.snapshot_hash,
|
|
2767
|
+
dashboard_limit: exported.dashboard_limit ?? result.dashboard_limit,
|
|
2768
|
+
auto_review_trace: {
|
|
2769
|
+
run_id: result.run_id,
|
|
2770
|
+
rule_version: result.rule_version,
|
|
2771
|
+
auto_approved: result.auto_approved,
|
|
2772
|
+
skipped: result.skipped,
|
|
2773
|
+
overflow: result.overflow,
|
|
2774
|
+
approved_items: autoCertifiedItems,
|
|
2775
|
+
skipped_items: handoffItems.map((item) => ({
|
|
2776
|
+
target_ref: record(item.target_ref),
|
|
2777
|
+
display_name: item.display_name,
|
|
2778
|
+
manual_review_reason: item.manual_review_reason
|
|
2779
|
+
}))
|
|
2780
|
+
},
|
|
2781
|
+
auto_certified_items: autoCertifiedItems,
|
|
2782
|
+
candidate_count: handoffItems.length,
|
|
2783
|
+
items: handoffItems,
|
|
2784
|
+
page_review_items: pageReviewItems,
|
|
2785
|
+
page_review_context_count: pageReviewItems.length - handoffItems.length,
|
|
2786
|
+
relations: relations.filter((edge) => pageReviewIds.has(stringValue(edge.parent)) && pageReviewIds.has(stringValue(edge.child))),
|
|
2787
|
+
source_index: array(material.source_index).map(record).filter((source) => pageReviewIds.has(stringValue(source.client_item_id))),
|
|
2788
|
+
quality_gates: array(material.quality_gates),
|
|
2789
|
+
definition_policy: record(material.definition_policy),
|
|
2790
|
+
submit_to_page_policy: {
|
|
2791
|
+
command: "analysis-meta agent-review submit-to-page",
|
|
2792
|
+
scope: "Submit page_review_items so unapproved assets keep dashboard/report parent context; only items without manual_review_context require human certification decisions.",
|
|
2793
|
+
reason_field: "manual_review_reason",
|
|
2794
|
+
source_metadata: "When submitting leftovers, copy manual_review_handoff.auto_review_trace to submit-to-page source_metadata.auto_review_trace so the page audit records show the assets Agent already certified.",
|
|
2795
|
+
requires_user_submission_intent: true
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
function buildPageReviewItems(handoffItems, candidates, relations, decisions) {
|
|
2800
|
+
const byId = /* @__PURE__ */ new Map();
|
|
2801
|
+
const requiredIds = /* @__PURE__ */ new Set();
|
|
2802
|
+
for (const value of candidates) {
|
|
2803
|
+
const candidate = record(value);
|
|
2804
|
+
const id = stringValue(candidate.client_item_id);
|
|
2805
|
+
if (id) byId.set(id, candidate);
|
|
2806
|
+
}
|
|
2807
|
+
for (const item of handoffItems) {
|
|
2808
|
+
const id = stringValue(item.client_item_id);
|
|
2809
|
+
if (id) requiredIds.add(id);
|
|
2810
|
+
}
|
|
2811
|
+
let changed = true;
|
|
2812
|
+
while (changed) {
|
|
2813
|
+
changed = false;
|
|
2814
|
+
for (const edge of relations) {
|
|
2815
|
+
const parent = stringValue(edge.parent);
|
|
2816
|
+
const child = stringValue(edge.child);
|
|
2817
|
+
if (parent && child && requiredIds.has(child) && !requiredIds.has(parent) && byId.has(parent)) {
|
|
2818
|
+
requiredIds.add(parent);
|
|
2819
|
+
changed = true;
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
const handoffById = new Map(handoffItems.map((item) => [stringValue(item.client_item_id), item]).filter((entry) => !!entry[0]));
|
|
2824
|
+
return candidates.map(record).filter((candidate) => {
|
|
2825
|
+
const id = stringValue(candidate.client_item_id);
|
|
2826
|
+
return id !== void 0 && requiredIds.has(id);
|
|
2827
|
+
}).map((candidate) => {
|
|
2828
|
+
const id = stringValue(candidate.client_item_id) ?? "";
|
|
2829
|
+
const handoff = handoffById.get(id);
|
|
2830
|
+
if (handoff) return handoff;
|
|
2831
|
+
const target = record(candidate.target_ref);
|
|
2832
|
+
const type = stringValue(target.type);
|
|
2833
|
+
const key = stringValue(target.key);
|
|
2834
|
+
const decision = type && key ? decisions.get(`${type}|${key}`) : void 0;
|
|
2835
|
+
return markContextCandidate(candidate, decision);
|
|
2836
|
+
});
|
|
2837
|
+
}
|
|
2838
|
+
function markContextCandidate(candidate, decision) {
|
|
2839
|
+
const item = { ...candidate };
|
|
2840
|
+
item.manual_review_context = true;
|
|
2841
|
+
item.manual_review_reason = "\u8BE5\u8D44\u4EA7\u7528\u4E8E\u4FDD\u7559\u81EA\u52A8\u53D1\u73B0\u9875\u9762\u7684\u7236\u5B50\u5C42\u7EA7\u548C\u6765\u6E90\u4E0A\u4E0B\u6587\uFF0C\u4E0D\u4F5C\u4E3A\u672C\u6B21\u4EBA\u5DE5\u5BA1\u6838\u5BF9\u8C61\u3002";
|
|
2842
|
+
if (decision?.decision === "APPROVE" && decision.landing_status === "APPLIED") {
|
|
2843
|
+
item.auto_review_decision = decision.raw;
|
|
2844
|
+
item.auto_review_context_reason = autoReviewDisplayReason(decision.raw, candidate);
|
|
2845
|
+
item.evidence_snapshot = markEvidenceAuthenticated(record(candidate.evidence_snapshot));
|
|
2846
|
+
}
|
|
2847
|
+
return item;
|
|
2848
|
+
}
|
|
2849
|
+
function markEvidenceAuthenticated(evidence) {
|
|
2850
|
+
const snapshot = { ...evidence };
|
|
2851
|
+
const asset = record(snapshot.asset);
|
|
2852
|
+
if (Object.keys(asset).length) {
|
|
2853
|
+
snapshot.asset = { ...asset, authentication_status: 1 };
|
|
2854
|
+
}
|
|
2855
|
+
return snapshot;
|
|
2856
|
+
}
|
|
2857
|
+
function decisionsByAsset(value) {
|
|
2858
|
+
const result = /* @__PURE__ */ new Map();
|
|
2859
|
+
for (const itemValue of array(value)) {
|
|
2860
|
+
const item = record(itemValue);
|
|
2861
|
+
if (item.item_type !== "asset") {
|
|
2862
|
+
continue;
|
|
2863
|
+
}
|
|
2864
|
+
const type = stringValue(item.resource_type);
|
|
2865
|
+
const key = stringValue(item.resource_key);
|
|
2866
|
+
if (!type || !key) {
|
|
2867
|
+
continue;
|
|
2868
|
+
}
|
|
2869
|
+
const assetKey = `${type}|${key}`;
|
|
2870
|
+
result.set(assetKey, {
|
|
2871
|
+
assetKey,
|
|
2872
|
+
decision: stringValue(item.decision) ?? "",
|
|
2873
|
+
landing_status: stringValue(item.landing_status) ?? "",
|
|
2874
|
+
raw: item
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
return result;
|
|
2878
|
+
}
|
|
2879
|
+
function buildAutoCertifiedItems(decisions, candidates) {
|
|
2880
|
+
const byAsset = /* @__PURE__ */ new Map();
|
|
2881
|
+
for (const value of candidates) {
|
|
2882
|
+
const candidate = record(value);
|
|
2883
|
+
const target = record(candidate.target_ref);
|
|
2884
|
+
const type = stringValue(target.type);
|
|
2885
|
+
const key = stringValue(target.key);
|
|
2886
|
+
if (type && key) byAsset.set(`${type}|${key}`, candidate);
|
|
2887
|
+
}
|
|
2888
|
+
const items = [];
|
|
2889
|
+
for (const decision of decisions.values()) {
|
|
2890
|
+
if (decision.decision !== "APPROVE" || decision.landing_status !== "APPLIED") continue;
|
|
2891
|
+
const candidate = byAsset.get(decision.assetKey) ?? {};
|
|
2892
|
+
items.push({
|
|
2893
|
+
target_ref: record(candidate.target_ref),
|
|
2894
|
+
display_name: candidate.display_name ?? decision.raw.resource_key,
|
|
2895
|
+
auto_review_reason: autoReviewDisplayReason(decision.raw, candidate),
|
|
2896
|
+
landing_message: decision.raw.landing_message
|
|
2897
|
+
});
|
|
2898
|
+
}
|
|
2899
|
+
return items;
|
|
2900
|
+
}
|
|
2901
|
+
function manualReviewReason(decision, context) {
|
|
2902
|
+
const reason = autoReviewDisplayReason(decision.raw, context);
|
|
2903
|
+
if (decision.decision === "SKIP") {
|
|
2904
|
+
return reason;
|
|
2905
|
+
}
|
|
2906
|
+
if (decision.decision === "APPROVE" && decision.landing_status !== "APPLIED") {
|
|
2907
|
+
const landing = stringValue(decision.raw.landing_message);
|
|
2908
|
+
return landing ? `${reason}; landing_${decision.landing_status.toLowerCase()}: ${landing}` : `${reason}; landing_${decision.landing_status.toLowerCase()}`;
|
|
2909
|
+
}
|
|
2910
|
+
return reason;
|
|
2911
|
+
}
|
|
2912
|
+
function autoReviewDisplayReason(raw, context = {}) {
|
|
2913
|
+
const display = stringValue(raw.display_reason);
|
|
2914
|
+
if (display) return display;
|
|
2915
|
+
const reason = stringValue(raw.reason);
|
|
2916
|
+
if (!reason) return "\u672C\u6B21\u81EA\u52A8\u8BA4\u8BC1\u6CA1\u6709\u8FD4\u56DE\u539F\u56E0\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u3002";
|
|
2917
|
+
return humanizeAutoReviewReason(reason, context);
|
|
2918
|
+
}
|
|
2919
|
+
function humanizeAutoReviewReason(reason, context) {
|
|
2920
|
+
if (reason.includes("semantic_duplicate_targets=")) {
|
|
2921
|
+
const targets = semanticDuplicateTargetsFromReason(reason).map(record).map((target) => {
|
|
2922
|
+
const ref = record(target.target_ref);
|
|
2923
|
+
const label = stringValue(target.display_name) ?? stringValue(target.resource_key) ?? stringValue(ref.key) ?? "\u672A\u77E5\u8D44\u4EA7";
|
|
2924
|
+
const type = stringValue(target.resource_type) ?? stringValue(ref.type) ?? "asset";
|
|
2925
|
+
const key = stringValue(target.resource_key) ?? stringValue(ref.key) ?? "-";
|
|
2926
|
+
const targetReason = stringValue(target.reason);
|
|
2927
|
+
return `${label}\uFF08${type}:${key}${targetReason ? `\uFF0C${targetReason}` : ""}\uFF09`;
|
|
2928
|
+
});
|
|
2929
|
+
const targetText = targets.length ? targets.join("\uFF1B") : "\u76F8\u8FD1\u8D44\u4EA7";
|
|
2930
|
+
return `\u672A\u81EA\u52A8\u8BA4\u8BC1\u539F\u56E0\uFF1A\u7591\u4F3C\u4E0E ${targetText} \u8BED\u4E49\u91CD\u590D\u6216\u53E3\u5F84\u76F8\u8FD1\u3002\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u662F\u5426\u5E94\u4F5C\u4E3A\u72EC\u7ACB\u8D44\u4EA7\u8BA4\u8BC1\uFF1B\u5982\u679C\u53EA\u662F\u526F\u672C\u3001\u540C\u4E49\u5C5E\u6027\u6216\u76F8\u8FD1\u53E3\u5F84\uFF0C\u8BF7\u4F18\u5148\u9009\u62E9\u66F4\u6807\u51C6\u7684\u8D44\u4EA7\u3002`;
|
|
2931
|
+
}
|
|
2932
|
+
if (reason.includes("previous_decision_exists_for_different_evidence")) {
|
|
2933
|
+
return "\u672A\u81EA\u52A8\u8BA4\u8BC1\u539F\u56E0\uFF1A\u68C0\u6D4B\u5230\u8BE5\u8D44\u4EA7\u5B58\u5728\u5386\u53F2\u5904\u7406\u8BB0\u5F55\uFF0C\u4F46\u672C\u6B21\u672A\u8FD4\u56DE\u53EF\u6838\u9A8C\u7684\u91CD\u590D\u5BF9\u8C61\u3002\u8BF7\u6309\u5F53\u524D\u8D44\u4EA7\u5B9A\u4E49\u548C\u6765\u6E90\u8BC1\u636E\u4EBA\u5DE5\u786E\u8BA4\uFF1B\u8FD9\u4E0D\u4EE3\u8868\u7CFB\u7EDF\u53D1\u73B0\u4E86\u91CD\u590D\u8D44\u4EA7\u3002";
|
|
2934
|
+
}
|
|
2935
|
+
if (reason.includes("same_evidence_rejected_before")) {
|
|
2936
|
+
return "\u672A\u81EA\u52A8\u8BA4\u8BC1\u539F\u56E0\uFF1A\u76F8\u540C\u8BA4\u8BC1\u5EFA\u8BAE\u6B64\u524D\u5DF2\u88AB\u4EBA\u5DE5\u9A73\u56DE\uFF0C\u81EA\u52A8\u8BA4\u8BC1\u4E0D\u4F1A\u8986\u76D6\u4EBA\u5DE5\u7ED3\u8BBA\u3002\u5982\u4E1A\u52A1\u53E3\u5F84\u5DF2\u8C03\u6574\uFF0C\u8BF7\u4EBA\u5DE5\u91CD\u65B0\u786E\u8BA4\u662F\u5426\u8BA4\u8BC1\u3002";
|
|
2937
|
+
}
|
|
2938
|
+
if (reason.includes("source_evidence_missing")) {
|
|
2939
|
+
return "\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u7F3A\u5C11\u53EF\u6838\u9A8C\u7684\u6765\u6E90\u8D44\u4EA7\u8BC1\u636E\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u8D44\u4EA7\u6765\u6E90\u3001\u5B9A\u4E49\u548C\u4F9D\u8D56\u5173\u7CFB\u540E\u518D\u8BA4\u8BC1\u3002";
|
|
2940
|
+
}
|
|
2941
|
+
if (reason.includes("signals_below_threshold")) {
|
|
2942
|
+
const heat = /heat_count90d=(\d+)/.exec(reason)?.[1];
|
|
2943
|
+
const users = /user_count90d=(\d+)/.exec(reason)?.[1];
|
|
2944
|
+
const impact = /impact_degree=([0-9.]+)/.exec(reason)?.[1];
|
|
2945
|
+
return `\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u8BE5\u8D44\u4EA7\u8FD1 90 \u5929\u8BBF\u95EE/\u4F7F\u7528 ${heat ?? "\u672A\u77E5"} \u6B21\u3001\u4F7F\u7528\u4EBA\u6570 ${users ?? "\u672A\u77E5"}\uFF0C\u5F71\u54CD\u5EA6 ${impact ?? "\u672A\u77E5"}\uFF0C\u672A\u8FBE\u5230\u81EA\u52A8\u8BA4\u8BC1\u9608\u503C\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u662F\u5426\u4ECD\u9700\u8981\u8BA4\u8BC1\u3002`;
|
|
2946
|
+
}
|
|
2947
|
+
if (reason.includes("matched=")) {
|
|
2948
|
+
const matched = [];
|
|
2949
|
+
if (reason.includes("heat_count90d>=")) matched.push("\u8BBF\u95EE/\u4F7F\u7528\u6B21\u6570\u8FBE\u5230\u9608\u503C");
|
|
2950
|
+
if (reason.includes("user_count90d>=")) matched.push("\u4F7F\u7528\u4EBA\u6570\u8FBE\u5230\u9608\u503C");
|
|
2951
|
+
if (reason.includes("impact_degree>")) matched.push("\u5F71\u54CD\u5EA6\u8FBE\u5230\u9608\u503C");
|
|
2952
|
+
const matchedText = matched.length ? matched.join("\u3001") : "\u547D\u4E2D\u81EA\u52A8\u8BA4\u8BC1\u89C4\u5219";
|
|
2953
|
+
return `Agent \u81EA\u52A8\u8BA4\u8BC1\u901A\u8FC7\uFF1A\u8BE5\u8D44\u4EA7\u8FD1 90 \u5929\u8BBF\u95EE/\u4F7F\u7528 ${displaySignal(context.heat_count90d)} \u6B21\u3001\u4F7F\u7528\u4EBA\u6570 ${displaySignal(context.user_count90d)}\uFF0C\u5F71\u54CD\u5EA6 ${displaySignal(context.impact_degree)}\uFF1B\u672A\u53D1\u73B0\u8BED\u4E49\u91CD\u590D\u98CE\u9669\uFF0C\u4E14${matchedText}\u3002`;
|
|
2954
|
+
}
|
|
2955
|
+
return reason.replace(/^source=AGENT_AUTO_REVIEW;\s*/, "").replace(/rule_version=[^;]+;\s*/, "").replace(/conflict_risks=\[[^\]]*]/, "\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u5B58\u5728\u9700\u8981\u4EBA\u5DE5\u786E\u8BA4\u7684\u5BA1\u6838\u98CE\u9669\u3002").replace(/conflict_risks=/, "\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u5B58\u5728\u9700\u8981\u4EBA\u5DE5\u786E\u8BA4\u7684\u5BA1\u6838\u98CE\u9669\u3002");
|
|
2956
|
+
}
|
|
2957
|
+
function displaySignal(value) {
|
|
2958
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
2959
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
2960
|
+
return "\u672A\u77E5";
|
|
2961
|
+
}
|
|
2962
|
+
function record(value) {
|
|
2963
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2964
|
+
}
|
|
2965
|
+
function array(value) {
|
|
2966
|
+
return Array.isArray(value) ? value : [];
|
|
2967
|
+
}
|
|
2968
|
+
function numberValue(value) {
|
|
2969
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
2970
|
+
}
|
|
2971
|
+
function stringValue(value) {
|
|
2972
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2241
2975
|
// src/commands/te-analysis/meta/governance-recommendation/decisions.ts
|
|
2242
2976
|
var runIdFlag2 = {
|
|
2243
2977
|
name: "run-id",
|
|
@@ -2245,7 +2979,7 @@ var runIdFlag2 = {
|
|
|
2245
2979
|
required: false,
|
|
2246
2980
|
desc: "Optional run_id filter."
|
|
2247
2981
|
};
|
|
2248
|
-
var
|
|
2982
|
+
var limitFlag5 = {
|
|
2249
2983
|
name: "limit",
|
|
2250
2984
|
type: "number",
|
|
2251
2985
|
required: false,
|
|
@@ -2258,7 +2992,7 @@ var metadataGovernanceRecommendationDecisions = createAnalysisMetaCapabilityComm
|
|
|
2258
2992
|
command: "decisions",
|
|
2259
2993
|
capabilityId: "metadata.governance_recommendation.decisions",
|
|
2260
2994
|
description: "List recent CLI Agent recommendation approval decisions.",
|
|
2261
|
-
flags: [projectIdFlag, runIdFlag2,
|
|
2995
|
+
flags: [projectIdFlag, runIdFlag2, limitFlag5],
|
|
2262
2996
|
risk: "read",
|
|
2263
2997
|
buildInput: (ctx) => compactInput({
|
|
2264
2998
|
...projectInput(ctx),
|
|
@@ -2271,6 +3005,7 @@ var metadataGovernanceRecommendationDecisions = createAnalysisMetaCapabilityComm
|
|
|
2271
3005
|
var commands11 = [
|
|
2272
3006
|
metadataGovernanceRecommendationExport,
|
|
2273
3007
|
metadataGovernanceRecommendationSubmit,
|
|
3008
|
+
metadataGovernanceRecommendationAutoReview,
|
|
2274
3009
|
metadataGovernanceRecommendationDecisions
|
|
2275
3010
|
];
|
|
2276
3011
|
var governance_recommendation_default = commands11;
|
|
@@ -2322,7 +3057,7 @@ function object(value, name) {
|
|
|
2322
3057
|
}
|
|
2323
3058
|
return value;
|
|
2324
3059
|
}
|
|
2325
|
-
function
|
|
3060
|
+
function array2(value, name) {
|
|
2326
3061
|
if (!Array.isArray(value) || value.length < 1 || value.length > 5e3) {
|
|
2327
3062
|
throw new Error(`${name} must contain 1 to 5000 items.`);
|
|
2328
3063
|
}
|
|
@@ -2367,6 +3102,7 @@ var SUBMIT_TO_PAGE_HELP = [
|
|
|
2367
3102
|
"- relations should let the page render dashboard -> report -> metadata with contains/uses edges. Use an empty relations array only when the package truly has no known parent-child evidence.",
|
|
2368
3103
|
"- Each submitted item must keep source_link or evidence_links[].url so reviewers can jump to source evidence.",
|
|
2369
3104
|
"- item.ai_summary.summary is the per-item recommendation reason. It must cite concrete item evidence, not generic review boilerplate. batch ai_summary.summary is only the batch overview.",
|
|
3105
|
+
"- When submitting manual_review_handoff leftovers, copy manual_review_handoff.auto_review_trace into source_metadata.auto_review_trace so page audit records include the assets already certified automatically.",
|
|
2370
3106
|
"- For reports and SQL reports, item.ai_summary.analysis_explanation must explain reviewer-readable calculations or measures from packaged evidence_snapshot.analysis. A purpose-only summary is incomplete and is rejected locally before dispatch.",
|
|
2371
3107
|
"- Reviewer-visible text should follow the project-KB source style: one business Chinese Agent summary that explains purpose, calculation caliber, filters, time scope, boundaries, and concrete reviewer questions. Keep raw SQL, parser labels, temporary aliases, parameter placeholders, hashes, and evidence paths in evidence_snapshot only; independent Agent preflight flags visible implementation terms as quality findings.",
|
|
2372
3108
|
"- The command output includes review_page_url when review_url is present. Return review_page_url to the user; do not prepend the Common/API host to review_url yourself.",
|
|
@@ -2378,6 +3114,7 @@ var SUBMIT_TO_PAGE_HELP = [
|
|
|
2378
3114
|
' "title": "<review batch title>",',
|
|
2379
3115
|
' "source_run_id": "<export.run_id>",',
|
|
2380
3116
|
' "source_task_id": "<optional preauthorized task id>",',
|
|
3117
|
+
' "source_metadata": { "auto_review_trace": "<optional trace from manual_review_handoff.auto_review_trace>" },',
|
|
2381
3118
|
' "ai_summary": { "summary": "<batch overview>" },',
|
|
2382
3119
|
' "presentation_snapshot": {',
|
|
2383
3120
|
' "project": { "id": 1, "name": "<project name>" },',
|
|
@@ -2465,7 +3202,7 @@ var agentReviewSubmitToPage = createAnalysisMetaCapabilityCommand({
|
|
|
2465
3202
|
postProcess: (result, _input, ctx) => normalizeSubmitResult(result, resolvePublicWebHost(ctx.host()), ctx.host())
|
|
2466
3203
|
});
|
|
2467
3204
|
function validateInput(input) {
|
|
2468
|
-
const items =
|
|
3205
|
+
const items = array2(input.items, "items").map((value) => {
|
|
2469
3206
|
const item = object(value, "items[]");
|
|
2470
3207
|
fields(item, [
|
|
2471
3208
|
"client_item_id",
|
|
@@ -2512,6 +3249,7 @@ function validateInput(input) {
|
|
|
2512
3249
|
"title",
|
|
2513
3250
|
"source_run_id",
|
|
2514
3251
|
"source_task_id",
|
|
3252
|
+
"source_metadata",
|
|
2515
3253
|
"ai_summary",
|
|
2516
3254
|
"presentation_snapshot",
|
|
2517
3255
|
"items"
|
|
@@ -2581,7 +3319,7 @@ function validateEvidenceLinks(item) {
|
|
|
2581
3319
|
const sourceLink = typeof item.source_link === "string" && item.source_link.trim();
|
|
2582
3320
|
let evidenceLink = false;
|
|
2583
3321
|
if ("evidence_links" in item) {
|
|
2584
|
-
evidenceLink =
|
|
3322
|
+
evidenceLink = array2(item.evidence_links, "items[].evidence_links").some((value) => {
|
|
2585
3323
|
const link = object(value, "items[].evidence_links[]");
|
|
2586
3324
|
return typeof link.url === "string" && !!link.url.trim();
|
|
2587
3325
|
});
|
|
@@ -2592,17 +3330,17 @@ function validateEvidenceLinks(item) {
|
|
|
2592
3330
|
}
|
|
2593
3331
|
function validatePresentation(presentation, itemIds) {
|
|
2594
3332
|
const displayed = /* @__PURE__ */ new Set();
|
|
2595
|
-
for (const topicValue of
|
|
3333
|
+
for (const topicValue of array2(presentation.topics, "presentation_snapshot.topics")) {
|
|
2596
3334
|
const topic = object(topicValue, "presentation_snapshot.topics[]");
|
|
2597
3335
|
if ("items" in topic) {
|
|
2598
3336
|
throw new Error("presentation_snapshot.topics[] must use groups[].items, not top-level items.");
|
|
2599
3337
|
}
|
|
2600
|
-
for (const groupValue of
|
|
3338
|
+
for (const groupValue of array2(topic.groups, "presentation_snapshot.topics[].groups")) {
|
|
2601
3339
|
const group = object(groupValue, "presentation_snapshot.topics[].groups[]");
|
|
2602
3340
|
if (typeof group.id !== "string" || !group.id.trim() || typeof group.name !== "string" || !group.name.trim()) {
|
|
2603
3341
|
throw new Error("presentation_snapshot.topics[].groups[] requires nonempty string id and name.");
|
|
2604
3342
|
}
|
|
2605
|
-
for (const itemValue of
|
|
3343
|
+
for (const itemValue of array2(group.items, "presentation_snapshot.topics[].groups[].items")) {
|
|
2606
3344
|
const item = object(itemValue, "presentation_snapshot.topics[].groups[].items[]");
|
|
2607
3345
|
if (typeof item.id !== "string" || !item.id.trim()) {
|
|
2608
3346
|
throw new Error("presentation_snapshot display items require nonempty string id.");
|
|
@@ -2649,7 +3387,7 @@ var agentReviewReview = createAnalysisMetaCapabilityCommand({
|
|
|
2649
3387
|
{ name: "decisions", type: "json", required: true, desc: "Versioned decisions: item_id (string), version (integer), decision APPROVE/DEFER/REJECT, reason (required for DEFER/REJECT)." }
|
|
2650
3388
|
],
|
|
2651
3389
|
buildInput: (ctx) => {
|
|
2652
|
-
const decisions =
|
|
3390
|
+
const decisions = array2(ctx.json("decisions"), "--decisions").map((value) => {
|
|
2653
3391
|
const decision = object(value, "decisions[]");
|
|
2654
3392
|
fields(decision, ["item_id", "version", "decision", "reason"], "decisions[]");
|
|
2655
3393
|
decimalId(decision.item_id, "decisions[].item_id");
|
|
@@ -2686,7 +3424,7 @@ var agentReviewRetry = createAnalysisMetaCapabilityCommand({
|
|
|
2686
3424
|
{ name: "item-ids", type: "json", required: true, desc: "1 to 5000 failed item IDs as decimal strings. Successful items must not be retried." }
|
|
2687
3425
|
],
|
|
2688
3426
|
buildInput: (ctx) => {
|
|
2689
|
-
const ids =
|
|
3427
|
+
const ids = array2(ctx.json("item-ids"), "--item-ids").map((id) => decimalId(id, "item_ids[]"));
|
|
2690
3428
|
unique(ids, "item_ids");
|
|
2691
3429
|
return { ...batchInput(ctx), client_request_id: text(ctx, "client-request-id"), item_ids: ids };
|
|
2692
3430
|
}
|
|
@@ -2770,9 +3508,9 @@ var analysisMetaAssetUsageList = createAnalysisGovernanceCapabilityCommand({
|
|
|
2770
3508
|
command: "list",
|
|
2771
3509
|
capabilityId: "governance.asset.list",
|
|
2772
3510
|
description: "List assets for usage governance.",
|
|
2773
|
-
flags: [projectIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, directoryLimitFlag, directoryOffsetFlag, payloadFlag],
|
|
3511
|
+
flags: [projectIdFlag, nodeIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, directoryLimitFlag, directoryOffsetFlag, payloadFlag],
|
|
2774
3512
|
risk: "read",
|
|
2775
|
-
buildInput: (ctx) => assetGovernanceInput(ctx, ["query", "searchs", "rule", "operation_type", "limit", "offset"])
|
|
3513
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, ["node_id", "query", "searchs", "rule", "operation_type", "limit", "offset"])
|
|
2776
3514
|
});
|
|
2777
3515
|
|
|
2778
3516
|
// src/commands/te-analysis/meta/asset/usage-export.ts
|
|
@@ -2780,10 +3518,11 @@ var analysisMetaAssetUsageExport = createAnalysisGovernanceCapabilityCommand({
|
|
|
2780
3518
|
resource: "asset",
|
|
2781
3519
|
command: "export",
|
|
2782
3520
|
capabilityId: "governance.asset.export",
|
|
2783
|
-
description: "Export asset usage governance rows as an
|
|
2784
|
-
flags: [projectIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, limitFlag, offsetFlag, payloadFlag],
|
|
3521
|
+
description: "Export asset usage governance rows as an asynchronous artifact; optionally wait and download.",
|
|
3522
|
+
flags: [projectIdFlag, nodeIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, limitFlag, offsetFlag, payloadFlag, ...governanceExportFlags("jsonl")],
|
|
2785
3523
|
risk: "read",
|
|
2786
|
-
|
|
3524
|
+
asyncArtifact: true,
|
|
3525
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "node_id", "query", "searchs", "rule", "operation_type", "limit", "offset"])
|
|
2787
3526
|
});
|
|
2788
3527
|
|
|
2789
3528
|
// src/commands/te-analysis/meta/asset/lineage-get.ts
|
|
@@ -2891,9 +3630,10 @@ var analysisMetaAssetBatchInfoExport = createAnalysisGovernanceCapabilityCommand
|
|
|
2891
3630
|
command: "batch-info-export",
|
|
2892
3631
|
capabilityId: "governance.asset.batch_export_info",
|
|
2893
3632
|
description: "Batch export asset information.",
|
|
2894
|
-
flags: [projectIdFlag, nodeIdsFlag, payloadFlag],
|
|
3633
|
+
flags: [projectIdFlag, nodeIdsFlag, payloadFlag, ...governanceExportFlags("xlsx")],
|
|
2895
3634
|
risk: "read",
|
|
2896
|
-
|
|
3635
|
+
asyncArtifact: true,
|
|
3636
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "node_ids"])
|
|
2897
3637
|
});
|
|
2898
3638
|
|
|
2899
3639
|
// src/commands/te-analysis/meta/asset/batch-sql-export.ts
|
|
@@ -2902,9 +3642,10 @@ var analysisMetaAssetBatchSqlExport = createAnalysisGovernanceCapabilityCommand(
|
|
|
2902
3642
|
command: "batch-sql-export",
|
|
2903
3643
|
capabilityId: "governance.asset.batch_export_sql",
|
|
2904
3644
|
description: "Batch export asset SQL definitions.",
|
|
2905
|
-
flags: [projectIdFlag, nodeIdsFlag, payloadFlag],
|
|
3645
|
+
flags: [projectIdFlag, nodeIdsFlag, payloadFlag, ...governanceExportFlags("xlsx")],
|
|
2906
3646
|
risk: "read",
|
|
2907
|
-
|
|
3647
|
+
asyncArtifact: true,
|
|
3648
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "node_ids"])
|
|
2908
3649
|
});
|
|
2909
3650
|
|
|
2910
3651
|
// src/commands/te-analysis/meta/asset/batch-delete.ts
|
|
@@ -2979,9 +3720,10 @@ var analysisMetaAssetOperationRecordExport = createAnalysisGovernanceCapabilityC
|
|
|
2979
3720
|
command: "export",
|
|
2980
3721
|
capabilityId: "governance.operation_record.export",
|
|
2981
3722
|
description: "Export one asset batch operation record result.",
|
|
2982
|
-
flags: [projectIdFlag, recordIdFlag, payloadFlag],
|
|
3723
|
+
flags: [projectIdFlag, recordIdFlag, payloadFlag, ...governanceExportFlags("xlsx")],
|
|
2983
3724
|
risk: "read",
|
|
2984
|
-
|
|
3725
|
+
asyncArtifact: true,
|
|
3726
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "record_id"])
|
|
2985
3727
|
});
|
|
2986
3728
|
|
|
2987
3729
|
// src/commands/te-analysis/governance/asset-authentication-shared.ts
|
|
@@ -3359,7 +4101,7 @@ var reportList = createAnalysisCapabilityCommand({
|
|
|
3359
4101
|
resource: "report",
|
|
3360
4102
|
command: "list",
|
|
3361
4103
|
capabilityId: "analysis.report.list",
|
|
3362
|
-
description: "List analysis reports
|
|
4104
|
+
description: "List analysis reports the current user can edit or manage. Read-only reports are excluded; use analysis asset search for readable asset discovery.",
|
|
3363
4105
|
flags: [
|
|
3364
4106
|
projectIdFlag,
|
|
3365
4107
|
queriesFlag,
|
|
@@ -3408,7 +4150,7 @@ var reportGet = createAnalysisCapabilityCommand({
|
|
|
3408
4150
|
resource: "report",
|
|
3409
4151
|
command: "get",
|
|
3410
4152
|
capabilityId: "analysis.report.get",
|
|
3411
|
-
description: "Get one analysis report definition
|
|
4153
|
+
description: "Get one analysis report definition and event-report presentation without executing report data.",
|
|
3412
4154
|
flags: [projectIdFlag, { name: "report-id", type: "number", required: true, desc: "Report ID." }],
|
|
3413
4155
|
risk: "read",
|
|
3414
4156
|
buildInput: (ctx) => ({
|
|
@@ -3439,7 +4181,7 @@ var REPORT_WRITE_MODEL_TYPE_VALUES = [
|
|
|
3439
4181
|
];
|
|
3440
4182
|
var REPORT_WRITE_MODEL_DESCRIPTION = `${AI_MODEL_DESCRIPTION} Report create/update also supports tag for saved tag report data; use tag as the AI-facing spelling.`;
|
|
3441
4183
|
var AI_DEFINITION_DESCRIPTION = 'Event metrics: omit optional display_name unless the target command schema explicitly supports it. Funnel step filters use event_property_name (not field) and string-array values, including "true"/"false" for boolean properties. For tag/cluster filters, cluster_date_policy accepts LATEST (default), AUTO (match the computed result for each analysis date), or SPECIFIED (requires specified_cluster_date in yyyy-MM-dd format). AI-facing model definition JSON. Do not pass raw QP, events, event_view, visual_view, or analysis_query. Distribution filters must be attached to the corresponding distribution_metrics[].filters; do not use top-level filters or relation. For path definitions, global filters support user_property, cluster, and tag only; event_property is not supported. session_unit accepts second (1..999), minute (1..999), or hour (1..24). Do not use day; express one day as session_interval=24 and session_unit=hour. For SQL, a simple query is {"sql":"select ..."}; raw variables use ${name}, while typed params use ${Text:name}, ${Selector:name}, or ${PartDate:name}. PartDate expands to a complete predicate, so write WHERE ${PartDate:d}, not a column followed by the placeholder. A part_date parameter may set boolean use_timezone; it defaults to false and controls whether that parameter uses the query effective timezone. Selector value must match one options[].value. Trino identifiers containing #, $, @, spaces, punctuation, or a reserved word must be delimited with double quotes, for example SELECT "#user_id", "$part_event", "end" FROM ...; single quotes are string literals. For multiline SQL JSON, the decoded sql value must contain a real line break; do not submit a literal \\n sequence outside quoted SQL text. Queries against an event table must include a date-partition predicate on the quoted "$part_date" column, for example WHERE "$part_date" BETWEEN \'2026-07-01\' AND \'2026-07-07\'; the backend rejects event-table SQL without it. The CLI preserves SQL text and never auto-quotes identifiers.';
|
|
3442
|
-
var REPORT_WRITE_DEFINITION_DESCRIPTION = `${AI_DEFINITION_DESCRIPTION} For model_type=tag, pass a tag report intent such as {"tag":{"tag_name":"vip_users","time_range":{"mode":"recent","unit":"day","value":7}}}. Tags are supported for report create/update and report data, not ad-hoc analysis.`;
|
|
4184
|
+
var REPORT_WRITE_DEFINITION_DESCRIPTION = `${AI_DEFINITION_DESCRIPTION} Saved funnel definitions may set optional funnel.steps[].display_name; report get returns it and report create/update preserves it. Saved-report filters may contain one compound group level only; every item inside that group must be a leaf without another items array. Historical deeper trees remain readable but cannot be written back as a definition. For model_type=tag, pass a tag report intent such as {"tag":{"tag_name":"vip_users","time_range":{"mode":"recent","unit":"day","value":7}}}. Tags are supported for report create/update and report data, not ad-hoc analysis.`;
|
|
3443
4185
|
function aiModelTypeFlag(required) {
|
|
3444
4186
|
return {
|
|
3445
4187
|
name: "model-type",
|
|
@@ -3453,18 +4195,32 @@ function validateFunnelStepFilters(modelType, definition) {
|
|
|
3453
4195
|
const steps = definition.funnel.steps;
|
|
3454
4196
|
if (!Array.isArray(steps)) return;
|
|
3455
4197
|
const errors = [];
|
|
3456
|
-
|
|
3457
|
-
if (!isRecord(
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
4198
|
+
const visit = (filter, location) => {
|
|
4199
|
+
if (!isRecord(filter)) {
|
|
4200
|
+
errors.push(`${location}: use a filter object.`);
|
|
4201
|
+
return;
|
|
4202
|
+
}
|
|
4203
|
+
if ("items" in filter) {
|
|
4204
|
+
if (Object.keys(filter).some((key) => key !== "items" && key !== "relation")) {
|
|
4205
|
+
errors.push(`${location}: compound groups contain only items and relation; put event_property_name and operator on their leaf items.`);
|
|
3463
4206
|
}
|
|
3464
|
-
if (
|
|
3465
|
-
errors.push(`${location}.
|
|
4207
|
+
if (!Array.isArray(filter.items) || filter.items.length === 0) {
|
|
4208
|
+
errors.push(`${location}.items: use a non-empty array of event-property filters or nested groups.`);
|
|
4209
|
+
} else {
|
|
4210
|
+
filter.items.forEach((item, index) => visit(item, `${location}.items[${index}]`));
|
|
3466
4211
|
}
|
|
3467
|
-
|
|
4212
|
+
return;
|
|
4213
|
+
}
|
|
4214
|
+
if ("field" in filter || typeof filter.event_property_name !== "string" || !filter.event_property_name.trim()) {
|
|
4215
|
+
errors.push(`${location}: use a non-empty event_property_name, not a generic field object.`);
|
|
4216
|
+
}
|
|
4217
|
+
if ("values" in filter && (!Array.isArray(filter.values) || filter.values.some((value) => typeof value !== "string"))) {
|
|
4218
|
+
errors.push(`${location}.values: use an array of strings (boolean properties use "true" or "false").`);
|
|
4219
|
+
}
|
|
4220
|
+
};
|
|
4221
|
+
steps.forEach((step, stepIndex) => {
|
|
4222
|
+
if (!isRecord(step) || !Array.isArray(step.filters)) return;
|
|
4223
|
+
step.filters.forEach((filter, filterIndex) => visit(filter, `definition.funnel.steps[${stepIndex}].filters[${filterIndex}]`));
|
|
3468
4224
|
});
|
|
3469
4225
|
if (errors.length) {
|
|
3470
4226
|
throw new CliValidationError(errors.join("\n"), {
|
|
@@ -3516,6 +4272,61 @@ function validateReportMetadataResolutions(ctx) {
|
|
|
3516
4272
|
}
|
|
3517
4273
|
}
|
|
3518
4274
|
|
|
4275
|
+
// src/commands/te-analysis/report/presentation.ts
|
|
4276
|
+
var reportPresentationFlag = {
|
|
4277
|
+
name: "presentation",
|
|
4278
|
+
type: "json",
|
|
4279
|
+
required: false,
|
|
4280
|
+
desc: 'Optional top-level event-report display JSON: chart_type (line|combo|bar|stacked|cumulative|pie), table_layout (date|event|group), series [{metric_index:1,type:"bar"|"line",axis:"primary"|"secondary"}]. Line/combo/cumulative require a non-total time_particle_size. Metric indexes are 1-based definition.metrics positions. Series is a subset patch; [] resets all series, and chart_type=line resets to pure primary-axis lines. Omit to preserve the saved chart/result-table layout on same-model updates. For a dashboard table card use analysis dashboard-report update --chart-type table.'
|
|
4281
|
+
};
|
|
4282
|
+
function validateReportPresentation(ctx) {
|
|
4283
|
+
if (!(ctx.has?.("presentation") ?? ctx.str("presentation") !== "")) return;
|
|
4284
|
+
const value = ctx.json("presentation");
|
|
4285
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4286
|
+
throw new Error("--presentation must be a non-empty event-report display object.");
|
|
4287
|
+
}
|
|
4288
|
+
const presentation = value;
|
|
4289
|
+
const keys = Object.keys(presentation);
|
|
4290
|
+
if (keys.length === 0 || keys.some((key) => !["chart_type", "table_layout", "series"].includes(key))) {
|
|
4291
|
+
throw new Error("--presentation accepts only chart_type, table_layout, and series; use semantic names, not raw QP fields.");
|
|
4292
|
+
}
|
|
4293
|
+
if (presentation.chart_type === "table") {
|
|
4294
|
+
throw new Error("A table is a dashboard card display; use analysis dashboard-report update --chart-type table.");
|
|
4295
|
+
}
|
|
4296
|
+
if (Object.hasOwn(presentation, "chart_type") && (typeof presentation.chart_type !== "string" || !["line", "combo", "bar", "stacked", "cumulative", "pie"].includes(presentation.chart_type))) {
|
|
4297
|
+
throw new Error("--presentation.chart_type must be line, combo, bar, stacked, cumulative, or pie.");
|
|
4298
|
+
}
|
|
4299
|
+
if (Object.hasOwn(presentation, "table_layout") && (typeof presentation.table_layout !== "string" || !["date", "event", "group"].includes(presentation.table_layout))) {
|
|
4300
|
+
throw new Error("--presentation.table_layout must be date, event, or group.");
|
|
4301
|
+
}
|
|
4302
|
+
if (ctx.str("model-type") !== "" && ctx.str("model-type") !== "event") {
|
|
4303
|
+
throw new Error("--presentation is supported only for event reports.");
|
|
4304
|
+
}
|
|
4305
|
+
if (Object.hasOwn(presentation, "series")) validateSeries(presentation.series);
|
|
4306
|
+
}
|
|
4307
|
+
function validateSeries(value) {
|
|
4308
|
+
if (!Array.isArray(value)) throw new Error("--presentation.series must be an array; [] resets all series.");
|
|
4309
|
+
const indexes = /* @__PURE__ */ new Set();
|
|
4310
|
+
for (const [position, item] of value.entries()) {
|
|
4311
|
+
const path = `--presentation.series[${position}]`;
|
|
4312
|
+
if (!item || typeof item !== "object" || Array.isArray(item) || Object.keys(item).length !== 3 || Object.keys(item).some((key) => !["metric_index", "type", "axis"].includes(key))) {
|
|
4313
|
+
throw new Error(`${path} requires only metric_index, type, and axis, all three required.`);
|
|
4314
|
+
}
|
|
4315
|
+
const series = item;
|
|
4316
|
+
if (typeof series.metric_index !== "number" || !Number.isInteger(series.metric_index) || series.metric_index < 1) {
|
|
4317
|
+
throw new Error(`${path}.metric_index must be a positive 1-based integer position in definition.metrics.`);
|
|
4318
|
+
}
|
|
4319
|
+
if (indexes.has(series.metric_index)) throw new Error(`${path}.metric_index must not repeat another series binding.`);
|
|
4320
|
+
indexes.add(series.metric_index);
|
|
4321
|
+
if (typeof series.type !== "string" || !["bar", "line"].includes(series.type)) {
|
|
4322
|
+
throw new Error(`${path}.type must be bar or line.`);
|
|
4323
|
+
}
|
|
4324
|
+
if (typeof series.axis !== "string" || !["primary", "secondary"].includes(series.axis)) {
|
|
4325
|
+
throw new Error(`${path}.axis must be primary or secondary.`);
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
}
|
|
4329
|
+
|
|
3519
4330
|
// src/commands/te-analysis/report/create.ts
|
|
3520
4331
|
var reportCreate = createAnalysisCapabilityCommand({
|
|
3521
4332
|
resource: "report",
|
|
@@ -3527,6 +4338,7 @@ var reportCreate = createAnalysisCapabilityCommand({
|
|
|
3527
4338
|
{ name: "report-name", type: "string", required: true, desc: "Report display name." },
|
|
3528
4339
|
reportWriteModelTypeFlag(true),
|
|
3529
4340
|
reportWriteDefinitionFlag(true),
|
|
4341
|
+
reportPresentationFlag,
|
|
3530
4342
|
modelDefinitionIntentSnapshotFlag,
|
|
3531
4343
|
reportMetadataResolutionsFlag,
|
|
3532
4344
|
{ name: "report-desc", type: "string", required: false, desc: "Optional report description." },
|
|
@@ -3535,15 +4347,19 @@ var reportCreate = createAnalysisCapabilityCommand({
|
|
|
3535
4347
|
{ name: "dashboard-ids", type: "json", required: false, desc: "Optional dashboard ID array to associate after creation." }
|
|
3536
4348
|
],
|
|
3537
4349
|
risk: "write",
|
|
3538
|
-
validate:
|
|
4350
|
+
validate: (ctx) => {
|
|
4351
|
+
validateReportMetadataResolutions(ctx);
|
|
4352
|
+
validateReportPresentation(ctx);
|
|
4353
|
+
},
|
|
3539
4354
|
intentConsistency: { definitionFlag: "definition", modelTypeFlag: "model-type" },
|
|
3540
4355
|
buildInput: (ctx) => compactInput({
|
|
3541
4356
|
...projectInput(ctx),
|
|
3542
4357
|
report_name: ctx.str("report-name"),
|
|
3543
4358
|
model_type: ctx.str("model-type"),
|
|
3544
4359
|
definition: ctx.json("definition"),
|
|
4360
|
+
presentation: optionalJson(ctx, "presentation"),
|
|
3545
4361
|
resolutions: optionalJson(ctx, "resolutions"),
|
|
3546
|
-
report_desc: optionalString(ctx, "report-desc"),
|
|
4362
|
+
report_desc: optionalString(ctx, "report-desc") ?? "",
|
|
3547
4363
|
cache_seconds: optionalNumber(ctx, "cache-seconds"),
|
|
3548
4364
|
query_duration_ms: optionalNumber(ctx, "query-duration-ms"),
|
|
3549
4365
|
dashboard_ids: optionalJsonArray(ctx, "dashboard-ids")
|
|
@@ -3554,9 +4370,10 @@ var reportCreate = createAnalysisCapabilityCommand({
|
|
|
3554
4370
|
function validateReportUpdate(ctx) {
|
|
3555
4371
|
const hasDefinition = ctx.str("definition") !== "";
|
|
3556
4372
|
const hasResolutions = ctx.json("resolutions") !== void 0;
|
|
3557
|
-
const
|
|
3558
|
-
|
|
3559
|
-
|
|
4373
|
+
const hasPresentation = ctx.has?.("presentation") ?? ctx.str("presentation") !== "";
|
|
4374
|
+
const hasMetadataUpdate = ctx.str("report-name") !== "" || optionalStringPreserveEmpty(ctx, "report-desc") !== void 0;
|
|
4375
|
+
if (!hasDefinition && !hasMetadataUpdate && !hasPresentation) {
|
|
4376
|
+
throw new Error("At least one of --report-name, --report-desc, --definition, or --presentation is required.");
|
|
3560
4377
|
}
|
|
3561
4378
|
if (hasDefinition && ctx.str("model-type") === "") {
|
|
3562
4379
|
throw new Error("--model-type is required when --definition is provided.");
|
|
@@ -3565,20 +4382,22 @@ function validateReportUpdate(ctx) {
|
|
|
3565
4382
|
throw new Error("--resolutions requires --definition.");
|
|
3566
4383
|
}
|
|
3567
4384
|
validateReportMetadataResolutions(ctx);
|
|
4385
|
+
validateReportPresentation(ctx);
|
|
3568
4386
|
}
|
|
3569
4387
|
var reportUpdate = createAnalysisCapabilityCommand({
|
|
3570
4388
|
resource: "report",
|
|
3571
4389
|
command: "update",
|
|
3572
4390
|
capabilityId: "analysis.report.update",
|
|
3573
|
-
description: "Update report metadata
|
|
4391
|
+
description: "Update report metadata, AI QP definition, or event-report presentation through the capability gateway.",
|
|
3574
4392
|
flags: [
|
|
3575
4393
|
projectIdFlag,
|
|
3576
4394
|
{ name: "report-id", type: "number", required: true, desc: "Report ID to update." },
|
|
3577
4395
|
{ name: "report-version", type: "number", required: true, desc: "Current report version from report get." },
|
|
3578
4396
|
{ name: "report-name", type: "string", required: false, desc: "New report display name." },
|
|
3579
|
-
{ name: "report-desc", type: "string", required: false, desc: "New report description." },
|
|
4397
|
+
{ name: "report-desc", type: "string", required: false, desc: "New report description. Pass an empty string to clear it; omit to preserve it." },
|
|
3580
4398
|
reportWriteModelTypeFlag(false),
|
|
3581
4399
|
reportWriteDefinitionFlag(false),
|
|
4400
|
+
reportPresentationFlag,
|
|
3582
4401
|
modelDefinitionIntentSnapshotFlag,
|
|
3583
4402
|
reportMetadataResolutionsFlag,
|
|
3584
4403
|
{ name: "cache-seconds", type: "number", required: false, desc: "Optional cache duration in seconds." },
|
|
@@ -3592,9 +4411,10 @@ var reportUpdate = createAnalysisCapabilityCommand({
|
|
|
3592
4411
|
report_id: ctx.num("report-id"),
|
|
3593
4412
|
version: ctx.num("report-version"),
|
|
3594
4413
|
report_name: optionalString(ctx, "report-name"),
|
|
3595
|
-
report_desc:
|
|
4414
|
+
report_desc: optionalStringPreserveEmpty(ctx, "report-desc"),
|
|
3596
4415
|
model_type: optionalString(ctx, "model-type"),
|
|
3597
4416
|
definition: optionalJson(ctx, "definition"),
|
|
4417
|
+
presentation: optionalJson(ctx, "presentation"),
|
|
3598
4418
|
resolutions: optionalJson(ctx, "resolutions"),
|
|
3599
4419
|
cache_seconds: optionalNumber(ctx, "cache-seconds"),
|
|
3600
4420
|
query_duration_ms: optionalNumber(ctx, "query-duration-ms")
|
|
@@ -3841,7 +4661,7 @@ var dashboardList = createAnalysisCapabilityCommand({
|
|
|
3841
4661
|
resource: "dashboard",
|
|
3842
4662
|
command: "list",
|
|
3843
4663
|
capabilityId: "analysis.dashboard.list",
|
|
3844
|
-
description: "List dashboards
|
|
4664
|
+
description: "List dashboards the current user can update or manage. Read-only dashboards are excluded; use analysis asset search for readable asset discovery.",
|
|
3845
4665
|
flags: [
|
|
3846
4666
|
projectIdFlag,
|
|
3847
4667
|
queriesFlag,
|
|
@@ -4044,6 +4864,42 @@ var dashboardCopy = createAnalysisCapabilityCommand({
|
|
|
4044
4864
|
})
|
|
4045
4865
|
});
|
|
4046
4866
|
|
|
4867
|
+
// src/commands/te-analysis/dashboard/move.ts
|
|
4868
|
+
var dashboardMove = createAnalysisCapabilityCommand({
|
|
4869
|
+
resource: "dashboard",
|
|
4870
|
+
command: "move",
|
|
4871
|
+
capabilityId: "analysis.dashboard.move",
|
|
4872
|
+
description: "Move one or more dashboards to the same project-space root or folder.",
|
|
4873
|
+
flags: [
|
|
4874
|
+
projectIdFlag,
|
|
4875
|
+
{
|
|
4876
|
+
name: "dashboard-ids",
|
|
4877
|
+
type: "json",
|
|
4878
|
+
required: true,
|
|
4879
|
+
desc: "Dashboard ID array. Pass a one-item array to move a single dashboard."
|
|
4880
|
+
},
|
|
4881
|
+
{
|
|
4882
|
+
name: "to-space-id",
|
|
4883
|
+
type: "number",
|
|
4884
|
+
required: true,
|
|
4885
|
+
desc: "Target project space ID."
|
|
4886
|
+
},
|
|
4887
|
+
{
|
|
4888
|
+
name: "to-folder-id",
|
|
4889
|
+
type: "number",
|
|
4890
|
+
required: false,
|
|
4891
|
+
desc: "Target folder ID within the target project space. Omit to move to the space root."
|
|
4892
|
+
}
|
|
4893
|
+
],
|
|
4894
|
+
risk: "write",
|
|
4895
|
+
buildInput: (ctx) => compactInput({
|
|
4896
|
+
...projectInput(ctx),
|
|
4897
|
+
dashboard_ids: jsonArray(ctx, "dashboard-ids"),
|
|
4898
|
+
to_space_id: ctx.num("to-space-id"),
|
|
4899
|
+
to_folder_id: optionalNumber(ctx, "to-folder-id")
|
|
4900
|
+
})
|
|
4901
|
+
});
|
|
4902
|
+
|
|
4047
4903
|
// src/commands/te-analysis/dashboard/freeze.ts
|
|
4048
4904
|
var dashboardFreeze = createAnalysisCapabilityCommand({
|
|
4049
4905
|
resource: "dashboard",
|
|
@@ -4102,6 +4958,7 @@ var commands19 = [
|
|
|
4102
4958
|
dashboardDelete,
|
|
4103
4959
|
dashboardHandover,
|
|
4104
4960
|
dashboardCopy,
|
|
4961
|
+
dashboardMove,
|
|
4105
4962
|
dashboardFreeze,
|
|
4106
4963
|
dashboardAbnormalGet,
|
|
4107
4964
|
dashboardTaskStatus
|
|
@@ -4127,9 +4984,71 @@ var dashboardReportAdd = createAnalysisCapabilityCommand({
|
|
|
4127
4984
|
})
|
|
4128
4985
|
});
|
|
4129
4986
|
|
|
4987
|
+
// src/commands/te-analysis/dashboard-report/get.ts
|
|
4988
|
+
var dashboardReportGet = createAnalysisCapabilityCommand({
|
|
4989
|
+
resource: "dashboard-report",
|
|
4990
|
+
command: "get",
|
|
4991
|
+
capabilityId: "analysis.dashboard_report.get",
|
|
4992
|
+
description: "Get an event report card presentation on one analysis dashboard, not the source report definition.",
|
|
4993
|
+
flags: [
|
|
4994
|
+
projectIdFlag,
|
|
4995
|
+
{ name: "dashboard-id", type: "number", required: true, desc: "Dashboard containing the report card." },
|
|
4996
|
+
{ name: "report-id", type: "number", required: true, desc: "Existing event report ID on that dashboard." }
|
|
4997
|
+
],
|
|
4998
|
+
risk: "read",
|
|
4999
|
+
buildInput: (ctx) => ({
|
|
5000
|
+
...projectInput(ctx),
|
|
5001
|
+
dashboard_id: ctx.num("dashboard-id"),
|
|
5002
|
+
report_id: ctx.num("report-id")
|
|
5003
|
+
})
|
|
5004
|
+
});
|
|
5005
|
+
|
|
5006
|
+
// src/commands/te-analysis/dashboard-report/update.ts
|
|
5007
|
+
var dashboardReportUpdate = createAnalysisCapabilityCommand({
|
|
5008
|
+
resource: "dashboard-report",
|
|
5009
|
+
command: "update",
|
|
5010
|
+
capabilityId: "analysis.dashboard_report.update",
|
|
5011
|
+
description: "Update one event report card presentation without changing the source report definition or other dashboards.",
|
|
5012
|
+
flags: [
|
|
5013
|
+
projectIdFlag,
|
|
5014
|
+
{ name: "dashboard-id", type: "number", required: true, desc: "Dashboard containing the report card." },
|
|
5015
|
+
{ name: "report-id", type: "number", required: true, desc: "Existing event report ID on that dashboard." },
|
|
5016
|
+
{ name: "chart-type", type: "string", required: false, desc: "Card chart type: line, combo, bar, stacked, cumulative, pie, or table. Combo inherits existing source-report series; this command cannot edit series. A pure line card requires resetting source combo first. Gateway validates compatibility with the saved event definition." },
|
|
5017
|
+
{ name: "table-layout", type: "string", required: false, desc: "Table layout: date, event, or group. Omit to preserve it." },
|
|
5018
|
+
{ name: "date-outside", type: "boolean", required: false, desc: "Show dates outside the table. True requires a grouped table with a non-date layout; also choose event/group layout when inherited. Pass false to clear, omit to preserve." }
|
|
5019
|
+
],
|
|
5020
|
+
risk: "write",
|
|
5021
|
+
validate: (ctx) => {
|
|
5022
|
+
const chartType = optionalString(ctx, "chart-type");
|
|
5023
|
+
const tableLayout = optionalString(ctx, "table-layout");
|
|
5024
|
+
const dateOutside = optionalBoolean(ctx, "date-outside");
|
|
5025
|
+
if (chartType === void 0 && tableLayout === void 0 && dateOutside === void 0) {
|
|
5026
|
+
throw new Error("At least one of --chart-type, --table-layout, or --date-outside is required.");
|
|
5027
|
+
}
|
|
5028
|
+
if (chartType !== void 0 && !["line", "combo", "bar", "stacked", "cumulative", "pie", "table"].includes(chartType)) {
|
|
5029
|
+
throw new Error("--chart-type must be line, combo, bar, stacked, cumulative, pie, or table.");
|
|
5030
|
+
}
|
|
5031
|
+
if (tableLayout !== void 0 && !["date", "event", "group"].includes(tableLayout)) {
|
|
5032
|
+
throw new Error("--table-layout must be date, event, or group.");
|
|
5033
|
+
}
|
|
5034
|
+
},
|
|
5035
|
+
buildInput: (ctx) => ({
|
|
5036
|
+
...projectInput(ctx),
|
|
5037
|
+
dashboard_id: ctx.num("dashboard-id"),
|
|
5038
|
+
report_id: ctx.num("report-id"),
|
|
5039
|
+
presentation: compactInput({
|
|
5040
|
+
chart_type: optionalString(ctx, "chart-type"),
|
|
5041
|
+
table_layout: optionalString(ctx, "table-layout"),
|
|
5042
|
+
date_outside: optionalBoolean(ctx, "date-outside")
|
|
5043
|
+
})
|
|
5044
|
+
})
|
|
5045
|
+
});
|
|
5046
|
+
|
|
4130
5047
|
// src/commands/te-analysis/dashboard-report/index.ts
|
|
4131
5048
|
var commands20 = [
|
|
4132
|
-
dashboardReportAdd
|
|
5049
|
+
dashboardReportAdd,
|
|
5050
|
+
dashboardReportGet,
|
|
5051
|
+
dashboardReportUpdate
|
|
4133
5052
|
];
|
|
4134
5053
|
var dashboard_report_default = commands20;
|
|
4135
5054
|
|
|
@@ -4176,14 +5095,13 @@ var dashboardReportDataExport = createAnalysisCapabilityCommand({
|
|
|
4176
5095
|
clusterQueryScopeFlag,
|
|
4177
5096
|
slaveClusterIdFlag,
|
|
4178
5097
|
{ name: "zone-offset", type: "number", required: false, desc: reportDataZoneOffsetDescription },
|
|
4179
|
-
{ name: "use-cache", type: "boolean", required: false, desc: "Whether to use cache. Default: true." },
|
|
4180
5098
|
{ name: "request-id", type: "string", required: false, desc: "Optional cli_<32 lowercase hex> request ID. Generated when omitted." },
|
|
4181
5099
|
asyncTimeoutSecondsFlag,
|
|
4182
5100
|
{ name: "artifact-format", type: "string", required: false, desc: "Artifact format. Only jsonl is supported." }
|
|
4183
5101
|
],
|
|
4184
5102
|
risk: "read",
|
|
4185
5103
|
validate: validateClusterQueryRouting,
|
|
4186
|
-
buildInput: dashboardReportDataInput
|
|
5104
|
+
buildInput: (ctx) => dashboardReportDataInput(ctx, false)
|
|
4187
5105
|
});
|
|
4188
5106
|
|
|
4189
5107
|
// src/commands/te-analysis/dashboard-report-data/index.ts
|
|
@@ -6592,7 +7510,7 @@ var sqlTableColumns = createAnalysisCapabilityCommand({
|
|
|
6592
7510
|
name: "table-ref",
|
|
6593
7511
|
type: "string",
|
|
6594
7512
|
required: true,
|
|
6595
|
-
desc: "Exact table_ref returned by analysis sql-table list; a unique table-only reference is also accepted."
|
|
7513
|
+
desc: "Exact table_ref or quoted sql_reference returned by analysis sql-table list; a unique table-only reference is also accepted."
|
|
6596
7514
|
},
|
|
6597
7515
|
sqlTableUsageFlag
|
|
6598
7516
|
],
|
|
@@ -6609,7 +7527,7 @@ var sqlTableList = createAnalysisCapabilityCommand({
|
|
|
6609
7527
|
resource: "sql-table",
|
|
6610
7528
|
command: "list",
|
|
6611
7529
|
capabilityId: "analysis.sql_table.list",
|
|
6612
|
-
description: "List server-authoritative SQL table references queryable by the current user in a project.",
|
|
7530
|
+
description: "List server-authoritative SQL table references queryable by the current user in a project, including authorized space tables. Use sql_reference when copying a table into SQL.",
|
|
6613
7531
|
flags: [projectIdFlag, queriesFlag, directoryLimitFlag, directoryOffsetFlag, sqlTableUsageFlag],
|
|
6614
7532
|
risk: "read",
|
|
6615
7533
|
validate: validateQueriesFlag,
|
|
@@ -9773,14 +10691,14 @@ var monitorTimeFields = [
|
|
|
9773
10691
|
type: "string",
|
|
9774
10692
|
required: true,
|
|
9775
10693
|
pattern: "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
|
|
9776
|
-
desc: "Inclusive
|
|
10694
|
+
desc: "Inclusive completion-time range start, yyyy-MM-dd HH:mm:ss."
|
|
9777
10695
|
},
|
|
9778
10696
|
{
|
|
9779
10697
|
flag: "end-time",
|
|
9780
10698
|
type: "string",
|
|
9781
10699
|
required: true,
|
|
9782
10700
|
pattern: "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
|
|
9783
|
-
desc: "Inclusive
|
|
10701
|
+
desc: "Inclusive completion-time range end, including the entire second, yyyy-MM-dd HH:mm:ss."
|
|
9784
10702
|
}
|
|
9785
10703
|
];
|
|
9786
10704
|
function validateTaskQueryInput(input) {
|
|
@@ -9844,6 +10762,27 @@ var systemMonitoringCommands = [
|
|
|
9844
10762
|
],
|
|
9845
10763
|
validate: (_ctx, input) => validateTaskQueryInput(input)
|
|
9846
10764
|
}),
|
|
10765
|
+
defineSystemCommand({
|
|
10766
|
+
resource: "query-task",
|
|
10767
|
+
command: "realtime-list",
|
|
10768
|
+
capabilityId: "system.query_task.realtime_list",
|
|
10769
|
+
description: "List a bounded realtime query-monitor snapshot; use query-task list for historical logs.",
|
|
10770
|
+
risk: "read",
|
|
10771
|
+
fields: [
|
|
10772
|
+
{ flag: "duration-minutes", type: "number", min: 1, max: 30, desc: "Realtime window in minutes. Default: 30." },
|
|
10773
|
+
...monitorScopeFields,
|
|
10774
|
+
{ flag: "cluster-names", type: "json", required: true, array: true, desc: "Query cluster-name JSON array." },
|
|
10775
|
+
{ flag: "status-codes", type: "json", array: true, desc: "Optional task status-code JSON array." },
|
|
10776
|
+
{ flag: "limit", type: "number", min: 1, max: 200, desc: "Maximum returned tasks. Default: 100, max: 200." }
|
|
10777
|
+
],
|
|
10778
|
+
validate: (_ctx, input) => {
|
|
10779
|
+
validateMonitorScope(input);
|
|
10780
|
+
requireAtLeastOne(input, ["cluster_names"], "--cluster-names must be a non-empty JSON array.");
|
|
10781
|
+
if (input.status_codes !== void 0) {
|
|
10782
|
+
requireAtLeastOne(input, ["status_codes"], "--status-codes must be a non-empty JSON array.");
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10785
|
+
}),
|
|
9847
10786
|
defineSystemCommand({
|
|
9848
10787
|
resource: "query-task",
|
|
9849
10788
|
command: "get",
|
|
@@ -10186,6 +11125,89 @@ var commands81 = [
|
|
|
10186
11125
|
];
|
|
10187
11126
|
var system_default = commands81;
|
|
10188
11127
|
|
|
11128
|
+
// src/commands/te-analysis/feedback/submit.ts
|
|
11129
|
+
import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
|
|
11130
|
+
var analysisQueryCapabilities = /* @__PURE__ */ new Set([
|
|
11131
|
+
"analysis.adhoc.run",
|
|
11132
|
+
"analysis.adhoc.export",
|
|
11133
|
+
"analysis.report_data.run",
|
|
11134
|
+
"analysis.report_data.export",
|
|
11135
|
+
"analysis.dashboard_report_data.run",
|
|
11136
|
+
"analysis.dashboard_report_data.export",
|
|
11137
|
+
"analysis.bi_panel_page_data.run",
|
|
11138
|
+
"analysis.bi_panel_page_data.export",
|
|
11139
|
+
"analysis.event_detail.run",
|
|
11140
|
+
"analysis.event_detail.export",
|
|
11141
|
+
"analysis.entity_detail.run",
|
|
11142
|
+
"analysis.entity_detail.export",
|
|
11143
|
+
"analysis.query.drilldown_events",
|
|
11144
|
+
"analysis.query.drilldown_events_export",
|
|
11145
|
+
"analysis.query.drilldown_entities",
|
|
11146
|
+
"analysis.query.drilldown_entities_export",
|
|
11147
|
+
"analysis.query.drilldown_user_events",
|
|
11148
|
+
"analysis.query.drilldown_user_events_export",
|
|
11149
|
+
"analysis.query.drilldown_session_details"
|
|
11150
|
+
]);
|
|
11151
|
+
function analysisFeedbackInput(ctx) {
|
|
11152
|
+
if (!ctx.bool("query-completed")) throw new CliValidationError("Feedback requires a completed data query and final analysis answer.");
|
|
11153
|
+
const queryCapabilityId = ctx.str("query-capability-id");
|
|
11154
|
+
if (!analysisQueryCapabilities.has(queryCapabilityId)) throw new CliValidationError("query-capability-id must identify an executed analysis data query.");
|
|
11155
|
+
const ratings = ["satisfied", "partially_satisfied", "dissatisfied", "unable_to_judge"];
|
|
11156
|
+
const satisfaction = ctx.str("satisfaction");
|
|
11157
|
+
if (!ratings.includes(satisfaction)) throw new CliValidationError("satisfaction must be an explicit user feedback category.");
|
|
11158
|
+
const feedbackText = ctx.str("feedback-text");
|
|
11159
|
+
if (!feedbackText.trim() || feedbackText.length > 2048) throw new CliValidationError("feedback-text must contain original user feedback up to 2048 characters.");
|
|
11160
|
+
const context = readCliAgentContext();
|
|
11161
|
+
if (!context.agent_session_id) throw new CliValidationError("The Agent context file must contain the evaluated agent_session_id.");
|
|
11162
|
+
const turns = ctx.json("target-turn-ids") ?? [];
|
|
11163
|
+
if (!Array.isArray(turns) || turns.length > 32 || turns.some((id) => typeof id !== "string" || !id.trim() || id.length > 191)) {
|
|
11164
|
+
throw new CliValidationError("target-turn-ids must be an array of at most 32 nonblank existing turn IDs.");
|
|
11165
|
+
}
|
|
11166
|
+
if (turns.includes(context.agent_turn_id)) throw new CliValidationError("target-turn-ids must reference analysis turns, not the feedback turn.");
|
|
11167
|
+
const targetTurns = [...new Set(turns)];
|
|
11168
|
+
const suppliedId = ctx.str("feedback-id");
|
|
11169
|
+
const feedbackId = suppliedId || (context.agent_turn_id ? createHash4("sha256").update(JSON.stringify([context.agent_session_id, context.agent_turn_id, targetTurns, queryCapabilityId, satisfaction, feedbackText])).digest("hex") : randomUUID2());
|
|
11170
|
+
if (!feedbackId.trim() || feedbackId.length > 128) throw new CliValidationError("feedback-id must be a nonblank string up to 128 characters.");
|
|
11171
|
+
const routeSummary = ctx.str("route-summary");
|
|
11172
|
+
if (routeSummary.length > 2048) throw new CliValidationError("route-summary must be at most 2048 characters.");
|
|
11173
|
+
const projectId = ctx.optionalNum("project-id");
|
|
11174
|
+
if (projectId !== void 0 && (!Number.isInteger(projectId) || projectId <= 0)) {
|
|
11175
|
+
throw new CliValidationError("project-id must be a positive integer.");
|
|
11176
|
+
}
|
|
11177
|
+
return {
|
|
11178
|
+
feedback_id: feedbackId,
|
|
11179
|
+
agent_session_id: context.agent_session_id,
|
|
11180
|
+
target_turn_ids: targetTurns,
|
|
11181
|
+
query_completed: true,
|
|
11182
|
+
query_capability_id: queryCapabilityId,
|
|
11183
|
+
satisfaction,
|
|
11184
|
+
feedback_text: feedbackText,
|
|
11185
|
+
...projectId !== void 0 ? { project_id: projectId } : {},
|
|
11186
|
+
...routeSummary.trim() ? { route_summary: routeSummary } : {}
|
|
11187
|
+
};
|
|
11188
|
+
}
|
|
11189
|
+
var analysisFeedbackSubmit = createAnalysisCapabilityCommand({
|
|
11190
|
+
resource: "feedback",
|
|
11191
|
+
command: "submit",
|
|
11192
|
+
capabilityId: "analysis.feedback.submit",
|
|
11193
|
+
risk: "write",
|
|
11194
|
+
description: "Submit explicit user feedback after a completed analysis data query and final answer. Reuses Agent session and analysis turn IDs; never submits an answer body.",
|
|
11195
|
+
flags: [
|
|
11196
|
+
{ name: "query-completed", type: "boolean", desc: "Confirm that query results and the final analysis answer have been delivered." },
|
|
11197
|
+
{ name: "query-capability-id", type: "string", required: true, desc: "Executed analysis data-query capability ID in the evaluated turns." },
|
|
11198
|
+
{ name: "satisfaction", type: "string", required: true, desc: "Explicit rating: satisfied, partially_satisfied, dissatisfied, or unable_to_judge." },
|
|
11199
|
+
{ name: "feedback-text", type: "string", required: true, sensitive: true, desc: "Original user feedback, up to 2048 characters. No answer content." },
|
|
11200
|
+
{ name: "target-turn-ids", type: "json", desc: "JSON array of evaluated analysis turn IDs; omit only when unknown." },
|
|
11201
|
+
{ name: "route-summary", type: "string", sensitive: true, desc: "Optional brief verifiable route and asset-selection rationale. No answer content." },
|
|
11202
|
+
{ name: "feedback-id", type: "string", desc: "Stable feedback ID for retries; defaults to current session/feedback-turn fingerprint when available." },
|
|
11203
|
+
{ name: "project-id", type: "number", desc: "Evaluated analysis project ID when available." }
|
|
11204
|
+
],
|
|
11205
|
+
buildInput: analysisFeedbackInput
|
|
11206
|
+
});
|
|
11207
|
+
|
|
11208
|
+
// src/commands/te-analysis/feedback/index.ts
|
|
11209
|
+
var feedback_default = [analysisFeedbackSubmit];
|
|
11210
|
+
|
|
10189
11211
|
// src/commands/te-analysis/index.ts
|
|
10190
11212
|
registerCapabilityGatewayRoute("analysis", { gatewayDomain: "analysis" });
|
|
10191
11213
|
registerCapabilityGatewayRoute("project", { gatewayDomain: "analysis" });
|
|
@@ -10232,7 +11254,8 @@ var baseCommands = [
|
|
|
10232
11254
|
...alert_detail_default,
|
|
10233
11255
|
...alert_job_default,
|
|
10234
11256
|
...alert_notice_config_default,
|
|
10235
|
-
...system_default
|
|
11257
|
+
...system_default,
|
|
11258
|
+
...feedback_default
|
|
10236
11259
|
];
|
|
10237
11260
|
var commands82 = [...baseCommands];
|
|
10238
11261
|
var te_analysis_default = commands82;
|