codeblog-app 2.3.2 → 2.3.4
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/drizzle/0000_init.sql +34 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +10 -0
- package/package.json +73 -8
- package/src/ai/__tests__/chat.test.ts +188 -0
- package/src/ai/__tests__/compat.test.ts +46 -0
- package/src/ai/__tests__/home.ai-stream.integration.test.ts +77 -0
- package/src/ai/__tests__/provider-registry.test.ts +98 -0
- package/src/ai/__tests__/provider.test.ts +239 -0
- package/src/ai/__tests__/stream-events.test.ts +152 -0
- package/src/ai/__tests__/tools.test.ts +93 -0
- package/src/ai/chat.ts +336 -0
- package/src/ai/configure.ts +144 -0
- package/src/ai/models.ts +67 -0
- package/src/ai/provider-registry.ts +150 -0
- package/src/ai/provider.ts +264 -0
- package/src/ai/stream-events.ts +64 -0
- package/src/ai/tools.ts +118 -0
- package/src/ai/types.ts +105 -0
- package/src/auth/index.ts +49 -0
- package/src/auth/oauth.ts +146 -0
- package/src/cli/__tests__/commands.test.ts +229 -0
- package/src/cli/cmd/agent.ts +97 -0
- package/src/cli/cmd/ai.ts +10 -0
- package/src/cli/cmd/chat.ts +190 -0
- package/src/cli/cmd/comment.ts +67 -0
- package/src/cli/cmd/config.ts +154 -0
- package/src/cli/cmd/feed.ts +53 -0
- package/src/cli/cmd/forum.ts +106 -0
- package/src/cli/cmd/login.ts +45 -0
- package/src/cli/cmd/logout.ts +14 -0
- package/src/cli/cmd/me.ts +188 -0
- package/src/cli/cmd/post.ts +25 -0
- package/src/cli/cmd/publish.ts +64 -0
- package/src/cli/cmd/scan.ts +78 -0
- package/src/cli/cmd/search.ts +35 -0
- package/src/cli/cmd/setup.ts +845 -0
- package/src/cli/cmd/tui.ts +20 -0
- package/src/cli/cmd/uninstall.ts +281 -0
- package/src/cli/cmd/update.ts +139 -0
- package/src/cli/cmd/vote.ts +50 -0
- package/src/cli/cmd/whoami.ts +18 -0
- package/src/cli/mcp-print.ts +6 -0
- package/src/cli/ui.ts +410 -0
- package/src/config/index.ts +125 -0
- package/src/flag/index.ts +23 -0
- package/src/global/index.ts +38 -0
- package/src/id/index.ts +20 -0
- package/src/index.ts +212 -0
- package/src/mcp/__tests__/client.test.ts +149 -0
- package/src/mcp/__tests__/e2e.ts +331 -0
- package/src/mcp/__tests__/integration.ts +148 -0
- package/src/mcp/client.ts +118 -0
- package/src/server/index.ts +48 -0
- package/src/storage/chat.ts +73 -0
- package/src/storage/db.ts +85 -0
- package/src/storage/schema.sql.ts +39 -0
- package/src/storage/schema.ts +1 -0
- package/src/tui/__tests__/input-intent.test.ts +27 -0
- package/src/tui/__tests__/stream-assembler.test.ts +33 -0
- package/src/tui/ai-stream.ts +28 -0
- package/src/tui/app.tsx +224 -0
- package/src/tui/commands.ts +224 -0
- package/src/tui/context/exit.tsx +15 -0
- package/src/tui/context/helper.tsx +25 -0
- package/src/tui/context/route.tsx +24 -0
- package/src/tui/context/theme.tsx +471 -0
- package/src/tui/input-intent.ts +26 -0
- package/src/tui/routes/home.tsx +1053 -0
- package/src/tui/routes/model.tsx +213 -0
- package/src/tui/routes/notifications.tsx +87 -0
- package/src/tui/routes/post.tsx +102 -0
- package/src/tui/routes/search.tsx +105 -0
- package/src/tui/routes/setup.tsx +267 -0
- package/src/tui/routes/trending.tsx +107 -0
- package/src/tui/stream-assembler.ts +49 -0
- package/src/util/__tests__/context.test.ts +31 -0
- package/src/util/__tests__/lazy.test.ts +37 -0
- package/src/util/context.ts +23 -0
- package/src/util/error.ts +46 -0
- package/src/util/lazy.ts +18 -0
- package/src/util/log.ts +144 -0
- package/tsconfig.json +11 -0
package/src/util/log.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import path from "path"
|
|
2
|
+
import fs from "fs/promises"
|
|
3
|
+
import { Global } from "../global"
|
|
4
|
+
import z from "zod"
|
|
5
|
+
|
|
6
|
+
export namespace Log {
|
|
7
|
+
export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" })
|
|
8
|
+
export type Level = z.infer<typeof Level>
|
|
9
|
+
|
|
10
|
+
const levelPriority: Record<Level, number> = {
|
|
11
|
+
DEBUG: 0,
|
|
12
|
+
INFO: 1,
|
|
13
|
+
WARN: 2,
|
|
14
|
+
ERROR: 3,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let level: Level = "INFO"
|
|
18
|
+
|
|
19
|
+
function shouldLog(input: Level): boolean {
|
|
20
|
+
return levelPriority[input] >= levelPriority[level]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Logger = {
|
|
24
|
+
debug(message?: any, extra?: Record<string, any>): void
|
|
25
|
+
info(message?: any, extra?: Record<string, any>): void
|
|
26
|
+
error(message?: any, extra?: Record<string, any>): void
|
|
27
|
+
warn(message?: any, extra?: Record<string, any>): void
|
|
28
|
+
tag(key: string, value: string): Logger
|
|
29
|
+
clone(): Logger
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const loggers = new Map<string, Logger>()
|
|
33
|
+
|
|
34
|
+
export const Default = create({ service: "default" })
|
|
35
|
+
|
|
36
|
+
export interface Options {
|
|
37
|
+
print: boolean
|
|
38
|
+
dev?: boolean
|
|
39
|
+
level?: Level
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let logpath = ""
|
|
43
|
+
export function file() {
|
|
44
|
+
return logpath
|
|
45
|
+
}
|
|
46
|
+
let write = (msg: any) => {
|
|
47
|
+
process.stderr.write(msg)
|
|
48
|
+
return msg.length
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function init(options: Options) {
|
|
52
|
+
if (options.level) level = options.level
|
|
53
|
+
cleanup(Global.Path.log)
|
|
54
|
+
if (options.print) return
|
|
55
|
+
const isoNow = new Date().toISOString()
|
|
56
|
+
const timestampBase = isoNow.split(".")[0] ?? isoNow
|
|
57
|
+
logpath = path.join(
|
|
58
|
+
Global.Path.log,
|
|
59
|
+
options.dev ? "dev.log" : `${timestampBase.replace(/:/g, "")}.log`,
|
|
60
|
+
)
|
|
61
|
+
const logfile = Bun.file(logpath)
|
|
62
|
+
await fs.truncate(logpath).catch(() => {})
|
|
63
|
+
const writer = logfile.writer()
|
|
64
|
+
write = async (msg: any) => {
|
|
65
|
+
const num = writer.write(msg)
|
|
66
|
+
writer.flush()
|
|
67
|
+
return num
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function cleanup(dir: string) {
|
|
72
|
+
const glob = new Bun.Glob("????-??-??T??????.log")
|
|
73
|
+
const files = await Array.fromAsync(
|
|
74
|
+
glob.scan({
|
|
75
|
+
cwd: dir,
|
|
76
|
+
absolute: true,
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
if (files.length <= 5) return
|
|
80
|
+
const filesToDelete = files.slice(0, -10)
|
|
81
|
+
await Promise.all(filesToDelete.map((file) => fs.unlink(file).catch(() => {})))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function formatError(error: Error, depth = 0): string {
|
|
85
|
+
const result = error.message
|
|
86
|
+
return error.cause instanceof Error && depth < 10
|
|
87
|
+
? result + " Caused by: " + formatError(error.cause, depth + 1)
|
|
88
|
+
: result
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let last = Date.now()
|
|
92
|
+
export function create(tags?: Record<string, any>) {
|
|
93
|
+
tags = tags || {}
|
|
94
|
+
|
|
95
|
+
const service = tags["service"]
|
|
96
|
+
if (service && typeof service === "string") {
|
|
97
|
+
const cached = loggers.get(service)
|
|
98
|
+
if (cached) return cached
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function build(message: any, extra?: Record<string, any>) {
|
|
102
|
+
const prefix = Object.entries({
|
|
103
|
+
...tags,
|
|
104
|
+
...extra,
|
|
105
|
+
})
|
|
106
|
+
.filter(([_, value]) => value !== undefined && value !== null)
|
|
107
|
+
.map(([key, value]) => {
|
|
108
|
+
const prefix = `${key}=`
|
|
109
|
+
if (value instanceof Error) return prefix + formatError(value)
|
|
110
|
+
if (typeof value === "object") return prefix + JSON.stringify(value)
|
|
111
|
+
return prefix + value
|
|
112
|
+
})
|
|
113
|
+
.join(" ")
|
|
114
|
+
const next = new Date()
|
|
115
|
+
const diff = next.getTime() - last
|
|
116
|
+
last = next.getTime()
|
|
117
|
+
return [next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message].filter(Boolean).join(" ") + "\n"
|
|
118
|
+
}
|
|
119
|
+
const result: Logger = {
|
|
120
|
+
debug(message?: any, extra?: Record<string, any>) {
|
|
121
|
+
if (shouldLog("DEBUG")) write("DEBUG " + build(message, extra))
|
|
122
|
+
},
|
|
123
|
+
info(message?: any, extra?: Record<string, any>) {
|
|
124
|
+
if (shouldLog("INFO")) write("INFO " + build(message, extra))
|
|
125
|
+
},
|
|
126
|
+
error(message?: any, extra?: Record<string, any>) {
|
|
127
|
+
if (shouldLog("ERROR")) write("ERROR " + build(message, extra))
|
|
128
|
+
},
|
|
129
|
+
warn(message?: any, extra?: Record<string, any>) {
|
|
130
|
+
if (shouldLog("WARN")) write("WARN " + build(message, extra))
|
|
131
|
+
},
|
|
132
|
+
tag(key: string, value: string) {
|
|
133
|
+
if (tags) tags[key] = value
|
|
134
|
+
return result
|
|
135
|
+
},
|
|
136
|
+
clone() {
|
|
137
|
+
return Log.create({ ...tags })
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (service && typeof service === "string") loggers.set(service, result)
|
|
142
|
+
return result
|
|
143
|
+
}
|
|
144
|
+
}
|