@allbluecn/web-app 0.24.0 → 0.24.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allbluecn/web-app",
3
- "version": "0.24.0",
3
+ "version": "0.24.1",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "type": "module",
6
6
  "files": [
@@ -197,6 +197,10 @@ export function HarnessComposer({
197
197
  onLocalCwdChange,
198
198
  engineLocked,
199
199
  }: HarnessComposerProps) {
200
+ // 本地工作区引擎由桌面 pi 按「设置 → AI 服务商」里已启用的服务商自行解析,
201
+ // 不依赖 session.hasAiKey(guest 会话该字段恒 false);云端仍要求 hasAiKey。
202
+ const localEngine = engine === "local"
203
+ const aiReady = hasAiKey || localEngine
200
204
  const [input, setInput] = useState("")
201
205
  const [pendingPrefillEntity, setPendingPrefillEntity] = useState<PrefillMentionEntity | null>(null)
202
206
  const [pendingPrefillText, setPendingPrefillText] = useState<string | null>(null)
@@ -204,7 +208,7 @@ export function HarnessComposer({
204
208
  const receiveEditor = useCallback((editor: Editor | null) => {
205
209
  editorRef.current = editor ?? null
206
210
  setInput(editor?.getText() ?? "")
207
- if (editor && hasAiKey) {
211
+ if (editor && aiReady) {
208
212
  if (pendingPrefillEntity) {
209
213
  insertMentionChip(editor, pendingPrefillEntity)
210
214
  setPendingPrefillEntity(null)
@@ -213,7 +217,7 @@ export function HarnessComposer({
213
217
  setPendingPrefillText(null)
214
218
  }
215
219
  }
216
- }, [pendingPrefillEntity, pendingPrefillText, hasAiKey])
220
+ }, [pendingPrefillEntity, pendingPrefillText, aiReady])
217
221
  const { attachments, addFiles, removeAttachment, clearAttachments, hasUploading } = useAttachments()
218
222
  // @mention chip 中携带的 kbId(由 ComposerEditor 通过 onMentionKbIds 回调上报)
219
223
  const [editorMentionKbIds, setEditorMentionKbIds] = useState<string[]>([])
@@ -242,24 +246,24 @@ export function HarnessComposer({
242
246
  }
243
247
  const entity: PrefillMentionEntity = prefill.entity
244
248
  setPendingPrefillEntity(entity)
245
- if (editorRef.current && hasAiKey) {
249
+ if (editorRef.current && aiReady) {
246
250
  insertMentionChip(editorRef.current, entity)
247
251
  setPendingPrefillEntity(null)
248
252
  }
249
- }, [handoffContext, handoffPrefillText, hasAiKey])
253
+ }, [handoffContext, handoffPrefillText, aiReady])
250
254
 
251
255
  // placeholder 五态
252
256
  const placeholder = computePlaceholder({
253
- hasAiKey,
257
+ hasAiKey: aiReady,
254
258
  isRunning,
255
259
  busyPreference,
256
260
  })
257
261
 
258
262
  const handleSend = useCallback(
259
263
  (text: string, whenBusy: "queue" | "interrupt" = "queue") => {
260
- if (!text.trim() || !hasAiKey) return
264
+ if (!text.trim() || !aiReady) return
261
265
 
262
- if (mediaRoute === "spec") {
266
+ if (!localEngine && mediaRoute === "spec") {
263
267
  if (!threadId) {
264
268
  toast.info(m.harness_spec_needThread())
265
269
  editorRef.current?.commands.clearContent()
@@ -309,7 +313,7 @@ export function HarnessComposer({
309
313
  clearAttachments()
310
314
  }
311
315
  },
312
- [hasAiKey, onSend, knowledgeBaseIds, editorMentionKbIds, handoffContext, clearAttachments, removeAttachment, attachments, mediaRoute, threadId]
316
+ [aiReady, localEngine, onSend, knowledgeBaseIds, editorMentionKbIds, handoffContext, clearAttachments, removeAttachment, attachments, mediaRoute, threadId]
313
317
  )
314
318
 
315
319
  const handleStop = useCallback(() => {
@@ -378,9 +382,9 @@ export function HarnessComposer({
378
382
  }}
379
383
  >
380
384
  <ComposerEditor
381
- key={String(hasAiKey)}
385
+ key={String(aiReady)}
382
386
  threadId={threadId ?? "default"}
383
- editable={hasAiKey}
387
+ editable={aiReady}
384
388
  editorRef={receiveEditor}
385
389
  onTextChange={() => setInput(editorRef.current?.getText() ?? "")}
386
390
  onMentionKbIds={setEditorMentionKbIds}
@@ -430,7 +434,7 @@ export function HarnessComposer({
430
434
  </div>
431
435
  <Button
432
436
  size="sm"
433
- disabled={!hasAiKey || sendBlocked || (engine === "local" && !localCwd)}
437
+ disabled={!aiReady || sendBlocked || (localEngine && !localCwd)}
434
438
  onClick={() => handleSend(editorRef.current?.getText() ?? "")}
435
439
  >
436
440
  {m.harness_composer_send()}
@@ -590,7 +590,7 @@ export default function HarnessWorkbenchPage({ initialThreadId, initialMessages,
590
590
  </div>
591
591
  </div>
592
592
 
593
- {!hasAiKey && (
593
+ {!hasAiKey && engine !== "local" && (
594
594
  <div className="mx-6 mt-3 flex items-center gap-2 rounded-lg border border-amber-200 bg-amber-50 p-3 dark:border-amber-900 dark:bg-amber-950">
595
595
  <AlertCircle className="size-4 shrink-0 text-amber-600 dark:text-amber-400" />
596
596
  <p className="flex-1 text-xs text-amber-700 dark:text-amber-300">
@@ -600,6 +600,16 @@ export default function HarnessWorkbenchPage({ initialThreadId, initialMessages,
600
600
  </div>
601
601
  )}
602
602
 
603
+ {!hasAiKey && engine === "local" && (
604
+ <div className="mx-6 mt-3 flex items-center gap-2 rounded-lg border border-border bg-muted/40 p-3">
605
+ <AlertCircle className="size-4 shrink-0 text-muted-foreground" />
606
+ <p className="flex-1 text-xs text-muted-foreground">
607
+ {m.harness_engine_localNeedsProvider()}
608
+ </p>
609
+ <Button render={<RouterLink to="/settings/ai" />} size="sm" variant="outline" className="shrink-0 h-7 text-xs" nativeButton={false}>{m.chat_goToSettings()}</Button>
610
+ </div>
611
+ )}
612
+
603
613
  {chat.error && !retryDismissed && (
604
614
  <RetryCountdownBar
605
615
  error={{ message: chat.error.message, retryable: (chat.error as unknown as { retryable?: boolean }).retryable ?? true }}
@@ -112,7 +112,7 @@ export const SDK_GROUPS: SdkGroup[] = [
112
112
  "items": [
113
113
  {
114
114
  "name": "@allbluecn/web-app",
115
- "version": "v0.24.0",
115
+ "version": "v0.24.1",
116
116
  "lastUpdate": "Nov 1, 2026",
117
117
  "source": "apps/web/package.json",
118
118
  "docsUrl": "https://github.com/allbluecn/allblue"