sheetnext 0.1.7 → 0.1.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/docs/demo.png ADDED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sheetnext",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "A powerful spreadsheet editor library with AI capabilities",
5
5
  "homepage": "https://www.sheetnext.com",
6
6
  "repository": {
@@ -25,8 +25,8 @@
25
25
  "types",
26
26
  "README.md",
27
27
  "DOCS.md",
28
- "AGENT.md",
29
- "docs/logo.png"
28
+ "docs/logo.png",
29
+ "docs/demo.png"
30
30
  ],
31
31
  "keywords": [
32
32
  "spreadsheet",
@@ -35,7 +35,14 @@
35
35
  "table",
36
36
  "ai",
37
37
  "canvas",
38
- "data-grid"
38
+ "data-grid",
39
+ "data-analysis",
40
+ "data-visualization",
41
+ "analytics",
42
+ "pivot-table",
43
+ "chart",
44
+ "business-intelligence",
45
+ "collaborative-editing"
39
46
  ],
40
47
  "author": "SheetNext Team",
41
48
  "license": "Apache-2.0",
package/types/index.d.ts CHANGED
@@ -167,5 +167,4 @@ export default class SheetNext {
167
167
  import(file: File): Promise<void>;
168
168
  export(type: 'XLSX'): void;
169
169
  r(): void;
170
- getLicenseInfo(): any;
171
170
  }
