Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
134 commits
Select commit Hold shift + click to select a range
59e0fc2
feat(agent): add v2 domain contracts
openai0229 Sep 8, 2026
22349c6
feat(agent): add v2 local storage
openai0229 Sep 8, 2026
9c718a9
feat(agent): define runtime lifecycle contracts
openai0229 Sep 8, 2026
e1e5e77
feat(agent): add v2 session service
openai0229 Sep 8, 2026
34d58ad
refactor(agent): freeze definition in v2 sessions
openai0229 Sep 8, 2026
b6fcdfc
feat(agent): manage active runtime handles
openai0229 Sep 8, 2026
ad186c9
feat(agent): orchestrate v2 runs
openai0229 Sep 8, 2026
3730263
feat(agent): expose v2 ai endpoints
openai0229 Sep 8, 2026
8a55ab9
feat(agent): verify bundled pi runtime
openai0229 Sep 8, 2026
fbd5ace
feat(agent): supervise pi runtime processes
openai0229 Sep 8, 2026
d6c2a4f
feat(agent): install pi runtime on demand
openai0229 Sep 9, 2026
11622d2
feat(agent): add strict pi jsonl rpc client
openai0229 Sep 9, 2026
0a8a872
feat(agent): adapt pi runtime lifecycle
openai0229 Sep 9, 2026
3770872
feat(agent): gate pi behind beta enablement
openai0229 Sep 9, 2026
17eda85
feat(agent): gate bash as a beta feature
openai0229 Sep 9, 2026
a1b2131
feat(ai): merge v1 and v2 session summaries
openai0229 Sep 9, 2026
9970abe
feat(agent): persist v2 user transcript events
openai0229 Sep 9, 2026
f17af0b
feat(agent): manage v2 session lifecycle
openai0229 Sep 9, 2026
0aea3f5
feat(ai): route frontend sessions by version
openai0229 Sep 9, 2026
d2103df
feat(agent): add pi and bash beta settings
openai0229 Sep 9, 2026
9ee1a22
feat(agent): add v2 agent chat experience
openai0229 Sep 9, 2026
c1ffc39
fix(agent): verify pi runtime before launch
openai0229 Sep 9, 2026
e60e87b
fix(agent): pin pi runtime manifests
openai0229 Sep 9, 2026
0e67478
fix(agent): select spring injection constructors
openai0229 Sep 9, 2026
331d17a
fix(agent): expose runtime availability errors
openai0229 Sep 9, 2026
39c7422
feat(agent): enable local community web runtime
openai0229 Sep 9, 2026
772ecd0
fix(agent): align pi rpc protocol
openai0229 Sep 9, 2026
384b67c
feat(agent): install official pi release archives
openai0229 Sep 9, 2026
4167be0
feat(agent): proxy pi model access
openai0229 Sep 9, 2026
129cf58
fix(agent): preserve v2 session model binding
openai0229 Sep 9, 2026
cb6319d
fix(agent): drain pi process diagnostics
openai0229 Sep 9, 2026
7385b55
fix(agent): keep pi entry visible before enablement
openai0229 Sep 9, 2026
360d720
fix(agent): preserve raw pi release archives
openai0229 Sep 9, 2026
1d178e0
fix(agent): decompress pi archives in bounded stages
openai0229 Sep 9, 2026
e12a663
fix(agent): show explicit agent entry
openai0229 Sep 9, 2026
e92c808
feat(agent): add runtime selector to ai panel
openai0229 Sep 9, 2026
39a0271
feat(agent): run pi installation through task center
openai0229 Sep 9, 2026
dd04648
fix(agent): register pi install task operation
openai0229 Sep 9, 2026
f366ec5
fix(agent): complete pi task and session flow
openai0229 Sep 9, 2026
3b56c6c
fix(agent): keep pi selection in ai panel
openai0229 Sep 9, 2026
321efd7
fix(agent): resolve prompts and model snapshots on the server
openai0229 Sep 9, 2026
57ade14
feat(agent): connect Pi tools and trace runtime lifecycle
openai0229 Sep 9, 2026
3d86720
fix(agent): reuse the chat panel for v2 session lifecycle
openai0229 Sep 9, 2026
3c09176
Merge branch 'main' of github.com:OtterMind/Chat2DB into feat/agent-v…
openai0229 Sep 9, 2026
61ae98f
Merge branch 'main' of github.com:OtterMind/Chat2DB into feat/agent-v…
openai0229 Sep 9, 2026
86cc89c
feat(agent): configure Bash working directory and show Pi tools
openai0229 Sep 9, 2026
577d9a9
feat(agent): enable native Pi tools with a shared workspace picker
openai0229 Sep 9, 2026
04ea6db
fix(agent): persist tool opt-in and open the system folder picker
openai0229 Sep 9, 2026
d53f31a
fix(agent): use a simple prompt for Pi sessions
openai0229 Sep 9, 2026
b728a25
fix(agent): show command approvals inside conversation replies
openai0229 Sep 9, 2026
a0380a5
feat(agent): add independent structured database operations
openai0229 Sep 9, 2026
347c1fd
feat(agent): register guided v2 database tools with Pi
openai0229 Sep 9, 2026
086b6d5
feat(agent): isolate V2 JDBC metadata readers and caches
openai0229 Sep 10, 2026
a4728dc
feat(agent): add filtered database discovery and column search
openai0229 Sep 10, 2026
ad5a356
refactor(agent): name filtered discovery tools as search
openai0229 Sep 10, 2026
d21c2cf
feat(agent): describe database objects in explicit scope
openai0229 Sep 10, 2026
dacb901
Merge branch 'main' of github.com:OtterMind/Chat2DB into feat/agent-v…
openai0229 Sep 10, 2026
98ceeec
feat(agent): add user questions and evidence-based scope discovery
openai0229 Sep 10, 2026
5df2e04
feat(agent): answer user questions inside the conversation
openai0229 Sep 10, 2026
772298b
Merge remote-tracking branch 'origin/main' into feat/agent-v2-contracts
openai0229 Sep 10, 2026
fd48aa6
refactor(agent): organize contracts by module responsibility
openai0229 Sep 10, 2026
367e148
refactor(agent): separate runtime implementation from JCEF
openai0229 Sep 10, 2026
a779f17
Merge latest origin/main into feat/agent-v2-contracts
openai0229 Sep 10, 2026
c939041
feat(agent): add SQL batch approval and random gateway ports
openai0229 Sep 10, 2026
a9ec4ae
feat(agent): support native Pi model protocols
openai0229 Sep 10, 2026
fe11657
feat(agent): allow model switching within conversations
openai0229 Sep 10, 2026
5eb1445
feat(agent): render charts from saved query results
openai0229 Sep 10, 2026
72207f6
feat(agent): add prompt context and ordered Pi session views
openai0229 Sep 11, 2026
e9d8db6
feat(agent): load built-in chart skills through Pi
openai0229 Sep 11, 2026
bade7e3
style(skills): normalize shared reference ending
openai0229 Sep 11, 2026
8759aa8
feat(agent): autocomplete skill commands in Pi conversations
openai0229 Sep 11, 2026
ad91c84
feat(agent): style skill messages and show live activity
openai0229 Sep 11, 2026
8f73684
feat(agent): show model tool call descriptions
openai0229 Sep 12, 2026
0f94908
fix(agent): avoid recovering runs during startup race
openai0229 Sep 12, 2026
ed783a9
fix(agent): clear stale runtime errors after completion
openai0229 Sep 12, 2026
88b7f58
fix(agent): show tool descriptions in trace headers
openai0229 Sep 12, 2026
4e108db
feat(agent): summarize tool execution timing
openai0229 Sep 12, 2026
a8d8064
feat(agent): add Pi slash command completion
openai0229 Sep 12, 2026
4460d75
fix(agent): execute chat commands and restore tool activity
openai0229 Sep 12, 2026
cdecc7d
fix(agent): make commands immediate and unify run progress
openai0229 Sep 12, 2026
bdb6f2f
fix(agent): preserve tool chronology and align execution columns
openai0229 Sep 12, 2026
0364617
fix(agent): keep suspended runs resumable
openai0229 Sep 13, 2026
5671708
fix(agent): harden runtime lifecycle and renew tool access
openai0229 Sep 13, 2026
589e1d2
feat(agent): persist large v2 tool outputs with scoped file access
openai0229 Sep 13, 2026
309425a
fix(agent): show thinking and tool progress as pulsing text
openai0229 Sep 13, 2026
3507596
feat(agent): improve v2 recovery, charts and object discovery
openai0229 Sep 15, 2026
da78b83
fix(agent): preserve output file references in v2 tool results
openai0229 Sep 15, 2026
849d05c
fix(agent): define v2 task completion and evidence checks
openai0229 Sep 15, 2026
af2cd47
merge: sync latest main into agent v2 branch
openai0229 Sep 15, 2026
02d601d
fix(agent): keep community workflows and exclude local fixtures
openai0229 Sep 15, 2026
8a69a40
fix(agent): support abort signals in desktop requests
openai0229 Sep 16, 2026
59785c6
fix(agent): complete desktop request routing and invocation
openai0229 Sep 16, 2026
9976dc2
fix(agent): load bundled resources with their owning class loader
openai0229 Sep 16, 2026
4c041c0
fix(agent): render horizontal bars with correct category and metric axes
openai0229 Sep 16, 2026
237e3ae
refactor(agent): unify Pi web and desktop adapters
openai0229 Sep 16, 2026
cd379db
merge: align Pi V2 branch with current desktop packaging
openai0229 Sep 16, 2026
1024e46
fix(agent): remove Pi session files and launch packaged runtime
openai0229 Sep 16, 2026
1b4275f
feat(agent): support shared user skills in Pi V2
openai0229 Sep 16, 2026
8a87067
test(agent): align skill fixtures and translation metadata
openai0229 Sep 16, 2026
02a770e
fix(agent): require explicit shell enablement for skill installs
openai0229 Sep 17, 2026
533810d
merge: integrate main into the Pi V2 branch
openai0229 Sep 17, 2026
7c4f300
fix(i18n): align JCEF language bundles with the new agent keys
openai0229 Sep 17, 2026
bbe3628
refactor(agent): install skills in place without content snapshots
openai0229 Sep 17, 2026
3c8aafd
fix(agent): keep a loaded user skill editable
openai0229 Sep 17, 2026
ef22def
fix(agent): keep skill directories from breaking unrelated file tools
openai0229 Sep 18, 2026
91cf50a
fix(agent): bound client recovery, refuse Pi attachments and gate age…
openai0229 Sep 18, 2026
d87f91a
fix(agent): serialise session deletion and stop retiring live runtimes
openai0229 Sep 18, 2026
aa636de
fix(agent): keep state-changing agent operations local
openai0229 Sep 18, 2026
42c4950
fix(agent): bound runtime installs and fail stalled RPC requests
openai0229 Sep 18, 2026
bc6d3f2
fix(ai): stop exposing the agent model protocol in the model dialog
openai0229 Sep 18, 2026
9bfbf8a
fix(ai): describe the Pi tool switches accurately
openai0229 Sep 18, 2026
b006a53
perf(agent): merge streamed deltas into few durable events
openai0229 Sep 18, 2026
13f08a0
fix(agent): open long conversations on their newest events
openai0229 Sep 18, 2026
e049b56
fix(agent): load earlier turns on scroll and align the first window
openai0229 Sep 18, 2026
83fad3e
fix(agent): prepend earlier turns without reloading the conversation
openai0229 Sep 18, 2026
560d16d
fix(agent): let file tools browse the loaded packaged skills
openai0229 Sep 18, 2026
6681756
fix(agent): keep a streaming conversation scrollable
openai0229 Sep 18, 2026
cd6c253
fix(agent): prepend earlier turns without touching the live view
openai0229 Sep 18, 2026
f010c39
fix(agent): show the load-earlier control in the Pi session view
openai0229 Sep 18, 2026
23d6079
fix(agent): load earlier turns for an idle session
openai0229 Sep 18, 2026
799a251
fix(agent): load earlier turns without a manual control
openai0229 Sep 18, 2026
dfbc0b8
fix(agent): page history by sequence instead of replaying it
openai0229 Sep 18, 2026
3713697
fix(agent): page forward by sequence instead of scanning the session
openai0229 Sep 18, 2026
a21b5cd
refactor(agent): drop compatibility with our own unreleased formats
openai0229 Sep 18, 2026
4a67771
feat(agent): manage external MCP servers from the conversation
openai0229 Sep 18, 2026
c0f4121
test(agent): drive a real MCP server and negotiate a current revision
openai0229 Sep 18, 2026
fc4fe53
fix(agent): route external MCP calls and keep the runtime alive
openai0229 Sep 18, 2026
474405d
fix(agent): show the real tool on an approval card and hide answers t…
openai0229 Sep 18, 2026
53c5ef9
fix(agent): make a new MCP server usable in the session that added it
openai0229 Sep 18, 2026
0043d8d
test(agent): verify the HTTP transport and large MCP results
openai0229 Sep 18, 2026
30eab45
merge: sync latest main into the agent v2 branch
openai0229 Sep 19, 2026
a967f36
test(agent): follow the approval decision enum and the mcp-manager skill
openai0229 Sep 19, 2026
bb2a630
refactor(ai): keep only Pi's tool labels in the agent tool panel
openai0229 Sep 22, 2026
83b78cb
merge: sync latest main into the agent v2 branch
openai0229 Sep 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ jobs:
- name: Run SQL clipboard test
run: yarn run test:sql-in-clipboard

