@theokit/sdk 4.19.1 → 4.19.2

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.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * M56 (agent-builder goal transparency) — PUBLIC goal-loop driver for CUSTOM agent surfaces.
3
+ *
4
+ * `LocalAgent.runUntil` binds the goal loop to a registered local agent. Surfaces that route turns
5
+ * through their OWN transport (e.g. a TUI store facade, so every goal turn renders in the same
6
+ * timeline as a manual turn) need the SAME loop over a minimal `send → wait` shape. This export
7
+ * gives them exactly that: the canonical `runUntilImpl` (judge + continuation + token budget +
8
+ * Codex states) with the default judge wired from the DI registry.
9
+ *
10
+ * @public
11
+ */
12
+ import type { RunUntilDeps } from "./internal/runtime/lifecycle/run-until.js";
13
+ /**
14
+ * Stable marker on the FIRST LINE of every goal-continuation prompt. Surfaces detect it to render the
15
+ * turn collapsed, exclude it from backtrack windows, and skip it in compaction preservation.
16
+ */
17
+ export declare const GOAL_CONTINUATION_MARKER = "[[theokit:goal-continuation]]";
18
+ import type { GoalEvent, GoalOptions, GoalResult } from "./types/goal-events.js";
19
+ /** The minimal surface the goal loop drives — anything that can send a prompt and wait for it. */
20
+ export interface GoalLoopAgent {
21
+ send(prompt: string): Promise<{
22
+ wait(): Promise<{
23
+ result?: string;
24
+ usage?: {
25
+ totalTokens?: number;
26
+ };
27
+ }>;
28
+ }>;
29
+ }
30
+ /**
31
+ * Run the goal-driven loop (`send → judge → continuation`) over ANY `send → wait` surface.
32
+ * Identical semantics to `Agent.runUntil` (ADRs D115-D121 + M55 token budget / states).
33
+ * `depsOverride` is a test seam for injecting a fake judge.
34
+ */
35
+ export declare function runGoalLoop(agent: GoalLoopAgent, goal: string, options?: GoalOptions, depsOverride?: RunUntilDeps): AsyncGenerator<GoalEvent, GoalResult, void>;
package/dist/index.cjs CHANGED
@@ -6179,7 +6179,9 @@ function isCompactSummary(content) {
6179
6179
  function plainText(content) {
6180
6180
  if (typeof content === "string") return content;
6181
6181
  if (!Array.isArray(content)) return void 0;
6182
- const texts = content.filter((p) => p !== null && typeof p === "object" && p.type === "text" && typeof p.text === "string").map((p) => p.text);
6182
+ const texts = content.filter(
6183
+ (p) => p !== null && typeof p === "object" && p.type === "text" && typeof p.text === "string"
6184
+ ).map((p) => p.text);
6183
6185
  return texts.length > 0 ? texts.join("\n") : void 0;
6184
6186
  }
6185
6187
  async function compactSessionTranscript(opts) {
@@ -6300,8 +6302,10 @@ async function autoCompactIfNeeded(opts) {
6300
6302
  return true;
6301
6303
  } catch (cause) {
6302
6304
  const msg = cause instanceof Error ? cause.message : String(cause);
6303
- process.stderr.write(`[theokit-sdk] auto-compaction failed (left transcript untouched): ${msg}
6304
- `);
6305
+ process.stderr.write(
6306
+ `[theokit-sdk] auto-compaction failed (left transcript untouched): ${msg}
6307
+ `
6308
+ );
6305
6309
  return false;
6306
6310
  }
6307
6311
  }
@@ -6311,11 +6315,11 @@ var init_compact_session = __esm({
6311
6315
  init_compaction();
6312
6316
  init_router();
6313
6317
  init_real_local_run_provider();
6318
+ init_session_transcript();
6314
6319
  init_providers();
6315
6320
  init_compression_model_registry();
6316
6321
  init_compression_summarizer();
6317
6322
  init_agent_session();
6318
- init_session_transcript();
6319
6323
  COMPACT_SUMMARY_MARKER = "[[theokit:compact-summary]]";
6320
6324
  COMPACT_USER_MESSAGE_MAX_TOKENS = 2e4;
6321
6325
  autoCompactAttempts = (() => {
@@ -6537,7 +6541,9 @@ async function loadDriver(filePath) {
6537
6541
  }
6538
6542
  try {
6539
6543
  const mod = await (driverLoaderOverrides?.nodeSqlite?.() ?? Promise.resolve(
6540
- process.getBuiltinModule?.("node:sqlite") ?? (() => {
6544
+ process.getBuiltinModule?.(
6545
+ "node:sqlite"
6546
+ ) ?? (() => {
6541
6547
  throw new Error("node:sqlite built-in unavailable (Node < 22.3)");
6542
6548
  })()
6543
6549
  ));
@@ -7504,10 +7510,136 @@ var init_context = __esm({
7504
7510
  }
7505
7511
  });
7506
7512
 
7513
+ // src/internal/judge/parse-verdict.ts
7514
+ function parseVerdict(text) {
7515
+ const trimmed = text.trim();
7516
+ if (trimmed.startsWith(DONE_PREFIX)) {
7517
+ return {
7518
+ verdict: "done",
7519
+ reason: trimmed.slice(DONE_PREFIX.length).trim(),
7520
+ parseFailed: false
7521
+ };
7522
+ }
7523
+ if (trimmed.startsWith(CONTINUE_PREFIX)) {
7524
+ return {
7525
+ verdict: "continue",
7526
+ reason: trimmed.slice(CONTINUE_PREFIX.length).trim(),
7527
+ parseFailed: false
7528
+ };
7529
+ }
7530
+ if (trimmed.startsWith(SKIPPED_PREFIX)) {
7531
+ return {
7532
+ verdict: "skipped",
7533
+ reason: trimmed.slice(SKIPPED_PREFIX.length).trim(),
7534
+ parseFailed: false
7535
+ };
7536
+ }
7537
+ return {
7538
+ verdict: "continue",
7539
+ reason: `judge response malformed: "${trimmed.slice(0, 100)}"`,
7540
+ parseFailed: true
7541
+ };
7542
+ }
7543
+ var DONE_PREFIX, CONTINUE_PREFIX, SKIPPED_PREFIX;
7544
+ var init_parse_verdict = __esm({
7545
+ "src/internal/judge/parse-verdict.ts"() {
7546
+ DONE_PREFIX = "DONE:";
7547
+ CONTINUE_PREFIX = "CONTINUE:";
7548
+ SKIPPED_PREFIX = "SKIPPED:";
7549
+ }
7550
+ });
7551
+
7552
+ // src/internal/judge/judge-call.ts
7553
+ var judge_call_exports = {};
7554
+ __export(judge_call_exports, {
7555
+ composeJudgePrompt: () => composeJudgePrompt,
7556
+ judgeCallImpl: () => judgeCallImpl
7557
+ });
7558
+ async function judgeCallImpl(ctx, options, deps) {
7559
+ const prompt = composeJudgePrompt(ctx);
7560
+ const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;
7561
+ if (apiKey === void 0) {
7562
+ return {
7563
+ verdict: "continue",
7564
+ reason: "judge unavailable: OPENROUTER_API_KEY missing and no override passed via options.apiKey",
7565
+ parseFailed: true
7566
+ };
7567
+ }
7568
+ const judgeModel = options?.judgeModel ?? "openai/gpt-4o-mini";
7569
+ let auxAgent;
7570
+ try {
7571
+ auxAgent = await deps.create({
7572
+ apiKey,
7573
+ model: { id: judgeModel },
7574
+ tools: [],
7575
+ local: {},
7576
+ metadata: { forkOrigin: "judge" }
7577
+ });
7578
+ const run = await auxAgent.send(prompt);
7579
+ const result = await run.wait();
7580
+ return parseVerdict(result.result ?? "");
7581
+ } catch (err) {
7582
+ return {
7583
+ verdict: "continue",
7584
+ reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,
7585
+ parseFailed: true
7586
+ };
7587
+ } finally {
7588
+ if (auxAgent !== void 0) {
7589
+ try {
7590
+ await auxAgent.dispose();
7591
+ } catch {
7592
+ }
7593
+ }
7594
+ }
7595
+ }
7596
+ function composeJudgePrompt(ctx) {
7597
+ const subgoals = ctx.subgoals !== void 0 && ctx.subgoals.length > 0 ? ctx.subgoals.join(", ") : "(none)";
7598
+ return `You are a goal judge. Determine if this goal is satisfied.
7599
+
7600
+ Goal: ${ctx.goal}
7601
+ Subgoals: ${subgoals}
7602
+ Last agent response: ${ctx.lastResponse}
7603
+
7604
+ Respond with EXACTLY one of:
7605
+ - DONE: <reason>
7606
+ - CONTINUE: <what's left>
7607
+ - SKIPPED: <why not applicable>
7608
+
7609
+ Be strict. If unclear, prefer CONTINUE.`;
7610
+ }
7611
+ var init_judge_call = __esm({
7612
+ "src/internal/judge/judge-call.ts"() {
7613
+ init_parse_verdict();
7614
+ }
7615
+ });
7616
+
7617
+ // src/goal-loop.ts
7618
+ function runGoalLoop(agent, goal, options, depsOverride) {
7619
+ async function* wrap() {
7620
+ const { runUntilImpl: runUntilImpl2 } = await Promise.resolve().then(() => (init_run_until(), run_until_exports));
7621
+ const deps = depsOverride ?? await (async () => {
7622
+ const { judgeCallImpl: judgeCallImpl2 } = await Promise.resolve().then(() => (init_judge_call(), judge_call_exports));
7623
+ const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
7624
+ const create = getAgentFacade2().create;
7625
+ return {
7626
+ judge: (ctx, opts) => judgeCallImpl2(ctx, opts, { create })
7627
+ };
7628
+ })();
7629
+ return yield* runUntilImpl2(agent, goal, options, deps);
7630
+ }
7631
+ return wrap();
7632
+ }
7633
+ exports.GOAL_CONTINUATION_MARKER = void 0;
7634
+ var init_goal_loop = __esm({
7635
+ "src/goal-loop.ts"() {
7636
+ exports.GOAL_CONTINUATION_MARKER = "[[theokit:goal-continuation]]";
7637
+ }
7638
+ });
7639
+
7507
7640
  // src/internal/runtime/lifecycle/run-until.ts
7508
7641
  var run_until_exports = {};
7509
7642
  __export(run_until_exports, {
7510
- GOAL_CONTINUATION_MARKER: () => exports.GOAL_CONTINUATION_MARKER,
7511
7643
  composeContinuation: () => composeContinuation,
7512
7644
  runUntilImpl: () => runUntilImpl
7513
7645
  });
@@ -7672,114 +7804,9 @@ ${goal}
7672
7804
  ${lastResponse.slice(-1e3)}`
7673
7805
  ].join("\n");
7674
7806
  }
7675
- exports.GOAL_CONTINUATION_MARKER = void 0;
7676
7807
  var init_run_until = __esm({
7677
7808
  "src/internal/runtime/lifecycle/run-until.ts"() {
7678
- exports.GOAL_CONTINUATION_MARKER = "[[theokit:goal-continuation]]";
7679
- }
7680
- });
7681
-
7682
- // src/internal/judge/parse-verdict.ts
7683
- function parseVerdict(text) {
7684
- const trimmed = text.trim();
7685
- if (trimmed.startsWith(DONE_PREFIX)) {
7686
- return {
7687
- verdict: "done",
7688
- reason: trimmed.slice(DONE_PREFIX.length).trim(),
7689
- parseFailed: false
7690
- };
7691
- }
7692
- if (trimmed.startsWith(CONTINUE_PREFIX)) {
7693
- return {
7694
- verdict: "continue",
7695
- reason: trimmed.slice(CONTINUE_PREFIX.length).trim(),
7696
- parseFailed: false
7697
- };
7698
- }
7699
- if (trimmed.startsWith(SKIPPED_PREFIX)) {
7700
- return {
7701
- verdict: "skipped",
7702
- reason: trimmed.slice(SKIPPED_PREFIX.length).trim(),
7703
- parseFailed: false
7704
- };
7705
- }
7706
- return {
7707
- verdict: "continue",
7708
- reason: `judge response malformed: "${trimmed.slice(0, 100)}"`,
7709
- parseFailed: true
7710
- };
7711
- }
7712
- var DONE_PREFIX, CONTINUE_PREFIX, SKIPPED_PREFIX;
7713
- var init_parse_verdict = __esm({
7714
- "src/internal/judge/parse-verdict.ts"() {
7715
- DONE_PREFIX = "DONE:";
7716
- CONTINUE_PREFIX = "CONTINUE:";
7717
- SKIPPED_PREFIX = "SKIPPED:";
7718
- }
7719
- });
7720
-
7721
- // src/internal/judge/judge-call.ts
7722
- var judge_call_exports = {};
7723
- __export(judge_call_exports, {
7724
- composeJudgePrompt: () => composeJudgePrompt,
7725
- judgeCallImpl: () => judgeCallImpl
7726
- });
7727
- async function judgeCallImpl(ctx, options, deps) {
7728
- const prompt = composeJudgePrompt(ctx);
7729
- const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;
7730
- if (apiKey === void 0) {
7731
- return {
7732
- verdict: "continue",
7733
- reason: "judge unavailable: OPENROUTER_API_KEY missing and no override passed via options.apiKey",
7734
- parseFailed: true
7735
- };
7736
- }
7737
- const judgeModel = options?.judgeModel ?? "openai/gpt-4o-mini";
7738
- let auxAgent;
7739
- try {
7740
- auxAgent = await deps.create({
7741
- apiKey,
7742
- model: { id: judgeModel },
7743
- tools: [],
7744
- local: {},
7745
- metadata: { forkOrigin: "judge" }
7746
- });
7747
- const run = await auxAgent.send(prompt);
7748
- const result = await run.wait();
7749
- return parseVerdict(result.result ?? "");
7750
- } catch (err) {
7751
- return {
7752
- verdict: "continue",
7753
- reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,
7754
- parseFailed: true
7755
- };
7756
- } finally {
7757
- if (auxAgent !== void 0) {
7758
- try {
7759
- await auxAgent.dispose();
7760
- } catch {
7761
- }
7762
- }
7763
- }
7764
- }
7765
- function composeJudgePrompt(ctx) {
7766
- const subgoals = ctx.subgoals !== void 0 && ctx.subgoals.length > 0 ? ctx.subgoals.join(", ") : "(none)";
7767
- return `You are a goal judge. Determine if this goal is satisfied.
7768
-
7769
- Goal: ${ctx.goal}
7770
- Subgoals: ${subgoals}
7771
- Last agent response: ${ctx.lastResponse}
7772
-
7773
- Respond with EXACTLY one of:
7774
- - DONE: <reason>
7775
- - CONTINUE: <what's left>
7776
- - SKIPPED: <why not applicable>
7777
-
7778
- Be strict. If unclear, prefer CONTINUE.`;
7779
- }
7780
- var init_judge_call = __esm({
7781
- "src/internal/judge/judge-call.ts"() {
7782
- init_parse_verdict();
7809
+ init_goal_loop();
7783
7810
  }
7784
7811
  });
7785
7812
 
@@ -21319,8 +21346,8 @@ async function getRegisteredAgentOrThrow(agentId) {
21319
21346
  // src/agent.ts
21320
21347
  init_errors();
21321
21348
  init_discovery();
21322
- init_agent_session();
21323
21349
  init_agent_factory_registry();
21350
+ init_agent_session();
21324
21351
  var streamObjectImport;
21325
21352
  var Agent = class _Agent {
21326
21353
  constructor() {
@@ -21612,7 +21639,9 @@ var Agent = class _Agent {
21612
21639
  reg = getRegisteredAgent(agentId);
21613
21640
  }
21614
21641
  if (reg === void 0 || reg.runtime !== "local") {
21615
- throw new exports.UnknownAgentError(`No local agent "${agentId}" registered \u2014 compact targets local sessions.`);
21642
+ throw new exports.UnknownAgentError(
21643
+ `No local agent "${agentId}" registered \u2014 compact targets local sessions.`
21644
+ );
21616
21645
  }
21617
21646
  const cwd = reg.cwd ?? process.cwd();
21618
21647
  const optModel = reg.options.model;
@@ -21622,16 +21651,20 @@ var Agent = class _Agent {
21622
21651
  const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
21623
21652
  const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
21624
21653
  const store = new FsSessionStore2({ baseDir, cwd });
21625
- return enqueueSessionWrite(cwd, agentId, () => compactSessionTranscript2({
21626
- store,
21627
- loc: { cwd, agentId, model },
21628
- sessionId: agentId,
21629
- trigger: options.trigger ?? "manual",
21630
- summarize: options.summarize ?? buildDefaultSummarizer2({
21631
- agentModel: model,
21632
- ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
21654
+ return enqueueSessionWrite(
21655
+ cwd,
21656
+ agentId,
21657
+ () => compactSessionTranscript2({
21658
+ store,
21659
+ loc: { cwd, agentId, model },
21660
+ sessionId: agentId,
21661
+ trigger: options.trigger ?? "manual",
21662
+ summarize: options.summarize ?? buildDefaultSummarizer2({
21663
+ agentModel: model,
21664
+ ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
21665
+ })
21633
21666
  })
21634
- }));
21667
+ );
21635
21668
  }
21636
21669
  /**
21637
21670
  * M51 — inject a SYNTHETIC user+assistant pair into a LOCAL session's persisted transcript WITHOUT
@@ -21648,7 +21681,9 @@ var Agent = class _Agent {
21648
21681
  reg = getRegisteredAgent(agentId);
21649
21682
  }
21650
21683
  if (reg === void 0 || reg.runtime !== "local") {
21651
- throw new exports.UnknownAgentError(`No local agent "${agentId}" registered \u2014 injectSessionTurn targets local sessions.`);
21684
+ throw new exports.UnknownAgentError(
21685
+ `No local agent "${agentId}" registered \u2014 injectSessionTurn targets local sessions.`
21686
+ );
21652
21687
  }
21653
21688
  const cwd = reg.cwd ?? process.cwd();
21654
21689
  const optModel = reg.options.model;
@@ -22813,24 +22848,7 @@ var EventBus = class {
22813
22848
 
22814
22849
  // src/index.ts
22815
22850
  init_generate_object();
22816
-
22817
- // src/goal-loop.ts
22818
- init_run_until();
22819
- function runGoalLoop(agent, goal, options, depsOverride) {
22820
- async function* wrap() {
22821
- const { runUntilImpl: runUntilImpl2 } = await Promise.resolve().then(() => (init_run_until(), run_until_exports));
22822
- const deps = depsOverride ?? await (async () => {
22823
- const { judgeCallImpl: judgeCallImpl2 } = await Promise.resolve().then(() => (init_judge_call(), judge_call_exports));
22824
- const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
22825
- const create = getAgentFacade2().create;
22826
- return {
22827
- judge: (ctx, opts) => judgeCallImpl2(ctx, opts, { create })
22828
- };
22829
- })();
22830
- return yield* runUntilImpl2(agent, goal, options, deps);
22831
- }
22832
- return wrap();
22833
- }
22851
+ init_goal_loop();
22834
22852
 
22835
22853
  // src/internal/budget/tracker/budget-tracker-counter.ts
22836
22854
  function createCounterBudgetTracker(options = {}) {