@yejiming/dsh-data-agent 0.0.11 → 0.0.13

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 (49) hide show
  1. package/README.en.md +70 -15
  2. package/README.md +70 -15
  3. package/conformance/dsh-ecosystem/baseline.json +59 -0
  4. package/conformance/dsh-ecosystem/dependencies.json +41 -0
  5. package/conformance/dsh-ecosystem/fixtures/host-degraded.fixture.json +12 -0
  6. package/conformance/dsh-ecosystem/fixtures/host-eligible.fixture.json +13 -0
  7. package/conformance/dsh-ecosystem/fixtures/host-rejected.fixture.json +12 -0
  8. package/conformance/dsh-ecosystem/fixtures/profiles/native-only/package.json +8 -0
  9. package/conformance/dsh-ecosystem/fixtures/profiles/native-plus-adapter/package.json +9 -0
  10. package/conformance/dsh-ecosystem/inventory.json +77 -0
  11. package/conformance/dsh-ecosystem/restrictions.json +20 -0
  12. package/dsh-plugin.json +67 -0
  13. package/lib/client.js +1352 -130
  14. package/lib/client.js.map +1 -1
  15. package/lib/{command-DuCpwVbl.js → command-utC5MHd9.js} +101 -60
  16. package/lib/command.js +1 -1
  17. package/lib/{connections-5sfdEDsG.js → connections-CHY4uB6z.js} +747 -65
  18. package/lib/defaults-Cngd8Tf8.js +131 -0
  19. package/lib/ecosystem.js +19 -0
  20. package/lib/index.js +40 -33
  21. package/lib/routes.js +5 -6
  22. package/lib/{tool-DVh61An-.js → tool-ZTOS4B33.js} +161 -177
  23. package/lib/tool.js +1 -1
  24. package/lib/types/analysis-html.d.ts +27 -0
  25. package/lib/types/analysis.d.ts +13 -1
  26. package/lib/types/client/DataAgentWorkbench.d.ts +1 -2
  27. package/lib/types/client/QueryResultTable.d.ts +13 -0
  28. package/lib/types/client/locales.d.ts +48 -0
  29. package/lib/types/client/persistence.d.ts +3 -1
  30. package/lib/types/client/query-export.d.ts +11 -0
  31. package/lib/types/client-discovery.d.ts +3 -4
  32. package/lib/types/clients.d.ts +14 -8
  33. package/lib/types/command.d.ts +2 -2
  34. package/lib/types/connections.d.ts +33 -4
  35. package/lib/types/database-types.d.ts +23 -0
  36. package/lib/types/defaults.d.ts +4 -0
  37. package/lib/types/ecosystem.d.ts +13 -0
  38. package/lib/types/index.d.ts +21 -16
  39. package/lib/types/presentation-text.d.ts +3 -0
  40. package/lib/types/query.d.ts +13 -11
  41. package/lib/types/sql.d.ts +9 -1
  42. package/lib/types/storage.d.ts +11 -1
  43. package/lib/types/structured-read.d.ts +2 -2
  44. package/lib/types/structured.d.ts +1 -1
  45. package/lib/types/tool.d.ts +5 -5
  46. package/lib/types/tui-connection-form.d.ts +10 -7
  47. package/package.json +66 -42
  48. package/preset/data-agent/agent.cordis.yml +9 -4
  49. package/lib/defaults-DP4RyRh1.js +0 -21
