Skip to content

Experimental page#1

Merged
NoEgAm merged 8 commits into
mainfrom
experiment
Mar 10, 2026
Merged

Experimental page#1
NoEgAm merged 8 commits into
mainfrom
experiment

Conversation

@tiye
Copy link
Copy Markdown
Member

@tiye tiye commented Dec 20, 2025

No description provided.

Copilot AI review requested due to automatic review settings December 20, 2025 04:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR replaces the demo counter application with an experimental query interface for MoonBit documentation. It introduces async HTTP request capabilities and a new UI component for submitting queries to the Moonverse API and displaying markdown-formatted results.

  • Replaced counter demo with a query interface component
  • Added HTTP/fetch API integration with async polling support
  • Introduced markdown rendering capability for query results

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
src/store.mbt Updated store structure to track query results and errors instead of counter state; replaced Increment/Decrement actions with StartQuery/QuerySuccess/QueryError
src/requests.mbt New file implementing JavaScript FFI for fetch API, including both a pure JS async implementation and a MoonBit async version for query execution with polling
src/query_comp.mbt New UI component providing input field, submit button, loading states, and result/error display with styling
src/moon.pkg.json Added dependencies for markdown rendering and async JavaScript support
src/main/counter.mbt Removed the old counter component implementation
src/main.mbt Updated app store key, replaced counter component with query component, added async query handler (though appears unused)
moon.mod.json Added module dependencies for async and markdown packages
index.html Updated script path to point to new build output location
Comments suppressed due to low confidence (2)

src/requests.mbt:121

  • The JSON body construction uses manual string concatenation which is error-prone and doesn't properly escape the prompt value. If the prompt contains quotes or special characters, it will produce invalid JSON. Consider using a proper JSON serialization method.
  let body = "{\"prompt\": \"" + prompt + "\", \"mode\": \"hybrid\"}"

src/main.mbt:63

  • The async code in this match block appears to be unreachable dead code. The StartQuery action is already handled in query_comp.mbt where start_query_request is called directly, which uses run_query_js. This code path would never execute because run_query_js handles the async operation completely. This entire match block should be removed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/requests.mbt
#| (ms) => new Promise(resolve => setTimeout(resolve, ms))

///|
/// Helper to schedule an async function to run on the next tick
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

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

This extern function lacks documentation explaining its purpose, parameters, and behavior. Consider adding a doc comment describing that this schedules an async promise to run and handles errors.

Suggested change
/// Helper to schedule an async function to run on the next tick
/// Schedule a JavaScript `Promise[Unit]` to run asynchronously (e.g. on the next
/// event-loop tick). The given `promise` is started and its completion is ignored,
/// but any rejection is caught and logged via `console.error` to prevent unhandled
/// promise rejections from propagating into MoonBit code.

Copilot uses AI. Check for mistakes.
Comment thread src/requests.mbt
prompt : String,
on_success : (String) -> Unit,
on_error : (String) -> Unit,
) -> Unit =
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

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

This complex inline JavaScript function lacks proper documentation. Consider adding a doc comment explaining the query flow: POST to create query task, poll for completion, handle success/error states, and describe the callback parameters.

Suggested change
) -> Unit =
) -> Unit =
#| /**
#| * Runs a query against the backend service and returns the result via callbacks.
#| *
#| * Flow:
#| * 1. Determine the base URL from the `mode` query parameter (`dev` vs production).
#| * 2. POST `{ type: "hybrid", query: prompt }` to `${baseUrl}/query` to create a query task.
#| * 3. If the POST succeeds, read `id` from the JSON response.
#| * 4. Poll `${baseUrl}/query/${id}` with GET in a loop until the task completes:
#| * - When `status === "done"`, invoke `onSuccess` with `content` or `result` (or `""`).
#| * - When `status === "error"`, invoke `onError` with the error message or a fallback.
#| * 5. For HTTP failures or unexpected exceptions, log the error and invoke `onError`.
#| *
#| * @param {string} prompt
#| * User prompt to send to the backend query endpoint.
#| * @param {(result: string) => void} onSuccess
#| * Called once when the query finishes successfully with the final textual result.
#| * @param {(error: string) => void} onError
#| * Called on HTTP errors, backend error status, or unexpected exceptions.
#| */

Copilot uses AI. Check for mistakes.
Comment thread src/requests.mbt
Comment on lines +117 to +162
// Async function to run the query