package/AGENT.md DELETED
@@ -1,330 +0,0 @@
1
- # SheetNext AI 中转配置指南
2
-
3
- > 一句话总结超级简单:写一个接口将前端传入的message消息分发给你想对接的大模型,然后在前端配置好接口地址即可开始工作!
4
-
5
- ## 文档导航
6
-
7
- - [← 返回 README](https://github.com/wyyazlz/sheetnext/blob/master/README.md) - 快速开始和特点介绍
8
- - [← API 文档](https://github.com/wyyazlz/sheetnext/blob/master/DOCS.md) - 详细的类、方法和属性说明
9
-
10
- ---
11
-
12
- ## 目录
13
-
14
- - [SheetNext AI 中转配置指南](#sheetnext-ai-中转配置指南)
15
- - [文档导航](#文档导航)
16
- - [目录](#目录)
17
- - [功能说明](#功能说明)
18
- - [核心功能](#核心功能)
19
- - [核心架构](#核心架构)
20
- - [工作流程](#工作流程)
21
- - [完整示例](#完整示例)
22
- - [安装依赖](#安装依赖)
23
- - [完整代码](#完整代码)
24
- - [配置说明](#配置说明)
25
- - [消息格式](#消息格式)
26
- - [请求格式](#请求格式)
27
- - [响应格式](#响应格式)
28
-
29
- ---
30
-
31
- ## 功能说明
32
-
33
- AI 服务中转层是连接 SheetNext 前端与大模型 API 的桥梁,主要负责以下核心功能:
34
-
35
- ### 核心功能
36
-
37
- 1. **消息格式转换** - 将 SheetNext 提供的通用消息结构转换为目标大模型(如 Claude、GPT 等)所需的标准格式
38
- 2. **流式数据处理** - 实现 AI 响应的流式接收与转发,提升用户交互体验
39
- 3. **安全隔离** - 在服务端隐藏真实的 API Key,避免密钥泄露风险
40
- 4. **使用统计** - 企业可在中转层统计 Token 消耗、请求次数等关键数据
41
-
42
- ---
43
-
44
- ## 核心架构
45
-
46
- ```
47
- ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
48
- │ │ │ │ │ │
49
- │ SheetNext │────────▶│ 中转服务器 │────────▶│各种大模型API│
50
- │ 前端 │ HTTP │ (您的服务器) │ HTTPS │ (Claude等) │
51
- │ │◀────────│ │◀────────│ │
52
- └─────────────┘ SSE流 └──────────────┘ Stream └─────────────┘
53
-
54
-
55
- ┌──────────────┐
56
- │ 使用统计/日志 │
57
- └──────────────┘
58
- ```
59
-
60
- ### 工作流程
61
-
62
- 1. **前端请求** - SheetNext 发送包含 `messages` 数组的 POST 请求到中转服务器
63
- 2. **格式转换** - 中转服务器将通用格式转换为目标大模型的专用格式
64
- 3. **API 调用** - 使用服务端存储的 API Key 调用大模型 API
65
- 4. **流式响应** - 接收大模型的流式响应,转换后通过 SSE (Server-Sent Events) 返回前端
66
-
67
- ---
68
-
69
- ## 完整示例
70
-
71
- 通用中转完整实现示例:
72
-
73
- ### 安装依赖
74
-
75
- ```bash
76
- npm install @anthropic-ai/sdk openai
77
- ```
78
-
79
- ### 完整代码
80
-
81
- ```javascript
82
- /**
83
- * SheetNext AI & claude/openai 中转服务器示例 Node.js 版本
84
- * 2025.10.17 v1.0.0
85
- */
86
-
87
- const http = require('http');
88
- const Anthropic = require('@anthropic-ai/sdk');
89
- const OpenAI = require('openai');
90
-
91
- // ======= 配置 =======
92
- const CONFIG = {
93
- model: 'claude-sonnet-4-5-20250929', // 设置模型名称,自动判断使用 claude 还是 openai
94
- claude: {
95
- apiKey: 'sk-xWp4TFA81arQCudIbLRmE0h1TtmM0lQWz4Lt7lKryUhk5HhN',
96
- baseURL: 'https://m5.aitoo.fun/'
97
- },
98
- openai: {
99
- apiKey: 'sk-UWq0SWmDIEFTI5hswtg5uONjQ95ECUneWtp46Pp9Kdujg9py',
100
- baseURL: 'https://m5.aitoo.fun/v1'
101
- }
102
- };
103
-
104
- const anthropic = new Anthropic({ apiKey: CONFIG.claude.apiKey, baseURL: CONFIG.claude.baseURL });
105
- const openai = new OpenAI({ apiKey: CONFIG.openai.apiKey, baseURL: CONFIG.openai.baseURL });
106
-
107
- // ======= message默认是openai格式,claude请求时转为它适配格式 =======
108
- const convertToClaudeMessages = (messages) => {
109
- const system = [];
110
- const claudeMessages = [];
111
- let isFirstSystem = true;
112
-
113
- // 转换内容部分的辅助函数
114
- const convertContent = (content) => {
115
- const parts = Array.isArray(content) ? content : [{ type: 'text', text: content }];
116
- return parts.map(part => {
117
- if (part.type === 'text') {
118
- return { type: 'text', text: part.text };
119
- }
120
- if (part.type === 'image_url') {
121
- const [, mediaType, base64Data] = part.image_url.url.match(/data:(.*?);base64,(.*)/) || [];
122
- if (base64Data) {
123
- return { type: 'image', source: { type: 'base64', media_type: mediaType || 'image/jpeg', data: base64Data } };
124
- }
125
- }
126
- return null;
127
- }).filter(Boolean);
128
- };
129
-
130
- for (const msg of messages) {
131
- if (msg.role === 'system') {
132
- if (isFirstSystem) {
133
- // 第一个 system:提取文本作为 system 参数(约定无图片)
134
- const text = typeof msg.content === 'string' ? msg.content : msg.content[0]?.text || '';
135
- if (text) system.push({ type: 'text', text });
136
- isFirstSystem = false;
137
- } else {
138
- // 其他 system:转为 user
139
- claudeMessages.push({ role: 'user', content: convertContent(msg.content) });
140
- }
141
- } else {
142
- // user/assistant 消息
143
- claudeMessages.push({ role: msg.role, content: convertContent(msg.content) });
144
- }
145
- }
146
-
147
- return { system, messages: claudeMessages };
148
- };
149
-
150
- // ======= Claude SDK =======
151
- async function callClaudeSDK(messages, model, onChunk) {
152
- const { system, messages: claudeMessages } = convertToClaudeMessages(messages);
153
-
154
- // 打印请求结构(省略 base64 数据)
155
- const printableRequest = {
156
- system: system.map(s => s.type === 'image'
157
- ? { type: 'image', source: { ...s.source, data: `[${s.source.data?.length || 0} chars]` } }
158
- : s
159
- ),
160
- messages: claudeMessages.map(msg => ({
161
- role: msg.role,
162
- content: typeof msg.content === 'string' ? msg.content :
163
- msg.content.map(c => c.type === 'image'
164
- ? { type: 'image', source: { ...c.source, data: `[${c.source.data?.length || 0} chars]` } }
165
- : c
166
- )
167
- }))
168
- };
169
-
170
- const stream = await anthropic.messages.create({
171
- model: model,
172
- max_tokens: 8192,
173
- system,
174
- messages: claudeMessages,
175
- stream: true,
176
- thinking: { type: "enabled", budget_tokens: 2000 }
177
- });
178
-
179
- for await (const event of stream) {
180
- if (event.type === 'content_block_delta') {
181
- const { delta } = event;
182
- if (delta?.type === 'thinking_delta' && delta.thinking) {
183
- onChunk({ type: 'think', delta: delta.thinking });
184
- } else if (delta?.type === 'text_delta') {
185
- onChunk({ type: 'text', delta: delta.text });
186
- }
187
- }
188
- }
189
- }
190
-
191
- // ======= OpenAI SDK =======
192
- async function callOpenAISDK(messages, model, onChunk) {
193
- const stream = await openai.chat.completions.create({
194
- model: model,
195
- messages: messages, // 直接使用 OpenAI 格式的 messages
196
- stream: true
197
- });
198
-
199
- for await (const chunk of stream) {
200
- const delta = chunk.choices[0]?.delta;
201
- if (delta?.content) {
202
- onChunk({ type: 'text', delta: delta.content });
203
- }
204
- }
205
- }
206
-
207
- // ======= HTTP 处理 =======
208
- async function handleChat(messages, res) {
209
- res.writeHead(200, {
210
- 'Content-Type': 'text/event-stream',
211
- 'Cache-Control': 'no-cache',
212
- 'Connection': 'keep-alive',
213
- 'Access-Control-Allow-Origin': '*'
214
- });
215
-
216
- let ended = false;
217
- const write = (data) => !ended && !res.writableEnded && res.write(data);
218
- const onChunk = (chunk) => write(`data: ${JSON.stringify(chunk)}\n\n`);
219
-
220
- try {
221
- // 根据模型名称自动判断使用哪个 provider
222
- const provider = CONFIG.model.toLowerCase().includes('claude') ? 'claude' : 'openai';
223
- if (provider === 'openai') {
224
- await callOpenAISDK(messages, CONFIG.model, onChunk);
225
- } else {
226
- await callClaudeSDK(messages, CONFIG.model, onChunk);
227
- }
228
- write(`data: [DONE]\n\n`);
229
- } catch (error) {
230
- write(`data: ${JSON.stringify({ error: error.message })}\n\n`);
231
- } finally {
232
- ended = true;
233
- res.end();
234
- }
235
- }
236
-
237
- // ======= HTTP 服务器 =======
238
- http.createServer(async (req, res) => {
239
- const corsHeaders = {
240
- 'Access-Control-Allow-Origin': '*',
241
- 'Access-Control-Allow-Methods': 'POST, OPTIONS',
242
- 'Access-Control-Allow-Headers': 'Content-Type'
243
- };
244
-
245
- if (req.method === 'OPTIONS') {
246
- res.writeHead(200, corsHeaders);
247
- return res.end();
248
- }
249
-
250
- if (req.url === '/sheetnextAI' && req.method === 'POST') {
251
- let body = '';
252
- req.on('data', chunk => body += chunk);
253
- req.on('end', async () => {
254
- try {
255
- const { messages } = JSON.parse(body);
256
- if (!Array.isArray(messages)) throw new Error('Invalid messages');
257
- await handleChat(messages, res);
258
- } catch (error) {
259
- res.writeHead(400, { 'Content-Type': 'application/json' });
260
- res.end(JSON.stringify({ error: error.message }));
261
- }
262
- });
263
- } else {
264
- res.writeHead(404);
265
- res.end('Not Found');
266
- }
267
- }).listen(3000, () => console.log('🚀 Server running on http://localhost:3000'));
268
- ```
269
-
270
- ### 配置说明
271
-
272
- **判断规则:**
273
- - 如果模型名称包含 `claude`(不区分大小写) → 使用 Claude SDK
274
- - 其他情况 → 使用 OpenAI SDK
275
-
276
- ---
277
-
278
- ## 消息格式
279
-
280
- ### 请求格式
281
-
282
- SheetNext 发送的请求体格式:
283
-
284
- ```json
285
- {
286
- "messages": [
287
- {
288
- "role": "system",
289
- "content": "你是一个电子表格助手..."
290
- },
291
- {
292
- "role": "user",
293
- "content": "帮我分析销售数据"
294
- },
295
- {
296
- "role": "assistant",
297
- "content": "好的,我来帮您分析..."
298
- },
299
- {
300
- "role": "user",
301
- "content": [
302
- {
303
- "type": "text",
304
- "text": "某区域图片"
305
- },
306
- {
307
- "type": "image_url",
308
- "image_url": {
309
- "url": "data:image/png;base64,iVBORw0KGgoAAAANS..."
310
- }
311
- }
312
- ]
313
- }
314
- ]
315
- }
316
- ```
317
-
318
- ### 响应格式
319
-
320
- 您的服务器应该返回 SSE 流:
321
-
322
- ```
323
- data: {"type":"text","delta":"我"}
324
-
325
- data: {"type":"text","delta":"来"}
326
-
327
- data: {"type":"text","delta":"帮"}
328
-
329
- data: [DONE]
330
- ```
package/README.zh-CN.md DELETED
@@ -1,100 +0,0 @@
1
- <div align="center">
2
- <div><img src="docs/logo.png" alt="SheetNext Logo" width="100" style="vertical-align: middle;"/></div>
3
- <div>✨ 数行代码可集成一个纯前端高性能 Excel 编辑器。</div>
4
- <div>🤖 内置超级AI工作流程,目标用 AI 操纵 Excel 表格完成所有任务。</div>
5
- <div>
6
- <a href="https://www.sheetnext.com/">🏠 官网</a> |
7
- <a href="https://www.sheetnext.com/editor">🎯 在线体验</a> |
8
- <a href="https://github.com/wyyazlz/sheetnext/blob/main/AGENT.md">🤖 AI中转文档</a> |
9
- <a href="https://github.com/wyyazlz/sheetnext/blob/main/DOCS.md">📖 编辑器操作文档</a>
10
- </div>
11
- </div>
12
-
13
- ---
14
-
15
- [English](./README.md) | 简体中文
16
-
17
- ## ✨ 特点
18
-
19
- - 📊 **电子表格功能** - 支持电子表格核心功能如:单元格编辑、样式、公式引擎、图表、排序、筛选等
20
- - 🤖 **AI 工作流** - 内置 AI 全自动操作工作流,简单配置可以生成模板、数据分析、公式编写、跨表逻辑操纵等
21
- - 📁 **导入导出** - 原生支持 Excel (.xlsx) 文件的导入和导出,无需插件前端秒操作
22
- - 🚀 **开箱即用** - 不用单独配置任何库和插件,安装后简单配置即用所有功能
23
- - 🔄 **快速迭代** - 版本快速迭代更新,有问题可随时联系或提交 issue
24
-
25
- ## 🚀 快速开始
26
-
27
- ### 📦 使用 npm 安装
28
-
29
- \`\`\`bash
30
- npm install sheetnext
31
- \`\`\`
32
-
33
- \`\`\`html
34
- <div id="SNContainer" style="width:100vw;height:100vh;padding:0 7px 7px"></div>
35
- \`\`\`
36
-
37
- \`\`\`javascript
38
- import SheetNext from 'sheetnext';
39
- import 'sheetnext/dist/sheetnext.css';
40
-
41
- // 注意设置容器#SNContainer宽高
42
- const SN = new SheetNext(document.querySelector('#SNContainer'));
43
- \`\`\`
44
-
45
- ### 🌐 浏览器直接引入
46
-
47
- \`\`\`html
48
- <!-- 引入样式 -->
49
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sheetnext/dist/sheetnext.css">
50
-
51
- <!-- 编辑器容器 -->
52
- <div id="SNContainer" style="width: 100vw; height: 100vh;padding:0 7px 7px"></div>
53
-
54
- <!-- 引入脚本 -->
55
- <script src="https://cdn.jsdelivr.net/npm/sheetnext/dist/sheetnext.umd.js"></script>
56
-
57
- <!-- 初始化,注意设置宽高 -->
58
- <script>
59
- const SN = new SheetNext(document.querySelector('#SNContainer'));
60
- </script>
61
- \`\`\`
62
-
63
- ## ⚙️ 初始化配置
64
-
65
- \`\`\`javascript
66
- const SN = new SheetNext(document.querySelector('#container'), {
67
- AI_URL: "http://localhost:3000/sheetnextAI", // AI 中转地址(可选)
68
- AI_TOKEN: "your-token" // 中转 token(可选)
69
- });
70
- \`\`\`
71
-
72
- ## 📚 文档
73
-
74
- - [DOCS.md](./DOCS.md) - 完整 API 文档
75
- - [AGENT.md](./AGENT.md) - AI Agent 集成指南
76
- - [官方网站](https://www.sheetnext.com) - 更多示例和教程
77
-
78
- ## 🤝 贡献
79
-
80
- 欢迎提交 Issue 和参与讨论!详见 [CONTRIBUTING.md](./CONTRIBUTING.md)
81
-
82
- ## 📄 许可证
83
-
84
- [Apache-2.0](./LICENSE)
85
-
86
- ## 🌟 社区版说明
87
-
88
- 这是 SheetNext 的社区版本,包含编译后的分发文件。核心源代码因商业原因保持私有。
89
-
90
- 您可以:
91
- - ✅ 免费使用和分发
92
- - ✅ 用于商业项目
93
- - ✅ 修改和定制(通过 API)
94
- - ✅ 报告问题和提出建议
95
-
96
- ## 🔗 相关链接
97
-
98
- - 🏠 [官网](https://www.sheetnext.com)
99
- - 📦 [npm 包地址](https://www.npmjs.com/package/sheetnext)
100
- - 💬 [问题反馈](https://github.com/wyyazlz/sheetnext/issues)