@@ -13,6 +13,9 @@ export declare const zh: {
13
13
  'type.oracle': string;
14
14
  'type.hive': string;
15
15
  'type.impala': string;
16
+ 'type.clickhouse': string;
17
+ 'type.doris': string;
18
+ 'type.sqlserver': string;
16
19
  'form.host': string;
17
20
  'form.port': string;
18
21
  'form.user': string;
@@ -28,6 +31,8 @@ export declare const zh: {
28
31
  'form.rememberPassword.hint': string;
29
32
  'form.readonly': string;
30
33
  'form.readonly.hint': string;
34
+ 'form.secure': string;
35
+ 'form.secure.hint': string;
31
36
  'form.database': string;
32
37
  'form.database.oracle': string;
33
38
  'form.database.hive': string;
@@ -57,10 +62,29 @@ export declare const zh: {
57
62
  'wb.columns': string;
58
63
  'wb.sql': string;
59
64
  'wb.sql.placeholder': string;
65
+ 'wb.sql.placeholder.sqlserver': string;
60
66
  'wb.sql.run': string;
61
67
  'wb.sql.running': string;
62
68
  'wb.sql.shortcut': string;
63
69
  'wb.sql.empty': string;
70
+ 'wb.sql.result.summary': string;
71
+ 'wb.sql.result.capped': string;
72
+ 'wb.sql.result.outputTruncated': string;
73
+ 'wb.sql.result.table': string;
74
+ 'wb.sql.result.noRows': string;
75
+ 'wb.sql.command.done': string;
76
+ 'wb.sql.export.actions': string;
77
+ 'wb.sql.export.excel': string;
78
+ 'wb.sql.export.csv': string;
79
+ 'wb.sql.export.clipboard': string;
80
+ 'wb.sql.exporting': string;
81
+ 'wb.sql.copying': string;
82
+ 'wb.sql.export.done': string;
83
+ 'wb.sql.copy.done': string;
84
+ 'wb.sql.export.failed': string;
85
+ 'wb.sql.page.summary': string;
86
+ 'wb.sql.page.previous': string;
87
+ 'wb.sql.page.next': string;
64
88
  'wb.loading': string;
65
89
  'wb.empty': string;
66
90
  'wb.modal.title': string;
@@ -101,6 +125,9 @@ export declare const en: {
101
125
  'type.oracle': string;
102
126
  'type.hive': string;
103
127
  'type.impala': string;
128
+ 'type.clickhouse': string;
129
+ 'type.doris': string;
130
+ 'type.sqlserver': string;
104
131
  'form.host': string;
105
132
  'form.port': string;
106
133
  'form.user': string;
@@ -116,6 +143,8 @@ export declare const en: {
116
143
  'form.rememberPassword.hint': string;
117
144
  'form.readonly': string;
118
145
  'form.readonly.hint': string;
146
+ 'form.secure': string;
147
+ 'form.secure.hint': string;
119
148
  'form.database': string;
120
149
  'form.database.oracle': string;
121
150
  'form.database.hive': string;
@@ -145,10 +174,29 @@ export declare const en: {
145
174
  'wb.columns': string;
146
175
  'wb.sql': string;
147
176
  'wb.sql.placeholder': string;
177
+ 'wb.sql.placeholder.sqlserver': string;
148
178
  'wb.sql.run': string;
149
179
  'wb.sql.running': string;
150
180
  'wb.sql.shortcut': string;
151
181
  'wb.sql.empty': string;
182
+ 'wb.sql.result.summary': string;
183
+ 'wb.sql.result.capped': string;
184
+ 'wb.sql.result.outputTruncated': string;
185
+ 'wb.sql.result.table': string;
186
+ 'wb.sql.result.noRows': string;
187
+ 'wb.sql.command.done': string;
188
+ 'wb.sql.export.actions': string;
189
+ 'wb.sql.export.excel': string;
190
+ 'wb.sql.export.csv': string;
191
+ 'wb.sql.export.clipboard': string;
192
+ 'wb.sql.exporting': string;
193
+ 'wb.sql.copying': string;
194
+ 'wb.sql.export.done': string;
195
+ 'wb.sql.copy.done': string;
196
+ 'wb.sql.export.failed': string;
197
+ 'wb.sql.page.summary': string;
198
+ 'wb.sql.page.previous': string;
199
+ 'wb.sql.page.next': string;
152
200
  'wb.loading': string;
153
201
  'wb.empty': string;
154
202
  'wb.modal.title': string;
@@ -9,7 +9,7 @@
9
9
  * key is versioned so a future shape change can migrate or ignore old data.
10
10
  * @module @yejiming/dsh-data-agent/persistence
11
11
  */
12
- import type { DatabaseType } from './DataAgentWorkbench.tsx';
12
+ import { type DatabaseType } from '../database-types.ts';
13
13
  /** localStorage key holding the most recent connection configuration. */
14
14
  export declare const CONNECTION_STORAGE_KEY = "dsh-data-agent.connection.v1";
15
15
  /** The persisted connection configuration. */
@@ -28,6 +28,8 @@ export interface SavedConnection {
28
28
  /** Opt-in flag; when true, {@link saveConnection} may write `password`. */
29
29
  persistPassword?: boolean;
30
30
  readonly?: boolean;
31
+ /** ClickHouse only: HTTPS with normal certificate verification. */
32
+ secure?: boolean;
31
33
  /** Diagnostic timestamp of the save. */
32
34
  savedAt: string;
33
35
  }
@@ -0,0 +1,11 @@
1
+ /** One structured result shape accepted by every workbench export. */
2
+ export interface QueryExportData {
3
+ columns: readonly string[];
4
+ rows: readonly Readonly<Record<string, string | null>>[];
5
+ }
6
+ /** UTF-8 CSV with BOM so desktop Excel opens Chinese text correctly. */
7
+ export declare function queryResultToCsv(data: QueryExportData): string;
8
+ /** Tabular plain text suitable for spreadsheet clipboard paste. */
9
+ export declare function queryResultToTsv(data: QueryExportData): string;
10
+ /** Build a real XLSX workbook using inline strings, frozen headers, and filters. */
11
+ export declare function queryResultToXlsx(data: QueryExportData): Uint8Array;
@@ -8,8 +8,7 @@
8
8
  * involved, and the exact discovery environment is returned for spawn.
9
9
  * @module @yejiming/dsh-data-agent/client-discovery
10
10
  */
11
- import type { ClientConfig } from './clients.ts';
12
- import type { DatabaseType } from './connections.ts';
11
+ import type { CliDatabaseType, ClientConfig } from './clients.ts';
13
12
  /** Host facts are injectable so all supported platforms can be tested on one CI host. */
14
13
  export interface ClientDiscoverySystem {
15
14
  platform: NodeJS.Platform;
@@ -28,7 +27,7 @@ export interface ClientExecutableResolution {
28
27
  }
29
28
  /** Input for one database client resolution attempt. */
30
29
  export interface ResolveClientExecutableOptions {
31
- type: DatabaseType;
30
+ type: CliDatabaseType;
32
31
  command: string;
33
32
  config?: ClientConfig;
34
33
  env: Readonly<Record<string, string>>;
@@ -37,7 +36,7 @@ export interface ResolveClientExecutableOptions {
37
36
  system?: ClientDiscoverySystem;
38
37
  }
39
38
  /** Build ordered fallback directories without recursively scanning the host. */
40
- export declare function buildClientSearchDirectories(type: DatabaseType, config: ClientConfig | undefined, signal: AbortSignal, system?: ClientDiscoverySystem): Promise<string[]>;
39
+ export declare function buildClientSearchDirectories(type: CliDatabaseType, config: ClientConfig | undefined, signal: AbortSignal, system?: ClientDiscoverySystem): Promise<string[]>;
41
40
  /**
42
41
  * Resolve one configured/default client. Current PATH (or an explicit path)
43
42
  * always wins. Only a missing bare command activates bounded PATH discovery.
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Pure CLI-client template construction for the supported database types.
3
3
  * Everything here is a function of (type, connection, optional overrides) —
4
- * no process, no I/O — so the injection-safety surface is unit-testable:
4
+ * no process, no I/O — so the CLI injection-safety surface is unit-testable:
5
5
  * argv stays an array (never shell-interpreted), the SQL itself always
6
6
  * travels on stdin, and passwords only ever appear in the environment
7
- * entries (`MYSQL_PWD` / `PGPASSWORD`) or in a stdin connect prefix
8
- * (Oracle `connect`, Hive `!connect`) — never in argv, logs, or returns.
7
+ * entries (`MYSQL_PWD` / `PGPASSWORD` / `SQLCMDPASSWORD`) or in a stdin
8
+ * connect prefix (Oracle `connect`, Hive `!connect`) — never in argv, logs,
9
+ * or returns. ClickHouse HTTP authentication lives in the shared runner.
9
10
  *
10
11
  * Metadata (schemas / tables / describe) queries and their per-type output
11
12
  * parsers live here too, so the /schemas /tables /describe routes stay thin.
@@ -13,8 +14,8 @@
13
14
  */
14
15
  import type { DatabaseConnection, DatabaseType } from './connections.ts';
15
16
  import z from 'schemastery';
16
- import { assertSingleStatement, hasTopLevelKeyword, stripTrailingTerminator } from './sql.ts';
17
- export { assertSingleStatement, hasTopLevelKeyword, stripTrailingTerminator };
17
+ import { assertSingleStatement, assertSqlServerSafeInput, hasTopLevelKeyword, stripTrailingTerminator } from './sql.ts';
18
+ export { assertSingleStatement, assertSqlServerSafeInput, hasTopLevelKeyword, stripTrailingTerminator };
18
19
  /**
19
20
  * Classify a SQL text as a read or write statement by its FIRST effective
20
21
  * token (a conservative read whitelist, not a parser). `with` is read only
@@ -33,6 +34,8 @@ export declare function classifyStatement(sql: string, type: DatabaseType): 'rea
33
34
  * unparseable LIMIT is left for the client (structured tools still truncate).
34
35
  */
35
36
  export declare function enforceReadRowLimit(sql: string, type: DatabaseType, maxRows: number): string;
37
+ /** Rare control separator keeps ordinary tabs/pipes inside sqlcmd values intact. */
38
+ export declare const SQLSERVER_COLUMN_SEPARATOR = "\u001F";
36
39
  /**
37
40
  * Validate and quote one schema/table identifier for a safe metadata query.
38
41
  * Identifiers are restricted to `[A-Za-z0-9_$]+` and then wrapped per type:
@@ -51,6 +54,8 @@ export interface ClientConfig {
51
54
  /** Absolute directories searched after the current subprocess PATH. */
52
55
  searchPaths?: readonly string[];
53
56
  }
57
+ /** Database types backed by a locally resolved CLI executable. */
58
+ export type CliDatabaseType = Exclude<DatabaseType, 'clickhouse'>;
54
59
  /** Loader schema for one client override (all fields optional at input). */
55
60
  export declare const clientConfigSchema: z<Schemastery.ObjectS<{
56
61
  command: z<string, string>;
@@ -61,16 +66,15 @@ export declare const clientConfigSchema: z<Schemastery.ObjectS<{
61
66
  args: z<string[], string[]>;
62
67
  searchPaths: z<string[], string[]>;
63
68
  }>>;
64
- /** Loader schema for the whole `clients` config object (any type key). */
65
69
  export declare const clientsSchema: z<import("cosmokit").Dict<{
66
70
  command?: string | null | undefined;
67
71
  args?: string[] | null | undefined;
68
72
  searchPaths?: string[] | null | undefined;
69
- } & import("@deepseek-ai/cosmokit").Dict, string>, import("cosmokit").Dict<Schemastery.ObjectT<{
73
+ } & import("@deepseek-ai/cosmokit").Dict, "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "doris" | "sqlserver">, import("cosmokit").Dict<Schemastery.ObjectT<{
70
74
  command: z<string, string>;
71
75
  args: z<string[], string[]>;
72
76
  searchPaths: z<string[], string[]>;
73
- }>, string>>;
77
+ }>, "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "doris" | "sqlserver">>;
74
78
  /**
75
79
  * A fully constructed client invocation: argv (command + flags, no SQL),
76
80
  * the credential env entries, and the stdin prefix (Oracle/Hive connect
@@ -127,6 +131,8 @@ export interface ColumnInfo {
127
131
  type: string;
128
132
  nullable?: boolean;
129
133
  }
134
+ /** Remove only terminal sqlcmd row-count footer lines, never matching data in the middle. */
135
+ export declare function stripSqlServerRowCountFooter(stdout: string): string;
130
136
  /**
131
137
  * Parse one type's describe output into columns. Formats:
132
138
  * - mysql `--batch`: `Field\tType\tNull\tKey\t...` (skip header);
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { Context } from '@deepseek-ai/cordis';
8
8
  import type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands';
9
- import { type ConnectionFormDraft, type ConnectionSummary, type DatabaseConnectionInput } from './connections.ts';
9
+ import { type ConnectionFormDraft, type ConnectionFormInitial, type ConnectionSummary, type DatabaseConnectionInput } from './connections.ts';
10
10
  export declare const name = "data-agent-database-command";
11
11
  export declare const inject: string[];
12
12
  export declare const DATABASE_COMMAND_USAGE: string;
@@ -24,7 +24,7 @@ export declare const DATA_AGENT_TOOL_NAMES: readonly ["str_replace_editor", "sql
24
24
  export interface DatabaseCommandInteraction {
25
25
  isTuiFormAvailable(): boolean;
26
26
  collectTuiConnection(signal: AbortSignal, options: {
27
- initialDraft?: ConnectionFormDraft;
27
+ initialDraft?: ConnectionFormInitial;
28
28
  persistDraft(draft: ConnectionFormDraft): Promise<void>;
29
29
  }): Promise<DatabaseConnectionInput | undefined>;
30
30
  }
@@ -9,11 +9,11 @@
9
9
  */
10
10
  import type { Context } from '@deepseek-ai/cordis';
11
11
  import { type ClientConfig, type ColumnInfo } from './clients.ts';
12
+ import { type DatabaseType } from './database-types.ts';
12
13
  import { type QueryResult } from './query.ts';
14
+ export type { DatabaseType } from './database-types.ts';
13
15
  /** Key of the wildcard connection applied to sessions without an exact entry. */
14
16
  export declare const WILDCARD_SESSION = "*";
15
- /** Supported database client kinds. */
16
- export type DatabaseType = 'mysql' | 'postgres' | 'sqlite' | 'oracle' | 'hive' | 'impala';
17
17
  /** How a non-SQLite profile authenticates without ever persisting a secret. */
18
18
  export type CredentialMode = 'none' | 'password' | 'reference';
19
19
  /** Safe credential facts returned to UI/command surfaces. */
@@ -33,6 +33,8 @@ export interface DatabaseConnectionInput {
33
33
  /** Non-secret DSH credential reference, mutually exclusive with password. */
34
34
  passwordRef?: string;
35
35
  readonly?: boolean;
36
+ /** ClickHouse HTTP transport uses HTTPS with normal certificate verification. */
37
+ secure?: boolean;
36
38
  /** Optional stable durable profile id. */
37
39
  profileId?: string;
38
40
  /** Optional human-readable profile label. */
@@ -53,6 +55,7 @@ export interface ConnectionSummary {
53
55
  database: string;
54
56
  passwordRef?: string;
55
57
  readonly?: boolean;
58
+ secure?: boolean;
56
59
  profileId?: string;
57
60
  name?: string;
58
61
  tables?: string[];
@@ -72,6 +75,7 @@ export interface PersistedConnectionProfile {
72
75
  user?: string;
73
76
  database: string;
74
77
  readonly?: boolean;
78
+ secure?: boolean;
75
79
  passwordRef?: string;
76
80
  credentialMode?: CredentialMode;
77
81
  updatedAt: string;
@@ -89,14 +93,25 @@ export interface ConnectionFormDraft {
89
93
  user: string;
90
94
  database: string;
91
95
  readonly: boolean;
96
+ secure?: boolean;
97
+ }
98
+ /** Form initial values may also restore one non-secret credential reference. */
99
+ export interface ConnectionFormInitial extends ConnectionFormDraft {
100
+ passwordRef?: string;
92
101
  }
93
102
  /** Durable draft record. Passwords and credential references are forbidden. */
94
103
  export interface PersistedConnectionFormDraft extends ConnectionFormDraft {
95
104
  updatedAt: string;
96
105
  }
106
+ /** Deterministic latest-profile lookup result supplied by durable adapters. */
107
+ export interface PersistedConnectionProfileEntry {
108
+ profileId: string;
109
+ profile: PersistedConnectionProfile;
110
+ }
97
111
  /** Minimal durable seam; backed by a DSH storage domain in production. */
98
112
  export interface ConnectionPersistence {
99
113
  getProfile(profileId: string): PersistedConnectionProfile | undefined;
114
+ getLatestProfile?(): PersistedConnectionProfileEntry | undefined;
100
115
  putProfile(profileId: string, profile: PersistedConnectionProfile): Promise<void>;
101
116
  deleteProfile(profileId: string): Promise<boolean>;
102
117
  getBinding(sessionId: string): SessionConnectionBinding | undefined;
@@ -104,6 +119,7 @@ export interface ConnectionPersistence {
104
119
  deleteBinding(sessionId: string): Promise<boolean>;
105
120
  getDraft?(sessionId: string): PersistedConnectionFormDraft | undefined;
106
121
  putDraft?(sessionId: string, draft: PersistedConnectionFormDraft): Promise<void>;
122
+ deleteDraft?(sessionId: string): Promise<boolean>;
107
123
  }
108
124
  /** Shared service configuration supplied by the host plugin. */
109
125
  export interface ConnectionServiceOptions {
@@ -120,6 +136,17 @@ export interface ConnectResult {
120
136
  tables: string[];
121
137
  summary: ConnectionSummary;
122
138
  }
139
+ /** Structured read result or raw command message returned to interactive surfaces. */
140
+ export type InteractiveQueryResult = {
141
+ kind: 'table';
142
+ columns: string[];
143
+ rows: Record<string, string | null>[];
144
+ elapsedMs: number;
145
+ truncated: boolean;
146
+ maxRows: number;
147
+ } | ({
148
+ kind: 'message';
149
+ } & QueryResult);
123
150
  /** Host-plane service (`ctx.dataAgentConnections`). */
124
151
  export interface DataAgentConnections {
125
152
  /** Compatibility setter for config seeds/tests; does not persist. */
@@ -131,8 +158,8 @@ export interface DataAgentConnections {
131
158
  has(sessionId: string): boolean;
132
159
  /** Compatibility runtime-only clear. Use disconnect() for durable bindings. */
133
160
  clear(sessionId: string): void;
134
- /** Restore the latest non-secret interactive form values for this session. */
135
- getFormDraft(sessionId: string): ConnectionFormDraft | undefined;
161
+ /** Restore exact or latest-profile non-secret interactive form values. */
162
+ getFormDraft(sessionId: string): ConnectionFormInitial | undefined;
136
163
  /** Save non-secret form values; the implementation never accepts a password. */
137
164
  saveFormDraft(sessionId: string, draft: ConnectionFormDraft): Promise<void>;
138
165
  status(sessionId: string): Promise<ConnectionSummary | undefined>;
@@ -144,6 +171,7 @@ export interface DataAgentConnections {
144
171
  listTables(sessionId: string, schema: string | undefined, signal: AbortSignal): Promise<string[]>;
145
172
  describe(sessionId: string, schema: string | undefined, table: string, signal: AbortSignal): Promise<ColumnInfo[]>;
146
173
  query(sessionId: string, sql: string, signal: AbortSignal): Promise<QueryResult>;
174
+ executeInteractive(sessionId: string, sql: string, signal: AbortSignal): Promise<InteractiveQueryResult>;
147
175
  }
148
176
  /** Build a password-stripped copy of one connection. */
149
177
  export declare function summarize(connection: DatabaseConnection): ConnectionSummary;
@@ -157,3 +185,4 @@ export declare function normalizeConnectionInput(input: DatabaseConnectionInput,
157
185
  export declare function createConnectionService(ctx?: Context, options?: ConnectionServiceOptions, persistence?: ConnectionPersistence): DataAgentConnections;
158
186
  /** Backward-compatible in-memory store factory used by embedders/tests. */
159
187
  export declare function createConnectionStore(): DataAgentConnections;
188
+ export declare function validatePasswordRef(value: string): void;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Browser-safe database type descriptors shared by every DSH surface.
3
+ * Keep this module dependency-free: server-only client/process details belong
4
+ * in the database adapters, not in Web or persistence bundles.
5
+ */
6
+ export declare const DATABASE_TYPES: readonly ["mysql", "postgres", "sqlite", "oracle", "hive", "impala", "clickhouse", "doris", "sqlserver"];
7
+ export type DatabaseType = typeof DATABASE_TYPES[number];
8
+ export interface DatabaseTypeDescriptor {
9
+ type: DatabaseType;
10
+ label: string;
11
+ localeKey: `type.${DatabaseType}`;
12
+ defaultPort: number;
13
+ defaultUser: string;
14
+ fileBased: boolean;
15
+ /** HTTPS port used when ClickHouse secure transport is selected. */
16
+ securePort?: number;
17
+ }
18
+ export declare const DATABASE_TYPE_DESCRIPTORS: Readonly<Record<DatabaseType, DatabaseTypeDescriptor>>;
19
+ export declare function isDatabaseType(value: unknown): value is DatabaseType;
20
+ export declare function databaseTypeDescriptor(type: DatabaseType): DatabaseTypeDescriptor;
21
+ export declare function defaultDatabasePort(type: DatabaseType, secure?: boolean): number;
22
+ export declare function defaultDatabaseUser(type: DatabaseType): string;
23
+ export declare function databaseTypeLabel(type: DatabaseType): string;
@@ -16,6 +16,10 @@ export declare const DEFAULT_QUERY_TIMEOUT_MS = 30000;
16
16
  export declare const DEFAULT_MAX_RESULT_CHARS = 20000;
17
17
  /** Maximum structured rows returned by one database read tool call. */
18
18
  export declare const DEFAULT_MAX_ROWS = 100;
19
+ /** Hard row cap for one structured Web workbench result/export. */
20
+ export declare const WORKBENCH_MAX_EXPORT_ROWS = 50000;
21
+ /** Bounded capture size for the larger structured Web workbench result. */
22
+ export declare const WORKBENCH_MAX_RESULT_CHARS: number;
19
23
  /** Cap on one /query SQL text length (abuse guard; the wire body stays small). */
20
24
  export declare const DEFAULT_MAX_QUERY_CHARS = 65536;
21
25
  /** Grace period for the subprocess terminate escalation. */
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Community v0.15 host facet.
3
+ *
4
+ * This facet intentionally publishes no commands, tools, UI, routes, storage,
5
+ * credentials, or database effects. The existing Cordis bundle remains the
6
+ * sole functional runtime so hosts may discover the ecosystem declaration
7
+ * without double-registering data-agent behavior.
8
+ */
9
+ import { type FacetProjection } from '@dsh-std/sdk';
10
+ /** Stable degraded snapshot for declaration-only ecosystem discovery. */
11
+ export declare const ECOSYSTEM_SNAPSHOT: FacetProjection;
12
+ declare const ecosystemFacet: import("@dsh-std/sdk").FacetModule;
13
+ export default ecosystemFacet;
@@ -25,14 +25,14 @@ declare module '@deepseek-ai/cordis' {
25
25
  }
26
26
  import z from 'schemastery';
27
27
  import { type DataAgentConnections, type DatabaseType } from './connections.ts';
28
- import { type ClientConfig } from './clients.ts';
28
+ import { type CliDatabaseType, type ClientConfig } from './clients.ts';
29
29
  import { type Config as ToolConfig } from './tool.ts';
30
30
  /** Cordis plugin name (diagnostics only). */
31
31
  export declare const name = "data-agent";
32
32
  /** Services required before the profile entry can mount its preset layer. */
33
33
  export declare const inject: string[];
34
34
  /** Deployment overrides for one database type's CLI client. */
35
- export type ClientsConfig = Partial<Record<DatabaseType, ClientConfig>>;
35
+ export type ClientsConfig = Partial<Record<CliDatabaseType, ClientConfig>>;
36
36
  /**
37
37
  * One config-seeded connection. Deliberately password-free: passwords are a
38
38
  * memory-only / connect-time value, so only the /connect route may carry one.
@@ -47,6 +47,8 @@ export interface SeededConnectionConfig {
47
47
  database: string;
48
48
  /** Optional per-seed read-only guard. */
49
49
  readonly?: boolean;
50
+ /** ClickHouse only: use HTTPS with certificate verification. */
51
+ secure?: boolean;
50
52
  /** Safe credential reference. Real passwords are rejected by the schema. */
51
53
  passwordRef?: string;
52
54
  password?: never;
@@ -94,27 +96,29 @@ export declare const Config: z<Schemastery.ObjectS<{
94
96
  command?: string | null | undefined;
95
97
  args?: string[] | null | undefined;
96
98
  searchPaths?: string[] | null | undefined;
97
- } & import("@deepseek-ai/cosmokit").Dict, string>, import("cosmokit").Dict<Schemastery.ObjectT<{
99
+ } & import("@deepseek-ai/cosmokit").Dict, "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "doris" | "sqlserver">, import("cosmokit").Dict<Schemastery.ObjectT<{
98
100
  command: z<string, string>;
99
101
  args: z<string[], string[]>;
100
102
  searchPaths: z<string[], string[]>;
101
- }>, string>>;
103
+ }>, "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "doris" | "sqlserver">>;
102
104
  connections: z<import("cosmokit").Dict<{
103
- type?: "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | null | undefined;
105
+ type?: "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "clickhouse" | "doris" | "sqlserver" | null | undefined;
104
106
  host?: string | null | undefined;
105
107
  port?: number | null | undefined;
106
108
  user?: string | null | undefined;
107
109
  database?: string | null | undefined;
108
110
  readonly?: boolean | null | undefined;
111
+ secure?: boolean | null | undefined;
109
112
  passwordRef?: string | null | undefined;
110
113
  password?: null | undefined;
111
114
  } & import("@deepseek-ai/cosmokit").Dict, string>, import("cosmokit").Dict<Schemastery.ObjectT<{
112
- type: z<"mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala", "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala">;
115
+ type: z<"mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "clickhouse" | "doris" | "sqlserver", "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "clickhouse" | "doris" | "sqlserver">;
113
116
  host: z<string, string>;
114
117
  port: z<number, number>;
115
118
  user: z<string, string>;
116
119
  database: z<string, string>;
117
120
  readonly: z<boolean, boolean>;
121
+ secure: z<boolean, boolean>;
118
122
  passwordRef: z<string, string>;
119
123
  password: z<never, never>;
120
124
  }>, string>>;
@@ -133,27 +137,29 @@ export declare const Config: z<Schemastery.ObjectS<{
133
137
  command?: string | null | undefined;
134
138
  args?: string[] | null | undefined;
135
139
  searchPaths?: string[] | null | undefined;
136
- } & import("@deepseek-ai/cosmokit").Dict, string>, import("cosmokit").Dict<Schemastery.ObjectT<{
140
+ } & import("@deepseek-ai/cosmokit").Dict, "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "doris" | "sqlserver">, import("cosmokit").Dict<Schemastery.ObjectT<{
137
141
  command: z<string, string>;
138
142
  args: z<string[], string[]>;
139
143
  searchPaths: z<string[], string[]>;
140
- }>, string>>;
144
+ }>, "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "doris" | "sqlserver">>;
141
145
  connections: z<import("cosmokit").Dict<{
142
- type?: "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | null | undefined;
146
+ type?: "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "clickhouse" | "doris" | "sqlserver" | null | undefined;
143
147
  host?: string | null | undefined;
144
148
  port?: number | null | undefined;
145
149
  user?: string | null | undefined;
146
150
  database?: string | null | undefined;
147
151
  readonly?: boolean | null | undefined;
152
+ secure?: boolean | null | undefined;
148
153
  passwordRef?: string | null | undefined;
149
154
  password?: null | undefined;
150
155
  } & import("@deepseek-ai/cosmokit").Dict, string>, import("cosmokit").Dict<Schemastery.ObjectT<{
151
- type: z<"mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala", "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala">;
156
+ type: z<"mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "clickhouse" | "doris" | "sqlserver", "mysql" | "postgres" | "sqlite" | "oracle" | "hive" | "impala" | "clickhouse" | "doris" | "sqlserver">;
152
157
  host: z<string, string>;
153
158
  port: z<number, number>;
154
159
  user: z<string, string>;
155
160
  database: z<string, string>;
156
161
  readonly: z<boolean, boolean>;
162
+ secure: z<boolean, boolean>;
157
163
  passwordRef: z<string, string>;
158
164
  password: z<never, never>;
159
165
  }>, string>>;
@@ -166,12 +172,11 @@ export declare function resolveDshHome(env?: Record<string, string | undefined>)
166
172
  /**
167
173
  * Install the packaged `preset/data-agent/` directory into
168
174
  * `$DSH_HOME/.agent-presets/<presetId>/`. Idempotent: an existing target is
169
- * normally left untouched. The exact package-owned 0.0.9 composition is
170
- * migrated once because its two dynamic package rows are incompatible with
171
- * DSH Desktop's unpacked-ASAR loader; user-edited compositions are never
172
- * overwritten. `installPreset: false` never calls this. Best-effort a
173
- * failure logs a warning with manual install instructions instead of failing
174
- * the boot.
175
+ * normally left untouched. Exact package-owned legacy compositions are
176
+ * migrated once when their runtime contract changes; user-edited compositions
177
+ * are never overwritten. `installPreset: false` never calls this. Best-effort
178
+ * a failure logs a warning with manual install instructions instead of
179
+ * failing the boot.
175
180
  */
176
181
  export declare function installPreset(ctx: Context, presetId: string): Promise<boolean>;
177
182
  /** Public for regression tests of the non-destructive preset migration gate. */
@@ -0,0 +1,3 @@
1
+ /** Surface-neutral control-sequence sanitization for generic tool cards. */
2
+ /** Remove control effects while keeping their presence visible to the user. */
3
+ export declare function sanitizePresentationText(value: unknown): string;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * The shared client-process runner used by both halves: the /connect
3
- * connectivity check (server half) and the database tools (tool half). All
4
- * execution goes through `ctx.subprocess` no shell layer, argv arrays only,
5
- * SQL on stdin, credentials in env entries — with a caller-owned timeout
6
- * (AbortController process-tree terminate escalation) and bounded captured
7
- * output.
2
+ * The shared database runner used by both halves: the /connect connectivity
3
+ * check (server half) and the database tools (tool half). CLI-backed adapters
4
+ * go through `ctx.subprocess` with argv arrays, SQL on stdin, and credentials
5
+ * in their dedicated environment/stdin channel. ClickHouse uses the official
6
+ * Node HTTP client with explicit transport/authentication fields. Both paths
7
+ * share caller-owned cancellation, deadlines, and bounded captured output.
8
8
  * @module @yejiming/dsh-data-agent/query
9
9
  */
10
10
  import type { Context } from '@deepseek-ai/cordis';
@@ -26,11 +26,11 @@ export interface QueryResult {
26
26
  /** True when either stream hit the maxResultChars cap. */
27
27
  truncated: boolean;
28
28
  }
29
- /** Which CLI flag set to use for one run. */
29
+ /** Which deterministic raw/introspection/structured output mode to use. */
30
30
  export type QueryTemplateMode = 'query' | 'introspect' | 'structured';
31
31
  /** Runner options: client overrides, deadlines, output caps. */
32
32
  export interface QueryOptions {
33
- /** Deployment client overrides keyed by database type. */
33
+ /** Deployment CLI overrides keyed by CLI-backed database type. */
34
34
  clients: Readonly<Partial<Record<DatabaseType, ClientConfig>>>;
35
35
  /** End-to-end deadline in milliseconds (timeout → terminate the tree). */
36
36
  timeoutMs: number;
@@ -41,10 +41,12 @@ export interface QueryOptions {
41
41
  /** CLI flag set; overrides the legacy `introspect` parameter when set. */
42
42
  mode?: QueryTemplateMode;
43
43
  }
44
+ /** ClickHouse endpoint construction never embeds username or password. */
45
+ export declare function clickHouseConnectionUrl(connection: DatabaseConnection): string;
44
46
  /**
45
- * Run one SQL text through the type's CLI client. The SQL is written to the
46
- * child's stdin (`{ data }` batch disposition) so it never appears in argv;
47
- * passwords travel in the env entries built by the template.
47
+ * Run one SQL text through the type's shared adapter. CLI SQL is written to
48
+ * child stdin (`{ data }` batch disposition), while ClickHouse SQL is an HTTP
49
+ * request body; neither path puts SQL or credentials in argv.
48
50
  *
49
51
  * Failure classification:
50
52
  * - the caller's external signal (e.g. the tool exec signal) aborts → the
@@ -6,7 +6,7 @@
6
6
  * docs/optimization-opportunities.md:
7
7
  *
8
8
  * - a single tool call carries at most ONE SQL statement;
9
- * - `maxRows` can be enforced with a real top-level LIMIT, not just a prompt.
9
+ * - `maxRows` can be enforced with a real dialect-level row bound, not just a prompt.
10
10
  *
11
11
  * @module @yejiming/dsh-data-agent/sql
12
12
  */
@@ -18,6 +18,14 @@
18
18
  export declare function assertSingleStatement(sql: string, label?: string): void;
19
19
  /** Whether `keyword` appears at top level as a whole word in `sql`. */
20
20
  export declare function hasTopLevelKeyword(sql: string, keyword: string): boolean;
21
+ /**
22
+ * Preserve executable SQL text while replacing strings, quoted identifiers,
23
+ * dollar/Oracle quoted bodies, and comments with spaces. Newlines are kept so
24
+ * line-oriented client directives can be checked without false positives.
25
+ */
26
+ export declare function maskSqlLiteralsAndComments(sql: string): string;
27
+ /** Reject commands interpreted by sqlcmd itself rather than by SQL Server. */
28
+ export declare function assertSqlServerSafeInput(sql: string, label?: string): void;
21
29
  /**
22
30
  * Strip trailing whitespace, statement terminators and trailing comments so a
23
31
  * limit clause can be appended to the actual statement text. Only comments