@vibe-forge/core 0.7.5 → 0.8.3

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.
Files changed (43) hide show
  1. package/package.json +4 -46
  2. package/src/env.ts +5 -25
  3. package/src/index.ts +0 -5
  4. package/src/types.ts +13 -72
  5. package/src/ws.ts +2 -12
  6. package/src/adapter/index.ts +0 -6
  7. package/src/adapter/loader.ts +0 -11
  8. package/src/adapter/type.ts +0 -117
  9. package/src/config/load.ts +0 -122
  10. package/src/config/types.ts +0 -289
  11. package/src/config.ts +0 -2
  12. package/src/controllers/benchmark/discover.ts +0 -89
  13. package/src/controllers/benchmark/index.ts +0 -24
  14. package/src/controllers/benchmark/result-store.ts +0 -46
  15. package/src/controllers/benchmark/runner.ts +0 -415
  16. package/src/controllers/benchmark/schema.ts +0 -60
  17. package/src/controllers/benchmark/types.ts +0 -80
  18. package/src/controllers/benchmark/utils.ts +0 -144
  19. package/src/controllers/benchmark/workspace.ts +0 -179
  20. package/src/controllers/config/index.ts +0 -214
  21. package/src/controllers/system/assets/completed.mp3 +0 -0
  22. package/src/controllers/system/assets/mcp.png +0 -0
  23. package/src/controllers/system/index.ts +0 -102
  24. package/src/controllers/task/generate-adapter-query-options.ts +0 -25
  25. package/src/controllers/task/index.ts +0 -2
  26. package/src/controllers/task/prepare.ts +0 -74
  27. package/src/controllers/task/run.ts +0 -231
  28. package/src/controllers/task/schema.ts +0 -131
  29. package/src/controllers/task/type.ts +0 -6
  30. package/src/hooks/bridge.ts +0 -368
  31. package/src/hooks/call.ts +0 -74
  32. package/src/hooks/index.ts +0 -41
  33. package/src/hooks/loader.ts +0 -79
  34. package/src/hooks/native.ts +0 -116
  35. package/src/hooks/runtime.ts +0 -139
  36. package/src/hooks/type.ts +0 -145
  37. package/src/utils/cache.ts +0 -58
  38. package/src/utils/create-logger.ts +0 -89
  39. package/src/utils/definition-loader.ts +0 -530
  40. package/src/utils/filter.ts +0 -26
  41. package/src/utils/string-transform.ts +0 -37
  42. package/src/utils/uuid.ts +0 -6
  43. package/src/utils/workspace-assets.ts +0 -919
