Skip to content

Commit 46a790b

Browse files
committed
test(agent): the typed-goal rule runs in a test, not only as a regex
rememberTypedGoal holds the rule agentFlow applies (record only a goal marked typed; trimmed; newest 20), so sessionExpiredHost lifts and runs it; agentFlow passing its flag through is pinned from source.
1 parent e9ff3cc commit 46a790b

2 files changed

Lines changed: 25 additions & 6 deletions

File tree

‎extensions/levelcode-ai/extension.js‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,6 +2240,16 @@ async function compactAgentMemory() {
22402240
}
22412241

22422242
let lastAgentGoal = null; // remembered so the response bar's Retry can re-run it
2243+
/**
2244+
* Only what the person typed becomes their word to the Ask When Risky reviewer. A retried or generated goal
2245+
* stays activity: a typed goal that Retry repeats is already on the list, and one from a resumed session
2246+
* must not be (see resumeSession). The newest 20 are kept.
2247+
*/
2248+
function rememberTypedGoal(text, opts) {
2249+
if (!(opts && opts.typed && text && String(text).trim())) { return; }
2250+
humanGoals.push(String(text).trim());
2251+
if (humanGoals.length > 20) { humanGoals.splice(0, humanGoals.length - 20); }
2252+
}
22432253
/**
22442254
* Run the agent on a goal. `opts.typed` says the person typed `text` into the chat just now (handleSend);
22452255
* every other caller — a diagram retry, Retry and Continue on the response bar — passes words the person
@@ -2274,10 +2284,7 @@ async function agentFlow(text, imageBlocks, opts) {
22742284
checkpoints.push(currentCheckpoint);
22752285
post({ type: 'checkpointOpened', turnId: currentCheckpoint.turnId });
22762286
agentMessages.push(goalMsg);
2277-
// Only what the person typed becomes their word to the Ask When Risky reviewer. A retried or generated goal
2278-
// stays activity: a typed goal Retry repeats is already on this list, and one from a resumed session must
2279-
// not be (see resumeSession).
2280-
if (opts && opts.typed && text && text.trim()) { humanGoals.push(text.trim()); if (humanGoals.length > 20) { humanGoals.splice(0, humanGoals.length - 20); } }
2287+
rememberTypedGoal(text, opts);
22812288
trimAgentMemory();
22822289
// Sessions: mark where THIS turn's messages begin (the goal, post-trim). agentMessages is a trimmed
22832290
// live window, but a persisted session is the FULL append-only history — so after the run we persist

‎extensions/levelcode-ai/test/sessionExpiredHost.test.js‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const FUNCTIONS = [
9797
'refreshCloudToken', 'renewSession', 'storedToken', 'catchUpWithStoredSession', 'withSessionLock', 'sameSession', 'sessionExpired', 'postSessionExpired',
9898
'sessionExpiredPending', 'isEndedSessionError', 'clearSessionExpired', 'replaySessionExpired', 'checkCloudSession',
9999
'refreshGatewayToken', 'prepProviderRequest', 'handleSend', 'currentAccount', 'postAccount', 'accountSignOut',
100-
'storeSession', 'newChat', 'resumeSession', 'restoreCheckpoint', 'onConfigChanged', 'readApprovalMode'
100+
'storeSession', 'newChat', 'resumeSession', 'restoreCheckpoint', 'onConfigChanged', 'readApprovalMode', 'rememberTypedGoal'
101101
];
102102
// eslint-disable-next-line no-new-func
103103
const makeHost = new Function('env', [
@@ -123,7 +123,7 @@ const makeHost = new Function('env', [
123123
'return { ' + FUNCTIONS.join(', ') + ',',
124124
' KEY: { token: ACCOUNT_TOKEN_KEY, refresh: ACCOUNT_REFRESH_KEY, profile: ACCOUNT_PROFILE_KEY, expired: ACCOUNT_EXPIRED_KEY },',
125125
' signedIn: () => cloudSignedIn, conversation: () => conversation, abort: () => abort,',
126-
' openWebview: (w) => { activeWebview = w; }, setAgentMessages: (m) => { agentMessages = m; }, approvalMode: () => approvalMode };'
126+
' openWebview: (w) => { activeWebview = w; }, setAgentMessages: (m) => { agentMessages = m; }, approvalMode: () => approvalMode, humanGoals: () => humanGoals };'
127127
].join('\n'));
128128

129129
// The defaults a fresh install runs with come from package.json, not from this file: the whole
@@ -1097,11 +1097,23 @@ async function test(name, fn) { await fn(); n++; console.log(' ok - ' + name);
10971097
// The response bar's buttons live in the message switch, which no harness lifts: pinned from source.
10981098
// Exactly one caller may say `typed: true`, and it is handleSend.
10991099
assert.strictEqual((src.match(/typed: true/g) || []).length, 1, 'another caller marks its goal as typed');
1100+
assert.match(src, /async function agentFlow\(text, imageBlocks, opts\) \{[\s\S]{0,4000}?rememberTypedGoal\(text, opts\);/, 'agentFlow hands the flag through unchanged');
11001101
assert.match(src, /if \(agentMode\) \{ await agentFlow\(text, imageBlocks, \{ typed: true \}\); return; \}/);
11011102
assert.match(src, /case 'retry':[^\n]*await agentFlow\(lastAgentGoal\);/);
11021103
assert.match(src, /case 'continueAgent':[^\n]*await agentFlow\('Continue from where you left off[^\n]*'\);/);
11031104
});
11041105

1106+
await test('TYPED GOALS: only a goal marked typed is recorded as the person\'s — trimmed, newest 20', async () => {
1107+
const t = boot();
1108+
t.host.rememberTypedGoal('Redraw the diagram “x” with render_diagram.');
1109+
t.host.rememberTypedGoal('Continue from where you left off', {});
1110+
t.host.rememberTypedGoal(' ', { typed: true });
1111+
assert.deepStrictEqual(t.host.humanGoals(), [], 'untyped or empty text was recorded');
1112+
for (let i = 0; i < 23; i++) { t.host.rememberTypedGoal(' goal ' + i + ' ', { typed: true }); }
1113+
assert.strictEqual(t.host.humanGoals().length, 20);
1114+
assert.deepStrictEqual([t.host.humanGoals()[0], t.host.humanGoals()[19]], ['goal 3', 'goal 22']);
1115+
});
1116+
11051117
await test('SETTINGS: the approvals mode changed in Settings or another window takes effect at once, and the pill follows', async () => {
11061118
const t = boot({ settings: { 'levelcode.ai.agent.approvals': 'autopilot' } });
11071119
assert.strictEqual(t.host.approvalMode(), 'ask', 'the window started before the change');

0 commit comments

Comments
 (0)