echopai 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +386 -0
  2. package/dist/_generated/commands.js +274 -0
  3. package/dist/_generated/help.js +190 -0
  4. package/dist/_generated/operations.js +1306 -0
  5. package/dist/bin.js +170 -0
  6. package/dist/runtime/auth.js +95 -0
  7. package/dist/runtime/envelope.js +52 -0
  8. package/dist/runtime/errors.js +186 -0
  9. package/dist/runtime/filters.js +153 -0
  10. package/dist/runtime/format.js +143 -0
  11. package/dist/runtime/http.js +65 -0
  12. package/dist/runtime/idempotency.js +18 -0
  13. package/dist/runtime/invoker.js +387 -0
  14. package/dist/runtime/io.js +16 -0
  15. package/dist/runtime/paginator.js +146 -0
  16. package/dist/runtime/trace.js +99 -0
  17. package/dist/runtime/tty.js +51 -0
  18. package/dist/runtime/verb_cmd.js +70 -0
  19. package/dist/runtime/verb_runner.js +152 -0
  20. package/dist/runtime/whoami_cache.js +109 -0
  21. package/dist/tools/api.js +81 -0
  22. package/dist/tools/completion.js +116 -0
  23. package/dist/tools/config.js +123 -0
  24. package/dist/tools/doctor.js +183 -0
  25. package/dist/tools/login.js +99 -0
  26. package/dist/tools/mcp.js +141 -0
  27. package/dist/tools/raw.js +96 -0
  28. package/dist/tools/schema.js +58 -0
  29. package/dist/tools/trace.js +54 -0
  30. package/dist/tools/whoami.js +132 -0
  31. package/dist/verbs/_spec.js +15 -0
  32. package/dist/verbs/bars_batch.js +66 -0
  33. package/dist/verbs/chart.js +110 -0
  34. package/dist/verbs/digest.js +342 -0
  35. package/dist/verbs/hot.js +29 -0
  36. package/dist/verbs/index.js +49 -0
  37. package/dist/verbs/lookup.js +72 -0
  38. package/dist/verbs/news.js +67 -0
  39. package/dist/verbs/quote.js +53 -0
  40. package/dist/verbs/research.js +44 -0
  41. package/dist/verbs/scan.js +42 -0
  42. package/dist/verbs/sentiment.js +46 -0
  43. package/dist/verbs/views.js +83 -0
  44. package/dist/version.js +5 -0
  45. package/package.json +58 -0
