@elisym/cli 0.12.0 → 0.13.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.
package/README.md CHANGED
@@ -127,6 +127,8 @@ my-project/
127
127
 
128
128
  Skills are defined in `SKILL.md` files inside `./skills/<skill-name>/`. Each file has YAML frontmatter (between `---` delimiters) that describes the skill, followed by a markdown body that becomes the LLM system prompt.
129
129
 
130
+ > Canonical reference for every frontmatter field, execution mode, the LLM health-monitor contract, and the script exit-code convention lives in [`SKILLS.md`](./SKILLS.md). The summary below covers the common cases; consult `SKILLS.md` for the full schema.
131
+
130
132
  ```markdown
131
133
  ---
132
134
  name: youtube-summary
package/dist/index.js CHANGED
@@ -1969,6 +1969,13 @@ function resolveJobAsset(tags, skills) {
1969
1969
  return skill?.asset ?? NATIVE_SOL;
1970
1970
  }
1971
1971
  var BILLING_BODY_MARKERS3 = ["credit balance", "billing", "insufficient", "insufficient_quota"];
1972
+ var AGENT_UNAVAILABLE_MESSAGE = "Agent temporarily unavailable";
1973
+ var AgentUnavailableError = class extends Error {
1974
+ constructor() {
1975
+ super(AGENT_UNAVAILABLE_MESSAGE);
1976
+ this.name = "AgentUnavailableError";
1977
+ }
1978
+ };
1972
1979
  function bodyLooksLikeBilling3(body) {
1973
1980
  const lower = body.toLowerCase();
1974
1981
  return BILLING_BODY_MARKERS3.some((marker) => lower.includes(marker));
@@ -2064,7 +2071,7 @@ var AgentRuntime = class {
2064
2071
  */
2065
2072
  markHealthFromExecuteError(skill, err, log, jobId) {
2066
2073
  if (!this.healthMonitor) {
2067
- return;
2074
+ return false;
2068
2075
  }
2069
2076
  const tag = `[${jobId.slice(0, 8)}]`;
2070
2077
  if (err instanceof ScriptBillingExhaustedError) {
@@ -2074,19 +2081,19 @@ var AgentRuntime = class {
2074
2081
  log(
2075
2082
  `${tag} Script returned exit ${err.exitCode} (billing-exhausted) but skill "${skill.name}" did not declare provider/model in SKILL.md - cannot gate future jobs.`
2076
2083
  );
2077
- return;
2084
+ return false;
2078
2085
  }
2079
2086
  log(
2080
2087
  `${tag} Script signaled billing-exhausted (exit ${err.exitCode}). Marking ${provider}/${model} unhealthy; future jobs against this pair will be refused until recovery probe succeeds.`
2081
2088
  );
2082
2089
  this.healthMonitor.markUnhealthyFromJob(provider, model, "billing", err.message);
2083
- return;
2090
+ return true;
2084
2091
  }
2085
2092
  if (skill.mode === "llm" && skill.resolvedTriple) {
2086
2093
  const message = err instanceof Error ? err.message : String(err);
2087
2094
  const match = /API error:\s*(\d{3})\b\s*(.*)/i.exec(message);
2088
2095
  if (!match) {
2089
- return;
2096
+ return false;
2090
2097
  }
2091
2098
  const status = Number(match[1]);
2092
2099
  const body = (match[2] ?? "").slice(0, 200);
@@ -2095,7 +2102,7 @@ var AgentRuntime = class {
2095
2102
  const isBilling400 = status === 400 && bodyLooksLikeBilling3(body);
2096
2103
  const isBilling429 = status === 429 && bodyLooksLikeBilling3(body);
2097
2104
  if (!isBillingStatus && !isAuthStatus && !isBilling400 && !isBilling429) {
2098
- return;
2105
+ return false;
2099
2106
  }
2100
2107
  const reason = isAuthStatus ? "invalid" : "billing";
2101
2108
  const provider = skill.resolvedTriple.provider;
@@ -2104,7 +2111,9 @@ var AgentRuntime = class {
2104
2111
  `${tag} LLM provider returned HTTP ${status} (${reason}). Marking ${provider}/${model} unhealthy; future jobs against this pair will be refused until recovery probe succeeds.`
2105
2112
  );
2106
2113
  this.healthMonitor.markUnhealthyFromJob(provider, model, reason, body);
2114
+ return true;
2107
2115
  }
2116
+ return false;
2108
2117
  }
2109
2118
  /** Fetch on-chain protocol config (fee, treasury). Always fetches fresh to avoid stale treasury. */
2110
2119
  async fetchProtocolConfig() {
@@ -2271,7 +2280,14 @@ var AgentRuntime = class {
2271
2280
  this.ledger.markFailed(job.jobId);
2272
2281
  }
2273
2282
  this.callbacks.onJobError?.(job.jobId, e.message);
2274
- const safeMessage = e.message?.includes("API") ? "Internal processing error" : e.message ?? "Unknown error";
2283
+ let safeMessage;
2284
+ if (e instanceof AgentUnavailableError) {
2285
+ safeMessage = e.message;
2286
+ } else if (e.message?.includes("API")) {
2287
+ safeMessage = "Internal processing error";
2288
+ } else {
2289
+ safeMessage = e.message ?? "Unknown error";
2290
+ }
2275
2291
  await this.transport.sendFeedback(job, { type: "error", message: safeMessage }).catch(() => {
2276
2292
  });
2277
2293
  } finally {
@@ -2295,7 +2311,7 @@ var AgentRuntime = class {
2295
2311
  log(`[${job.jobId.slice(0, 8)}] LLM health gate refused job: ${detail}`);
2296
2312
  await this.transport.sendFeedback(job, {
2297
2313
  type: "error",
2298
- message: "Service temporarily unavailable, try again later"
2314
+ message: AGENT_UNAVAILABLE_MESSAGE
2299
2315
  }).catch(() => {
2300
2316
  });
2301
2317
  return;
@@ -2348,7 +2364,10 @@ var AgentRuntime = class {
2348
2364
  { ...this.skillCtx, signal }
2349
2365
  );
2350
2366
  } catch (err) {
2351
- this.markHealthFromExecuteError(skill, err, log, job.jobId);
2367
+ const flippedToUnhealthy = this.markHealthFromExecuteError(skill, err, log, job.jobId);
2368
+ if (flippedToUnhealthy) {
2369
+ throw new AgentUnavailableError();
2370
+ }
2352
2371
  throw err;
2353
2372
  }
2354
2373
  this.ledger.markExecuted(job.jobId, output.data);