qingflow-mcp 0.3.8 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -12
- package/dist/server.js +421 -199
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -161,17 +161,20 @@ Summary mode output:
|
|
|
161
161
|
|
|
162
162
|
1. `summary`: aggregated stats (`total_count`, `total_amount`, `by_day`, `missing_count`).
|
|
163
163
|
2. `rows`: strict column rows (only requested `select_columns`).
|
|
164
|
-
3. `meta`: field mapping, filter scope, stat policy, execution limits.
|
|
164
|
+
3. `meta`: field mapping, filter scope, stat policy, execution limits (`output_profile=verbose` only).
|
|
165
165
|
|
|
166
166
|
Return shape:
|
|
167
167
|
|
|
168
|
-
1. success: structured payload `{ "ok": true, "data":
|
|
168
|
+
1. success: structured payload `{ "ok": true, "data": ... }` (`meta` only in `output_profile=verbose`)
|
|
169
169
|
2. failure: MCP `isError=true`, and text content is JSON payload like `{ "ok": false, "message": ..., ... }`
|
|
170
170
|
3. incomplete strict queries fail with `{ "code": "NEED_MORE_DATA", "status": "need_more_data", ... }`
|
|
171
171
|
|
|
172
172
|
Deterministic read protocol (list/summary/aggregate):
|
|
173
173
|
|
|
174
|
-
1.
|
|
174
|
+
1. output profile:
|
|
175
|
+
- default `output_profile=compact`: return core data only (`rows/row/groups/summary` + `next_page_token`)
|
|
176
|
+
- `output_profile=verbose`: include full contract (`completeness` + `evidence` + `meta`)
|
|
177
|
+
2. when `output_profile=verbose`, `completeness` fields are:
|
|
175
178
|
- `result_amount`
|
|
176
179
|
- `returned_items`
|
|
177
180
|
- `fetched_pages`
|
|
@@ -183,15 +186,14 @@ Deterministic read protocol (list/summary/aggregate):
|
|
|
183
186
|
- `partial`
|
|
184
187
|
- `omitted_items`
|
|
185
188
|
- `omitted_chars`
|
|
186
|
-
|
|
189
|
+
3. when `output_profile=verbose`, `evidence` fields are:
|
|
187
190
|
- `query_id`
|
|
188
191
|
- `app_key`
|
|
189
192
|
- `filters`
|
|
190
193
|
- `selected_columns`
|
|
191
194
|
- `time_range`
|
|
192
195
|
- `source_pages`
|
|
193
|
-
|
|
194
|
-
4. Success payloads also expose top-level `error_code=null`, `fix_hint=null`, `next_page_token`.
|
|
196
|
+
4. `strict_full=true` makes incomplete results fail fast with `NEED_MORE_DATA`.
|
|
195
197
|
5. Error payloads expose `error_code` and `fix_hint` for actionable retries.
|
|
196
198
|
6. Parameter tolerance supports stringified JSON and numeric/boolean strings for key query fields.
|
|
197
199
|
|
|
@@ -201,17 +203,17 @@ Strict mode (`qf_records_list`):
|
|
|
201
203
|
|
|
202
204
|
1. `select_columns` is required.
|
|
203
205
|
2. `include_answers=false` is not allowed.
|
|
204
|
-
3. Output `
|
|
206
|
+
3. Output is flat `rows[]` (no raw `answers` payload).
|
|
205
207
|
|
|
206
208
|
1. For `qf_records_list.sort[].que_id`, use a real field `que_id` (numeric) or exact field title from `qf_form_get`.
|
|
207
209
|
2. Avoid aliases like `create_time`; Qingflow often rejects them.
|
|
208
210
|
3. Use `max_rows` (or `max_items`) to cap returned rows. Default row cap is 200.
|
|
209
|
-
4. Use `max_columns` to cap
|
|
211
|
+
4. Use `max_columns` to cap returned columns per row.
|
|
210
212
|
5. Use `select_columns` to return only specific columns (supports `que_id` or exact field title).
|
|
211
213
|
6. The server may still trim by response-size guardrail (`QINGFLOW_LIST_MAX_ITEMS_BYTES`) when payload is too large.
|
|
212
214
|
7. Use `requested_pages` and `scan_max_pages` for deterministic page scan.
|
|
213
215
|
8. Continue with `page_token` from previous `next_page_token`.
|
|
214
|
-
9. Column limits: `select_columns <=
|
|
216
|
+
9. Column limits: `select_columns <= 3`, `max_columns <= 3`.
|
|
215
217
|
|
|
216
218
|
Example:
|
|
217
219
|
|
|
@@ -224,8 +226,9 @@ Example:
|
|
|
224
226
|
"scan_max_pages": 1,
|
|
225
227
|
"include_answers": true,
|
|
226
228
|
"max_rows": 10,
|
|
227
|
-
"max_columns":
|
|
229
|
+
"max_columns": 3,
|
|
228
230
|
"select_columns": [1, "客户名称", "1003"],
|
|
231
|
+
"output_profile": "compact",
|
|
229
232
|
"strict_full": false
|
|
230
233
|
}
|
|
231
234
|
```
|
|
@@ -235,8 +238,9 @@ For single record details (`qf_record_get`), the same column controls are suppor
|
|
|
235
238
|
```json
|
|
236
239
|
{
|
|
237
240
|
"apply_id": "497600278750478338",
|
|
238
|
-
"max_columns":
|
|
239
|
-
"select_columns": [1, "客户名称"]
|
|
241
|
+
"max_columns": 3,
|
|
242
|
+
"select_columns": [1, "客户名称"],
|
|
243
|
+
"output_profile": "compact"
|
|
240
244
|
}
|
|
241
245
|
```
|
|
242
246
|
|
package/dist/server.js
CHANGED
|
@@ -46,10 +46,12 @@ const formCache = new Map();
|
|
|
46
46
|
const DEFAULT_PAGE_SIZE = 50;
|
|
47
47
|
const DEFAULT_SCAN_MAX_PAGES = 10;
|
|
48
48
|
const DEFAULT_ROW_LIMIT = 200;
|
|
49
|
+
const MAX_COLUMN_LIMIT = 3;
|
|
50
|
+
const DEFAULT_OUTPUT_PROFILE = "compact";
|
|
49
51
|
const MAX_LIST_ITEMS_BYTES = toPositiveInt(process.env.QINGFLOW_LIST_MAX_ITEMS_BYTES) ?? 400000;
|
|
50
52
|
const REQUEST_TIMEOUT_MS = toPositiveInt(process.env.QINGFLOW_REQUEST_TIMEOUT_MS) ?? 18000;
|
|
51
53
|
const EXECUTION_BUDGET_MS = toPositiveInt(process.env.QINGFLOW_EXECUTION_BUDGET_MS) ?? 20000;
|
|
52
|
-
const SERVER_VERSION = "0.3.
|
|
54
|
+
const SERVER_VERSION = "0.3.10";
|
|
53
55
|
const accessToken = process.env.QINGFLOW_ACCESS_TOKEN;
|
|
54
56
|
const baseUrl = process.env.QINGFLOW_BASE_URL;
|
|
55
57
|
if (!accessToken) {
|
|
@@ -119,6 +121,7 @@ const apiMetaSchema = z.object({
|
|
|
119
121
|
provider_err_msg: z.string().nullable(),
|
|
120
122
|
base_url: z.string()
|
|
121
123
|
});
|
|
124
|
+
const outputProfileSchema = z.enum(["compact", "verbose"]);
|
|
122
125
|
const completenessSchema = z.object({
|
|
123
126
|
result_amount: z.number().int().nonnegative(),
|
|
124
127
|
returned_items: z.number().int().nonnegative(),
|
|
@@ -148,11 +151,12 @@ const evidenceSchema = z.object({
|
|
|
148
151
|
source_pages: z.array(z.number().int().positive())
|
|
149
152
|
});
|
|
150
153
|
const queryContractFields = {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
output_profile: outputProfileSchema.optional(),
|
|
155
|
+
completeness: completenessSchema.optional(),
|
|
156
|
+
evidence: z.record(z.unknown()).optional(),
|
|
157
|
+
error_code: z.null().optional(),
|
|
158
|
+
fix_hint: z.null().optional(),
|
|
159
|
+
next_page_token: z.string().nullable().optional()
|
|
156
160
|
};
|
|
157
161
|
const appSchema = z.object({
|
|
158
162
|
appKey: z.string(),
|
|
@@ -165,14 +169,6 @@ const fieldSummarySchema = z.object({
|
|
|
165
169
|
has_sub_fields: z.boolean(),
|
|
166
170
|
sub_field_count: z.number().int().nonnegative()
|
|
167
171
|
});
|
|
168
|
-
const recordItemSchema = z.object({
|
|
169
|
-
apply_id: z.union([z.string(), z.number(), z.null()]),
|
|
170
|
-
app_key: z.string().nullable(),
|
|
171
|
-
apply_num: z.union([z.number(), z.string(), z.null()]),
|
|
172
|
-
apply_time: z.string().nullable(),
|
|
173
|
-
last_update_time: z.string().nullable(),
|
|
174
|
-
answers: z.array(z.unknown()).optional()
|
|
175
|
-
});
|
|
176
172
|
const operationResultSchema = z.object({
|
|
177
173
|
request_id: z.string(),
|
|
178
174
|
operation_result: z.unknown()
|
|
@@ -293,15 +289,16 @@ const listInputSchema = z
|
|
|
293
289
|
.optional(),
|
|
294
290
|
max_rows: z.number().int().positive().max(200).optional(),
|
|
295
291
|
max_items: z.number().int().positive().max(200).optional(),
|
|
296
|
-
max_columns: z.number().int().positive().max(
|
|
292
|
+
max_columns: z.number().int().positive().max(MAX_COLUMN_LIMIT).optional(),
|
|
297
293
|
// Strict mode: callers must explicitly choose columns.
|
|
298
294
|
select_columns: z
|
|
299
295
|
.array(z.union([z.string().min(1), z.number().int()]))
|
|
300
296
|
.min(1)
|
|
301
|
-
.max(
|
|
297
|
+
.max(MAX_COLUMN_LIMIT)
|
|
302
298
|
.optional(),
|
|
303
299
|
include_answers: z.boolean().optional(),
|
|
304
|
-
strict_full: z.boolean().optional()
|
|
300
|
+
strict_full: z.boolean().optional(),
|
|
301
|
+
output_profile: outputProfileSchema.optional()
|
|
305
302
|
}))
|
|
306
303
|
.refine((value) => value.include_answers !== false, {
|
|
307
304
|
message: "include_answers=false is not allowed in strict column mode"
|
|
@@ -319,7 +316,7 @@ const listSuccessOutputSchema = z.object({
|
|
|
319
316
|
page_amount: z.number().int().nonnegative().nullable(),
|
|
320
317
|
result_amount: z.number().int().nonnegative()
|
|
321
318
|
}),
|
|
322
|
-
|
|
319
|
+
rows: z.array(z.record(z.unknown())),
|
|
323
320
|
applied_limits: z
|
|
324
321
|
.object({
|
|
325
322
|
include_answers: z.boolean(),
|
|
@@ -328,43 +325,43 @@ const listSuccessOutputSchema = z.object({
|
|
|
328
325
|
selected_columns: z.array(z.string())
|
|
329
326
|
})
|
|
330
327
|
.optional(),
|
|
331
|
-
completeness: completenessSchema,
|
|
332
|
-
evidence: evidenceSchema
|
|
328
|
+
completeness: completenessSchema.optional(),
|
|
329
|
+
evidence: evidenceSchema.optional()
|
|
333
330
|
}),
|
|
334
331
|
...queryContractFields,
|
|
335
|
-
meta: apiMetaSchema
|
|
332
|
+
meta: apiMetaSchema.optional()
|
|
336
333
|
});
|
|
337
334
|
const listOutputSchema = listSuccessOutputSchema;
|
|
338
335
|
const recordGetInputSchema = z.preprocess(normalizeRecordGetInput, z.object({
|
|
339
336
|
apply_id: z.union([z.string().min(1), z.number().int()]),
|
|
340
|
-
max_columns: z.number().int().positive().max(
|
|
337
|
+
max_columns: z.number().int().positive().max(MAX_COLUMN_LIMIT).optional(),
|
|
341
338
|
select_columns: z
|
|
342
339
|
.array(z.union([z.string().min(1), z.number().int()]))
|
|
343
340
|
.min(1)
|
|
344
|
-
.max(
|
|
345
|
-
.optional()
|
|
341
|
+
.max(MAX_COLUMN_LIMIT)
|
|
342
|
+
.optional(),
|
|
343
|
+
output_profile: outputProfileSchema.optional()
|
|
346
344
|
}));
|
|
347
345
|
const recordGetSuccessOutputSchema = z.object({
|
|
348
346
|
ok: z.literal(true),
|
|
349
347
|
data: z.object({
|
|
350
348
|
apply_id: z.union([z.string(), z.number(), z.null()]),
|
|
351
|
-
|
|
352
|
-
record: z.unknown(),
|
|
349
|
+
row: z.record(z.unknown()),
|
|
353
350
|
applied_limits: z
|
|
354
351
|
.object({
|
|
355
352
|
column_cap: z.number().int().positive().nullable(),
|
|
356
353
|
selected_columns: z.array(z.string()).nullable()
|
|
357
354
|
})
|
|
358
355
|
.optional(),
|
|
359
|
-
completeness: completenessSchema,
|
|
356
|
+
completeness: completenessSchema.optional(),
|
|
360
357
|
evidence: z.object({
|
|
361
358
|
query_id: z.string(),
|
|
362
359
|
apply_id: z.string(),
|
|
363
360
|
selected_columns: z.array(z.string())
|
|
364
|
-
})
|
|
361
|
+
}).optional()
|
|
365
362
|
}),
|
|
366
363
|
...queryContractFields,
|
|
367
|
-
meta: apiMetaSchema
|
|
364
|
+
meta: apiMetaSchema.optional()
|
|
368
365
|
});
|
|
369
366
|
const recordGetOutputSchema = recordGetSuccessOutputSchema;
|
|
370
367
|
const createInputSchema = z
|
|
@@ -476,11 +473,11 @@ const queryInputSchema = z
|
|
|
476
473
|
.optional(),
|
|
477
474
|
max_rows: z.number().int().positive().max(200).optional(),
|
|
478
475
|
max_items: z.number().int().positive().max(200).optional(),
|
|
479
|
-
max_columns: z.number().int().positive().max(
|
|
476
|
+
max_columns: z.number().int().positive().max(MAX_COLUMN_LIMIT).optional(),
|
|
480
477
|
select_columns: z
|
|
481
478
|
.array(z.union([z.string().min(1), z.number().int()]))
|
|
482
479
|
.min(1)
|
|
483
|
-
.max(
|
|
480
|
+
.max(MAX_COLUMN_LIMIT)
|
|
484
481
|
.optional(),
|
|
485
482
|
include_answers: z.boolean().optional(),
|
|
486
483
|
amount_column: z.union([z.string().min(1), z.number().int()]).optional(),
|
|
@@ -499,7 +496,8 @@ const queryInputSchema = z
|
|
|
499
496
|
})
|
|
500
497
|
.optional(),
|
|
501
498
|
scan_max_pages: z.number().int().positive().max(500).optional(),
|
|
502
|
-
strict_full: z.boolean().optional()
|
|
499
|
+
strict_full: z.boolean().optional(),
|
|
500
|
+
output_profile: outputProfileSchema.optional()
|
|
503
501
|
}))
|
|
504
502
|
.refine((value) => !(value.page_num !== undefined && value.page_token !== undefined), {
|
|
505
503
|
message: "page_num and page_token cannot be used together"
|
|
@@ -516,8 +514,8 @@ const querySummaryOutputSchema = z.object({
|
|
|
516
514
|
missing_count: z.number().int().nonnegative()
|
|
517
515
|
}),
|
|
518
516
|
rows: z.array(z.record(z.unknown())),
|
|
519
|
-
completeness: completenessSchema,
|
|
520
|
-
evidence: evidenceSchema,
|
|
517
|
+
completeness: completenessSchema.optional(),
|
|
518
|
+
evidence: evidenceSchema.optional(),
|
|
521
519
|
meta: z.object({
|
|
522
520
|
field_mapping: z.array(z.object({
|
|
523
521
|
role: z.enum(["row", "amount", "time"]),
|
|
@@ -549,7 +547,7 @@ const querySummaryOutputSchema = z.object({
|
|
|
549
547
|
column_cap: z.number().int().positive().nullable(),
|
|
550
548
|
scan_max_pages: z.number().int().positive()
|
|
551
549
|
})
|
|
552
|
-
})
|
|
550
|
+
}).optional()
|
|
553
551
|
});
|
|
554
552
|
const querySuccessOutputSchema = z.object({
|
|
555
553
|
ok: z.literal(true),
|
|
@@ -561,7 +559,7 @@ const querySuccessOutputSchema = z.object({
|
|
|
561
559
|
summary: querySummaryOutputSchema.optional()
|
|
562
560
|
}),
|
|
563
561
|
...queryContractFields,
|
|
564
|
-
meta: apiMetaSchema
|
|
562
|
+
meta: apiMetaSchema.optional()
|
|
565
563
|
});
|
|
566
564
|
const queryOutputSchema = querySuccessOutputSchema;
|
|
567
565
|
const aggregateInputSchema = z
|
|
@@ -628,7 +626,8 @@ const aggregateInputSchema = z
|
|
|
628
626
|
})
|
|
629
627
|
.optional(),
|
|
630
628
|
max_groups: z.number().int().positive().max(2000).optional(),
|
|
631
|
-
strict_full: z.boolean().optional()
|
|
629
|
+
strict_full: z.boolean().optional(),
|
|
630
|
+
output_profile: outputProfileSchema.optional()
|
|
632
631
|
}))
|
|
633
632
|
.refine((value) => !(value.page_num !== undefined && value.page_token !== undefined), {
|
|
634
633
|
message: "page_num and page_token cannot be used together"
|
|
@@ -648,8 +647,8 @@ const aggregateOutputSchema = z.object({
|
|
|
648
647
|
amount_total: z.number().nullable(),
|
|
649
648
|
amount_ratio: z.number().nullable()
|
|
650
649
|
})),
|
|
651
|
-
completeness: completenessSchema,
|
|
652
|
-
evidence: evidenceSchema,
|
|
650
|
+
completeness: completenessSchema.optional(),
|
|
651
|
+
evidence: evidenceSchema.optional(),
|
|
653
652
|
meta: z.object({
|
|
654
653
|
field_mapping: z.array(z.object({
|
|
655
654
|
role: z.enum(["group_by", "amount", "time"]),
|
|
@@ -662,10 +661,10 @@ const aggregateOutputSchema = z.object({
|
|
|
662
661
|
include_negative: z.boolean(),
|
|
663
662
|
include_null: z.boolean()
|
|
664
663
|
})
|
|
665
|
-
})
|
|
664
|
+
}).optional()
|
|
666
665
|
}),
|
|
667
666
|
...queryContractFields,
|
|
668
|
-
meta: apiMetaSchema
|
|
667
|
+
meta: apiMetaSchema.optional()
|
|
669
668
|
});
|
|
670
669
|
server.registerTool("qf_tool_spec_get", {
|
|
671
670
|
title: "Qingflow Tool Spec Get",
|
|
@@ -841,8 +840,8 @@ server.registerTool("qf_query", {
|
|
|
841
840
|
if (routedMode === "record") {
|
|
842
841
|
const recordArgs = buildRecordGetArgsFromQuery(args);
|
|
843
842
|
const executed = await executeRecordGet(recordArgs);
|
|
844
|
-
const completeness = executed.
|
|
845
|
-
const evidence = executed.
|
|
843
|
+
const completeness = executed.completeness;
|
|
844
|
+
const evidence = executed.evidence;
|
|
846
845
|
return okResult({
|
|
847
846
|
ok: true,
|
|
848
847
|
data: {
|
|
@@ -850,18 +849,27 @@ server.registerTool("qf_query", {
|
|
|
850
849
|
source_tool: "qf_record_get",
|
|
851
850
|
record: executed.payload.data
|
|
852
851
|
},
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
852
|
+
output_profile: executed.outputProfile,
|
|
853
|
+
...(isVerboseProfile(executed.outputProfile)
|
|
854
|
+
? {
|
|
855
|
+
completeness,
|
|
856
|
+
evidence,
|
|
857
|
+
error_code: null,
|
|
858
|
+
fix_hint: null
|
|
859
|
+
}
|
|
860
|
+
: {}),
|
|
857
861
|
next_page_token: completeness.next_page_token,
|
|
858
|
-
|
|
862
|
+
...(isVerboseProfile(executed.outputProfile)
|
|
863
|
+
? {
|
|
864
|
+
meta: executed.payload.meta
|
|
865
|
+
}
|
|
866
|
+
: {})
|
|
859
867
|
}, executed.message);
|
|
860
868
|
}
|
|
861
869
|
if (routedMode === "summary") {
|
|
862
870
|
const executed = await executeRecordsSummary(args);
|
|
863
|
-
const completeness = executed.
|
|
864
|
-
const evidence = executed.
|
|
871
|
+
const completeness = executed.completeness;
|
|
872
|
+
const evidence = executed.evidence;
|
|
865
873
|
return okResult({
|
|
866
874
|
ok: true,
|
|
867
875
|
data: {
|
|
@@ -869,18 +877,27 @@ server.registerTool("qf_query", {
|
|
|
869
877
|
source_tool: "qf_records_summary",
|
|
870
878
|
summary: executed.data
|
|
871
879
|
},
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
880
|
+
output_profile: executed.outputProfile,
|
|
881
|
+
...(isVerboseProfile(executed.outputProfile)
|
|
882
|
+
? {
|
|
883
|
+
completeness,
|
|
884
|
+
evidence,
|
|
885
|
+
error_code: null,
|
|
886
|
+
fix_hint: null
|
|
887
|
+
}
|
|
888
|
+
: {}),
|
|
876
889
|
next_page_token: completeness.next_page_token,
|
|
877
|
-
|
|
890
|
+
...(isVerboseProfile(executed.outputProfile)
|
|
891
|
+
? {
|
|
892
|
+
meta: executed.meta
|
|
893
|
+
}
|
|
894
|
+
: {})
|
|
878
895
|
}, executed.message);
|
|
879
896
|
}
|
|
880
897
|
const listArgs = buildListArgsFromQuery(args);
|
|
881
898
|
const executed = await executeRecordsList(listArgs);
|
|
882
|
-
const completeness = executed.
|
|
883
|
-
const evidence = executed.
|
|
899
|
+
const completeness = executed.completeness;
|
|
900
|
+
const evidence = executed.evidence;
|
|
884
901
|
return okResult({
|
|
885
902
|
ok: true,
|
|
886
903
|
data: {
|
|
@@ -888,12 +905,21 @@ server.registerTool("qf_query", {
|
|
|
888
905
|
source_tool: "qf_records_list",
|
|
889
906
|
list: executed.payload.data
|
|
890
907
|
},
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
908
|
+
output_profile: executed.outputProfile,
|
|
909
|
+
...(isVerboseProfile(executed.outputProfile)
|
|
910
|
+
? {
|
|
911
|
+
completeness,
|
|
912
|
+
evidence,
|
|
913
|
+
error_code: null,
|
|
914
|
+
fix_hint: null
|
|
915
|
+
}
|
|
916
|
+
: {}),
|
|
895
917
|
next_page_token: completeness.next_page_token,
|
|
896
|
-
|
|
918
|
+
...(isVerboseProfile(executed.outputProfile)
|
|
919
|
+
? {
|
|
920
|
+
meta: executed.payload.meta
|
|
921
|
+
}
|
|
922
|
+
: {})
|
|
897
923
|
}, executed.message);
|
|
898
924
|
}
|
|
899
925
|
catch (error) {
|
|
@@ -1288,6 +1314,12 @@ function buildMeta(response) {
|
|
|
1288
1314
|
base_url: baseUrl
|
|
1289
1315
|
};
|
|
1290
1316
|
}
|
|
1317
|
+
function resolveOutputProfile(value) {
|
|
1318
|
+
return value === "verbose" ? "verbose" : DEFAULT_OUTPUT_PROFILE;
|
|
1319
|
+
}
|
|
1320
|
+
function isVerboseProfile(profile) {
|
|
1321
|
+
return profile === "verbose";
|
|
1322
|
+
}
|
|
1291
1323
|
function missingRequiredFieldError(params) {
|
|
1292
1324
|
return new InputValidationError({
|
|
1293
1325
|
message: `Missing required field "${params.field}" for ${params.tool}`,
|
|
@@ -1335,6 +1367,9 @@ const COMMON_INPUT_ALIASES = {
|
|
|
1335
1367
|
statPolicy: "stat_policy",
|
|
1336
1368
|
groupBy: "group_by",
|
|
1337
1369
|
strictFull: "strict_full",
|
|
1370
|
+
outputProfile: "output_profile",
|
|
1371
|
+
responseProfile: "output_profile",
|
|
1372
|
+
profile: "output_profile",
|
|
1338
1373
|
forceRefresh: "force_refresh",
|
|
1339
1374
|
forceRefreshForm: "force_refresh_form",
|
|
1340
1375
|
applyUser: "apply_user"
|
|
@@ -1416,8 +1451,9 @@ function buildToolSpecCatalog() {
|
|
|
1416
1451
|
scan_max_pages_max: 500,
|
|
1417
1452
|
max_rows_max: 200,
|
|
1418
1453
|
max_items_max: 200,
|
|
1419
|
-
max_columns_max:
|
|
1420
|
-
select_columns_max:
|
|
1454
|
+
max_columns_max: MAX_COLUMN_LIMIT,
|
|
1455
|
+
select_columns_max: MAX_COLUMN_LIMIT,
|
|
1456
|
+
output_profile: "compact|verbose (default compact)"
|
|
1421
1457
|
},
|
|
1422
1458
|
aliases: collectAliasHints([
|
|
1423
1459
|
"app_key",
|
|
@@ -1431,35 +1467,41 @@ function buildToolSpecCatalog() {
|
|
|
1431
1467
|
"max_items",
|
|
1432
1468
|
"max_columns",
|
|
1433
1469
|
"select_columns",
|
|
1470
|
+
"output_profile",
|
|
1434
1471
|
"strict_full",
|
|
1435
1472
|
"include_answers",
|
|
1436
1473
|
"time_range"
|
|
1437
1474
|
], {
|
|
1438
1475
|
select_columns: ["columns", "selected_columns", "selectedColumns"],
|
|
1439
|
-
max_rows: ["limit", "row_limit", "rowLimit"]
|
|
1476
|
+
max_rows: ["limit", "row_limit", "rowLimit"],
|
|
1477
|
+
output_profile: ["outputProfile", "responseProfile", "profile"]
|
|
1440
1478
|
}),
|
|
1441
1479
|
minimal_example: {
|
|
1442
1480
|
app_key: "21b3d559",
|
|
1443
1481
|
mode: "all",
|
|
1444
1482
|
page_size: 50,
|
|
1445
1483
|
max_rows: 20,
|
|
1446
|
-
select_columns: [0, "客户名称", "报价总金额"]
|
|
1484
|
+
select_columns: [0, "客户名称", "报价总金额"],
|
|
1485
|
+
output_profile: "compact"
|
|
1447
1486
|
}
|
|
1448
1487
|
},
|
|
1449
1488
|
{
|
|
1450
1489
|
tool: "qf_record_get",
|
|
1451
1490
|
required: ["apply_id", "select_columns"],
|
|
1452
1491
|
limits: {
|
|
1453
|
-
max_columns_max:
|
|
1454
|
-
select_columns_max:
|
|
1492
|
+
max_columns_max: MAX_COLUMN_LIMIT,
|
|
1493
|
+
select_columns_max: MAX_COLUMN_LIMIT,
|
|
1494
|
+
output_profile: "compact|verbose (default compact)"
|
|
1455
1495
|
},
|
|
1456
|
-
aliases: collectAliasHints(["apply_id", "max_columns", "select_columns"], {
|
|
1457
|
-
select_columns: ["columns", "selected_columns", "selectedColumns"]
|
|
1496
|
+
aliases: collectAliasHints(["apply_id", "max_columns", "select_columns", "output_profile"], {
|
|
1497
|
+
select_columns: ["columns", "selected_columns", "selectedColumns"],
|
|
1498
|
+
output_profile: ["outputProfile", "responseProfile", "profile"]
|
|
1458
1499
|
}),
|
|
1459
1500
|
minimal_example: {
|
|
1460
1501
|
apply_id: "497600278750478338",
|
|
1461
1502
|
select_columns: [0, "客户名称"],
|
|
1462
|
-
max_columns:
|
|
1503
|
+
max_columns: 3,
|
|
1504
|
+
output_profile: "compact"
|
|
1463
1505
|
}
|
|
1464
1506
|
},
|
|
1465
1507
|
{
|
|
@@ -1476,8 +1518,9 @@ function buildToolSpecCatalog() {
|
|
|
1476
1518
|
scan_max_pages_max: 500,
|
|
1477
1519
|
max_rows_max: 200,
|
|
1478
1520
|
max_items_max: 200,
|
|
1479
|
-
max_columns_max:
|
|
1480
|
-
select_columns_max:
|
|
1521
|
+
max_columns_max: MAX_COLUMN_LIMIT,
|
|
1522
|
+
select_columns_max: MAX_COLUMN_LIMIT,
|
|
1523
|
+
output_profile: "compact|verbose (default compact)"
|
|
1481
1524
|
},
|
|
1482
1525
|
aliases: collectAliasHints([
|
|
1483
1526
|
"query_mode",
|
|
@@ -1492,6 +1535,7 @@ function buildToolSpecCatalog() {
|
|
|
1492
1535
|
"max_items",
|
|
1493
1536
|
"max_columns",
|
|
1494
1537
|
"select_columns",
|
|
1538
|
+
"output_profile",
|
|
1495
1539
|
"amount_column",
|
|
1496
1540
|
"time_range",
|
|
1497
1541
|
"stat_policy",
|
|
@@ -1500,7 +1544,8 @@ function buildToolSpecCatalog() {
|
|
|
1500
1544
|
select_columns: ["columns", "selected_columns", "selectedColumns"],
|
|
1501
1545
|
max_rows: ["limit", "row_limit", "rowLimit"],
|
|
1502
1546
|
amount_column: ["amount_que_ids", "amountQueIds", "amountColumns"],
|
|
1503
|
-
time_range: ["date_field + date_from + date_to"]
|
|
1547
|
+
time_range: ["date_field + date_from + date_to"],
|
|
1548
|
+
output_profile: ["outputProfile", "responseProfile", "profile"]
|
|
1504
1549
|
}),
|
|
1505
1550
|
minimal_example: {
|
|
1506
1551
|
query_mode: "list",
|
|
@@ -1509,6 +1554,7 @@ function buildToolSpecCatalog() {
|
|
|
1509
1554
|
page_size: 50,
|
|
1510
1555
|
max_rows: 20,
|
|
1511
1556
|
select_columns: [0, "客户名称", "报价总金额"],
|
|
1557
|
+
output_profile: "compact",
|
|
1512
1558
|
time_range: {
|
|
1513
1559
|
column: 6299264,
|
|
1514
1560
|
from: "2026-03-05",
|
|
@@ -1524,7 +1570,8 @@ function buildToolSpecCatalog() {
|
|
|
1524
1570
|
requested_pages_max: 500,
|
|
1525
1571
|
scan_max_pages_max: 500,
|
|
1526
1572
|
max_groups_max: 2000,
|
|
1527
|
-
group_by_max: 20
|
|
1573
|
+
group_by_max: 20,
|
|
1574
|
+
output_profile: "compact|verbose (default compact)"
|
|
1528
1575
|
},
|
|
1529
1576
|
aliases: collectAliasHints([
|
|
1530
1577
|
"app_key",
|
|
@@ -1535,18 +1582,21 @@ function buildToolSpecCatalog() {
|
|
|
1535
1582
|
"page_size",
|
|
1536
1583
|
"requested_pages",
|
|
1537
1584
|
"scan_max_pages",
|
|
1585
|
+
"output_profile",
|
|
1538
1586
|
"time_range",
|
|
1539
1587
|
"stat_policy",
|
|
1540
1588
|
"strict_full"
|
|
1541
1589
|
], {
|
|
1542
1590
|
amount_column: ["amount_que_ids", "amountQueIds", "amountColumns"],
|
|
1543
|
-
time_range: ["date_field + date_from + date_to"]
|
|
1591
|
+
time_range: ["date_field + date_from + date_to"],
|
|
1592
|
+
output_profile: ["outputProfile", "responseProfile", "profile"]
|
|
1544
1593
|
}),
|
|
1545
1594
|
minimal_example: {
|
|
1546
1595
|
app_key: "21b3d559",
|
|
1547
1596
|
mode: "all",
|
|
1548
1597
|
group_by: [9500572],
|
|
1549
1598
|
amount_column: 6299263,
|
|
1599
|
+
output_profile: "compact",
|
|
1550
1600
|
time_range: {
|
|
1551
1601
|
column: 6299264,
|
|
1552
1602
|
from: "2026-03-05",
|
|
@@ -1647,6 +1697,7 @@ function normalizeListInput(raw) {
|
|
|
1647
1697
|
max_columns: coerceNumberLike(normalizedObj.max_columns),
|
|
1648
1698
|
strict_full: coerceBooleanLike(normalizedObj.strict_full),
|
|
1649
1699
|
include_answers: coerceBooleanLike(normalizedObj.include_answers),
|
|
1700
|
+
output_profile: normalizeOutputProfileInput(normalizedObj.output_profile),
|
|
1650
1701
|
apply_ids: normalizeIdArrayInput(normalizedObj.apply_ids),
|
|
1651
1702
|
sort: normalizeSortInput(normalizedObj.sort),
|
|
1652
1703
|
filters: normalizeFiltersInput(normalizedObj.filters),
|
|
@@ -1666,7 +1717,8 @@ function normalizeRecordGetInput(raw) {
|
|
|
1666
1717
|
...normalizedObj,
|
|
1667
1718
|
apply_id: coerceNumberLike(normalizedObj.apply_id),
|
|
1668
1719
|
max_columns: coerceNumberLike(normalizedObj.max_columns),
|
|
1669
|
-
select_columns: normalizeSelectorListInput(selectColumns)
|
|
1720
|
+
select_columns: normalizeSelectorListInput(selectColumns),
|
|
1721
|
+
output_profile: normalizeOutputProfileInput(normalizedObj.output_profile)
|
|
1670
1722
|
};
|
|
1671
1723
|
}
|
|
1672
1724
|
function normalizeQueryInput(raw) {
|
|
@@ -1691,6 +1743,7 @@ function normalizeQueryInput(raw) {
|
|
|
1691
1743
|
apply_id: coerceNumberLike(normalizedObj.apply_id),
|
|
1692
1744
|
strict_full: coerceBooleanLike(normalizedObj.strict_full),
|
|
1693
1745
|
include_answers: coerceBooleanLike(normalizedObj.include_answers),
|
|
1746
|
+
output_profile: normalizeOutputProfileInput(normalizedObj.output_profile),
|
|
1694
1747
|
amount_column: normalizeAmountColumnInput(normalizedObj.amount_column),
|
|
1695
1748
|
apply_ids: normalizeIdArrayInput(normalizedObj.apply_ids),
|
|
1696
1749
|
sort: normalizeSortInput(normalizedObj.sort),
|
|
@@ -1717,6 +1770,7 @@ function normalizeAggregateInput(raw) {
|
|
|
1717
1770
|
type: coerceNumberLike(normalizedObj.type),
|
|
1718
1771
|
max_groups: coerceNumberLike(normalizedObj.max_groups),
|
|
1719
1772
|
strict_full: coerceBooleanLike(normalizedObj.strict_full),
|
|
1773
|
+
output_profile: normalizeOutputProfileInput(normalizedObj.output_profile),
|
|
1720
1774
|
group_by: normalizeSelectorListInput(normalizedObj.group_by),
|
|
1721
1775
|
amount_column: normalizeAmountColumnInput(normalizedObj.amount_column),
|
|
1722
1776
|
apply_ids: normalizeIdArrayInput(normalizedObj.apply_ids),
|
|
@@ -1758,6 +1812,23 @@ function coerceBooleanLike(value) {
|
|
|
1758
1812
|
}
|
|
1759
1813
|
return parsed;
|
|
1760
1814
|
}
|
|
1815
|
+
function normalizeOutputProfileInput(value) {
|
|
1816
|
+
const parsed = parseJsonLikeDeep(value);
|
|
1817
|
+
if (typeof parsed !== "string") {
|
|
1818
|
+
return parsed;
|
|
1819
|
+
}
|
|
1820
|
+
const normalized = parsed.trim().toLowerCase();
|
|
1821
|
+
if (!normalized) {
|
|
1822
|
+
return parsed;
|
|
1823
|
+
}
|
|
1824
|
+
if (normalized === "compact" || normalized === "lite" || normalized === "minimal") {
|
|
1825
|
+
return "compact";
|
|
1826
|
+
}
|
|
1827
|
+
if (normalized === "verbose" || normalized === "full" || normalized === "debug") {
|
|
1828
|
+
return "verbose";
|
|
1829
|
+
}
|
|
1830
|
+
return parsed;
|
|
1831
|
+
}
|
|
1761
1832
|
function parseJsonLikeDeep(value, maxDepth = 4) {
|
|
1762
1833
|
let current = value;
|
|
1763
1834
|
for (let i = 0; i < maxDepth; i += 1) {
|
|
@@ -2198,7 +2269,7 @@ function buildListArgsFromQuery(args) {
|
|
|
2198
2269
|
throw missingRequiredFieldError({
|
|
2199
2270
|
field: "select_columns",
|
|
2200
2271
|
tool: "qf_query(list)",
|
|
2201
|
-
fixHint: "Provide select_columns as an array (<=
|
|
2272
|
+
fixHint: "Provide select_columns as an array (<=3), for example: {\"select_columns\":[0,\"客户全称\",\"报价总金额\"]}"
|
|
2202
2273
|
});
|
|
2203
2274
|
}
|
|
2204
2275
|
const filters = buildListFiltersFromQuery(args);
|
|
@@ -2223,7 +2294,8 @@ function buildListArgsFromQuery(args) {
|
|
|
2223
2294
|
max_columns: args.max_columns,
|
|
2224
2295
|
select_columns: args.select_columns,
|
|
2225
2296
|
include_answers: args.include_answers,
|
|
2226
|
-
strict_full: args.strict_full
|
|
2297
|
+
strict_full: args.strict_full,
|
|
2298
|
+
output_profile: args.output_profile
|
|
2227
2299
|
});
|
|
2228
2300
|
}
|
|
2229
2301
|
function buildListFiltersFromQuery(args) {
|
|
@@ -2392,13 +2464,14 @@ function buildRecordGetArgsFromQuery(args) {
|
|
|
2392
2464
|
throw missingRequiredFieldError({
|
|
2393
2465
|
field: "select_columns",
|
|
2394
2466
|
tool: "qf_query(record)",
|
|
2395
|
-
fixHint: "Provide select_columns as an array (<=
|
|
2467
|
+
fixHint: "Provide select_columns as an array (<=3), for example: {\"select_columns\":[0,\"客户全称\"]}"
|
|
2396
2468
|
});
|
|
2397
2469
|
}
|
|
2398
2470
|
return recordGetInputSchema.parse({
|
|
2399
2471
|
apply_id: args.apply_id,
|
|
2400
2472
|
max_columns: args.max_columns,
|
|
2401
|
-
select_columns: args.select_columns
|
|
2473
|
+
select_columns: args.select_columns,
|
|
2474
|
+
output_profile: args.output_profile
|
|
2402
2475
|
});
|
|
2403
2476
|
}
|
|
2404
2477
|
async function executeRecordsList(args) {
|
|
@@ -2413,9 +2486,10 @@ async function executeRecordsList(args) {
|
|
|
2413
2486
|
throw missingRequiredFieldError({
|
|
2414
2487
|
field: "select_columns",
|
|
2415
2488
|
tool: "qf_records_list",
|
|
2416
|
-
fixHint: "Provide select_columns as an array (<=
|
|
2489
|
+
fixHint: "Provide select_columns as an array (<=3), for example: {\"select_columns\":[0,\"客户全称\",\"报价总金额\"]}"
|
|
2417
2490
|
});
|
|
2418
2491
|
}
|
|
2492
|
+
const outputProfile = resolveOutputProfile(args.output_profile);
|
|
2419
2493
|
const queryId = randomUUID();
|
|
2420
2494
|
const pageNum = resolveStartPage(args.page_num, args.page_token, args.app_key);
|
|
2421
2495
|
const pageSize = args.page_size ?? DEFAULT_PAGE_SIZE;
|
|
@@ -2485,6 +2559,7 @@ async function executeRecordsList(args) {
|
|
|
2485
2559
|
const items = collectedRawItems
|
|
2486
2560
|
.slice(0, listLimit.limit)
|
|
2487
2561
|
.map((raw) => normalizeRecordItem(raw, includeAnswers));
|
|
2562
|
+
const sourceItemsForRows = items.slice();
|
|
2488
2563
|
const columnProjection = projectRecordItemsColumns({
|
|
2489
2564
|
items,
|
|
2490
2565
|
includeAnswers,
|
|
@@ -2503,16 +2578,23 @@ async function executeRecordsList(args) {
|
|
|
2503
2578
|
}
|
|
2504
2579
|
});
|
|
2505
2580
|
}
|
|
2506
|
-
const
|
|
2507
|
-
|
|
2581
|
+
const selectedColumnsForRows = args.max_columns !== undefined
|
|
2582
|
+
? columnProjection.selectedColumns.slice(0, args.max_columns)
|
|
2583
|
+
: columnProjection.selectedColumns;
|
|
2584
|
+
const rows = buildFlatRowsFromItems({
|
|
2585
|
+
items: sourceItemsForRows,
|
|
2586
|
+
selectedColumns: selectedColumnsForRows
|
|
2587
|
+
});
|
|
2588
|
+
const fittedRows = fitListItemsWithinSize({
|
|
2589
|
+
items: rows,
|
|
2508
2590
|
limitBytes: MAX_LIST_ITEMS_BYTES
|
|
2509
2591
|
});
|
|
2510
|
-
const truncationReason = mergeTruncationReasons(listLimit.reason, columnProjection.reason,
|
|
2511
|
-
const omittedItems = Math.max(0, knownResultAmount -
|
|
2592
|
+
const truncationReason = mergeTruncationReasons(listLimit.reason, columnProjection.reason, fittedRows.reason);
|
|
2593
|
+
const omittedItems = Math.max(0, knownResultAmount - fittedRows.items.length);
|
|
2512
2594
|
const isComplete = !hasMore &&
|
|
2513
2595
|
omittedItems === 0 &&
|
|
2514
|
-
|
|
2515
|
-
|
|
2596
|
+
fittedRows.omittedItems === 0 &&
|
|
2597
|
+
fittedRows.omittedChars === 0;
|
|
2516
2598
|
const nextPageToken = hasMore && nextPageNum
|
|
2517
2599
|
? encodeContinuationToken({
|
|
2518
2600
|
app_key: args.app_key,
|
|
@@ -2522,7 +2604,7 @@ async function executeRecordsList(args) {
|
|
|
2522
2604
|
: null;
|
|
2523
2605
|
const completeness = {
|
|
2524
2606
|
result_amount: knownResultAmount,
|
|
2525
|
-
returned_items:
|
|
2607
|
+
returned_items: fittedRows.items.length,
|
|
2526
2608
|
fetched_pages: fetchedPages,
|
|
2527
2609
|
requested_pages: requestedPages,
|
|
2528
2610
|
actual_scanned_pages: fetchedPages,
|
|
@@ -2531,7 +2613,7 @@ async function executeRecordsList(args) {
|
|
|
2531
2613
|
is_complete: isComplete,
|
|
2532
2614
|
partial: !isComplete,
|
|
2533
2615
|
omitted_items: omittedItems,
|
|
2534
|
-
omitted_chars:
|
|
2616
|
+
omitted_chars: fittedRows.omittedChars
|
|
2535
2617
|
};
|
|
2536
2618
|
const listState = {
|
|
2537
2619
|
query_id: queryId,
|
|
@@ -2565,30 +2647,46 @@ async function executeRecordsList(args) {
|
|
|
2565
2647
|
page_amount: pageAmount,
|
|
2566
2648
|
result_amount: knownResultAmount
|
|
2567
2649
|
},
|
|
2568
|
-
|
|
2650
|
+
rows: fittedRows.items,
|
|
2569
2651
|
applied_limits: {
|
|
2570
2652
|
include_answers: includeAnswers,
|
|
2571
2653
|
row_cap: listLimit.limit,
|
|
2572
2654
|
column_cap: args.max_columns ?? null,
|
|
2573
|
-
selected_columns:
|
|
2655
|
+
selected_columns: selectedColumnsForRows
|
|
2574
2656
|
},
|
|
2575
|
-
|
|
2576
|
-
|
|
2657
|
+
...(isVerboseProfile(outputProfile)
|
|
2658
|
+
? {
|
|
2659
|
+
completeness,
|
|
2660
|
+
evidence
|
|
2661
|
+
}
|
|
2662
|
+
: {})
|
|
2577
2663
|
},
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2664
|
+
output_profile: outputProfile,
|
|
2665
|
+
...(isVerboseProfile(outputProfile)
|
|
2666
|
+
? {
|
|
2667
|
+
completeness,
|
|
2668
|
+
evidence,
|
|
2669
|
+
error_code: null,
|
|
2670
|
+
fix_hint: null
|
|
2671
|
+
}
|
|
2672
|
+
: {}),
|
|
2582
2673
|
next_page_token: completeness.next_page_token,
|
|
2583
|
-
|
|
2674
|
+
...(isVerboseProfile(outputProfile)
|
|
2675
|
+
? {
|
|
2676
|
+
meta: responseMeta
|
|
2677
|
+
}
|
|
2678
|
+
: {})
|
|
2584
2679
|
};
|
|
2585
2680
|
return {
|
|
2586
2681
|
payload: responsePayload,
|
|
2587
2682
|
message: buildRecordsListMessage({
|
|
2588
|
-
returned:
|
|
2683
|
+
returned: fittedRows.items.length,
|
|
2589
2684
|
total: knownResultAmount,
|
|
2590
2685
|
truncationReason
|
|
2591
|
-
})
|
|
2686
|
+
}),
|
|
2687
|
+
completeness,
|
|
2688
|
+
evidence,
|
|
2689
|
+
outputProfile
|
|
2592
2690
|
};
|
|
2593
2691
|
}
|
|
2594
2692
|
async function executeRecordGet(args) {
|
|
@@ -2596,9 +2694,10 @@ async function executeRecordGet(args) {
|
|
|
2596
2694
|
throw missingRequiredFieldError({
|
|
2597
2695
|
field: "select_columns",
|
|
2598
2696
|
tool: "qf_record_get",
|
|
2599
|
-
fixHint: "Provide select_columns as an array (<=
|
|
2697
|
+
fixHint: "Provide select_columns as an array (<=3), for example: {\"apply_id\":\"...\",\"select_columns\":[0]}"
|
|
2600
2698
|
});
|
|
2601
2699
|
}
|
|
2700
|
+
const outputProfile = resolveOutputProfile(args.output_profile);
|
|
2602
2701
|
const queryId = randomUUID();
|
|
2603
2702
|
const response = await client.getRecord(String(args.apply_id));
|
|
2604
2703
|
const record = asObject(response.result) ?? {};
|
|
@@ -2607,65 +2706,69 @@ async function executeRecordGet(args) {
|
|
|
2607
2706
|
maxColumns: args.max_columns,
|
|
2608
2707
|
selectColumns: args.select_columns
|
|
2609
2708
|
});
|
|
2610
|
-
const
|
|
2611
|
-
|
|
2612
|
-
|
|
2709
|
+
const selectedColumnsForRow = args.max_columns !== undefined
|
|
2710
|
+
? (projection.selectedColumns ?? []).slice(0, args.max_columns)
|
|
2711
|
+
: projection.selectedColumns ?? [];
|
|
2712
|
+
const row = buildFlatRowFromAnswers({
|
|
2713
|
+
applyId: record.applyId ?? null,
|
|
2714
|
+
answers: asArray(record.answers),
|
|
2715
|
+
selectedColumns: selectedColumnsForRow
|
|
2716
|
+
});
|
|
2717
|
+
const completeness = {
|
|
2718
|
+
result_amount: 1,
|
|
2719
|
+
returned_items: 1,
|
|
2720
|
+
fetched_pages: 1,
|
|
2721
|
+
requested_pages: 1,
|
|
2722
|
+
actual_scanned_pages: 1,
|
|
2723
|
+
has_more: false,
|
|
2724
|
+
next_page_token: null,
|
|
2725
|
+
is_complete: true,
|
|
2726
|
+
partial: false,
|
|
2727
|
+
omitted_items: 0,
|
|
2728
|
+
omitted_chars: 0
|
|
2729
|
+
};
|
|
2730
|
+
const evidence = {
|
|
2731
|
+
query_id: queryId,
|
|
2732
|
+
apply_id: String(args.apply_id),
|
|
2733
|
+
selected_columns: selectedColumnsForRow
|
|
2613
2734
|
};
|
|
2614
|
-
const answerCount = projection.answers.length;
|
|
2615
2735
|
return {
|
|
2616
2736
|
payload: {
|
|
2617
2737
|
ok: true,
|
|
2618
2738
|
data: {
|
|
2619
2739
|
apply_id: record.applyId ?? null,
|
|
2620
|
-
|
|
2621
|
-
record: projectedRecord,
|
|
2740
|
+
row,
|
|
2622
2741
|
applied_limits: {
|
|
2623
2742
|
column_cap: args.max_columns ?? null,
|
|
2624
|
-
selected_columns:
|
|
2743
|
+
selected_columns: selectedColumnsForRow
|
|
2625
2744
|
},
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
has_more: false,
|
|
2633
|
-
next_page_token: null,
|
|
2634
|
-
is_complete: true,
|
|
2635
|
-
partial: false,
|
|
2636
|
-
omitted_items: 0,
|
|
2637
|
-
omitted_chars: 0
|
|
2638
|
-
},
|
|
2639
|
-
evidence: {
|
|
2640
|
-
query_id: queryId,
|
|
2641
|
-
apply_id: String(args.apply_id),
|
|
2642
|
-
selected_columns: projection.selectedColumns ?? []
|
|
2643
|
-
}
|
|
2644
|
-
},
|
|
2645
|
-
completeness: {
|
|
2646
|
-
result_amount: 1,
|
|
2647
|
-
returned_items: 1,
|
|
2648
|
-
fetched_pages: 1,
|
|
2649
|
-
requested_pages: 1,
|
|
2650
|
-
actual_scanned_pages: 1,
|
|
2651
|
-
has_more: false,
|
|
2652
|
-
next_page_token: null,
|
|
2653
|
-
is_complete: true,
|
|
2654
|
-
partial: false,
|
|
2655
|
-
omitted_items: 0,
|
|
2656
|
-
omitted_chars: 0
|
|
2657
|
-
},
|
|
2658
|
-
evidence: {
|
|
2659
|
-
query_id: queryId,
|
|
2660
|
-
apply_id: String(args.apply_id),
|
|
2661
|
-
selected_columns: projection.selectedColumns ?? []
|
|
2745
|
+
...(isVerboseProfile(outputProfile)
|
|
2746
|
+
? {
|
|
2747
|
+
completeness,
|
|
2748
|
+
evidence
|
|
2749
|
+
}
|
|
2750
|
+
: {})
|
|
2662
2751
|
},
|
|
2663
|
-
|
|
2664
|
-
|
|
2752
|
+
output_profile: outputProfile,
|
|
2753
|
+
...(isVerboseProfile(outputProfile)
|
|
2754
|
+
? {
|
|
2755
|
+
completeness,
|
|
2756
|
+
evidence,
|
|
2757
|
+
error_code: null,
|
|
2758
|
+
fix_hint: null
|
|
2759
|
+
}
|
|
2760
|
+
: {}),
|
|
2665
2761
|
next_page_token: null,
|
|
2666
|
-
|
|
2762
|
+
...(isVerboseProfile(outputProfile)
|
|
2763
|
+
? {
|
|
2764
|
+
meta: buildMeta(response)
|
|
2765
|
+
}
|
|
2766
|
+
: {})
|
|
2667
2767
|
},
|
|
2668
|
-
message: `Fetched record ${String(args.apply_id)}
|
|
2768
|
+
message: `Fetched record ${String(args.apply_id)}`,
|
|
2769
|
+
completeness,
|
|
2770
|
+
evidence,
|
|
2771
|
+
outputProfile
|
|
2669
2772
|
};
|
|
2670
2773
|
}
|
|
2671
2774
|
async function executeRecordsSummary(args) {
|
|
@@ -2680,9 +2783,10 @@ async function executeRecordsSummary(args) {
|
|
|
2680
2783
|
throw missingRequiredFieldError({
|
|
2681
2784
|
field: "select_columns",
|
|
2682
2785
|
tool: "qf_query(summary)",
|
|
2683
|
-
fixHint: "Provide select_columns as an array (<=
|
|
2786
|
+
fixHint: "Provide select_columns as an array (<=3), for example: {\"select_columns\":[\"客户全称\"]}"
|
|
2684
2787
|
});
|
|
2685
2788
|
}
|
|
2789
|
+
const outputProfile = resolveOutputProfile(args.output_profile);
|
|
2686
2790
|
const queryId = randomUUID();
|
|
2687
2791
|
const strictFull = args.strict_full ?? true;
|
|
2688
2792
|
const includeNegative = args.stat_policy?.include_negative ?? true;
|
|
@@ -2892,44 +2996,52 @@ async function executeRecordsSummary(args) {
|
|
|
2892
2996
|
missing_count: missingCount
|
|
2893
2997
|
},
|
|
2894
2998
|
rows,
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2999
|
+
...(isVerboseProfile(outputProfile)
|
|
3000
|
+
? {
|
|
3001
|
+
completeness,
|
|
3002
|
+
evidence,
|
|
3003
|
+
meta: {
|
|
3004
|
+
field_mapping: fieldMapping,
|
|
3005
|
+
filters: {
|
|
3006
|
+
app_key: args.app_key,
|
|
3007
|
+
time_range: timeColumn
|
|
3008
|
+
? {
|
|
3009
|
+
column: timeColumn.requested,
|
|
3010
|
+
from: args.time_range?.from ?? null,
|
|
3011
|
+
to: args.time_range?.to ?? null,
|
|
3012
|
+
timezone
|
|
3013
|
+
}
|
|
3014
|
+
: null
|
|
3015
|
+
},
|
|
3016
|
+
stat_policy: {
|
|
3017
|
+
include_negative: includeNegative,
|
|
3018
|
+
include_null: includeNull
|
|
3019
|
+
},
|
|
3020
|
+
execution: {
|
|
3021
|
+
scanned_records: scannedRecords,
|
|
3022
|
+
scanned_pages: scannedPages,
|
|
3023
|
+
truncated: !isComplete,
|
|
3024
|
+
row_cap: rowCap,
|
|
3025
|
+
column_cap: args.max_columns ?? null,
|
|
3026
|
+
scan_max_pages: scanMaxPages
|
|
2907
3027
|
}
|
|
2908
|
-
|
|
2909
|
-
},
|
|
2910
|
-
stat_policy: {
|
|
2911
|
-
include_negative: includeNegative,
|
|
2912
|
-
include_null: includeNull
|
|
2913
|
-
},
|
|
2914
|
-
execution: {
|
|
2915
|
-
scanned_records: scannedRecords,
|
|
2916
|
-
scanned_pages: scannedPages,
|
|
2917
|
-
truncated: !isComplete,
|
|
2918
|
-
row_cap: rowCap,
|
|
2919
|
-
column_cap: args.max_columns ?? null,
|
|
2920
|
-
scan_max_pages: scanMaxPages
|
|
3028
|
+
}
|
|
2921
3029
|
}
|
|
2922
|
-
|
|
3030
|
+
: {})
|
|
2923
3031
|
},
|
|
2924
3032
|
meta: summaryMeta,
|
|
2925
3033
|
message: isComplete
|
|
2926
3034
|
? `Summarized ${scannedRecords} records`
|
|
2927
|
-
: `Summarized ${scannedRecords}/${knownResultAmount} records (partial)
|
|
3035
|
+
: `Summarized ${scannedRecords}/${knownResultAmount} records (partial)`,
|
|
3036
|
+
completeness,
|
|
3037
|
+
evidence,
|
|
3038
|
+
outputProfile
|
|
2928
3039
|
};
|
|
2929
3040
|
}
|
|
2930
3041
|
async function executeRecordsAggregate(args) {
|
|
2931
3042
|
const queryId = randomUUID();
|
|
2932
3043
|
const strictFull = args.strict_full ?? true;
|
|
3044
|
+
const outputProfile = resolveOutputProfile(args.output_profile);
|
|
2933
3045
|
const includeNegative = args.stat_policy?.include_negative ?? true;
|
|
2934
3046
|
const includeNull = args.stat_policy?.include_null ?? false;
|
|
2935
3047
|
const pageSize = args.page_size ?? DEFAULT_PAGE_SIZE;
|
|
@@ -3127,22 +3239,35 @@ async function executeRecordsAggregate(args) {
|
|
|
3127
3239
|
total_amount: amountColumn ? totalAmount : null
|
|
3128
3240
|
},
|
|
3129
3241
|
groups,
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3242
|
+
...(isVerboseProfile(outputProfile)
|
|
3243
|
+
? {
|
|
3244
|
+
completeness,
|
|
3245
|
+
evidence,
|
|
3246
|
+
meta: {
|
|
3247
|
+
field_mapping: fieldMapping,
|
|
3248
|
+
stat_policy: {
|
|
3249
|
+
include_negative: includeNegative,
|
|
3250
|
+
include_null: includeNull
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3137
3253
|
}
|
|
3138
|
-
|
|
3254
|
+
: {})
|
|
3139
3255
|
},
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3256
|
+
output_profile: outputProfile,
|
|
3257
|
+
...(isVerboseProfile(outputProfile)
|
|
3258
|
+
? {
|
|
3259
|
+
completeness,
|
|
3260
|
+
evidence,
|
|
3261
|
+
error_code: null,
|
|
3262
|
+
fix_hint: null
|
|
3263
|
+
}
|
|
3264
|
+
: {}),
|
|
3144
3265
|
next_page_token: completeness.next_page_token,
|
|
3145
|
-
|
|
3266
|
+
...(isVerboseProfile(outputProfile)
|
|
3267
|
+
? {
|
|
3268
|
+
meta: responseMeta
|
|
3269
|
+
}
|
|
3270
|
+
: {})
|
|
3146
3271
|
},
|
|
3147
3272
|
message: isComplete
|
|
3148
3273
|
? `Aggregated ${scannedRecords} records`
|
|
@@ -3635,10 +3760,13 @@ function projectRecordItemsColumns(params) {
|
|
|
3635
3760
|
projected = projected.slice(0, params.maxColumns);
|
|
3636
3761
|
columnCapped = true;
|
|
3637
3762
|
}
|
|
3638
|
-
|
|
3763
|
+
const slimProjected = projected
|
|
3764
|
+
.map((answer) => simplifyAnswerForOutput(answer))
|
|
3765
|
+
.filter((answer) => Boolean(answer));
|
|
3766
|
+
matchedAnswersCount += slimProjected.length;
|
|
3639
3767
|
return {
|
|
3640
3768
|
...item,
|
|
3641
|
-
answers:
|
|
3769
|
+
answers: slimProjected
|
|
3642
3770
|
};
|
|
3643
3771
|
});
|
|
3644
3772
|
const reason = mergeTruncationReasons(selectorSet.size > 0 ? `selected columns=${normalizedSelectors.length}` : null, columnCapped && params.maxColumns !== undefined
|
|
@@ -3661,11 +3789,99 @@ function projectAnswersForOutput(params) {
|
|
|
3661
3789
|
if (params.maxColumns !== undefined && projected.length > params.maxColumns) {
|
|
3662
3790
|
projected = projected.slice(0, params.maxColumns);
|
|
3663
3791
|
}
|
|
3792
|
+
const slimProjected = projected
|
|
3793
|
+
.map((answer) => simplifyAnswerForOutput(answer))
|
|
3794
|
+
.filter((answer) => Boolean(answer));
|
|
3664
3795
|
return {
|
|
3665
|
-
answers:
|
|
3796
|
+
answers: slimProjected,
|
|
3666
3797
|
selectedColumns: normalizedSelectors.length > 0 ? normalizedSelectors : null
|
|
3667
3798
|
};
|
|
3668
3799
|
}
|
|
3800
|
+
function simplifyAnswerForOutput(answer) {
|
|
3801
|
+
const obj = asObject(answer);
|
|
3802
|
+
if (!obj) {
|
|
3803
|
+
return null;
|
|
3804
|
+
}
|
|
3805
|
+
const queId = obj.queId ?? obj.que_id ?? null;
|
|
3806
|
+
const queTitle = asNullableString(obj.queTitle ?? obj.que_title);
|
|
3807
|
+
const queType = obj.queType ?? obj.que_type;
|
|
3808
|
+
const value = extractAnswerDisplayValue(obj);
|
|
3809
|
+
const slim = {
|
|
3810
|
+
queId,
|
|
3811
|
+
queTitle
|
|
3812
|
+
};
|
|
3813
|
+
if (queType !== undefined && queType !== null) {
|
|
3814
|
+
slim.queType = queType;
|
|
3815
|
+
}
|
|
3816
|
+
if (value !== undefined) {
|
|
3817
|
+
slim.value = value;
|
|
3818
|
+
}
|
|
3819
|
+
return slim;
|
|
3820
|
+
}
|
|
3821
|
+
function buildFlatRowsFromItems(params) {
|
|
3822
|
+
return params.items.map((item) => buildFlatRowFromAnswers({
|
|
3823
|
+
applyId: item.apply_id ?? null,
|
|
3824
|
+
answers: asArray(item.answers),
|
|
3825
|
+
selectedColumns: params.selectedColumns
|
|
3826
|
+
}));
|
|
3827
|
+
}
|
|
3828
|
+
function buildFlatRowFromAnswers(params) {
|
|
3829
|
+
const row = {
|
|
3830
|
+
apply_id: params.applyId
|
|
3831
|
+
};
|
|
3832
|
+
const selectors = normalizeColumnSelectors(params.selectedColumns);
|
|
3833
|
+
for (const selector of selectors) {
|
|
3834
|
+
const hit = findAnswerBySelector(params.answers, selector);
|
|
3835
|
+
const keyBase = resolveFlatRowColumnKey(selector, hit);
|
|
3836
|
+
const key = getUniqueRowKey(row, keyBase);
|
|
3837
|
+
row[key] = hit ? extractAnswerDisplayValue(hit) : null;
|
|
3838
|
+
}
|
|
3839
|
+
return row;
|
|
3840
|
+
}
|
|
3841
|
+
function findAnswerBySelector(answers, selector) {
|
|
3842
|
+
const target = normalizeColumnSelector(selector);
|
|
3843
|
+
for (const answerRaw of answers) {
|
|
3844
|
+
const answer = asObject(answerRaw);
|
|
3845
|
+
if (!answer) {
|
|
3846
|
+
continue;
|
|
3847
|
+
}
|
|
3848
|
+
const answerQueId = asNullableString(answer.queId ?? answer.que_id);
|
|
3849
|
+
if (answerQueId && normalizeColumnSelector(answerQueId) === target) {
|
|
3850
|
+
return answer;
|
|
3851
|
+
}
|
|
3852
|
+
const answerQueTitle = asNullableString(answer.queTitle ?? answer.que_title);
|
|
3853
|
+
if (answerQueTitle && normalizeColumnSelector(answerQueTitle) === target) {
|
|
3854
|
+
return answer;
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
return null;
|
|
3858
|
+
}
|
|
3859
|
+
function resolveFlatRowColumnKey(selector, answer) {
|
|
3860
|
+
const trimmed = selector.trim();
|
|
3861
|
+
if (!trimmed) {
|
|
3862
|
+
return "column";
|
|
3863
|
+
}
|
|
3864
|
+
if (!isNumericKey(trimmed)) {
|
|
3865
|
+
return trimmed;
|
|
3866
|
+
}
|
|
3867
|
+
const title = asNullableString(answer?.queTitle ?? answer?.que_title);
|
|
3868
|
+
if (title && title.trim()) {
|
|
3869
|
+
return title;
|
|
3870
|
+
}
|
|
3871
|
+
return trimmed;
|
|
3872
|
+
}
|
|
3873
|
+
function getUniqueRowKey(row, preferred) {
|
|
3874
|
+
if (!(preferred in row)) {
|
|
3875
|
+
return preferred;
|
|
3876
|
+
}
|
|
3877
|
+
let index = 2;
|
|
3878
|
+
let candidate = `${preferred}#${index}`;
|
|
3879
|
+
while (candidate in row) {
|
|
3880
|
+
index += 1;
|
|
3881
|
+
candidate = `${preferred}#${index}`;
|
|
3882
|
+
}
|
|
3883
|
+
return candidate;
|
|
3884
|
+
}
|
|
3669
3885
|
function fitListItemsWithinSize(params) {
|
|
3670
3886
|
let candidate = params.items;
|
|
3671
3887
|
const originalSize = jsonSizeBytes(candidate);
|
|
@@ -4041,7 +4257,8 @@ function buildBaseExampleCall(params) {
|
|
|
4041
4257
|
tool: "qf_record_get",
|
|
4042
4258
|
arguments: {
|
|
4043
4259
|
apply_id: "your_apply_id",
|
|
4044
|
-
select_columns: params.selectColumns
|
|
4260
|
+
select_columns: params.selectColumns,
|
|
4261
|
+
output_profile: "compact"
|
|
4045
4262
|
}
|
|
4046
4263
|
};
|
|
4047
4264
|
}
|
|
@@ -4053,7 +4270,8 @@ function buildBaseExampleCall(params) {
|
|
|
4053
4270
|
mode: "all",
|
|
4054
4271
|
page_size: 50,
|
|
4055
4272
|
max_rows: 20,
|
|
4056
|
-
select_columns: params.selectColumns
|
|
4273
|
+
select_columns: params.selectColumns,
|
|
4274
|
+
output_profile: "compact"
|
|
4057
4275
|
}
|
|
4058
4276
|
};
|
|
4059
4277
|
}
|
|
@@ -4067,7 +4285,8 @@ function buildBaseExampleCall(params) {
|
|
|
4067
4285
|
page_size: 50,
|
|
4068
4286
|
requested_pages: 3,
|
|
4069
4287
|
scan_max_pages: 3,
|
|
4070
|
-
strict_full: false
|
|
4288
|
+
strict_full: false,
|
|
4289
|
+
output_profile: "compact"
|
|
4071
4290
|
}
|
|
4072
4291
|
};
|
|
4073
4292
|
}
|
|
@@ -4078,7 +4297,8 @@ function buildBaseExampleCall(params) {
|
|
|
4078
4297
|
arguments: {
|
|
4079
4298
|
query_mode: "record",
|
|
4080
4299
|
apply_id: "your_apply_id",
|
|
4081
|
-
select_columns: params.selectColumns
|
|
4300
|
+
select_columns: params.selectColumns,
|
|
4301
|
+
output_profile: "compact"
|
|
4082
4302
|
}
|
|
4083
4303
|
};
|
|
4084
4304
|
}
|
|
@@ -4092,7 +4312,8 @@ function buildBaseExampleCall(params) {
|
|
|
4092
4312
|
select_columns: params.selectColumns,
|
|
4093
4313
|
page_size: 50,
|
|
4094
4314
|
scan_max_pages: 3,
|
|
4095
|
-
strict_full: false
|
|
4315
|
+
strict_full: false,
|
|
4316
|
+
output_profile: "compact"
|
|
4096
4317
|
}
|
|
4097
4318
|
};
|
|
4098
4319
|
}
|
|
@@ -4104,7 +4325,8 @@ function buildBaseExampleCall(params) {
|
|
|
4104
4325
|
mode: "all",
|
|
4105
4326
|
page_size: 50,
|
|
4106
4327
|
max_rows: 20,
|
|
4107
|
-
select_columns: params.selectColumns
|
|
4328
|
+
select_columns: params.selectColumns,
|
|
4329
|
+
output_profile: "compact"
|
|
4108
4330
|
}
|
|
4109
4331
|
};
|
|
4110
4332
|
}
|