@@ -0,0 +1,1306 @@
1
+ /**
2
+ * AUTO-GENERATED — DO NOT EDIT BY HAND.
3
+ *
4
+ * Source: docs/api-contract/openapi.yaml (operations with x-cli-key + x-visibility: public)
5
+ * Generator: scripts/codegen/generate_cli_v2.py
6
+ *
7
+ * Regenerate:
8
+ * make codegen
9
+ */
10
+ export const OPERATIONS = {
11
+ "agent.session-end": {
12
+ "cliKey": "agent.session-end",
13
+ "cliName": "agent session-end",
14
+ "method": "POST",
15
+ "path": "/v1/agent/session/{id}/end",
16
+ "description": "关闭 `/v1/agent/session/start` 开启的会话,最终用量提交入库。",
17
+ "summary": "End a billable agent session",
18
+ "positional": [
19
+ "id"
20
+ ],
21
+ "outputDefault": "json",
22
+ "pagination": "none",
23
+ "stream": false,
24
+ "billable": false,
25
+ "idempotencyRequired": true,
26
+ "scopesAny": [
27
+ "agent:session.create",
28
+ "agent:session.read"
29
+ ],
30
+ "sideEffect": "write",
31
+ "dryRunSupported": false,
32
+ "inputSchema": {
33
+ "type": "object",
34
+ "properties": {
35
+ "id": {
36
+ "type": "string",
37
+ "description": "Session id returned by /v1/agent/session/start."
38
+ }
39
+ },
40
+ "additionalProperties": false,
41
+ "required": [
42
+ "id"
43
+ ]
44
+ }
45
+ },
46
+ "agent.session-start": {
47
+ "cliKey": "agent.session-start",
48
+ "cliName": "agent session-start",
49
+ "method": "POST",
50
+ "path": "/v1/agent/session/start",
51
+ "description": "开启 agent kind 凭据的计费会话。返回 session_id,用于将多次调用归并到一次 billable 单位。需要 `Idempotency-Key` 头。",
52
+ "summary": "Start a billable agent session",
53
+ "positional": [],
54
+ "outputDefault": "json",
55
+ "pagination": "none",
56
+ "stream": false,
57
+ "billable": false,
58
+ "idempotencyRequired": true,
59
+ "scopesAny": [
60
+ "agent:session.create"
61
+ ],
62
+ "sideEffect": "write",
63
+ "dryRunSupported": true,
64
+ "inputSchema": {
65
+ "type": "object",
66
+ "properties": {
67
+ "agent_id": {
68
+ "type": "string",
69
+ "maxLength": 200,
70
+ "description": "Partner-defined agent identifier (max 200 chars).",
71
+ "example": "agent-prod-1"
72
+ },
73
+ "conversation_id": {
74
+ "type": "string",
75
+ "maxLength": 200,
76
+ "description": "Optional conversation thread id (max 200 chars)."
77
+ },
78
+ "scopes": {
79
+ "type": "array",
80
+ "items": {
81
+ "type": "string"
82
+ },
83
+ "description": "Subset of partner scopes to derive into the agent token. Omit for \"all derivable from partner scopes\"."
84
+ },
85
+ "budget_usd": {
86
+ "type": "number",
87
+ "exclusiveMinimum": 0,
88
+ "maximum": 1000,
89
+ "default": 1.0,
90
+ "description": "Hard USD budget cap; session terminates when exhausted (0 < x ≤ 1000).",
91
+ "example": 1.0
92
+ },
93
+ "ttl_seconds": {
94
+ "type": "integer",
95
+ "minimum": 60,
96
+ "maximum": 28800,
97
+ "default": 3600,
98
+ "description": "Session lifetime cap (60 ≤ x ≤ 28800, default 1h)."
99
+ },
100
+ "metadata": {
101
+ "type": "object",
102
+ "description": "Free-form JSON object for partner bookkeeping (e.g. user_intent, model name)."
103
+ }
104
+ },
105
+ "additionalProperties": false,
106
+ "required": [
107
+ "agent_id"
108
+ ]
109
+ }
110
+ },
111
+ "agent.session-usage": {
112
+ "cliKey": "agent.session-usage",
113
+ "cliName": "agent session-usage",
114
+ "method": "GET",
115
+ "path": "/v1/agent/session/{id}/usage",
116
+ "description": "返回 session 内累计 billable 调用次数、各 scope 配额消耗。",
117
+ "summary": "Get cumulative usage of an agent session",
118
+ "positional": [
119
+ "id"
120
+ ],
121
+ "outputDefault": "json",
122
+ "pagination": "none",
123
+ "stream": false,
124
+ "billable": false,
125
+ "idempotencyRequired": false,
126
+ "scopesAny": [
127
+ "agent:session.create",
128
+ "agent:session.read"
129
+ ],
130
+ "sideEffect": "read",
131
+ "dryRunSupported": false,
132
+ "inputSchema": {
133
+ "type": "object",
134
+ "properties": {
135
+ "id": {
136
+ "type": "string",
137
+ "description": "Session id returned by /v1/agent/session/start."
138
+ }
139
+ },
140
+ "additionalProperties": false,
141
+ "required": [
142
+ "id"
143
+ ]
144
+ }
145
+ },
146
+ "auth.whoami": {
147
+ "cliKey": "auth.whoami",
148
+ "cliName": "auth whoami",
149
+ "method": "GET",
150
+ "path": "/v1/auth/whoami",
151
+ "description": "Returns the calling token's kind, scopes, audience, app metadata,\nrate_limit, allowed_clients, agent_budget (if kind=agent), api_version,\nfeature_flags. Any valid JWT can call — no specific scope required.\n\nCLI/MCP call this once at startup, cache 5 minutes in-process, and use\nthe response to derive `verbs.available` (intersection of curated verb\nscopes with token scopes) and to populate `echopai doctor` checks.\n\nSee `docs/PLAN_CLI_V2_AGENT_SURFACE.md` §5.1.\n",
152
+ "summary": "Token introspection (CLI/MCP capability discovery)",
153
+ "positional": [],
154
+ "outputDefault": "json",
155
+ "pagination": "none",
156
+ "stream": false,
157
+ "billable": false,
158
+ "idempotencyRequired": false,
159
+ "scopesAny": [],
160
+ "sideEffect": "read",
161
+ "dryRunSupported": false,
162
+ "inputSchema": {
163
+ "type": "object",
164
+ "properties": {},
165
+ "additionalProperties": false
166
+ }
167
+ },
168
+ "backtest.excess-distribution": {
169
+ "cliKey": "backtest.excess-distribution",
170
+ "cliName": "backtest excess-distribution",
171
+ "method": "GET",
172
+ "path": "/v1/backtest/excess-distribution",
173
+ "description": "信号相对基准(沪深 300 / 中证 1000 等)持有期超额收益的直方分布。",
174
+ "summary": "Excess-return distribution over a benchmark",
175
+ "positional": [],
176
+ "outputDefault": "json",
177
+ "pagination": "none",
178
+ "stream": false,
179
+ "billable": false,
180
+ "idempotencyRequired": false,
181
+ "scopesAny": [],
182
+ "sideEffect": "read",
183
+ "dryRunSupported": false,
184
+ "inputSchema": {
185
+ "type": "object",
186
+ "properties": {},
187
+ "additionalProperties": false
188
+ }
189
+ },
190
+ "backtest.rolling-win-rate": {
191
+ "cliKey": "backtest.rolling-win-rate",
192
+ "cliName": "backtest rolling-win-rate",
193
+ "method": "GET",
194
+ "path": "/v1/backtest/rolling-win-rate",
195
+ "description": "信号在滚动窗口(默认 60 个交易日)内的胜率时间序列。",
196
+ "summary": "Rolling win rate of a signal series",
197
+ "positional": [],
198
+ "outputDefault": "json",
199
+ "pagination": "none",
200
+ "stream": false,
201
+ "billable": false,
202
+ "idempotencyRequired": false,
203
+ "scopesAny": [],
204
+ "sideEffect": "read",
205
+ "dryRunSupported": false,
206
+ "inputSchema": {
207
+ "type": "object",
208
+ "properties": {},
209
+ "additionalProperties": false
210
+ }
211
+ },
212
+ "backtest.summary": {
213
+ "cliKey": "backtest.summary",
214
+ "cliName": "backtest summary",
215
+ "method": "GET",
216
+ "path": "/v1/backtest/summary",
217
+ "description": "信号回测汇总:胜率、平均超额收益、Sharpe-like 评分、最大回撤等。",
218
+ "summary": "Backtest summary metrics for a signal series",
219
+ "positional": [],
220
+ "outputDefault": "json",
221
+ "pagination": "none",
222
+ "stream": false,
223
+ "billable": false,
224
+ "idempotencyRequired": false,
225
+ "scopesAny": [],
226
+ "sideEffect": "read",
227
+ "dryRunSupported": false,
228
+ "inputSchema": {
229
+ "type": "object",
230
+ "properties": {},
231
+ "additionalProperties": false
232
+ }
233
+ },
234
+ "bars.daily": {
235
+ "cliKey": "bars.daily",
236
+ "cliName": "bars daily",
237
+ "method": "GET",
238
+ "path": "/v1/bars/daily",
239
+ "description": "Daily OHLC bars for one A-share security over a date range. Returns open / high / low / close / volume / turnover per trading day. Requires `bars:30d` (last 30 trading days) or `bars:full` (full history) scope.",
240
+ "summary": "Daily OHLC bars for one A-share security",
241
+ "positional": [],
242
+ "outputDefault": "json",
243
+ "pagination": "none",
244
+ "stream": false,
245
+ "billable": true,
246
+ "idempotencyRequired": false,
247
+ "scopesAny": [
248
+ "bars:30d",
249
+ "bars:full"
250
+ ],
251
+ "sideEffect": "read",
252
+ "dryRunSupported": false,
253
+ "inputSchema": {
254
+ "type": "object",
255
+ "properties": {
256
+ "code": {
257
+ "type": "string",
258
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$",
259
+ "description": "Single canonical code.",
260
+ "example": "SSE:600519"
261
+ },
262
+ "from": {
263
+ "type": "string",
264
+ "format": "date",
265
+ "description": "Inclusive start date (YYYY-MM-DD).",
266
+ "example": "2026-01-01"
267
+ },
268
+ "to": {
269
+ "type": "string",
270
+ "format": "date",
271
+ "description": "Inclusive end date (YYYY-MM-DD).",
272
+ "example": "2026-05-01"
273
+ }
274
+ },
275
+ "additionalProperties": false,
276
+ "required": [
277
+ "code",
278
+ "from",
279
+ "to"
280
+ ]
281
+ }
282
+ },
283
+ "bars.daily-batch": {
284
+ "cliKey": "bars.daily-batch",
285
+ "cliName": "bars daily-batch",
286
+ "method": "GET",
287
+ "path": "/v1/bars/daily-batch",
288
+ "description": "Batch daily OHLC bars for multiple A-share securities. Up to 100 codes\nper call, up to 1-year date range. Single round-trip; ClickHouse `IN(...)`\nunder the hood.\n\nReturns partial success envelope: codes denied by `allowed_securities`\nappear in `errors[]`, others in `items[]` (with empty `bars[]` if no\ndata found). Order in `items[]` matches input order.\n\nRequires `bars:30d` or `bars:full` scope.\n",
289
+ "summary": "Batch daily OHLC bars for up to 100 A-share securities",
290
+ "positional": [],
291
+ "outputDefault": "json",
292
+ "pagination": "none",
293
+ "stream": false,
294
+ "billable": true,
295
+ "idempotencyRequired": false,
296
+ "scopesAny": [
297
+ "bars:30d",
298
+ "bars:full"
299
+ ],
300
+ "sideEffect": "read",
301
+ "dryRunSupported": false,
302
+ "inputSchema": {
303
+ "type": "object",
304
+ "properties": {
305
+ "codes": {
306
+ "type": "array",
307
+ "items": {
308
+ "type": "string",
309
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$"
310
+ },
311
+ "minItems": 1,
312
+ "maxItems": 100,
313
+ "description": "1-100 canonical codes; CSV-encoded on the wire.",
314
+ "example": [
315
+ "SSE:600519",
316
+ "SZSE:000001"
317
+ ]
318
+ },
319
+ "from": {
320
+ "type": "string",
321
+ "format": "date",
322
+ "description": "Inclusive start date (YYYY-MM-DD)."
323
+ },
324
+ "to": {
325
+ "type": "string",
326
+ "format": "date",
327
+ "description": "Inclusive end date (YYYY-MM-DD). Range must be ≤ 365 days."
328
+ }
329
+ },
330
+ "additionalProperties": false,
331
+ "required": [
332
+ "codes",
333
+ "from",
334
+ "to"
335
+ ]
336
+ }
337
+ },
338
+ "bars.minute": {
339
+ "cliKey": "bars.minute",
340
+ "cliName": "bars minute",
341
+ "method": "GET",
342
+ "path": "/v1/bars/minute",
343
+ "description": "Minute-level OHLC bars for one A-share security on a single trade date. Requires `bars:30d` or `bars:full` scope.",
344
+ "summary": "Minute-level OHLC bars for one A-share security",
345
+ "positional": [],
346
+ "outputDefault": "json",
347
+ "pagination": "none",
348
+ "stream": false,
349
+ "billable": true,
350
+ "idempotencyRequired": false,
351
+ "scopesAny": [
352
+ "bars:30d",
353
+ "bars:full"
354
+ ],
355
+ "sideEffect": "read",
356
+ "dryRunSupported": false,
357
+ "inputSchema": {
358
+ "type": "object",
359
+ "properties": {
360
+ "code": {
361
+ "type": "string",
362
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$",
363
+ "description": "Single canonical code.",
364
+ "example": "SSE:600519"
365
+ },
366
+ "date": {
367
+ "type": "string",
368
+ "format": "date",
369
+ "description": "Single trade date (YYYY-MM-DD). Returns 240 minute bars for that session.",
370
+ "example": "2026-05-09"
371
+ }
372
+ },
373
+ "additionalProperties": false,
374
+ "required": [
375
+ "code",
376
+ "date"
377
+ ]
378
+ }
379
+ },
380
+ "bars.minute-batch": {
381
+ "cliKey": "bars.minute-batch",
382
+ "cliName": "bars minute-batch",
383
+ "method": "GET",
384
+ "path": "/v1/bars/minute-batch",
385
+ "description": "Batch minute OHLC bars for multiple A-share securities. Up to 20 codes\nper call, up to 7 calendar days (≈5 trading days) date range. Single\nClickHouse round-trip; app groups rows by canonical_code.\n\nPartial success envelope same as daily-batch: codes denied by\n`allowed_securities` go to `errors[]`; others to `items[]` with flat\n`bars[]` (each bar carries its own `trade_date` for client grouping).\n\nRequires `bars:30d` or `bars:full` scope.\n",
386
+ "summary": "Batch minute OHLC bars for up to 20 A-share securities",
387
+ "positional": [],
388
+ "outputDefault": "json",
389
+ "pagination": "none",
390
+ "stream": false,
391
+ "billable": true,
392
+ "idempotencyRequired": false,
393
+ "scopesAny": [
394
+ "bars:30d",
395
+ "bars:full"
396
+ ],
397
+ "sideEffect": "read",
398
+ "dryRunSupported": false,
399
+ "inputSchema": {
400
+ "type": "object",
401
+ "properties": {
402
+ "codes": {
403
+ "type": "array",
404
+ "items": {
405
+ "type": "string",
406
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$"
407
+ },
408
+ "minItems": 1,
409
+ "maxItems": 20,
410
+ "description": "1-20 canonical codes; CSV-encoded on the wire.",
411
+ "example": [
412
+ "SSE:600519",
413
+ "SZSE:000001"
414
+ ]
415
+ },
416
+ "from": {
417
+ "type": "string",
418
+ "format": "date",
419
+ "description": "Inclusive start date (YYYY-MM-DD)."
420
+ },
421
+ "to": {
422
+ "type": "string",
423
+ "format": "date",
424
+ "description": "Inclusive end date. Range must be ≤ 7 calendar days."
425
+ }
426
+ },
427
+ "additionalProperties": false,
428
+ "required": [
429
+ "codes",
430
+ "from",
431
+ "to"
432
+ ]
433
+ }
434
+ },
435
+ "digest.get": {
436
+ "cliKey": "digest.get",
437
+ "cliName": "digest get",
438
+ "method": "GET",
439
+ "path": "/v1/digest/{code}",
440
+ "description": "Composite endpoint: in one HTTP call returns views (PRIMARY research),\nresearch-entity performance (quality layer), real-time quote, market\nsentiment context, and supplementary news. Partial-failure tolerant:\neach bucket is independently fetched and per-bucket failures surface\nin `meta.partial_failures[]` rather than poisoning the response. If\nevery sub-bucket fails the endpoint returns 502.\n\nBucket scopes are checked *per bucket* (not at gateway level): a\ntoken with only `views:read` gets the views bucket populated and the\nrest reported as `scope_insufficient` partial failures. This mirrors\nthe CLI fan-out contract exactly so `echopai digest` can either call\nthis endpoint (preferred, single round-trip) or fall back to local\nfan-out without behavior drift.\n\nSee `docs/PLAN_CLI_V2_AGENT_SURFACE.md` §3.3 (digest spec) and §11\nPhase 5.2 (server endpoint).\n",
441
+ "summary": "One-shot research digest for a single security (composite)",
442
+ "positional": [
443
+ "code"
444
+ ],
445
+ "outputDefault": "json",
446
+ "pagination": "none",
447
+ "stream": false,
448
+ "billable": true,
449
+ "idempotencyRequired": false,
450
+ "scopesAny": [],
451
+ "sideEffect": "read",
452
+ "dryRunSupported": false,
453
+ "inputSchema": {
454
+ "type": "object",
455
+ "properties": {
456
+ "code": {
457
+ "type": "string",
458
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$",
459
+ "description": "Canonical security code, e.g. SSE:600519."
460
+ },
461
+ "views_since_days": {
462
+ "type": "integer",
463
+ "minimum": 1,
464
+ "maximum": 90,
465
+ "default": 7,
466
+ "description": "Views lookback in days (1-90)."
467
+ },
468
+ "news_hours": {
469
+ "type": "integer",
470
+ "minimum": 1,
471
+ "maximum": 168,
472
+ "default": 24,
473
+ "description": "News lookback in hours (1-168)."
474
+ },
475
+ "limit_per_bucket": {
476
+ "type": "integer",
477
+ "minimum": 1,
478
+ "maximum": 50,
479
+ "default": 10,
480
+ "description": "Per-bucket item cap for views / news (1-50)."
481
+ }
482
+ },
483
+ "additionalProperties": false,
484
+ "required": [
485
+ "code"
486
+ ]
487
+ }
488
+ },
489
+ "market.status": {
490
+ "cliKey": "market.status",
491
+ "cliName": "market status",
492
+ "method": "GET",
493
+ "path": "/v1/market/status",
494
+ "description": "Current A-share market session: pre-open / open / lunch / closed; current and next trading day; holiday flag. Requires `market:read` or any `quote:*` scope.",
495
+ "summary": "Current A-share market session state",
496
+ "positional": [],
497
+ "outputDefault": "json",
498
+ "pagination": "none",
499
+ "stream": false,
500
+ "billable": false,
501
+ "idempotencyRequired": false,
502
+ "scopesAny": [
503
+ "market:read",
504
+ "quote:l1",
505
+ "quote:l2",
506
+ "quote:delayed"
507
+ ],
508
+ "sideEffect": "read",
509
+ "dryRunSupported": false,
510
+ "inputSchema": {
511
+ "type": "object",
512
+ "properties": {},
513
+ "additionalProperties": false
514
+ }
515
+ },
516
+ "news.feed": {
517
+ "cliKey": "news.feed",
518
+ "cliName": "news feed",
519
+ "method": "GET",
520
+ "path": "/v1/news",
521
+ "description": "与 `/v1/news/list` 行为一致,旧客户端兼容用。",
522
+ "summary": "List recent news (alias of /v1/news/list)",
523
+ "positional": [],
524
+ "outputDefault": "json",
525
+ "pagination": "offset",
526
+ "stream": false,
527
+ "billable": false,
528
+ "idempotencyRequired": false,
529
+ "scopesAny": [],
530
+ "sideEffect": "read",
531
+ "dryRunSupported": false,
532
+ "inputSchema": {
533
+ "type": "object",
534
+ "properties": {},
535
+ "additionalProperties": false
536
+ }
537
+ },
538
+ "news.get": {
539
+ "cliKey": "news.get",
540
+ "cliName": "news get",
541
+ "method": "GET",
542
+ "path": "/v1/news/{news_id}",
543
+ "description": "返回新闻完整内容:title、content snippet、source URL、tagged securities。",
544
+ "summary": "Fetch a single news item by id",
545
+ "positional": [
546
+ "news_id"
547
+ ],
548
+ "outputDefault": "json",
549
+ "pagination": "none",
550
+ "stream": false,
551
+ "billable": false,
552
+ "idempotencyRequired": false,
553
+ "scopesAny": [],
554
+ "sideEffect": "read",
555
+ "dryRunSupported": false,
556
+ "inputSchema": {
557
+ "type": "object",
558
+ "properties": {
559
+ "news_id": {
560
+ "type": "string",
561
+ "description": "News item id (returned by news.list / search items[].id)."
562
+ }
563
+ },
564
+ "additionalProperties": false,
565
+ "required": [
566
+ "news_id"
567
+ ]
568
+ }
569
+ },
570
+ "news.list": {
571
+ "cliKey": "news.list",
572
+ "cliName": "news list",
573
+ "method": "GET",
574
+ "path": "/v1/news/list",
575
+ "description": "List news mentioning a specific A-share security, ordered by published_at desc. Requires `news:read` scope.",
576
+ "summary": "List news mentioning a specific security",
577
+ "positional": [],
578
+ "outputDefault": "json",
579
+ "pagination": "none",
580
+ "stream": false,
581
+ "billable": true,
582
+ "idempotencyRequired": false,
583
+ "scopesAny": [
584
+ "news:read"
585
+ ],
586
+ "sideEffect": "read",
587
+ "dryRunSupported": false,
588
+ "inputSchema": {
589
+ "type": "object",
590
+ "properties": {
591
+ "security": {
592
+ "type": "string",
593
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$",
594
+ "description": "Canonical security code.",
595
+ "example": "SSE:600519"
596
+ },
597
+ "since_hours": {
598
+ "type": "integer",
599
+ "minimum": 1,
600
+ "maximum": 720,
601
+ "default": 24,
602
+ "description": "Lookback window in hours (max 720 = 30 days)."
603
+ },
604
+ "limit": {
605
+ "type": "integer",
606
+ "minimum": 1,
607
+ "maximum": 100,
608
+ "default": 20,
609
+ "description": "Max items per page."
610
+ }
611
+ },
612
+ "additionalProperties": false,
613
+ "required": [
614
+ "security"
615
+ ]
616
+ }
617
+ },
618
+ "news.search": {
619
+ "cliKey": "news.search",
620
+ "cliName": "news search",
621
+ "method": "GET",
622
+ "path": "/v1/news/search",
623
+ "description": "Full-text search recent news / market briefs. Returns title, source, published_at, snippet, tagged securities. Requires `news:read` scope. Note: news fields are user-generated; meta.untrusted_text_fields lists fields that need sanitization before passing to an LLM.",
624
+ "summary": "Full-text search recent news",
625
+ "positional": [],
626
+ "outputDefault": "json",
627
+ "pagination": "none",
628
+ "stream": false,
629
+ "billable": true,
630
+ "idempotencyRequired": false,
631
+ "scopesAny": [
632
+ "news:read"
633
+ ],
634
+ "sideEffect": "read",
635
+ "dryRunSupported": false,
636
+ "inputSchema": {
637
+ "type": "object",
638
+ "properties": {
639
+ "query": {
640
+ "type": "string",
641
+ "minLength": 1,
642
+ "maxLength": 200,
643
+ "description": "Free-text query (Chinese or English).",
644
+ "example": "光伏龙头"
645
+ },
646
+ "since_hours": {
647
+ "type": "integer",
648
+ "minimum": 1,
649
+ "maximum": 168,
650
+ "default": 24,
651
+ "description": "Lookback window in hours."
652
+ },
653
+ "limit": {
654
+ "type": "integer",
655
+ "minimum": 1,
656
+ "maximum": 100,
657
+ "default": 20,
658
+ "description": "Max items per page."
659
+ }
660
+ },
661
+ "additionalProperties": false,
662
+ "required": [
663
+ "query"
664
+ ]
665
+ }
666
+ },
667
+ "news.sources": {
668
+ "cliKey": "news.sources",
669
+ "cliName": "news sources",
670
+ "method": "GET",
671
+ "path": "/v1/news/sources",
672
+ "description": "返回新闻 source 标识列表(如 `cls`、`jin10`、`twitter`、`wallstreetcn`),可用于 list/search 的 source 过滤。",
673
+ "summary": "List canonical news source identifiers",
674
+ "positional": [],
675
+ "outputDefault": "json",
676
+ "pagination": "none",
677
+ "stream": false,
678
+ "billable": false,
679
+ "idempotencyRequired": false,
680
+ "scopesAny": [],
681
+ "sideEffect": "read",
682
+ "dryRunSupported": false,
683
+ "inputSchema": {
684
+ "type": "object",
685
+ "properties": {},
686
+ "additionalProperties": false
687
+ }
688
+ },
689
+ "payment.plans": {
690
+ "cliKey": "payment.plans",
691
+ "cliName": "payment plans",
692
+ "method": "GET",
693
+ "path": "/v1/payment/plans",
694
+ "description": "返回订阅计划清单(plan_id + 价格 + 时长 + 描述)。",
695
+ "summary": "List subscription plans",
696
+ "positional": [],
697
+ "outputDefault": "json",
698
+ "pagination": "none",
699
+ "stream": false,
700
+ "billable": false,
701
+ "idempotencyRequired": false,
702
+ "scopesAny": [],
703
+ "sideEffect": "read",
704
+ "dryRunSupported": false,
705
+ "inputSchema": {
706
+ "type": "object",
707
+ "properties": {},
708
+ "additionalProperties": false
709
+ }
710
+ },
711
+ "quote": {
712
+ "cliKey": "quote",
713
+ "cliName": "quote",
714
+ "method": "GET",
715
+ "path": "/v1/quote/realtime",
716
+ "description": "Real-time quote for one or more A-share securities. Returns last price, volume, change %, bid/ask. Up to 200 codes per call. Requires `quote:l1`, `quote:l2`, or `quote:delayed` scope.",
717
+ "summary": "Real-time quote for one or more A-share securities",
718
+ "positional": [],
719
+ "outputDefault": "json",
720
+ "pagination": "none",
721
+ "stream": false,
722
+ "billable": true,
723
+ "idempotencyRequired": false,
724
+ "scopesAny": [
725
+ "quote:l1",
726
+ "quote:l2",
727
+ "quote:delayed"
728
+ ],
729
+ "sideEffect": "read",
730
+ "dryRunSupported": false,
731
+ "inputSchema": {
732
+ "type": "object",
733
+ "properties": {
734
+ "codes": {
735
+ "type": "array",
736
+ "items": {
737
+ "type": "string",
738
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$"
739
+ },
740
+ "minItems": 1,
741
+ "maxItems": 200,
742
+ "description": "1-200 canonical codes; CSV-encoded on the wire.",
743
+ "example": [
744
+ "SSE:600519",
745
+ "SZSE:000001"
746
+ ]
747
+ },
748
+ "include_l2": {
749
+ "type": "boolean",
750
+ "default": false,
751
+ "description": "Include L2 5-level order book (requires quote:l2 scope)."
752
+ }
753
+ },
754
+ "additionalProperties": false,
755
+ "required": [
756
+ "codes"
757
+ ]
758
+ }
759
+ },
760
+ "quote.scan": {
761
+ "cliKey": "quote.scan",
762
+ "cliName": "quote scan",
763
+ "method": "GET",
764
+ "path": "/v1/quote/scan",
765
+ "description": "Dumps the entire Redis snapshot of A-share real-time quotes in a single\nround-trip. Use for \"全市场扫描\" / agent universe-of-interest discovery\nwhen you don't yet know which codes to query.\n\nFiltering:\n- `exchange=SSE|SZSE|BSE` narrows to one exchange (canonical_code prefix)\n- `app.allowed_securities` is ALWAYS applied; codes outside drop silently\n\nResponse size: ~3 MB unfiltered (~5800 items). CLI users should pair\nwith `--max-bytes` / `--fields` / `--query` from Phase 1.4.\n\n9:00–9:14 集合竞价时段返回空 items + `note` 字段说明。\n\nRequires `quote:l1`, `quote:l2`, or `quote:delayed` scope.\n",
766
+ "summary": "Full-market real-time quote scan (~5800 A-share securities)",
767
+ "positional": [],
768
+ "outputDefault": "json",
769
+ "pagination": "none",
770
+ "stream": false,
771
+ "billable": true,
772
+ "idempotencyRequired": false,
773
+ "scopesAny": [
774
+ "quote:l1",
775
+ "quote:l2",
776
+ "quote:delayed"
777
+ ],
778
+ "sideEffect": "read",
779
+ "dryRunSupported": false,
780
+ "inputSchema": {
781
+ "type": "object",
782
+ "properties": {
783
+ "exchange": {
784
+ "type": "string",
785
+ "enum": [
786
+ "SSE",
787
+ "SZSE",
788
+ "BSE",
789
+ "sse",
790
+ "szse",
791
+ "bse"
792
+ ],
793
+ "description": "Filter by exchange: SSE / SZSE / BSE (case-insensitive). Omit for all."
794
+ }
795
+ },
796
+ "additionalProperties": false
797
+ }
798
+ },
799
+ "research.entity-performance": {
800
+ "cliKey": "research.entity-performance",
801
+ "cliName": "research entity-performance",
802
+ "method": "GET",
803
+ "path": "/v1/research-entities/{entity_id}/performance",
804
+ "description": "单个研究实体的细化绩效指标,对照 `/v1/research-entities/performance`。",
805
+ "summary": "Performance of one research entity",
806
+ "positional": [
807
+ "entity_id"
808
+ ],
809
+ "outputDefault": "json",
810
+ "pagination": "none",
811
+ "stream": false,
812
+ "billable": false,
813
+ "idempotencyRequired": false,
814
+ "scopesAny": [],
815
+ "sideEffect": "read",
816
+ "dryRunSupported": false,
817
+ "inputSchema": {
818
+ "type": "object",
819
+ "properties": {
820
+ "entity_id": {
821
+ "type": "string",
822
+ "description": "Research-entity id (returned by research-entities.list / matcher)."
823
+ }
824
+ },
825
+ "additionalProperties": false,
826
+ "required": [
827
+ "entity_id"
828
+ ]
829
+ }
830
+ },
831
+ "research.entity-performance-list": {
832
+ "cliKey": "research.entity-performance-list",
833
+ "cliName": "research entity-performance-list",
834
+ "method": "GET",
835
+ "path": "/v1/research-entities/performance",
836
+ "description": "全体研究实体(analyst / team / institution)的命中率、平均目标价达成率、覆盖股票数等汇总。需要 `research:read` scope。",
837
+ "summary": "Aggregate performance of research entities",
838
+ "positional": [],
839
+ "outputDefault": "json",
840
+ "pagination": "none",
841
+ "stream": false,
842
+ "billable": false,
843
+ "idempotencyRequired": false,
844
+ "scopesAny": [],
845
+ "sideEffect": "read",
846
+ "dryRunSupported": false,
847
+ "inputSchema": {
848
+ "type": "object",
849
+ "properties": {},
850
+ "additionalProperties": false
851
+ }
852
+ },
853
+ "semantic.find": {
854
+ "cliKey": "semantic.find",
855
+ "cliName": "semantic find",
856
+ "method": "GET",
857
+ "path": "/v1/securities/search",
858
+ "description": "Find A-share securities matching a name (Chinese), code (e.g. 600519), or pinyin initials (e.g. gzmt). Use this when an agent has a description and needs canonical codes.",
859
+ "summary": "Find A-share securities by name / code / pinyin",
860
+ "positional": [],
861
+ "outputDefault": "json",
862
+ "pagination": "none",
863
+ "stream": false,
864
+ "billable": false,
865
+ "idempotencyRequired": false,
866
+ "scopesAny": [],
867
+ "sideEffect": "read",
868
+ "dryRunSupported": false,
869
+ "inputSchema": {
870
+ "type": "object",
871
+ "properties": {
872
+ "query": {
873
+ "type": "string",
874
+ "minLength": 1,
875
+ "maxLength": 20,
876
+ "description": "Search query: Chinese name, A-share code, or pinyin initials.",
877
+ "example": "贵州茅台"
878
+ },
879
+ "limit": {
880
+ "type": "integer",
881
+ "minimum": 1,
882
+ "maximum": 30,
883
+ "default": 10,
884
+ "description": "Max matches."
885
+ }
886
+ },
887
+ "additionalProperties": false,
888
+ "required": [
889
+ "query"
890
+ ]
891
+ }
892
+ },
893
+ "sentiment.breadth": {
894
+ "cliKey": "sentiment.breadth",
895
+ "cliName": "sentiment breadth",
896
+ "method": "GET",
897
+ "path": "/v1/sentiment/breadth",
898
+ "description": "Intraday breadth time series. Requires `sentiment:read` scope.",
899
+ "summary": "Intraday breadth time series",
900
+ "positional": [],
901
+ "outputDefault": "json",
902
+ "pagination": "none",
903
+ "stream": false,
904
+ "billable": true,
905
+ "idempotencyRequired": false,
906
+ "scopesAny": [
907
+ "sentiment:read"
908
+ ],
909
+ "sideEffect": "read",
910
+ "dryRunSupported": false,
911
+ "inputSchema": {
912
+ "type": "object",
913
+ "properties": {
914
+ "scope": {
915
+ "type": "string",
916
+ "enum": [
917
+ "all_a",
918
+ "all_a_ex_st",
919
+ "main_board",
920
+ "star_market",
921
+ "chinext",
922
+ "bse"
923
+ ],
924
+ "default": "all_a_ex_st",
925
+ "description": "Universe filter."
926
+ }
927
+ },
928
+ "additionalProperties": false
929
+ }
930
+ },
931
+ "sentiment.overview": {
932
+ "cliKey": "sentiment.overview",
933
+ "cliName": "sentiment overview",
934
+ "method": "GET",
935
+ "path": "/v1/sentiment/overview",
936
+ "description": "Aggregate sentiment: limit-up/down counts, breadth, divergence index, top movers. Requires `sentiment:read` scope.",
937
+ "summary": "Aggregate market sentiment indicators",
938
+ "positional": [],
939
+ "outputDefault": "json",
940
+ "pagination": "none",
941
+ "stream": false,
942
+ "billable": true,
943
+ "idempotencyRequired": false,
944
+ "scopesAny": [
945
+ "sentiment:read"
946
+ ],
947
+ "sideEffect": "read",
948
+ "dryRunSupported": false,
949
+ "inputSchema": {
950
+ "type": "object",
951
+ "properties": {
952
+ "scope": {
953
+ "type": "string",
954
+ "enum": [
955
+ "all_a",
956
+ "all_a_ex_st",
957
+ "main_board",
958
+ "star_market",
959
+ "chinext",
960
+ "bse"
961
+ ],
962
+ "default": "all_a_ex_st",
963
+ "description": "Universe filter.",
964
+ "example": "main_board"
965
+ }
966
+ },
967
+ "additionalProperties": false
968
+ }
969
+ },
970
+ "sentiment.pct-distribution": {
971
+ "cliKey": "sentiment.pct-distribution",
972
+ "cliName": "sentiment pct-distribution",
973
+ "method": "GET",
974
+ "path": "/v1/sentiment/pct-distribution",
975
+ "description": "返回 A 股全市场涨跌幅分桶(≤-10% / -9% / ... / +10% / 涨停)的家数分布,用于市场宽度可视化。",
976
+ "summary": "Distribution of intraday percent change across the universe",
977
+ "positional": [],
978
+ "outputDefault": "json",
979
+ "pagination": "none",
980
+ "stream": false,
981
+ "billable": true,
982
+ "idempotencyRequired": false,
983
+ "scopesAny": [
984
+ "sentiment:read"
985
+ ],
986
+ "sideEffect": "read",
987
+ "dryRunSupported": false,
988
+ "inputSchema": {
989
+ "type": "object",
990
+ "properties": {},
991
+ "additionalProperties": false
992
+ }
993
+ },
994
+ "sentiment.turnover": {
995
+ "cliKey": "sentiment.turnover",
996
+ "cliName": "sentiment turnover",
997
+ "method": "GET",
998
+ "path": "/v1/sentiment/turnover",
999
+ "description": "Intraday turnover time series. Requires `sentiment:read` scope.",
1000
+ "summary": "Intraday turnover time series",
1001
+ "positional": [],
1002
+ "outputDefault": "json",
1003
+ "pagination": "none",
1004
+ "stream": false,
1005
+ "billable": true,
1006
+ "idempotencyRequired": false,
1007
+ "scopesAny": [
1008
+ "sentiment:read"
1009
+ ],
1010
+ "sideEffect": "read",
1011
+ "dryRunSupported": false,
1012
+ "inputSchema": {
1013
+ "type": "object",
1014
+ "properties": {
1015
+ "scope": {
1016
+ "type": "string",
1017
+ "enum": [
1018
+ "all_a",
1019
+ "all_a_ex_st",
1020
+ "main_board",
1021
+ "star_market",
1022
+ "chinext",
1023
+ "bse"
1024
+ ],
1025
+ "default": "all_a_ex_st",
1026
+ "description": "Universe filter."
1027
+ }
1028
+ },
1029
+ "additionalProperties": false
1030
+ }
1031
+ },
1032
+ "signals.outcome": {
1033
+ "cliKey": "signals.outcome",
1034
+ "cliName": "signals outcome",
1035
+ "method": "GET",
1036
+ "path": "/v1/signals/{signal_id}/outcome",
1037
+ "description": "单条 signal 的细化结果追踪。",
1038
+ "summary": "Outcome trace for a single signal",
1039
+ "positional": [
1040
+ "signal_id"
1041
+ ],
1042
+ "outputDefault": "json",
1043
+ "pagination": "none",
1044
+ "stream": false,
1045
+ "billable": false,
1046
+ "idempotencyRequired": false,
1047
+ "scopesAny": [],
1048
+ "sideEffect": "read",
1049
+ "dryRunSupported": false,
1050
+ "inputSchema": {
1051
+ "type": "object",
1052
+ "properties": {
1053
+ "signal_id": {
1054
+ "type": "string",
1055
+ "description": "Signal id (returned by signals/outcomes items[].signal_id)."
1056
+ }
1057
+ },
1058
+ "additionalProperties": false,
1059
+ "required": [
1060
+ "signal_id"
1061
+ ]
1062
+ }
1063
+ },
1064
+ "signals.outcomes": {
1065
+ "cliKey": "signals.outcomes",
1066
+ "cliName": "signals outcomes",
1067
+ "method": "GET",
1068
+ "path": "/v1/signals/outcomes",
1069
+ "description": "返回分析师 views 派生信号的实际结果(目标价命中 / 止损 / 到期),含命中时长、最大回撤等。",
1070
+ "summary": "Outcomes of analyst-view-derived signals",
1071
+ "positional": [],
1072
+ "outputDefault": "json",
1073
+ "pagination": "offset",
1074
+ "stream": false,
1075
+ "billable": false,
1076
+ "idempotencyRequired": false,
1077
+ "scopesAny": [],
1078
+ "sideEffect": "read",
1079
+ "dryRunSupported": false,
1080
+ "inputSchema": {
1081
+ "type": "object",
1082
+ "properties": {},
1083
+ "additionalProperties": false
1084
+ }
1085
+ },
1086
+ "squawk.audio": {
1087
+ "cliKey": "squawk.audio",
1088
+ "cliName": "squawk audio",
1089
+ "method": "GET",
1090
+ "path": "/v1/squawk/{item_id}/audio",
1091
+ "description": "返回 squawk 项的 TTS 音频(MP3)。直接 stream,可作为 `<audio>` src 用。",
1092
+ "summary": "Stream squawk TTS audio",
1093
+ "positional": [
1094
+ "item_id"
1095
+ ],
1096
+ "outputDefault": "json",
1097
+ "pagination": "none",
1098
+ "stream": false,
1099
+ "billable": false,
1100
+ "idempotencyRequired": false,
1101
+ "scopesAny": [],
1102
+ "sideEffect": "read",
1103
+ "dryRunSupported": false,
1104
+ "inputSchema": {
1105
+ "type": "object",
1106
+ "properties": {
1107
+ "item_id": {
1108
+ "type": "string",
1109
+ "description": "Squawk item id (returned by squawk.recent items[].id)."
1110
+ }
1111
+ },
1112
+ "additionalProperties": false,
1113
+ "required": [
1114
+ "item_id"
1115
+ ]
1116
+ }
1117
+ },
1118
+ "squawk.waveform": {
1119
+ "cliKey": "squawk.waveform",
1120
+ "cliName": "squawk waveform",
1121
+ "method": "GET",
1122
+ "path": "/v1/squawk/{item_id}/waveform",
1123
+ "description": "返回 squawk 音频的预计算波形 peak 数据,用于客户端波形可视化。",
1124
+ "summary": "Waveform peaks for squawk audio",
1125
+ "positional": [
1126
+ "item_id"
1127
+ ],
1128
+ "outputDefault": "json",
1129
+ "pagination": "none",
1130
+ "stream": false,
1131
+ "billable": false,
1132
+ "idempotencyRequired": false,
1133
+ "scopesAny": [],
1134
+ "sideEffect": "read",
1135
+ "dryRunSupported": false,
1136
+ "inputSchema": {
1137
+ "type": "object",
1138
+ "properties": {
1139
+ "item_id": {
1140
+ "type": "string",
1141
+ "description": "Squawk item id (returned by squawk.recent items[].id)."
1142
+ }
1143
+ },
1144
+ "additionalProperties": false,
1145
+ "required": [
1146
+ "item_id"
1147
+ ]
1148
+ }
1149
+ },
1150
+ "stocks.hot": {
1151
+ "cliKey": "stocks.hot",
1152
+ "cliName": "stocks hot",
1153
+ "method": "GET",
1154
+ "path": "/v1/stocks/hot",
1155
+ "description": "今日最热股票榜(来源 East-Money),按搜索 / 关注 / 评论综合分排序。",
1156
+ "summary": "Today's hot-stock leaderboard",
1157
+ "positional": [],
1158
+ "outputDefault": "json",
1159
+ "pagination": "none",
1160
+ "stream": false,
1161
+ "billable": false,
1162
+ "idempotencyRequired": false,
1163
+ "scopesAny": [],
1164
+ "sideEffect": "read",
1165
+ "dryRunSupported": false,
1166
+ "inputSchema": {
1167
+ "type": "object",
1168
+ "properties": {},
1169
+ "additionalProperties": false
1170
+ }
1171
+ },
1172
+ "stocks.social-hot": {
1173
+ "cliKey": "stocks.social-hot",
1174
+ "cliName": "stocks social-hot",
1175
+ "method": "GET",
1176
+ "path": "/v1/stocks/social-hot",
1177
+ "description": "跨平台(微博 / 雪球 / Twitter)社交媒体提及聚合榜,按提及量 / 情感打分。",
1178
+ "summary": "Cross-platform social-hot stocks",
1179
+ "positional": [],
1180
+ "outputDefault": "json",
1181
+ "pagination": "none",
1182
+ "stream": false,
1183
+ "billable": false,
1184
+ "idempotencyRequired": false,
1185
+ "scopesAny": [],
1186
+ "sideEffect": "read",
1187
+ "dryRunSupported": false,
1188
+ "inputSchema": {
1189
+ "type": "object",
1190
+ "properties": {},
1191
+ "additionalProperties": false
1192
+ }
1193
+ },
1194
+ "views.feed": {
1195
+ "cliKey": "views.feed",
1196
+ "cliName": "views feed",
1197
+ "method": "GET",
1198
+ "path": "/v1/views",
1199
+ "description": "分析师观点 / 卖方研报 / 长文本观点流。可按机构 / 分析师 / 证券 / hours 过滤。需要 `views:read` scope。",
1200
+ "summary": "List analyst views",
1201
+ "positional": [],
1202
+ "outputDefault": "json",
1203
+ "pagination": "offset",
1204
+ "stream": false,
1205
+ "billable": false,
1206
+ "idempotencyRequired": false,
1207
+ "scopesAny": [],
1208
+ "sideEffect": "read",
1209
+ "dryRunSupported": false,
1210
+ "inputSchema": {
1211
+ "type": "object",
1212
+ "properties": {},
1213
+ "additionalProperties": false
1214
+ }
1215
+ },
1216
+ "views.get": {
1217
+ "cliKey": "views.get",
1218
+ "cliName": "views get",
1219
+ "method": "GET",
1220
+ "path": "/v1/views/{view_id}",
1221
+ "description": "返回单条 view 完整内容、附件图片、tagged securities、AI 摘要。",
1222
+ "summary": "Fetch a single analyst view",
1223
+ "positional": [
1224
+ "view_id"
1225
+ ],
1226
+ "outputDefault": "json",
1227
+ "pagination": "none",
1228
+ "stream": false,
1229
+ "billable": false,
1230
+ "idempotencyRequired": false,
1231
+ "scopesAny": [],
1232
+ "sideEffect": "read",
1233
+ "dryRunSupported": false,
1234
+ "inputSchema": {
1235
+ "type": "object",
1236
+ "properties": {
1237
+ "view_id": {
1238
+ "type": "string",
1239
+ "description": "Analyst-view id (returned by views.recent / list items[].id)."
1240
+ }
1241
+ },
1242
+ "additionalProperties": false,
1243
+ "required": [
1244
+ "view_id"
1245
+ ]
1246
+ }
1247
+ },
1248
+ "views.recent": {
1249
+ "cliKey": "views.recent",
1250
+ "cliName": "views recent",
1251
+ "method": "GET",
1252
+ "path": "/v1/views/recent",
1253
+ "description": "List recent broker / analyst views (research notes, price targets, ratings). Filter by analyst, institution, or a specific security. Requires `views:read` scope.",
1254
+ "summary": "Recent broker / analyst views",
1255
+ "positional": [],
1256
+ "outputDefault": "json",
1257
+ "pagination": "none",
1258
+ "stream": false,
1259
+ "billable": true,
1260
+ "idempotencyRequired": false,
1261
+ "scopesAny": [
1262
+ "views:read"
1263
+ ],
1264
+ "sideEffect": "read",
1265
+ "dryRunSupported": false,
1266
+ "inputSchema": {
1267
+ "type": "object",
1268
+ "properties": {
1269
+ "analyst": {
1270
+ "type": "string",
1271
+ "description": "Analyst name (Chinese), exact or fuzzy."
1272
+ },
1273
+ "institution": {
1274
+ "type": "string",
1275
+ "description": "Broker / institution Chinese name."
1276
+ },
1277
+ "security": {
1278
+ "type": "string",
1279
+ "pattern": "^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$",
1280
+ "description": "Filter by security code."
1281
+ },
1282
+ "since_days": {
1283
+ "type": "integer",
1284
+ "minimum": 1,
1285
+ "maximum": 90,
1286
+ "default": 7,
1287
+ "description": "Lookback window in days. (Translated to hours upstream.)"
1288
+ },
1289
+ "limit": {
1290
+ "type": "integer",
1291
+ "minimum": 1,
1292
+ "maximum": 100,
1293
+ "default": 30,
1294
+ "description": "Max items per page."
1295
+ }
1296
+ },
1297
+ "additionalProperties": false
1298
+ }
1299
+ }
1300
+ };
1301
+ export function getOperation(key) {
1302
+ return OPERATIONS[key];
1303
+ }
1304
+ export function listOperations() {
1305
+ return Object.values(OPERATIONS);
1306
+ }