From 5a950de0ba9de9358d11d6321562e7b34ccf870d Mon Sep 17 00:00:00 2001 From: Guillaume ARM Date: Thu, 11 Jun 2026 18:34:32 +0200 Subject: [PATCH] feat(ai): add atm10 expert agent --- .opencode/agent-context/atm10-expert/INDEX.md | 30 +++++ .../advanced_peripherals_glossary.md | 0 .../atm10-expert/glossaries}/cc_glossary.md | 0 .../glossaries}/create_cc_tweaked_glossary.md | 0 .../atm10-expert/modpacks/atm10-7.0.md | 20 ++++ .../scripts/fetch-atm10-7.0-mods.sh | 93 +++++++++++++++ .opencode/agent/atm10-expert.md | 61 ++++++++++ .opencode/agent/computercraft.md | 37 ------ ATM_EXPERT_AGENT_PLAN.md | 109 ++++++++++++++++++ apis/libai.lua | 41 ++++++- docs/README.md | 4 +- docs/ingame-trapos-ai-mcp-guide.md | 2 +- docs/opencode_api.md | 4 +- docs/opencode_server_guide.md | 4 +- programs/ai.lua | 2 +- tests/ai.lua | 82 +++++++++++-- 16 files changed, 432 insertions(+), 57 deletions(-) create mode 100644 .opencode/agent-context/atm10-expert/INDEX.md rename {docs => .opencode/agent-context/atm10-expert/glossaries}/advanced_peripherals_glossary.md (100%) rename {docs => .opencode/agent-context/atm10-expert/glossaries}/cc_glossary.md (100%) rename {docs => .opencode/agent-context/atm10-expert/glossaries}/create_cc_tweaked_glossary.md (100%) create mode 100644 .opencode/agent-context/atm10-expert/modpacks/atm10-7.0.md create mode 100755 .opencode/agent-context/atm10-expert/scripts/fetch-atm10-7.0-mods.sh create mode 100644 .opencode/agent/atm10-expert.md delete mode 100644 .opencode/agent/computercraft.md create mode 100644 ATM_EXPERT_AGENT_PLAN.md diff --git a/.opencode/agent-context/atm10-expert/INDEX.md b/.opencode/agent-context/atm10-expert/INDEX.md new file mode 100644 index 0000000..3643922 --- /dev/null +++ b/.opencode/agent-context/atm10-expert/INDEX.md @@ -0,0 +1,30 @@ +# ATM10 Expert Context Index + +Local context for the `atm10-expert` opencode agent. + +## Target Pack + +- ATM10 / All The Mods 10 version `7.0` (`0.7.0` is accepted as a user alias). +- Minecraft `1.21.1`. +- NeoForge `21.1.228`. +- CurseForge project id `925200`. +- Client pack file id `8091114`. +- Server pack file id `8094893`. +- Source: [AllTheMods/ATM-10](https://github.com/AllTheMods/ATM-10). + +## Local Glossaries + +- [CC:Tweaked glossary](glossaries/cc_glossary.md) - globals, modules, peripherals, events, and guides. +- [Advanced Peripherals glossary](glossaries/advanced_peripherals_glossary.md) - Advanced Peripherals 0.7 guides, peripherals, turtles, integrations, and changelog pages. +- [Create CC:Tweaked glossary](glossaries/create_cc_tweaked_glossary.md) - Create CC:Tweaked integration pages. + +## Modpack Notes + +- [ATM10 7.0 modpack](modpacks/atm10-7.0.md) - pack metadata and generated CurseForge mod ids. + +## Update Workflow + +- Use local glossaries first when answering in-game questions. +- Use web lookup when local context is missing, stale, or too shallow. +- When a useful durable documentation source is found, update or create a glossary and update this index. +- Refresh the mod id list with `./.opencode/agent-context/atm10-expert/scripts/fetch-atm10-7.0-mods.sh`. diff --git a/docs/advanced_peripherals_glossary.md b/.opencode/agent-context/atm10-expert/glossaries/advanced_peripherals_glossary.md similarity index 100% rename from docs/advanced_peripherals_glossary.md rename to .opencode/agent-context/atm10-expert/glossaries/advanced_peripherals_glossary.md diff --git a/docs/cc_glossary.md b/.opencode/agent-context/atm10-expert/glossaries/cc_glossary.md similarity index 100% rename from docs/cc_glossary.md rename to .opencode/agent-context/atm10-expert/glossaries/cc_glossary.md diff --git a/docs/create_cc_tweaked_glossary.md b/.opencode/agent-context/atm10-expert/glossaries/create_cc_tweaked_glossary.md similarity index 100% rename from docs/create_cc_tweaked_glossary.md rename to .opencode/agent-context/atm10-expert/glossaries/create_cc_tweaked_glossary.md diff --git a/.opencode/agent-context/atm10-expert/modpacks/atm10-7.0.md b/.opencode/agent-context/atm10-expert/modpacks/atm10-7.0.md new file mode 100644 index 0000000..cb4eb27 --- /dev/null +++ b/.opencode/agent-context/atm10-expert/modpacks/atm10-7.0.md @@ -0,0 +1,20 @@ +# ATM10 7.0 Modpack + +Known facts for ATM10 / All The Mods 10 version `7.0`. + +## Pack Metadata + +- Minecraft: `1.21.1`. +- NeoForge: `21.1.228`. +- CurseForge project id: `925200`. +- Client pack file id: `8091114`. +- Server pack file id: `8094893`. +- Source: [AllTheMods/ATM-10](https://github.com/AllTheMods/ATM-10). + +## Mod List + +The mod list is generated by [`../scripts/fetch-atm10-7.0-mods.sh`](../scripts/fetch-atm10-7.0-mods.sh). + +Run it with `CURSEFORGE_API_KEY` to resolve project names through the CurseForge API. Without an API key, the generated table preserves raw project/file ids and API URLs for later enrichment. + +Generated list: not fetched yet. diff --git a/.opencode/agent-context/atm10-expert/scripts/fetch-atm10-7.0-mods.sh b/.opencode/agent-context/atm10-expert/scripts/fetch-atm10-7.0-mods.sh new file mode 100755 index 0000000..bdeda22 --- /dev/null +++ b/.opencode/agent-context/atm10-expert/scripts/fetch-atm10-7.0-mods.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_ID=925200 +FILE_ID=8091114 +SERVER_FILE_ID=8094893 +NEOFORGE_VERSION=21.1.228 + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +CONTEXT_DIR="$(cd -- "${SCRIPT_DIR}/.." && pwd)" +OUTPUT="${CONTEXT_DIR}/modpacks/atm10-7.0.md" +TMP_DIR="$(mktemp -d)" + +cleanup() { + rm -rf "${TMP_DIR}" +} +trap cleanup EXIT + +require_cmd() { + if ! command -v "$1" >/dev/null 2>&1; then + printf 'missing required command: %s\n' "$1" >&2 + exit 1 + fi +} + +require_cmd curl +require_cmd jq +require_cmd unzip + +ARCHIVE="${TMP_DIR}/atm10-${FILE_ID}.zip" +MANIFEST="${TMP_DIR}/manifest.json" +PROJECTS="${TMP_DIR}/projects.json" + +download_url='' +if [ -n "${CURSEFORGE_API_KEY:-}" ]; then + download_url="$(curl -fsS \ + -H "x-api-key: ${CURSEFORGE_API_KEY}" \ + "https://api.curseforge.com/v1/mods/${PROJECT_ID}/files/${FILE_ID}/download-url" \ + | jq -r '.data // empty')" +fi + +if [ -n "${download_url}" ]; then + curl -fL --retry 3 -o "${ARCHIVE}" "${download_url}" +else + curl -fL --retry 3 -o "${ARCHIVE}" \ + "https://www.curseforge.com/api/v1/mods/${PROJECT_ID}/files/${FILE_ID}/download" +fi + +unzip -p "${ARCHIVE}" manifest.json > "${MANIFEST}" + +if [ -n "${CURSEFORGE_API_KEY:-}" ]; then + mod_ids="$(jq -c '[.files[].projectID] | unique' "${MANIFEST}")" + curl -fsS \ + -H "x-api-key: ${CURSEFORGE_API_KEY}" \ + -H 'content-type: application/json' \ + -d "{\"modIds\":${mod_ids}}" \ + 'https://api.curseforge.com/v1/mods' > "${PROJECTS}" +else + printf '{"data":[]}\n' > "${PROJECTS}" +fi + +{ + printf '# ATM10 7.0 Modpack\n\n' + printf 'Generated from CurseForge client file `%s`.\n\n' "${FILE_ID}" + printf 'Last generated: `%s`.\n\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" + printf '## Pack Metadata\n\n' + printf -- '- Minecraft: `%s`.\n' "$(jq -r '.minecraft.version // "1.21.1"' "${MANIFEST}")" + printf -- '- NeoForge: `%s`.\n' "${NEOFORGE_VERSION}" + printf -- '- CurseForge project id: `%s`.\n' "${PROJECT_ID}" + printf -- '- Client pack file id: `%s`.\n' "${FILE_ID}" + printf -- '- Server pack file id: `%s`.\n' "${SERVER_FILE_ID}" + printf -- '- Source: [AllTheMods/ATM-10](https://github.com/AllTheMods/ATM-10).\n\n' + printf '## Manifest\n\n' + jq -r '"- Name: `" + (.name // "unknown") + "`.", "- Version: `" + (.version // "unknown") + "`."' "${MANIFEST}" + printf '\n## Mods\n\n' + printf '| Project id | File id | Name | Reference |\n' + printf '| --- | --- | --- | --- |\n' + jq -r --slurpfile projects "${PROJECTS}" ' + def project($id): (($projects[0].data // [])[]? | select(.id == $id)) // {}; + def cell: tostring | gsub("\\|"; "\\\\|"); + .files[] + | project(.projectID) as $project + | [ + (.projectID | tostring), + (.fileID | tostring), + (($project.name // "unresolved") | cell), + (($project.links.websiteUrl // ("https://api.curseforge.com/v1/mods/" + (.projectID | tostring))) | cell) + ] + | "| " + join(" | ") + " |" + ' "${MANIFEST}" +} > "${OUTPUT}" + +printf 'wrote %s\n' "${OUTPUT}" diff --git a/.opencode/agent/atm10-expert.md b/.opencode/agent/atm10-expert.md new file mode 100644 index 0000000..4c3fe97 --- /dev/null +++ b/.opencode/agent/atm10-expert.md @@ -0,0 +1,61 @@ +--- +description: Answers in-game ATM10, ComputerCraft, CC:Tweaked, Advanced Peripherals, Create, and TrapOS user questions with concise player-facing replies; use for programs/ai.lua requests when opencc.agent is atm10-expert. +mode: primary +permission: + "*": deny + read: allow + glob: allow + grep: allow + webfetch: allow + websearch: allow + edit: ask + bash: + "*": ask + "just check": allow + computercraft-mcp-bridge_probe-computers: allow + computercraft-mcp-bridge_exec-lua: allow +--- + +You answer players using TrapOS `ai` from inside ATM10 / All The Mods 10. + +Target environment: + +- ATM10 / All The Mods 10 pack version `7.0`; accept `0.7.0` as the same user alias. +- Minecraft `1.21.1`. +- NeoForge `21.1.228`. +- ComputerCraft is CC:Tweaked in the ComputerCraft sandbox, not desktop Lua. + +Response style: + +- Keep replies short for in-game terminals. Prefer 1-4 concise lines. +- Default to practical, non-technical answers unless the user asks for details. +- Answer in the user's language; usually French when the prompt is French. +- When giving commands, make them directly runnable in CraftOS when possible. +- When giving code, keep it minimal and runnable. Avoid markdown fences unless the user clearly asks for a code block. +- If the prompt asks for raw Lua code only, output raw Lua only with no markdown or explanation. + +Context workflow: + +- Use `.opencode/agent-context/atm10-expert/INDEX.md` first. +- Prefer local glossaries and modpack notes before web lookup. +- Use web search or fetch only for current external facts, missing mod documentation, or stale local references. +- If you find a useful durable mod documentation source, ask before editing, then update or create a glossary and update `INDEX.md`. + +MCP bridge safety: + +- You may use the ComputerCraft MCP bridge only through `probe-computers` and `exec-lua`. +- Use `probe-computers` before `exec-lua` unless the target computer id is already clear from the hidden caller context or conversation. +- Treat `exec-lua` as privileged in-game execution. Prefer read-only inspection. +- Do not delete files, reboot or shut down computers, move turtles, change inventories, transmit network traffic, mutate peripherals, or run long loops unless the user explicitly asks for that specific effect. +- Keep `exec-lua` snippets small and bounded. Use short timeouts. Avoid blocking pulls, sleeps, infinite loops, and assumptions that a timeout stops code already running in ComputerCraft. +- `print()` and `write()` output is captured in MCP results. To intentionally write to the visible ComputerCraft screen, use terminal APIs such as `term.clear()`, `term.setCursorPos()`, and `term.write()`. + +Caller context: + +- TrapOS may prepend hidden caller context with the ComputerCraft computer id and label. +- Use that context to choose the right MCP target, but do not expose it unless it helps the user. + +Repository scope: + +- If the user asks for repo internals, answer only what is needed to unblock them. +- This agent is explicit and player-facing. Do not assume it is the default coding assistant. diff --git a/.opencode/agent/computercraft.md b/.opencode/agent/computercraft.md deleted file mode 100644 index 5e93eb9..0000000 --- a/.opencode/agent/computercraft.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -description: Answers in-game ComputerCraft and TrapOS user questions with concise, actionable replies; use for programs/ai.lua requests. -mode: primary -permission: - "*": deny - websearch: allow - computercraft-mcp-bridge_probe-computers: allow - computercraft-mcp-bridge_exec-lua: allow ---- - -You answer ComputerCraft / CC:Tweaked users from inside Minecraft through TrapOS `ai`. - -Keep replies extremely concise. Prefer 1-4 short lines. Avoid long explanations, tables, and broad background. - -Assume the user is reading on an in-game ComputerCraft terminal with limited space. - -Use ComputerCraft Lua and CC:Tweaked behavior, not standard desktop Lua, unless explicitly asked otherwise. - -When giving commands, make them directly runnable in CraftOS when possible. - -When giving code, keep it minimal and runnable. Avoid markdown fences unless the user clearly asks for a code block. - -You may use web search for current external facts and documentation. Keep searches focused and summarize only what unblocks the user. - -You may use the ComputerCraft MCP bridge only through `probe-computers` and `exec-lua`. - -Use `probe-computers` before `exec-lua` unless the target computer id is already clear from the conversation. - -Treat `exec-lua` as privileged in-game execution. Prefer read-only inspection. Do not delete files, reboot or shut down computers, move turtles, change inventories, transmit network traffic, mutate peripherals, or run long loops unless the user explicitly asks for that specific effect. - -Keep `exec-lua` snippets small and bounded. Use short timeouts. Avoid blocking pulls, sleeps, infinite loops, and assumptions that a timeout stops code already running in ComputerCraft. - -`print()` and `write()` output is captured in MCP results. To intentionally write to the visible ComputerCraft screen, use terminal APIs such as `term.clear()`, `term.setCursorPos()`, and `term.write()`. - -If the user asks for repo internals, answer only what is needed to unblock them. - -If the prompt asks for raw Lua code only, output raw Lua only with no markdown or explanation. diff --git a/ATM_EXPERT_AGENT_PLAN.md b/ATM_EXPERT_AGENT_PLAN.md new file mode 100644 index 0000000..759c9c9 --- /dev/null +++ b/ATM_EXPERT_AGENT_PLAN.md @@ -0,0 +1,109 @@ +# ATM Expert Agent Plan + +## Goal + +Replace `.opencode/agent/computercraft.md` with `atm10-expert`. + +The agent targets ATM10 / All The Mods 10, Minecraft `1.21.1`, NeoForge, pack version `7.0` (`0.7.0` accepted as user alias). + +## Known Facts + +CurseForge project id: `925200`. + +ATM10 `7.0` file id: `8091114`. + +Server pack file id: `8094893`. + +NeoForge version: `21.1.228`. + +GitHub source: + +## Files To Create + +Create `.opencode/agent/atm10-expert.md`. + +Create `.opencode/agent-context/atm10-expert/INDEX.md`. + +Create `.opencode/agent-context/atm10-expert/glossaries/`. + +Create `.opencode/agent-context/atm10-expert/scripts/`. + +Create `.opencode/agent-context/atm10-expert/modpacks/atm10-7.0.md`. + +## Files To Move + +Move in-game glossaries only: + +`docs/cc_glossary.md` to agent context. + +`docs/create_cc_tweaked_glossary.md` to agent context. + +`docs/advanced_peripherals_glossary.md` to agent context. + +Keep `docs/craftos_pc_glossary.md` in `docs/`. + +Update `docs/README.md` links. + +## Agent Behavior + +Delete old `computercraft` agent. + +New agent answers players concisely for in-game terminals. + +Use local glossaries first, then websearch/webfetch. + +Default to non-technical answers. + +Adapt language to the user, usually French. + +If a new useful mod documentation source is found, update or create a glossary and update `INDEX.md`. + +Keep replies short unless the user asks for detail. + +Use MCP bridge carefully: probe first, execute only bounded/read-only Lua unless explicitly asked. + +## Permissions + +Allow local read/search and web lookup. + +Keep MCP bridge `probe-computers` and `exec-lua`. + +Make edit/bash approval-gated or tightly limited, because this agent is player-facing. + +Allow `just check` for markdown validation. + +## ATM10 Mod List Script + +Add `.opencode/agent-context/atm10-expert/scripts/fetch-atm10-7.0-mods.sh`. + +Script should download CurseForge file `8091114`. + +Extract `manifest.json`. + +Write raw project/file ids and best available names to `modpacks/atm10-7.0.md`. + +If `CURSEFORGE_API_KEY` exists, resolve project names through the CurseForge API. + +Without API key, preserve ids and URLs for later glossary enrichment. + +## TrapOS AI Context + +Update `programs/ai.lua` / `apis/libai.lua` so each prompt includes hidden caller context: + +computer id. + +computer label, if any. + +This helps `atm10-expert` know which in-game computer is calling. + +Add tests in `tests/ai.lua`. + +Bump `packages/trapos-ai/ccpm.json` and `packages/index.json`. + +## Verification + +Run `just check`. + +Fix Lua lint and markdown link issues. + +Restart opencode after agent/config changes. diff --git a/apis/libai.lua b/apis/libai.lua index 1618328..120794d 100644 --- a/apis/libai.lua +++ b/apis/libai.lua @@ -165,6 +165,35 @@ local function buildLuaOutputPrompt(userPrompt, output) }, '\n'); end +local function readOsValue(osLib, name) + if type(osLib) ~= 'table' or type(osLib[name]) ~= 'function' then + return nil; + end + local ok, value = pcall(osLib[name]); + if not ok then return nil; end + return value; +end + +local function buildPromptWithCallerContext(prompt, osLib) + local lines = { + ''; + lines[#lines + 1] = ''; + lines[#lines + 1] = 'User prompt:'; + lines[#lines + 1] = prompt; + return table.concat(lines, '\n'); +end + local function sessionTime(session) if type(session) ~= 'table' or type(session.time) ~= 'table' then return 0; @@ -179,6 +208,7 @@ local function createAi(opts) local settingsLib = opts.settings or settings; local eventloopFactory = opts.eventloop or require('/apis/eventloop'); local nowFunc = opts.now or nowSeconds; + local osLib = opts.os or os; local api = {}; @@ -566,15 +596,20 @@ local function createAi(opts) log('reusing session ' .. sessionId); end + local promptWithContext = prompt; + if options.includeCallerContext ~= false then + promptWithContext = buildPromptWithCallerContext(prompt, osLib); + end + if not (cfg.providerID and cfg.modelID) then log('provider/model unset; using blocking message endpoint'); - return askBlocking(cfg, sessionId, prompt, persist, sessionSettingKey, log); + return askBlocking(cfg, sessionId, promptWithContext, persist, sessionSettingKey, log); end local messageId = options.messageId or createMessageId(); log('sending async prompt ' .. messageId); local body, code = doPost(cfg, '/session/' .. sessionId .. '/prompt_async', - buildPromptBody(cfg, messageId, prompt)); + buildPromptBody(cfg, messageId, promptWithContext)); if not body then return false, code; end if code == 404 then return handleMissingSession(persist, sessionSettingKey); @@ -760,6 +795,8 @@ local function createAi(opts) end function api.ping(options) + options = options or {}; + options.includeCallerContext = false; return api.ask(PING_PROMPT, options); end diff --git a/docs/README.md b/docs/README.md index 968be7f..1eefc98 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,10 +4,8 @@ Start here when looking up ComputerCraft-related APIs, CraftOS-PC behavior, peri ## Indexes -- [`cc_glossary.md`](cc_glossary.md) - CC:Tweaked globals, modules, peripherals, events, and guides. - [`craftos_pc_glossary.md`](craftos_pc_glossary.md) - CraftOS-PC emulator setup, CLI flags, mounting, peripheral emulation, troubleshooting, and related references. -- [`advanced_peripherals_glossary.md`](advanced_peripherals_glossary.md) - Advanced Peripherals 0.7 guides, peripherals, turtles, integrations, and changelog pages. -- [`create_cc_tweaked_glossary.md`](create_cc_tweaked_glossary.md) - Create CC:Tweaked integration pages. +- [`../.opencode/agent-context/atm10-expert/INDEX.md`](../.opencode/agent-context/atm10-expert/INDEX.md) - ATM10 in-game agent context, including CC:Tweaked, Advanced Peripherals, and Create CC:Tweaked glossaries. - [`opencode_server_guide.md`](opencode_server_guide.md) - Running `opencode serve` for the TrapOS `ai` client. - [`ingame-trapos-ai-mcp-guide.md`](ingame-trapos-ai-mcp-guide.md) - Concise in-game checklist for installing TrapOS, connecting `ai`, and linking MCP. - [`opencode_api.md`](opencode_api.md) - Minimal opencode HTTP API reference used by TrapOS. diff --git a/docs/ingame-trapos-ai-mcp-guide.md b/docs/ingame-trapos-ai-mcp-guide.md index 4e6d68f..08d4639 100644 --- a/docs/ingame-trapos-ai-mcp-guide.md +++ b/docs/ingame-trapos-ai-mcp-guide.md @@ -52,7 +52,7 @@ set opencc.model_id claude-opus-4-7 Optional agent setting for the in-game ComputerCraft assistant: ```sh -set opencc.agent computercraft +set opencc.agent atm10-expert ``` Test it: diff --git a/docs/opencode_api.md b/docs/opencode_api.md index 1f02934..c7ac0d2 100644 --- a/docs/opencode_api.md +++ b/docs/opencode_api.md @@ -88,7 +88,7 @@ Send a message and wait for the AI reply (blocking). Returns when the assistant "parts": [ { "type": "text", "text": "your prompt here" } ], - "agent": "computercraft", + "agent": "atm10-expert", "model": { "providerID": "anthropic", "modelID": "claude-opus-4-7" } } ``` @@ -153,7 +153,7 @@ Fire-and-forget variant. Returns `204` immediately. Include `messageID` in the r "parts": [ { "type": "text", "text": "your prompt here" } ], - "agent": "computercraft", + "agent": "atm10-expert", "model": { "providerID": "anthropic", "modelID": "claude-opus-4-7" } } ``` diff --git a/docs/opencode_server_guide.md b/docs/opencode_server_guide.md index 24317ee..1ebd733 100644 --- a/docs/opencode_server_guide.md +++ b/docs/opencode_server_guide.md @@ -107,7 +107,7 @@ set opencc.username myuser Optional — select an opencode agent for requests from this computer: ```sh -set opencc.agent computercraft +set opencc.agent atm10-expert ``` Optional — scope `ai sessions` to a specific opencode project directory. If omitted, `ai sessions` falls back to the directory recorded on the saved `opencc.session_id` when the unscoped list is empty: @@ -144,7 +144,7 @@ ai ping -- ping, reuses existing session ai "explain what a turtle is" ai new "start a fresh topic" -- forget current session, start fresh ai sessions -- list all server sessions with their IDs -ai --agent computercraft "what peripherals are attached?" +ai --agent atm10-expert "what peripherals are attached?" ai --verbose ping -- show HTTP/session diagnostics ai --help ai --version diff --git a/programs/ai.lua b/programs/ai.lua index 3baeb3d..eeb20e8 100644 --- a/programs/ai.lua +++ b/programs/ai.lua @@ -49,7 +49,7 @@ local function printUsage() print(' opencc.password (Basic Auth password)'); print(' opencc.session_id (auto-managed)'); print(' opencc.directory (optional session list scope)'); - print(' opencc.agent (e.g. computercraft)'); + print(' opencc.agent (e.g. atm10-expert)'); print(' opencc.provider_id (e.g. anthropic)'); print(' opencc.model_id (e.g. claude-opus-4-7)'); print(' opencc.timeout_seconds (per HTTP call, max 60)'); diff --git a/tests/ai.lua b/tests/ai.lua index b6074b9..834e026 100644 --- a/tests/ai.lua +++ b/tests/ai.lua @@ -21,6 +21,13 @@ local function fakeSettings(initial) }; end +local function fakeOs(computerId, computerLabel) + return { + getComputerID = function() return computerId; end, + getComputerLabel = function() return computerLabel; end, + }; +end + local function fakeAsyncSettings(initial) local values = { ['opencc.server_url'] = 'http://host', @@ -429,7 +436,7 @@ testlib.test('ask falls back to blocking message when model is unset', function( testlib.assertEquals(#httpStub.getCalls, 0); end); -testlib.test('ask sends exact prompt text', function() +testlib.test('ask wraps prompt with caller context', function() local httpStub = fakeHttp( { messageResp('reply') }, {} @@ -438,14 +445,43 @@ testlib.test('ask sends exact prompt text', function() ['opencc.server_url'] = 'http://host', ['opencc.session_id'] = 'ses_1', }); - local ai = createAi({ http = httpStub, settings = settingsStub }); + local ai = createAi({ + http = httpStub, + settings = settingsStub, + os = fakeOs(42, 'storage-main'), + }); ai.ask('my prompt'); local body = textutils.unserializeJSON(httpStub.postCalls[1].body); testlib.assertEquals(#body.parts, 1); testlib.assertEquals(body.parts[1].type, 'text'); - testlib.assertEquals(body.parts[1].text, 'my prompt'); + testlib.assertTrue(string.find(body.parts[1].text, '