feat(extensions): integrate OpenCode plugin hooks runtime #5544
ci.yml
on: pull_request
Build Impact
22s
Shell Deploy Scripts
14s
Matrix: cli-test
Matrix: Impact-selected Linux / Relay Contract / build
Matrix: rust-build-check
DSH Profile Packaging (windows-latest)
46s
Frontend Build
5m 45s
Rust / CLI Validation
8s
Annotations
21 errors and 4 warnings
|
src/flow_chat/tool-cards/FileOperationToolCard.test.tsx > FileOperationToolCard > does not treat a successful fallback write as a completed plan:
src/web-ui/src/flow_chat/tool-cards/FileOperationToolCard.test.tsx#L160
TypeError: Cannot read properties of undefined (reading 'mockClear')
❯ src/flow_chat/tool-cards/FileOperationToolCard.test.tsx:160:23
|
|
src/flow_chat/tool-cards/FileOperationToolCard.test.tsx > FileOperationToolCard > keeps failed .plan.md writes on the normal error card:
src/web-ui/src/flow_chat/tool-cards/FileOperationToolCard.test.tsx#L160
TypeError: Cannot read properties of undefined (reading 'mockClear')
❯ src/flow_chat/tool-cards/FileOperationToolCard.test.tsx:160:23
|
|
src/flow_chat/tool-cards/FileOperationToolCard.test.tsx > FileOperationToolCard > keeps Edit calls for .plan.md files on the normal file operation card:
src/web-ui/src/flow_chat/tool-cards/FileOperationToolCard.test.tsx#L160
TypeError: Cannot read properties of undefined (reading 'mockClear')
❯ src/flow_chat/tool-cards/FileOperationToolCard.test.tsx:160:23
|
|
src/flow_chat/tool-cards/FileOperationToolCard.test.tsx > FileOperationToolCard > routes only successful Write calls for .plan.md files to the plan display:
src/web-ui/src/flow_chat/tool-cards/FileOperationToolCard.test.tsx#L160
TypeError: Cannot read properties of undefined (reading 'mockClear')
❯ src/flow_chat/tool-cards/FileOperationToolCard.test.tsx:160:23
|
|
src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx > CodeReviewToolCard > maps internal reviewer source ids before rendering issues:
src/web-ui/src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx#L501
AssertionError: expected undefined to be truthy
- Expected:
true
+ Received:
undefined
❯ src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx:501:33
|
|
src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx > CodeReviewToolCard > renders limited-scope reliability status from structured report signals:
src/web-ui/src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx#L437
AssertionError: expected 'Strict Review Result - Low Risk' to contain 'Limited review scope'
Expected: "Limited review scope"
Received: "Strict Review Result - Low Risk"
❯ src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx:437:35
|
|
src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx > CodeReviewToolCard > renders compact reliability status when a reviewer returned partial evidence:
src/web-ui/src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx#L374
AssertionError: expected 'Strict Review Result - Medium Risk' to contain 'Review status'
Expected: "Review status"
Received: "Strict Review Result - Medium Risk"
❯ src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx:374:35
|
|
src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx > CodeReviewToolCard > updates coverage reliability when session metadata arrives after render:
src/web-ui/src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx#L313
AssertionError: expected 'Strict Review Result - Low Risk' to contain 'Review scope tailored'
Expected: "Review scope tailored"
Received: "Strict Review Result - Low Risk"
❯ src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx:313:35
|
|
src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx > CodeReviewToolCard > summarizes deep review coverage without exposing the run manifest:
src/web-ui/src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx#L227
AssertionError: expected 'Strict Review Result - Low Risk' to contain 'Review status'
Expected: "Review status"
Received: "Strict Review Result - Low Risk"
❯ src/flow_chat/tool-cards/CodeReviewToolCard.test.tsx:227:35
|
|
src/app/startup/startupPerformanceContract.test.ts > startup performance contract > keeps passive chat Git refresh out of the history open transition window:
src/web-ui/src/app/startup/startupPerformanceContract.test.ts#L618
AssertionError: expected '/**\n * File operation tool card on t…' to contain 'getHistorySessionOpenTransitionSnapsh…'
- Expected
+ Received
- getHistorySessionOpenTransitionSnapshot
+ /**
+ * File operation tool card on the shared prominent FlowChat framework.
+ * Supports Write/Edit/Delete file operations
+ *
+ * Card height changes reflow naturally. Expanded-state changes use
+ * `useToolCardHeightContract.applyExpandedState(...)` only to notify the virtualizer
+ * that it should remeasure the card after the transition.
+ */
+
+ import React, { useEffect, useCallback, useMemo, useState, useRef, useLayoutEffect } from 'react';
+ import { useTranslation } from 'react-i18next';
+ import path from 'path-browserify';
+ import type { ToolCardProps } from '../types/flow-chat';
+ import {
+ FileOperationToolCard as FileOperationCardView,
+ } from '@bitfun/ui/flow-chat';
+ import { useSnapshotState } from '../../tools/snapshot_system/hooks/useSnapshotState';
+ import { SnapshotEventBus, SNAPSHOT_EVENTS } from '../../tools/snapshot_system/core/SnapshotEventBus';
+ import { useOptionalCurrentWorkspace } from '../../infrastructure/contexts/WorkspaceContext';
+ import { createDiffEditorTab } from '../../shared/utils/tabUtils';
+ import { fileTabManager } from '../../shared/services/FileTabManager';
+ import { CodePreview } from '../components/CodePreview';
+ import { InlineDiffPreview } from '../components/InlineDiffPreview';
+ import { diffLines } from 'diff';
+ import { createLogger } from '@/shared/utils/logger';
+ import { useToolCardHeightContract } from './useToolCardHeightContract';
+ import { useToolCardCompletionGracePeriod } from './useToolCardCompletionGracePeriod';
+ import { useTypewriter } from '../hooks/useTypewriter';
+ import { useReportTypewriterReveal } from '../hooks/typewriterRevealGateContext';
+ import { hasNonFileUriScheme } from '@/shared/utils/pathUtils';
+ import {
+ displayFileToolGuidanceMessage,
+ isFileToolGuidanceMessage,
+ } from './fileToolGuidance';
+ import { extractFilePathFromJsonBuffer, splitFilePathAndContent } from '@/shared/utils/partialJsonParser';
+ import { i18nService } from '@/infrastructure/i18n';
+ import { WritePlanDisplay } from './WritePlanDisplay';
+
+ const log = createLogger('FileOperationToolCard');
+ const FILE_OPERATION_STREAMING_MAX_HEIGHT = 4 * 22; // 88px – compact while streaming
+ const FILE_OPERATION_DIFF_MAX_HEIGHT = 15 * 22; // 330px – comfortable diff reading when expanded
+
+ function stringPath(value: unknown): string {
+ return typeof value === 'string' && value.trim().length > 0 ? value : '';
+ }
+
+ function objectValue(value: unknown): Record<string, unknown> | null {
+ return typeof value === 'object' && value !== null ? value as Record<string, unknown> : null;
+ }
+
+ function firstStringValue(source: Record<string, unknown> | null | undefined, keys: string[]): string {
+ if (!source) return '';
+ for (const key of keys) {
+ const value = stringPath(source[key]);
+ if (value) return value;
+ }
+ return '';
+ }
+
+ function pathFromAcpLocations(locations: unknown): string {
+ if (!Array.isArray(locations)) return '';
+ for (const location of locations) {
+ const object = objectValue(location);
+ const filePath = firstStringValue(object, ['path', 'file_path', 'filePath', 'uri']);
+ if (filePath) return filePath;
+ }
+ return '';
+ }
+
+ function isWindowsAbsolutePath(filePath: string): boolean {
+ return /^[A-Za-z]:[\\/]/.test(filePath);
+ }
+
+ function resolveOpenFilePath(filePath: string, workspacePath?: string): string {
+ if (!filePath || hasNonFileUriScheme(filePath) || isWindowsAbsolutePath(filePath) || path.isAbsolute(filePath)) {
+ return filePath;
+ }
+
+ return workspacePath ? path.join(workspacePath, filePath) : filePath;
+ }
+
+ function fileOperationPath(toolItem: ToolCardProps['toolItem']): string {
+ const result = toolItem.toolResult?.result;
+ const resultPath = stringPath(result?.file_path) || stringPath(result?.filePath);
+ if (resultPath) return resultPath
|
|
Rust Build Check (windows-latest)
Canceling since a higher priority waiting request for ci-refs/pull/2518/merge exists
|
|
Rust Build Check (windows-latest)
The operation was canceled.
|
|
Impact-selected Linux / Relay Contract / Linux Binaries (linux-x64)
Canceling since a higher priority waiting request for ci-refs/pull/2518/merge exists
|
|
Impact-selected Linux / Relay Contract / Linux Binaries (linux-x64)
The operation was canceled.
|
|
Impact-selected Linux / Relay Contract / Linux Binaries (linux-arm64)
Canceling since a higher priority waiting request for ci-refs/pull/2518/merge exists
|
|
Impact-selected Linux / Relay Contract / Linux Binaries (linux-arm64)
The operation was canceled.
|
|
Rust Build Check (macos-15)
Canceling since a higher priority waiting request for ci-refs/pull/2518/merge exists
|
|
Rust Build Check (macos-15)
The operation was canceled.
|
|
Rust / CLI Validation
Process completed with exit code 1.
|
|
CI
Canceling since a higher priority waiting request for ci-refs/pull/2518/merge exists
|
|
CI
Canceling since a higher priority waiting request for ci-refs/pull/2518/merge exists
|
|
Frontend Build:
src/web-ui/src/flow_chat/tool-cards/AgentWaitToolCard.tsx#L17
Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
|
|
Frontend Build:
src/web-ui/src/flow_chat/components/voice/RealtimeVoiceCallContext.tsx#L32
Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
|
|
Frontend Build:
src/web-ui/src/flow_chat/components/voice/RealtimeVoiceCallContext.tsx#L23
Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
|
|
Frontend Build:
src/web-ui/src/app/components/SceneTopBar/SceneChrome.tsx#L119
Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
|