@@ -1,139 +0,0 @@
1
- import { Buffer } from 'node:buffer'
2
- import process from 'node:process'
3
-
4
- import { loadConfig, resetConfigCache } from '#~/config/load.js'
5
- import { resolveServerLogLevel } from '#~/env.js'
6
- import { createLogger } from '#~/utils/create-logger.js'
7
- import { transformCamelKey } from '#~/utils/string-transform.js'
8
-
9
- import type { HookInput, HookInputs, HookOutputCore, HookOutputs } from './type'
10
- import type { HookContext, Plugin } from './index'
11
- import { resolvePlugins } from './loader'
12
-
13
- export const callPluginHook = async <K extends keyof HookInputs>(
14
- eventName: K,
15
- context: HookContext,
16
- input: HookInputs[K],
17
- plugins: Partial<Plugin>[] = []
18
- ): Promise<HookOutputs[K]> => {
19
- const { logger } = context
20
- const filteredPlugins = plugins.filter(
21
- (
22
- item
23
- ): item is
24
- & {
25
- name?: string
26
- }
27
- & {
28
- [P in K]: NonNullable<Plugin[P]>
29
- } => !!item && !!item[eventName]
30
- )
31
-
32
- let index = 0
33
-
34
- const next = async (): Promise<HookOutputs[K]> => {
35
- if (index >= filteredPlugins.length) {
36
- return { continue: true }
37
- }
38
-
39
- const currentPlugin = filteredPlugins[index]
40
- const { name = '<anonymous>', [eventName]: hook } = currentPlugin
41
- index++
42
-
43
- const withNameLogger = {
44
- ...logger,
45
- info: logger.info.bind(logger, `[plugin.${name}]`),
46
- warn: logger.warn.bind(logger, `[plugin.${name}]`),
47
- debug: logger.debug.bind(logger, `[plugin.${name}]`),
48
- error: logger.error.bind(logger, `[plugin.${name}]`)
49
- }
50
-
51
- try {
52
- return await hook(
53
- {
54
- ...context,
55
- logger: withNameLogger
56
- },
57
- input,
58
- next
59
- )
60
- } catch (error) {
61
- if (error instanceof Error && !error.name.includes('[plugin.')) {
62
- error.name = `${error.name}[plugin.${name}]`
63
- }
64
- throw error
65
- }
66
- }
67
-
68
- return next()
69
- }
70
-
71
- export const executeHookInput = async (
72
- input: HookInput,
73
- env: Record<string, string | null | undefined> = process.env
74
- ) => {
75
- const workspaceFolder = env.__VF_PROJECT_WORKSPACE_FOLDER__ ?? input.cwd ?? process.env.HOME ?? '/'
76
- const ctxId = env.__VF_PROJECT_AI_CTX_ID__ ?? input.sessionId ?? 'default'
77
- const logPrefix = env.__VF_PROJECT_AI_LOG_PREFIX__ ?? ''
78
- const loggerBase = createLogger(
79
- workspaceFolder,
80
- ctxId,
81
- input.sessionId,
82
- logPrefix,
83
- resolveServerLogLevel(env)
84
- )
85
-
86
- const logger: typeof loggerBase = {
87
- ...loggerBase,
88
- info: (...args) => loggerBase.info(`[${input.hookEventName}]`, ...args),
89
- warn: (...args) => loggerBase.warn(`[${input.hookEventName}]`, ...args),
90
- debug: (...args) => loggerBase.debug(`[${input.hookEventName}]`, ...args),
91
- error: (...args) => loggerBase.error(`[${input.hookEventName}]`, ...args)
92
- }
93
-
94
- resetConfigCache()
95
- const jsonVariables = {
96
- ...env,
97
- WORKSPACE_FOLDER: workspaceFolder,
98
- __VF_PROJECT_WORKSPACE_FOLDER__: workspaceFolder
99
- }
100
- const [config, userConfig] = await loadConfig({ jsonVariables })
101
- const plugins = [
102
- ...await resolvePlugins(config?.plugins ?? [], config?.enabledPlugins ?? {}),
103
- ...await resolvePlugins(userConfig?.plugins ?? [], userConfig?.enabledPlugins ?? {})
104
- ]
105
-
106
- return callPluginHook(
107
- input.hookEventName,
108
- { logger },
109
- input as HookInputs[typeof input.hookEventName],
110
- plugins
111
- )
112
- }
113
-
114
- export const readHookInput = async () => {
115
- const stdoutBuffer = await new Promise<Buffer>((resolve) => {
116
- const chunks: Buffer[] = []
117
- process.stdin.on('data', chunk => chunks.push(chunk))
118
- process.stdin.once('end', () => resolve(Buffer.concat(chunks)))
119
- })
120
-
121
- return transformCamelKey<HookInput>(
122
- JSON.parse(stdoutBuffer.toString() || '{}')
123
- )
124
- }
125
-
126
- export const runHookCli = async () => {
127
- try {
128
- const input = await readHookInput()
129
- const result = await executeHookInput(input)
130
- console.log(JSON.stringify(result))
131
- } catch (error) {
132
- console.log(
133
- JSON.stringify({
134
- continue: false,
135
- stopReason: `run hook error: ${String(error)}`
136
- } satisfies HookOutputCore)
137
- )
138
- }
139
- }
package/src/hooks/type.ts DELETED
@@ -1,145 +0,0 @@
1
- import type { AdapterQueryOptions } from '../adapter'
2
-
3
- export type HookSource = 'native' | 'bridge'
4
-
5
- export interface HookToolCall {
6
- toolCallId?: string
7
- toolName: string
8
- toolInput?: unknown
9
- }
10
-
11
- export interface HookToolResult extends HookToolCall {
12
- toolResponse?: unknown
13
- isError?: boolean
14
- }
15
-
16
- /**
17
- * https://docs.anthropic.com/en/docs/claude-code/hooks#hook-input
18
- */
19
- export interface HookInputCore {
20
- cwd: string
21
- sessionId: string
22
- hookEventName: keyof HookInputs
23
- adapter?: string
24
- runtime?: AdapterQueryOptions['runtime']
25
- hookSource?: HookSource
26
- canBlock?: boolean
27
- }
28
-
29
- export interface HookInputs {
30
- /**
31
- * https://docs.anthropic.com/en/docs/claude-code/hooks#pretooluse-input
32
- */
33
- PreToolUse: HookInputCore & HookToolCall
34
- /**
35
- * https://docs.anthropic.com/en/docs/claude-code/hooks#posttooluse-input
36
- */
37
- PostToolUse: HookInputCore & HookToolResult
38
- Notification: HookInputCore
39
- UserPromptSubmit: HookInputCore & { prompt: string }
40
- Stop: HookInputCore & {
41
- lastAssistantMessage?: string
42
- }
43
- SubagentStop: HookInputCore
44
- PreCompact: HookInputCore
45
- SessionStart: HookInputCore & {
46
- source?: 'startup' | 'resume'
47
- model?: string
48
- }
49
- SessionEnd: HookInputCore & {
50
- reason: string
51
- exitCode?: number
52
- stderr?: string
53
- lastAssistantMessage?: string
54
- }
55
-
56
- StartTasks: HookInputCore & {
57
- tasks: Array<{
58
- description: string
59
- type: 'default' | 'spec' | 'entity'
60
- name?: string
61
- adapter?: string
62
- background?: boolean
63
- }>
64
- }
65
- GenerateSystemPrompt: HookInputCore & {
66
- type?: 'spec' | 'entity'
67
- name?: string
68
- data?: unknown
69
- }
70
- TaskStart: HookInputCore & {
71
- adapter?: string
72
- options: unknown
73
- adapterOptions: unknown
74
- }
75
- TaskStop: HookInputCore & {
76
- exitCode?: number
77
- stderr?: string
78
- adapter?: string
79
-
80
- options: unknown
81
- adapterOptions: unknown
82
- }
83
- }
84
-
85
- export type HookInput = HookInputs[keyof HookInputs]
86
-
87
- /**
88
- * https://docs.anthropic.com/en/docs/claude-code/hooks#common-json-fields
89
- */
90
- export interface HookOutputCore {
91
- /**
92
- * Whether Claude should continue after hook execution
93
- * @default true
94
- */
95
- continue?: boolean
96
- /**
97
- * Message shown when continue is false
98
- */
99
- stopReason?: string
100
- /**
101
- * Hide stdout from transcript mode
102
- * @default false
103
- */
104
- suppressOutput?: boolean
105
- /**
106
- * Optional warning message shown to the user
107
- */
108
- systemMessage?: string
109
- }
110
-
111
- export interface HookOutputs {
112
- /**
113
- * https://docs.anthropic.com/en/docs/claude-code/hooks#pretooluse-decision-control
114
- */
115
- PreToolUse: HookOutputCore & {
116
- hookSpecificOutput?: {
117
- hookEventName: 'PreToolUse'
118
- permissionDecision: 'allow' | 'deny' | 'ask'
119
- permissionDecisionReason: string
120
- }
121
- }
122
- /**
123
- * https://docs.anthropic.com/en/docs/claude-code/hooks#posttooluse-decision-control
124
- */
125
- PostToolUse: HookOutputCore & {
126
- hookSpecificOutput?: {
127
- hookEventName: 'PostToolUse'
128
- additionalContext: string
129
- }
130
- }
131
- Notification: HookOutputCore
132
- UserPromptSubmit: HookOutputCore
133
- Stop: HookOutputCore
134
- SessionStart: HookOutputCore
135
- SessionEnd: HookOutputCore
136
- SubagentStop: HookOutputCore
137
- PreCompact: HookOutputCore
138
-
139
- StartTasks: HookOutputCore
140
- GenerateSystemPrompt: HookOutputCore
141
- TaskStart: HookOutputCore
142
- TaskStop: HookOutputCore
143
- }
144
-
145
- export type HookOutput = HookOutputs[keyof HookOutputs]
@@ -1,58 +0,0 @@
1
- import * as fs from 'node:fs/promises'
2
- import { dirname, resolve } from 'node:path'
3
-
4
- import type { Cache } from '@vibe-forge/core'
5
-
6
- declare module '@vibe-forge/core' {
7
- interface Cache {
8
- }
9
- }
10
-
11
- export const getCachePath = (
12
- cwd: string,
13
- taskId: string,
14
- sessionId: string | undefined,
15
- key: keyof Cache
16
- ) => {
17
- const taskDir = resolve(cwd, '.ai/caches', taskId)
18
- const cacheDir = sessionId ? resolve(taskDir, sessionId) : taskDir
19
- return resolve(cacheDir, `${key}.json`)
20
- }
21
-
22
- export const setCache = async <K extends keyof Cache>(
23
- cwd: string,
24
- taskId: string,
25
- sessionId: string | undefined,
26
- key: K,
27
- value: Cache[K]
28
- ) => {
29
- const cachePath = getCachePath(cwd, taskId, sessionId, key)
30
- const cacheDir = dirname(cachePath)
31
- try {
32
- await fs.access(cacheDir)
33
- } catch {
34
- await fs.mkdir(cacheDir, { recursive: true })
35
- }
36
- await fs.writeFile(cachePath, JSON.stringify(value, null, 2), {
37
- flag: 'w'
38
- })
39
- return { cachePath }
40
- }
41
-
42
- export const getCache = async <K extends keyof Cache>(
43
- cwd: string,
44
- taskId: string,
45
- sessionId: string | undefined,
46
- key: K
47
- ): Promise<Cache[K] | undefined> => {
48
- const cachePath = getCachePath(cwd, taskId, sessionId, key)
49
- try {
50
- await fs.access(cachePath)
51
- } catch (error) {
52
- if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
53
- return undefined
54
- }
55
- throw error
56
- }
57
- return JSON.parse(await fs.readFile(cachePath, 'utf-8'))
58
- }
@@ -1,89 +0,0 @@
1
- import { createWriteStream, existsSync, mkdirSync } from 'node:fs'
2
- import { dirname, resolve } from 'node:path'
3
-
4
- import type { LogLevel } from '#~/env.js'
5
-
6
- export interface Logger {
7
- stream: NodeJS.WritableStream
8
- info: (...args: unknown[]) => void
9
- warn: (...args: unknown[]) => void
10
- debug: (...args: unknown[]) => void
11
- error: (...args: unknown[]) => void
12
- }
13
-
14
- const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
15
- debug: 10,
16
- info: 20,
17
- warn: 30,
18
- error: 40
19
- }
20
-
21
- export const createLogger = (
22
- cwd: string,
23
- taskId: string,
24
- sessionId: string,
25
- logPrefix = '',
26
- level: LogLevel = 'info'
27
- ) => {
28
- const normalizedSessionId = sessionId ?? 'default'
29
- const taskDir = resolve(
30
- cwd,
31
- `.ai${logPrefix}/logs/${taskId}`
32
- )
33
-
34
- const loggerFilePath = resolve(
35
- taskDir,
36
- `${normalizedSessionId}.log.md`
37
- )
38
- // 默认日志文件不存在时,创建一个默认的日志文件
39
- if (!existsSync(loggerFilePath)) {
40
- mkdirSync(dirname(loggerFilePath), { recursive: true })
41
- }
42
- const loggerStream = createWriteStream(loggerFilePath, {
43
- flags: 'a'
44
- })
45
- const createLog = (tag: string, currentLevel: LogLevel) => (...args: unknown[]) => {
46
- if (LOG_LEVEL_PRIORITY[currentLevel] < LOG_LEVEL_PRIORITY[level]) {
47
- return
48
- }
49
- const msg = args
50
- .map((arg) => {
51
- if (typeof arg === 'string') {
52
- return arg
53
- }
54
- if (arg instanceof Error) {
55
- return (
56
- '\n```text\n' +
57
- `${arg.stack}\n` +
58
- '```'
59
- )
60
- }
61
- return (
62
- '\n```json\n' +
63
- `${JSON.stringify(arg, null, 2)}\n` +
64
- '```'
65
- )
66
- })
67
- .join(' ')
68
- const now = new Date().toLocaleString()
69
- if (loggerStream.writableEnded) {
70
- const tempLoggerStream = createWriteStream(loggerFilePath, {
71
- flags: 'a'
72
- })
73
- tempLoggerStream.write(
74
- `# [${now}] __E__ UNEXPECTED LOGGER STREAM ENDED\n`
75
- )
76
- tempLoggerStream.write(`# [${now}] __${tag}__ ${msg}\n`)
77
- tempLoggerStream.end()
78
- return
79
- }
80
- loggerStream.write(`# [${now}] __${tag}__ ${msg}\n`)
81
- }
82
- return {
83
- stream: loggerStream,
84
- info: createLog('I', 'info'),
85
- warn: createLog('W', 'warn'),
86
- debug: createLog('D', 'debug'),
87
- error: createLog('E', 'error')
88
- }
89
- }