agentlife 2.6.12 → 2.6.14
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 +42 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -951,7 +951,7 @@ A widget is a **goal** — a persistent objective that lives on the dashboard un
|
|
|
951
951
|
|
|
952
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.
|
|
953
953
|
|
|
954
|
-
**Face vs detail.** Face = metrics, badges, gauges, one-line headers (2-second glance).
|
|
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.
|
|
955
955
|
|
|
956
956
|
### surfaceId
|
|
957
957
|
|
|
@@ -1919,6 +1919,32 @@ function matchMetadata(block, key) {
|
|
|
1919
1919
|
}
|
|
1920
1920
|
return v || null;
|
|
1921
1921
|
}
|
|
1922
|
+
function isLoadingPush(rawDsl) {
|
|
1923
|
+
const header = rawDsl.split(`
|
|
1924
|
+
`, 1)[0] ?? "";
|
|
1925
|
+
return /\bstate=loading\b/.test(header);
|
|
1926
|
+
}
|
|
1927
|
+
function hasDetailContent(rawDsl) {
|
|
1928
|
+
const lines = rawDsl.split(`
|
|
1929
|
+
`);
|
|
1930
|
+
for (let i = 0;i < lines.length; i++) {
|
|
1931
|
+
const m = lines[i].match(/^\s*detail:\s*(.*)$/);
|
|
1932
|
+
if (!m)
|
|
1933
|
+
continue;
|
|
1934
|
+
if (m[1].trim())
|
|
1935
|
+
return true;
|
|
1936
|
+
for (let j = i + 1;j < lines.length; j++) {
|
|
1937
|
+
const next = lines[j];
|
|
1938
|
+
if (next.trim() === "")
|
|
1939
|
+
continue;
|
|
1940
|
+
if (/^\s/.test(next))
|
|
1941
|
+
return true;
|
|
1942
|
+
return false;
|
|
1943
|
+
}
|
|
1944
|
+
return false;
|
|
1945
|
+
}
|
|
1946
|
+
return false;
|
|
1947
|
+
}
|
|
1922
1948
|
|
|
1923
1949
|
// dsl/validate.ts
|
|
1924
1950
|
var KNOWN_BODY_KEYWORDS = new Set([
|
|
@@ -6297,7 +6323,7 @@ function registerWidgetPushTool(api, state2) {
|
|
|
6297
6323
|
const view = getSurface(state2, sid);
|
|
6298
6324
|
if (!view)
|
|
6299
6325
|
continue;
|
|
6300
|
-
if (view.isOverlay || view.isInput || view.
|
|
6326
|
+
if (view.isOverlay || view.isInput || isLoadingPush(view.rawDsl))
|
|
6301
6327
|
continue;
|
|
6302
6328
|
const notifTitle = capitalize(agentId);
|
|
6303
6329
|
const notifBody = extractWidgetText(view.lines) ?? "New update";
|
|
@@ -6317,6 +6343,7 @@ function registerWidgetPushTool(api, state2) {
|
|
|
6317
6343
|
const errors = [];
|
|
6318
6344
|
const goalChanges = [];
|
|
6319
6345
|
const missingFollowup = [];
|
|
6346
|
+
const missingDetail = [];
|
|
6320
6347
|
for (const r of results) {
|
|
6321
6348
|
if (r.kind !== "push")
|
|
6322
6349
|
continue;
|
|
@@ -6329,17 +6356,26 @@ function registerWidgetPushTool(api, state2) {
|
|
|
6329
6356
|
if (r.isTransient)
|
|
6330
6357
|
continue;
|
|
6331
6358
|
const view = getSurface(state2, r.surfaceId);
|
|
6332
|
-
|
|
6359
|
+
const isLoading = view ? isLoadingPush(view.rawDsl) : false;
|
|
6360
|
+
if (view && !isLoading && !view.followup && !goalChanges.includes(r.surfaceId)) {
|
|
6333
6361
|
missingFollowup.push(r.surfaceId);
|
|
6334
6362
|
recordActivity(state2, "quality_warning", sessionKey, agentId, {
|
|
6335
6363
|
data: JSON.stringify({ issue: "missing_followup", surfaceId: r.surfaceId })
|
|
6336
6364
|
});
|
|
6337
6365
|
}
|
|
6366
|
+
if (view && !isLoading && !view.isInput && !hasDetailContent(view.rawDsl) && !goalChanges.includes(r.surfaceId) && !missingFollowup.includes(r.surfaceId)) {
|
|
6367
|
+
missingDetail.push(r.surfaceId);
|
|
6368
|
+
recordActivity(state2, "quality_warning", sessionKey, agentId, {
|
|
6369
|
+
data: JSON.stringify({ issue: "missing_detail", surfaceId: r.surfaceId })
|
|
6370
|
+
});
|
|
6371
|
+
}
|
|
6338
6372
|
}
|
|
6339
6373
|
if (goalChanges.length > 0)
|
|
6340
6374
|
errors.push(buildGoalChangedError(goalChanges));
|
|
6341
6375
|
if (missingFollowup.length > 0)
|
|
6342
6376
|
errors.push(buildMissingFollowupError(missingFollowup));
|
|
6377
|
+
if (missingDetail.length > 0)
|
|
6378
|
+
errors.push(buildMissingDetailError(missingDetail));
|
|
6343
6379
|
const validationErrors = collectValidationErrors(state2, results, sessionKey, agentId);
|
|
6344
6380
|
errors.push(...validationErrors);
|
|
6345
6381
|
if (ownershipViolations.length > 0) {
|
|
@@ -6371,6 +6407,9 @@ function buildGoalChangedError(ids) {
|
|
|
6371
6407
|
function buildMissingFollowupError(ids) {
|
|
6372
6408
|
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.`;
|
|
6373
6409
|
}
|
|
6410
|
+
function buildMissingDetailError(ids) {
|
|
6411
|
+
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.`;
|
|
6412
|
+
}
|
|
6374
6413
|
function collectValidationErrors(state2, results, sessionKey, agentId) {
|
|
6375
6414
|
const errors = [];
|
|
6376
6415
|
const unknownKeywordHits = [];
|