@autonoma-ai/planner 0.1.8 → 0.1.10

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.
package/dist/index.js CHANGED
@@ -2160,25 +2160,6 @@ function resolveEntityOrder(models, importanceRank) {
2160
2160
  }
2161
2161
  return result;
2162
2162
  }
2163
- function getEntityDependencyChain(entityName, models, entityOrder) {
2164
- const modelMap = new Map(models.map((m) => [m.name, m]));
2165
- const visited = /* @__PURE__ */ new Set();
2166
- const chain = [];
2167
- function walk(name) {
2168
- if (visited.has(name)) return;
2169
- visited.add(name);
2170
- const model = modelMap.get(name);
2171
- if (!model) return;
2172
- for (const dep of model.created_by) {
2173
- if (entityOrder.includes(dep.owner)) {
2174
- walk(dep.owner);
2175
- }
2176
- }
2177
- chain.push(name);
2178
- }
2179
- walk(entityName);
2180
- return chain;
2181
- }
2182
2163
  var createdBySchema, auditedModelSchema, frontmatterSchema;
2183
2164
  var init_entity_order = __esm({
2184
2165
  "src/agents/04-recipe-builder/entity-order.ts"() {
@@ -3475,15 +3456,44 @@ var init_highlight = __esm({
3475
3456
  // src/agents/04-recipe-builder/recipe.ts
3476
3457
  import { readFile as readFile15, writeFile as writeFile7 } from "fs/promises";
3477
3458
  import { join as join22 } from "path";
3459
+ function collectRefs(value, out) {
3460
+ if (Array.isArray(value)) {
3461
+ for (const v of value) collectRefs(v, out);
3462
+ } else if (value !== null && typeof value === "object") {
3463
+ const obj = value;
3464
+ if (typeof obj._ref === "string") out.add(obj._ref);
3465
+ for (const v of Object.values(obj)) collectRefs(v, out);
3466
+ }
3467
+ }
3478
3468
  function buildSingleEntityRecipe(entityName, models, entityOrder, allEntities) {
3479
- const chain = getEntityDependencyChain(entityName, models, entityOrder);
3480
- const recipe = {};
3481
- for (const name of chain) {
3482
- const entity = allEntities[name];
3483
- if (entity?.recipeData && entity.recipeData.length > 0) {
3484
- recipe[name] = entity.recipeData;
3469
+ const modelMap = new Map(models.map((m) => [m.name, m]));
3470
+ const aliasOwner = /* @__PURE__ */ new Map();
3471
+ for (const [name, entity] of Object.entries(allEntities)) {
3472
+ for (const rec of entity?.recipeData ?? []) {
3473
+ if (typeof rec._alias === "string") aliasOwner.set(rec._alias, name);
3485
3474
  }
3486
3475
  }
3476
+ const recipe = {};
3477
+ const done = /* @__PURE__ */ new Set();
3478
+ const onStack = /* @__PURE__ */ new Set();
3479
+ function include(name) {
3480
+ if (done.has(name) || onStack.has(name)) return;
3481
+ onStack.add(name);
3482
+ const records = allEntities[name]?.recipeData ?? [];
3483
+ for (const dep of modelMap.get(name)?.created_by ?? []) {
3484
+ if (entityOrder.includes(dep.owner)) include(dep.owner);
3485
+ }
3486
+ const refs = /* @__PURE__ */ new Set();
3487
+ collectRefs(records, refs);
3488
+ for (const alias of refs) {
3489
+ const owner = aliasOwner.get(alias);
3490
+ if (owner && owner !== name) include(owner);
3491
+ }
3492
+ onStack.delete(name);
3493
+ done.add(name);
3494
+ if (records.length > 0) recipe[name] = records;
3495
+ }
3496
+ include(entityName);
3487
3497
  return recipe;
3488
3498
  }
3489
3499
  function buildFullRecipe(entityOrder, allEntities) {
@@ -3525,7 +3535,6 @@ var init_recipe = __esm({
3525
3535
  "src/agents/04-recipe-builder/recipe.ts"() {
3526
3536
  "use strict";
3527
3537
  init_esm_shims();
3528
- init_entity_order();
3529
3538
  RECIPE_FILE = "recipe.json";
3530
3539
  }
3531
3540
  });
@@ -3585,7 +3594,7 @@ function buildClassifierPrompt(args) {
3585
3594
  const statusLine = args.httpStatus != null ? `HTTP status: ${args.httpStatus}. (A 5xx usually means the handler threw; a 4xx is more often a rejected payload, but use the error text \u2014 status alone is not decisive.)` : `No HTTP status (the request threw before a response \u2014 often a network/server-process problem, lean implementation or unclear).`;
3586
3595
  return `${PRIMER}
3587
3596
 
3588
- - RECIPE DATA is wrong \u2014 the JSON the tool sent doesn't fit the developer's (correct) schema. Examples of the *kind* of problem (not an exhaustive list): a _ref points at an alias that does not exist among the valid targets listed below, a field holds a value the backend rejects, a required field is missing or an unknown field was sent, or a value has the wrong type. These are fixable by regenerating the data \u2014 the developer's code is fine.
3597
+ - RECIPE DATA is wrong \u2014 the JSON the tool sent doesn't fit the developer's (correct) schema. Examples of the *kind* of problem (not an exhaustive list): the request body references an alias (_ref) that no record in THIS SAME request declares with an _alias, a field holds a value the backend rejects, a required field is missing or an unknown field was sent, or a value has the wrong type. These are fixable by regenerating the data \u2014 the developer's code is fine. NOTE: an error like "references unknown alias(es): X" is recipe-side whenever X is not declared by an _alias in the test data shown below \u2014 the SDK resolves _refs WITHIN the request body, so it does not matter whether X appears in the "valid targets" list (that list is historical context about other entities' own runs, NOT the contents of this request).
3589
3598
  - IMPLEMENTATION is wrong \u2014 the developer's own handler/factory code is broken. Examples of the *kind* of problem: the factory for this entity is not registered, the handler references a column or table that does not exist (even though the recipe never mentioned it), the insert/delete logic has a bug, or the server threw an unhandled exception. No change to the test data can fix this; the developer must edit code.
3590
3599
 
3591
3600
  ## How to decide
@@ -3595,7 +3604,7 @@ Ask: "Would sending DIFFERENT, corrected test data \u2014 still matching the int
3595
3604
  - If the data shown below looks valid and the error points at the server's own logic, a missing factory, or a column/table the recipe never referenced \u2192 **implementation**.
3596
3605
  - If you genuinely cannot tell from the evidence \u2192 **unclear**. Prefer "unclear" over a confident guess; a wrong confident answer is worse than admitting uncertainty.
3597
3606
 
3598
- Cross-check the error against the actual data below before deciding \u2014 e.g. only call a _ref invalid if its target really is absent from the valid targets list.
3607
+ Cross-check the error against the actual data sent below before deciding. For an "unknown alias" error, look at whether a record in the test data declares that alias with an _alias \u2014 NOT at the valid-targets list. If the alias the error names is missing from (or spelled differently in) the data we sent, it is recipe-side, even when that alias appears in the valid-targets list.
3599
3608
 
3600
3609
  ## Evidence
3601
3610
 
@@ -3740,6 +3749,7 @@ ${completedAliases}
3740
3749
  Rules:
3741
3750
  - _alias fields must be unique identifiers (e.g., "card_1", "transaction_1")
3742
3751
  - _ref fields must reference an alias that ALREADY EXISTS on a parent entity \u2014 see the list of valid targets below. Never invent a _ref to an alias that isn't listed.
3752
+ - If the error says "references unknown alias(es): X", a _ref points at "X" but nothing being created declares it. Correct that _ref to one of the valid targets listed below (it's usually a typo, e.g. "users_1" vs "user_1"), or drop the reference if the field is optional. Do NOT leave a _ref pointing at an alias that isn't in the valid targets list.
3743
3753
  - Read scenarios.md to verify you're using correct alias names from parent entities
3744
3754
  - Field names must match the entity's schema from entity-audit.md`,
3745
3755
  model,
@@ -3906,8 +3916,7 @@ function seedFeedbackFromError(errorContext, reason) {
3906
3916
  async function promptOnFailure(entityName, errorBody, ctx, phase, httpStatus) {
3907
3917
  notify("Autonoma", `${entityName} \u2014 failed, action needed`);
3908
3918
  const errorContext = formatErrorContext(errorBody);
3909
- const budgetLeft = ctx.budget.attempts < MAX_AUTOFIX_ATTEMPTS;
3910
- const { side, reason } = await classifyFailure(ctx.model, {
3919
+ const { reason } = await classifyFailure(ctx.model, {
3911
3920
  entityName,
3912
3921
  phase,
3913
3922
  httpStatus,
@@ -3916,31 +3925,25 @@ async function promptOnFailure(entityName, errorBody, ctx, phase, httpStatus) {
3916
3925
  validRefAliases: ctx.validRefAliases,
3917
3926
  entityAudit: ctx.entityAudit
3918
3927
  });
3919
- if (side === "recipe" && budgetLeft) {
3928
+ if (ctx.budget.attempts < MAX_AUTOFIX_ATTEMPTS) {
3920
3929
  ctx.budget.attempts++;
3930
+ p5.log.info(`Triage: ${reason}`);
3921
3931
  p5.log.info(
3922
- `Triaged as a recipe-data issue \u2014 fixing automatically (attempt ${ctx.budget.attempts}/${MAX_AUTOFIX_ATTEMPTS}): ${reason}`
3932
+ `Handing the failure to the agent to fix from the error (attempt ${ctx.budget.attempts}/${MAX_AUTOFIX_ATTEMPTS})...`
3923
3933
  );
3924
3934
  return seedFeedbackFromError(errorContext, reason);
3925
3935
  }
3926
- const offerAutofix = side !== "implementation" && budgetLeft;
3927
- if (side === "implementation") {
3928
- p5.log.warn(`This looks like a handler/code issue, not the test data: ${reason}`);
3929
- } else if (side === "recipe" && !budgetLeft) {
3930
- p5.log.warn(`Autofix ran ${MAX_AUTOFIX_ATTEMPTS}\xD7 without resolving it \u2014 over to you. Latest read: ${reason}`);
3931
- }
3936
+ p5.log.warn(`The agent tried ${MAX_AUTOFIX_ATTEMPTS}\xD7 without resolving it. Latest triage: ${reason}`);
3932
3937
  const action = await p5.select({
3933
3938
  message: "What would you like to do?",
3934
3939
  options: [
3935
3940
  { value: "retry", label: "Yes, retry \u2014 I fixed my handler code", hint: "Send the same request again" },
3936
- ...offerAutofix ? [
3937
- {
3938
- value: "autofix",
3939
- label: "Yes, let the agent fix it from the error",
3940
- hint: "The error explains itself \u2014 hand it to the agent, no typing"
3941
- }
3942
- ] : [],
3943
- { value: "feedback", label: "Yes, fix the recipe data \u2014 I'll explain what's wrong", hint: "The request data is wrong and I'll describe the change" },
3941
+ {
3942
+ value: "autofix",
3943
+ label: "Let the agent try again from the error",
3944
+ hint: "Hand the raw error back to the agent, no typing"
3945
+ },
3946
+ { value: "feedback", label: "Let me explain what's wrong", hint: "Describe the change and the agent will apply it" },
3944
3947
  { value: "skip", label: "No, skip this entity", hint: "Move on to the next entity" }
3945
3948
  ]
3946
3949
  });
@@ -3949,7 +3952,7 @@ async function promptOnFailure(entityName, errorBody, ctx, phase, httpStatus) {
3949
3952
  if (action === "retry") return "retry";
3950
3953
  if (action === "autofix") {
3951
3954
  ctx.budget.attempts++;
3952
- return seedFeedbackFromError(errorContext);
3955
+ return seedFeedbackFromError(errorContext, reason);
3953
3956
  }
3954
3957
  const fb = await p5.text({
3955
3958
  message: "What's wrong with the recipe data?",