codeblog-app 2.2.3 → 2.2.6
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 +7 -7
- package/src/auth/oauth.ts +14 -0
- package/src/config/index.ts +1 -0
- package/src/tui/app.tsx +19 -0
- package/src/tui/commands.ts +1 -0
- package/src/tui/routes/home.tsx +22 -7
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "codeblog-app",
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.6",
|
|
5
5
|
"description": "CLI client for CodeBlog — the forum where AI writes the posts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -56,11 +56,11 @@
|
|
|
56
56
|
"typescript": "5.8.2"
|
|
57
57
|
},
|
|
58
58
|
"optionalDependencies": {
|
|
59
|
-
"codeblog-app-darwin-arm64": "2.2.
|
|
60
|
-
"codeblog-app-darwin-x64": "2.2.
|
|
61
|
-
"codeblog-app-linux-arm64": "2.2.
|
|
62
|
-
"codeblog-app-linux-x64": "2.2.
|
|
63
|
-
"codeblog-app-windows-x64": "2.2.
|
|
59
|
+
"codeblog-app-darwin-arm64": "2.2.6",
|
|
60
|
+
"codeblog-app-darwin-x64": "2.2.6",
|
|
61
|
+
"codeblog-app-linux-arm64": "2.2.6",
|
|
62
|
+
"codeblog-app-linux-x64": "2.2.6",
|
|
63
|
+
"codeblog-app-windows-x64": "2.2.6"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"@ai-sdk/anthropic": "^3.0.44",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"@opentui/core": "^0.1.79",
|
|
72
72
|
"@opentui/solid": "^0.1.79",
|
|
73
73
|
"ai": "^6.0.86",
|
|
74
|
-
"codeblog-mcp": "^2.1.
|
|
74
|
+
"codeblog-mcp": "^2.1.5",
|
|
75
75
|
"drizzle-orm": "1.0.0-beta.12-a5629fb",
|
|
76
76
|
"fuzzysort": "^3.1.0",
|
|
77
77
|
"hono": "4.10.7",
|
package/src/auth/oauth.ts
CHANGED
|
@@ -24,6 +24,20 @@ export namespace OAuth {
|
|
|
24
24
|
} catch (err) {
|
|
25
25
|
log.warn("failed to sync API key to MCP config", { error: String(err) })
|
|
26
26
|
}
|
|
27
|
+
// Fetch agent name and save to CLI config
|
|
28
|
+
try {
|
|
29
|
+
const meRes = await fetch(`${base}/api/v1/agents/me`, {
|
|
30
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
31
|
+
})
|
|
32
|
+
if (meRes.ok) {
|
|
33
|
+
const meData = await meRes.json() as { agent?: { name?: string } }
|
|
34
|
+
if (meData.agent?.name) {
|
|
35
|
+
await Config.save({ activeAgent: meData.agent.name })
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} catch (err) {
|
|
39
|
+
log.warn("failed to fetch agent info", { error: String(err) })
|
|
40
|
+
}
|
|
27
41
|
log.info("authenticated with api key")
|
|
28
42
|
} else if (token) {
|
|
29
43
|
await Auth.set({ type: "jwt", value: token, username })
|
package/src/config/index.ts
CHANGED
package/src/tui/app.tsx
CHANGED
|
@@ -85,6 +85,25 @@ function App() {
|
|
|
85
85
|
const cfg = await Config.load()
|
|
86
86
|
if (cfg.activeAgent) {
|
|
87
87
|
setActiveAgent(cfg.activeAgent)
|
|
88
|
+
} else if (loggedIn()) {
|
|
89
|
+
// If logged in but no activeAgent cached, fetch from API
|
|
90
|
+
const { Auth } = await import("../auth")
|
|
91
|
+
const tok = await Auth.get()
|
|
92
|
+
if (tok?.type === "apikey" && tok.value) {
|
|
93
|
+
try {
|
|
94
|
+
const base = await Config.url()
|
|
95
|
+
const res = await fetch(`${base}/api/v1/agents/me`, {
|
|
96
|
+
headers: { Authorization: `Bearer ${tok.value}` },
|
|
97
|
+
})
|
|
98
|
+
if (res.ok) {
|
|
99
|
+
const data = await res.json() as { agent?: { name?: string } }
|
|
100
|
+
if (data.agent?.name) {
|
|
101
|
+
setActiveAgent(data.agent.name)
|
|
102
|
+
await Config.save({ activeAgent: data.agent.name })
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} catch {}
|
|
106
|
+
}
|
|
88
107
|
}
|
|
89
108
|
} catch {}
|
|
90
109
|
|
package/src/tui/commands.ts
CHANGED
|
@@ -165,6 +165,7 @@ export const TIPS = [
|
|
|
165
165
|
"Type / to see all available commands with autocomplete",
|
|
166
166
|
"Just start typing to chat with AI — no command needed!",
|
|
167
167
|
"Use /clear to reset the conversation",
|
|
168
|
+
"Press Shift+Enter to add a new line in the input box",
|
|
168
169
|
]
|
|
169
170
|
|
|
170
171
|
export const TIPS_NO_AI = [
|
package/src/tui/routes/home.tsx
CHANGED
|
@@ -163,11 +163,18 @@ export function Home(props: {
|
|
|
163
163
|
})
|
|
164
164
|
|
|
165
165
|
usePaste((evt) => {
|
|
166
|
-
|
|
166
|
+
// For URL/key modes, strip newlines; for normal input, preserve them
|
|
167
|
+
if (aiMode() === "url" || aiMode() === "key") {
|
|
168
|
+
const text = evt.text.replace(/[\n\r]/g, "").trim()
|
|
169
|
+
if (!text) return
|
|
170
|
+
evt.preventDefault()
|
|
171
|
+
if (aiMode() === "url") { setAiUrl(text); return }
|
|
172
|
+
setAiKey(text)
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
const text = evt.text.replace(/\r\n/g, "\n").replace(/\r/g, "\n")
|
|
167
176
|
if (!text) return
|
|
168
177
|
evt.preventDefault()
|
|
169
|
-
if (aiMode() === "url") { setAiUrl(text); return }
|
|
170
|
-
if (aiMode() === "key") { setAiKey(text); return }
|
|
171
178
|
setInput((s) => s + text)
|
|
172
179
|
})
|
|
173
180
|
|
|
@@ -444,6 +451,7 @@ export function Home(props: {
|
|
|
444
451
|
if (evt.name === "escape" && chatting() && !streaming()) { clearChat(); evt.preventDefault(); return }
|
|
445
452
|
|
|
446
453
|
if (evt.name === "return" && !evt.shift) { handleSubmit(); evt.preventDefault(); return }
|
|
454
|
+
if (evt.name === "return" && evt.shift) { setInput((s) => s + "\n"); evt.preventDefault(); return }
|
|
447
455
|
if (evt.name === "backspace") { setInput((s) => s.slice(0, -1)); setSelectedIdx(0); evt.preventDefault(); return }
|
|
448
456
|
if (evt.sequence && evt.sequence.length >= 1 && !evt.ctrl && !evt.meta) {
|
|
449
457
|
const clean = evt.sequence.replace(/[\x00-\x1f\x7f]/g, "")
|
|
@@ -632,10 +640,17 @@ export function Home(props: {
|
|
|
632
640
|
</box>
|
|
633
641
|
</Show>
|
|
634
642
|
{/* Input line with blinking cursor */}
|
|
635
|
-
<box flexDirection="
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
643
|
+
<box flexDirection="column">
|
|
644
|
+
{(() => {
|
|
645
|
+
const lines = input().split("\n")
|
|
646
|
+
return lines.map((line, i) => (
|
|
647
|
+
<box flexDirection="row">
|
|
648
|
+
<text fg={theme.colors.primary}><span style={{ bold: true }}>{i === 0 ? "❯ " : " "}</span></text>
|
|
649
|
+
<text fg={theme.colors.input}>{line}</text>
|
|
650
|
+
{i === lines.length - 1 && <text fg={theme.colors.cursor} style={{ bold: true }}>{"█"}</text>}
|
|
651
|
+
</box>
|
|
652
|
+
))
|
|
653
|
+
})()}
|
|
639
654
|
</box>
|
|
640
655
|
</box>
|
|
641
656
|
</Show>
|