@theokit/sdk 4.19.0 → 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
@@ -6174,12 +6174,14 @@ __export(compact_session_exports, {
6174
6174
  shouldAutoCompact: () => shouldAutoCompact
6175
6175
  });
6176
6176
  function isCompactSummary(content) {
6177
- return content.startsWith(COMPACT_SUMMARY_MARKER);
6177
+ return content.startsWith(COMPACT_SUMMARY_MARKER) || content.startsWith("[[theokit:goal-continuation]]");
6178
6178
  }
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,6 +7510,133 @@ 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, {
@@ -7647,6 +7780,7 @@ async function* runUntilImpl(agent, goal, options, deps) {
7647
7780
  }
7648
7781
  function composeContinuation(goal, lastResponse) {
7649
7782
  return [
7783
+ exports.GOAL_CONTINUATION_MARKER,
7650
7784
  "Continue working toward the active goal.",
7651
7785
  "",
7652
7786
  `<objective>
@@ -7667,115 +7801,12 @@ ${goal}
7667
7801
  " current state, requirement by requirement. Treat uncertain or indirect evidence as not achieved.",
7668
7802
  "",
7669
7803
  `Your last response was:
7670
- ${lastResponse.slice(0, 1e3)}`
7804
+ ${lastResponse.slice(-1e3)}`
7671
7805
  ].join("\n");
7672
7806
  }
7673
7807
  var init_run_until = __esm({
7674
7808
  "src/internal/runtime/lifecycle/run-until.ts"() {
7675
- }
7676
- });
7677
-
7678
- // src/internal/judge/parse-verdict.ts
7679
- function parseVerdict(text) {
7680
- const trimmed = text.trim();
7681
- if (trimmed.startsWith(DONE_PREFIX)) {
7682
- return {
7683
- verdict: "done",
7684
- reason: trimmed.slice(DONE_PREFIX.length).trim(),
7685
- parseFailed: false
7686
- };
7687
- }
7688
- if (trimmed.startsWith(CONTINUE_PREFIX)) {
7689
- return {
7690
- verdict: "continue",
7691
- reason: trimmed.slice(CONTINUE_PREFIX.length).trim(),
7692
- parseFailed: false
7693
- };
7694
- }
7695
- if (trimmed.startsWith(SKIPPED_PREFIX)) {
7696
- return {
7697
- verdict: "skipped",
7698
- reason: trimmed.slice(SKIPPED_PREFIX.length).trim(),
7699
- parseFailed: false
7700
- };
7701
- }
7702
- return {
7703
- verdict: "continue",
7704
- reason: `judge response malformed: "${trimmed.slice(0, 100)}"`,
7705
- parseFailed: true
7706
- };
7707
- }
7708
- var DONE_PREFIX, CONTINUE_PREFIX, SKIPPED_PREFIX;
7709
- var init_parse_verdict = __esm({
7710
- "src/internal/judge/parse-verdict.ts"() {
7711
- DONE_PREFIX = "DONE:";
7712
- CONTINUE_PREFIX = "CONTINUE:";
7713
- SKIPPED_PREFIX = "SKIPPED:";
7714
- }
7715
- });
7716
-
7717
- // src/internal/judge/judge-call.ts
7718
- var judge_call_exports = {};
7719
- __export(judge_call_exports, {
7720
- composeJudgePrompt: () => composeJudgePrompt,
7721
- judgeCallImpl: () => judgeCallImpl
7722
- });
7723
- async function judgeCallImpl(ctx, options, deps) {
7724
- const prompt = composeJudgePrompt(ctx);
7725
- const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;
7726
- if (apiKey === void 0) {
7727
- return {
7728
- verdict: "continue",
7729
- reason: "judge unavailable: OPENROUTER_API_KEY missing and no override passed via options.apiKey",
7730
- parseFailed: true
7731
- };
7732
- }
7733
- const judgeModel = options?.judgeModel ?? "openai/gpt-4o-mini";
7734
- let auxAgent;
7735
- try {
7736
- auxAgent = await deps.create({
7737
- apiKey,
7738
- model: { id: judgeModel },
7739
- tools: [],
7740
- local: {},
7741
- metadata: { forkOrigin: "judge" }
7742
- });
7743
- const run = await auxAgent.send(prompt);
7744
- const result = await run.wait();
7745
- return parseVerdict(result.result ?? "");
7746
- } catch (err) {
7747
- return {
7748
- verdict: "continue",
7749
- reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,
7750
- parseFailed: true
7751
- };
7752
- } finally {
7753
- if (auxAgent !== void 0) {
7754
- try {
7755
- await auxAgent.dispose();
7756
- } catch {
7757
- }
7758
- }
7759
- }
7760
- }
7761
- function composeJudgePrompt(ctx) {
7762
- const subgoals = ctx.subgoals !== void 0 && ctx.subgoals.length > 0 ? ctx.subgoals.join(", ") : "(none)";
7763
- return `You are a goal judge. Determine if this goal is satisfied.
7764
-
7765
- Goal: ${ctx.goal}
7766
- Subgoals: ${subgoals}
7767
- Last agent response: ${ctx.lastResponse}
7768
-
7769
- Respond with EXACTLY one of:
7770
- - DONE: <reason>
7771
- - CONTINUE: <what's left>
7772
- - SKIPPED: <why not applicable>
7773
-
7774
- Be strict. If unclear, prefer CONTINUE.`;
7775
- }
7776
- var init_judge_call = __esm({
7777
- "src/internal/judge/judge-call.ts"() {
7778
- init_parse_verdict();
7809
+ init_goal_loop();
7779
7810
  }
7780
7811
  });
7781
7812
 
@@ -21315,8 +21346,8 @@ async function getRegisteredAgentOrThrow(agentId) {
21315
21346
  // src/agent.ts
21316
21347
  init_errors();
21317
21348
  init_discovery();
21318
- init_agent_session();
21319
21349
  init_agent_factory_registry();
21350
+ init_agent_session();
21320
21351
  var streamObjectImport;
21321
21352
  var Agent = class _Agent {
21322
21353
  constructor() {
@@ -21608,7 +21639,9 @@ var Agent = class _Agent {
21608
21639
  reg = getRegisteredAgent(agentId);
21609
21640
  }
21610
21641
  if (reg === void 0 || reg.runtime !== "local") {
21611
- 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
+ );
21612
21645
  }
21613
21646
  const cwd = reg.cwd ?? process.cwd();
21614
21647
  const optModel = reg.options.model;
@@ -21618,16 +21651,20 @@ var Agent = class _Agent {
21618
21651
  const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
21619
21652
  const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
21620
21653
  const store = new FsSessionStore2({ baseDir, cwd });
21621
- return enqueueSessionWrite(cwd, agentId, () => compactSessionTranscript2({
21622
- store,
21623
- loc: { cwd, agentId, model },
21624
- sessionId: agentId,
21625
- trigger: options.trigger ?? "manual",
21626
- summarize: options.summarize ?? buildDefaultSummarizer2({
21627
- agentModel: model,
21628
- ...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
+ })
21629
21666
  })
21630
- }));
21667
+ );
21631
21668
  }
