agentworkshop 0.2.2 → 0.4.0
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/LICENSE +91 -0
- package/README-zh.md +431 -424
- package/README.md +10 -3
- package/app/components/AppSidebar.vue +1 -0
- package/app/pages/plugins/index.vue +258 -0
- package/app/plugins/aw-plugins.client.ts +81 -48
- package/cli/commands/plugin.mjs +57 -7
- package/docs/plugins.md +133 -63
- package/docs/sdk.md +265 -0
- package/i18n/locales/en.ts +17 -0
- package/i18n/locales/zh-CN.ts +17 -0
- package/package.json +19 -2
- package/scripts/_dbg-docs-site-shot.mjs +33 -0
- package/scripts/dev-guard.mjs +13 -0
- package/scripts/home-bootstrap.mjs +26 -1
- package/sdk/api.mjs +101 -0
- package/sdk/client.mjs +56 -8
- package/sdk/context.mjs +56 -15
- package/sdk/examples/line-sentinel/client.mjs +31 -0
- package/sdk/examples/line-sentinel/index.mjs +102 -0
- package/sdk/examples/ops-notifier/client.mjs +23 -0
- package/sdk/examples/ops-notifier/index.mjs +34 -0
- package/sdk/index.d.mts +135 -0
- package/sdk/index.mjs +5 -18
- package/sdk/lifecycle.mjs +25 -0
- package/server/api/plugins/[name]/[...path].ts +5 -2
- package/server/api/workshop/plugins/[name]/disable.post.ts +19 -0
- package/server/api/workshop/plugins/[name]/enable.post.ts +19 -0
- package/server/api/workshop/plugins/[name]/index.get.ts +14 -0
- package/server/api/workshop/plugins/index.get.ts +17 -0
- package/server/data/daqs.json +260 -62
- package/server/data/dcw-lines.json +63 -0
- package/server/data/dcw-products.json +49 -0
- package/server/data/dcw-recipes.json +140 -0
- package/server/data/dcw-rollback.json +1 -1
- package/server/data/dcw-runs.json +175 -126
- package/server/data/dcws.json +147 -0
- package/server/data/line-runs.json +85 -15
- package/server/plugins/aw-plugins.ts +7 -1
- package/server/services/workshop/plugins/host.mjs +212 -18
package/sdk/index.d.mts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// AgentWorkShop SDK 类型声明(agentworkshop/sdk)
|
|
2
|
+
import type { HookBus } from './hooks.mjs'
|
|
3
|
+
|
|
4
|
+
export declare const SDK_VERSION: string
|
|
5
|
+
|
|
6
|
+
/** 生命周期钩子总线:异步串行、错误隔离、'*' 通配、连续失败自动熔断 */
|
|
7
|
+
export declare class HookBus {
|
|
8
|
+
constructor(opts?: { name?: string, onError?: (err: Error, meta?: { bus?: string, type?: string, fails?: number }) => void })
|
|
9
|
+
on(type: string, fn: (payload: any) => any): () => void
|
|
10
|
+
once(type: string, fn: (payload: any) => any): () => void
|
|
11
|
+
off(type: string, fn: (payload: any) => any): void
|
|
12
|
+
emit(type: string, payload?: any): Promise<any>
|
|
13
|
+
readonly size: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface PluginLogger {
|
|
17
|
+
debug(...args: unknown[]): void
|
|
18
|
+
info(...args: unknown[]): void
|
|
19
|
+
warn(...args: unknown[]): void
|
|
20
|
+
error(...args: unknown[]): void
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PluginKv {
|
|
24
|
+
get(key: string): any
|
|
25
|
+
set(key: string, value: any): any
|
|
26
|
+
all(): Record<string, any>
|
|
27
|
+
bump(key: string, by?: number): number
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface PluginHttp {
|
|
31
|
+
get(url: string, opts?: { timeoutMs?: number, headers?: Record<string, string> }): Promise<Response>
|
|
32
|
+
post(url: string, body?: unknown, opts?: { timeoutMs?: number, headers?: Record<string, string> }): Promise<Response>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** 平台 REST 客户端(SDK 作为项目服务 client 的门面) */
|
|
36
|
+
export interface PlatformClient {
|
|
37
|
+
call<T = any>(method: string, path: string, body?: unknown): Promise<T>
|
|
38
|
+
get<T = any>(path: string, query?: Record<string, unknown>): Promise<T>
|
|
39
|
+
post<T = any>(path: string, body?: unknown): Promise<T>
|
|
40
|
+
patch<T = any>(path: string, body?: unknown): Promise<T>
|
|
41
|
+
delete<T = any>(path: string): Promise<T>
|
|
42
|
+
setToken(token: string | null): PlatformClient
|
|
43
|
+
ping(): Promise<any>
|
|
44
|
+
users: { list(q?: any): Promise<any>, get(id: string): Promise<any>, create(b: any): Promise<any>, login(email: string, password: string): Promise<any>, me(): Promise<any> }
|
|
45
|
+
lines: { list(q?: any): Promise<any>, get(id: string): Promise<any>, create(b: any): Promise<any>, update(id: string, p: any): Promise<any>, remove(id: string): Promise<any>, start(id: string, recipeId?: string): Promise<any>, stop(id: string): Promise<any> }
|
|
46
|
+
products: { list(q?: any): Promise<any>, create(b: any): Promise<any> }
|
|
47
|
+
recipes: { list(q?: any): Promise<any>, create(b: any): Promise<any> }
|
|
48
|
+
dcwNodes: { list(q?: any): Promise<any>, create(b: any): Promise<any> }
|
|
49
|
+
daqNodes: { list(q?: any): Promise<any>, create(b: any): Promise<any>, alarms(): Promise<any> }
|
|
50
|
+
templates: { daq(): Promise<any[]>, dcw(): Promise<any[]> }
|
|
51
|
+
twins: { list(q?: any): Promise<any>, create(b: any): Promise<any> }
|
|
52
|
+
teams: { list(q?: any): Promise<any>, create(b: any): Promise<any> }
|
|
53
|
+
agents: { list(q?: any): Promise<any>, create(b: any): Promise<any> }
|
|
54
|
+
channels: { list(q?: any): Promise<any> }
|
|
55
|
+
plugins: { manifest(): Promise<any> }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface PluginContext {
|
|
59
|
+
name: string
|
|
60
|
+
scope: 'project' | 'user'
|
|
61
|
+
dir: string
|
|
62
|
+
sdkVersion: string
|
|
63
|
+
hooks: HookBus
|
|
64
|
+
logger: PluginLogger
|
|
65
|
+
config: {
|
|
66
|
+
get(key: string): any
|
|
67
|
+
all(): Record<string, any>
|
|
68
|
+
onChange(fn: (payload?: { at: string }) => any): () => void
|
|
69
|
+
}
|
|
70
|
+
paths: { home: string, configRoot: string, dataDir: string }
|
|
71
|
+
dataDir: string
|
|
72
|
+
kv: PluginKv
|
|
73
|
+
timer: {
|
|
74
|
+
setInterval(fn: (...args: any[]) => void, ms: number, ...rest: any[]): NodeJS.Timeout
|
|
75
|
+
setTimeout(fn: (...args: any[]) => void, ms: number, ...rest: any[]): NodeJS.Timeout
|
|
76
|
+
}
|
|
77
|
+
onDispose(fn: () => any): () => void
|
|
78
|
+
subscriptions: { add(d: { dispose(): any } | (() => any)): any }
|
|
79
|
+
route(method: string, path: string, handler: (event: any) => any): boolean
|
|
80
|
+
api: PlatformClient
|
|
81
|
+
http: PluginHttp
|
|
82
|
+
events: { on(type: string, fn: (payload: any) => any): () => void, off(type: string, fn: (payload: any) => any): void }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface PluginRouteDef {
|
|
86
|
+
method?: string
|
|
87
|
+
path: string
|
|
88
|
+
handler: (event: any) => any
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface PluginDef {
|
|
92
|
+
name: string
|
|
93
|
+
version?: string
|
|
94
|
+
description?: string
|
|
95
|
+
setup?(ctx: PluginContext): void | Promise<void>
|
|
96
|
+
client?: string
|
|
97
|
+
routes?: PluginRouteDef[]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** 显式糖:类型化定义插件(宿主同样接受裸对象导出) */
|
|
101
|
+
export declare function definePlugin(def: PluginDef): PluginDef
|
|
102
|
+
|
|
103
|
+
export declare function createPluginContext(opts: Record<string, any>): PluginContext
|
|
104
|
+
export declare function createRouteTable(): {
|
|
105
|
+
register(name: string, method: string, path: string, handler: (event: any) => any): boolean
|
|
106
|
+
resolve(name: string, method: string, path: string): ((event: any) => any) | null
|
|
107
|
+
byPlugin(name: string): Array<{ method: string, path: string }>
|
|
108
|
+
readonly size: number
|
|
109
|
+
}
|
|
110
|
+
export declare function validatePluginModule(mod: any, source: string): { ok: boolean, def?: PluginDef, error?: string }
|
|
111
|
+
export declare function pluginKvExists(dataDir: string, name: string): boolean
|
|
112
|
+
|
|
113
|
+
export declare function createPlatformClient(opts?: { baseUrl?: string, token?: string, logger?: PluginLogger, timeoutMs?: number }): PlatformClient
|
|
114
|
+
|
|
115
|
+
export declare const LIFECYCLE_EVENTS: readonly ['plugin:host:init', 'config:changed', 'event:*', 'daq:sample', 'dcw:write', 'line:start', 'line:stop', 'server:close']
|
|
116
|
+
export declare const CLIENT_EVENTS: readonly ['client:init', 'event:*', 'page:change', 'client:destroy']
|
|
117
|
+
|
|
118
|
+
/** 客户端插件上下文(sdk/client.mjs) */
|
|
119
|
+
export declare const CLIENT_SDK_VERSION: string
|
|
120
|
+
export interface ClientContext {
|
|
121
|
+
name: string
|
|
122
|
+
sdkVersion: string
|
|
123
|
+
hooks: HookBus
|
|
124
|
+
on(type: string, fn: (payload: any) => any): () => void
|
|
125
|
+
fetch<T = any>(path: string, opt?: { method?: string, body?: unknown, headers?: Record<string, string> }): Promise<T>
|
|
126
|
+
el(tag: string, attrs?: Record<string, unknown>, children?: Array<Node | string>): HTMLElement
|
|
127
|
+
mount(target: string | Element, node: Node): Node
|
|
128
|
+
root(): HTMLElement
|
|
129
|
+
log: PluginLogger
|
|
130
|
+
dispose(): void
|
|
131
|
+
}
|
|
132
|
+
export declare function createClientContext(opts: { name: string, eventBridge?: (fn: (type: string, payload: any) => void) => (() => void), baseUrl?: string }): ClientContext
|
|
133
|
+
|
|
134
|
+
declare const _default: Record<string, unknown>
|
|
135
|
+
export default _default
|
package/sdk/index.mjs
CHANGED
|
@@ -15,29 +15,15 @@
|
|
|
15
15
|
// ============================================================
|
|
16
16
|
import { SDK_VERSION, definePlugin, createPluginContext, createRouteTable, validatePluginModule, pluginKvExists } from './context.mjs'
|
|
17
17
|
import { HookBus } from './hooks.mjs'
|
|
18
|
+
import { createPlatformClient } from './api.mjs'
|
|
18
19
|
import { CLIENT_SDK_VERSION, createClientContext } from './client.mjs'
|
|
20
|
+
import { LIFECYCLE_EVENTS, CLIENT_EVENTS } from './lifecycle.mjs'
|
|
19
21
|
|
|
20
22
|
export { SDK_VERSION, definePlugin, createPluginContext, createRouteTable, validatePluginModule, pluginKvExists } from './context.mjs'
|
|
21
23
|
export { HookBus } from './hooks.mjs'
|
|
24
|
+
export { createPlatformClient } from './api.mjs'
|
|
22
25
|
export { CLIENT_SDK_VERSION, createClientContext } from './client.mjs'
|
|
23
|
-
|
|
24
|
-
/** 服务端生命周期事件清单(宿主触发;文档见 docs/plugins.md) */
|
|
25
|
-
export const LIFECYCLE_EVENTS = Object.freeze([
|
|
26
|
-
'plugin:host:init',
|
|
27
|
-
'event:*',
|
|
28
|
-
'daq:sample',
|
|
29
|
-
'dcw:write',
|
|
30
|
-
'line:start',
|
|
31
|
-
'line:stop',
|
|
32
|
-
'server:close',
|
|
33
|
-
])
|
|
34
|
-
|
|
35
|
-
/** 客户端生命周期事件清单 */
|
|
36
|
-
export const CLIENT_EVENTS = Object.freeze([
|
|
37
|
-
'client:init',
|
|
38
|
-
'event:*',
|
|
39
|
-
'page:change',
|
|
40
|
-
])
|
|
26
|
+
export { LIFECYCLE_EVENTS, CLIENT_EVENTS } from './lifecycle.mjs'
|
|
41
27
|
|
|
42
28
|
export default {
|
|
43
29
|
SDK_VERSION,
|
|
@@ -47,6 +33,7 @@ export default {
|
|
|
47
33
|
createRouteTable,
|
|
48
34
|
validatePluginModule,
|
|
49
35
|
pluginKvExists,
|
|
36
|
+
createPlatformClient,
|
|
50
37
|
CLIENT_SDK_VERSION,
|
|
51
38
|
createClientContext,
|
|
52
39
|
LIFECYCLE_EVENTS,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// AgentWorkShop SDK — 生命周期事件清单(宿主触发;单一事实源)
|
|
3
|
+
// ============================================================
|
|
4
|
+
|
|
5
|
+
/** 服务端生命周期事件清单(宿主触发;文档见 docs/plugins.md) */
|
|
6
|
+
export const LIFECYCLE_EVENTS = Object.freeze([
|
|
7
|
+
'plugin:host:init',
|
|
8
|
+
'config:changed',
|
|
9
|
+
'event:*',
|
|
10
|
+
'daq:sample',
|
|
11
|
+
'dcw:write',
|
|
12
|
+
'line:start',
|
|
13
|
+
'line:stop',
|
|
14
|
+
'server:close',
|
|
15
|
+
])
|
|
16
|
+
|
|
17
|
+
/** 客户端生命周期事件清单 */
|
|
18
|
+
export const CLIENT_EVENTS = Object.freeze([
|
|
19
|
+
'client:init',
|
|
20
|
+
'event:*',
|
|
21
|
+
'page:change',
|
|
22
|
+
'client:destroy',
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
export default { LIFECYCLE_EVENTS, CLIENT_EVENTS }
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* 插件经 ctx.route(method, path, handler) 注册;handler(event) 返回值由 nitro 序列化。
|
|
4
4
|
* 鉴权由插件自行处理(v1 不强制;可经 resolveUser 复用业务鉴权)。
|
|
5
5
|
*/
|
|
6
|
-
import { defineEventHandler, createError } from 'h3'
|
|
6
|
+
import { defineEventHandler, createError, readBody } from 'h3'
|
|
7
7
|
import { getPluginHost } from '@/server/services/workshop/plugins/host.mjs'
|
|
8
8
|
|
|
9
|
-
export default defineEventHandler((event) => {
|
|
9
|
+
export default defineEventHandler(async (event) => {
|
|
10
10
|
const host = getPluginHost()
|
|
11
11
|
if (!host) throw createError({ statusCode: 503, statusMessage: 'plugin host not ready' })
|
|
12
12
|
const name = String(event.context.params?.name ?? '')
|
|
@@ -15,5 +15,8 @@ export default defineEventHandler((event) => {
|
|
|
15
15
|
if (!handler) {
|
|
16
16
|
throw createError({ statusCode: 404, statusMessage: `plugin route not found: ${event.method} /api/plugins/${name}${path}` })
|
|
17
17
|
}
|
|
18
|
+
// 预读 body 挂到 event(插件 handler 无 h3 导入能力,经 event.awBody 消费)
|
|
19
|
+
const awBody = await readBody(event).catch(() => undefined)
|
|
20
|
+
;(event as Record<string, unknown>).awBody = awBody
|
|
18
21
|
return handler(event)
|
|
19
22
|
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/plugins/:name/disable —— 停用插件(admin;热重载生效)。
|
|
3
|
+
*/
|
|
4
|
+
import { defineEventHandler, createError } from 'h3'
|
|
5
|
+
import { resolveUser, requireAdmin } from '@/server/api/workshop/caller'
|
|
6
|
+
import { pluginManifest, reloadPluginHost, setPluginEnabled } from '@/server/services/workshop/plugins/host.mjs'
|
|
7
|
+
|
|
8
|
+
export default defineEventHandler(async (event) => {
|
|
9
|
+
const user = resolveUser(event)
|
|
10
|
+
requireAdmin(event)
|
|
11
|
+
const name = String(event.context.params?.name ?? '')
|
|
12
|
+
if (!pluginManifest().some(p => p.name === name)) {
|
|
13
|
+
throw createError({ statusCode: 404, statusMessage: `plugin not found: ${name}` })
|
|
14
|
+
}
|
|
15
|
+
setPluginEnabled(name, false)
|
|
16
|
+
await reloadPluginHost()
|
|
17
|
+
const p = pluginManifest().find(x => x.name === name)
|
|
18
|
+
return { ok: true, enabled: p?.enabled ?? false, by: user.name }
|
|
19
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/plugins/:name/enable —— 启用插件(admin;热重载生效)。
|
|
3
|
+
*/
|
|
4
|
+
import { defineEventHandler, createError } from 'h3'
|
|
5
|
+
import { resolveUser, requireAdmin } from '@/server/api/workshop/caller'
|
|
6
|
+
import { pluginManifest, reloadPluginHost, setPluginEnabled } from '@/server/services/workshop/plugins/host.mjs'
|
|
7
|
+
|
|
8
|
+
export default defineEventHandler(async (event) => {
|
|
9
|
+
const user = resolveUser(event)
|
|
10
|
+
requireAdmin(event)
|
|
11
|
+
const name = String(event.context.params?.name ?? '')
|
|
12
|
+
if (!pluginManifest().some(p => p.name === name)) {
|
|
13
|
+
throw createError({ statusCode: 404, statusMessage: `plugin not found: ${name}` })
|
|
14
|
+
}
|
|
15
|
+
setPluginEnabled(name, true)
|
|
16
|
+
await reloadPluginHost()
|
|
17
|
+
const p = pluginManifest().find(x => x.name === name)
|
|
18
|
+
return { ok: true, enabled: p?.enabled ?? true, by: user.name }
|
|
19
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/workshop/plugins/:name —— 单插件详情(鉴权)。
|
|
3
|
+
*/
|
|
4
|
+
import { defineEventHandler, createError } from 'h3'
|
|
5
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
6
|
+
import { pluginManifest } from '@/server/services/workshop/plugins/host.mjs'
|
|
7
|
+
|
|
8
|
+
export default defineEventHandler((event) => {
|
|
9
|
+
resolveUser(event)
|
|
10
|
+
const name = String(event.context.params?.name ?? '')
|
|
11
|
+
const p = pluginManifest().find(x => x.name === name)
|
|
12
|
+
if (!p) throw createError({ statusCode: 404, statusMessage: `plugin not found: ${name}` })
|
|
13
|
+
return p
|
|
14
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/workshop/plugins —— 插件管理清单(鉴权;含启停状态/路由/装载失败)。
|
|
3
|
+
* 网页「插件管理」页数据源。
|
|
4
|
+
*/
|
|
5
|
+
import { defineEventHandler } from 'h3'
|
|
6
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
7
|
+
import { getPluginHost, pluginManifest } from '@/server/services/workshop/plugins/host.mjs'
|
|
8
|
+
|
|
9
|
+
export default defineEventHandler((event) => {
|
|
10
|
+
resolveUser(event)
|
|
11
|
+
const host = getPluginHost()
|
|
12
|
+
return {
|
|
13
|
+
plugins: pluginManifest(),
|
|
14
|
+
failures: host?.failures ?? [],
|
|
15
|
+
initedAt: host?.initedAt ?? null,
|
|
16
|
+
}
|
|
17
|
+
})
|