Skip to content

Commit cd8c351

Browse files
feat(lua): expose action-menu macros for CLI automation
Assisted-by: openai/gpt-5.3-codex on opencode Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
1 parent 8d09ab8 commit cd8c351

File tree

11 files changed

+582
-201
lines changed

11 files changed

+582
-201
lines changed

data/json/main.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local voltmeter = require("./voltmeter")
22
local slimepit = require("./slimepit")
33
local artifact_analyzer = require("./artifact_analyzer")
44
local lua_traits = require("./lua_traits")
5+
local action_menu_macros = require("lib.action_menu_macros")
56

67
local mod = game.mod_runtime[game.current_mod]
78
local storage = game.mod_storage[game.current_mod]
@@ -11,3 +12,4 @@ mod.slimepit = slimepit
1112
mod.artifact_analyzer = artifact_analyzer
1213
mod.lua_traits = lua_traits
1314
lua_traits.register(mod)
15+
action_menu_macros.register_defaults()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
local ui = require("lib.ui")
2+
3+
local action_menu_macros = {}
4+
5+
local function popup_recent_messages()
6+
local entries = gapi.get_messages(12)
7+
if #entries == 0 then
8+
ui.popup(locale.gettext("No recent messages."))
9+
return
10+
end
11+
12+
local lines = { locale.gettext("Recent Messages"), "" }
13+
for _, entry in ipairs(entries) do
14+
table.insert(lines, string.format("[%s] %s", entry.time, entry.text))
15+
end
16+
17+
ui.popup(table.concat(lines, "\n"))
18+
end
19+
20+
local function popup_recent_lua_log()
21+
local entries = gapi.get_lua_log(20)
22+
if #entries == 0 then
23+
ui.popup(locale.gettext("No recent Lua log entries."))
24+
return
25+
end
26+
27+
local lines = { locale.gettext("Recent Lua Log"), "" }
28+
for _, entry in ipairs(entries) do
29+
local source_prefix = entry.from_user and "> " or ""
30+
table.insert(lines, string.format("[%s] %s%s", entry.level, source_prefix, entry.text))
31+
end
32+
33+
ui.popup(table.concat(lines, "\n"))
34+
end
35+
36+
local function announce_current_turn()
37+
local turn_value = gapi.current_turn():to_turn()
38+
gapi.add_msg(string.format(locale.gettext("Current turn: %d"), turn_value))
39+
end
40+
41+
action_menu_macros.register_defaults = function()
42+
gapi.register_action_menu_entry({
43+
id = "bn_macro_recent_messages",
44+
name = locale.gettext("Recent Messages"),
45+
description = locale.gettext("Show the latest in-game messages in a popup."),
46+
category = "info",
47+
fn = popup_recent_messages,
48+
})
49+
50+
gapi.register_action_menu_entry({
51+
id = "bn_macro_recent_lua_log",
52+
name = locale.gettext("Recent Lua Log"),
53+
description = locale.gettext("Show the latest Lua console log entries in a popup."),
54+
category = "info",
55+
fn = popup_recent_lua_log,
56+
})
57+
58+
gapi.register_action_menu_entry({
59+
id = "bn_macro_current_turn",
60+
name = locale.gettext("Current Turn"),
61+
description = locale.gettext("Print the current absolute turn in the message log."),
62+
category = "info",
63+
fn = announce_current_turn,
64+
})
65+
end
66+
67+
return action_menu_macros

scripts/curses-cli/common.ts

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,21 @@ export const listAvailableInputs = (
392392
return detectPromptInputs(pane)
393393
}
394394

