@yejiming/dsh-data-agent 0.0.5 → 0.0.9
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 +127 -128
- package/README.md +123 -127
- package/lib/client.js +42071 -114
- package/lib/client.js.map +1 -1
- package/lib/command.js +875 -0
- package/lib/{defaults-Bac6QvNt.js → connections-DeauhaZi.js} +427 -19
- package/lib/defaults-DP4RyRh1.js +21 -0
- package/lib/index.js +185 -51
- package/lib/routes.js +94 -170
- package/lib/tool.js +751 -50
- package/lib/types/analysis.d.ts +1071 -0
- package/lib/types/client/AnalysisChart.d.ts +26 -0
- package/lib/types/client/AnalysisDashboard.d.ts +30 -0
- package/lib/types/client/analysis-charts.d.ts +40 -0
- package/lib/types/client/analysis-view-model.d.ts +44 -0
- package/lib/types/client/locales.d.ts +48 -0
- package/lib/types/client/persistence.d.ts +6 -1
- package/lib/types/clients.d.ts +10 -9
- package/lib/types/command.d.ts +41 -0
- package/lib/types/connections.d.ts +115 -40
- package/lib/types/index.d.ts +67 -47
- package/lib/types/routes.d.ts +25 -77
- package/lib/types/sql.d.ts +1 -1
- package/lib/types/storage.d.ts +70 -0
- package/lib/types/structured-read.d.ts +50 -0
- package/lib/types/tool.d.ts +25 -20
- package/lib/types/tui-connection-form.d.ts +98 -0
- package/package.json +61 -4
- package/preset/data-agent/agent.cordis.yml +34 -18
- package/preset/data-agent/preset.yml +2 -2
- package/lib/query-CmhTFklw.js +0 -86
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable chart container (task 3.3): owns one ECharts instance per mount,
|
|
3
|
+
* resizes it through a ResizeObserver, disposes it on unmount, and exposes an
|
|
4
|
+
* accessible image role + short text summary. Options arrive pre-built by
|
|
5
|
+
* chartOptionFor (token theme, non-HTML tooltips, reduced-motion included).
|
|
6
|
+
* @module @yejiming/dsh-data-agent/client/AnalysisChart
|
|
7
|
+
*/
|
|
8
|
+
import type { EChartsCoreOption } from 'echarts/core';
|
|
9
|
+
/** Chart container props. */
|
|
10
|
+
export interface AnalysisChartProps {
|
|
11
|
+
/** Safe pre-built option (pure mapping of the constrained report). */
|
|
12
|
+
option: EChartsCoreOption;
|
|
13
|
+
/** Accessible name of the chart image. */
|
|
14
|
+
ariaLabel: string;
|
|
15
|
+
/** Short plain-text summary announced to assistive tech. */
|
|
16
|
+
summary: string;
|
|
17
|
+
/** Chart canvas height in px (the container always spans full width). */
|
|
18
|
+
height?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One chart instance: init on mount, setOption on every option change (theme
|
|
22
|
+
* switches rebuild the option), resize on container changes, dispose on
|
|
23
|
+
* unmount. Null data points render as gaps because numericOrNull never
|
|
24
|
+
* converts null to zero.
|
|
25
|
+
*/
|
|
26
|
+
export declare function AnalysisChart({ option, ariaLabel, summary, height }: AnalysisChartProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* render-analysis tool result row + Dashboard Modal (tasks 3.4, 4.x).
|
|
3
|
+
*
|
|
4
|
+
* The row is registered for the keyed tool.call.toolview slot under
|
|
5
|
+
* key: render-analysis. It is a pure function of the frozen ToolCallBlock
|
|
6
|
+
* owner payload (decoded by analysis-view-model): running/error/interrupted
|
|
7
|
+
* statuses, a compact summary for complex reports, a bounded inline preview
|
|
8
|
+
* for the simple single-chart report, and a native "查看分析" button that
|
|
9
|
+
* opens THIS call's own Dashboard Modal (local state — one session may hold
|
|
10
|
+
* many independent reports).
|
|
11
|
+
*
|
|
12
|
+
* The Modal reuses the host primitives Modal (Escape/mask close) headless,
|
|
13
|
+
* keeps its own header fixed, scrolls the body independently, and returns
|
|
14
|
+
* focus to the trigger button on close. All interactive elements are native
|
|
15
|
+
* buttons; every chart carries an aria-label plus a plain-text summary; all
|
|
16
|
+
* cell/label/axis values render as text (React escaping + ECharts richText),
|
|
17
|
+
* so no report field can become executable DOM.
|
|
18
|
+
* @module @yejiming/dsh-data-agent/client/AnalysisDashboard
|
|
19
|
+
*/
|
|
20
|
+
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
21
|
+
import type { ToolCallViewProps } from '@deepseek-ai/dsh-client-ui-tool/client';
|
|
22
|
+
import { type AnalysisViewV1, type AnalysisViewWidth } from '../analysis.ts';
|
|
23
|
+
/** Full row props: the toolview runtime share + the data-agent locale seat. */
|
|
24
|
+
export type RenderAnalysisRowProps = ToolCallViewProps & PropsLocale<'data-agent'>;
|
|
25
|
+
/** Effective grid width per view id: tables and the first chart default full. */
|
|
26
|
+
export declare function computeViewWidths(views: readonly AnalysisViewV1[]): Map<string, AnalysisViewWidth>;
|
|
27
|
+
/** Format one metric value without ever inventing data. */
|
|
28
|
+
export declare function formatMetricValue(value: string | null, format: 'number' | 'percent' | undefined, empty: string): string;
|
|
29
|
+
/** The registered render-analysis tool result row. */
|
|
30
|
+
export declare function RenderAnalysisRow({ toolName, block, t }: RenderAnalysisRowProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe ECharts mapping for the analysis dashboard (tasks 3.2/3.3). Only the
|
|
3
|
+
* four first-version chart types and their required components are registered
|
|
4
|
+
* from echarts/core — line/bar/pie/scatter + grid/tooltip/legend/aria with
|
|
5
|
+
* the SVG renderer — so the client bundle stays tree-shaken per chart type.
|
|
6
|
+
*
|
|
7
|
+
* Every option is a PURE mapping of the constrained AnalysisReportV1 (the
|
|
8
|
+
* client never aggregates, sorts, or null→0 converts), tooltips use the
|
|
9
|
+
* non-HTML richText render mode, all labels/values stay text, and the series
|
|
10
|
+
* palette is finite, colorblind-safe, and stable by series NAME (the same
|
|
11
|
+
* series name gets the same color across every view of one report).
|
|
12
|
+
* @module @yejiming/dsh-data-agent/client/analysis-charts
|
|
13
|
+
*/
|
|
14
|
+
import type { EChartsCoreOption } from 'echarts/core';
|
|
15
|
+
import { type AnalysisDatasetResultV1, type AnalysisViewV1 } from '../analysis.ts';
|
|
16
|
+
/** Colorblind-safe, finite series palette (Tableau 10 order). */
|
|
17
|
+
export declare const ANALYSIS_PALETTE: readonly ["#4e79a7", "#f28e2b", "#59a14f", "#e15759", "#76b7b2", "#edc948", "#b07aa1", "#9c755f"];
|
|
18
|
+
/** Stable color per series NAME: same name → same color in every view. */
|
|
19
|
+
export declare function seriesColor(name: string): string;
|
|
20
|
+
/** DSH token values the charts need (fallback constants for non-DOM tests). */
|
|
21
|
+
export interface ChartThemeTokens {
|
|
22
|
+
fontFamily: string;
|
|
23
|
+
text: string;
|
|
24
|
+
textSecondary: string;
|
|
25
|
+
border: string;
|
|
26
|
+
background: string;
|
|
27
|
+
tooltipBorder: string;
|
|
28
|
+
grid: string;
|
|
29
|
+
}
|
|
30
|
+
/** Read the host's DSH tokens once per render (falls back off-DOM). */
|
|
31
|
+
export declare function readChartThemeTokens(): ChartThemeTokens;
|
|
32
|
+
/** Whether the environment asks for reduced motion. */
|
|
33
|
+
export declare function prefersReducedMotion(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Map one constrained view + dataset pair to a safe ECharts option. Returns an
|
|
36
|
+
* empty option for metric/table views (they never reach the chart component).
|
|
37
|
+
*/
|
|
38
|
+
export declare function chartOptionFor(view: AnalysisViewV1, dataset: AnalysisDatasetResultV1, tokens: ChartThemeTokens, ariaLabel: string): EChartsCoreOption;
|
|
39
|
+
/** Short plain-text summary of one chart (the accessible text description). */
|
|
40
|
+
export declare function chartTextSummary(view: AnalysisViewV1, dataset: AnalysisDatasetResultV1, kindLabel: string): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen-session decoder for render-analysis tool results (task 3.1). The
|
|
3
|
+
* component owns NO database state: everything derives from the frozen
|
|
4
|
+
* ToolCallBlock the slot owner supplies, so history replay is a pure function
|
|
5
|
+
* of the persisted meta and never touches the database, HTTP routes, or any
|
|
6
|
+
* storage domain.
|
|
7
|
+
*
|
|
8
|
+
* States:
|
|
9
|
+
* - running: tool/call seen, tool/result not yet;
|
|
10
|
+
* - error / interrupted: settled with an error outcome (interrupted carries
|
|
11
|
+
* the host's interrupted error code);
|
|
12
|
+
* - report: settled with a valid AnalysisReportV1 meta;
|
|
13
|
+
* - fallback: missing, malformed, string-encoded or unknown-version meta —
|
|
14
|
+
* degrade to the safe model content text, never guess or re-query.
|
|
15
|
+
* @module @yejiming/dsh-data-agent/client/analysis-view-model
|
|
16
|
+
*/
|
|
17
|
+
import type { ToolCallBlock } from '@deepseek-ai/dsh-client-runtime/client';
|
|
18
|
+
import { type AnalysisReportV1 } from '../analysis.ts';
|
|
19
|
+
/** The five display states of one render-analysis call. */
|
|
20
|
+
export type AnalysisBlockState = 'running' | 'error' | 'interrupted' | 'report' | 'fallback';
|
|
21
|
+
/** Decoded view model for one frozen block. */
|
|
22
|
+
export interface AnalysisViewModel {
|
|
23
|
+
state: AnalysisBlockState;
|
|
24
|
+
/** Valid version-1 report (state=report only). */
|
|
25
|
+
report?: AnalysisReportV1;
|
|
26
|
+
/** Safe error text (state=error/interrupted). */
|
|
27
|
+
errorText?: string;
|
|
28
|
+
/** Safe model content text (state=fallback). */
|
|
29
|
+
fallbackText?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Join the text blocks of a settled result into one safe plain string. */
|
|
32
|
+
export declare function contentText(content: readonly unknown[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* Decode one frozen ToolCallBlock into the display view model. The block is
|
|
35
|
+
* treated as immutable input; no lookups, no queries, no throws.
|
|
36
|
+
*/
|
|
37
|
+
export declare function decodeAnalysisBlock(block: ToolCallBlock): AnalysisViewModel;
|
|
38
|
+
/** Whether a report is the simple single-chart case deserving an inline preview. */
|
|
39
|
+
export declare function isSimpleChartReport(report: AnalysisReportV1): boolean;
|
|
40
|
+
/** Human-facing dataset/view counts for the summary line. */
|
|
41
|
+
export declare function reportCounts(report: AnalysisReportV1): {
|
|
42
|
+
datasets: number;
|
|
43
|
+
views: number;
|
|
44
|
+
};
|
|
@@ -17,6 +17,13 @@ export declare const zh: {
|
|
|
17
17
|
'form.port': string;
|
|
18
18
|
'form.user': string;
|
|
19
19
|
'form.password': string;
|
|
20
|
+
'form.credentialMode': string;
|
|
21
|
+
'form.credentialMode.password': string;
|
|
22
|
+
'form.credentialMode.reference': string;
|
|
23
|
+
'form.passwordRef': string;
|
|
24
|
+
'form.passwordRef.hint': string;
|
|
25
|
+
'credential.configured': string;
|
|
26
|
+
'credential.unconfigured': string;
|
|
20
27
|
'form.rememberPassword': string;
|
|
21
28
|
'form.rememberPassword.hint': string;
|
|
22
29
|
'form.readonly': string;
|
|
@@ -50,6 +57,23 @@ export declare const zh: {
|
|
|
50
57
|
'action.browse': string;
|
|
51
58
|
'action.close': string;
|
|
52
59
|
'error.title': string;
|
|
60
|
+
'analysis.running': string;
|
|
61
|
+
'analysis.failed': string;
|
|
62
|
+
'analysis.interrupted': string;
|
|
63
|
+
'analysis.fallback': string;
|
|
64
|
+
'analysis.view': string;
|
|
65
|
+
'analysis.close': string;
|
|
66
|
+
'analysis.summary': string;
|
|
67
|
+
'analysis.empty': string;
|
|
68
|
+
'analysis.kind.metric': string;
|
|
69
|
+
'analysis.kind.line': string;
|
|
70
|
+
'analysis.kind.bar': string;
|
|
71
|
+
'analysis.kind.pie': string;
|
|
72
|
+
'analysis.kind.scatter': string;
|
|
73
|
+
'analysis.kind.table': string;
|
|
74
|
+
'analysis.chart.summary': string;
|
|
75
|
+
'analysis.metric.null': string;
|
|
76
|
+
'analysis.row.title': string;
|
|
53
77
|
};
|
|
54
78
|
/** The data-agent namespace key union. */
|
|
55
79
|
export type DataAgentKey = keyof typeof zh;
|
|
@@ -69,6 +93,13 @@ export declare const en: {
|
|
|
69
93
|
'form.port': string;
|
|
70
94
|
'form.user': string;
|
|
71
95
|
'form.password': string;
|
|
96
|
+
'form.credentialMode': string;
|
|
97
|
+
'form.credentialMode.password': string;
|
|
98
|
+
'form.credentialMode.reference': string;
|
|
99
|
+
'form.passwordRef': string;
|
|
100
|
+
'form.passwordRef.hint': string;
|
|
101
|
+
'credential.configured': string;
|
|
102
|
+
'credential.unconfigured': string;
|
|
72
103
|
'form.rememberPassword': string;
|
|
73
104
|
'form.rememberPassword.hint': string;
|
|
74
105
|
'form.readonly': string;
|
|
@@ -102,4 +133,21 @@ export declare const en: {
|
|
|
102
133
|
'action.browse': string;
|
|
103
134
|
'action.close': string;
|
|
104
135
|
'error.title': string;
|
|
136
|
+
'analysis.running': string;
|
|
137
|
+
'analysis.failed': string;
|
|
138
|
+
'analysis.interrupted': string;
|
|
139
|
+
'analysis.fallback': string;
|
|
140
|
+
'analysis.view': string;
|
|
141
|
+
'analysis.close': string;
|
|
142
|
+
'analysis.summary': string;
|
|
143
|
+
'analysis.empty': string;
|
|
144
|
+
'analysis.kind.metric': string;
|
|
145
|
+
'analysis.kind.line': string;
|
|
146
|
+
'analysis.kind.bar': string;
|
|
147
|
+
'analysis.kind.pie': string;
|
|
148
|
+
'analysis.kind.scatter': string;
|
|
149
|
+
'analysis.kind.table': string;
|
|
150
|
+
'analysis.chart.summary': string;
|
|
151
|
+
'analysis.metric.null': string;
|
|
152
|
+
'analysis.row.title': string;
|
|
105
153
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Connection-config persistence for the database workbench. The most recent
|
|
3
3
|
* successful connection (type/host/port/user/database/password) is kept in
|
|
4
4
|
* localStorage under one key so remounts and restarts can restore the form
|
|
5
|
-
* and auto-reconnect (the server
|
|
5
|
+
* and auto-reconnect (the server persists only non-secret profiles/bindings).
|
|
6
6
|
*
|
|
7
7
|
* Security note: the password is persisted in PLAIN TEXT by explicit user
|
|
8
8
|
* decision (local single-user scenario) — see README 安全说明. The storage
|
|
@@ -21,8 +21,13 @@ export interface SavedConnection {
|
|
|
21
21
|
database: string;
|
|
22
22
|
/** Present only when the user explicitly opted in to persist the password. */
|
|
23
23
|
password?: string;
|
|
24
|
+
/** Non-secret credential reference; mutually exclusive with `password`. */
|
|
25
|
+
passwordRef?: string;
|
|
26
|
+
/** Explicit form mode; absent legacy records infer it from passwordRef. */
|
|
27
|
+
credentialMode?: 'password' | 'reference';
|
|
24
28
|
/** Opt-in flag; when true, {@link saveConnection} may write `password`. */
|
|
25
29
|
persistPassword?: boolean;
|
|
30
|
+
readonly?: boolean;
|
|
26
31
|
/** Diagnostic timestamp of the save. */
|
|
27
32
|
savedAt: string;
|
|
28
33
|
}
|
package/lib/types/clients.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* @module @yejiming/dsh-data-agent/clients
|
|
13
13
|
*/
|
|
14
14
|
import type { DatabaseConnection, DatabaseType } from './connections.ts';
|
|
15
|
+
import z from 'schemastery';
|
|
15
16
|
import { assertSingleStatement, hasTopLevelKeyword, stripTrailingTerminator } from './sql.ts';
|
|
16
17
|
export { assertSingleStatement, hasTopLevelKeyword, stripTrailingTerminator };
|
|
17
18
|
/**
|
|
@@ -49,20 +50,20 @@ export interface ClientConfig {
|
|
|
49
50
|
args?: readonly string[];
|
|
50
51
|
}
|
|
51
52
|
/** Loader schema for one client override (all fields optional at input). */
|
|
52
|
-
export declare const clientConfigSchema:
|
|
53
|
-
command:
|
|
54
|
-
args:
|
|
53
|
+
export declare const clientConfigSchema: z<Schemastery.ObjectS<{
|
|
54
|
+
command: z<string, string>;
|
|
55
|
+
args: z<string[], string[]>;
|
|
55
56
|
}>, Schemastery.ObjectT<{
|
|
56
|
-
command:
|
|
57
|
-
args:
|
|
57
|
+
command: z<string, string>;
|
|
58
|
+
args: z<string[], string[]>;
|
|
58
59
|
}>>;
|
|
59
60
|
/** Loader schema for the whole `clients` config object (any type key). */
|
|
60
|
-
export declare const clientsSchema:
|
|
61
|
+
export declare const clientsSchema: z<import("cosmokit").Dict<{
|
|
61
62
|
command?: string | null | undefined;
|
|
62
63
|
args?: string[] | null | undefined;
|
|
63
|
-
} & import("cosmokit").Dict, string>, import("
|
|
64
|
-
command:
|
|
65
|
-
args:
|
|
64
|
+
} & import("@deepseek-ai/cosmokit").Dict, string>, import("cosmokit").Dict<Schemastery.ObjectT<{
|
|
65
|
+
command: z<string, string>;
|
|
66
|
+
args: z<string[], string[]>;
|
|
66
67
|
}>, string>>;
|
|
67
68
|
/**
|
|
68
69
|
* A fully constructed client invocation: argv (command + flags, no SQL),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-scoped `/database` human command. The preset mounts this entry below
|
|
3
|
+
* the agent context, so the command registry scopes it to data-agent without
|
|
4
|
+
* importing dsh-tui, React, or Ink.
|
|
5
|
+
* @module @yejiming/dsh-data-agent/command
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands';
|
|
9
|
+
import { type ConnectionFormDraft, type ConnectionSummary, type DatabaseConnectionInput } from './connections.ts';
|
|
10
|
+
export declare const name = "data-agent-database-command";
|
|
11
|
+
export declare const inject: string[];
|
|
12
|
+
export declare const DATABASE_COMMAND_USAGE: string;
|
|
13
|
+
type DatabaseAction = {
|
|
14
|
+
kind: 'status';
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'connect';
|
|
17
|
+
input?: DatabaseConnectionInput;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'test';
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'disconnect';
|
|
22
|
+
};
|
|
23
|
+
export declare const DATA_AGENT_TOOL_NAMES: readonly ["str_replace_editor", "sql-query", "sql-write", "sql-cmd"];
|
|
24
|
+
export interface DatabaseCommandInteraction {
|
|
25
|
+
isTuiFormAvailable(): boolean;
|
|
26
|
+
collectTuiConnection(signal: AbortSignal, options: {
|
|
27
|
+
initialDraft?: ConnectionFormDraft;
|
|
28
|
+
persistDraft(draft: ConnectionFormDraft): Promise<void>;
|
|
29
|
+
}): Promise<DatabaseConnectionInput | undefined>;
|
|
30
|
+
}
|
|
31
|
+
/** Register the command in the calling preset/agent scope. */
|
|
32
|
+
export declare function apply(ctx: Context): void;
|
|
33
|
+
/** Public for focused command tests and alternate command adapters. */
|
|
34
|
+
export declare function executeDatabaseCommand(ctx: Context, invocation: CommandInvocation, interaction?: DatabaseCommandInteraction): Promise<CommandResult>;
|
|
35
|
+
/** Parse one command's raw input without ever accepting a plaintext password. */
|
|
36
|
+
export declare function parseDatabaseAction(rawInput: string): DatabaseAction;
|
|
37
|
+
/** Non-interactive `connect` argument grammar. */
|
|
38
|
+
export declare function parseConnectArguments(tokens: readonly string[]): DatabaseConnectionInput;
|
|
39
|
+
/** Render a public summary; no password-bearing field exists in the type. */
|
|
40
|
+
export declare function formatConnectionStatus(summary: ConnectionSummary | undefined): string;
|
|
41
|
+
export {};
|
|
@@ -1,74 +1,149 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* consumed by the sqlcmd tool half (`src/tool.ts`) inside the data-agent
|
|
5
|
-
* preset.
|
|
2
|
+
* Surface-independent database connection service shared by Web routes,
|
|
3
|
+
* agent tools, and human commands.
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - `get()` returns a password-stripped COPY, so UI/status consumers never
|
|
11
|
-
* see the secret;
|
|
12
|
-
* - `getWithSecret()` is the process-internal read used ONLY by the sqlcmd
|
|
13
|
-
* tool half (same package), which forwards the password to the database
|
|
14
|
-
* client through an environment variable.
|
|
15
|
-
*
|
|
16
|
-
* Wildcard: a connection stored under the key `'*'` acts as the fallback for
|
|
17
|
-
* every session without its own entry (a deployment seeding a default
|
|
18
|
-
* database, or a headless/keyless run). Config-seeded entries cannot carry
|
|
19
|
-
* passwords, so the wildcard is always password-free.
|
|
5
|
+
* Runtime records may contain one temporary Web password. Durable records
|
|
6
|
+
* never do: they contain a non-secret profile plus an optional credential
|
|
7
|
+
* reference that is resolved again at the start of every database operation.
|
|
20
8
|
* @module @yejiming/dsh-data-agent/connections
|
|
21
9
|
*/
|
|
22
|
-
|
|
10
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
11
|
+
import { type ClientConfig, type ColumnInfo } from './clients.ts';
|
|
12
|
+
import { type QueryResult } from './query.ts';
|
|
13
|
+
/** Key of the wildcard connection applied to sessions without an exact entry. */
|
|
23
14
|
export declare const WILDCARD_SESSION = "*";
|
|
24
15
|
/** Supported database client kinds. */
|
|
25
16
|
export type DatabaseType = 'mysql' | 'postgres' | 'sqlite' | 'oracle' | 'hive' | 'impala';
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*/
|
|
32
|
-
export interface
|
|
17
|
+
/** Safe credential facts returned to UI/command surfaces. */
|
|
18
|
+
export interface CredentialSummary {
|
|
19
|
+
configured: boolean;
|
|
20
|
+
source?: string;
|
|
21
|
+
}
|
|
22
|
+
/** One connect request accepted by every surface. */
|
|
23
|
+
export interface DatabaseConnectionInput {
|
|
33
24
|
type: DatabaseType;
|
|
34
25
|
host?: string;
|
|
35
26
|
port?: number;
|
|
36
27
|
user?: string;
|
|
37
28
|
database: string;
|
|
38
|
-
/**
|
|
29
|
+
/** Temporary Web-only secret, retained in this process only. */
|
|
39
30
|
password?: string;
|
|
40
|
-
/**
|
|
31
|
+
/** Non-secret DSH credential reference, mutually exclusive with password. */
|
|
32
|
+
passwordRef?: string;
|
|
41
33
|
readonly?: boolean;
|
|
34
|
+
/** Optional stable durable profile id. */
|
|
35
|
+
profileId?: string;
|
|
36
|
+
/** Optional human-readable profile label. */
|
|
37
|
+
name?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Runtime connection. `tables` and temporary `password` are never durable. */
|
|
40
|
+
export interface DatabaseConnection extends DatabaseConnectionInput {
|
|
42
41
|
tables?: string[];
|
|
43
42
|
}
|
|
44
|
-
/** Password-free
|
|
43
|
+
/** Password-free public connection view. */
|
|
45
44
|
export interface ConnectionSummary {
|
|
46
45
|
type: DatabaseType;
|
|
47
46
|
host?: string;
|
|
48
47
|
port?: number;
|
|
49
48
|
user?: string;
|
|
50
49
|
database: string;
|
|
51
|
-
|
|
50
|
+
passwordRef?: string;
|
|
52
51
|
readonly?: boolean;
|
|
52
|
+
profileId?: string;
|
|
53
|
+
name?: string;
|
|
53
54
|
tables?: string[];
|
|
55
|
+
credential?: CredentialSummary;
|
|
56
|
+
}
|
|
57
|
+
/** Value stored in the `profiles` domain table. Never add secrets here. */
|
|
58
|
+
export interface PersistedConnectionProfile {
|
|
59
|
+
name?: string;
|
|
60
|
+
type: DatabaseType;
|
|
61
|
+
host?: string;
|
|
62
|
+
port?: number;
|
|
63
|
+
user?: string;
|
|
64
|
+
database: string;
|
|
65
|
+
readonly?: boolean;
|
|
66
|
+
passwordRef?: string;
|
|
67
|
+
updatedAt: string;
|
|
68
|
+
}
|
|
69
|
+
/** Value stored in the `bindings` domain table. */
|
|
70
|
+
export interface SessionConnectionBinding {
|
|
71
|
+
profileId: string;
|
|
72
|
+
updatedAt: string;
|
|
73
|
+
}
|
|
74
|
+
/** Non-secret values restored when a session reopens an interactive form. */
|
|
75
|
+
export interface ConnectionFormDraft {
|
|
76
|
+
type: DatabaseType;
|
|
77
|
+
host: string;
|
|
78
|
+
port: string;
|
|
79
|
+
user: string;
|
|
80
|
+
database: string;
|
|
81
|
+
readonly: boolean;
|
|
82
|
+
}
|
|
83
|
+
/** Durable draft record. Passwords and credential references are forbidden. */
|
|
84
|
+
export interface PersistedConnectionFormDraft extends ConnectionFormDraft {
|
|
85
|
+
updatedAt: string;
|
|
86
|
+
}
|
|
87
|
+
/** Minimal durable seam; backed by a DSH storage domain in production. */
|
|
88
|
+
export interface ConnectionPersistence {
|
|
89
|
+
getProfile(profileId: string): PersistedConnectionProfile | undefined;
|
|
90
|
+
putProfile(profileId: string, profile: PersistedConnectionProfile): Promise<void>;
|
|
91
|
+
deleteProfile(profileId: string): Promise<boolean>;
|
|
92
|
+
getBinding(sessionId: string): SessionConnectionBinding | undefined;
|
|
93
|
+
putBinding(sessionId: string, binding: SessionConnectionBinding): Promise<void>;
|
|
94
|
+
deleteBinding(sessionId: string): Promise<boolean>;
|
|
95
|
+
getDraft?(sessionId: string): PersistedConnectionFormDraft | undefined;
|
|
96
|
+
putDraft?(sessionId: string, draft: PersistedConnectionFormDraft): Promise<void>;
|
|
97
|
+
}
|
|
98
|
+
/** Shared service configuration supplied by the host plugin. */
|
|
99
|
+
export interface ConnectionServiceOptions {
|
|
100
|
+
connectTimeoutMs: number;
|
|
101
|
+
queryTimeoutMs: number;
|
|
102
|
+
maxResultChars: number;
|
|
103
|
+
maxQueryChars?: number;
|
|
104
|
+
introspectMaxTables: number;
|
|
105
|
+
readonly: boolean;
|
|
106
|
+
clients: Partial<Record<string, ClientConfig>>;
|
|
107
|
+
cwd?: string;
|
|
108
|
+
}
|
|
109
|
+
export interface ConnectResult {
|
|
110
|
+
tables: string[];
|
|
111
|
+
summary: ConnectionSummary;
|
|
54
112
|
}
|
|
55
|
-
/**
|
|
113
|
+
/** Host-plane service (`ctx.dataAgentConnections`). */
|
|
56
114
|
export interface DataAgentConnections {
|
|
57
|
-
/**
|
|
115
|
+
/** Compatibility setter for config seeds/tests; does not persist. */
|
|
58
116
|
set(sessionId: string, connection: DatabaseConnection): void;
|
|
59
|
-
/**
|
|
117
|
+
/** Password-free synchronous status (runtime/binding/wildcard resolution). */
|
|
60
118
|
get(sessionId: string): ConnectionSummary | undefined;
|
|
61
|
-
/**
|
|
62
|
-
* Read one session's connection INCLUDING the password. Process-internal
|
|
63
|
-
* only (the sqlcmd tool half); never hand this to a wire/UI consumer.
|
|
64
|
-
*/
|
|
119
|
+
/** Compatibility internal read; credential references remain unresolved. */
|
|
65
120
|
getWithSecret(sessionId: string): DatabaseConnection | undefined;
|
|
66
|
-
/** Whether a session currently has a connection. */
|
|
67
121
|
has(sessionId: string): boolean;
|
|
68
|
-
/**
|
|
122
|
+
/** Compatibility runtime-only clear. Use disconnect() for durable bindings. */
|
|
69
123
|
clear(sessionId: string): void;
|
|
124
|
+
/** Restore the latest non-secret interactive form values for this session. */
|
|
125
|
+
getFormDraft(sessionId: string): ConnectionFormDraft | undefined;
|
|
126
|
+
/** Save non-secret form values; the implementation never accepts a password. */
|
|
127
|
+
saveFormDraft(sessionId: string, draft: ConnectionFormDraft): Promise<void>;
|
|
128
|
+
status(sessionId: string): Promise<ConnectionSummary | undefined>;
|
|
129
|
+
connect(sessionId: string, input: DatabaseConnectionInput, signal: AbortSignal): Promise<ConnectResult>;
|
|
130
|
+
disconnect(sessionId: string): Promise<void>;
|
|
131
|
+
test(sessionId: string, signal: AbortSignal): Promise<ConnectResult>;
|
|
132
|
+
resolveForExecution(sessionId: string): Promise<DatabaseConnection>;
|
|
133
|
+
listSchemas(sessionId: string, signal: AbortSignal): Promise<string[]>;
|
|
134
|
+
listTables(sessionId: string, schema: string | undefined, signal: AbortSignal): Promise<string[]>;
|
|
135
|
+
describe(sessionId: string, schema: string | undefined, table: string, signal: AbortSignal): Promise<ColumnInfo[]>;
|
|
136
|
+
query(sessionId: string, sql: string, signal: AbortSignal): Promise<QueryResult>;
|
|
70
137
|
}
|
|
71
|
-
/** Build
|
|
138
|
+
/** Build a password-stripped copy of one connection. */
|
|
72
139
|
export declare function summarize(connection: DatabaseConnection): ConnectionSummary;
|
|
73
|
-
/**
|
|
140
|
+
/** Replace every occurrence of a resolved secret before crossing a public seam. */
|
|
141
|
+
export declare function redactSecretText(text: string, secrets: readonly (string | undefined)[]): string;
|
|
142
|
+
/** Redact a client result without mutating the runner-owned object. */
|
|
143
|
+
export declare function redactQueryResult(result: QueryResult, connection: DatabaseConnection): QueryResult;
|
|
144
|
+
/** Validate/normalize a shared connect input before any I/O. */
|
|
145
|
+
export declare function normalizeConnectionInput(input: DatabaseConnectionInput, cwd?: string): DatabaseConnection;
|
|
146
|
+
/** Create the surface-independent service. */
|
|
147
|
+
export declare function createConnectionService(ctx?: Context, options?: ConnectionServiceOptions, persistence?: ConnectionPersistence): DataAgentConnections;
|
|
148
|
+
/** Backward-compatible in-memory store factory used by embedders/tests. */
|
|
74
149
|
export declare function createConnectionStore(): DataAgentConnections;
|