@theokit/sdk 2.2.0 → 2.4.0

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/dist/a2a/index.cjs +191 -48
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +192 -49
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/compaction.cjs +78 -0
  7. package/dist/compaction.cjs.map +1 -0
  8. package/dist/compaction.d.cts +76 -0
  9. package/dist/compaction.d.ts +76 -0
  10. package/dist/compaction.js +70 -0
  11. package/dist/compaction.js.map +1 -0
  12. package/dist/{cron-JSPSFczQ.d.cts → cron-B656C3iq.d.cts} +28 -2
  13. package/dist/{cron-Aksw2Hy4.d.ts → cron-CM2M9mhB.d.ts} +28 -2
  14. package/dist/cron.cjs +192 -57
  15. package/dist/cron.cjs.map +1 -1
  16. package/dist/cron.d.cts +2 -2
  17. package/dist/cron.d.ts +2 -2
  18. package/dist/cron.js +192 -57
  19. package/dist/cron.js.map +1 -1
  20. package/dist/{errors-Bcw_Pakm.d.ts → errors-DG_7CAUg.d.ts} +1 -1
  21. package/dist/{errors-Vhg6ZV4o.d.cts → errors-QDYUPABr.d.cts} +1 -1
  22. package/dist/errors.d.cts +2 -2
  23. package/dist/eval.cjs +192 -57
  24. package/dist/eval.cjs.map +1 -1
  25. package/dist/eval.js +192 -57
  26. package/dist/eval.js.map +1 -1
  27. package/dist/index.cjs +275 -68
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +50 -7
  30. package/dist/index.d.ts +50 -7
  31. package/dist/index.js +275 -69
  32. package/dist/index.js.map +1 -1
  33. package/dist/internal/agent-loop/loop.d.ts +5 -0
  34. package/dist/internal/llm/model-capabilities.d.ts +40 -0
  35. package/dist/internal/llm/model-identifier.d.ts +9 -1
  36. package/dist/internal/llm/model-option.d.ts +38 -0
  37. package/dist/internal/runtime/compression/compression-attempt.d.ts +24 -0
  38. package/dist/internal/runtime/compression/compression-config.d.ts +33 -0
  39. package/dist/internal/runtime/compression/compression-decision.d.ts +10 -0
  40. package/dist/internal/runtime/compression/compression-helpers.d.ts +18 -0
  41. package/dist/internal/runtime/compression/compression-model-registry.d.ts +41 -0
  42. package/dist/internal/runtime/compression/compression-summarizer.d.ts +29 -0
  43. package/dist/internal/runtime/context/project-instructions.d.ts +66 -0
  44. package/dist/internal/runtime/context/replay-history.d.ts +43 -0
  45. package/dist/internal/runtime/hooks/hooks-frontmatter.d.ts +1 -1
  46. package/dist/internal/runtime/lifecycle/run-to-completion.d.ts +22 -0
  47. package/dist/internal/runtime/skills/discover-skills.d.ts +68 -0
  48. package/dist/internal/runtime/skills/skills-block.d.ts +18 -0
  49. package/dist/internal/runtime/skills/subagent-tool-scope.d.ts +25 -0
  50. package/dist/messages.cjs +24 -0
  51. package/dist/messages.cjs.map +1 -0
  52. package/dist/messages.d.cts +33 -0
  53. package/dist/messages.d.ts +33 -0
  54. package/dist/messages.js +20 -0
  55. package/dist/messages.js.map +1 -0
  56. package/dist/models.cjs +233 -0
  57. package/dist/models.cjs.map +1 -0
  58. package/dist/models.d.cts +16 -0
  59. package/dist/models.d.ts +16 -0
  60. package/dist/models.js +228 -0
  61. package/dist/models.js.map +1 -0
  62. package/dist/project.cjs +149 -0
  63. package/dist/project.cjs.map +1 -0
  64. package/dist/project.d.cts +14 -0
  65. package/dist/project.d.ts +14 -0
  66. package/dist/project.js +146 -0
  67. package/dist/project.js.map +1 -0
  68. package/dist/{run-ekGKZlmg.d.cts → run-BPRYG1Id.d.cts} +55 -2
  69. package/dist/{run-ekGKZlmg.d.ts → run-BPRYG1Id.d.ts} +55 -2
  70. package/dist/skills.cjs +282 -0
  71. package/dist/skills.cjs.map +1 -0
  72. package/dist/skills.d.cts +19 -0
  73. package/dist/skills.d.ts +19 -0
  74. package/dist/skills.js +279 -0
  75. package/dist/skills.js.map +1 -0
  76. package/dist/subagents.cjs +24 -0
  77. package/dist/subagents.cjs.map +1 -0
  78. package/dist/subagents.d.cts +14 -0
  79. package/dist/subagents.d.ts +14 -0
  80. package/dist/subagents.js +21 -0
  81. package/dist/subagents.js.map +1 -0
  82. package/dist/types/agent.d.ts +22 -0
  83. package/dist/types/conversation-storage.d.ts +5 -1
  84. package/dist/types/run.d.ts +54 -1
  85. package/package.json +62 -2
