@c4t4/heyamigo 0.8.10 → 0.8.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/config.example.json +6 -0
- package/dist/ai/codex.js +53 -22
- package/dist/config.js +14 -0
- package/package.json +1 -1
package/dist/ai/codex.js
CHANGED
|
@@ -8,13 +8,19 @@
|
|
|
8
8
|
// - --add-dir for extra writable roots
|
|
9
9
|
// - --sandbox for tier (read-only / workspace-write / danger-full-access)
|
|
10
10
|
// - `resume <id>` subcommand for session continuation (not a flag)
|
|
11
|
-
// - prompt passed
|
|
12
|
-
//
|
|
11
|
+
// - prompt passed as positional arg
|
|
12
|
+
//
|
|
13
|
+
// Configurable via config.codex:
|
|
14
|
+
// - yolo (default true): adds --yolo, which bundles no-approvals +
|
|
15
|
+
// full sandbox + skip-trust-check. The right default for a headless
|
|
16
|
+
// owner-bot; set false to honor runTask's mode-driven sandbox.
|
|
17
|
+
// - skipGitRepoCheck (default true): adds --skip-git-repo-check when
|
|
18
|
+
// yolo is off. Codex refuses to run in untrusted cwds without it.
|
|
19
|
+
// - extraArgs: appended verbatim. Escape hatch for version drift.
|
|
13
20
|
//
|
|
14
21
|
// What's deliberately coarse:
|
|
15
22
|
// - allowedTools is ignored on this provider. Codex has no per-tool
|
|
16
|
-
// allowlist; the sandbox mode is the only knob.
|
|
17
|
-
// covers the practical cases (read vs. write vs. full).
|
|
23
|
+
// allowlist; the sandbox mode is the only knob.
|
|
18
24
|
import { readFileSync } from 'fs';
|
|
19
25
|
import { resolve } from 'path';
|
|
20
26
|
import { config } from '../config.js';
|
|
@@ -57,8 +63,20 @@ function laneTimeoutMs(lane) {
|
|
|
57
63
|
return TIMEOUT_MS[lane];
|
|
58
64
|
}
|
|
59
65
|
function buildExecArgs(params) {
|
|
66
|
+
const cfg = config.codex;
|
|
60
67
|
const args = ['exec', '--json'];
|
|
61
|
-
|
|
68
|
+
if (cfg.yolo) {
|
|
69
|
+
// --yolo: no approvals, full sandbox, skip trust check. Single switch
|
|
70
|
+
// that covers the owner-bot case. mode is ignored on this path.
|
|
71
|
+
args.push('--yolo');
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
if (cfg.skipGitRepoCheck)
|
|
75
|
+
args.push('--skip-git-repo-check');
|
|
76
|
+
args.push('--sandbox', sandboxFor(params.mode));
|
|
77
|
+
}
|
|
78
|
+
for (const extra of cfg.extraArgs)
|
|
79
|
+
args.push(extra);
|
|
62
80
|
if (params.sessionId) {
|
|
63
81
|
// Resume is a subcommand of exec, not a flag: `codex exec [opts] resume
|
|
64
82
|
// <SESSION_ID> [prompt]`. System prompt and add-dirs were baked in on
|
|
@@ -82,6 +100,27 @@ function buildExecArgs(params) {
|
|
|
82
100
|
args.push(params.prompt);
|
|
83
101
|
return args;
|
|
84
102
|
}
|
|
103
|
+
function extractReply(ev) {
|
|
104
|
+
// Primary shape: item.completed with item.type === 'agent_message'
|
|
105
|
+
if (ev.type === 'item.completed' &&
|
|
106
|
+
ev.item &&
|
|
107
|
+
ev.item.type === 'agent_message' &&
|
|
108
|
+
typeof ev.item.text === 'string') {
|
|
109
|
+
return ev.item.text;
|
|
110
|
+
}
|
|
111
|
+
// Older shape: msg.type === 'agent_message' with msg.message
|
|
112
|
+
if (ev.msg &&
|
|
113
|
+
ev.msg.type === 'agent_message' &&
|
|
114
|
+
typeof ev.msg.message === 'string') {
|
|
115
|
+
return ev.msg.message;
|
|
116
|
+
}
|
|
117
|
+
// Last-ditch top-level fields
|
|
118
|
+
if (typeof ev.message === 'string')
|
|
119
|
+
return ev.message;
|
|
120
|
+
if (typeof ev.text === 'string')
|
|
121
|
+
return ev.text;
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
85
124
|
function parseCodexOutput(stdout) {
|
|
86
125
|
const events = [];
|
|
87
126
|
for (const line of stdout.split(/\r?\n/)) {
|
|
@@ -97,37 +136,29 @@ function parseCodexOutput(stdout) {
|
|
|
97
136
|
}
|
|
98
137
|
if (events.length === 0)
|
|
99
138
|
return null;
|
|
100
|
-
//
|
|
101
|
-
// versions — try the common shapes in order.
|
|
139
|
+
// Latest agent message wins (handles multi-turn output).
|
|
102
140
|
let reply = null;
|
|
103
141
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
reply = ev.msg.message;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
if (typeof ev.message === 'string') {
|
|
111
|
-
reply = ev.message;
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
if (typeof ev.text === 'string') {
|
|
115
|
-
reply = ev.text;
|
|
142
|
+
const r = extractReply(events[i]);
|
|
143
|
+
if (r !== null) {
|
|
144
|
+
reply = r;
|
|
116
145
|
break;
|
|
117
146
|
}
|
|
118
147
|
}
|
|
119
148
|
if (reply === null)
|
|
120
149
|
return null;
|
|
121
|
-
// Session id —
|
|
150
|
+
// Session id — `thread_id` on thread.started in current Codex; older
|
|
151
|
+
// builds used session_id / conversation_id / response_id.
|
|
122
152
|
let sessionId;
|
|
123
153
|
for (const ev of events) {
|
|
124
|
-
const id = ev.session_id ?? ev.conversation_id ?? ev.response_id;
|
|
154
|
+
const id = ev.thread_id ?? ev.session_id ?? ev.conversation_id ?? ev.response_id;
|
|
125
155
|
if (typeof id === 'string' && id) {
|
|
126
156
|
sessionId = id;
|
|
127
157
|
break;
|
|
128
158
|
}
|
|
129
159
|
}
|
|
130
|
-
// Usage —
|
|
160
|
+
// Usage — turn.completed carries final totals; fall back to any event
|
|
161
|
+
// with a usage object if the type marker is missing.
|
|
131
162
|
let inputTokens = 0;
|
|
132
163
|
let outputTokens = 0;
|
|
133
164
|
let cacheReadTokens = 0;
|
package/dist/config.js
CHANGED
|
@@ -36,6 +36,20 @@ const ConfigSchema = z.object({
|
|
|
36
36
|
outputFormat: z.enum(['json', 'text', 'stream-json']),
|
|
37
37
|
contextWindow: z.number(),
|
|
38
38
|
}),
|
|
39
|
+
codex: z
|
|
40
|
+
.object({
|
|
41
|
+
// --yolo on the Codex CLI bundles "no approvals + full sandbox + no
|
|
42
|
+
// trust prompts". Right default for a headless owner-bot; flip to
|
|
43
|
+
// false if you want runTask's mode to drive the sandbox tier instead.
|
|
44
|
+
yolo: z.boolean().default(true),
|
|
45
|
+
// When yolo=false, still bypass the trust-directory prompt. Codex
|
|
46
|
+
// refuses to run in an "untrusted" cwd otherwise.
|
|
47
|
+
skipGitRepoCheck: z.boolean().default(true),
|
|
48
|
+
// Appended verbatim to every `codex exec` invocation. Escape hatch
|
|
49
|
+
// for version-specific flags we haven't first-classed.
|
|
50
|
+
extraArgs: z.array(z.string()).default([]),
|
|
51
|
+
})
|
|
52
|
+
.default({}),
|
|
39
53
|
bootstrap: z.object({
|
|
40
54
|
historyDepth: z.number(),
|
|
41
55
|
includeHistory: z.boolean(),
|