- name: Run agent chat tests
run: yarn run test:agent-chat

- name: Run result Markdown formatter test
run: yarn run test:result-markdown

Expand Down
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ Instruction authority and factual evidence are separate:
JCEF, SPI, plugin, tools, and startup modules.
- `chat2db-community-server/chat2db-community-start/`: executable backend,
configuration, assembled frontend resources, and final jar.
- `chat2db-community-server/chat2db-community-agent/`: agent runtime adapters,
installation, process/RPC transport, and runtime resources. It depends only
on tools and third-party libraries; start assembles it with business services.
- `chat2db-community-server/chat2db-community-plugins/`: database-specific
implementations. Keep dialect-specific behavior inside the owning plugin.
- `docker/`: Community image, Compose file, and local image build entry point.
Expand Down
8 changes: 6 additions & 2 deletions chat2db-community-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"build": "yarn run build:web:community",
"build:prod": "yarn run build:web:community",
"build:web": "umi build",
"prebuild:web:community": "yarn test:ipc-log-redaction && yarn test:community-boundary && yarn test:database-capabilities && yarn test:table-editor && yarn test:retired-ai && yarn test:tree-title-highlight && yarn test:tree-search-lifecycle && yarn test:driver-upload && yarn test:tree-loading && yarn test:tree-node-lookup && yarn test:tree-node-path && yarn test:data-source-authorization && yarn test:active-transactions && yarn test:data-source-mutation-refresh && yarn test:ai-model-config && yarn test:ai-model-select && yarn test:export-connections && yarn test:main-page-navigation && yarn test:shortcut && yarn test:console-tab-name && yarn test:workspace-tab-scroll && yarn test:workspace-split-lifecycle && yarn test:sql-completion-context && yarn test:file-manager-label && yarn test:local-file-encoding && yarn test:local-file-save && yarn test:local-file-tree-path && yarn test:saved-console-dirty && yarn test:editor-close && yarn test:result-set-ui && yarn test:result-pagination && yarn test:sql-execution-stream && yarn test:result-table-layout && yarn test:result-status && yarn test:data-source-identity && yarn test:data-source-execution-snapshot && yarn test:data-source-watermark && yarn test:hot-update && yarn test:update-check-schedule && yarn test:task-center && yarn test:import-preview && yarn test:application-exit && yarn test:monaco-lifecycle && yarn test:result-set-editor && yarn test:account-grants-request && yarn test:connection-close-request && yarn test:ssh-connection && yarn test:operation-log-filters && yarn test:dashboard-store",
"prebuild:web:community": "yarn test:ipc-log-redaction && yarn test:community-boundary && yarn test:database-capabilities && yarn test:table-editor && yarn test:retired-ai && yarn test:tree-title-highlight && yarn test:tree-search-lifecycle && yarn test:driver-upload && yarn test:tree-loading && yarn test:tree-node-lookup && yarn test:tree-node-path && yarn test:data-source-authorization && yarn test:active-transactions && yarn test:data-source-mutation-refresh && yarn test:ai-model-config && yarn test:ai-model-select && yarn test:export-connections && yarn test:main-page-navigation && yarn test:shortcut && yarn test:console-tab-name && yarn test:workspace-tab-scroll && yarn test:workspace-split-lifecycle && yarn test:sql-completion-context && yarn test:file-manager-label && yarn test:local-file-encoding && yarn test:local-file-save && yarn test:local-file-tree-path && yarn test:saved-console-dirty && yarn test:editor-close && yarn test:result-set-ui && yarn test:result-pagination && yarn test:sql-execution-stream && yarn test:result-table-layout && yarn test:result-status && yarn test:data-source-identity && yarn test:data-source-execution-snapshot && yarn test:data-source-watermark && yarn test:hot-update && yarn test:update-check-schedule && yarn test:task-center && yarn test:import-preview && yarn test:application-exit && yarn test:monaco-lifecycle && yarn test:result-set-editor && yarn test:account-grants-request && yarn test:connection-close-request && yarn test:ssh-connection && yarn test:operation-log-filters && yarn test:dashboard-store && yarn test:agent-chat",
"postbuild:web:community": "node ./scripts/verify-production-bundles.cjs",
"build:web:2java": "yarn run build:web:community && rm -rf ../chat2db-community-server/chat2db-community-start/src/main/resources/thymeleaf/* && cp -r dist/index.html ../chat2db-community-server/chat2db-community-start/src/main/resources/thymeleaf/",
"build:web:community": "cross-env UMI_ENV=community cross-env APP_NAME=chat2db-community cross-env APP_VERSION=${npm_config_app_version} cross-env PRINT_LOGS=${npm_config_print_logs} cross-env APP_PORT=${npm_config_app_port} umi build",
Expand All @@ -35,6 +35,9 @@
"test:tree-node-path": "tsx src/blocks/NewTree/utils/treeNodePath.test.ts",
"test:ai-model-config": "tsx src/blocks/AI/components/AIModelConfigModal/modelConfigDefaults.test.ts",
"test:ai-model-select": "tsx src/blocks/AI/components/AIModelSelect/modelSelectOptions.test.ts",
"test:desktop-request": "tsx src/service/commandLine/commandLineRequest.test.ts",
"test:agent-chat": "cross-env NODE_ENV=test yarn run test:agent-chat:suite",
"test:agent-chat:suite": "yarn test:desktop-request && yarn test:pi-adapters && tsx src/blocks/AI/agentOutput.test.ts && tsx src/blocks/AI/components/AgentV2Session/useOutputPage.test.tsx && tsx src/blocks/AI/components/AIAtMetion/useActive.test.tsx && tsx src/blocks/AI/components/AgentV2Session/presentation.test.ts && tsx src/blocks/AI/components/AIChatInput/inputSuggestions.test.ts && tsx src/blocks/AI/agentContext.test.ts && tsx src/blocks/AI/components/AIChatInput/mentionSelection.test.ts && tsx src/blocks/AI/agentCharts.test.ts && tsx src/blocks/AI/components/AgentChartCard/option.test.ts && tsx src/blocks/AI/agentEvents.test.ts && tsx src/blocks/AI/agentQuestions.test.ts && tsx src/blocks/AI/agentEventStream.test.ts && tsx src/blocks/AI/chatSessionRoute.test.ts && tsx src/blocks/AI/components/PiToolSettings/model.test.ts && tsx src/utils/confirmBetaFeature.test.ts",
"test:active-tab-locator": "tsx src/pages/main/workspace/utils/activeTabLocator.test.ts",
"test:application-exit": "tsx src/layouts/init/applicationExitCoordinator.test.ts",
"test:base-table-interaction": "tsx src/components/BaseTable/treeInteraction.test.ts",
Expand Down Expand Up @@ -109,7 +112,8 @@
"start": "yarn run start:community:hot",
"start:community:hot": "cross-env UMI_ENV=community cross-env APP_NAME=chat2db-community cross-env DISABLE_MFSU=true cross-env UMI_DEV_SERVER_COMPRESS=none cross-env HOST=127.0.0.1 cross-env PORT=8889 node --require ./scripts/bind-dev-server-loopback.cjs ./node_modules/umi/bin/umi.js dev --public_path=/",
"ui": "yarn add @chat2db/ui",
"test:create-stream-index": "tsx src/blocks/RedisAllData/CreateStream/mapDisplayedIndex.test.ts"
"test:create-stream-index": "tsx src/blocks/RedisAllData/CreateStream/mapDisplayedIndex.test.ts",
"test:pi-adapters": "tsx src/service/pi/client.test.ts"
},
"dependencies": {
"@chat2db/ui": "^1.45.3",
Expand Down
8 changes: 4 additions & 4 deletions chat2db-community-client/scripts/i18n-source-hashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
"notification.ts": "500751da2f02391622f074448eb46611fd41da2e5530d6c7d65f17a1382bd236",
"plugin.ts": "01f15b6342cc5b29899ee4144d67b04bb4bc02c6bb10779806be322dc5e9a2bc",
"redis.ts": "cacf9cf685bf3bf6d019f18eead0f63713d4727be741a87d8dc1d22807ebd9ad",
"setting.ts": "c256e93a1c6ee99eac34f0d22cea8b5c0609b4cb0960af56198e663bf3e3f93c",
"setting.ts": "8422043f7352260c681fac02550af8cec5524df0409ff2fdaa9434bda04957c9",
"spaceSetting.ts": "defdf3138e5e1782f0282760bcef4ce1b8550cc80b03052fea468d97165cb980",
"sqlEditor.ts": "5c41e5f24d5ba78909795bcc681cabb8460cca075233b665dc4940afe82ce0c9",
"stream.ts": "2e2fca0b1ba1ecd5a1501b767be8857cf0b72d800d69a4acf9cd62a61d5ceaf5",
"stream.ts": "8c870a19ec607a359ed9a0fbfe711554cbb07c9c460414c371a350fb7b0ea405",
"workspace.ts": "f41dcc31f6fa7de500cda95ef550737c99606569077d26150239b4ce14db7ef1"
},
"ko-KR": {
Expand All @@ -38,10 +38,10 @@
"notification.ts": "500751da2f02391622f074448eb46611fd41da2e5530d6c7d65f17a1382bd236",
"plugin.ts": "01f15b6342cc5b29899ee4144d67b04bb4bc02c6bb10779806be322dc5e9a2bc",
"redis.ts": "cacf9cf685bf3bf6d019f18eead0f63713d4727be741a87d8dc1d22807ebd9ad",
"setting.ts": "c256e93a1c6ee99eac34f0d22cea8b5c0609b4cb0960af56198e663bf3e3f93c",
"setting.ts": "8422043f7352260c681fac02550af8cec5524df0409ff2fdaa9434bda04957c9",
"spaceSetting.ts": "defdf3138e5e1782f0282760bcef4ce1b8550cc80b03052fea468d97165cb980",
"sqlEditor.ts": "5c41e5f24d5ba78909795bcc681cabb8460cca075233b665dc4940afe82ce0c9",
"stream.ts": "2e2fca0b1ba1ecd5a1501b767be8857cf0b72d800d69a4acf9cd62a61d5ceaf5",
"stream.ts": "8c870a19ec607a359ed9a0fbfe711554cbb07c9c460414c371a350fb7b0ea405",
"workspace.ts": "f41dcc31f6fa7de500cda95ef550737c99606569077d26150239b4ce14db7ef1"
}
}
Expand Down
88 changes: 88 additions & 0 deletions chat2db-community-client/src/blocks/AI/agentCharts.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import type { AgentEvent } from '@/service/agent';
import { agentChartDetail, isPartialChart, updateAgentCharts, usesGroupedAgentChart } from './agentCharts';
import { buildAgentChartOption } from './components/AgentChartCard/option';

