@hedeqiang/dsh-nl2sql 0.13.0 → 0.14.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.
package/service/query.js CHANGED
@@ -9,7 +9,7 @@ import { admitSql, prepareSql, stripSql } from '../sql-guard.js'
9
9
  import { cacheKey } from '../store.js'
10
10
  import { createHash } from 'node:crypto'
11
11
  import { writeXlsx } from '../xlsx.js'
12
- import { RESULT_CACHE_LIMIT, SENSITIVE_NAME, UserError, columnKind, fillChartHint, fmtNum, maskValue, newId, normalizeChart, suggestChart, summarize } from './shared.js'
12
+ import { RESULT_CACHE_LIMIT, SENSITIVE_NAME, UserError, callContext, columnKind, fillChartHint, fmtNum, maskValue, newId, normalizeChart, suggestChart, summarize } from './shared.js'
13
13
 
14
14
  export const methods = {
15
15
  // ---------------------------------------------------------------- query
@@ -36,6 +36,7 @@ export const methods = {
36
36
  await this.save()
37
37
  throw new UserError('nl2sql/access-denied', denied)
38
38
  }
39
+ callContext.getStore()?.phase?.('admitted', { datasource: ds.name, title })
39
40
  let appliedFilters = []
40
41
  if (filters?.length) {
41
42
  let f
@@ -108,15 +109,22 @@ export const methods = {
108
109
  }
109
110
  }
110
111
  const started = Date.now()
112
+ // Optional per-call context (MCP tools/call): progress phases and cancellation.
113
+ const call = callContext.getStore()
114
+ call?.phase?.('running', { datasource: ds.name, title })
111
115
  let res
112
116
  try {
113
- res = await this.withDriver(ds, d => d.query(prepared, { timeoutMs: settings.timeoutMs, maxRows: settings.maxRows }))
117
+ if (call?.signal?.aborted) throw new UserError('query/cancelled', '查询已取消')
118
+ res = await this.withDriver(ds, d => d.query(prepared, { timeoutMs: settings.timeoutMs, maxRows: settings.maxRows, ...(call?.signal ? { signal: call.signal } : {}) }))
119
+ if (call?.signal?.aborted) throw new UserError('query/cancelled', '查询已取消')
114
120
  } catch (error) {
115
- this.audit({ ds, sessionId, source, sql: admitted.sql, title, status: 'error', error: error.message, elapsedMs: Date.now() - started, actor })
121
+ const cancelled = error.code === 'query/cancelled' || call?.signal?.aborted
122
+ this.audit({ ds, sessionId, source, sql: admitted.sql, title, status: cancelled ? 'cancelled' : 'error', error: cancelled ? 'cancelled by the client' : error.message, elapsedMs: Date.now() - started, actor })
116
123
  await this.save()
117
124
  throw error
118
125
  }
119
126
  const elapsedMs = Date.now() - started
127
+ call?.phase?.('fetched', { datasource: ds.name, title, rows: Math.min(res.rows.length, settings.maxRows) })
120
128
  const truncated = res.rows.length > settings.maxRows
121
129
  let cells = truncated ? res.rows.slice(0, settings.maxRows) : res.rows
122
130
  const schema = fullSchema
package/service/shared.js CHANGED
@@ -4,7 +4,13 @@
4
4
  import { createHash, randomBytes } from 'node:crypto'
5
5
  import { DIALECTS, describeError } from '../drivers.js'
6
6
  import { sqliteDialectHints } from '../sqlite-driver.js'
7
+ import { AsyncLocalStorage } from 'node:async_hooks'
7
8
 
9
+ /**
10
+ * Per-call context for long requests (MCP tools/call): { signal?: AbortSignal, phase?(name, info) }.
11
+ * runQuery reports phases and passes the signal to drivers that can cancel a running statement.
12
+ */
13
+ export const callContext = new AsyncLocalStorage()
8
14
 
9
15
  export const SUPPORTED_TYPES = Object.keys(DIALECTS)
10
16
 
@@ -231,6 +237,9 @@ RECORD_REF.bitableRun = 'syncId'
231
237
  // Daily digest runs (service/proactive.js).
232
238
  RECORD_LIMITS.digestRun = 1000
233
239
  RECORD_REF.digestRun = 'digestId'
240
+ // MCP per-token call log (service/mcp.js): time, method/tool, data source, ms, status, rows.
241
+ RECORD_LIMITS.mcpCall = 5000
242
+ RECORD_REF.mcpCall = 'tokenId'
234
243
 
235
244
  /**
236
245
  * Growing logs (audit history, feedback, push deliveries, alert events, admin