happy-imou-cloud 2.1.39 → 2.1.41

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 (25) hide show
  1. package/dist/{BaseReasoningProcessor-BUTolvO5.cjs → BaseReasoningProcessor-DAPsauUX.cjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-Cbp6sIDm.mjs → BaseReasoningProcessor-Dica2zdX.mjs} +2 -2
  3. package/dist/{ProviderSelectionHandler-B22eXuym.cjs → ProviderSelectionHandler-4nuTd8AP.cjs} +2 -2
  4. package/dist/{ProviderSelectionHandler-DrSgStLw.mjs → ProviderSelectionHandler-CmeZ92yO.mjs} +2 -2
  5. package/dist/{api-BoeZDGwx.cjs → api-C_Tnx4UG.cjs} +131 -5
  6. package/dist/{api-wcqkneTg.mjs → api-CwNEbJBM.mjs} +131 -6
  7. package/dist/{command-CkYq_KwA.cjs → command-C3RwwPVD.cjs} +2 -2
  8. package/dist/{command-DcgK0y3F.mjs → command-D0FxDynx.mjs} +2 -2
  9. package/dist/{index-B9mt95QV.mjs → index-D5m2Duxd.mjs} +7 -7
  10. package/dist/{index-Cgor8CE7.cjs → index-Dh0qGrEd.cjs} +10 -10
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/lib.cjs +1 -1
  14. package/dist/lib.d.cts +195 -40
  15. package/dist/lib.d.mts +195 -40
  16. package/dist/lib.mjs +1 -1
  17. package/dist/{registerKillSessionHandler-Buc97BEh.mjs → registerKillSessionHandler-6JloVYkb.mjs} +132 -7
  18. package/dist/{registerKillSessionHandler-DtXhn2Cd.cjs → registerKillSessionHandler-Bkh8uLhC.cjs} +132 -7
  19. package/dist/{runClaude-BYKNCDEU.mjs → runClaude-Bng_IsE7.mjs} +59 -5
  20. package/dist/{runClaude-CwXQwmgw.cjs → runClaude-mIFO7YxF.cjs} +59 -5
  21. package/dist/{runCodex-DqAddhDE.mjs → runCodex-DAc6flez.mjs} +34 -8
  22. package/dist/{runCodex-BkB_YKhV.cjs → runCodex-cNuxGshy.cjs} +34 -8
  23. package/dist/{runGemini-3jkfOtlr.mjs → runGemini-DdXj8ltI.mjs} +65 -7
  24. package/dist/{runGemini-B4uXPrue.cjs → runGemini-DsRFV8WN.cjs} +65 -7
  25. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
- import { k as initialMachineMetadata, R as RuntimeShell, f as formatDisplayMessage, l as resolveCanonicalToolNameV2, m as isTerminalReferenceOnlyPayload } from './index-B9mt95QV.mjs';
2
- import { r as readSettings, H as HeadTailPreviewBuffer, d as HAPPY_ORG_REPLY_ACK_VERSION, e as HAPPY_ORG_TURN_REPORT_TAG, f as HAPPY_ORG_SUMMARY_MAX_LENGTH, g as HAPPY_ORG_REPEAT_THRESHOLD, l as logger } from './api-wcqkneTg.mjs';
1
+ import { k as initialMachineMetadata, R as RuntimeShell, f as formatDisplayMessage, l as resolveCanonicalToolNameV2, m as isTerminalReferenceOnlyPayload } from './index-D5m2Duxd.mjs';
2
+ import { r as readSettings, H as HeadTailPreviewBuffer, e as HAPPY_ORG_REPLY_ACK_VERSION, f as HAPPY_ORG_TURN_REPORT_TAG, g as HAPPY_ORG_SUMMARY_MAX_LENGTH, h as HAPPY_ORG_REPEAT_THRESHOLD, l as logger } from './api-CwNEbJBM.mjs';
3
3
  import { randomUUID } from 'node:crypto';
4
4
  import { basename } from 'node:path';
5
5
  import { createHash } from 'crypto';
@@ -762,6 +762,12 @@ const SCOPE_ALIASES = ["scope"];
762
762
  const READ_ACK_ALIASES = ["read_ack", "readAck"];
763
763
  const STATUS_ALIASES = ["status"];
764
764
  const NOTE_ALIASES = ["note"];
