codeblog-app 1.0.0 → 1.1.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/ai/provider.ts +11 -0
- package/src/cli/cmd/ai-publish.ts +16 -0
- package/src/cli/cmd/chat.ts +19 -0
- package/src/cli/cmd/setup.ts +17 -0
- package/src/global/index.ts +8 -4
- package/src/index.ts +1 -1
package/package.json
CHANGED
package/src/ai/provider.ts
CHANGED
|
@@ -289,6 +289,17 @@ export namespace AIProvider {
|
|
|
289
289
|
return cfg.model
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
// ---------------------------------------------------------------------------
|
|
293
|
+
// Check if any AI provider has a key configured
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
export async function hasAnyKey(): Promise<boolean> {
|
|
296
|
+
for (const providerID of Object.keys(PROVIDER_ENV)) {
|
|
297
|
+
const key = await getApiKey(providerID)
|
|
298
|
+
if (key) return true
|
|
299
|
+
}
|
|
300
|
+
return false
|
|
301
|
+
}
|
|
302
|
+
|
|
292
303
|
// ---------------------------------------------------------------------------
|
|
293
304
|
// List available models with key status (for codeblog config --list)
|
|
294
305
|
// ---------------------------------------------------------------------------
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CommandModule } from "yargs"
|
|
2
2
|
import { AIChat } from "../../ai/chat"
|
|
3
|
+
import { AIProvider } from "../../ai/provider"
|
|
3
4
|
import { Posts } from "../../api/posts"
|
|
4
5
|
import { Config } from "../../config"
|
|
5
6
|
import { scanAll, parseSession, registerAllScanners } from "../../scanner"
|
|
@@ -32,6 +33,21 @@ export const AIPublishCommand: CommandModule = {
|
|
|
32
33
|
}),
|
|
33
34
|
handler: async (args) => {
|
|
34
35
|
try {
|
|
36
|
+
// Check AI key before scanning
|
|
37
|
+
const hasKey = await AIProvider.hasAnyKey()
|
|
38
|
+
if (!hasKey) {
|
|
39
|
+
console.log("")
|
|
40
|
+
UI.warn("No AI provider configured. ai-publish requires an AI API key to generate posts.")
|
|
41
|
+
console.log("")
|
|
42
|
+
console.log(` ${UI.Style.TEXT_NORMAL_BOLD}Configure an AI provider first:${UI.Style.TEXT_NORMAL}`)
|
|
43
|
+
console.log(` ${UI.Style.TEXT_HIGHLIGHT}codeblog config --provider anthropic --api-key sk-ant-...${UI.Style.TEXT_NORMAL}`)
|
|
44
|
+
console.log("")
|
|
45
|
+
console.log(` ${UI.Style.TEXT_DIM}Run: codeblog config --list to see all supported providers${UI.Style.TEXT_NORMAL}`)
|
|
46
|
+
console.log("")
|
|
47
|
+
process.exitCode = 1
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
35
51
|
UI.info("Scanning IDE sessions...")
|
|
36
52
|
registerAllScanners()
|
|
37
53
|
const sessions = scanAll(args.limit as number)
|
package/src/cli/cmd/chat.ts
CHANGED
|
@@ -23,6 +23,25 @@ export const ChatCommand: CommandModule = {
|
|
|
23
23
|
handler: async (args) => {
|
|
24
24
|
const modelID = args.model as string | undefined
|
|
25
25
|
|
|
26
|
+
// Check AI key before doing anything
|
|
27
|
+
const hasKey = await AIProvider.hasAnyKey()
|
|
28
|
+
if (!hasKey) {
|
|
29
|
+
console.log("")
|
|
30
|
+
UI.warn("No AI provider configured. AI features require an API key.")
|
|
31
|
+
console.log("")
|
|
32
|
+
console.log(` ${UI.Style.TEXT_NORMAL_BOLD}Configure an AI provider:${UI.Style.TEXT_NORMAL}`)
|
|
33
|
+
console.log("")
|
|
34
|
+
console.log(` ${UI.Style.TEXT_HIGHLIGHT}codeblog config --provider anthropic --api-key sk-ant-...${UI.Style.TEXT_NORMAL}`)
|
|
35
|
+
console.log(` ${UI.Style.TEXT_HIGHLIGHT}codeblog config --provider openai --api-key sk-...${UI.Style.TEXT_NORMAL}`)
|
|
36
|
+
console.log(` ${UI.Style.TEXT_HIGHLIGHT}codeblog config --provider google --api-key AIza...${UI.Style.TEXT_NORMAL}`)
|
|
37
|
+
console.log("")
|
|
38
|
+
console.log(` ${UI.Style.TEXT_DIM}Or set an environment variable: ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.${UI.Style.TEXT_NORMAL}`)
|
|
39
|
+
console.log(` ${UI.Style.TEXT_DIM}Run: codeblog config --list to see all 15+ supported providers${UI.Style.TEXT_NORMAL}`)
|
|
40
|
+
console.log("")
|
|
41
|
+
process.exitCode = 1
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
// Non-interactive: single prompt
|
|
27
46
|
if (args.prompt) {
|
|
28
47
|
try {
|
package/src/cli/cmd/setup.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CommandModule } from "yargs"
|
|
2
2
|
import { Auth } from "../../auth"
|
|
3
3
|
import { OAuth } from "../../auth/oauth"
|
|
4
|
+
import { AIProvider } from "../../ai/provider"
|
|
4
5
|
import { registerAllScanners, scanAll } from "../../scanner"
|
|
5
6
|
import { Publisher } from "../../publisher"
|
|
6
7
|
import { UI } from "../ui"
|
|
@@ -76,10 +77,26 @@ export const SetupCommand: CommandModule = {
|
|
|
76
77
|
console.log("")
|
|
77
78
|
UI.success("Setup complete! 🎉")
|
|
78
79
|
console.log("")
|
|
80
|
+
|
|
81
|
+
// Check if AI is configured
|
|
82
|
+
const hasKey = await AIProvider.hasAnyKey()
|
|
83
|
+
if (!hasKey) {
|
|
84
|
+
console.log(` ${UI.Style.TEXT_WARNING}💡 Optional: Configure an AI provider to unlock AI features${UI.Style.TEXT_NORMAL}`)
|
|
85
|
+
console.log(` ${UI.Style.TEXT_DIM}(ai-publish, chat, and other AI-powered commands)${UI.Style.TEXT_NORMAL}`)
|
|
86
|
+
console.log("")
|
|
87
|
+
console.log(` ${UI.Style.TEXT_HIGHLIGHT}codeblog config --provider anthropic --api-key sk-ant-...${UI.Style.TEXT_NORMAL}`)
|
|
88
|
+
console.log(` ${UI.Style.TEXT_HIGHLIGHT}codeblog config --provider openai --api-key sk-...${UI.Style.TEXT_NORMAL}`)
|
|
89
|
+
console.log("")
|
|
90
|
+
console.log(` ${UI.Style.TEXT_DIM}Run: codeblog config --list to see all 15+ supported providers${UI.Style.TEXT_NORMAL}`)
|
|
91
|
+
console.log("")
|
|
92
|
+
}
|
|
93
|
+
|
|
79
94
|
console.log(` ${UI.Style.TEXT_DIM}Useful commands:${UI.Style.TEXT_NORMAL}`)
|
|
80
95
|
console.log(` codeblog feed ${UI.Style.TEXT_DIM}— Browse the forum${UI.Style.TEXT_NORMAL}`)
|
|
81
96
|
console.log(` codeblog scan ${UI.Style.TEXT_DIM}— Scan IDE sessions${UI.Style.TEXT_NORMAL}`)
|
|
82
97
|
console.log(` codeblog publish ${UI.Style.TEXT_DIM}— Publish sessions${UI.Style.TEXT_NORMAL}`)
|
|
98
|
+
console.log(` codeblog ai-publish ${UI.Style.TEXT_DIM}— AI writes a post from your session${UI.Style.TEXT_NORMAL}`)
|
|
99
|
+
console.log(` codeblog chat ${UI.Style.TEXT_DIM}— Interactive AI chat${UI.Style.TEXT_NORMAL}`)
|
|
83
100
|
console.log(` codeblog dashboard ${UI.Style.TEXT_DIM}— Your stats${UI.Style.TEXT_NORMAL}`)
|
|
84
101
|
console.log("")
|
|
85
102
|
},
|
package/src/global/index.ts
CHANGED
|
@@ -6,10 +6,14 @@ import os from "os"
|
|
|
6
6
|
const app = "codeblog"
|
|
7
7
|
|
|
8
8
|
const home = process.env.CODEBLOG_TEST_HOME || os.homedir()
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
9
|
+
const win = os.platform() === "win32"
|
|
10
|
+
const appdata = process.env.APPDATA || path.join(home, "AppData", "Roaming")
|
|
11
|
+
const localappdata = process.env.LOCALAPPDATA || path.join(home, "AppData", "Local")
|
|
12
|
+
|
|
13
|
+
const data = win ? path.join(localappdata, app) : path.join(xdgData || path.join(home, ".local", "share"), app)
|
|
14
|
+
const cache = win ? path.join(localappdata, app, "cache") : path.join(xdgCache || path.join(home, ".cache"), app)
|
|
15
|
+
const config = win ? path.join(appdata, app) : path.join(xdgConfig || path.join(home, ".config"), app)
|
|
16
|
+
const state = win ? path.join(localappdata, app, "state") : path.join(xdgState || path.join(home, ".local", "state"), app)
|
|
13
17
|
|
|
14
18
|
export namespace Global {
|
|
15
19
|
export const Path = {
|
package/src/index.ts
CHANGED
|
@@ -35,7 +35,7 @@ import { WeeklyDigestCommand } from "./cli/cmd/weekly-digest"
|
|
|
35
35
|
import { TagsCommand } from "./cli/cmd/tags"
|
|
36
36
|
import { ExploreCommand } from "./cli/cmd/explore"
|
|
37
37
|
|
|
38
|
-
const VERSION = "
|
|
38
|
+
const VERSION = "1.1.0"
|
|
39
39
|
|
|
40
40
|
process.on("unhandledRejection", (e) => {
|
|
41
41
|
Log.Default.error("rejection", {
|