21632
21669
  /**
21633
21670
  * M51 — inject a SYNTHETIC user+assistant pair into a LOCAL session's persisted transcript WITHOUT
@@ -21644,7 +21681,9 @@ var Agent = class _Agent {
21644
21681
  reg = getRegisteredAgent(agentId);
21645
21682
  }
21646
21683
  if (reg === void 0 || reg.runtime !== "local") {
21647
- 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
+ );
21648
21687
  }
21649
21688
  const cwd = reg.cwd ?? process.cwd();
21650
21689
  const optModel = reg.options.model;
@@ -22670,23 +22709,6 @@ async function updateJobStatus(jobId, enabled) {
22670
22709
  return updated;
22671
22710
  }
22672
22711
 
22673
- // src/goal-loop.ts
22674
- function runGoalLoop(agent, goal, options, depsOverride) {
22675
- async function* wrap() {
22676
- const { runUntilImpl: runUntilImpl2 } = await Promise.resolve().then(() => (init_run_until(), run_until_exports));
22677
- const deps = depsOverride ?? await (async () => {
22678
- const { judgeCallImpl: judgeCallImpl2 } = await Promise.resolve().then(() => (init_judge_call(), judge_call_exports));
22679
- const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
22680
- const create = getAgentFacade2().create;
22681
- return {
22682
- judge: (ctx, opts) => judgeCallImpl2(ctx, opts, { create })
22683
- };
22684
- })();
22685
- return yield* runUntilImpl2(agent, goal, options, deps);
22686
- }
22687
- return wrap();
22688
- }
22689
-
22690
22712
  // src/define-provider.ts
22691
22713
  init_builtin();
22692
22714
  init_registry();
@@ -22826,6 +22848,7 @@ var EventBus = class {
22826
22848
 
22827
22849
  // src/index.ts
22828
22850
  init_generate_object();
22851
+ init_goal_loop();
22829
22852
 
22830
22853
  // src/internal/budget/tracker/budget-tracker-counter.ts
22831
22854
  function createCounterBudgetTracker(options = {}) {