Compare commits
11 Commits
85a88cdf1a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0476b24c14 | ||
|
|
57326c14d6 | ||
|
|
c832465d57 | ||
|
|
babee3f155 | ||
|
|
35d3cae9f1 | ||
|
|
b7e2bdcb1c | ||
|
|
c3bc0d2465 | ||
|
|
bcb5552ebc | ||
|
|
342b68abe3 | ||
|
|
228635a3cc | ||
|
|
4e8eb06f56 |
1
.npmrc
1
.npmrc
@@ -1,3 +1,2 @@
|
|||||||
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
|
|
||||||
//npm.cnb.cool/kevisual/registry/-/packages/:_authToken=${CNB_API_KEY}
|
//npm.cnb.cool/kevisual/registry/-/packages/:_authToken=${CNB_API_KEY}
|
||||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||||
@@ -42,17 +42,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@inquirer/prompts": "^8.3.0",
|
"@inquirer/prompts": "^8.3.2",
|
||||||
"@kevisual/ai": "^0.0.28",
|
"@kevisual/ai": "^0.0.28",
|
||||||
"@kevisual/api": "^0.0.64",
|
"@kevisual/api": "^0.0.64",
|
||||||
"@kevisual/load": "^0.0.6",
|
"@kevisual/load": "^0.0.6",
|
||||||
"@kevisual/local-app-manager": "^0.1.32",
|
"@kevisual/local-app-manager": "^0.1.32",
|
||||||
"@kevisual/logger": "^0.0.4",
|
"@kevisual/logger": "^0.0.4",
|
||||||
"@kevisual/query": "0.0.53",
|
"@kevisual/query": "0.0.53",
|
||||||
"@kevisual/router": "^0.1.1",
|
"@kevisual/router": "^0.1.5",
|
||||||
"@kevisual/types": "^0.0.12",
|
"@kevisual/types": "^0.0.12",
|
||||||
"@kevisual/use-config": "^1.0.30",
|
"@kevisual/use-config": "^1.0.30",
|
||||||
"@opencode-ai/plugin": "^1.2.24",
|
"@opencode-ai/plugin": "^1.2.27",
|
||||||
"@types/bun": "^1.3.10",
|
"@types/bun": "^1.3.10",
|
||||||
"@types/node": "^25.5.0",
|
"@types/node": "^25.5.0",
|
||||||
"@types/send": "^1.2.1",
|
"@types/send": "^1.2.1",
|
||||||
@@ -63,8 +63,8 @@
|
|||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"get-port": "^7.1.0",
|
"get-port": "^7.1.0",
|
||||||
"meilisearch": "^0.55.0",
|
"meilisearch": "^0.56.0",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.7",
|
||||||
"send": "^1.2.1",
|
"send": "^1.2.1",
|
||||||
"supports-color": "^10.2.2",
|
"supports-color": "^10.2.2",
|
||||||
"table": "^6.9.0",
|
"table": "^6.9.0",
|
||||||
@@ -77,15 +77,15 @@
|
|||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.1008.0",
|
"@aws-sdk/client-s3": "^3.1011.0",
|
||||||
"@kevisual/js-filter": "^0.0.6",
|
"@kevisual/js-filter": "^0.0.6",
|
||||||
"@kevisual/oss": "^0.0.20",
|
"@kevisual/oss": "^0.0.20",
|
||||||
"@kevisual/video-tools": "^0.0.13",
|
"@kevisual/video-tools": "^0.0.13",
|
||||||
"@opencode-ai/sdk": "^1.2.24",
|
"@opencode-ai/sdk": "^1.2.27",
|
||||||
"es-toolkit": "^1.45.1",
|
"es-toolkit": "^1.45.1",
|
||||||
"eventemitter3": "^5.0.4",
|
"eventemitter3": "^5.0.4",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
"lru-cache": "^11.2.6",
|
"lru-cache": "^11.2.7",
|
||||||
"pm2": "^6.0.14",
|
"pm2": "^6.0.14",
|
||||||
"unstorage": "^1.17.4",
|
"unstorage": "^1.17.4",
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6"
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ export class AssistantConfig {
|
|||||||
return checkConfigDir;
|
return checkConfigDir;
|
||||||
}
|
}
|
||||||
protected getDefaultInitAssistantConfig() {
|
protected getDefaultInitAssistantConfig() {
|
||||||
const id = randomId();
|
let id = randomId();
|
||||||
const isCNB = !!useKey('CNB');
|
const isCNB = !!useKey('CNB');
|
||||||
let kevisualUrl = 'https://kevisual.cn';
|
let kevisualUrl = 'https://kevisual.cn';
|
||||||
if (isCNB) {
|
if (isCNB) {
|
||||||
@@ -390,6 +390,11 @@ export class AssistantConfig {
|
|||||||
kevisualUrl = 'http://kevisual.cn';
|
kevisualUrl = 'http://kevisual.cn';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const routes = ["@kevisual/cnb/routes"]
|
||||||
|
if (isCNB) {
|
||||||
|
routes.push("@kevisual/project-search/routes")
|
||||||
|
id = 'cnb-dev'
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
app: {
|
app: {
|
||||||
url: kevisualUrl,
|
url: kevisualUrl,
|
||||||
@@ -399,9 +404,7 @@ export class AssistantConfig {
|
|||||||
docs: `${kevisualUrl}/root/cli/docs/`,
|
docs: `${kevisualUrl}/root/cli/docs/`,
|
||||||
home: isCNB ? '/root/cli-center' : '/root/home',
|
home: isCNB ? '/root/cli-center' : '/root/home',
|
||||||
proxy: [],
|
proxy: [],
|
||||||
"routes": [
|
"routes": routes,
|
||||||
"@kevisual/cnb/routes"
|
|
||||||
],
|
|
||||||
share: {
|
share: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
url: 'https://kevisual.cn/ws/proxy',
|
url: 'https://kevisual.cn/ws/proxy',
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ export class AssistantApp extends Manager {
|
|||||||
try {
|
try {
|
||||||
const routeStr = typeof route === 'string' ? route : route.path;
|
const routeStr = typeof route === 'string' ? route : route.path;
|
||||||
const resolvedPath = this.resolver.resolve(routeStr);
|
const resolvedPath = this.resolver.resolve(routeStr);
|
||||||
|
// console.log('Resolved route path:', routeStr, '->', resolvedPath);
|
||||||
await import(resolvedPath);
|
await import(resolvedPath);
|
||||||
console.log('[routes] 路由已初始化', route);
|
console.log('[routes] 路由已初始化', route);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const getLiveMdContent = (opts?: { more?: boolean }) => {
|
|||||||
const token = useKey('CNB_TOKEN') || ''
|
const token = useKey('CNB_TOKEN') || ''
|
||||||
const openclawPort = useKey('OPENCLAW_PORT') || '80'
|
const openclawPort = useKey('OPENCLAW_PORT') || '80'
|
||||||
const openclawUrl = url.replace('{{port}}', openclawPort)
|
const openclawUrl = url.replace('{{port}}', openclawPort)
|
||||||
const openclawUrlSecret = openclawUrl + '/openclaw?token=' + token
|
const openclawUrlSecret = openclawUrl + '/openclaw#token=' + token
|
||||||
|
|
||||||
const opencodePort = useKey('OPENCODE_PORT') || '100'
|
const opencodePort = useKey('OPENCODE_PORT') || '100'
|
||||||
const opencodeUrl = url.replace('{{port}}', opencodePort)
|
const opencodeUrl = url.replace('{{port}}', opencodePort)
|
||||||
|
|||||||
@@ -4,6 +4,50 @@ import { getClient } from './module/client.ts';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { Session } from '@opencode-ai/sdk';
|
import { Session } from '@opencode-ai/sdk';
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-cnb',
|
||||||
|
key: 'models',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '获取 OpenCode 可用模型列表,返回 providerID 和 modelID',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
baseUrl: z.string().optional().describe('OpenCode 服务地址,默认为 http://localhost:4096'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { baseUrl } = ctx.query;
|
||||||
|
const client = await getClient({ baseUrl });
|
||||||
|
if (!client) {
|
||||||
|
ctx.body = { content: '获取 OpenCode 客户端失败' };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await client.provider.list();
|
||||||
|
const providerData = (res as any)?.data ?? res;
|
||||||
|
const all: any[] = providerData?.all ?? [];
|
||||||
|
const connected: string[] = providerData?.connected ?? [];
|
||||||
|
const defaultModels: Record<string, string> = providerData?.default ?? {};
|
||||||
|
|
||||||
|
const models: Array<{ providerID: string; providerName: string; modelID: string; modelName: string; isDefault: boolean; isConnected: boolean }> = [];
|
||||||
|
for (const provider of all) {
|
||||||
|
const isConnected = connected.includes(provider.id);
|
||||||
|
for (const [modelKey, model] of Object.entries<any>(provider.models ?? {})) {
|
||||||
|
models.push({
|
||||||
|
providerID: provider.id,
|
||||||
|
providerName: provider.name,
|
||||||
|
modelID: modelKey,
|
||||||
|
modelName: model.name ?? modelKey,
|
||||||
|
isDefault: defaultModels[provider.id] === modelKey,
|
||||||
|
isConnected,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
content: `共 ${models.length} 个模型,已连接提供商: ${connected.join(', ') || '无'}`,
|
||||||
|
data: { models, connected, default: defaultModels },
|
||||||
|
};
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
app.route({
|
app.route({
|
||||||
path: 'opencode-cnb',
|
path: 'opencode-cnb',
|
||||||
key: 'question',
|
key: 'question',
|
||||||
@@ -14,13 +58,16 @@ app.route({
|
|||||||
question: z.string().describe('问题'),
|
question: z.string().describe('问题'),
|
||||||
baseUrl: z.string().optional().describe('OpenCode 服务地址,默认为 http://localhost:4096'),
|
baseUrl: z.string().optional().describe('OpenCode 服务地址,默认为 http://localhost:4096'),
|
||||||
directory: z.string().optional().describe('运行目录,默认为根目录'),
|
directory: z.string().optional().describe('运行目录,默认为根目录'),
|
||||||
messageID: z.string().optional().describe('消息 ID,选填'),
|
messageId: z.string().optional().describe('消息 ID,选填'),
|
||||||
sessionId: z.string().optional().describe('会话 ID,选填'),
|
sessionId: z.string().optional().describe('会话 ID,选填'),
|
||||||
|
providerId: z.string().optional().describe('指定使用的提供商 ID,默认为空,表示使用默认提供商'),
|
||||||
|
modelId: z.string().optional().describe('指定使用的模型 ID,默认为空,表示使用默认模型'),
|
||||||
parts: z.array(z.any()).optional().describe('消息内容的分块,优先于 question 参数'),
|
parts: z.array(z.any()).optional().describe('消息内容的分块,优先于 question 参数'),
|
||||||
|
awaitAnswer: z.boolean().optional().describe('是否等待回答完成,默认为 false,开启后会在回答完成后返回完整回答内容')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).define(async (ctx) => {
|
}).define(async (ctx) => {
|
||||||
const { question, baseUrl, directory = '/workspace', messageID, sessionId, parts } = ctx.query;
|
const { question, baseUrl, directory = '/workspace', messageId, sessionId, parts, awaitAnswer = false, providerId, modelId } = ctx.query;
|
||||||
const client = await getClient({ baseUrl: baseUrl });
|
const client = await getClient({ baseUrl: baseUrl });
|
||||||
if (!client) {
|
if (!client) {
|
||||||
ctx.body = { content: `OpenCode 客户端获取失败` };
|
ctx.body = { content: `OpenCode 客户端获取失败` };
|
||||||
@@ -30,12 +77,7 @@ app.route({
|
|||||||
ctx.body = { content: `问题不能为空` };
|
ctx.body = { content: `问题不能为空` };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// const sessionList = await client.session.list()
|
|
||||||
let session: Session | null = null;
|
let session: Session | null = null;
|
||||||
// const hasSession = sessionList.data.find(s => s.directory === directory);
|
|
||||||
// if (hasSession) {
|
|
||||||
// session = hasSession;
|
|
||||||
// } else {
|
|
||||||
if (sessionId) {
|
if (sessionId) {
|
||||||
try {
|
try {
|
||||||
const getSession = await client.session.get({ path: { id: sessionId } });
|
const getSession = await client.session.get({ path: { id: sessionId } });
|
||||||
@@ -53,16 +95,30 @@ app.route({
|
|||||||
session = createSession.data;
|
session = createSession.data;
|
||||||
}
|
}
|
||||||
let _parts: any[] = parts ?? [{ type: "text", text: question }];
|
let _parts: any[] = parts ?? [{ type: "text", text: question }];
|
||||||
const message = await client.session.prompt({
|
let data: any = null;
|
||||||
|
let model = null;
|
||||||
|
if (providerId && modelId) {
|
||||||
|
model = { providerID: providerId, modelID: modelId };
|
||||||
|
}
|
||||||
|
const promptPromise = client.session.prompt({
|
||||||
body: {
|
body: {
|
||||||
messageID: messageID,
|
messageID: messageId,
|
||||||
parts: _parts,
|
parts: _parts,
|
||||||
|
...model ? { model } : {},
|
||||||
},
|
},
|
||||||
path: {
|
path: {
|
||||||
id: sessionId || session.id,
|
id: sessionId || session.id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const data = message.data;
|
if (awaitAnswer) {
|
||||||
|
const message = await promptPromise;
|
||||||
ctx.body = { content: `已经启动`, data };
|
data = message.data;
|
||||||
|
} else {
|
||||||
|
promptPromise.then(res => {
|
||||||
|
console.log(`Prompt completed with response:`, res.data.info.id);
|
||||||
|
}).catch(() => {
|
||||||
|
// 忽略错误
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ctx.body = { content: awaitAnswer ? `已经完成` : `运行中`, data, sessionId: session.id };
|
||||||
}).addTo(app);
|
}).addTo(app);
|
||||||
@@ -1 +1,3 @@
|
|||||||
import './ls.ts'
|
import './ls.ts'
|
||||||
|
import './cnb.ts'
|
||||||
|
import './session/index.ts'
|
||||||
282
assistant/src/routes/opencode/session/index.ts
Normal file
282
assistant/src/routes/opencode/session/index.ts
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
import { app } from '@/app.ts'
|
||||||
|
import { createSkill, tool } from '@kevisual/router';
|
||||||
|
import { opencodeManager } from '../module/open.ts';
|
||||||
|
|
||||||
|
// 查询 - 列出所有 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'list',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '列出所有 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'list-opencode-sessions',
|
||||||
|
title: '列出所有 Session',
|
||||||
|
summary: '列出 OpenCode 中的所有会话,可按目录过滤',
|
||||||
|
args: {
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { port } = ctx.query;
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.list();
|
||||||
|
ctx.body = { data: result.data, content: `共 ${(result.data as any[])?.length ?? 0} 个 Session` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 查询 - 获取单个 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'get',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '获取指定 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'get-opencode-session',
|
||||||
|
title: '获取 Session',
|
||||||
|
summary: '根据 ID 获取指定的 OpenCode 会话信息',
|
||||||
|
args: {
|
||||||
|
id: tool.schema.string().describe('Session ID'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { id, port } = ctx.query;
|
||||||
|
if (!id) {
|
||||||
|
ctx.throw(400, 'Session ID 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.get({ path: { id } });
|
||||||
|
ctx.body = { data: result.data, content: `已获取 Session: ${id}` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 查询 - 获取 session 状态
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'status',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '获取 OpenCode Session 状态',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'get-opencode-session-status',
|
||||||
|
title: '获取 Session 状态',
|
||||||
|
summary: '获取当前 OpenCode 会话的运行状态,可按目录过滤',
|
||||||
|
args: {
|
||||||
|
directory: tool.schema.string().optional().describe('工作目录'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { directory, port } = ctx.query;
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.status(directory ? { query: { directory } } : undefined);
|
||||||
|
ctx.body = { data: result.data, content: `Session 状态已获取` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 查询 - 列出 session 消息
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'messages',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '列出 OpenCode Session 消息',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'list-opencode-session-messages',
|
||||||
|
title: '列出 Session 消息',
|
||||||
|
summary: '列出指定 OpenCode 会话的所有消息记录',
|
||||||
|
args: {
|
||||||
|
sessionId: tool.schema.string().describe('Session ID'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { sessionId, port } = ctx.query;
|
||||||
|
if (!sessionId) {
|
||||||
|
ctx.throw(400, 'Session ID 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.messages({ path: { id: sessionId } });
|
||||||
|
ctx.body = { data: result.data, content: `Session ${sessionId} 共 ${(result.data as any[])?.length ?? 0} 条消息` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 新增 - 创建 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'create',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '创建 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'create-opencode-session',
|
||||||
|
title: '创建 Session',
|
||||||
|
summary: '在指定目录创建一个新的 OpenCode 会话',
|
||||||
|
args: {
|
||||||
|
directory: tool.schema.string().optional().describe('工作目录,默认为 /workspace'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { directory = '/workspace', port } = ctx.query;
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.create({ query: { directory } });
|
||||||
|
ctx.body = { data: result.data, content: `Session 已创建,ID: ${(result.data as any)?.id}` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 修改 - 更新 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'update',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '更新 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'update-opencode-session',
|
||||||
|
title: '更新 Session',
|
||||||
|
summary: '更新指定 OpenCode 会话的属性,如标题',
|
||||||
|
args: {
|
||||||
|
sessionId: tool.schema.string().describe('Session ID'),
|
||||||
|
title: tool.schema.string().optional().describe('新的会话标题'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { sessionId, title, port } = ctx.query;
|
||||||
|
if (!sessionId) {
|
||||||
|
ctx.throw(400, 'Session ID 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.update({ path: { id: sessionId }, body: { title } });
|
||||||
|
ctx.body = { data: result.data, content: `Session ${sessionId} 已更新` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 删除 - 删除 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'delete',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '删除 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'delete-opencode-session',
|
||||||
|
title: '删除 Session',
|
||||||
|
summary: '根据 ID 删除指定的 OpenCode 会话及其所有数据',
|
||||||
|
args: {
|
||||||
|
sessionId: tool.schema.string().describe('Session ID'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { sessionId, port } = ctx.query;
|
||||||
|
if (!sessionId) {
|
||||||
|
ctx.throw(400, 'Session ID 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
await client.session.delete({ path: { id: sessionId } });
|
||||||
|
ctx.body = { content: `Session ${sessionId} 已删除` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 操作 - 中止 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'abort',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '中止 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'abort-opencode-session',
|
||||||
|
title: '中止 Session',
|
||||||
|
summary: '中止正在运行的 OpenCode 会话',
|
||||||
|
args: {
|
||||||
|
sessionId: tool.schema.string().describe('Session ID'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { sessionId, port } = ctx.query;
|
||||||
|
if (!sessionId) {
|
||||||
|
ctx.throw(400, 'Session ID 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
await client.session.abort({ path: { id: sessionId } });
|
||||||
|
ctx.body = { content: `Session ${sessionId} 已中止` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 操作 - Fork session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'fork',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: 'Fork OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'fork-opencode-session',
|
||||||
|
title: 'Fork Session',
|
||||||
|
summary: '从指定消息处 Fork 一个 OpenCode 会话',
|
||||||
|
args: {
|
||||||
|
sessionId: tool.schema.string().describe('Session ID'),
|
||||||
|
messageId: tool.schema.string().describe('从该消息处开始 Fork'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { sessionId, messageId, port } = ctx.query;
|
||||||
|
if (!sessionId || !messageId) {
|
||||||
|
ctx.throw(400, 'Session ID 和 messageId 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.fork({ path: { id: sessionId }, body: { messageID: messageId } });
|
||||||
|
ctx.body = { data: result.data, content: `Session ${sessionId} 已从消息 ${messageId} Fork` };
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
// 操作 - 总结 session
|
||||||
|
app.route({
|
||||||
|
path: 'opencode-session',
|
||||||
|
key: 'summarize',
|
||||||
|
middleware: ['auth-admin'],
|
||||||
|
description: '总结 OpenCode Session',
|
||||||
|
metadata: {
|
||||||
|
tags: ['session'],
|
||||||
|
...createSkill({
|
||||||
|
skill: 'summarize-opencode-session',
|
||||||
|
title: '总结 Session',
|
||||||
|
summary: '对指定的 OpenCode 会话进行内容总结',
|
||||||
|
args: {
|
||||||
|
sessionId: tool.schema.string().describe('Session ID'),
|
||||||
|
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { sessionId, port } = ctx.query;
|
||||||
|
if (!sessionId) {
|
||||||
|
ctx.throw(400, 'Session ID 不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = await opencodeManager.getClient({ port });
|
||||||
|
const result = await client.session.summarize({ path: { id: sessionId } });
|
||||||
|
ctx.body = { data: result.data, content: `Session ${sessionId} 总结完成` };
|
||||||
|
}).addTo(app);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
export const configJson = `{
|
export const configJson = `{
|
||||||
"name": "assistant-app",
|
"name": "assistant-app",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"description": "assistant-app package pnpm, node pkgs projects",
|
"description": "assistant-app package pnpm, node pkgs projects",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -11,18 +11,21 @@ export const configJson = `{
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.1007.0",
|
"@aws-sdk/client-s3": "^3.1011.0",
|
||||||
|
"@kevisual/cnb": "^0.0.53",
|
||||||
"@kevisual/oss": "^0.0.20",
|
"@kevisual/oss": "^0.0.20",
|
||||||
|
"@kevisual/project-search": "^0.0.12",
|
||||||
"@kevisual/query": "^0.0.53",
|
"@kevisual/query": "^0.0.53",
|
||||||
"@kevisual/router": "^0.1.1",
|
"@kevisual/router": "^0.1.5",
|
||||||
"@kevisual/cnb": "^0.0.42",
|
|
||||||
"@kevisual/use-config": "^1.0.30",
|
"@kevisual/use-config": "^1.0.30",
|
||||||
"dayjs": "^1.11.19",
|
"@parcel/watcher": "^2.5.6",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"dayjs": "^1.11.20",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"es-toolkit": "^1.45.1",
|
"es-toolkit": "^1.45.1",
|
||||||
"eventemitter3": "^5.0.4",
|
"eventemitter3": "^5.0.4",
|
||||||
"ioredis": "^5.10.0",
|
"ioredis": "^5.10.0",
|
||||||
"node-cron": "^4.2.1",
|
"cron": "^4.4.0",
|
||||||
"pg": "^8.20.0",
|
"pg": "^8.20.0",
|
||||||
"pm2": "^6.0.14",
|
"pm2": "^6.0.14",
|
||||||
"unstorage": "^1.17.4"
|
"unstorage": "^1.17.4"
|
||||||
@@ -30,7 +33,8 @@ export const configJson = `{
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/types": "^0.0.12",
|
"@kevisual/types": "^0.0.12",
|
||||||
"@types/bun": "^1.3.10",
|
"@types/bun": "^1.3.10",
|
||||||
"@types/node": "^25.4.0",
|
"@types/crypto-js": "^4.2.2",
|
||||||
|
"@types/node": "^25.5.0",
|
||||||
"semver": "^7.7.4"
|
"semver": "^7.7.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ export class AssistantInit extends AssistantConfig {
|
|||||||
`packages:
|
`packages:
|
||||||
- 'apps/**/*'
|
- 'apps/**/*'
|
||||||
- 'pages/**/*'
|
- 'pages/**/*'
|
||||||
|
- 'skills/**/*'
|
||||||
|
allowBuilds:
|
||||||
|
'@parcel/watcher': true
|
||||||
|
|
||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
console.log(chalk.green('助手 pnpm-workspace.yaml 文件创建成功'));
|
console.log(chalk.green('助手 pnpm-workspace.yaml 文件创建成功'));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "assistant-app",
|
"name": "assistant-app",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"description": "assistant-app package pnpm, node pkgs projects",
|
"description": "assistant-app package pnpm, node pkgs projects",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -11,18 +11,21 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.1007.0",
|
"@aws-sdk/client-s3": "^3.1011.0",
|
||||||
|
"@kevisual/cnb": "^0.0.53",
|
||||||
"@kevisual/oss": "^0.0.20",
|
"@kevisual/oss": "^0.0.20",
|
||||||
|
"@kevisual/project-search": "^0.0.12",
|
||||||
"@kevisual/query": "^0.0.53",
|
"@kevisual/query": "^0.0.53",
|
||||||
"@kevisual/router": "^0.1.1",
|
"@kevisual/router": "^0.1.5",
|
||||||
"@kevisual/cnb": "^0.0.42",
|
|
||||||
"@kevisual/use-config": "^1.0.30",
|
"@kevisual/use-config": "^1.0.30",
|
||||||
"dayjs": "^1.11.19",
|
"@parcel/watcher": "^2.5.6",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"dayjs": "^1.11.20",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"es-toolkit": "^1.45.1",
|
"es-toolkit": "^1.45.1",
|
||||||
"eventemitter3": "^5.0.4",
|
"eventemitter3": "^5.0.4",
|
||||||
"ioredis": "^5.10.0",
|
"ioredis": "^5.10.0",
|
||||||
"node-cron": "^4.2.1",
|
"cron": "^4.4.0",
|
||||||
"pg": "^8.20.0",
|
"pg": "^8.20.0",
|
||||||
"pm2": "^6.0.14",
|
"pm2": "^6.0.14",
|
||||||
"unstorage": "^1.17.4"
|
"unstorage": "^1.17.4"
|
||||||
@@ -30,7 +33,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/types": "^0.0.12",
|
"@kevisual/types": "^0.0.12",
|
||||||
"@types/bun": "^1.3.10",
|
"@types/bun": "^1.3.10",
|
||||||
"@types/node": "^25.4.0",
|
"@types/crypto-js": "^4.2.2",
|
||||||
|
"@types/node": "^25.5.0",
|
||||||
"semver": "^7.7.4"
|
"semver": "^7.7.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
21
package.json
21
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kevisual/cli",
|
"name": "@kevisual/cli",
|
||||||
"version": "0.1.23",
|
"version": "0.1.29",
|
||||||
"description": "envision 命令行工具",
|
"description": "envision 命令行工具",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"basename": "/root/cli",
|
"basename": "/root/cli",
|
||||||
@@ -41,28 +41,28 @@
|
|||||||
],
|
],
|
||||||
"author": "abearxiong",
|
"author": "abearxiong",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@inquirer/prompts": "^8.3.0",
|
"@inquirer/prompts": "^8.3.2",
|
||||||
"@kevisual/app": "^0.0.2",
|
"@kevisual/app": "^0.0.2",
|
||||||
"@kevisual/auth": "^2.0.3",
|
"@kevisual/auth": "^2.0.3",
|
||||||
"@kevisual/context": "^0.0.8",
|
"@kevisual/context": "^0.0.8",
|
||||||
"@kevisual/router": "^0.1.1",
|
"@kevisual/router": "^0.1.5",
|
||||||
"@kevisual/use-config": "^1.0.30",
|
"@kevisual/use-config": "^1.0.30",
|
||||||
"@opencode-ai/sdk": "^1.2.24",
|
"@opencode-ai/sdk": "^1.2.27",
|
||||||
"@types/busboy": "^1.5.4",
|
"@types/busboy": "^1.5.4",
|
||||||
"busboy": "^1.6.0",
|
"busboy": "^1.6.0",
|
||||||
"eventemitter3": "^5.0.4",
|
"eventemitter3": "^5.0.4",
|
||||||
"jose": "^6.2.1",
|
"jose": "^6.2.1",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
"lru-cache": "^11.2.6",
|
"lru-cache": "^11.2.7",
|
||||||
"micromatch": "^4.0.8",
|
"micromatch": "^4.0.8",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.7",
|
||||||
"pm2": "latest",
|
"pm2": "latest",
|
||||||
"semver": "^7.7.4",
|
"semver": "^7.7.4",
|
||||||
"unstorage": "^1.17.4"
|
"unstorage": "^1.17.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/api": "^0.0.64",
|
"@kevisual/api": "^0.0.64",
|
||||||
"@kevisual/cnb": "^0.0.45",
|
"@kevisual/cnb": "^0.0.53",
|
||||||
"@kevisual/dts": "^0.0.4",
|
"@kevisual/dts": "^0.0.4",
|
||||||
"@kevisual/load": "^0.0.6",
|
"@kevisual/load": "^0.0.6",
|
||||||
"@kevisual/logger": "^0.0.4",
|
"@kevisual/logger": "^0.0.4",
|
||||||
@@ -83,12 +83,15 @@
|
|||||||
"jsonwebtoken": "^9.0.3",
|
"jsonwebtoken": "^9.0.3",
|
||||||
"pm2": "^6.0.14",
|
"pm2": "^6.0.14",
|
||||||
"tar": "^7.5.11",
|
"tar": "^7.5.11",
|
||||||
"zustand": "^5.0.11"
|
"zustand": "^5.0.12"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.0.0"
|
"node": ">=22.0.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
}
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"assistant"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
4983
pnpm-lock.yaml
generated
Normal file
4983
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
# 一个简单的cli工具
|
# 一个简单的cli工具
|
||||||
|
|
||||||
```
|
```
|
||||||
|
pnpm i
|
||||||
npm i -g @kevisual/cli
|
npm i -g @kevisual/cli
|
||||||
```
|
```
|
||||||
@@ -14,11 +14,79 @@ const parseIfJson = (str: string) => {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const publishRegistry = (options: { execPath: string, registry: string, tag?: string, config: any, env: any }) => {
|
||||||
|
const packageJson = path.resolve(options.execPath, 'package.json');
|
||||||
|
let cmd = '';
|
||||||
|
const config = options.config || {};
|
||||||
|
const execPath = options.execPath;
|
||||||
|
const registry = options.registry;
|
||||||
|
const setEnv = options.env || {};
|
||||||
|
switch (registry) {
|
||||||
|
case 'npm':
|
||||||
|
cmd = 'npm publish -s --registry https://registry.npmjs.org';
|
||||||
|
break;
|
||||||
|
case 'cnb':
|
||||||
|
cmd = 'npm publish -s --registry https://npm.cnb.cool/kevisual/registry/-/packages/';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cmd = 'npm publish -s --registry https://registry.npmjs.org';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fileIsExist(packageJson)) {
|
||||||
|
const keys = Object.keys(config).filter((key) => key.includes('NPM_TOKEN'));
|
||||||
|
const tokenEnv = keys.reduce((prev, key) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[key]: config[key],
|
||||||
|
};
|
||||||
|
}, {});
|
||||||
|
const pkg = fs.readFileSync(packageJson, 'utf-8');
|
||||||
|
const pkgJson = parseIfJson(pkg);
|
||||||
|
const version = pkgJson?.version as string;
|
||||||
|
if (version && options?.tag) {
|
||||||
|
let tag = String(version).split('-')[1] || '';
|
||||||
|
if (tag) {
|
||||||
|
if (tag.includes('.')) {
|
||||||
|
tag = tag.split('.')[0];
|
||||||
|
}
|
||||||
|
cmd = `${cmd} --tag ${tag}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(chalk.green(cmd));
|
||||||
|
|
||||||
|
const child = spawn(cmd, {
|
||||||
|
shell: true,
|
||||||
|
cwd: execPath,
|
||||||
|
env: {
|
||||||
|
...process.env, // 保留当前环境变量
|
||||||
|
...tokenEnv,
|
||||||
|
...setEnv,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
child.stdout.on('data', (data) => {
|
||||||
|
console.log(chalk.green(`${data}`));
|
||||||
|
});
|
||||||
|
child.stderr.on('data', (data) => {
|
||||||
|
// 过滤掉 'npm notice' 或者其他信息
|
||||||
|
if (data.toString().includes('npm notice')) {
|
||||||
|
console.log(chalk.yellow(`notice: ${data}`));
|
||||||
|
} else {
|
||||||
|
console.error(`stderr: ${data}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
child.on('close', (code) => {
|
||||||
|
// console.log(`child process exited with code ${code}`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red('package.json not found'));
|
||||||
|
}
|
||||||
|
}
|
||||||
const command = new Command('npm').description('npm command show publish and set .npmrc').action(async (options) => { });
|
const command = new Command('npm').description('npm command show publish and set .npmrc').action(async (options) => { });
|
||||||
const publish = new Command('publish')
|
const publish = new Command('publish')
|
||||||
.argument('[registry]')
|
.argument('[registry]')
|
||||||
.option('-p --proxy', 'proxy')
|
.option('-p --proxy', 'proxy')
|
||||||
.option('-t, --tag', 'tag')
|
.option('-t, --tag', 'tag')
|
||||||
|
.option('-u, --update', 'update new version')
|
||||||
.description('publish npm')
|
.description('publish npm')
|
||||||
.action(async (registry, options) => {
|
.action(async (registry, options) => {
|
||||||
if (!registry) {
|
if (!registry) {
|
||||||
@@ -26,8 +94,8 @@ const publish = new Command('publish')
|
|||||||
message: 'Select the registry to publish',
|
message: 'Select the registry to publish',
|
||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
name: 'me',
|
name: 'all',
|
||||||
value: 'me',
|
value: 'all',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'npm',
|
name: 'npm',
|
||||||
@@ -41,7 +109,6 @@ const publish = new Command('publish')
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
let cmd = '';
|
|
||||||
const execPath = process.cwd();
|
const execPath = process.cwd();
|
||||||
let setEnv = {};
|
let setEnv = {};
|
||||||
const proxyEnv = {
|
const proxyEnv = {
|
||||||
@@ -55,70 +122,15 @@ const publish = new Command('publish')
|
|||||||
...proxyEnv,
|
...proxyEnv,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (registry) {
|
if (options?.update) {
|
||||||
const packageJson = path.resolve(execPath, 'package.json');
|
patchFunc({ directory: execPath });
|
||||||
switch (registry) {
|
}
|
||||||
case 'me':
|
|
||||||
cmd = 'npm publish --registry https://npm.xiongxiao.me';
|
|
||||||
break;
|
|
||||||
case 'npm':
|
|
||||||
cmd = 'npm publish --registry https://registry.npmjs.org';
|
|
||||||
break;
|
|
||||||
case 'cnb':
|
|
||||||
cmd = 'npm publish --registry https://npm.cnb.cool/kevisual/registry/-/packages/';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cmd = 'npm publish --registry https://npm.xiongxiao.me';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (fileIsExist(packageJson)) {
|
|
||||||
const keys = Object.keys(config).filter((key) => key.includes('NPM_TOKEN'));
|
|
||||||
const tokenEnv = keys.reduce((prev, key) => {
|
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
[key]: config[key],
|
|
||||||
};
|
|
||||||
}, {});
|
|
||||||
const pkg = fs.readFileSync(packageJson, 'utf-8');
|
|
||||||
const pkgJson = parseIfJson(pkg);
|
|
||||||
const version = pkgJson?.version as string;
|
|
||||||
if (version && options?.tag) {
|
|
||||||
let tag = String(version).split('-')[1] || '';
|
|
||||||
if (tag) {
|
|
||||||
if (tag.includes('.')) {
|
|
||||||
tag = tag.split('.')[0];
|
|
||||||
}
|
|
||||||
cmd = `${cmd} --tag ${tag}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(chalk.green(cmd));
|
|
||||||
|
|
||||||
const child = spawn(cmd, {
|
if (registry === 'all') {
|
||||||
shell: true,
|
publishRegistry({ execPath, registry: 'npm', config, env: setEnv });
|
||||||
cwd: execPath,
|
publishRegistry({ execPath, registry: 'cnb', config, env: setEnv });
|
||||||
env: {
|
} else {
|
||||||
...process.env, // 保留当前环境变量
|
publishRegistry({ execPath, registry, tag: options?.tag, config, env: setEnv });
|
||||||
...tokenEnv,
|
|
||||||
...setEnv,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
child.stdout.on('data', (data) => {
|
|
||||||
console.log(chalk.green(`${data}`));
|
|
||||||
});
|
|
||||||
child.stderr.on('data', (data) => {
|
|
||||||
// 过滤掉 'npm notice' 或者其他信息
|
|
||||||
if (data.toString().includes('npm notice')) {
|
|
||||||
console.log(chalk.yellow(`notice: ${data}`));
|
|
||||||
} else {
|
|
||||||
console.error(`stderr: ${data}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
child.on('close', (code) => {
|
|
||||||
// console.log(`child process exited with code ${code}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(chalk.red('package.json not found'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -142,8 +154,7 @@ const npmrc = new Command('set')
|
|||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
const npmrcContent =
|
const npmrcContent =
|
||||||
config?.npmrc ||
|
config?.npmrc ||
|
||||||
`//npm.xiongxiao.me/:_authToken=\${ME_NPM_TOKEN}
|
`/npm.cnb.cool/kevisual/registry/-/packages/:_authToken=\${CNB_API_KEY}
|
||||||
//npm.cnb.cool/kevisual/registry/-/packages/:_authToken=\${CNB_API_KEY}
|
|
||||||
//registry.npmjs.org/:_authToken=\${NPM_TOKEN}
|
//registry.npmjs.org/:_authToken=\${NPM_TOKEN}
|
||||||
`;
|
`;
|
||||||
const execPath = process.cwd();
|
const execPath = process.cwd();
|
||||||
@@ -210,9 +221,8 @@ const install = new Command('install')
|
|||||||
});
|
});
|
||||||
command.addCommand(install);
|
command.addCommand(install);
|
||||||
|
|
||||||
// npm patch
|
const patchFunc = (opts?: { directory?: string }) => {
|
||||||
const patch = new Command('patch').description('npm patch 发布补丁版本').action(async () => {
|
const cwd = opts?.directory || process.cwd();
|
||||||
const cwd = process.cwd();
|
|
||||||
const packageJson = path.resolve(cwd, 'package.json');
|
const packageJson = path.resolve(cwd, 'package.json');
|
||||||
if (fileIsExist(packageJson)) {
|
if (fileIsExist(packageJson)) {
|
||||||
const pkg = fs.readFileSync(packageJson, 'utf-8');
|
const pkg = fs.readFileSync(packageJson, 'utf-8');
|
||||||
@@ -229,6 +239,10 @@ const patch = new Command('patch').description('npm patch 发布补丁版本').a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// npm patch
|
||||||
|
const patch = new Command('patch').description('npm patch 发布补丁版本').action(async () => {
|
||||||
|
patchFunc();
|
||||||
});
|
});
|
||||||
command.addCommand(patch);
|
command.addCommand(patch);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user