///|
pub async fn run_query(prompt : String) -> String raise Failure {
let body = "{\"prompt\": \"" + prompt + "\", \"mode\": \"hybrid\"}"
let options = make_post_options(body)

// POST /query
let resp = fetch("http://localhost:8080/query", options).wait() catch {
error => raise Failure("Fetch failed: " + error.to_string())
}
if not(resp.ok()) {
raise Failure("Failed to start query: " + resp.status().to_string())
}
let json_resp = resp.json().wait() catch {
error => raise Failure("JSON parse failed: " + error.to_string())
}
let id = get_id(json_resp)

// Poll /query/{id}
while true {
let poll_resp = fetch(
"http://localhost:8080/query/" + id,
make_get_options(),
).wait() catch {
error => raise Failure("Poll fetch failed: " + error.to_string())
}
if not(poll_resp.ok()) {
raise Failure("Failed to poll query: " + poll_resp.status().to_string())
}
let poll_json = poll_resp.json().wait() catch {
error => raise Failure("Poll JSON parse failed: " + error.to_string())
}
let status = get_status(poll_json)
if status == "done" {
break get_result(poll_json)
} else if status == "error" {
raise Failure("Query failed")
}
sleep(1000).wait() catch {
_ => ()
}
} else {
raise Failure("Unreachable")
}
}
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

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

This async function run_query appears to be unused in the codebase. The actual implementation uses run_query_js (lines 67-115) which is a pure JavaScript async function. This function should either be removed or the code should be refactored to use it instead of run_query_js.

Suggested change
// Async function to run the query
///|
pub async fn run_query(prompt : String) -> String raise Failure {
let body = "{\"prompt\": \"" + prompt + "\", \"mode\": \"hybrid\"}"
let options = make_post_options(body)
// POST /query
let resp = fetch("http://localhost:8080/query", options).wait() catch {
error => raise Failure("Fetch failed: " + error.to_string())
}
if not(resp.ok()) {
raise Failure("Failed to start query: " + resp.status().to_string())
}
let json_resp = resp.json().wait() catch {
error => raise Failure("JSON parse failed: " + error.to_string())
}
let id = get_id(json_resp)
// Poll /query/{id}
while true {
let poll_resp = fetch(
"http://localhost:8080/query/" + id,
make_get_options(),
).wait() catch {
error => raise Failure("Poll fetch failed: " + error.to_string())
}
if not(poll_resp.ok()) {
raise Failure("Failed to poll query: " + poll_resp.status().to_string())
}
let poll_json = poll_resp.json().wait() catch {
error => raise Failure("Poll JSON parse failed: " + error.to_string())
}
let status = get_status(poll_json)
if status == "done" {
break get_result(poll_json)
} else if status == "error" {
raise Failure("Query failed")
}
sleep(1000).wait() catch {
_ => ()
}
} else {
raise Failure("Unreachable")
}
}
// Async function run_query(prompt : String) removed because it was unused;
// run_query_js is the active implementation used by this module.

Copilot uses AI. Check for mistakes.
Comment thread src/requests.mbt
let options = make_post_options(body)

// POST /query
let resp = fetch("http://localhost:8080/query", options).wait() catch {
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

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

The hardcoded URL "http://localhost:8080" should be made configurable or use the same baseUrl logic as in run_query_js. The run_query_js function correctly handles both development and production environments by checking for a "mode" URL parameter, but this function doesn't.

Copilot uses AI. Check for mistakes.
Comment thread src/query_comp.mbt Outdated
Comment thread src/query_comp.mbt Outdated
Comment thread src/query_comp.mbt Outdated
Comment thread src/query_comp.mbt Outdated
Comment thread src/query_comp.mbt Outdated
Comment thread src/requests.mbt

///|
pub async fn run_query(prompt : String) -> String raise Failure {
let body = "{\"prompt\": \"" + prompt + "\", \"mode\": \"hybrid\"}"
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

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

In run_query, the user-controlled prompt is concatenated directly into a JSON string without any escaping, so a value like "x", "mode": "evil" would break out of the "prompt" field and inject additional JSON keys or otherwise change the structure of the body sent to the backend. This constitutes a string injection issue because structured JSON is being constructed via string concatenation instead of a safe JSON encoder, allowing untrusted input to alter the semantics of the request. Use a proper JSON serialization API or rigorously escape prompt for JSON context before building the body so that user input cannot modify the JSON structure.

Copilot uses AI. Check for mistakes.
@tiye tiye requested a review from a team January 4, 2026 17:25
@NoEgAm
Copy link
Copy Markdown
Contributor

NoEgAm commented Jan 15, 2026

no access

@tiye
Copy link
Copy Markdown
Member Author

tiye commented Jan 15, 2026

@NoEgAm my bad, please try again

@NoEgAm NoEgAm merged commit e880037 into main Mar 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants