agentlife 2.6.11 → 2.6.13

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 (2) hide show
  1. package/dist/index.js +43 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -908,12 +908,9 @@ All inter-system signals are fixed strings. Nothing else is a signal.
908
908
  **Work-order markers — you RECEIVE (always process, never treat as end-of-conversation):**
909
909
  - \`[action:<name>] surfaceId=<id> [key=value ...]\` — user tapped a button on a widget you own. \`<name>\` is whatever you put in \`action=\` when you pushed the widget. Process it, then update or delete the source widget in the same turn.
910
910
  - \`[system:dismiss-requested] surfaceId=<id>\` — user tapped dismiss on a widget. You have ~30s to push an \`input\` surface with contextual alternatives before the platform finalizes the dismiss.
911
- - \`[event:dismissed] surfaceId=<id>\` — dismiss completed. Widget is already gone — do NOT push \`delete\`. Clean up any custom infra tied to the surface, then \`NO_REPLY\`.
911
+ - \`[event:dismissed] surfaceId=<id>\` — the platform deleted a widget without your involvement (non-guided dismiss path). The widget is already gone — do NOT push \`delete\`. Clean up any custom infra tied to the surface, then \`NO_REPLY\`. Does NOT fire for widgets you deleted yourself with the \`delete\` DSL — no notification is needed when you initiated the delete.
912
912
  - \`[system:cancelled]\` — user cancelled the turn mid-flight. Reply \`NO_REPLY\` and stop.
913
-
914
- **Input-surface control signals — platform EMITS when the user closes/skips an input surface:**
915
- - \`input_closed\` — user tapped the [×] on an input surface. Push it again later if still relevant.
916
- - \`input_skipped\` — user tapped Skip. Do not re-ask this session.
913
+ - \`[system] <free-form text>\` — platform-generated instruction (scheduled followup firing, Supervisor notification, quality/regression signal). The \`<text>\` after \`[system] \` is the instruction; read it and act. No fixed playbook — the text is the playbook.
917
914
 
918
915
  **Input-surface \`action=\` values — canonical set (anything else is a QUALITY ERROR on input surfaces):**
919
916
  - \`action=choice\` or \`action=select\` → numbered single-select (one tap fires). Dispatched as \`[action:choice] label=<label>\`.
@@ -954,7 +951,7 @@ A widget is a **goal** — a persistent objective that lives on the dashboard un
954
951
 
955
952
  **Goal validation:** could you have written this goal text BEFORE doing the work? If yes, it's a template — the goal must be derived from your findings. For one-shot operations, the goal is the unresolved question, decision, or opportunity your work surfaces.
956
953
 
957
- **Face vs detail.** Face = metrics, badges, gauges, one-line headers (2-second glance). Prose, analysis, lists \`detail:\`.
954
+ **Face vs detail.** Face = metrics, badges, gauges, one-line headers (2-second glance). \`detail:\` = markdown: analysis, trends, patterns, next-step context, personality. Every final (non-loading, non-input) widget MUST include \`detail:\` — that is where your expertise and voice live. Without it the widget is just a receipt and the platform enforces with a QUALITY ERROR. If you genuinely have nothing meaningful to add beyond the face, the goal is too shallow — rethink the goal before pushing an empty-detail widget.
958
955
 
959
956
  ### surfaceId
960
957
 
@@ -993,7 +990,7 @@ Button shapes and dispatch format for input surfaces are in **Signal Protocol**
993
990
 
994
991
  **One widget, one goal.** Set at creation, MUST NOT change. If an action shifts the objective, delete and create with a new surfaceId. Platform rejects goal mutations with a QUALITY ERROR.
995
992
 
996
- **User-initiated dismiss** (\`[system:dismiss-requested] surfaceId=<id>\`): you have ~30s to push an \`input\` surface with 2-3 contextual options + "Remove it" last. If the user picks an alternative, act on it and the dismiss is cancelled. If the user picks "Remove it" or skips, \`[event:dismissed]\` arrives the widget is already gone. See \`DISMISS_ALTERNATIVES_GUIDANCE\` (injected on the dismiss event) for crafting rules.
993
+ **User-initiated dismiss** (\`[system:dismiss-requested] surfaceId=<id>\`): you have ~30s to push an \`input\` surface with 2-3 contextual options + "Remove it" last. If the user picks an alternative, act on it and the dismiss is cancelled. If the user picks "Remove it" or the followup fires on timeout, push \`delete <parentSurfaceId>\` to finalize removal (and delete the dismiss-alt input surface in the same block). See \`DISMISS_ALTERNATIVES_GUIDANCE\` (injected on the dismiss event) for crafting rules.
997
994
 
998
995
  ### Autonomy & approval
999
996
 
@@ -1223,7 +1220,11 @@ The user is dismissing this widget. You have ~30s to push an \`input\` surface w
1223
1220
  - "Remove it" is always last. Use \`action=choice\` so it renders as a numbered list.
1224
1221
  - surfaceId: \`dismiss-alt-{parent-surfaceId}\`. Goal: reference the parent. Followup: ~1m so the flow doesn't stall if the user walks away.
1225
1222
 
1226
- If the user picks an alternative → act on it; the dismiss is cancelled. If they pick "Remove it" or skip → \`[event:dismissed]\` arrives, the widget is already gone, clean up any custom infra.`;
1223
+ If the user picks an alternative → act on it; the dismiss is cancelled.
1224
+
1225
+ If the user picks "Remove it" → push \`delete <parentSurfaceId>\` in the same turn (and delete the dismiss-alt input surface alongside it; both go in one \`agentlife_push\` with \`---\` between them). No \`[event:dismissed]\` fires in the guided flow — you initiated the delete, so no notification is needed. Clean up any custom infra inline before the delete.
1226
+
1227
+ If the 1-minute followup fires with no user response → same move: push \`delete <parentSurfaceId>\` + \`delete dismiss-alt-<parentSurfaceId>\`.`;
1227
1228
  var ORCHESTRATOR_AGENTS_MD = `# AgentLife Orchestrator
1228
1229
 
1229
1230
  You are a message router. You never answer questions, perform tasks, push widgets, or produce content.
@@ -1918,6 +1919,27 @@ function matchMetadata(block, key) {
1918
1919
  }
1919
1920
  return v || null;
1920
1921
  }
1922
+ function hasDetailContent(rawDsl) {
1923
+ const lines = rawDsl.split(`
1924
+ `);
1925
+ for (let i = 0;i < lines.length; i++) {
1926
+ const m = lines[i].match(/^\s*detail:\s*(.*)$/);
1927
+ if (!m)
1928
+ continue;
1929
+ if (m[1].trim())
1930
+ return true;
1931
+ for (let j = i + 1;j < lines.length; j++) {
1932
+ const next = lines[j];
1933
+ if (next.trim() === "")
1934
+ continue;
1935
+ if (/^\s/.test(next))
1936
+ return true;
1937
+ return false;
1938
+ }
1939
+ return false;
1940
+ }
1941
+ return false;
1942
+ }
1921
1943
 
1922
1944
  // dsl/validate.ts
1923
1945
  var KNOWN_BODY_KEYWORDS = new Set([
@@ -4724,7 +4746,7 @@ ${parts.join(`
4724
4746
  });