395-
export const buildLaunchCommand = (
396-
binPath: string,
397-
userdir: string,
398-
world: string,
399-
seed = "",
400-
availableKeysJson = "",
401-
aiHelperOutput = "",
402-
): string => {
395+
type BuildLaunchCommandOptions = {
396+
binPath: string
397+
userdir: string
398+
world: string
399+
seed?: string
400+
availableKeysJson?: string
401+
availableMacrosJson?: string
402+
aiHelperOutput?: string
403+
}
404+
405+
export const buildLaunchCommand = (options: BuildLaunchCommandOptions): string => {
406+
const seed = options.seed ?? ""
407+
const availableKeysJson = options.availableKeysJson ?? ""
408+
const availableMacrosJson = options.availableMacrosJson ?? ""
409+
const aiHelperOutput = options.aiHelperOutput ?? ""
403410
const parts = [
404411
"TERM=xterm-256color",
405412
"COLORTERM=truecolor",
@@ -408,16 +415,19 @@ export const buildLaunchCommand = (
408415
...(availableKeysJson.length > 0
409416
? [`CATA_AVAILABLE_KEYS_JSON=${shellEscape(availableKeysJson)}`]
410417
: []),
418+
...(availableMacrosJson.length > 0
419+
? [`CATA_AVAILABLE_MACROS_JSON=${shellEscape(availableMacrosJson)}`]
420+
: []),
411421
...(aiHelperOutput.length > 0 ? [`AI_HELPER_OUTPUT=${shellEscape(aiHelperOutput)}`] : []),
412-
shellEscape(binPath),
422+
shellEscape(options.binPath),
413423
"--basepath",
414424
shellEscape(REPO_ROOT),
415425
"--userdir",
416-
shellEscape(userdir),
426+
shellEscape(options.userdir),
417427
]
418428

419-
if (world.length > 0) {
420-
parts.push("--world", shellEscape(world))
429+
if (options.world.length > 0) {
430+
parts.push("--world", shellEscape(options.world))
421431
}
422432

423433
if (seed.length > 0) {
@@ -435,23 +445,25 @@ export const writeCodeBlockCapture = async (
435445
await Deno.writeTextFile(outputPath, body)
436446
}
437447

438-
export const writeIndex = async (
439-
outputPath: string,
440-
sessionName: string,
441-
captures: CaptureEntry[],
442-
status: RunStatus,
443-
castFile?: string,
444-
failureMessage?: string,
445-
): Promise<void> => {
448+
type WriteIndexOptions = {
449+
outputPath: string
450+
sessionName: string
451+
captures: CaptureEntry[]
452+
status: RunStatus
453+
castFile?: string
454+
failureMessage?: string
455+
}
456+
457+
export const writeIndex = async (options: WriteIndexOptions): Promise<void> => {
446458
const lines = [
447459
"# PR Verify Artifact",
448460
"",
449-
`Session: ${sessionName}`,
450-
`Status: ${status}`,
461+
`Session: ${options.sessionName}`,
462+
`Status: ${options.status}`,
451463
"",
452464
"## Captures",
453465
"",
454-
...captures.map((capture, index) => {
466+
...options.captures.map((capture, index) => {
455467
const title = capture.caption.length > 0 ? capture.caption : capture.id
456468
const screenshotSuffix = capture.screenshot_file
457469
? `, screenshot: \`${capture.screenshot_file}\``
@@ -463,19 +475,19 @@ export const writeIndex = async (
463475
"",
464476
]
465477

466-
if (castFile !== undefined) {
467-
lines.push(`Cast recording: \`${castFile}\``)
478+
if (options.castFile !== undefined) {
479+
lines.push(`Cast recording: \`${options.castFile}\``)
468480
lines.push("")
469481
}
470482

471-
if (failureMessage !== undefined) {
483+
if (options.failureMessage !== undefined) {
472484
lines.push("## Failure")
473485
lines.push("")
474486
lines.push("```text")
475-
lines.push(failureMessage)
487+
lines.push(options.failureMessage)
476488
lines.push("```")
477489
lines.push("")
478490
}
479491

480-
await Deno.writeTextFile(outputPath, lines.join("\n"))
492+
await Deno.writeTextFile(options.outputPath, lines.join("\n"))
481493
}

0 commit comments

Comments
 (0)