@yeaft/webchat-agent 1.0.565 → 1.0.566

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.565",
3
+ "version": "1.0.566",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -28,7 +28,7 @@ const BROWSER_ACTION_DEBUG_OPS = new Set(['get_action_messages', 'get_action_req
28
28
  // client-supplied value and only emits files resolved from owned upload ids.
29
29
  const BROWSER_FILE_FIELDS = Object.freeze({
30
30
  create: [
31
- 'title', 'goal', 'acceptanceCriteria', 'workItemType', 'workDir', 'deliveryTarget',
31
+ 'title', 'titleSource', 'goal', 'acceptanceCriteria', 'workItemType', 'workDir', 'deliveryTarget', 'deliveryInstructions',
32
32
  'reuseMemory', 'files', 'start',
33
33
  ],
34
34
  post_work_item_message: [
@@ -243,7 +243,7 @@ Return exactly one JSON object and no surrounding prose:
243
243
  }
244
244
 
245
245
  Rules:
246
- - When workItem.titleSource is coordinator_pending, include a concise title (prefer 6–12 words or a short Chinese phrase; at most 200 characters) in decision.title. This display label summarizes the original goal; it is not a contractPatch and must not rewrite or shorten the goal. Otherwise leave decision.title null. A missing or oversized display title is normalized by the runtime and must not change the substantive decision.
246
+ - When workItem.titleSource is coordinator_pending, include a concise title (prefer 6–12 words or a short Chinese phrase; at most 80 characters) in decision.title. This display label summarizes the original goal; it is not a contractPatch and must not rewrite or shorten the goal. Otherwise leave decision.title null. A missing or oversized display title is normalized by the runtime and must not change the substantive decision.
247
247
  - answer: explain state only. Never use it for an automatic advance trigger.
248
248
  - Never mutate goal, acceptanceCriteria, or deliveryTarget during automatic advance/recovery. decision.title is the only automatic title-generation path and is allowed only while titleSource is coordinator_pending; contractPatch (including a user-specified title) is allowed only for explicit user-originated refinement, never to make existing evidence pass. For an older WorkItem with no acceptance criteria, request_human to establish its completion condition before commissioning new work.
249
249
  - create_actions: create 1..8 currently runnable Actions. Every Action needs type, objective, approach, expectedOutcome, capability, candidateVpIds, assignmentReason, sourceActionIds, workspaceMode, and optional maxAttempts/separateFromActionTypes. sourceActionIds are context/audit references, never scheduling dependencies. Do not include dependsOnActionIds, dependsOnStageIds, stages, or a graph.
@@ -292,11 +292,21 @@ function cleanText(value, limit, name) {
292
292
  return text;
293
293
  }
294
294
 
295
+ function conciseDisplayTitle(value) {
296
+ const text = String(value || '').trim().replace(/\s+/g, ' ');
297
+ if (!text) return '';
298
+ const words = text.split(' ');
299
+ const concise = words.length > 12 ? `${words.slice(0, 12).join(' ')}…` : text;
300
+ const characters = [...concise];
301
+ return characters.length > 80 ? `${characters.slice(0, 79).join('')}…` : concise;
302
+ }
303
+
295
304
  function coordinatorDisplayTitle(value, detail) {
296
305
  if (detail.titleSource !== 'coordinator_pending') return null;
297
306
  const proposed = typeof value === 'string' ? value.trim() : '';
298
- const fallback = String(detail.goal || detail.title || 'Work Item').trim().replace(/\s+/g, ' ');
299
- return (proposed || fallback || 'Work Item').slice(0, 200);
307
+ return conciseDisplayTitle(proposed)
308
+ || conciseDisplayTitle(detail.goal || detail.title)
309
+ || 'Work Item';
300
310
  }
301
311
 
302
312
  function requiresDeliveryBoundaryDecision(detail, actions) {
@@ -634,6 +644,7 @@ export function coordinatorSnapshot(detail) {
634
644
  titleSource: detail.titleSource || 'explicit',
635
645
  goal: truncateUtf8(detail.goal, 4 * 1024),
636
646
  deliveryTarget: detail.deliveryTarget || null,
647
+ deliveryInstructions: truncateUtf8(detail.deliveryInstructions || '', 500) || null,
637
648
  acceptanceCriteria,
638
649
  workItemType: truncateUtf8(detail.workflowSnapshot?.workItemType, 256) || null,
639
650
  };
@@ -1,6 +1,6 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
2
 
3
- export const WORK_CENTER_SCHEMA_VERSION = 40;
3
+ export const WORK_CENTER_SCHEMA_VERSION = 41;
4
4
 
5
5
  const MIGRATIONS = [
6
6
  ['23-conversation-stream', migrateConversationStream],
@@ -21,6 +21,7 @@ const MIGRATIONS = [
21
21
  ['38-action-closure-and-outputs', migrateActionClosureAndOutputs],
22
22
  ['39-action-creation-source', migrateActionCreationSource],
23
23
  ['40-work-item-schedules', migrateWorkItemSchedules],
24
+ ['41-delivery-instructions', migrateDeliveryInstructions],
24
25
  ];
25
26
 
26
27
  const MIGRATION_ALIASES = new Map([
@@ -582,6 +583,12 @@ function migrateWorkItemSchedules(db) {
582
583
  WHERE schedule_status = 'scheduled'`);
583
584
  }
584
585
 
586
+ function migrateDeliveryInstructions(db) {
587
+ if (!hasColumn(db, 'work_items', 'delivery_instructions')) {
588
+ db.exec('ALTER TABLE work_items ADD COLUMN delivery_instructions TEXT');
589
+ }
590
+ }
591
+
585
592
  function migrateActionCreationSource(db) {
586
593
  if (!hasColumn(db, 'actions', 'creation_source')) {
587
594
  db.exec("ALTER TABLE actions ADD COLUMN creation_source TEXT NOT NULL DEFAULT 'legacy'");
@@ -1097,6 +1097,7 @@ export function projectWorkItemDetail(detail, options = {}) {
1097
1097
  schedule: detail.schedule || null,
1098
1098
  deliveryTarget: ['response', 'workspace_files', 'pull_request', 'merge'].includes(detail.deliveryTarget)
1099
1099
  ? detail.deliveryTarget : null,
1100
+ deliveryInstructions: truncateUtf8(detail.deliveryInstructions || '', 2 * 1024),
1100
1101
  waitingReason: sanitizeDiagnosticText(waitingReason(detail), MAX_ACTION_DIAGNOSTIC_CHARS),
1101
1102
  failureReason: workItemFailureReason(detail),
1102
1103
 
@@ -35,6 +35,11 @@ function requiredString(value, name) {
35
35
  return value.trim();
36
36
  }
37
37
 
38
+ function optionalString(value, limit) {
39
+ if (typeof value !== 'string') return '';
40
+ return value.trim().slice(0, limit);
41
+ }
42
+
38
43
  function requiredWorkDir(value) {
39
44
  const workDir = requiredString(value, 'workDir');
40
45
  let canonical;
@@ -164,6 +169,8 @@ export class WorkCenterService {
164
169
  watcher: this.watcher.status(),
165
170
  };
166
171
  }
172
+ case 'list_delivery_instructions':
173
+ return { values: this.store.listRecentDeliveryInstructions(payload.limit) };
167
174
  case 'get':
168
175
  return this.#requiredItem(payload.id);
169
176
  case 'get_action_messages': {
@@ -280,6 +287,8 @@ export class WorkCenterService {
280
287
  deliveryTarget: requestContext.userOriginated === true
281
288
  && ['response', 'workspace_files', 'pull_request', 'merge'].includes(payload.deliveryTarget)
282
289
  ? payload.deliveryTarget : null,
290
+ deliveryInstructions: requestContext.userOriginated === true
291
+ ? optionalString(payload.deliveryInstructions, 500) : '',
283
292
  reuseMemory: payload.reuseMemory !== false,
284
293
  origin: payload.origin && typeof payload.origin === 'object'
285
294
  ? {
@@ -112,6 +112,7 @@ function mapWorkItem(row) {
112
112
  coordinationMode: row.coordination_mode || 'legacy',
113
113
  finalResult: parseJson(row.final_result, null),
114
114
  deliveryTarget: row.delivery_target || null,
115
+ deliveryInstructions: row.delivery_instructions || '',
115
116
  schedule: row.schedule_status ? {
116
117
  status: row.schedule_status,
117
118
  scheduledFor: Number(row.scheduled_for) || null,
@@ -863,6 +864,7 @@ export class WorkItemStore {
863
864
  coordination_mode TEXT NOT NULL DEFAULT 'legacy',
864
865
  final_result TEXT,
865
866
  delivery_target TEXT,
867
+ delivery_instructions TEXT,
866
868
  schedule_status TEXT,
867
869
  scheduled_for INTEGER,
868
870
  schedule_triggered_at INTEGER,
@@ -1161,6 +1163,9 @@ export class WorkItemStore {
1161
1163
  if (!hasColumn(this.db, 'work_items', 'delivery_target')) {
1162
1164
  this.db.exec('ALTER TABLE work_items ADD COLUMN delivery_target TEXT');
1163
1165
  }
1166
+ if (!hasColumn(this.db, 'work_items', 'delivery_instructions')) {
1167
+ this.db.exec('ALTER TABLE work_items ADD COLUMN delivery_instructions TEXT');
1168
+ }
1164
1169
  if (!hasColumn(this.db, 'work_items', 'title_source')) {
1165
1170
  // Old titles were explicit under the previous creation contract.
1166
1171
  this.db.exec("ALTER TABLE work_items ADD COLUMN title_source TEXT NOT NULL DEFAULT 'explicit'");
@@ -2424,15 +2429,16 @@ export class WorkItemStore {
2424
2429
  const id = input.id || randomUUID();
2425
2430
  const workspaceKey = canonicalWorkspaceKey(input.workDir);
2426
2431
  this.db.prepare(`INSERT INTO work_items
2427
- (id, revision, execution_schema_version, ledger_revision, coordination_mode, final_result, delivery_target,
2432
+ (id, revision, execution_schema_version, ledger_revision, coordination_mode, final_result, delivery_target, delivery_instructions,
2428
2433
  schedule_status, scheduled_for, schedule_triggered_at, title, title_source, requirement, goal, acceptance_criteria, workflow_template, workflow_snapshot, status,
2429
2434
  current_action_id, current_run_id, work_dir, workspace_key, reuse_memory, origin, linked_session_ids,
2430
2435
  session_context, attachments, created_at, updated_at)
2431
- VALUES (?, 1, ?, 0, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(
2436
+ VALUES (?, 1, ?, 0, ?, NULL, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(
2432
2437
  id,
2433
2438
  Number.isInteger(input.executionSchemaVersion) ? input.executionSchemaVersion : 2,
2434
2439
  input.coordinationMode || 'legacy',
2435
2440
  input.deliveryTarget || null,
2441
+ input.deliveryInstructions || null,
2436
2442
  input.schedule?.status || null,
2437
2443
  input.schedule?.scheduledFor || null,
2438
2444
  input.title,
@@ -2463,6 +2469,16 @@ export class WorkItemStore {
2463
2469
  });
2464
2470
  }
2465
2471
 
2472
+ listRecentDeliveryInstructions(limit = 12) {
2473
+ const boundedLimit = Math.min(Math.max(Number(limit) || 12, 1), 24);
2474
+ return this.db.prepare(`SELECT delivery_instructions AS value, MAX(created_at) AS last_used_at
2475
+ FROM work_items
2476
+ WHERE delivery_instructions IS NOT NULL AND trim(delivery_instructions) != ''
2477
+ GROUP BY delivery_instructions
2478
+ ORDER BY last_used_at DESC, value ASC
2479
+ LIMIT ?`).all(boundedLimit).map(row => row.value);
2480
+ }
2481
+
2466
2482
  #insertAction(workItemId, input, sequence, now = this.now(), options = {}) {
2467
2483
  const workItem = this.getWorkItem(workItemId);
2468
2484
  const stageId = input.stageId || input.type;