Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .codex/review-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ Every comment must be traceable to changed behavior in this PR and anchored to a

#### Security


- Injection risks (SQL, command, XSS) when handling user input.
- Hardcoded secrets — API keys, passwords, tokens in code.
- Missing input validation at system boundaries (user input, external APIs). Not for internal function calls.
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/check-package-lock.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ on:
branches:
- main
paths:
- 'package.json'
- 'package-lock.json'
- '**/package.json'
- "package.json"
- "package-lock.json"
- "**/package.json"
pull_request:
branches:
- "**"
paths:
- 'package.json'
- 'package-lock.json'
- '**/package.json'
- "package.json"
- "package-lock.json"
- "**/package.json"

jobs:
verify-package-lock:
Expand Down Expand Up @@ -55,7 +55,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
node-version: "22"

- name: Validate package-lock.json is valid and in sync
run: npm ci --dry-run --ignore-scripts
2 changes: 1 addition & 1 deletion .github/workflows/validate-plugin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@ jobs:
echo "✅ Core Functionality tests found"
echo "✅ Error Handling tests found"
echo "✅ All tests passing"
fi
fi
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ Before you consider a task "done", you must:
# Task: [<task number (last + 1)>] <feature>

## Goal

- <short goal>

## Subtasks

- [ ] <subtask 1>
- [ ] <subtask 2>

## Notes