const payload = {
id: 'chart-1', runId: 'run-1', resultId: 'result-1', chartType: 'Line', title: 'Same title',
xField: 'month', yField: 'value', series: [], warnings: [],
data: [{ month: 'Jan', value: 0.1 }, { month: 'Feb', value: null }], page: { number: 1, hasMore: false },
};
const event = (chart: unknown, sequence = 1): AgentEvent => ({
id: `event-${sequence}`, sessionId: 'session', runId: 'run-1', sequence,
type: 'CHART_CREATED', payload: { chart }, occurredAt: '',
});
const first = updateAgentCharts([], [event(payload)]);
assert.equal(first.length, 1);
assert.strictEqual(updateAgentCharts(first, [event(payload)]), first);
const second = updateAgentCharts(first, [event({ ...payload, id: 'chart-2' }, 2)]);
assert.equal(second.length, 2, 'Equal titles do not merge distinct charts');
assert.deepEqual(agentChartDetail(first[0]).chartSchema?.data, payload.data);
assert.equal(agentChartDetail(first[0]).chartSchema?.data[1].value, null);
assert.equal(agentChartDetail({ ...first[0], chartType: 'Combo' }).chartSchema?.chartOptionCheckbox.includes('showLabel'), false);
assert.equal(isPartialChart(first[0]), false);
assert.equal(isPartialChart({ ...first[0], page: { number: 2, hasMore: false } }), true);
assert.equal(isPartialChart({ ...first[0], page: { number: 1, hasMore: null } }), true);
assert.deepEqual(updateAgentCharts([], [event({ ...payload, chartType: 'Bad' }), event({ ...payload, runId: 'foreign' })]), []);
assert.equal(updateAgentCharts([], [event({ ...payload, chartType: 'Statistics', xField: undefined, page: undefined })]).length, 1);
assert.equal(updateAgentCharts([], [event({ ...payload, data: [{ value: Number.NaN }] })]).length, 0);
assert.equal(usesGroupedAgentChart(first[0]), false, 'Historic charts keep the existing renderer');
assert.equal(updateAgentCharts([], [event({ ...payload, groupBy: null, stack: null })]).length, 1);
const groupedPayload = {
...payload, chartType: 'Column', groupBy: ['region'], stack: true,
data: [{ month: 'Jan', region: '华东', value: 10 }, { month: 'Jan', region: '华西', value: 20 }],
};
const restored = updateAgentCharts([], JSON.parse(JSON.stringify([event(groupedPayload)])));
assert.equal(restored.length, 1);
assert.deepEqual(restored[0].groupBy, ['region']);
assert.equal(restored[0].stack, true);
assert.equal(usesGroupedAgentChart(restored[0]), true);
assert.deepEqual(buildAgentChartOption(restored[0], { border: '#ddd', text: '#111' })
.series.map((series) => series.data), [[10], [20]], 'Restored event payloads render the same groups');
for (const invalid of [
{ groupBy: 'region' }, { groupBy: ['region', 'region'] }, { groupBy: [''] }, { groupBy: [null] },
{ groupBy: ['a', 'b', 'c', 'd'] }, { groupBy: ['month'] }, { groupBy: ['value'] }, { groupBy: ['missing'] },
{ stack: 'true' }, { stack: 1 }, { chartType: 'Pie' }, { chartType: 'Statistics' },
{ chartType: 'Line' }, { chartType: 'Scatter' },
{ data: [...groupedPayload.data, groupedPayload.data[0]] },
]) {
assert.equal(updateAgentCharts([], [event({ ...groupedPayload, ...invalid })]).length, 0,
`Reject invalid group/stack payload ${JSON.stringify(invalid)}`);
}
for (const chartType of ['Line', 'Scatter', 'AreaLine', 'Bar']) {
assert.equal(updateAgentCharts([], [event({ ...groupedPayload, chartType, stack: false })]).length, 1);
}
assert.equal(updateAgentCharts([], [event({
...groupedPayload, chartType: 'Scatter', stack: false,
data: [...groupedPayload.data, { ...groupedPayload.data[0], value: 15 }],
})]).length, 1, 'Scatter allows repeated X values for the same group');
const seriesLimit = (count: number) => ({
...groupedPayload,
data: Array.from({ length: count }, (_, index) => ({ month: 'Jan', region: index, value: 1 })),
});
assert.equal(updateAgentCharts([], [event(seriesLimit(32))]).length, 1);
assert.equal(updateAgentCharts([], [event(seriesLimit(33))]).length, 0);
const comboPayload = {
...groupedPayload, chartType: 'Combo',
series: [
{ field: 'value', chartType: 'Column', axisPosition: 'left' },
{ field: 'count', chartType: 'Line', axisPosition: 'right' },
],
};
assert.equal(updateAgentCharts([], [event({ ...comboPayload, data: seriesLimit(16).data })]).length, 1);
assert.equal(updateAgentCharts([], [event({ ...comboPayload, data: seriesLimit(17).data })]).length, 0);
assert.equal(updateAgentCharts([], [event({
...comboPayload, groupBy: [], data: [groupedPayload.data[0]],
})]).length, 1);
assert.equal(updateAgentCharts([], [event({
...comboPayload, series: [comboPayload.series[0], comboPayload.series[0]],
})]).length, 0, 'Duplicate metric fields cannot create duplicate ECharts series IDs');
assert.equal(updateAgentCharts([], [event({
...comboPayload, series: [{ field: 'value', chartType: 'Line', axisPosition: 'left' }],
})]).length, 0, 'Stacked Combo must contain a column or area series');
for (const locale of ['zh-CN', 'en-US', 'es-ES', 'ja-JP', 'ko-KR']) {
const source = readFileSync(new URL(`../../i18n/${locale}/stream.ts`, import.meta.url), 'utf8');
for (const key of ['partialResult', 'viewQueryData', 'queryData']) assert.ok(source.includes(`stream.chart.${key}`));
}
console.log('Agent chart restoration, group/stack schema, identity, series limits and locale coverage passed.');
Loading
Loading