765
+ const REPLY_TO_ALIASES = ["reply_to", "replyTo"];
766
+ const POSITION_STATUS_ALIASES = ["position_status", "positionStatus"];
767
+ const LATEST_USER_VISIBLE_RESULT_ALIASES = ["latest_user_visible_result", "latestUserVisibleResult"];
768
+ const BLOCKER_SUMMARY_ALIASES = ["blocker_summary", "blockerSummary"];
769
+ const ACCEPTANCE_STATE_ALIASES = ["acceptance_state", "acceptanceState"];
770
+ const CEO_WRITE_NEXT_STEP_ALIASES = ["ceo_write_next_step", "ceoWriteNextStep"];
765
771
  function normalizeOptionalText(value) {
766
772
  if (typeof value !== "string") {
767
773
  return null;
@@ -793,12 +799,23 @@ function cloneHappyOrgReplyContext(replyContext) {
793
799
  function cloneHappyOrgSpecialistHomeIdentity(specialistHome) {
794
800
  return specialistHome ? { ...specialistHome } : null;
795
801
  }
802
+ function cloneHappyOrgAcceptanceHandoff(handoff) {
803
+ if (handoff === void 0) {
804
+ return void 0;
805
+ }
806
+ return handoff ? { ...handoff } : null;
807
+ }
796
808
  function cloneHappyOrgTurnReport(report) {
797
- return report ? {
809
+ if (!report) {
810
+ return void 0;
811
+ }
812
+ const acceptanceHandoff = cloneHappyOrgAcceptanceHandoff(report.acceptanceHandoff);
813
+ return {
798
814
  ...report,
799
815
  replyContext: cloneHappyOrgReplyContext(report.replyContext),
800
- specialistHome: cloneHappyOrgSpecialistHomeIdentity(report.specialistHome)
801
- } : void 0;
816
+ specialistHome: cloneHappyOrgSpecialistHomeIdentity(report.specialistHome),
817
+ ...acceptanceHandoff !== void 0 ? { acceptanceHandoff } : {}
818
+ };
802
819
  }
803
820
  function cloneHappyOrgMetadata(happyOrg) {
804
821
  return {
@@ -972,6 +989,48 @@ function normalizeReplyMode(value) {
972
989
  }
973
990
  return null;
974
991
  }
992
+ function normalizeAcceptanceState(value) {
993
+ const normalized = normalizeSingleLineText(value)?.toLowerCase();
994
+ if (normalized === "not_ready" || normalized === "awaiting_acceptance" || normalized === "closed") {
995
+ return normalized;
996
+ }
997
+ return null;
998
+ }
999
+ function normalizeBlockerSummary(value) {
1000
+ const normalized = normalizeSingleLineText(value);
1001
+ if (!normalized) {
1002
+ return null;
1003
+ }
1004
+ const lowered = normalized.toLowerCase();
1005
+ if (lowered === "none" || lowered === "null" || lowered === "no blocker") {
1006
+ return null;
1007
+ }
1008
+ return normalized;
1009
+ }
1010
+ function normalizeHappyOrgAcceptanceHandoffRecord(record) {
1011
+ const dispatchId = normalizeSingleLineText(getFirstDefined(record, DISPATCH_ID_ALIASES));
1012
+ const replyTo = normalizeSingleLineText(getFirstDefined(record, REPLY_TO_ALIASES));
1013
+ const taskId = normalizeSingleLineText(getFirstDefined(record, TASK_ID_ALIASES));
1014
+ const positionStatus = normalizeSingleLineText(getFirstDefined(record, POSITION_STATUS_ALIASES));
1015
+ const latestUserVisibleResult = normalizeSingleLineText(getFirstDefined(record, LATEST_USER_VISIBLE_RESULT_ALIASES));
1016
+ const acceptanceState = normalizeAcceptanceState(getFirstDefined(record, ACCEPTANCE_STATE_ALIASES));
1017
+ const ceoWriteNextStep = normalizeSingleLineText(getFirstDefined(record, CEO_WRITE_NEXT_STEP_ALIASES));
1018
+ if (!dispatchId || !replyTo || !taskId || !positionStatus || !latestUserVisibleResult || !acceptanceState || !ceoWriteNextStep) {
1019
+ return null;
1020
+ }
1021
+ return {
1022
+ dispatchId,
1023
+ replyTo,
1024
+ taskId,
1025
+ positionId: normalizeSingleLineText(getFirstDefined(record, POSITION_ID_ALIASES)),
1026
+ responsibilityId: normalizeSingleLineText(getFirstDefined(record, RESPONSIBILITY_ID_ALIASES)),
1027
+ positionStatus,
1028
+ latestUserVisibleResult,
1029
+ blockerSummary: normalizeBlockerSummary(getFirstDefined(record, BLOCKER_SUMMARY_ALIASES)),
1030
+ acceptanceState,
1031
+ ceoWriteNextStep
1032
+ };
1033
+ }
975
1034
  function normalizeHappyOrgDispatchAckRecord(record) {
976
1035
  const ackVersion = normalizeSingleLineText(getFirstDefined(record, ACK_VERSION_ALIASES));
977
1036
  const dispatchId = normalizeSingleLineText(getFirstDefined(record, DISPATCH_ID_ALIASES));
@@ -1040,6 +1099,20 @@ function isHappyOrgDispatchAckCandidateRecord(record) {
1040
1099
  ...NOTE_ALIASES
1041
1100
  ].some((key) => Object.prototype.hasOwnProperty.call(record, key));
1042
1101
  }
1102
+ function isHappyOrgAcceptanceHandoffCandidateRecord(record) {
1103
+ return [
1104
+ ...DISPATCH_ID_ALIASES,
1105
+ ...REPLY_TO_ALIASES,
1106
+ ...TASK_ID_ALIASES,
1107
+ ...POSITION_ID_ALIASES,
1108
+ ...RESPONSIBILITY_ID_ALIASES,
1109
+ ...POSITION_STATUS_ALIASES,
1110
+ ...LATEST_USER_VISIBLE_RESULT_ALIASES,
1111
+ ...BLOCKER_SUMMARY_ALIASES,
1112
+ ...ACCEPTANCE_STATE_ALIASES,
1113
+ ...CEO_WRITE_NEXT_STEP_ALIASES
1114
+ ].some((key) => Object.prototype.hasOwnProperty.call(record, key));
1115
+ }
1043
1116
  function extractKeyValueBlocks(text) {
1044
1117
  const blocks = [];
1045
1118
  let currentBlock = null;
@@ -1106,6 +1179,51 @@ function resolveHappyOrgDispatchAckEnvelopeCandidate(text) {
1106
1179
  outcome: "absent"
1107
1180
  };
1108
1181
  }
1182
+ function resolveHappyOrgAcceptanceHandoffCandidate(text) {
1183
+ const trimmed = stripCodeFence(text).trim();
1184
+ if (!trimmed) {
1185
+ return { outcome: "absent" };
1186
+ }
1187
+ let sawCandidate = false;
1188
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
1189
+ try {
1190
+ const parsed = JSON.parse(trimmed);
1191
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1192
+ const record = parsed;
1193
+ if (isHappyOrgAcceptanceHandoffCandidateRecord(record)) {
1194
+ const handoff = normalizeHappyOrgAcceptanceHandoffRecord(record);
1195
+ if (handoff) {
1196
+ return {
1197
+ outcome: "valid",
1198
+ handoff
1199
+ };
1200
+ }
1201
+ sawCandidate = true;
1202
+ }
1203
+ }
1204
+ } catch {
1205
+ }
1206
+ }
1207
+ for (const block of extractKeyValueBlocks(text)) {
1208
+ if (!isHappyOrgAcceptanceHandoffCandidateRecord(block)) {
1209
+ continue;
1210
+ }
1211
+ const handoff = normalizeHappyOrgAcceptanceHandoffRecord(block);
1212
+ if (handoff) {
1213
+ return {
1214
+ outcome: "valid",
1215
+ handoff
1216
+ };
1217
+ }
1218
+ sawCandidate = true;
1219
+ }
1220
+ return sawCandidate ? {
1221
+ outcome: "invalid",
1222
+ diagnostic: "Happy Org acceptance handoff ignored: malformed mini-pack. Required fields are dispatch_id, reply_to, task_id, position_status, latest_user_visible_result, acceptance_state, and ceo_write_next_step."
1223
+ } : {
1224
+ outcome: "absent"
1225
+ };
1226
+ }
1109
1227
  function recordHappyOrgDispatchAck(metadata, ack, acknowledgedAt) {
1110
1228
  const nextHappyOrg = normalizeHappyOrgMetadata(metadata);
1111
1229
  nextHappyOrg.dispatchAcks = nextHappyOrg.dispatchAcks ?? {};
@@ -1627,7 +1745,11 @@ function buildHappyOrgTurnPrompt(prompt, turn) {
1627
1745
  `task_ack=${turn.context.taskId}`,
1628
1746
  "read_ack=yes",
1629
1747
  "status=accepted | standby | blocked",
1630
- "note=<short note>"
1748
+ "note=<short note>",
1749
+ "Keep dispatch_id / task_id / position_id / responsibility_id stable across the visible ack, visible reply, and final turn report.",
1750
+ "When turnStatus=task_complete and reply context exists, include a short source reply for the original requester at reply_to before the final JSON block.",
1751
+ "That source reply / acceptance handoff mini-pack should explicitly mention position_status, latest_user_visible_result, blocker_summary, and acceptance_state=awaiting_acceptance.",
1752
+ "Use acceptance_state=closed only after CEO or the original requester actually confirms close; do not self-mark closed."
1631
1753
  ].filter(Boolean) : [];
1632
1754
  const specialistHomeLines = turn.specialistHome ? [
1633
1755
  "",
@@ -1819,6 +1941,8 @@ function finalizeHappyOrgTurn(opts) {
1819
1941
  const currentHappyOrg = normalizeHappyOrgMetadata(metadata);
1820
1942
  const resolvedReplyContext = cloneHappyOrgReplyContext(queuedTurn.replyContext) ?? cloneHappyOrgReplyContext(currentHappyOrg.replyContext);
1821
1943
  const resolvedSpecialistHome = cloneHappyOrgSpecialistHomeIdentity(queuedTurn.specialistHome) ?? cloneHappyOrgSpecialistHomeIdentity(currentHappyOrg.specialistHome);
1944
+ const acceptanceHandoffCandidate = resolveHappyOrgAcceptanceHandoffCandidate(cleanedText);
1945
+ const acceptanceHandoff = acceptanceHandoffCandidate.outcome === "valid" && acceptanceHandoffCandidate.handoff.taskId === queuedTurn.context.taskId && (!resolvedReplyContext || acceptanceHandoffCandidate.handoff.dispatchId === resolvedReplyContext.dispatchId) ? acceptanceHandoffCandidate.handoff : null;
1822
1946
  const report = {
1823
1947
  ...queuedTurn.context,
1824
1948
  turnStatus: reportTurnStatus,
@@ -1834,7 +1958,8 @@ function finalizeHappyOrgTurn(opts) {
1834
1958
  normalizedDraft.targetArtifact ?? null
1835
1959
  ),
1836
1960
  replyContext: resolvedReplyContext,
1837
- specialistHome: resolvedSpecialistHome
1961
+ specialistHome: resolvedSpecialistHome,
1962
+ ...acceptanceHandoff ? { acceptanceHandoff } : {}
1838
1963
  };
1839
1964
  const nextHappyOrg = currentHappyOrg;
1840
1965
  nextHappyOrg.taskContext = { ...queuedTurn.context };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-Cgor8CE7.cjs');
4
- var persistence = require('./api-BoeZDGwx.cjs');
3
+ var index = require('./index-Dh0qGrEd.cjs');
4
+ var persistence = require('./api-C_Tnx4UG.cjs');
5
5
  var node_crypto = require('node:crypto');
6
6
  var path = require('node:path');
7
7
  var crypto = require('crypto');
@@ -764,6 +764,12 @@ const SCOPE_ALIASES = ["scope"];
764
764
  const READ_ACK_ALIASES = ["read_ack", "readAck"];
765
765
  const STATUS_ALIASES = ["status"];
766
766
  const NOTE_ALIASES = ["note"];
767
+ const REPLY_TO_ALIASES = ["reply_to", "replyTo"];
768
+ const POSITION_STATUS_ALIASES = ["position_status", "positionStatus"];
769
+ const LATEST_USER_VISIBLE_RESULT_ALIASES = ["latest_user_visible_result", "latestUserVisibleResult"];
770
+ const BLOCKER_SUMMARY_ALIASES = ["blocker_summary", "blockerSummary"];
771
+ const ACCEPTANCE_STATE_ALIASES = ["acceptance_state", "acceptanceState"];
772
+ const CEO_WRITE_NEXT_STEP_ALIASES = ["ceo_write_next_step", "ceoWriteNextStep"];
767
773
  function normalizeOptionalText(value) {
768
774
  if (typeof value !== "string") {
769
775
  return null;
@@ -795,12 +801,23 @@ function cloneHappyOrgReplyContext(replyContext) {
795
801
  function cloneHappyOrgSpecialistHomeIdentity(specialistHome) {
796
802
  return specialistHome ? { ...specialistHome } : null;
797
803
  }
804
+ function cloneHappyOrgAcceptanceHandoff(handoff) {
805
+ if (handoff === void 0) {
806
+ return void 0;
807
+ }
808
+ return handoff ? { ...handoff } : null;
809
+ }
798
810
  function cloneHappyOrgTurnReport(report) {
799
- return report ? {
811
+ if (!report) {
812
+ return void 0;
813
+ }
814
+ const acceptanceHandoff = cloneHappyOrgAcceptanceHandoff(report.acceptanceHandoff);
815
+ return {
800
816
  ...report,
801
817
  replyContext: cloneHappyOrgReplyContext(report.replyContext),
802
- specialistHome: cloneHappyOrgSpecialistHomeIdentity(report.specialistHome)
803
- } : void 0;
818
+ specialistHome: cloneHappyOrgSpecialistHomeIdentity(report.specialistHome),
819
+ ...acceptanceHandoff !== void 0 ? { acceptanceHandoff } : {}
820
+ };
804
821
  }
805
822
  function cloneHappyOrgMetadata(happyOrg) {
806
823
  return {
@@ -974,6 +991,48 @@ function normalizeReplyMode(value) {
974
991
  }
975
992
  return null;
976
993
  }
994
+ function normalizeAcceptanceState(value) {
995
+ const normalized = normalizeSingleLineText(value)?.toLowerCase();
996
+ if (normalized === "not_ready" || normalized === "awaiting_acceptance" || normalized === "closed") {
997
+ return normalized;
998
+ }
999
+ return null;
1000
+ }
1001
+ function normalizeBlockerSummary(value) {
1002
+ const normalized = normalizeSingleLineText(value);
1003
+ if (!normalized) {
1004
+ return null;
1005
+ }
1006
+ const lowered = normalized.toLowerCase();
1007
+ if (lowered === "none" || lowered === "null" || lowered === "no blocker") {
1008
+ return null;
1009
+ }
1010
+ return normalized;
1011
+ }
1012
+ function normalizeHappyOrgAcceptanceHandoffRecord(record) {
1013
+ const dispatchId = normalizeSingleLineText(getFirstDefined(record, DISPATCH_ID_ALIASES));
1014
+ const replyTo = normalizeSingleLineText(getFirstDefined(record, REPLY_TO_ALIASES));
1015
+ const taskId = normalizeSingleLineText(getFirstDefined(record, TASK_ID_ALIASES));
1016
+ const positionStatus = normalizeSingleLineText(getFirstDefined(record, POSITION_STATUS_ALIASES));
1017
+ const latestUserVisibleResult = normalizeSingleLineText(getFirstDefined(record, LATEST_USER_VISIBLE_RESULT_ALIASES));
1018
+ const acceptanceState = normalizeAcceptanceState(getFirstDefined(record, ACCEPTANCE_STATE_ALIASES));
1019
+ const ceoWriteNextStep = normalizeSingleLineText(getFirstDefined(record, CEO_WRITE_NEXT_STEP_ALIASES));
1020
+ if (!dispatchId || !replyTo || !taskId || !positionStatus || !latestUserVisibleResult || !acceptanceState || !ceoWriteNextStep) {
1021
+ return null;
1022
+ }
1023
+ return {
1024
+ dispatchId,
1025
+ replyTo,
1026
+ taskId,
1027
+ positionId: normalizeSingleLineText(getFirstDefined(record, POSITION_ID_ALIASES)),
1028
+ responsibilityId: normalizeSingleLineText(getFirstDefined(record, RESPONSIBILITY_ID_ALIASES)),
1029
+ positionStatus,
1030
+ latestUserVisibleResult,
1031
+ blockerSummary: normalizeBlockerSummary(getFirstDefined(record, BLOCKER_SUMMARY_ALIASES)),
1032
+ acceptanceState,
1033
+ ceoWriteNextStep
1034
+ };
1035
+ }
977
1036
  function normalizeHappyOrgDispatchAckRecord(record) {
978
1037
  const ackVersion = normalizeSingleLineText(getFirstDefined(record, ACK_VERSION_ALIASES));
979
1038
  const dispatchId = normalizeSingleLineText(getFirstDefined(record, DISPATCH_ID_ALIASES));
@@ -1042,6 +1101,20 @@ function isHappyOrgDispatchAckCandidateRecord(record) {
1042
1101
  ...NOTE_ALIASES
1043
1102
  ].some((key) => Object.prototype.hasOwnProperty.call(record, key));
1044
1103
  }
1104
+ function isHappyOrgAcceptanceHandoffCandidateRecord(record) {
1105
+ return [
1106
+ ...DISPATCH_ID_ALIASES,
1107
+ ...REPLY_TO_ALIASES,
1108
+ ...TASK_ID_ALIASES,
1109
+ ...POSITION_ID_ALIASES,
1110
+ ...RESPONSIBILITY_ID_ALIASES,
1111
+ ...POSITION_STATUS_ALIASES,
1112
+ ...LATEST_USER_VISIBLE_RESULT_ALIASES,
1113
+ ...BLOCKER_SUMMARY_ALIASES,
1114
+ ...ACCEPTANCE_STATE_ALIASES,
1115
+ ...CEO_WRITE_NEXT_STEP_ALIASES
1116
+ ].some((key) => Object.prototype.hasOwnProperty.call(record, key));
1117
+ }
1045
1118
  function extractKeyValueBlocks(text) {
1046
1119
  const blocks = [];
1047
1120
  let currentBlock = null;
@@ -1108,6 +1181,51 @@ function resolveHappyOrgDispatchAckEnvelopeCandidate(text) {
1108
1181
  outcome: "absent"
1109
1182
  };
1110
1183
  }
1184
+ function resolveHappyOrgAcceptanceHandoffCandidate(text) {
1185
+ const trimmed = stripCodeFence(text).trim();
1186
+ if (!trimmed) {
1187
+ return { outcome: "absent" };
1188
+ }
1189
+ let sawCandidate = false;
1190
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
1191
+ try {
1192
+ const parsed = JSON.parse(trimmed);
1193
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1194
+ const record = parsed;
1195
+ if (isHappyOrgAcceptanceHandoffCandidateRecord(record)) {
1196
+ const handoff = normalizeHappyOrgAcceptanceHandoffRecord(record);
1197
+ if (handoff) {
1198
+ return {
1199
+ outcome: "valid",
1200
+ handoff
1201
+ };
1202
+ }
1203
+ sawCandidate = true;
1204
+ }
1205
+ }
1206
+ } catch {
1207
+ }
1208
+ }
1209
+ for (const block of extractKeyValueBlocks(text)) {
1210
+ if (!isHappyOrgAcceptanceHandoffCandidateRecord(block)) {
1211
+ continue;
1212
+ }
1213
+ const handoff = normalizeHappyOrgAcceptanceHandoffRecord(block);
1214
+ if (handoff) {
1215
+ return {
1216
+ outcome: "valid",
1217
+ handoff
1218
+ };
1219
+ }
1220
+ sawCandidate = true;
1221
+ }
1222
+ return sawCandidate ? {
1223
+ outcome: "invalid",
1224
+ diagnostic: "Happy Org acceptance handoff ignored: malformed mini-pack. Required fields are dispatch_id, reply_to, task_id, position_status, latest_user_visible_result, acceptance_state, and ceo_write_next_step."
1225
+ } : {
1226
+ outcome: "absent"
1227
+ };
1228
+ }
1111
1229
  function recordHappyOrgDispatchAck(metadata, ack, acknowledgedAt) {
1112
1230
  const nextHappyOrg = normalizeHappyOrgMetadata(metadata);
1113
1231
  nextHappyOrg.dispatchAcks = nextHappyOrg.dispatchAcks ?? {};
@@ -1629,7 +1747,11 @@ function buildHappyOrgTurnPrompt(prompt, turn) {
1629
1747
  `task_ack=${turn.context.taskId}`,
1630
1748
  "read_ack=yes",
1631
1749
  "status=accepted | standby | blocked",
1632
- "note=<short note>"
1750
+ "note=<short note>",
1751
+ "Keep dispatch_id / task_id / position_id / responsibility_id stable across the visible ack, visible reply, and final turn report.",
1752
+ "When turnStatus=task_complete and reply context exists, include a short source reply for the original requester at reply_to before the final JSON block.",
1753
+ "That source reply / acceptance handoff mini-pack should explicitly mention position_status, latest_user_visible_result, blocker_summary, and acceptance_state=awaiting_acceptance.",
1754
+ "Use acceptance_state=closed only after CEO or the original requester actually confirms close; do not self-mark closed."
1633
1755
  ].filter(Boolean) : [];
1634
1756
  const specialistHomeLines = turn.specialistHome ? [
1635
1757
  "",
@@ -1821,6 +1943,8 @@ function finalizeHappyOrgTurn(opts) {
1821
1943
  const currentHappyOrg = normalizeHappyOrgMetadata(metadata);
1822
1944
  const resolvedReplyContext = cloneHappyOrgReplyContext(queuedTurn.replyContext) ?? cloneHappyOrgReplyContext(currentHappyOrg.replyContext);
1823
1945
  const resolvedSpecialistHome = cloneHappyOrgSpecialistHomeIdentity(queuedTurn.specialistHome) ?? cloneHappyOrgSpecialistHomeIdentity(currentHappyOrg.specialistHome);
1946
+ const acceptanceHandoffCandidate = resolveHappyOrgAcceptanceHandoffCandidate(cleanedText);
1947
+ const acceptanceHandoff = acceptanceHandoffCandidate.outcome === "valid" && acceptanceHandoffCandidate.handoff.taskId === queuedTurn.context.taskId && (!resolvedReplyContext || acceptanceHandoffCandidate.handoff.dispatchId === resolvedReplyContext.dispatchId) ? acceptanceHandoffCandidate.handoff : null;
1824
1948
  const report = {
1825
1949
  ...queuedTurn.context,
1826
1950
  turnStatus: reportTurnStatus,
@@ -1836,7 +1960,8 @@ function finalizeHappyOrgTurn(opts) {
1836
1960
  normalizedDraft.targetArtifact ?? null
1837
1961
  ),
1838
1962
  replyContext: resolvedReplyContext,
1839
- specialistHome: resolvedSpecialistHome
1963
+ specialistHome: resolvedSpecialistHome,
1964
+ ...acceptanceHandoff ? { acceptanceHandoff } : {}
1840
1965
  };
1841
1966
  const nextHappyOrg = currentHappyOrg;
1842
1967
  nextHappyOrg.taskContext = { ...queuedTurn.context };
@@ -1,8 +1,8 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { l as logger, h as backoff, j as delay, k as AsyncLock, c as configuration, s as startOfflineReconnection, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-wcqkneTg.mjs';
2
+ import { l as logger, j as backoff, k as delay, d as AssistantMessageStream, m as AsyncLock, c as configuration, s as startOfflineReconnection, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-CwNEbJBM.mjs';
3
3
  import 'cross-spawn';
4
4
  import '@agentclientprotocol/sdk';
5
- import { n as getProjectPath, F as Future, o as claudeLocal, E as ExitCodeError, q as trimIdent, u as createClaudeBackend, f as formatDisplayMessage, t as truncateDisplayMessage, w as claudeCheckSession, x as projectPath, y as mapToClaudeMode, P as PushableAsyncIterable, z as query, A as AbortError, e as stopCaffeinate, p as publishSessionRegistration, B as getEnvironmentInfo, a as createSessionMetadata, C as startCaffeinate, b as closeProviderSession } from './index-B9mt95QV.mjs';
5
+ import { n as getProjectPath, F as Future, o as claudeLocal, E as ExitCodeError, q as trimIdent, u as createClaudeBackend, f as formatDisplayMessage, t as truncateDisplayMessage, w as claudeCheckSession, x as projectPath, y as mapToClaudeMode, P as PushableAsyncIterable, z as query, A as AbortError, e as stopCaffeinate, p as publishSessionRegistration, B as getEnvironmentInfo, a as createSessionMetadata, C as startCaffeinate, b as closeProviderSession } from './index-D5m2Duxd.mjs';
6
6
  import 'ps-list';
7
7
  import 'fs';
8
8
  import 'path';
@@ -23,9 +23,9 @@ import 'tweetnacl';
23
23
  import 'open';
24
24
  import React, { useState, useRef, useEffect, useCallback } from 'react';
25
25
  import { useStdout, useInput, Box, Text, render } from 'ink';
26
- import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-DrSgStLw.mjs';
26
+ import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-CmeZ92yO.mjs';
27
27
  import { R as RawJSONLinesSchema } from './types-CiliQpqS.mjs';
28
- import { B as BasePermissionHandler, d as MessageBuffer, C as ConversationHistory$1, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurnWithBusinessAck, j as buildTurnResultPushNotification, k as buildReadyPushNotification, l as launchRuntimeHandleWithFactoryResult, o as renderTerminalOutputPreview, q as forwardAgentMessageToProviderSession, n as buildPermissionPushNotification, s as syncControlledByUserState, r as resolveHappyOrgQueuedTurn, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, h as hashObject, c as registerKillSessionHandler } from './registerKillSessionHandler-Buc97BEh.mjs';
28
+ import { B as BasePermissionHandler, d as MessageBuffer, C as ConversationHistory$1, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurnWithBusinessAck, j as buildTurnResultPushNotification, k as buildReadyPushNotification, l as launchRuntimeHandleWithFactoryResult, o as renderTerminalOutputPreview, q as forwardAgentMessageToProviderSession, n as buildPermissionPushNotification, s as syncControlledByUserState, r as resolveHappyOrgQueuedTurn, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, h as hashObject, c as registerKillSessionHandler } from './registerKillSessionHandler-6JloVYkb.mjs';
29
29
  import 'socket.io-client';
30
30
  import 'expo-server-sdk';
31
31
  import { isDeepStrictEqual } from 'node:util';
@@ -998,6 +998,7 @@ async function claudeAcpRemoteLauncher(session) {
998
998
  let currentModeHash = null;
999
999
  let pending = null;
1000
1000
  let accumulatedResponse = "";
1001
+ let currentAssistantStreamStartLength = 0;
1001
1002
  let accumulatedThinking = "";
1002
1003
  let isResponseInProgress = false;
1003
1004
  let taskStartedSent = false;
@@ -1006,6 +1007,8 @@ async function claudeAcpRemoteLauncher(session) {
1006
1007
  let shouldInjectHistoryOnNextSession = false;
1007
1008
  let unexpectedRuntimeStopRecovery = null;
1008
1009
  let readyAlreadySent = false;
1010
+ let currentHappyOrgTurn = null;
1011
+ const assistantMessageStream = new AssistantMessageStream();
1009
1012
  const permissionHandler = new ClaudeAcpPermissionHandler(session.client);
1010
1013
  const selectionHandler = new ProviderSelectionHandler(session.client, "Claude");
1011
1014
  const conversationHistory = new ConversationHistory$1({
@@ -1057,13 +1060,35 @@ async function claudeAcpRemoteLauncher(session) {
1057
1060
  };
1058
1061
  const resetTurnState = () => {
1059
1062
  accumulatedResponse = "";
1063
+ currentAssistantStreamStartLength = 0;
1060
1064
  accumulatedThinking = "";
1061
1065
  isResponseInProgress = false;
1062
1066
  taskStartedSent = false;
1063
1067
  currentAssistantMessageId = null;
1064
1068
  currentThinkingMessageId = null;
1069
+ currentHappyOrgTurn = null;
1070
+ assistantMessageStream.reset();
1065
1071
  session.onThinkingChange(false);
1066
1072
  };
1073
+ const emitAssistantMessageDelta = (text) => {
1074
+ if (currentHappyOrgTurn) {
1075
+ return false;
1076
+ }
1077
+ if (!text.trim()) {
1078
+ return false;
1079
+ }
1080
+ if (!assistantMessageStream.hasActive()) {
1081
+ currentAssistantStreamStartLength = accumulatedResponse.length - text.length;
1082
+ }
1083
+ const stream = assistantMessageStream.delta();
1084
+ session.client.sendAgentMessage("claude", {
1085
+ type: "message",
1086
+ message: text,
1087
+ id: stream.messageId,
1088
+ ...stream
1089
+ });
1090
+ return true;
1091
+ };
1067
1092
  const emitPendingThinkingMessage = () => {
1068
1093
  const thinking = accumulatedThinking.trim();
1069
1094
  if (!thinking) {
@@ -1081,15 +1106,19 @@ async function claudeAcpRemoteLauncher(session) {
1081
1106
  if (!finalMessage) {
1082
1107
  accumulatedResponse = "";
1083
1108
  isResponseInProgress = false;
1109
+ assistantMessageStream.reset();
1084
1110
  return;
1085
1111
  }
1086
1112
  if (currentAssistantMessageId) {
1087
1113
  messageBuffer.updateMessage(currentAssistantMessageId, finalMessage, { mode: "replace" });
1088
1114
  }
1089
1115
  conversationHistory.addAssistantMessage(finalMessage);
1116
+ const hadActiveStream = assistantMessageStream.hasActive();
1117
+ const stream = hadActiveStream ? assistantMessageStream.commit() : null;
1090
1118
  session.client.sendAgentMessage("claude", {
1091
1119
  type: "message",
1092
- message: finalMessage
1120
+ message: hadActiveStream ? finalMessage.slice(currentAssistantStreamStartLength) : finalMessage,
1121
+ ...stream ? { id: stream.messageId, ...stream } : {}
1093
1122
  });
1094
1123
  session.client.sendClaudeSessionMessage({
1095
1124
  type: "assistant",
@@ -1107,8 +1136,29 @@ async function claudeAcpRemoteLauncher(session) {
1107
1136
  }
1108
1137
  });
1109
1138
  accumulatedResponse = "";
1139
+ currentAssistantStreamStartLength = 0;
1110
1140
  isResponseInProgress = false;
1111
1141
  };
1142
+ const commitActiveAssistantMessageStream = () => {
1143
+ if (!assistantMessageStream.hasActive()) {
1144
+ return false;
1145
+ }
1146
+ const finalMessage = accumulatedResponse.trim();
1147
+ if (!finalMessage) {
1148
+ assistantMessageStream.reset();
1149
+ currentAssistantStreamStartLength = accumulatedResponse.length;
1150
+ return false;
1151
+ }
1152
+ const stream = assistantMessageStream.commit();
1153
+ session.client.sendAgentMessage("claude", {
1154
+ type: "message",
1155
+ message: finalMessage.slice(currentAssistantStreamStartLength),
1156
+ id: stream.messageId,
1157
+ ...stream
1158
+ });
1159
+ currentAssistantStreamStartLength = accumulatedResponse.length;
1160
+ return true;
1161
+ };
1112
1162
  const disposeRuntimeHandle = async () => {
1113
1163
  if (!runtimeHandle) {
1114
1164
  return;
@@ -1186,6 +1236,7 @@ async function claudeAcpRemoteLauncher(session) {
1186
1236
  }
1187
1237
  }
1188
1238
  accumulatedResponse += text;
1239
+ emitAssistantMessageDelta(text);
1189
1240
  return;
1190
1241
  }
1191
1242
  case "status": {
@@ -1218,6 +1269,7 @@ async function claudeAcpRemoteLauncher(session) {
1218
1269
  return;
1219
1270
  }
1220
1271
  case "tool-call": {
1272
+ commitActiveAssistantMessageStream();
1221
1273
  emitPendingThinkingMessage();
1222
1274
  const toolArgs = truncateDisplayMessage(msg.args, 100);
1223
1275
  messageBuffer.addMessage(
@@ -1328,6 +1380,7 @@ ${systemPrompt}` : systemPrompt,
1328
1380
  const abortActiveTurn = async () => {
1329
1381
  const activeController = rotateAbortController();
1330
1382
  activeController.abort();
1383
+ assistantMessageStream.reset();
1331
1384
  session.onThinkingChange(false);
1332
1385
  if (runtimeHandle) {
1333
1386
  await runtimeHandle.cancel().catch((error) => {
@@ -1441,6 +1494,7 @@ ${systemPrompt}` : systemPrompt,
1441
1494
  let turnStatus = "task_complete";
1442
1495
  try {
1443
1496
  turnInFlight = true;
1497
+ currentHappyOrgTurn = message.mode.happyOrg ?? null;
1444
1498
  const activeRuntimeHandle = runtimeHandle ?? await createRuntimeHandle(message.mode);
1445
1499
  let promptToSend = message.message;
1446
1500
  if (shouldInjectHistoryOnNextSession && conversationHistory.hasHistory()) {