@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.
- package/README.en.md +70 -15
- package/README.md +70 -15
- package/conformance/dsh-ecosystem/baseline.json +59 -0
- package/conformance/dsh-ecosystem/dependencies.json +41 -0
- package/conformance/dsh-ecosystem/fixtures/host-degraded.fixture.json +12 -0
- package/conformance/dsh-ecosystem/fixtures/host-eligible.fixture.json +13 -0
- package/conformance/dsh-ecosystem/fixtures/host-rejected.fixture.json +12 -0
- package/conformance/dsh-ecosystem/fixtures/profiles/native-only/package.json +8 -0
- package/conformance/dsh-ecosystem/fixtures/profiles/native-plus-adapter/package.json +9 -0
- package/conformance/dsh-ecosystem/inventory.json +77 -0
- package/conformance/dsh-ecosystem/restrictions.json +20 -0
- package/dsh-plugin.json +67 -0
- package/lib/client.js +1352 -130
- package/lib/client.js.map +1 -1
- package/lib/{command-DuCpwVbl.js → command-utC5MHd9.js} +101 -60
- package/lib/command.js +1 -1
- package/lib/{connections-5sfdEDsG.js → connections-CHY4uB6z.js} +747 -65
- package/lib/defaults-Cngd8Tf8.js +131 -0
- package/lib/ecosystem.js +19 -0
- package/lib/index.js +40 -33
- package/lib/routes.js +5 -6
- package/lib/{tool-DVh61An-.js → tool-ZTOS4B33.js} +161 -177
- package/lib/tool.js +1 -1
- package/lib/types/analysis-html.d.ts +27 -0
- package/lib/types/analysis.d.ts +13 -1
- package/lib/types/client/DataAgentWorkbench.d.ts +1 -2
- package/lib/types/client/QueryResultTable.d.ts +13 -0
- package/lib/types/client/locales.d.ts +48 -0
- package/lib/types/client/persistence.d.ts +3 -1
- package/lib/types/client/query-export.d.ts +11 -0
- package/lib/types/client-discovery.d.ts +3 -4
- package/lib/types/clients.d.ts +14 -8
- package/lib/types/command.d.ts +2 -2
- package/lib/types/connections.d.ts +33 -4
- package/lib/types/database-types.d.ts +23 -0
- package/lib/types/defaults.d.ts +4 -0
- package/lib/types/ecosystem.d.ts +13 -0
- package/lib/types/index.d.ts +21 -16
- package/lib/types/presentation-text.d.ts +3 -0
- package/lib/types/query.d.ts +13 -11
- package/lib/types/sql.d.ts +9 -1
- package/lib/types/storage.d.ts +11 -1
- package/lib/types/structured-read.d.ts +2 -2
- package/lib/types/structured.d.ts +1 -1
- package/lib/types/tool.d.ts +5 -5
- package/lib/types/tui-connection-form.d.ts +10 -7
- package/package.json +66 -42
- package/preset/data-agent/agent.cordis.yml +9 -4
- 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
|
|
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:
|
|
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:
|
|
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.
|
package/lib/types/clients.d.ts
CHANGED
|
@@ -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
|
|
8
|
-
* (Oracle `connect`, Hive `!connect`) — never in argv, logs,
|
|
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,
|
|
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
|
-
}>,
|
|
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);
|
package/lib/types/command.d.ts
CHANGED
|
@@ -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?:
|
|
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
|
|
135
|
-
getFormDraft(sessionId: string):
|
|
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;
|
package/lib/types/defaults.d.ts
CHANGED
|
@@ -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;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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<
|
|
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,
|
|
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
|
-
}>,
|
|
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,
|
|
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
|
-
}>,
|
|
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.
|
|
170
|
-
* migrated once
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
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. */
|
package/lib/types/query.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The shared
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
|
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
|
|
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
|
|
46
|
-
* child
|
|
47
|
-
*
|
|
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
|
package/lib/types/sql.d.ts
CHANGED
|
@@ -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
|
|
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
|