@vibe-forge/core 0.6.0 → 0.7.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/package.json +1 -1
- package/src/adapter/index.ts +1 -1
- package/src/adapter/loader.ts +5 -3
- package/src/adapter/type.ts +1 -6
- package/src/controllers/task/prepare.ts +9 -1
- package/src/controllers/task/run.ts +3 -1
- package/src/env.ts +31 -3
- package/src/hooks/call.ts +74 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/runtime.ts +139 -0
- package/src/utils/create-logger.ts +26 -11
- package/src/utils/api.ts +0 -32
package/package.json
CHANGED
package/src/adapter/index.ts
CHANGED
package/src/adapter/loader.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Adapter } from './type'
|
|
2
2
|
|
|
3
|
+
const resolveAdapterPackageName = (type: string) => (
|
|
4
|
+
type.startsWith('@') ? type : `@vibe-forge/adapter-${type}`
|
|
5
|
+
)
|
|
6
|
+
|
|
3
7
|
export const loadAdapter = async (type: string) =>
|
|
4
8
|
(
|
|
5
9
|
// eslint-disable-next-line ts/no-require-imports
|
|
6
|
-
require(
|
|
7
|
-
type.startsWith('@') ? type : `@vibe-forge/adapter-${type}`
|
|
8
|
-
)
|
|
10
|
+
require(resolveAdapterPackageName(type))
|
|
9
11
|
).default as Adapter
|
package/src/adapter/type.ts
CHANGED
|
@@ -87,10 +87,6 @@ export interface AdapterQueryOptions {
|
|
|
87
87
|
onEvent: (event: AdapterOutputEvent) => void
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
export interface AdapterInitOptions {
|
|
91
|
-
force?: boolean
|
|
92
|
-
}
|
|
93
|
-
|
|
94
90
|
export interface AdapterSession {
|
|
95
91
|
kill: () => void
|
|
96
92
|
emit: (event: AdapterEvent) => void
|
|
@@ -99,8 +95,7 @@ export interface AdapterSession {
|
|
|
99
95
|
|
|
100
96
|
export interface Adapter {
|
|
101
97
|
init?: (
|
|
102
|
-
ctx: AdapterCtx
|
|
103
|
-
options: AdapterInitOptions
|
|
98
|
+
ctx: AdapterCtx
|
|
104
99
|
) => Promise<void>
|
|
105
100
|
query: (
|
|
106
101
|
ctx: AdapterCtx,
|
|
@@ -6,6 +6,8 @@ import { getCache, setCache } from '@vibe-forge/core/utils/cache'
|
|
|
6
6
|
import { createLogger } from '@vibe-forge/core/utils/create-logger'
|
|
7
7
|
import { uuid } from '@vibe-forge/core/utils/uuid'
|
|
8
8
|
|
|
9
|
+
import { resolveServerLogLevel } from '#~/env.js'
|
|
10
|
+
|
|
9
11
|
import type { RunTaskOptions } from './type'
|
|
10
12
|
|
|
11
13
|
export const prepare = async (
|
|
@@ -36,7 +38,13 @@ export const prepare = async (
|
|
|
36
38
|
// 移除 NODE_OPTIONS 环境变量,防止干扰子进程的运行环境
|
|
37
39
|
NODE_OPTIONS: undefined
|
|
38
40
|
}
|
|
39
|
-
const logger = createLogger(
|
|
41
|
+
const logger = createLogger(
|
|
42
|
+
cwd,
|
|
43
|
+
ctxId,
|
|
44
|
+
sessionId,
|
|
45
|
+
env?.LOG_PREFIX ?? '',
|
|
46
|
+
resolveServerLogLevel(env)
|
|
47
|
+
)
|
|
40
48
|
|
|
41
49
|
const jsonVariables: Record<string, string | null | undefined> = {
|
|
42
50
|
...env,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AdapterCtx, AdapterOutputEvent, AdapterQueryOptions } from '#~/adapter/index.js'
|
|
2
2
|
import { loadAdapter } from '#~/adapter/index.js'
|
|
3
3
|
import type { ModelServiceConfig } from '#~/config.js'
|
|
4
|
+
import { callHook } from '#~/hooks/call.js'
|
|
4
5
|
import type { TaskDetail } from '#~/types.js'
|
|
5
|
-
import { callHook } from '#~/utils/api.js'
|
|
6
6
|
|
|
7
7
|
import { prepare } from './prepare'
|
|
8
8
|
import type { RunTaskOptions } from './type'
|
|
@@ -162,6 +162,8 @@ export const run = async (
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
const adapter = await loadAdapter(adapterType)
|
|
165
|
+
await adapter.init?.(ctx)
|
|
166
|
+
|
|
165
167
|
const resolvedModel = resolveQueryModel({
|
|
166
168
|
config,
|
|
167
169
|
userConfig,
|
package/src/env.ts
CHANGED
|
@@ -1,18 +1,45 @@
|
|
|
1
1
|
import { env as processEnv } from 'node:process'
|
|
2
2
|
|
|
3
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
|
4
|
+
|
|
3
5
|
export interface ServerEnv {
|
|
4
6
|
__VF_PROJECT_AI_SERVER_HOST__: string
|
|
5
7
|
__VF_PROJECT_AI_SERVER_PORT__: number
|
|
6
8
|
__VF_PROJECT_AI_SERVER_WS_PATH__: string
|
|
7
9
|
__VF_PROJECT_AI_SERVER_DATA_DIR__: string
|
|
8
10
|
__VF_PROJECT_AI_SERVER_LOG_DIR__: string
|
|
9
|
-
__VF_PROJECT_AI_SERVER_LOG_LEVEL__:
|
|
11
|
+
__VF_PROJECT_AI_SERVER_LOG_LEVEL__: LogLevel
|
|
12
|
+
__VF_PROJECT_AI_SERVER_DEBUG__: boolean
|
|
10
13
|
__VF_PROJECT_AI_SERVER_ALLOW_CORS__: boolean
|
|
11
14
|
__VF_PROJECT_AI_CLIENT_MODE__?: 'dev' | 'static'
|
|
12
15
|
__VF_PROJECT_AI_CLIENT_BASE__?: string
|
|
13
16
|
__VF_PROJECT_AI_CLIENT_DIST_PATH__?: string
|
|
14
17
|
}
|
|
15
18
|
|
|
19
|
+
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'] as const satisfies readonly LogLevel[]
|
|
20
|
+
|
|
21
|
+
export function normalizeLogLevel(value: unknown): LogLevel | undefined {
|
|
22
|
+
if (typeof value !== 'string') return undefined
|
|
23
|
+
const normalized = value.trim().toLowerCase()
|
|
24
|
+
return LOG_LEVELS.includes(normalized as LogLevel)
|
|
25
|
+
? normalized as LogLevel
|
|
26
|
+
: undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function resolveServerLogLevel(
|
|
30
|
+
env: {
|
|
31
|
+
__VF_PROJECT_AI_SERVER_LOG_LEVEL__?: unknown
|
|
32
|
+
__VF_PROJECT_AI_SERVER_DEBUG__?: unknown
|
|
33
|
+
},
|
|
34
|
+
fallback: LogLevel = 'info'
|
|
35
|
+
): LogLevel {
|
|
36
|
+
if (env.__VF_PROJECT_AI_SERVER_DEBUG__ === true || env.__VF_PROJECT_AI_SERVER_DEBUG__ === 'true') {
|
|
37
|
+
return 'debug'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return normalizeLogLevel(env.__VF_PROJECT_AI_SERVER_LOG_LEVEL__) ?? fallback
|
|
41
|
+
}
|
|
42
|
+
|
|
16
43
|
export function loadEnv(): ServerEnv {
|
|
17
44
|
const {
|
|
18
45
|
__VF_PROJECT_AI_SERVER_HOST__ = 'localhost',
|
|
@@ -21,6 +48,7 @@ export function loadEnv(): ServerEnv {
|
|
|
21
48
|
__VF_PROJECT_AI_SERVER_DATA_DIR__ = '.data',
|
|
22
49
|
__VF_PROJECT_AI_SERVER_LOG_DIR__ = '.logs',
|
|
23
50
|
__VF_PROJECT_AI_SERVER_LOG_LEVEL__ = 'info',
|
|
51
|
+
__VF_PROJECT_AI_SERVER_DEBUG__,
|
|
24
52
|
__VF_PROJECT_AI_SERVER_ALLOW_CORS__,
|
|
25
53
|
__VF_PROJECT_AI_CLIENT_MODE__ = 'static',
|
|
26
54
|
__VF_PROJECT_AI_CLIENT_BASE__,
|
|
@@ -32,8 +60,8 @@ export function loadEnv(): ServerEnv {
|
|
|
32
60
|
__VF_PROJECT_AI_SERVER_WS_PATH__,
|
|
33
61
|
__VF_PROJECT_AI_SERVER_DATA_DIR__,
|
|
34
62
|
__VF_PROJECT_AI_SERVER_LOG_DIR__,
|
|
35
|
-
__VF_PROJECT_AI_SERVER_LOG_LEVEL__:
|
|
36
|
-
|
|
63
|
+
__VF_PROJECT_AI_SERVER_LOG_LEVEL__: normalizeLogLevel(__VF_PROJECT_AI_SERVER_LOG_LEVEL__) ?? 'info',
|
|
64
|
+
__VF_PROJECT_AI_SERVER_DEBUG__: __VF_PROJECT_AI_SERVER_DEBUG__ === 'true',
|
|
37
65
|
__VF_PROJECT_AI_SERVER_ALLOW_CORS__: __VF_PROJECT_AI_SERVER_ALLOW_CORS__ != null
|
|
38
66
|
? __VF_PROJECT_AI_SERVER_ALLOW_CORS__ === 'true'
|
|
39
67
|
: true,
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer'
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
|
|
6
|
+
import type { HookInputs, HookOutputs } from './type'
|
|
7
|
+
|
|
8
|
+
export type HookEventName = keyof HookInputs
|
|
9
|
+
|
|
10
|
+
type HookInputPayload<K extends HookEventName> = Omit<HookInputs[K], 'hookEventName'>
|
|
11
|
+
|
|
12
|
+
const pickHookEnv = (env: Record<string, unknown>): Record<string, string> => {
|
|
13
|
+
const result: Record<string, string> = {}
|
|
14
|
+
for (const [key, value] of Object.entries(env)) {
|
|
15
|
+
if (typeof value === 'string') {
|
|
16
|
+
result[key] = value
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return result
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const resolveHookCliJs = () => {
|
|
23
|
+
try {
|
|
24
|
+
const pkgJsonPath = require.resolve('@vibe-forge/cli/package.json')
|
|
25
|
+
return path.resolve(path.dirname(pkgJsonPath), 'call-hook.js')
|
|
26
|
+
} catch (error) {
|
|
27
|
+
throw new Error('Failed to resolve @vibe-forge/cli hook entry', { cause: error })
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const callHook = async <K extends HookEventName>(
|
|
32
|
+
hookEventName: K,
|
|
33
|
+
input: HookInputPayload<K>,
|
|
34
|
+
env: Record<string, unknown> = process.env
|
|
35
|
+
): Promise<HookOutputs[K]> => {
|
|
36
|
+
const childEnv = pickHookEnv(env)
|
|
37
|
+
const child = spawn(process.execPath, [resolveHookCliJs()], {
|
|
38
|
+
cwd: typeof input.cwd === 'string' ? input.cwd : process.cwd(),
|
|
39
|
+
env: childEnv,
|
|
40
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const stdoutChunks: Buffer[] = []
|
|
44
|
+
const stderrChunks: Buffer[] = []
|
|
45
|
+
|
|
46
|
+
child.stdout.on('data', chunk => stdoutChunks.push(chunk))
|
|
47
|
+
child.stderr.on('data', chunk => stderrChunks.push(chunk))
|
|
48
|
+
|
|
49
|
+
const exitCode = await new Promise<number>((resolve, reject) => {
|
|
50
|
+
child.once('error', reject)
|
|
51
|
+
child.once('close', code => resolve(code ?? 0))
|
|
52
|
+
child.stdin.end(JSON.stringify({
|
|
53
|
+
...input,
|
|
54
|
+
hookEventName
|
|
55
|
+
}))
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const stdout = Buffer.concat(stdoutChunks).toString('utf-8').trim()
|
|
59
|
+
const stderr = Buffer.concat(stderrChunks).toString('utf-8').trim()
|
|
60
|
+
|
|
61
|
+
if (exitCode !== 0) {
|
|
62
|
+
throw new Error(`Failed to call hook: process exited with code ${exitCode}${stderr ? ` - ${stderr}` : ''}`)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (stdout === '') {
|
|
66
|
+
return { continue: true } as HookOutputs[K]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
return JSON.parse(stdout) as HookOutputs[K]
|
|
71
|
+
} catch (error) {
|
|
72
|
+
throw new Error(`Failed to parse hook output: ${stdout}${stderr ? `\nstderr: ${stderr}` : ''}`, { cause: error })
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,139 @@
|
|
|
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 ?? []),
|
|
103
|
+
...await resolvePlugins(userConfig?.plugins ?? [])
|
|
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
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createWriteStream, existsSync, mkdirSync } from 'node:fs'
|
|
2
2
|
import { dirname, resolve } from 'node:path'
|
|
3
3
|
|
|
4
|
+
import type { LogLevel } from '#~/env.js'
|
|
5
|
+
|
|
4
6
|
export interface Logger {
|
|
5
7
|
stream: NodeJS.WritableStream
|
|
6
8
|
info: (...args: unknown[]) => void
|
|
@@ -9,19 +11,29 @@ export interface Logger {
|
|
|
9
11
|
error: (...args: unknown[]) => void
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
|
|
15
|
+
debug: 10,
|
|
16
|
+
info: 20,
|
|
17
|
+
warn: 30,
|
|
18
|
+
error: 40
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
export const createLogger = (
|
|
13
22
|
cwd: string,
|
|
14
23
|
taskId: string,
|
|
15
24
|
sessionId: string,
|
|
16
|
-
logPrefix = ''
|
|
25
|
+
logPrefix = '',
|
|
26
|
+
level: LogLevel = 'info'
|
|
17
27
|
) => {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
const normalizedSessionId = sessionId ?? 'default'
|
|
29
|
+
const taskDir = resolve(
|
|
30
|
+
cwd,
|
|
31
|
+
`.ai${logPrefix}/logs/${taskId}`
|
|
32
|
+
)
|
|
21
33
|
|
|
22
34
|
const loggerFilePath = resolve(
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
taskDir,
|
|
36
|
+
`${normalizedSessionId}.log.md`
|
|
25
37
|
)
|
|
26
38
|
// 默认日志文件不存在时,创建一个默认的日志文件
|
|
27
39
|
if (!existsSync(loggerFilePath)) {
|
|
@@ -30,7 +42,10 @@ export const createLogger = (
|
|
|
30
42
|
const loggerStream = createWriteStream(loggerFilePath, {
|
|
31
43
|
flags: 'a'
|
|
32
44
|
})
|
|
33
|
-
const createLog = (tag: string) => (...args: unknown[]) => {
|
|
45
|
+
const createLog = (tag: string, currentLevel: LogLevel) => (...args: unknown[]) => {
|
|
46
|
+
if (LOG_LEVEL_PRIORITY[currentLevel] < LOG_LEVEL_PRIORITY[level]) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
34
49
|
const msg = args
|
|
35
50
|
.map((arg) => {
|
|
36
51
|
if (typeof arg === 'string') {
|
|
@@ -66,9 +81,9 @@ export const createLogger = (
|
|
|
66
81
|
}
|
|
67
82
|
return {
|
|
68
83
|
stream: loggerStream,
|
|
69
|
-
info: createLog('I'),
|
|
70
|
-
warn: createLog('W'),
|
|
71
|
-
debug: createLog('D'),
|
|
72
|
-
error: createLog('E')
|
|
84
|
+
info: createLog('I', 'info'),
|
|
85
|
+
warn: createLog('W', 'warn'),
|
|
86
|
+
debug: createLog('D', 'debug'),
|
|
87
|
+
error: createLog('E', 'error')
|
|
73
88
|
}
|
|
74
89
|
}
|
package/src/utils/api.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
|
|
3
|
-
import type { HookInputs, HookOutputs } from '#~/hooks/type.js'
|
|
4
|
-
|
|
5
|
-
export type HookEventName = keyof HookInputs
|
|
6
|
-
|
|
7
|
-
type HookInputPayload<K extends HookEventName> = Omit<HookInputs[K], 'hookEventName'>
|
|
8
|
-
|
|
9
|
-
const host = process.env.__VF_PROJECT_AI_SERVER_HOST__ ?? 'localhost'
|
|
10
|
-
const port = process.env.__VF_PROJECT_AI_SERVER_PORT__ ?? '8787'
|
|
11
|
-
const baseUrl = `http://${host}:${port}`
|
|
12
|
-
|
|
13
|
-
export const callHook = async <K extends HookEventName>(
|
|
14
|
-
hookEventName: K,
|
|
15
|
-
input: HookInputPayload<K>,
|
|
16
|
-
env: Record<string, unknown> = process.env
|
|
17
|
-
): Promise<HookOutputs[K]> => {
|
|
18
|
-
const response = await fetch(`${baseUrl}/api/hooks/call`, {
|
|
19
|
-
method: 'POST',
|
|
20
|
-
headers: { 'Content-Type': 'application/json' },
|
|
21
|
-
body: JSON.stringify({
|
|
22
|
-
hookEventName,
|
|
23
|
-
input,
|
|
24
|
-
env
|
|
25
|
-
})
|
|
26
|
-
})
|
|
27
|
-
if (!response.ok) {
|
|
28
|
-
const errorText = await response.text()
|
|
29
|
-
throw new Error(`Failed to call hook: ${response.statusText} - ${errorText}`)
|
|
30
|
-
}
|
|
31
|
-
return response.json()
|
|
32
|
-
}
|