package/dist/a2a/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, realpathSync, lstatSync, readlinkSync, mkdirSync, readFileSync, readdirSync } from 'fs';
1
+ import { existsSync, realpathSync, mkdirSync, lstatSync, readlinkSync, readFileSync, readdirSync } from 'fs';
2
2
  import { randomUUID, createHash, randomBytes } from 'crypto';
3
3
  import { join, dirname, resolve, sep, relative, isAbsolute } from 'path';
4
4
  import { stat, mkdir, readFile, rename, rm, readdir, appendFile, open, unlink, statfs, access } from 'fs/promises';
@@ -3000,6 +3000,18 @@ var init_cloud_agent = __esm({
3000
3000
  "fork"
3001
3001
  );
3002
3002
  }
3003
+ /**
3004
+ * The continuation driver re-sends against a stateful local session; the
3005
+ * cloud runtime manages its own continuation policy server-side (M1 Phase 3).
3006
+ *
3007
+ * @public
3008
+ */
3009
+ runToCompletion() {
3010
+ throw new UnsupportedRunOperationError(
3011
+ "Agent.runToCompletion() is not supported on cloud agents. Cloud runtime manages continuation server-side. Use a local agent.",
3012
+ "runToCompletion"
3013
+ );
3014
+ }
3003
3015
  /**
3004
3016
  * Personality presets require consistent server-side enforcement that
3005
3017
  * the cloud runtime (pre-release) does not yet provide. Reject explicitly
@@ -4907,6 +4919,8 @@ function parseSubagentMarkdown(raw, filename) {
4907
4919
  if (fields.model !== void 0) {
4908
4920
  definition.model = fields.model === "inherit" ? "inherit" : { id: fields.model };
4909
4921
  }
4922
+ const tools = fields.tools?.split(/[\s,]+/).map((t) => t.trim()).filter((t) => t.length > 0);
4923
+ if (tools !== void 0 && tools.length > 0) definition.tools = tools;
4910
4924
  return { name, definition };
4911
4925
  }
4912
4926
  function splitFrontmatter2(raw, filename) {
@@ -5110,25 +5124,33 @@ ${lines.join("\n")}
5110
5124
  }
5111
5125
  });
5112
5126
 
5127
+ // src/internal/runtime/skills/skills-block.ts
5128
+ function buildSkillsBlock(skills) {
5129
+ if (skills.length === 0) return void 0;
5130
+ const lines = skills.map(
5131
+ (skill) => ` - ${escapeBlockBody(skill.name)}: ${escapeBlockBody(skill.description)}`
5132
+ );
5133
+ return `<skills>
5134
+ ${lines.join("\n")}
5135
+ </skills>`;
5136
+ }
5137
+ var init_skills_block = __esm({
5138
+ "src/internal/runtime/skills/skills-block.ts"() {
5139
+ init_escape();
5140
+ }
5141
+ });
5142
+
5113
5143
  // src/internal/runtime/system-prompt/sources/skills-provider.ts
5114
5144
  var SkillsPromptProvider;
5115
5145
  var init_skills_provider = __esm({
5116
5146
  "src/internal/runtime/system-prompt/sources/skills-provider.ts"() {
5117
- init_escape();
5147
+ init_skills_block();
5118
5148
  SkillsPromptProvider = class {
5119
5149
  id = "skills";
5120
5150
  priority = 20;
5121
5151
  contribute(ctx) {
5122
5152
  if (ctx.skillsAutoInject === false) return Promise.resolve(void 0);
5123
- if (ctx.skills.length === 0) return Promise.resolve(void 0);
5124
- const lines = ctx.skills.map((skill) => {
5125
- const name = escapeBlockBody(skill.name);
5126
- const description = escapeBlockBody(skill.description);
5127
- return ` - ${name}: ${description}`;
5128
- });
5129
- return Promise.resolve(`<skills>
5130
- ${lines.join("\n")}
5131
- </skills>`);
5153
+ return Promise.resolve(buildSkillsBlock(ctx.skills));
5132
5154
  }
5133
5155
  };
5134
5156
  }
@@ -6384,36 +6406,71 @@ var init_skill_frontmatter = __esm({
6384
6406
  init_yaml_frontmatter();
6385
6407
  }
6386
6408
  });
6387
- function tryParseSkill(raw, fallbackName, source) {
6409
+ async function discoverSkills(dir, options) {
6410
+ let entries;
6411
+ try {
6412
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
6413
+ } catch {
6414
+ return [];
6415
+ }
6416
+ const skills = [];
6417
+ for (const entry of entries) {
6418
+ if (!entry.isDirectory()) continue;
6419
+ let skillDir;
6420
+ try {
6421
+ skillDir = safePathJoin(dir, entry.name);
6422
+ assertNoSymlinkEscape(skillDir, dir);
6423
+ } catch {
6424
+ continue;
6425
+ }
6426
+ const skillPath = join(skillDir, "SKILL.md");
6427
+ let raw;
6428
+ try {
6429
+ raw = await readFile(skillPath, "utf8");
6430
+ } catch {
6431
+ continue;
6432
+ }
6433
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
6434
+ if (skill !== void 0) skills.push(skill);
6435
+ }
6436
+ return skills;
6437
+ }
6438
+ function tryParseSkill(raw, fallbackName, source, options) {
6388
6439
  try {
6389
6440
  const frontmatter = parseSkillFrontmatter(raw, fallbackName);
6390
- const metadata = {
6441
+ const skill = {
6391
6442
  name: frontmatter.name,
6392
6443
  description: frontmatter.description,
6393
6444
  source
6394
6445
  };
6395
- if (frontmatter.category !== void 0) metadata.category = frontmatter.category;
6396
- if (frontmatter.dependencies !== void 0) metadata.dependencies = frontmatter.dependencies;
6397
- return metadata;
6446
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
6447
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
6448
+ return skill;
6398
6449
  } catch (cause) {
6399
6450
  if (cause instanceof ConfigurationError) {
6400
- const code = cause.code ?? "unknown";
6401
- process.stderr.write(
6402
- `[theokit-sdk] skill ${fallbackName} skipped (${code}): ${cause.message}
6403
- `
6404
- );
6451
+ options?.onInvalidSkill?.({
6452
+ name: fallbackName,
6453
+ source,
6454
+ code: cause.code ?? "unknown",
6455
+ message: cause.message
6456
+ });
6405
6457
  return void 0;
6406
6458
  }
6407
6459
  throw cause;
6408
6460
  }
6409
6461
  }
6410
- var SkillsManager;
6411
- var init_skills_manager = __esm({
6412
- "src/internal/runtime/skills/skills-manager.ts"() {
6462
+ var init_discover_skills = __esm({
6463
+ "src/internal/runtime/skills/discover-skills.ts"() {
6413
6464
  init_errors();
6414
6465
  init_path_guard();
6415
6466
  init_workspace_dir();
6416
6467
  init_skill_frontmatter();
6468
+ }
6469
+ });
6470
+ var SkillsManager;
6471
+ var init_skills_manager = __esm({
6472
+ "src/internal/runtime/skills/skills-manager.ts"() {
6473
+ init_discover_skills();
6417
6474
  SkillsManager = class {
6418
6475
  constructor(cwd, _enabled, settingSourcesIncludeProject) {
6419
6476
  this.cwd = cwd;
@@ -6430,28 +6487,15 @@ var init_skills_manager = __esm({
6430
6487
  await this.refresh();
6431
6488
  }
6432
6489
  async refresh() {
6433
- this.skills = [];
6434
6490
  const skillsRoot = join(this.cwd, ".theokit", "skills");
6435
- const entries = await readWorkspaceDir(skillsRoot, "skills_read_error", "skills directory");
6436
- for (const entry of entries) {
6437
- if (!entry.isDirectory()) continue;
6438
- let skillDir;
6439
- try {
6440
- skillDir = safePathJoin(skillsRoot, entry.name);
6441
- assertNoSymlinkEscape(skillDir, skillsRoot);
6442
- } catch {
6443
- continue;
6444
- }
6445
- const skillPath = join(skillDir, "SKILL.md");
6446
- let raw;
6447
- try {
6448
- raw = await readFile(skillPath, "utf8");
6449
- } catch {
6450
- continue;
6491
+ this.skills = await discoverSkills(skillsRoot, {
6492
+ onInvalidSkill: (info) => {
6493
+ process.stderr.write(
6494
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
6495
+ `
6496
+ );
6451
6497
  }
6452
- const metadata = tryParseSkill(raw, entry.name, skillPath);
6453
- if (metadata !== void 0) this.skills.push(metadata);
6454
- }
6498
+ });
6455
6499
  }
6456
6500
  list() {
6457
6501
  return Promise.resolve(this.skills);
@@ -6913,6 +6957,7 @@ async function initLoopContext(inputs) {
6913
6957
  finalStatus: "finished",
6914
6958
  usage: new UsageAccumulator(),
6915
6959
  nudgeAttempts: 0,
6960
+ stopFeedbackAttempts: 0,
6916
6961
  ...memoryProviderHandle !== void 0 ? { memoryProviderHandle } : {},
6917
6962
  ...memorySystemPromptAdditions !== void 0 ? { memorySystemPromptAdditions } : {}
6918
6963
  };
@@ -7068,8 +7113,9 @@ function registerLoopError(ctx, cause) {
7068
7113
  if (ctx.error !== void 0) return;
7069
7114
  const rawMessage = cause?.message;
7070
7115
  const message = typeof rawMessage === "string" ? rawMessage : cause instanceof Error ? cause.message : String(cause);
7116
+ const metaCode = cause?.metadata?.code;
7071
7117
  const rawCode = cause?.code;
7072
- const code = typeof rawCode === "string" ? rawCode : void 0;
7118
+ const code = typeof metaCode === "string" ? metaCode : typeof rawCode === "string" ? rawCode : void 0;
7073
7119
  ctx.error = code !== void 0 ? { message, code, cause } : { message, cause };
7074
7120
  }
7075
7121
  async function runCollectorLoop(generator, inputs, ctx) {
@@ -8152,6 +8198,28 @@ function shouldNudgeAndContinue(ctx, llmOutput) {
8152
8198
  });
8153
8199
  return true;
8154
8200
  }
8201
+ async function reflectAfterStop(inputs, ctx) {
8202
+ const result = await inputs.hooks.run({
8203
+ event: "stop",
8204
+ agentId: inputs.agentId,
8205
+ runId: inputs.runId
8206
+ });
8207
+ if (result.blocked) return false;
8208
+ if (ctx.stopFeedbackAttempts >= MAX_STOP_FEEDBACK_ATTEMPTS) return false;
8209
+ const feedback = result.decisions.find(
8210
+ (d) => d.decision === "feedback" && (d.feedback ?? "").length > 0
8211
+ )?.feedback;
8212
+ if (feedback === void 0) return false;
8213
+ ctx.stopFeedbackAttempts += 1;
8214
+ ctx.messages.push({ role: "user", content: [{ type: "text", text: feedback }] });
8215
+ return true;
8216
+ }
8217
+ async function finishOrReflect(inputs, ctx, llmOutput) {
8218
+ if (shouldNudgeAndContinue(ctx, llmOutput)) return "continue";
8219
+ if (await reflectAfterStop(inputs, ctx)) return "continue";
8220
+ ctx.finalStatus = "finished";
8221
+ return "done";
8222
+ }
8155
8223
  async function runIteration(inputs, ctx) {
8156
8224
  const llmOutput = await streamLlmTurn(inputs, ctx);
8157
8225
  accumulateUsage(ctx.usage, llmOutput);
@@ -8185,9 +8253,7 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
8185
8253
  await emitAssistantTextStep(inputs, ctx, llmOutput.text);
8186
8254
  }
8187
8255
  if (llmOutput.stopReason !== "tool_use" || llmOutput.toolCalls.length === 0) {
8188
- if (shouldNudgeAndContinue(ctx, llmOutput)) return "continue";
8189
- ctx.finalStatus = "finished";
8190
- return "done";
8256
+ return finishOrReflect(inputs, ctx, llmOutput);
8191
8257
  }
8192
8258
  ctx.messages.push(buildAssistantTurn(llmOutput.text, llmOutput.toolCalls));
8193
8259
  const toolResults = await dispatchTools(inputs, ctx.tools, llmOutput.toolCalls, ctx.events);
@@ -8210,7 +8276,7 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
8210
8276
  pushToolConversationSteps(ctx, llmOutput.toolCalls, toolResults);
8211
8277
  return handleToolErrorContinuation(inputs, ctx, toolResults);
8212
8278
  }
8213
- var MAX_NUDGE_ATTEMPTS;
8279
+ var MAX_NUDGE_ATTEMPTS, MAX_STOP_FEEDBACK_ATTEMPTS;
8214
8280
  var init_loop = __esm({
8215
8281
  "src/internal/agent-loop/loop.ts"() {
8216
8282
  init_budget();
@@ -8223,6 +8289,7 @@ var init_loop = __esm({
8223
8289
  init_tool_dispatch();
8224
8290
  init_usage_and_cost();
8225
8291
  MAX_NUDGE_ATTEMPTS = 2;
8292
+ MAX_STOP_FEEDBACK_ATTEMPTS = 2;
8226
8293
  }
8227
8294
  });
8228
8295
 
@@ -14187,6 +14254,71 @@ var init_agent_factory_registry = __esm({
14187
14254
  }
14188
14255
  });
14189
14256
 
14257
+ // src/internal/runtime/lifecycle/run-to-completion.ts
14258
+ var run_to_completion_exports = {};
14259
+ __export(run_to_completion_exports, {
14260
+ classifyRound: () => classifyRound,
14261
+ runToCompletionImpl: () => runToCompletionImpl
14262
+ });
14263
+ function isEmptyRound(result) {
14264
+ return (result.result ?? "").trim() === "";
14265
+ }
14266
+ function classifyRound(result, round, maxRounds, emptyStreak) {
14267
+ if (result.stoppedAtIterationLimit !== true) return "done";
14268
+ if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
14269
+ if (round >= maxRounds) return "step_limit";
14270
+ return "continue";
14271
+ }
14272
+ function addUsage(acc, u) {
14273
+ if (u === void 0) return acc;
14274
+ const inputTokens = (acc?.inputTokens ?? 0) + u.inputTokens;
14275
+ const outputTokens = (acc?.outputTokens ?? 0) + u.outputTokens;
14276
+ const sumOpt = (a, b) => a === void 0 && b === void 0 ? void 0 : (a ?? 0) + (b ?? 0);
14277
+ return {
14278
+ inputTokens,
14279
+ outputTokens,
14280
+ totalTokens: inputTokens + outputTokens,
14281
+ cacheReadTokens: sumOpt(acc?.cacheReadTokens, u.cacheReadTokens),
14282
+ cacheWriteTokens: sumOpt(acc?.cacheWriteTokens, u.cacheWriteTokens),
14283
+ reasoningTokens: sumOpt(acc?.reasoningTokens, u.reasoningTokens)
14284
+ };
14285
+ }
14286
+ function buildResult(terminal, rounds, lastResult, usage) {
14287
+ return { terminal, rounds, lastResult, ...usage !== void 0 ? { usage } : {} };
14288
+ }
14289
+ async function stepRound(agent, prompt, sendOptions, round, maxRounds, state2) {
14290
+ const run = await agent.send(prompt, sendOptions);
14291
+ const result = await run.wait();
14292
+ const usage = addUsage(state2.usage, result.usage);
14293
+ const decision = classifyRound(result, round, maxRounds, state2.emptyStreak);
14294
+ if (decision !== "continue") return { terminal: buildResult(decision, round, result, usage) };
14295
+ const emptyStreak = isEmptyRound(result) ? state2.emptyStreak + 1 : 0;
14296
+ return { next: { usage, emptyStreak }, lastResult: result };
14297
+ }
14298
+ async function runToCompletionImpl(agent, message, options) {
14299
+ const maxRounds = options?.maxRounds ?? DEFAULT_MAX_ROUNDS;
14300
+ const continuationPrompt = options?.continuationPrompt ?? DEFAULT_CONTINUATION_PROMPT;
14301
+ const { onTruncated, signal, sendOptions } = options ?? {};
14302
+ let state2 = { usage: void 0, emptyStreak: 0 };
14303
+ for (let round = 0; ; round += 1) {
14304
+ const prompt = round === 0 ? message : continuationPrompt;
14305
+ const outcome = await stepRound(agent, prompt, sendOptions, round, maxRounds, state2);
14306
+ if ("terminal" in outcome) return outcome.terminal;
14307
+ state2 = outcome.next;
14308
+ await onTruncated?.({ round });
14309
+ if (signal?.aborted === true) {
14310
+ return buildResult("step_limit", round, outcome.lastResult, state2.usage);
14311
+ }
14312
+ }
14313
+ }
14314
+ var DEFAULT_MAX_ROUNDS, DEFAULT_CONTINUATION_PROMPT;
14315
+ var init_run_to_completion = __esm({
14316
+ "src/internal/runtime/lifecycle/run-to-completion.ts"() {
14317
+ DEFAULT_MAX_ROUNDS = 5;
14318
+ DEFAULT_CONTINUATION_PROMPT = "Continue from where you left off and finish the task. If it is already complete, give the final answer.";
14319
+ }
14320
+ });
14321
+
14190
14322
  // src/internal/runtime/lifecycle/fork-agent.ts
14191
14323
  var fork_agent_exports = {};
14192
14324
  __export(fork_agent_exports, {
@@ -14267,6 +14399,13 @@ function localAgentRunUntil(agent, goal, options) {
14267
14399
  }
14268
14400
  return wrap();
14269
14401
  }
14402
+ function localAgentRunToCompletion(agent, message, options) {
14403
+ async function run() {
14404
+ const { runToCompletionImpl: runToCompletionImpl2 } = await Promise.resolve().then(() => (init_run_to_completion(), run_to_completion_exports));
14405
+ return runToCompletionImpl2({ send: (m, o) => agent.send(m, o) }, message, options);
14406
+ }
14407
+ return run();
14408
+ }
14270
14409
  async function localAgentFork(parent, options) {
14271
14410
  const { forkAgentImpl: forkAgentImpl2 } = await Promise.resolve().then(() => (init_fork_agent(), fork_agent_exports));
14272
14411
  const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
@@ -15401,6 +15540,10 @@ var init_local_agent = __esm({
15401
15540
  fork(options) {
15402
15541
  return localAgentFork({ agentId: this.agentId, options: this.options, personalitySlugSnapshot: this.personalityStore.active(this.agentId) }, options);
15403
15542
  }
15543
+ // biome-ignore format: G8 budget — see runUntil comment above.
15544
+ runToCompletion(message, options) {
15545
+ return localAgentRunToCompletion(this, message, options);
15546
+ }
15404
15547
  };
15405
15548
  }
15406
15549
  });