-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: add file:// URI support in agent prompt_append #821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
|
@sisyphus-dev-ai review this ulw |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 4 files
Confidence score: 3/5
- Handling of percent-encoded file URIs in
src/agents/utils.tsis incomplete, so validfile://paths with encoded characters won’t load and instead produce false warnings. - This impacts users relying on encoded characters in file paths, making URI handling less reliable than expected.
- Pay close attention to
src/agents/utils.ts- ensure percent-encoded segments are properly decoded before path resolution.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/agents/utils.ts">
<violation number="1" location="src/agents/utils.ts:128">
P2: File URI parsing ignores percent-encoding, so valid file:// URIs with encoded characters won’t resolve and trigger false warnings instead of loading the file.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Ultrawork Review: PR #821 - file:// URI Support in prompt_appendOverall Assessment: ✅ Good feature with VALID bug identified by cubic-dev-ai ✅ What's Excellent
🐛 VALID Issue (identified by @cubic-dev-ai)The percent-encoding issue is REAL and should be fixed. ProblemCurrent implementation strips const path = prompt_append.slice(7) // Just removes "file://"
const abs = path.startsWith("~/") ? resolve(homedir(), path.slice(2)) : ...This DOES NOT handle percent-encoded URIs:
Evidence from CodebaseThe project already uses the standard solution elsewhere:
Recommended FixUse Node.js built-in import { fileURLToPath } from "node:url"
if (prompt_append.startsWith("file://")) {
try {
const abs = fileURLToPath(prompt_append) // Handles percent-encoding + all edge cases
resolved = existsSync(abs)
? readFileSync(abs, "utf-8")
: `[WARNING: Could not resolve file URI: ${prompt_append}]`
} catch (err) {
resolved = `[WARNING: Invalid file URI: ${prompt_append}]`
}
}Why this is better:
📝 Missing Test CaseAdd test for percent-encoded URIs: test("resolves file:// URI with percent-encoded spaces", () => {
// #given - file with spaces in name
const fileWithSpaces = join(TEST_DIR, "custom prompt.md")
writeFileSync(fileWithSpaces, "Content from spaced file")
const encodedPath = fileWithSpaces.replace(/ /g, "%20")
const overrides = { oracle: { prompt_append: `file://${encodedPath}` } }
// #when
const agents = createBuiltinAgents([], overrides, TEST_DIR)
// #then
expect(agents.oracle.prompt).toContain("Content from spaced file")
})🎯 Verification Checklist
🚀 RecommendationACTION REQUIRED: Fix the percent-encoding bug before merge. The feature is solid but the bug will cause frustration for users with:
Using Review completed with exhaustive search across:
Credit to @cubic-dev-ai for identifying this - the issue is accurate and should be addressed. |
Properly handle encoded characters (e.g., %20 for spaces) when resolving file:// URIs in prompt_append configuration. Adds decodeURIComponent() to unwrap percent-encoded paths before filesystem access. Includes test case verifying percent-encoded paths with spaces can be loaded.
|
The flaky test failure in Fixed in #822 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/agents/utils.ts">
<violation number="1" location="src/agents/utils.ts:128">
P2: Uncaught decodeURIComponent URIError can crash agent config creation on malformed file:// paths.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Fix Applied: Percent-Encoding SupportThanks @cubic-dev-ai for identifying this issue and @sisyphus-dev-ai for the detailed review! What was fixedCommit const path = decodeURIComponent(prompt_append.slice(7))Test case added: Verifies that Why
|
| URI Format | fileURLToPath() |
decodeURIComponent() |
|---|---|---|
file:///absolute/path |
✅ Works | ✅ Works |
file://~/home/path |
❌ ERR_INVALID_FILE_URL_HOST |
✅ Works |
file://./relative/path |
❌ ERR_INVALID_FILE_URL_HOST |
✅ Works |
This PR intentionally introduces custom URI formats (file://~/... and file://./...) that extend standard file URIs for user convenience. These are not valid RFC 8089 URIs, so fileURLToPath() rejects them.
The decodeURIComponent() approach:
- ✅ Handles percent-encoding (spaces, special chars, non-ASCII)
- ✅ Preserves home-relative path support (
~/) - ✅ Preserves relative path support
- ✅ All tests pass
|
@sisyphus-dev-ai review again ulw |
Ultrawork Review: PR #821 - file:// URI Support (Round 2)Overall Assessment: ✅ What's Working Excellently
🐛 CRITICAL BUG (identified by @cubic-dev-ai)Issue: Evidence (empirically verified): decodeURIComponent('test%20file.md') // ✅ Works: "test file.md"
decodeURIComponent('test%') // ❌ Throws: URIError: URI error
decodeURIComponent('test%GG') // ❌ Throws: URIError: URI errorVerified with: bun --eval "console.log(decodeURIComponent('test%20file.md')); try { decodeURIComponent('test%'); } catch(e) { console.log('CRASH:', e.message); }"
# Output:
# test file.md
# CRASH: URI errorImpact:
Real-world scenarios:
💡 Recommended FixApply @cubic-dev-ai's suggested fix with minor refinement: if (prompt_append.startsWith("file://")) {
const uriPath = prompt_append.slice(7)
let path: string
try {
path = decodeURIComponent(uriPath)
} catch (e) {
// Malformed percent-encoding - show warning and skip file resolution
resolved = `[WARNING: Malformed file URI (invalid percent-encoding): ${prompt_append}]`
path = "" // Skip file resolution
}
if (path) {
const abs = path.startsWith("~/")
? resolve(homedir(), path.slice(2))
: isAbsolute(path)
? path
: resolve(configDir ?? process.cwd(), path)
resolved = existsSync(abs)
? readFileSync(abs, "utf-8")
: `[WARNING: Could not resolve file URI: ${prompt_append}]`
}
}Why this approach:
📝 Missing Test CaseAdd test for malformed percent-encoding: test("handles malformed percent-encoding in file URI with warning", () => {
// #given - malformed percent-encoding
const overrides = {
oracle: { prompt_append: "file://my%prompt.md" },
}
// #when
const agents = createBuiltinAgents([], overrides, TEST_DIR)
// #then
expect(agents.oracle.prompt).toContain("[WARNING: Malformed file URI (invalid percent-encoding): file://my%prompt.md]")
})🎯 Verification Checklist
🚀 RecommendationACTION REQUIRED: Add try-catch around This is a 5-minute fix that prevents potential session crashes. The feature is otherwise production-ready and well-designed. 🙏 Credit
Review Methodology:
The bug is real, the fix is simple, and the feature will be rock-solid after this final change. Confidence: 100% - Bug is empirically verified, fix is standard practice, and the rest of the implementation is excellent. |
Add try-catch wrapper around decodeURIComponent() to gracefully handle invalid percent-encoding sequences (e.g., file://my%prompt.md). Shows warning message instead of crashing with URIError. Add test case verifying warning output for malformed URIs.
Fix Applied: Malformed URI Error HandlingThanks @sisyphus-dev-ai for the thorough review! What was fixedCommit let path: string
try {
path = decodeURIComponent(prompt_append.slice(7))
} catch {
resolved = `[WARNING: Malformed file URI (invalid percent-encoding): ${prompt_append}]`
path = ""
}Test case added: Verifies that Verification
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 issues found across 2 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/agents/utils.ts">
<violation number="1" location="src/agents/utils.ts:137">
P1: `file://` prompt_append reads arbitrary filesystem paths (including absolute/home) without sandboxing, enabling secret exfiltration by untrusted config</violation>
<violation number="2" location="src/agents/utils.ts:142">
P2: Uncaught fs errors on file:// prompt_append can crash config merge (invalid path or unreadable file throws before warning)</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| } | ||
|
|
||
| if (path) { | ||
| const abs = path.startsWith("~/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: file:// prompt_append reads arbitrary filesystem paths (including absolute/home) without sandboxing, enabling secret exfiltration by untrusted config
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/agents/utils.ts, line 137:
<comment>`file://` prompt_append reads arbitrary filesystem paths (including absolute/home) without sandboxing, enabling secret exfiltration by untrusted config</comment>
<file context>
@@ -125,15 +125,24 @@ function mergeAgentConfig(
+ }
+
+ if (path) {
+ const abs = path.startsWith("~/")
+ ? resolve(homedir(), path.slice(2))
+ : isAbsolute(path)
</file context>
| resolved = existsSync(abs) | ||
| ? readFileSync(abs, "utf-8") | ||
| : `[WARNING: Could not resolve file URI: ${prompt_append}]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Uncaught fs errors on file:// prompt_append can crash config merge (invalid path or unreadable file throws before warning)
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/agents/utils.ts, line 142:
<comment>Uncaught fs errors on file:// prompt_append can crash config merge (invalid path or unreadable file throws before warning)</comment>
<file context>
@@ -125,15 +125,24 @@ function mergeAgentConfig(
+ : isAbsolute(path)
+ ? path
+ : resolve(configDir ?? process.cwd(), path)
+ resolved = existsSync(abs)
+ ? readFileSync(abs, "utf-8")
+ : `[WARNING: Could not resolve file URI: ${prompt_append}]`
</file context>
| resolved = existsSync(abs) | |
| ? readFileSync(abs, "utf-8") | |
| : `[WARNING: Could not resolve file URI: ${prompt_append}]` | |
| if (abs.includes("\0")) { | |
| resolved = `[WARNING: Invalid file path in URI: ${prompt_append}]` | |
| } else { | |
| try { | |
| resolved = existsSync(abs) | |
| ? readFileSync(abs, "utf-8") | |
| : `[WARNING: Could not resolve file URI: ${prompt_append}]` | |
| } catch { | |
| resolved = `[WARNING: Failed to read file URI: ${prompt_append}]` | |
| } | |
| } |
Summary
Add
file://URI support inprompt_appendto load agent instructions from external files.Examples
Load from home directory:
{ "agents": { "oracle": { "prompt_append": "file://~/.config/opencode/my-oracle-rules.md" } } }Load project-specific context:
{ "agents": { "Sisyphus": { "prompt_append": "file://./docs/ai-context.md" } } }Combine with model override:
{ "agents": { "librarian": { "model": "anthropic/claude-sonnet-4", "prompt_append": "file://~/.config/opencode/research-guidelines.md" } } }Supported Formats
file:///Users/me/prompt.md/Users/me/prompt.mdfile://./context.md{project}/context.mdfile://~/prompts/rules.md~/prompts/rules.mdReturns
[WARNING: Could not resolve file URI: ...]if file not found.