Skip to content

Commit b5ff989

Browse files
authored
Merge pull request #169 from SentienceAPI/tighten
tighten debugger lifecycle ergonomics
2 parents 634178a + b9da034 commit b5ff989

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

src/agent-runtime.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,15 @@ export class AgentRuntime {
10901090
return stepEndData;
10911091
}
10921092

1093+
/**
1094+
* User-friendly alias for emitStepEnd().
1095+
*
1096+
* Keeps step lifecycle naming symmetric with beginStep().
1097+
*/
1098+
endStep(opts: Parameters<AgentRuntime['emitStepEnd']>[0] = {}): any {
1099+
return this.emitStepEnd(opts);
1100+
}
1101+
10931102
private async captureArtifactFrame(): Promise<void> {
10941103
if (!this.artifactBuffer) {
10951104
return;

src/debugger.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import { Tracer } from './tracing/tracer';
77
export class SentienceDebugger {
88
readonly runtime: AgentRuntime;
99
private stepOpen: boolean = false;
10+
private autoStep: boolean = true;
1011

11-
constructor(runtime: AgentRuntime) {
12+
constructor(runtime: AgentRuntime, options?: { autoStep?: boolean }) {
1213
this.runtime = runtime;
14+
this.autoStep = options?.autoStep !== undefined ? Boolean(options.autoStep) : true;
1315
}
1416

1517
static attach(page: Page, tracer: Tracer, options?: AttachOptions): SentienceDebugger {
@@ -43,6 +45,13 @@ export class SentienceDebugger {
4345

4446
check(predicate: Predicate, label: string, required: boolean = false) {
4547
if (!this.stepOpen) {
48+
if (!this.autoStep) {
49+
throw new Error(
50+
`No active step. Call dbg.beginStep(...) or dbg.step(...) before check(label=${JSON.stringify(
51+
label
52+
)}).`
53+
);
54+
}
4655
this.beginStep(`verify:${label}`);
4756
}
4857
return this.runtime.check(predicate, label, required);

tests/agent-runtime-attach.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,15 @@ describe('AgentRuntime.fromPlaywrightPage()', () => {
6767
spy.mockRestore();
6868
});
6969
});
70+
71+
describe('AgentRuntime.endStep()', () => {
72+
it('aliases emitStepEnd()', () => {
73+
const runtime: any = {
74+
emitStepEnd: jest.fn().mockReturnValue({ ok: true }),
75+
};
76+
77+
const out = (AgentRuntime.prototype as any).endStep.call(runtime, { action: 'noop' });
78+
expect(runtime.emitStepEnd).toHaveBeenCalledWith({ action: 'noop' });
79+
expect(out).toEqual({ ok: true });
80+
});
81+
});

tests/debugger.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,17 @@ describe('SentienceDebugger', () => {
6666
expect(runtime.check).toHaveBeenCalled();
6767
expect(handle).toBe('handle');
6868
});
69+
70+
it('can disable auto-step (strict mode)', () => {
71+
const runtime = {
72+
beginStep: jest.fn().mockReturnValue('step-1'),
73+
check: jest.fn().mockReturnValue('handle'),
74+
} as unknown as AgentRuntime;
75+
76+
const dbg = new SentienceDebugger(runtime, { autoStep: false } as any);
77+
78+
expect(() =>
79+
dbg.check((_ctx: any) => ({ passed: true, reason: '', details: {} }), 'has_cart')
80+
).toThrow(/No active step/i);
81+
});
6982
});

0 commit comments

Comments
 (0)