4725
4747
  }
4726
4748
  var QUALITY_CHECK_MAX_WAIT_MS = 5000;
4727
- var TERMINAL_MARKERS = new Set(["NO_REPLY", "ANNOUNCE_SKIP", "REPLY_SKIP", "HEARTBEAT_OK", "done"]);
4749
+ var TERMINAL_MARKERS = new Set(["NO_REPLY", "ANNOUNCE_SKIP", "REPLY_SKIP", "HEARTBEAT_OK"]);
4728
4750
  function processPendingQualityChecks(state) {
4729
4751
  if (state.disabled || !state.historyDb)
4730
4752
  return 0;
@@ -6316,6 +6338,7 @@ function registerWidgetPushTool(api, state2) {
6316
6338
  const errors = [];
6317
6339
  const goalChanges = [];
6318
6340
  const missingFollowup = [];
6341
+ const missingDetail = [];
6319
6342
  for (const r of results) {
6320
6343
  if (r.kind !== "push")
6321
6344
  continue;
@@ -6334,11 +6357,19 @@ function registerWidgetPushTool(api, state2) {
6334
6357
  data: JSON.stringify({ issue: "missing_followup", surfaceId: r.surfaceId })
6335
6358
  });
6336
6359
  }
6360
+ if (view && view.state !== "loading" && !view.isInput && !hasDetailContent(view.rawDsl) && !goalChanges.includes(r.surfaceId) && !missingFollowup.includes(r.surfaceId)) {
6361
+ missingDetail.push(r.surfaceId);
6362
+ recordActivity(state2, "quality_warning", sessionKey, agentId, {
6363
+ data: JSON.stringify({ issue: "missing_detail", surfaceId: r.surfaceId })
6364
+ });
6365
+ }
6337
6366
  }
6338
6367
  if (goalChanges.length > 0)
6339
6368
  errors.push(buildGoalChangedError(goalChanges));
6340
6369
  if (missingFollowup.length > 0)
6341
6370
  errors.push(buildMissingFollowupError(missingFollowup));
6371
+ if (missingDetail.length > 0)
6372
+ errors.push(buildMissingDetailError(missingDetail));
6342
6373
  const validationErrors = collectValidationErrors(state2, results, sessionKey, agentId);
6343
6374
  errors.push(...validationErrors);
6344
6375
  if (ownershipViolations.length > 0) {
@@ -6370,6 +6401,9 @@ function buildGoalChangedError(ids) {
6370
6401
  function buildMissingFollowupError(ids) {
6371
6402
  return `[QUALITY ERROR] ${ids.join(", ")}: missing followup. Every widget MUST have a followup — it is the widget's heartbeat and ownership signal. Push again with a followup: line, or delete the widget if work is done.`;
6372
6403
  }
6404
+ function buildMissingDetailError(ids) {
6405
+ return `[QUALITY ERROR] ${ids.join(", ")}: missing detail. Every final widget MUST include a \`detail:\` block — it's where your analysis, trends, and voice live. The face alone is just a receipt. Push again with a detail: block containing analysis/personality/next-step context appropriate to the domain.`;
6406
+ }
6373
6407
  function collectValidationErrors(state2, results, sessionKey, agentId) {
6374
6408
  const errors = [];
6375
6409
  const unknownKeywordHits = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlife",
3
- "version": "2.6.11",
3
+ "version": "2.6.13",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "bun build index.ts --outfile dist/index.js --target node --external openclaw/plugin-sdk",