kanna-code 0.13.9 → 0.14.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/dist/client/assets/{index-BypLQCc0.js → index-CVu2H5bX.js} +120 -120
- package/dist/client/assets/{index-CA-kJR8F.css → index-D5tYLJi-.css} +1 -1
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/src/server/agent.ts +34 -4
- package/src/server/generate-title.ts +13 -0
- package/src/server/quick-response.test.ts +29 -0
- package/src/server/quick-response.ts +48 -10
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { query } from "@anthropic-ai/claude-agent-sdk"
|
|
2
2
|
import { CodexAppServerManager } from "./codex-app-server"
|
|
3
3
|
|
|
4
|
+
const LOG_PREFIX = "[kanna:title]"
|
|
5
|
+
const CLAUDE_STRUCTURED_TIMEOUT_MS = 5_000
|
|
6
|
+
|
|
4
7
|
type JsonSchema = {
|
|
5
8
|
type: "object"
|
|
6
9
|
properties: Record<string, unknown>
|
|
@@ -61,14 +64,32 @@ async function runClaudeStructured(args: Omit<StructuredQuickResponseArgs<unknow
|
|
|
61
64
|
})
|
|
62
65
|
|
|
63
66
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const result = await Promise.race<unknown | null>([
|
|
68
|
+
(async () => {
|
|
69
|
+
for await (const message of q) {
|
|
70
|
+
if ("result" in message) {
|
|
71
|
+
return (message as Record<string, unknown>).structured_output ?? null
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null
|
|
75
|
+
})(),
|
|
76
|
+
new Promise<null>((_, reject) => {
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
reject(new Error(`Claude structured response timed out after ${CLAUDE_STRUCTURED_TIMEOUT_MS}ms`))
|
|
79
|
+
}, CLAUDE_STRUCTURED_TIMEOUT_MS)
|
|
80
|
+
}),
|
|
81
|
+
])
|
|
82
|
+
|
|
83
|
+
return result
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn(`${LOG_PREFIX} claude structured query failed before fallback:`, error)
|
|
69
86
|
return null
|
|
70
87
|
} finally {
|
|
71
|
-
|
|
88
|
+
try {
|
|
89
|
+
q.close()
|
|
90
|
+
} catch {
|
|
91
|
+
// Ignore close failures on timed-out or failed quick responses.
|
|
92
|
+
}
|
|
72
93
|
}
|
|
73
94
|
}
|
|
74
95
|
|
|
@@ -104,20 +125,37 @@ export class QuickResponseAdapter {
|
|
|
104
125
|
schema: args.schema,
|
|
105
126
|
}
|
|
106
127
|
|
|
107
|
-
|
|
128
|
+
console.log(`${LOG_PREFIX} starting ${args.task} via claude`, { cwd: args.cwd })
|
|
129
|
+
const claudeResult = await this.tryProvider("claude", args.task, args.parse, () => this.runClaudeStructured(request))
|
|
108
130
|
if (claudeResult !== null) return claudeResult
|
|
109
131
|
|
|
110
|
-
|
|
132
|
+
console.warn(`${LOG_PREFIX} claude returned no usable result for ${args.task}, falling back to codex`)
|
|
133
|
+
return await this.tryProvider("codex", args.task, args.parse, () => this.runCodexStructured(request))
|
|
111
134
|
}
|
|
112
135
|
|
|
113
136
|
private async tryProvider<T>(
|
|
137
|
+
provider: "claude" | "codex",
|
|
138
|
+
task: string,
|
|
114
139
|
parse: (value: unknown) => T | null,
|
|
115
140
|
run: () => Promise<unknown | null>
|
|
116
141
|
): Promise<T | null> {
|
|
117
142
|
try {
|
|
118
143
|
const result = await run()
|
|
119
|
-
|
|
120
|
-
|
|
144
|
+
if (result === null) {
|
|
145
|
+
console.warn(`${LOG_PREFIX} ${provider} returned no structured output for ${task}`)
|
|
146
|
+
return null
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const parsed = parse(result)
|
|
150
|
+
if (parsed === null) {
|
|
151
|
+
console.warn(`${LOG_PREFIX} ${provider} returned unparseable structured output for ${task}`, { result })
|
|
152
|
+
return null
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log(`${LOG_PREFIX} ${provider} produced structured output for ${task}`)
|
|
156
|
+
return parsed
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.warn(`${LOG_PREFIX} ${provider} failed during ${task}:`, error)
|
|
121
159
|
return null
|
|
122
160
|
}
|
|
123
161
|
}
|