- <risks, decisions, links>
```

Expand Down
49 changes: 0 additions & 49 deletions apps/agent/fix-uuid.js

This file was deleted.

17 changes: 8 additions & 9 deletions apps/agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
"test:ragas": "NODE_OPTIONS='--import tsx' tsx tests/ragas/evaluate.ts",
"test:ragas:results": "NODE_OPTIONS='--import tsx' tsx tests/ragas/show-results.ts",
"test:ragas:dashboard": "NODE_OPTIONS='--import tsx' tsx tests/ragas/dashboard.ts",
"ragas": "chmod +x tests/ragas/run-ragas.sh && tests/ragas/run-ragas.sh",
"postinstall": "node fix-uuid.js"
"ragas": "chmod +x tests/ragas/run-ragas.sh && tests/ragas/run-ragas.sh"
},
"dependencies": {
"@dkg/expo-forcegraph": "^0.0.0",
Expand All @@ -39,13 +38,13 @@
"@expo-google-fonts/manrope": "^0.4.1",
"@expo-google-fonts/space-grotesk": "^0.4.0",
"@expo/vector-icons": "^14.1.0",
"@langchain/anthropic": "^0.3.28",
"@langchain/core": "^0.3.66",
"@langchain/google-genai": "^0.2.18",
"@langchain/groq": "^0.2.4",
"@langchain/mistralai": "^0.2.1",
"@langchain/openai": "^0.6.3",
"@langchain/xai": "^0.1.0",
"@langchain/anthropic": "^1.3.22",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: This upgrades LangChain packages across major versions, but the PR does not add regression coverage for the changed content-shape handling in chat parsing. Add tests for both string/object image_url blocks and non-string/missing text fields so migration regressions are caught.

"@langchain/core": "^1.1.30",
"@langchain/google-genai": "^2.1.24",
"@langchain/groq": "^1.1.4",
"@langchain/mistralai": "^1.0.7",
"@langchain/openai": "^1.2.12",
"@langchain/xai": "^1.3.8",
"@modelcontextprotocol/sdk": "^1.16.0",
"@node-rs/argon2": "^2.0.2",
"@react-native-async-storage/async-storage": "2.1.2",
Expand Down
60 changes: 35 additions & 25 deletions apps/agent/src/app/(protected)/chat.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { View, Platform, KeyboardAvoidingView, ScrollView } from "react-native";
import { Image } from "expo-image";
import * as Clipboard from "expo-clipboard";
import { Image } from "expo-image";
import { fetch } from "expo/fetch";
import { useCallback, useEffect, useRef, useState } from "react";
import { KeyboardAvoidingView, Platform, ScrollView, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
//import AsyncStorage from "@react-native-async-storage/async-storage";
import {
Expand All @@ -11,17 +11,18 @@ import {
} from "@dkg/plugin-dkg-essentials/utils";

import { useMcpClient } from "@/client";
import useMcpToolsSession from "@/hooks/useMcpToolsSession";
import useColors from "@/hooks/useColors";
import usePlatform from "@/hooks/usePlatform";
import Page from "@/components/layout/Page";
import Container from "@/components/layout/Container";
import Header from "@/components/layout/Header";
import { useAlerts } from "@/components/Alerts";
import Chat from "@/components/Chat";
import { SourceKAResolver } from "@/components/Chat/Message/SourceKAs/CollapsibleItem";
import Container from "@/components/layout/Container";
import Header from "@/components/layout/Header";
import Page from "@/components/layout/Page";
import Markdown from "@/components/Markdown";
import { useAlerts } from "@/components/Alerts";
import useColors from "@/hooks/useColors";
import useMcpToolsSession from "@/hooks/useMcpToolsSession";
import usePlatform from "@/hooks/usePlatform";

import useSettings from "@/hooks/useSettings";
import {
type ChatMessage,
type ToolCall,
Expand All @@ -30,23 +31,22 @@ import {
makeStreamingCompletionRequest,
toContents,
} from "@/shared/chat";
import { toError } from "@/shared/errors";
import {
FileDefinition,
parseFilesFromContent,
serializeFiles,
uploadFiles,
} from "@/shared/files";
import { toError } from "@/shared/errors";
import useSettings from "@/hooks/useSettings";
import {
isThinkingVisible,
shouldStopGenerating,
} from "@/shared/thinkingIndicator";
import {
type ToolExecutionMode,
toToolExecutionMode,
toToolExecutionSettings,
} from "@/shared/toolExecutionMode";
import {
isThinkingVisible,
shouldStopGenerating,
} from "@/shared/thinkingIndicator";

function normalizeStreamingMarkdown(content: string): string {
const fencePattern = /^(`{3,})[^`]*$/gm;
Expand Down Expand Up @@ -118,7 +118,10 @@ export default function ChatPage() {

const s = toToolExecutionSettings(mode);
await settings.set("autoApproveMcpTools", s.autoApproveMcpTools);
await settings.set("showMcpToolExecutionPanels", s.showMcpToolExecutionPanels);
await settings.set(
"showMcpToolExecutionPanels",
s.showMcpToolExecutionPanels,
);
await settings.reload();
},
[settings, tools],
Expand Down Expand Up @@ -180,8 +183,7 @@ export default function ChatPage() {
continue;
}

const existingId =
typeof tc.id === "string" ? tc.id.trim() : "";
const existingId = typeof tc.id === "string" ? tc.id.trim() : "";
normalizedToolCalls.push({
...tc,
id: existingId || `local-tool-call-${localToolCallIdCounter.current++}`,
Expand Down Expand Up @@ -637,7 +639,7 @@ export default function ChatPage() {
const text: string[] = [];

for (const c of toContents(m.content)) {
if (c.type === "image_url") {
if (c.type === "image_url" && typeof c.image_url === "string") {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Bug: This now only handles image_url when it is a string, but LangChain message blocks can also provide image_url as an object ({ url: ... }), so those images are silently dropped. Normalize both shapes (e.g. string or c.image_url?.url) before pushing to images.

images.push({ uri: c.image_url });
continue;
}
Expand All @@ -658,7 +660,7 @@ export default function ChatPage() {
continue;
}

text.push(c.text);
text.push(c.text as string);
}
}

Expand All @@ -667,7 +669,8 @@ export default function ChatPage() {
const allToolCallsHidden =
hasToolCalls &&
m.tool_calls!.every((tc) => {
const isAutoApproved = autoApproveTools || tools.isAllowedForSession(tc.name);
const isAutoApproved =
autoApproveTools || tools.isAllowedForSession(tc.name);
return isAutoApproved && !showToolExecutionPanels;
});

Expand Down Expand Up @@ -792,7 +795,10 @@ export default function ChatPage() {
lastUserMessageYRef.current = y;
if (scrollPendingRef.current) {
scrollPendingRef.current = false;
scrollTargetRef.current = Math.max(0, y - SCROLL_TOP_GAP);
scrollTargetRef.current = Math.max(
0,
y - SCROLL_TOP_GAP,
);
setContentMinHeight(y + messagesViewHeight);
}
}}
Expand All @@ -804,11 +810,15 @@ export default function ChatPage() {

return <View key={i}>{messageContent}</View>;
})}
{isThinkingVisible(isGenerating, streamingContent) && <Chat.Thinking />}
{isThinkingVisible(isGenerating, streamingContent) && (
<Chat.Thinking />
)}
{streamingContent !== null && (
<Chat.Message icon="assistant">
<Markdown>
{normalizeStreamingMarkdown(stripThinkTags(streamingContent))}
{normalizeStreamingMarkdown(
stripThinkTags(streamingContent),
)}
</Markdown>
</Chat.Message>
)}
Expand Down
Loading
Loading