@agimon-ai/doompi-user-feedback 0.0.1-alpha.61 → 0.0.1-alpha.64

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 (138) hide show
  1. package/package.json +21 -16
  2. package/dist/_virtual/_rolldown/runtime.cjs +0 -1
  3. package/dist/api-contracts.cjs +0 -1
  4. package/dist/api-contracts.d.cts +0 -2
  5. package/dist/api-contracts.d.mts +0 -2
  6. package/dist/api-contracts.mjs +0 -1
  7. package/dist/constants/package.cjs +0 -2
  8. package/dist/constants/package.cjs.map +0 -1
  9. package/dist/constants/package.mjs +0 -2
  10. package/dist/constants/package.mjs.map +0 -1
  11. package/dist/constants/questionnaire.cjs +0 -2
  12. package/dist/constants/questionnaire.cjs.map +0 -1
  13. package/dist/constants/questionnaire.mjs +0 -2
  14. package/dist/constants/questionnaire.mjs.map +0 -1
  15. package/dist/constants/tool.cjs +0 -2
  16. package/dist/constants/tool.cjs.map +0 -1
  17. package/dist/constants/tool.mjs +0 -2
  18. package/dist/constants/tool.mjs.map +0 -1
  19. package/dist/extensions/pi.cjs +0 -2
  20. package/dist/extensions/pi.cjs.map +0 -1
  21. package/dist/extensions/pi.d.cts +0 -5
  22. package/dist/extensions/pi.d.cts.map +0 -1
  23. package/dist/extensions/pi.d.mts +0 -5
  24. package/dist/extensions/pi.d.mts.map +0 -1
  25. package/dist/extensions/pi.mjs +0 -2
  26. package/dist/extensions/pi.mjs.map +0 -1
  27. package/dist/extensions/server.cjs +0 -2
  28. package/dist/extensions/server.cjs.map +0 -1
  29. package/dist/extensions/server.d.cts +0 -5
  30. package/dist/extensions/server.d.cts.map +0 -1
  31. package/dist/extensions/server.d.mts +0 -5
  32. package/dist/extensions/server.d.mts.map +0 -1
  33. package/dist/extensions/server.mjs +0 -2
  34. package/dist/extensions/server.mjs.map +0 -1
  35. package/dist/index.cjs +0 -0
  36. package/dist/index.d.cts +0 -3
  37. package/dist/index.d.mts +0 -3
  38. package/dist/index.mjs +0 -1
  39. package/dist/schemas/apiContracts.cjs +0 -2
  40. package/dist/schemas/apiContracts.cjs.map +0 -1
  41. package/dist/schemas/apiContracts.d.cts +0 -53
  42. package/dist/schemas/apiContracts.d.cts.map +0 -1
  43. package/dist/schemas/apiContracts.d.mts +0 -53
  44. package/dist/schemas/apiContracts.d.mts.map +0 -1
  45. package/dist/schemas/apiContracts.mjs +0 -2
  46. package/dist/schemas/apiContracts.mjs.map +0 -1
  47. package/dist/schemas/questionnaire.cjs +0 -2
  48. package/dist/schemas/questionnaire.cjs.map +0 -1
  49. package/dist/schemas/questionnaire.d.cts +0 -17
  50. package/dist/schemas/questionnaire.d.cts.map +0 -1
  51. package/dist/schemas/questionnaire.d.mts +0 -17
  52. package/dist/schemas/questionnaire.d.mts.map +0 -1
  53. package/dist/schemas/questionnaire.mjs +0 -2
  54. package/dist/schemas/questionnaire.mjs.map +0 -1
  55. package/dist/services/answerEnvelope/index.cjs +0 -2
  56. package/dist/services/answerEnvelope/index.cjs.map +0 -1
  57. package/dist/services/answerEnvelope/index.mjs +0 -2
  58. package/dist/services/answerEnvelope/index.mjs.map +0 -1
  59. package/dist/services/askUserToolGate/index.cjs +0 -2
  60. package/dist/services/askUserToolGate/index.cjs.map +0 -1
  61. package/dist/services/askUserToolGate/index.mjs +0 -2
  62. package/dist/services/askUserToolGate/index.mjs.map +0 -1
  63. package/dist/services/autonomousVoiceMode/index.cjs +0 -2
  64. package/dist/services/autonomousVoiceMode/index.cjs.map +0 -1
  65. package/dist/services/autonomousVoiceMode/index.mjs +0 -2
  66. package/dist/services/autonomousVoiceMode/index.mjs.map +0 -1
  67. package/dist/services/config/index.cjs +0 -2
  68. package/dist/services/config/index.cjs.map +0 -1
  69. package/dist/services/config/index.mjs +0 -2
  70. package/dist/services/config/index.mjs.map +0 -1
  71. package/dist/services/questionnaireCoordinator/index.cjs +0 -2
  72. package/dist/services/questionnaireCoordinator/index.cjs.map +0 -1
  73. package/dist/services/questionnaireCoordinator/index.mjs +0 -2
  74. package/dist/services/questionnaireCoordinator/index.mjs.map +0 -1
  75. package/dist/services/questionnaireService/index.cjs +0 -2
  76. package/dist/services/questionnaireService/index.cjs.map +0 -1
  77. package/dist/services/questionnaireService/index.mjs +0 -2
  78. package/dist/services/questionnaireService/index.mjs.map +0 -1
  79. package/dist/services/responseService/index.cjs +0 -2
  80. package/dist/services/responseService/index.cjs.map +0 -1
  81. package/dist/services/responseService/index.mjs +0 -2
  82. package/dist/services/responseService/index.mjs.map +0 -1
  83. package/dist/services/rpcQuestionnaire/index.cjs +0 -2
  84. package/dist/services/rpcQuestionnaire/index.cjs.map +0 -1
  85. package/dist/services/rpcQuestionnaire/index.mjs +0 -2
  86. package/dist/services/rpcQuestionnaire/index.mjs.map +0 -1
  87. package/dist/services/validationService/index.cjs +0 -2
  88. package/dist/services/validationService/index.cjs.map +0 -1
  89. package/dist/services/validationService/index.mjs +0 -2
  90. package/dist/services/validationService/index.mjs.map +0 -1
  91. package/dist/services/voiceQuestionHandoff/index.cjs +0 -5
  92. package/dist/services/voiceQuestionHandoff/index.cjs.map +0 -1
  93. package/dist/services/voiceQuestionHandoff/index.mjs +0 -5
  94. package/dist/services/voiceQuestionHandoff/index.mjs.map +0 -1
  95. package/dist/services/voiceQuestionNarration/index.cjs +0 -2
  96. package/dist/services/voiceQuestionNarration/index.cjs.map +0 -1
  97. package/dist/services/voiceQuestionNarration/index.mjs +0 -2
  98. package/dist/services/voiceQuestionNarration/index.mjs.map +0 -1
  99. package/dist/tools/askUserHeadless.cjs +0 -2
  100. package/dist/tools/askUserHeadless.cjs.map +0 -1
  101. package/dist/tools/askUserHeadless.mjs +0 -2
  102. package/dist/tools/askUserHeadless.mjs.map +0 -1
  103. package/dist/tools/askUserQuestion.cjs +0 -14
  104. package/dist/tools/askUserQuestion.cjs.map +0 -1
  105. package/dist/tools/askUserQuestion.mjs +0 -14
  106. package/dist/tools/askUserQuestion.mjs.map +0 -1
  107. package/dist/tui/askUserToolRender.cjs +0 -3
  108. package/dist/tui/askUserToolRender.cjs.map +0 -1
  109. package/dist/tui/askUserToolRender.mjs +0 -3
  110. package/dist/tui/askUserToolRender.mjs.map +0 -1
  111. package/dist/tui/externalEditor.cjs +0 -2
  112. package/dist/tui/externalEditor.cjs.map +0 -1
  113. package/dist/tui/externalEditor.mjs +0 -2
  114. package/dist/tui/externalEditor.mjs.map +0 -1
  115. package/dist/tui/questionnaireComponent.cjs +0 -2
  116. package/dist/tui/questionnaireComponent.cjs.map +0 -1
  117. package/dist/tui/questionnaireComponent.mjs +0 -2
  118. package/dist/tui/questionnaireComponent.mjs.map +0 -1
  119. package/dist/tui/runQuestionnaire.cjs +0 -2
  120. package/dist/tui/runQuestionnaire.cjs.map +0 -1
  121. package/dist/tui/runQuestionnaire.mjs +0 -2
  122. package/dist/tui/runQuestionnaire.mjs.map +0 -1
  123. package/dist/types/askUserWire.cjs +0 -2
  124. package/dist/types/askUserWire.cjs.map +0 -1
  125. package/dist/types/askUserWire.mjs +0 -2
  126. package/dist/types/askUserWire.mjs.map +0 -1
  127. package/dist/types/questionnaire.d.cts +0 -32
  128. package/dist/types/questionnaire.d.cts.map +0 -1
  129. package/dist/types/questionnaire.d.mts +0 -32
  130. package/dist/types/questionnaire.d.mts.map +0 -1
  131. package/src/extensions/web.ts +0 -33
  132. package/src/types/askUserWire.ts +0 -45
  133. package/src/types/questionnaire.ts +0 -44
  134. package/src/web/components/AskUserQuestionToolMessage.tsx +0 -88
  135. package/src/web/components/QuestionnairePrompt.tsx +0 -371
  136. package/src/web/lib/askUserText.ts +0 -65
  137. package/src/web/lib/questionnaireDraft.ts +0 -149
  138. package/src/web/tsconfig.json +0 -23
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-user-feedback",
3
- "version": "0.0.1-alpha.61",
3
+ "version": "0.0.1-alpha.64",
4
4
  "description": "Structured user questions with interactive and autonomous Voice handoff for Pi agents.",
5
5
  "keywords": [
6
6
  "ai",
@@ -27,18 +27,14 @@
27
27
  },
28
28
  "files": [
29
29
  "dist",
30
- "src/web",
31
- "src/extensions/web.ts",
32
- "src/types/askUserWire.ts",
33
- "src/types/questionnaire.ts",
34
30
  "README.md",
35
31
  "LICENSE",
36
- "package.json",
37
- "!src/web/**/*.stories.tsx"
32
+ "package.json"
38
33
  ],
39
34
  "type": "module",
40
35
  "main": "./dist/index.cjs",
41
- "types": "./dist/index.d.mts",
36
+ "module": "./dist/index.mjs",
37
+ "types": "./dist/index.d.cts",
42
38
  "jsnext:main": "./dist/index.mjs",
43
39
  "exports": {
44
40
  ".": {
@@ -46,6 +42,11 @@
46
42
  "import": "./dist/index.mjs",
47
43
  "require": "./dist/index.cjs"
48
44
  },
45
+ "./api-contracts": {
46
+ "types": "./dist/api-contracts.d.mts",
47
+ "import": "./dist/api-contracts.mjs",
48
+ "require": "./dist/api-contracts.cjs"
49
+ },
49
50
  "./extensions/pi": {
50
51
  "types": "./dist/extensions/pi.d.mts",
51
52
  "import": "./dist/extensions/pi.mjs",
@@ -56,21 +57,25 @@
56
57
  "import": "./dist/extensions/server.mjs",
57
58
  "require": "./dist/extensions/server.cjs"
58
59
  },
60
+ "./extensions/web": {
61
+ "import": "./dist/extensions/web.mjs"
62
+ },
59
63
  "./package.json": "./package.json"
60
64
  },
61
65
  "publishConfig": {
62
66
  "access": "public"
63
67
  },
64
68
  "dependencies": {
65
- "@agimon-ai/doompi-core": "0.0.1-alpha.72",
66
- "@agimon-ai/doompi-minor-mode": "0.0.1-alpha.72",
67
- "@agimon-ai/doompi-ui": "0.0.1-alpha.72",
68
- "@agimon-ai/doompi-web-components": "0.0.1-alpha.30",
69
+ "@agimon-ai/doompi-core": "0.0.1-alpha.75",
70
+ "@agimon-ai/doompi-minor-mode": "0.0.1-alpha.75",
71
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.75",
72
+ "@agimon-ai/doompi-web-components": "0.0.1-alpha.33",
69
73
  "@deepseek-ai/cordis": "4.0.2",
70
74
  "typebox": "1.3.30"
71
75
  },
72
76
  "devDependencies": {
73
- "@agimon-ai/doompi-voice": "0.0.1-alpha.73",
77
+ "@agimon-ai/doompi-build": "0.0.1-alpha.4",
78
+ "@agimon-ai/doompi-voice": "0.0.1-alpha.76",
74
79
  "@earendil-works/pi-coding-agent": "0.85.1",
75
80
  "@earendil-works/pi-tui": "0.85.1",
76
81
  "@tanstack/react-store": "0.11.1",
@@ -100,7 +105,7 @@
100
105
  "node": ">=22.19.0"
101
106
  },
102
107
  "doompiServer": {
103
- "entry": "./src/extensions/server.ts",
108
+ "entry": "./generated/server.ts",
104
109
  "dist": "./dist/extensions/server.mjs",
105
110
  "scopes": [
106
111
  "session"
@@ -113,7 +118,7 @@
113
118
  "doompiWeb": {
114
119
  "pluginId": "ask-user",
115
120
  "channels": [],
116
- "client": "./src/extensions/web.ts",
121
+ "client": "./dist/extensions/web.mjs",
117
122
  "scopes": [
118
123
  "session"
119
124
  ]
@@ -126,7 +131,7 @@
126
131
  "scripts": {
127
132
  "build": "tsdown",
128
133
  "test": "vitest --run",
129
- "typecheck": "tsc --noEmit && tsc --noEmit -p src/web/tsconfig.json",
134
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.web.json",
130
135
  "lint": "oxlint . && oxfmt . --check",
131
136
  "fixcode": "oxlint . --fix && oxfmt ."
132
137
  }
@@ -1 +0,0 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
@@ -1 +0,0 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./schemas/apiContracts.cjs");exports.apiContracts=e.apiContracts,exports.default=e.apiContracts;
@@ -1,2 +0,0 @@
1
- import { apiContracts } from "./schemas/apiContracts.cjs";
2
- export { apiContracts, apiContracts as default };
@@ -1,2 +0,0 @@
1
- import { apiContracts } from "./schemas/apiContracts.mjs";
2
- export { apiContracts, apiContracts as default };
@@ -1 +0,0 @@
1
- import{apiContracts as e}from"./schemas/apiContracts.mjs";export{e as apiContracts,e as default};
@@ -1,2 +0,0 @@
1
- exports.PACKAGE_SOURCE=`@agimon-ai/doompi-user-feedback`;
2
- //# sourceMappingURL=package.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"package.cjs","names":[],"sources":["../../src/constants/package.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-user-feedback';\n"],"mappings":""}
@@ -1,2 +0,0 @@
1
- const e=`@agimon-ai/doompi-user-feedback`;export{e as PACKAGE_SOURCE};
2
- //# sourceMappingURL=package.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"package.mjs","names":[],"sources":["../../src/constants/package.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-user-feedback';\n"],"mappings":"AAAA,MAAa,EAAiB"}
@@ -1,2 +0,0 @@
1
- const e=[`Other`,`Type something.`,`Next`];exports.RESERVED_LABELS=e;
2
- //# sourceMappingURL=questionnaire.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionnaire.cjs","names":[],"sources":["../../src/constants/questionnaire.ts"],"sourcesContent":["export const MAX_QUESTIONS = 4;\nexport const MIN_OPTIONS = 2;\nexport const MAX_OPTIONS = 4;\nexport const MAX_HEADER_LENGTH = 16;\nexport const MAX_LABEL_LENGTH = 60;\n\nexport const RESERVED_LABELS = ['Other', 'Type something.', 'Next'] as const;\n"],"mappings":"AAMA,MAAa,EAAkB,CAAC,QAAS,kBAAmB,MAAM"}
@@ -1,2 +0,0 @@
1
- const e=[`Other`,`Type something.`,`Next`];export{e as RESERVED_LABELS};
2
- //# sourceMappingURL=questionnaire.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionnaire.mjs","names":[],"sources":["../../src/constants/questionnaire.ts"],"sourcesContent":["export const MAX_QUESTIONS = 4;\nexport const MIN_OPTIONS = 2;\nexport const MAX_OPTIONS = 4;\nexport const MAX_HEADER_LENGTH = 16;\nexport const MAX_LABEL_LENGTH = 60;\n\nexport const RESERVED_LABELS = ['Other', 'Type something.', 'Next'] as const;\n"],"mappings":"AAMA,MAAa,EAAkB,CAAC,QAAS,kBAAmB,MAAM"}
@@ -1,2 +0,0 @@
1
- const e=[`Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions, you can ask up to 4 questions per invocation.`,`Each question MUST have 2-4 options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer via the automatically appended "Type something." row on every question, or press Esc to abandon the questionnaire. Do NOT author "Other" or "Type something." labels yourself, reserved labels are rejected at runtime.`,`Set multiSelect: true when multiple answers are valid. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs), single-select only. If you recommend a specific option, make that the first option and append "(Recommended)" to its label.`,`Do not stack multiple ask_user_question calls back-to-back, group all clarifying questions into one invocation.`];exports.ASK_USER_QUESTION_TOOL_NAME=`ask_user_question`,exports.DEFAULT_PROMPT_GUIDELINES=e,exports.DEFAULT_PROMPT_SNIPPET=`Ask the user up to 4 structured questions (2-4 options each) when requirements are ambiguous`,exports.ERROR_NO_CUSTOM_UI=`Error: this client cannot render the questionnaire (custom UI is unavailable). The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead, without using this tool.`,exports.ERROR_NO_UI=`Error: UI not available (running in non-interactive mode)`,exports.ERROR_SESSION_INACTIVE=`Error: the questionnaire session is no longer active.`,exports.ERROR_SESSION_LOAD_FAILED=`Error: the questionnaire UI failed to load. The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead.`;
2
- //# sourceMappingURL=tool.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool.cjs","names":[],"sources":["../../src/constants/tool.ts"],"sourcesContent":["import { MAX_OPTIONS, MAX_QUESTIONS, MIN_OPTIONS } from './questionnaire';\nexport const ASK_USER_QUESTION_TOOL_NAME = 'ask_user_question';\n\nexport const DEFAULT_PROMPT_SNIPPET = `Ask the user up to ${MAX_QUESTIONS} structured questions (${MIN_OPTIONS}-${MAX_OPTIONS} options each) when requirements are ambiguous`;\nexport const DEFAULT_PROMPT_GUIDELINES = [\n `Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions, you can ask up to ${MAX_QUESTIONS} questions per invocation.`,\n `Each question MUST have ${MIN_OPTIONS}-${MAX_OPTIONS} options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer via the automatically appended \"Type something.\" row on every question, or press Esc to abandon the questionnaire. Do NOT author \"Other\" or \"Type something.\" labels yourself, reserved labels are rejected at runtime.`,\n 'Set multiSelect: true when multiple answers are valid. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs), single-select only. If you recommend a specific option, make that the first option and append \"(Recommended)\" to its label.',\n 'Do not stack multiple ask_user_question calls back-to-back, group all clarifying questions into one invocation.',\n];\n\nexport const ERROR_NO_UI = 'Error: UI not available (running in non-interactive mode)';\nexport const ERROR_NO_CUSTOM_UI =\n 'Error: this client cannot render the questionnaire (custom UI is unavailable). The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead, without using this tool.';\nexport const ERROR_SESSION_LOAD_FAILED =\n 'Error: the questionnaire UI failed to load. The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead.';\nexport const ERROR_SESSION_INACTIVE = 'Error: the questionnaire session is no longer active.';\n"],"mappings":"AACA,MAGa,EAA4B,CACvC,uKACA,saACA,wUACA,iHACF"}
@@ -1,2 +0,0 @@
1
- const e=`ask_user_question`,t=`Ask the user up to 4 structured questions (2-4 options each) when requirements are ambiguous`,n=[`Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions, you can ask up to 4 questions per invocation.`,`Each question MUST have 2-4 options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer via the automatically appended "Type something." row on every question, or press Esc to abandon the questionnaire. Do NOT author "Other" or "Type something." labels yourself, reserved labels are rejected at runtime.`,`Set multiSelect: true when multiple answers are valid. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs), single-select only. If you recommend a specific option, make that the first option and append "(Recommended)" to its label.`,`Do not stack multiple ask_user_question calls back-to-back, group all clarifying questions into one invocation.`],r=`Error: UI not available (running in non-interactive mode)`,i=`Error: this client cannot render the questionnaire (custom UI is unavailable). The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead, without using this tool.`,a=`Error: the questionnaire UI failed to load. The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead.`,o=`Error: the questionnaire session is no longer active.`;export{e as ASK_USER_QUESTION_TOOL_NAME,n as DEFAULT_PROMPT_GUIDELINES,t as DEFAULT_PROMPT_SNIPPET,i as ERROR_NO_CUSTOM_UI,r as ERROR_NO_UI,o as ERROR_SESSION_INACTIVE,a as ERROR_SESSION_LOAD_FAILED};
2
- //# sourceMappingURL=tool.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool.mjs","names":[],"sources":["../../src/constants/tool.ts"],"sourcesContent":["import { MAX_OPTIONS, MAX_QUESTIONS, MIN_OPTIONS } from './questionnaire';\nexport const ASK_USER_QUESTION_TOOL_NAME = 'ask_user_question';\n\nexport const DEFAULT_PROMPT_SNIPPET = `Ask the user up to ${MAX_QUESTIONS} structured questions (${MIN_OPTIONS}-${MAX_OPTIONS} options each) when requirements are ambiguous`;\nexport const DEFAULT_PROMPT_GUIDELINES = [\n `Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions, you can ask up to ${MAX_QUESTIONS} questions per invocation.`,\n `Each question MUST have ${MIN_OPTIONS}-${MAX_OPTIONS} options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer via the automatically appended \"Type something.\" row on every question, or press Esc to abandon the questionnaire. Do NOT author \"Other\" or \"Type something.\" labels yourself, reserved labels are rejected at runtime.`,\n 'Set multiSelect: true when multiple answers are valid. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs), single-select only. If you recommend a specific option, make that the first option and append \"(Recommended)\" to its label.',\n 'Do not stack multiple ask_user_question calls back-to-back, group all clarifying questions into one invocation.',\n];\n\nexport const ERROR_NO_UI = 'Error: UI not available (running in non-interactive mode)';\nexport const ERROR_NO_CUSTOM_UI =\n 'Error: this client cannot render the questionnaire (custom UI is unavailable). The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead, without using this tool.';\nexport const ERROR_SESSION_LOAD_FAILED =\n 'Error: the questionnaire UI failed to load. The user never saw the questions, do NOT treat this as a decline. Ask the questions as plain chat text instead.';\nexport const ERROR_SESSION_INACTIVE = 'Error: the questionnaire session is no longer active.';\n"],"mappings":"AACA,MAAa,EAA8B,oBAE9B,EAAyB,+FACzB,EAA4B,CACvC,uKACA,saACA,wUACA,iHACF,EAEa,EAAc,4DACd,EACX,0NACW,EACX,8JACW,EAAyB"}
@@ -1,2 +0,0 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../constants/package.cjs"),t=require("../constants/tool.cjs"),n=require("../services/askUserToolGate/index.cjs"),r=require("../services/autonomousVoiceMode/index.cjs"),i=require("../services/questionnaireCoordinator/index.cjs"),a=require("../services/voiceQuestionHandoff/index.cjs"),o=require("../tools/askUserQuestion.cjs"),s=require("../tui/askUserToolRender.cjs");let c=require("@agimon-ai/doompi-core/narration"),l=require("@agimon-ai/doompi-core/pi-extension"),u=require("@agimon-ai/doompi-minor-mode");function d(){return{answers:[],cancelled:!0}}const f=(0,l.definePiExtension)(e.PACKAGE_SOURCE,({context:f})=>{let p=!0,m=0,h,g=!1,_=new i.QuestionnaireCoordinator,v,y=!1,b=!0,x=new Set,S=()=>n.askUserToolRestriction(t.ASK_USER_QUESTION_TOOL_NAME,b&&!y),C=()=>x.forEach(e=>e()),w=Promise.resolve(),T=new Set,E=e=>(T.add(e),e.then(()=>T.delete(e),()=>T.delete(e)),e),D=(e,t)=>p&&e===m&&t===h,O=(e,t)=>p&&g&&t?.aborted!==!0&&e.sessionManager.getSessionId()===h,k=async()=>{if(!p)return;let e=_;e.shutdown(),p=!1,m+=1,g=!1,h=void 0,await Promise.allSettled(T),await e.waitForIdle()},A={enqueue:(e,t)=>{let n=_,r=m,i=h;return!g||!D(r,i)||t?.aborted?Promise.resolve(d()):n.enqueue(async t=>{if(!g||!D(r,i)||t.signal.aborted)return d();let n=await e({...t,reportProgress:e=>{D(r,i)&&!t.signal.aborted&&t.reportProgress(e)}});return g&&D(r,i)&&!t.signal.aborted?n:d()},t)},isActive:O,runTui:async(e,t,n,r,i)=>{if(!O(e,r))return;let{runTuiQuestionnaire:a}=await Promise.resolve().then(()=>require("../tui/runQuestionnaire.cjs"));if(!O(e,r))return;let o=await a(e,t,n,r,i);return O(e,r)?o:void 0},tryVoice:e=>p&&g?v?.handoff(e):void 0};return{services:[e=>{e.inject([u.DOOM_MINOR_MODE_CATALOG_SERVICE,c.DOOM_NARRATION_SERVICE],e=>{let t=a.createVoiceQuestionHandoff((0,u.requireMinorModeCatalog)(e),(0,c.requireDoomNarrationService)(e));return v=t,()=>{v===t&&(v=void 0)}}),e.inject([u.DOOM_MINOR_MODE_CATALOG_SERVICE],e=>{let t=(0,u.requireMinorModeCatalog)(e),n=()=>{y=r.isAutonomousVoiceActive(t.list()),C()},i=t.subscribe(n);return n(),()=>{i(),y=!1,C()}})}],tools:[(0,l.definePiTool)(o.createAskUserQuestionTool(f,A,s.askUserToolRender))],events:{before_agent_start:(e,t)=>{O(t)&&(b=t.hasUI,C())},session_start:(e,t)=>{if(!p)return;let n=_;n.shutdown();let r=t.sessionManager.getSessionId(),a=++m;_=new i.QuestionnaireCoordinator,h=r,g=!1;let o=async()=>{await n.waitForIdle(),D(a,r)&&(g=!0)},s=w.then(o,o);return w=s.catch(()=>void 0),E(s)}},onDispose:k,toolRestrictions:[{source:e.PACKAGE_SOURCE,get restrict(){return S()},subscribe(e){return x.add(e),()=>{x.delete(e)}}}]}});exports.default=f,exports.userFeedbackExtension=f;
2
- //# sourceMappingURL=pi.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.cjs","names":["definePiExtension","PACKAGE_SOURCE","QuestionnaireCoordinator","askUserToolRestriction","ASK_USER_QUESTION_TOOL_NAME","DOOM_MINOR_MODE_CATALOG_SERVICE","DOOM_NARRATION_SERVICE","createVoiceQuestionHandoff","requireMinorModeCatalog","requireDoomNarrationService","isAutonomousVoiceActive","definePiTool","createAskUserQuestionTool","askUserToolRender"],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { DOOM_NARRATION_SERVICE, requireDoomNarrationService } from '@agimon-ai/doompi-core/narration';\nimport { definePiExtension, definePiTool } from '@agimon-ai/doompi-core/pi-extension';\nimport { type DoomToolRestriction } from '@agimon-ai/doompi-core/tool-surface';\nimport { DOOM_MINOR_MODE_CATALOG_SERVICE, requireMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { PACKAGE_SOURCE } from '../constants/package';\nimport { ASK_USER_QUESTION_TOOL_NAME } from '../constants/tool';\nimport { askUserToolRestriction } from '../services/askUserToolGate';\nimport { isAutonomousVoiceActive } from '../services/autonomousVoiceMode';\nimport { QuestionnaireCoordinator, type QuestionnaireRunner } from '../services/questionnaireCoordinator';\nimport { createVoiceQuestionHandoff, type VoiceQuestionHandoff } from '../services/voiceQuestionHandoff';\nimport { createAskUserQuestionTool } from '../tools/askUserQuestion';\nimport { askUserToolRender } from '../tui/askUserToolRender';\nimport type { QuestionnaireResult } from '../types/questionnaire';\n\nfunction cancelledResult(): QuestionnaireResult {\n return { answers: [], cancelled: true };\n}\n\nexport const userFeedbackExtension = definePiExtension(PACKAGE_SOURCE, ({ context: cordis }) => {\n let active = true;\n let sessionGeneration = 0;\n let sessionId: string | undefined;\n let sessionReady = false;\n let coordinator = new QuestionnaireCoordinator();\n let voiceHandoff: VoiceQuestionHandoff | undefined;\n let voiceActive = false;\n let hasUI = true;\n const restrictionListeners = new Set<() => void>();\n const currentRestriction = (): DoomToolRestriction =>\n askUserToolRestriction(ASK_USER_QUESTION_TOOL_NAME, hasUI && !voiceActive);\n const syncToolRestriction = (): void => restrictionListeners.forEach((listener) => listener());\n let lifecycleQueue: Promise<void> = Promise.resolve();\n const pendingOperations = new Set<Promise<unknown>>();\n\n const trackOperation = <T>(operation: Promise<T>): Promise<T> => {\n pendingOperations.add(operation);\n void operation.then(\n () => pendingOperations.delete(operation),\n () => pendingOperations.delete(operation),\n );\n return operation;\n };\n const ownsGeneration = (generation: number, expectedSessionId: string | undefined): boolean =>\n active && generation === sessionGeneration && expectedSessionId === sessionId;\n const isContextActive = (context: ExtensionContext, signal?: AbortSignal): boolean =>\n active && sessionReady && signal?.aborted !== true && context.sessionManager.getSessionId() === sessionId;\n\n const shutdownRuntime = async (): Promise<void> => {\n if (!active) return;\n const ownedCoordinator = coordinator;\n ownedCoordinator.shutdown();\n active = false;\n sessionGeneration += 1;\n sessionReady = false;\n sessionId = undefined;\n await Promise.allSettled(pendingOperations);\n await ownedCoordinator.waitForIdle();\n };\n\n const toolDependencies: Parameters<typeof createAskUserQuestionTool>[1] = {\n enqueue: (runner: QuestionnaireRunner, signal?: AbortSignal) => {\n const ownedCoordinator = coordinator;\n const generation = sessionGeneration;\n const expectedSessionId = sessionId;\n if (!sessionReady || !ownsGeneration(generation, expectedSessionId) || signal?.aborted) {\n return Promise.resolve(cancelledResult());\n }\n return ownedCoordinator.enqueue(async (context) => {\n if (!sessionReady || !ownsGeneration(generation, expectedSessionId) || context.signal.aborted) {\n return cancelledResult();\n }\n const result = await runner({\n ...context,\n reportProgress: (progress) => {\n if (ownsGeneration(generation, expectedSessionId) && !context.signal.aborted) {\n context.reportProgress(progress);\n }\n },\n });\n return sessionReady && ownsGeneration(generation, expectedSessionId) && !context.signal.aborted\n ? result\n : cancelledResult();\n }, signal);\n },\n isActive: isContextActive,\n runTui: async (context, params, collapseKey, signal, reportProgress) => {\n if (!isContextActive(context, signal)) return undefined;\n const { runTuiQuestionnaire } = await import('../tui/runQuestionnaire');\n if (!isContextActive(context, signal)) return undefined;\n const result = await runTuiQuestionnaire(context, params, collapseKey, signal, reportProgress);\n return isContextActive(context, signal) ? result : undefined;\n },\n tryVoice: (params) => (active && sessionReady ? voiceHandoff?.handoff(params) : undefined),\n };\n\n const beforeAgentStart = (_event: unknown, context: ExtensionContext) => {\n if (!isContextActive(context)) return;\n hasUI = context.hasUI;\n syncToolRestriction();\n };\n\n const sessionStart = (_event: unknown, context: ExtensionContext) => {\n if (!active) return;\n const previousCoordinator = coordinator;\n previousCoordinator.shutdown();\n const activeSessionId = context.sessionManager.getSessionId();\n const generation = ++sessionGeneration;\n const nextCoordinator = new QuestionnaireCoordinator();\n coordinator = nextCoordinator;\n sessionId = activeSessionId;\n sessionReady = false;\n\n const initializeSession = async (): Promise<void> => {\n await previousCoordinator.waitForIdle();\n if (!ownsGeneration(generation, activeSessionId)) return;\n sessionReady = true;\n // The surface is re-registered per session from the gate state in force, so a session\n // that starts with Voice already active needs nothing extra here.\n };\n\n const operation = lifecycleQueue.then(initializeSession, initializeSession);\n lifecycleQueue = operation.catch(() => undefined);\n return trackOperation(operation);\n };\n return {\n services: [\n (serviceContextOwner: Context) => {\n serviceContextOwner.inject([DOOM_MINOR_MODE_CATALOG_SERVICE, DOOM_NARRATION_SERVICE], (serviceContext) => {\n const handoff = createVoiceQuestionHandoff(\n requireMinorModeCatalog(serviceContext),\n requireDoomNarrationService(serviceContext),\n );\n voiceHandoff = handoff;\n return () => {\n if (voiceHandoff === handoff) voiceHandoff = undefined;\n };\n });\n\n // Separate from the handoff binding above: the gate needs only the mode catalog, so it\n // still applies to a Voice build that publishes modes without providing narration.\n serviceContextOwner.inject([DOOM_MINOR_MODE_CATALOG_SERVICE], (modeContext) => {\n const modes = requireMinorModeCatalog(modeContext);\n const apply = (): void => {\n voiceActive = isAutonomousVoiceActive(modes.list());\n syncToolRestriction();\n };\n const unsubscribe = modes.subscribe(apply);\n apply();\n return () => {\n unsubscribe();\n voiceActive = false;\n syncToolRestriction();\n };\n });\n },\n ],\n tools: [definePiTool(createAskUserQuestionTool(cordis, toolDependencies, askUserToolRender))],\n events: { before_agent_start: beforeAgentStart, session_start: sessionStart },\n onDispose: shutdownRuntime,\n toolRestrictions: [\n {\n source: PACKAGE_SOURCE,\n get restrict() {\n return currentRestriction();\n },\n subscribe(listener) {\n restrictionListeners.add(listener);\n return () => {\n restrictionListeners.delete(listener);\n };\n },\n },\n ],\n };\n});\nexport default userFeedbackExtension;\n"],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- //#region src/extensions/pi.d.ts
2
- export declare const userFeedbackExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<undefined>;
3
- //#endregion
4
- export { userFeedbackExtension as default };
5
- //# sourceMappingURL=pi.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.d.cts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";qBAqBa,6EAAqB"}
@@ -1,5 +0,0 @@
1
- //#region src/extensions/pi.d.ts
2
- export declare const userFeedbackExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<undefined>;
3
- //#endregion
4
- export { userFeedbackExtension as default };
5
- //# sourceMappingURL=pi.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";qBAqBa,6EAAqB"}
@@ -1,2 +0,0 @@
1
- import{PACKAGE_SOURCE as e}from"../constants/package.mjs";import{ASK_USER_QUESTION_TOOL_NAME as t}from"../constants/tool.mjs";import{askUserToolRestriction as n}from"../services/askUserToolGate/index.mjs";import{isAutonomousVoiceActive as r}from"../services/autonomousVoiceMode/index.mjs";import{QuestionnaireCoordinator as i}from"../services/questionnaireCoordinator/index.mjs";import{createVoiceQuestionHandoff as a}from"../services/voiceQuestionHandoff/index.mjs";import{createAskUserQuestionTool as o}from"../tools/askUserQuestion.mjs";import{askUserToolRender as s}from"../tui/askUserToolRender.mjs";import{DOOM_NARRATION_SERVICE as c,requireDoomNarrationService as l}from"@agimon-ai/doompi-core/narration";import{definePiExtension as u,definePiTool as d}from"@agimon-ai/doompi-core/pi-extension";import{DOOM_MINOR_MODE_CATALOG_SERVICE as f,requireMinorModeCatalog as p}from"@agimon-ai/doompi-minor-mode";function m(){return{answers:[],cancelled:!0}}const h=u(e,({context:u})=>{let h=!0,g=0,_,v=!1,y=new i,b,x=!1,S=!0,C=new Set,w=()=>n(t,S&&!x),T=()=>C.forEach(e=>e()),E=Promise.resolve(),D=new Set,O=e=>(D.add(e),e.then(()=>D.delete(e),()=>D.delete(e)),e),k=(e,t)=>h&&e===g&&t===_,A=(e,t)=>h&&v&&t?.aborted!==!0&&e.sessionManager.getSessionId()===_;return{services:[e=>{e.inject([f,c],e=>{let t=a(p(e),l(e));return b=t,()=>{b===t&&(b=void 0)}}),e.inject([f],e=>{let t=p(e),n=()=>{x=r(t.list()),T()},i=t.subscribe(n);return n(),()=>{i(),x=!1,T()}})}],tools:[d(o(u,{enqueue:(e,t)=>{let n=y,r=g,i=_;return!v||!k(r,i)||t?.aborted?Promise.resolve(m()):n.enqueue(async t=>{if(!v||!k(r,i)||t.signal.aborted)return m();let n=await e({...t,reportProgress:e=>{k(r,i)&&!t.signal.aborted&&t.reportProgress(e)}});return v&&k(r,i)&&!t.signal.aborted?n:m()},t)},isActive:A,runTui:async(e,t,n,r,i)=>{if(!A(e,r))return;let{runTuiQuestionnaire:a}=await import(`../tui/runQuestionnaire.mjs`);if(!A(e,r))return;let o=await a(e,t,n,r,i);return A(e,r)?o:void 0},tryVoice:e=>h&&v?b?.handoff(e):void 0},s))],events:{before_agent_start:(e,t)=>{A(t)&&(S=t.hasUI,T())},session_start:(e,t)=>{if(!h)return;let n=y;n.shutdown();let r=t.sessionManager.getSessionId(),a=++g;y=new i,_=r,v=!1;let o=async()=>{await n.waitForIdle(),k(a,r)&&(v=!0)},s=E.then(o,o);return E=s.catch(()=>void 0),O(s)}},onDispose:async()=>{if(!h)return;let e=y;e.shutdown(),h=!1,g+=1,v=!1,_=void 0,await Promise.allSettled(D),await e.waitForIdle()},toolRestrictions:[{source:e,get restrict(){return w()},subscribe(e){return C.add(e),()=>{C.delete(e)}}}]}});export{h as default,h as userFeedbackExtension};
2
- //# sourceMappingURL=pi.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.mjs","names":[],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { DOOM_NARRATION_SERVICE, requireDoomNarrationService } from '@agimon-ai/doompi-core/narration';\nimport { definePiExtension, definePiTool } from '@agimon-ai/doompi-core/pi-extension';\nimport { type DoomToolRestriction } from '@agimon-ai/doompi-core/tool-surface';\nimport { DOOM_MINOR_MODE_CATALOG_SERVICE, requireMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { PACKAGE_SOURCE } from '../constants/package';\nimport { ASK_USER_QUESTION_TOOL_NAME } from '../constants/tool';\nimport { askUserToolRestriction } from '../services/askUserToolGate';\nimport { isAutonomousVoiceActive } from '../services/autonomousVoiceMode';\nimport { QuestionnaireCoordinator, type QuestionnaireRunner } from '../services/questionnaireCoordinator';\nimport { createVoiceQuestionHandoff, type VoiceQuestionHandoff } from '../services/voiceQuestionHandoff';\nimport { createAskUserQuestionTool } from '../tools/askUserQuestion';\nimport { askUserToolRender } from '../tui/askUserToolRender';\nimport type { QuestionnaireResult } from '../types/questionnaire';\n\nfunction cancelledResult(): QuestionnaireResult {\n return { answers: [], cancelled: true };\n}\n\nexport const userFeedbackExtension = definePiExtension(PACKAGE_SOURCE, ({ context: cordis }) => {\n let active = true;\n let sessionGeneration = 0;\n let sessionId: string | undefined;\n let sessionReady = false;\n let coordinator = new QuestionnaireCoordinator();\n let voiceHandoff: VoiceQuestionHandoff | undefined;\n let voiceActive = false;\n let hasUI = true;\n const restrictionListeners = new Set<() => void>();\n const currentRestriction = (): DoomToolRestriction =>\n askUserToolRestriction(ASK_USER_QUESTION_TOOL_NAME, hasUI && !voiceActive);\n const syncToolRestriction = (): void => restrictionListeners.forEach((listener) => listener());\n let lifecycleQueue: Promise<void> = Promise.resolve();\n const pendingOperations = new Set<Promise<unknown>>();\n\n const trackOperation = <T>(operation: Promise<T>): Promise<T> => {\n pendingOperations.add(operation);\n void operation.then(\n () => pendingOperations.delete(operation),\n () => pendingOperations.delete(operation),\n );\n return operation;\n };\n const ownsGeneration = (generation: number, expectedSessionId: string | undefined): boolean =>\n active && generation === sessionGeneration && expectedSessionId === sessionId;\n const isContextActive = (context: ExtensionContext, signal?: AbortSignal): boolean =>\n active && sessionReady && signal?.aborted !== true && context.sessionManager.getSessionId() === sessionId;\n\n const shutdownRuntime = async (): Promise<void> => {\n if (!active) return;\n const ownedCoordinator = coordinator;\n ownedCoordinator.shutdown();\n active = false;\n sessionGeneration += 1;\n sessionReady = false;\n sessionId = undefined;\n await Promise.allSettled(pendingOperations);\n await ownedCoordinator.waitForIdle();\n };\n\n const toolDependencies: Parameters<typeof createAskUserQuestionTool>[1] = {\n enqueue: (runner: QuestionnaireRunner, signal?: AbortSignal) => {\n const ownedCoordinator = coordinator;\n const generation = sessionGeneration;\n const expectedSessionId = sessionId;\n if (!sessionReady || !ownsGeneration(generation, expectedSessionId) || signal?.aborted) {\n return Promise.resolve(cancelledResult());\n }\n return ownedCoordinator.enqueue(async (context) => {\n if (!sessionReady || !ownsGeneration(generation, expectedSessionId) || context.signal.aborted) {\n return cancelledResult();\n }\n const result = await runner({\n ...context,\n reportProgress: (progress) => {\n if (ownsGeneration(generation, expectedSessionId) && !context.signal.aborted) {\n context.reportProgress(progress);\n }\n },\n });\n return sessionReady && ownsGeneration(generation, expectedSessionId) && !context.signal.aborted\n ? result\n : cancelledResult();\n }, signal);\n },\n isActive: isContextActive,\n runTui: async (context, params, collapseKey, signal, reportProgress) => {\n if (!isContextActive(context, signal)) return undefined;\n const { runTuiQuestionnaire } = await import('../tui/runQuestionnaire');\n if (!isContextActive(context, signal)) return undefined;\n const result = await runTuiQuestionnaire(context, params, collapseKey, signal, reportProgress);\n return isContextActive(context, signal) ? result : undefined;\n },\n tryVoice: (params) => (active && sessionReady ? voiceHandoff?.handoff(params) : undefined),\n };\n\n const beforeAgentStart = (_event: unknown, context: ExtensionContext) => {\n if (!isContextActive(context)) return;\n hasUI = context.hasUI;\n syncToolRestriction();\n };\n\n const sessionStart = (_event: unknown, context: ExtensionContext) => {\n if (!active) return;\n const previousCoordinator = coordinator;\n previousCoordinator.shutdown();\n const activeSessionId = context.sessionManager.getSessionId();\n const generation = ++sessionGeneration;\n const nextCoordinator = new QuestionnaireCoordinator();\n coordinator = nextCoordinator;\n sessionId = activeSessionId;\n sessionReady = false;\n\n const initializeSession = async (): Promise<void> => {\n await previousCoordinator.waitForIdle();\n if (!ownsGeneration(generation, activeSessionId)) return;\n sessionReady = true;\n // The surface is re-registered per session from the gate state in force, so a session\n // that starts with Voice already active needs nothing extra here.\n };\n\n const operation = lifecycleQueue.then(initializeSession, initializeSession);\n lifecycleQueue = operation.catch(() => undefined);\n return trackOperation(operation);\n };\n return {\n services: [\n (serviceContextOwner: Context) => {\n serviceContextOwner.inject([DOOM_MINOR_MODE_CATALOG_SERVICE, DOOM_NARRATION_SERVICE], (serviceContext) => {\n const handoff = createVoiceQuestionHandoff(\n requireMinorModeCatalog(serviceContext),\n requireDoomNarrationService(serviceContext),\n );\n voiceHandoff = handoff;\n return () => {\n if (voiceHandoff === handoff) voiceHandoff = undefined;\n };\n });\n\n // Separate from the handoff binding above: the gate needs only the mode catalog, so it\n // still applies to a Voice build that publishes modes without providing narration.\n serviceContextOwner.inject([DOOM_MINOR_MODE_CATALOG_SERVICE], (modeContext) => {\n const modes = requireMinorModeCatalog(modeContext);\n const apply = (): void => {\n voiceActive = isAutonomousVoiceActive(modes.list());\n syncToolRestriction();\n };\n const unsubscribe = modes.subscribe(apply);\n apply();\n return () => {\n unsubscribe();\n voiceActive = false;\n syncToolRestriction();\n };\n });\n },\n ],\n tools: [definePiTool(createAskUserQuestionTool(cordis, toolDependencies, askUserToolRender))],\n events: { before_agent_start: beforeAgentStart, session_start: sessionStart },\n onDispose: shutdownRuntime,\n toolRestrictions: [\n {\n source: PACKAGE_SOURCE,\n get restrict() {\n return currentRestriction();\n },\n subscribe(listener) {\n restrictionListeners.add(listener);\n return () => {\n restrictionListeners.delete(listener);\n };\n },\n },\n ],\n };\n});\nexport default userFeedbackExtension;\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../constants/package.cjs"),t=require("../services/questionnaireCoordinator/index.cjs"),n=require("../tools/askUserHeadless.cjs"),r=(0,require("@agimon-ai/doompi-core/server-facet").defineServerPlugin)({name:e.PACKAGE_SOURCE,session:()=>{let e=new t.QuestionnaireCoordinator;return{tools:[n.createAskUserHeadlessTool(e)],hooks:[{event:`session_shutdown`,handle:()=>e.shutdown()}],onDispose:()=>e.shutdown()}}});exports.default=r,exports.userFeedbackServerFacet=r;
2
- //# sourceMappingURL=server.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.cjs","names":["defineServerPlugin","PACKAGE_SOURCE","QuestionnaireCoordinator","createAskUserHeadlessTool"],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { PACKAGE_SOURCE } from '../constants/package';\nimport { QuestionnaireCoordinator } from '../services/questionnaireCoordinator';\nimport { createAskUserHeadlessTool } from '../tools/askUserHeadless';\nexport const userFeedbackServerFacet = defineServerPlugin({\n name: PACKAGE_SOURCE,\n session: () => {\n const coordinator = new QuestionnaireCoordinator();\n return {\n tools: [createAskUserHeadlessTool(coordinator)],\n hooks: [{ event: 'session_shutdown', handle: () => coordinator.shutdown() }],\n onDispose: () => coordinator.shutdown(),\n };\n },\n});\nexport default userFeedbackServerFacet;\n"],"mappings":"iPAKa,GAAA,+CAA0BA,CAAAA,CAAAA,mBAAAA,CAAmB,CACxD,KAAMC,EAAAA,eACN,YAAe,CACb,IAAM,EAAc,IAAIC,EAAAA,yBACxB,MAAO,CACL,MAAO,CAACC,EAAAA,0BAA0B,CAAW,CAAC,EAC9C,MAAO,CAAC,CAAE,MAAO,mBAAoB,WAAc,EAAY,SAAS,CAAE,CAAC,EAC3E,cAAiB,EAAY,SAAS,CACxC,CACF,CACF,CAAC"}
@@ -1,5 +0,0 @@
1
- //#region src/extensions/server.d.ts
2
- export declare const userFeedbackServerFacet: import("@agimon-ai/doompi-core/server-facet").DoomServerFacet;
3
- //#endregion
4
- export { userFeedbackServerFacet as default };
5
- //# sourceMappingURL=server.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.cts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAKa,uEAAuB"}
@@ -1,5 +0,0 @@
1
- //#region src/extensions/server.d.ts
2
- export declare const userFeedbackServerFacet: import("@agimon-ai/doompi-core/server-facet").DoomServerFacet;
3
- //#endregion
4
- export { userFeedbackServerFacet as default };
5
- //# sourceMappingURL=server.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.mts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAKa,uEAAuB"}
@@ -1,2 +0,0 @@
1
- import{PACKAGE_SOURCE as e}from"../constants/package.mjs";import{QuestionnaireCoordinator as t}from"../services/questionnaireCoordinator/index.mjs";import{createAskUserHeadlessTool as n}from"../tools/askUserHeadless.mjs";import{defineServerPlugin as r}from"@agimon-ai/doompi-core/server-facet";const i=r({name:e,session:()=>{let e=new t;return{tools:[n(e)],hooks:[{event:`session_shutdown`,handle:()=>e.shutdown()}],onDispose:()=>e.shutdown()}}});export{i as default,i as userFeedbackServerFacet};
2
- //# sourceMappingURL=server.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.mjs","names":[],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { PACKAGE_SOURCE } from '../constants/package';\nimport { QuestionnaireCoordinator } from '../services/questionnaireCoordinator';\nimport { createAskUserHeadlessTool } from '../tools/askUserHeadless';\nexport const userFeedbackServerFacet = defineServerPlugin({\n name: PACKAGE_SOURCE,\n session: () => {\n const coordinator = new QuestionnaireCoordinator();\n return {\n tools: [createAskUserHeadlessTool(coordinator)],\n hooks: [{ event: 'session_shutdown', handle: () => coordinator.shutdown() }],\n onDispose: () => coordinator.shutdown(),\n };\n },\n});\nexport default userFeedbackServerFacet;\n"],"mappings":"sSAKA,MAAa,EAA0B,EAAmB,CACxD,KAAM,EACN,YAAe,CACb,IAAM,EAAc,IAAI,EACxB,MAAO,CACL,MAAO,CAAC,EAA0B,CAAW,CAAC,EAC9C,MAAO,CAAC,CAAE,MAAO,mBAAoB,WAAc,EAAY,SAAS,CAAE,CAAC,EAC3E,cAAiB,EAAY,SAAS,CACxC,CACF,CACF,CAAC"}
package/dist/index.cjs DELETED
File without changes
package/dist/index.d.cts DELETED
@@ -1,3 +0,0 @@
1
- import { QuestionParams } from "./schemas/questionnaire.cjs";
2
- import { QuestionnaireResult, ToolTextResult } from "./types/questionnaire.cjs";
3
- export type { QuestionParams, QuestionnaireResult, ToolTextResult };
package/dist/index.d.mts DELETED
@@ -1,3 +0,0 @@
1
- import { QuestionParams } from "./schemas/questionnaire.mjs";
2
- import { QuestionnaireResult, ToolTextResult } from "./types/questionnaire.mjs";
3
- export type { QuestionParams, QuestionnaireResult, ToolTextResult };
package/dist/index.mjs DELETED
@@ -1 +0,0 @@
1
- export{};
@@ -1,2 +0,0 @@
1
- const e=(0,require("@agimon-ai/doompi-core/api-contracts").defineApiContract)({version:1,http:[],sockets:[],dynamic:[]});exports.apiContracts=e,exports.default=e;
2
- //# sourceMappingURL=apiContracts.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/api-contracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":"AAGA,MAAa,GAAA,gDAAeA,CAAAA,CAAAA,kBAAAA,CAAkB,CAAE,QAAS,EAAG,KAAM,CAAC,EAAG,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,CAAC"}
@@ -1,53 +0,0 @@
1
- //#region src/schemas/apiContracts.d.ts
2
- /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
- export declare const apiContracts: {
4
- version: 1;
5
- protocols?: Record<string, string> | undefined;
6
- schemas?: Record<string, boolean | object> | undefined;
7
- http: {
8
- id: string;
9
- scope: "global" | "session" | "workspace";
10
- basePath?: string | undefined;
11
- path: string;
12
- method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
- description: string;
14
- availability?: string | undefined;
15
- authentication: "device" | "none" | "owner";
16
- parameters?: {
17
- name: string;
18
- in: "header" | "path" | "query";
19
- required: boolean;
20
- schema: boolean | object;
21
- }[] | undefined;
22
- body?: {
23
- contentType: string;
24
- contentTypes?: string[] | undefined;
25
- required: boolean;
26
- schema: boolean | object;
27
- } | undefined;
28
- responses: Record<string, {
29
- description: string;
30
- contentType?: string | undefined;
31
- schema?: boolean | object | undefined;
32
- events?: Record<string, boolean | object> | undefined;
33
- }>;
34
- }[];
35
- sockets: {
36
- id: string;
37
- scope: "global" | "session" | "workspace";
38
- description: string;
39
- availability?: string | undefined;
40
- service: string;
41
- member: string;
42
- direction: "client-to-server" | "server-to-client";
43
- kind: "channel" | "method" | "state";
44
- input: boolean | object;
45
- output?: boolean | object | undefined;
46
- errors?: boolean | object | undefined;
47
- }[];
48
- dynamic: string[];
49
- gaps?: string[] | undefined;
50
- };
51
- //#endregion
52
- export { apiContracts as default };
53
- //# sourceMappingURL=apiContracts.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.d.cts","names":[],"sources":["../../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -1,53 +0,0 @@
1
- //#region src/schemas/apiContracts.d.ts
2
- /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
- export declare const apiContracts: {
4
- version: 1;
5
- protocols?: Record<string, string> | undefined;
6
- schemas?: Record<string, boolean | object> | undefined;
7
- http: {
8
- id: string;
9
- scope: "global" | "session" | "workspace";
10
- basePath?: string | undefined;
11
- path: string;
12
- method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
- description: string;
14
- availability?: string | undefined;
15
- authentication: "device" | "none" | "owner";
16
- parameters?: {
17
- name: string;
18
- in: "header" | "path" | "query";
19
- required: boolean;
20
- schema: boolean | object;
21
- }[] | undefined;
22
- body?: {
23
- contentType: string;
24
- contentTypes?: string[] | undefined;
25
- required: boolean;
26
- schema: boolean | object;
27
- } | undefined;
28
- responses: Record<string, {
29
- description: string;
30
- contentType?: string | undefined;
31
- schema?: boolean | object | undefined;
32
- events?: Record<string, boolean | object> | undefined;
33
- }>;
34
- }[];
35
- sockets: {
36
- id: string;
37
- scope: "global" | "session" | "workspace";
38
- description: string;
39
- availability?: string | undefined;
40
- service: string;
41
- member: string;
42
- direction: "client-to-server" | "server-to-client";
43
- kind: "channel" | "method" | "state";
44
- input: boolean | object;
45
- output?: boolean | object | undefined;
46
- errors?: boolean | object | undefined;
47
- }[];
48
- dynamic: string[];
49
- gaps?: string[] | undefined;
50
- };
51
- //#endregion
52
- export { apiContracts as default };
53
- //# sourceMappingURL=apiContracts.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -1,2 +0,0 @@
1
- import{defineApiContract as e}from"@agimon-ai/doompi-core/api-contracts";const t=e({version:1,http:[],sockets:[],dynamic:[]});export{t as apiContracts,t as default};
2
- //# sourceMappingURL=apiContracts.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/api-contracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":"yEAGA,MAAa,EAAe,EAAkB,CAAE,QAAS,EAAG,KAAM,CAAC,EAAG,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,CAAC"}
@@ -1,2 +0,0 @@
1
- let e=require("typebox");const t=e.Type.Object({label:e.Type.String({maxLength:60,description:`MAX 60 CHARACTERS, hard limit. Concise option label shown to the user, ideally 1-5 words.`}),description:e.Type.String({description:`Explanation of what the option means and its important trade-offs.`}),preview:e.Type.Optional(e.Type.String({description:`Optional markdown preview rendered while this option is focused.`}))},{additionalProperties:!1}),n=e.Type.Object({question:e.Type.String({description:`The complete, clear question to ask the user.`}),header:e.Type.String({maxLength:16,description:`MAX 16 CHARACTERS, short label used when navigating several questions.`}),options:e.Type.Array(t,{minItems:2,maxItems:4,description:`The 2-4 choices offered for this question.`}),multiSelect:e.Type.Optional(e.Type.Boolean({description:`Allow more than one option to be selected.`,default:!1}))},{additionalProperties:!1}),r=e.Type.Object({questions:e.Type.Array(n,{minItems:1,maxItems:4,description:`Questions to ask the user (1-4 questions).`})},{additionalProperties:!1});exports.OptionSchema=t,exports.QuestionParamsSchema=r,exports.QuestionSchema=n;
2
- //# sourceMappingURL=questionnaire.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionnaire.cjs","names":["Type"],"sources":["../../src/schemas/questionnaire.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nimport {\n MAX_QUESTIONS,\n MIN_OPTIONS,\n MAX_OPTIONS,\n MAX_HEADER_LENGTH,\n MAX_LABEL_LENGTH,\n} from '../constants/questionnaire';\n\nexport const OptionSchema = Type.Object(\n {\n label: Type.String({\n maxLength: MAX_LABEL_LENGTH,\n description: 'MAX 60 CHARACTERS, hard limit. Concise option label shown to the user, ideally 1-5 words.',\n }),\n description: Type.String({\n description: 'Explanation of what the option means and its important trade-offs.',\n }),\n preview: Type.Optional(\n Type.String({ description: 'Optional markdown preview rendered while this option is focused.' }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport const QuestionSchema = Type.Object(\n {\n question: Type.String({ description: 'The complete, clear question to ask the user.' }),\n header: Type.String({\n maxLength: MAX_HEADER_LENGTH,\n description: 'MAX 16 CHARACTERS, short label used when navigating several questions.',\n }),\n options: Type.Array(OptionSchema, {\n minItems: MIN_OPTIONS,\n maxItems: MAX_OPTIONS,\n description: 'The 2-4 choices offered for this question.',\n }),\n multiSelect: Type.Optional(\n Type.Boolean({ description: 'Allow more than one option to be selected.', default: false }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport const QuestionParamsSchema = Type.Object(\n {\n questions: Type.Array(QuestionSchema, {\n minItems: 1,\n maxItems: MAX_QUESTIONS,\n description: 'Questions to ask the user (1-4 questions).',\n }),\n },\n { additionalProperties: false },\n);\n\nexport type OptionData = Static<typeof OptionSchema>;\nexport type QuestionData = Static<typeof QuestionSchema>;\nexport type QuestionParams = Static<typeof QuestionParamsSchema>;\n"],"mappings":"yBAUA,MAAa,EAAeA,EAAAA,KAAK,OAC/B,CACE,MAAOA,EAAAA,KAAK,OAAO,CACjB,UAAA,GACA,YAAa,2FACf,CAAC,EACD,YAAaA,EAAAA,KAAK,OAAO,CACvB,YAAa,oEACf,CAAC,EACD,QAASA,EAAAA,KAAK,SACZA,EAAAA,KAAK,OAAO,CAAE,YAAa,kEAAmE,CAAC,CACjG,CACF,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAAiBA,EAAAA,KAAK,OACjC,CACE,SAAUA,EAAAA,KAAK,OAAO,CAAE,YAAa,+CAAgD,CAAC,EACtF,OAAQA,EAAAA,KAAK,OAAO,CAClB,UAAA,GACA,YAAa,wEACf,CAAC,EACD,QAASA,EAAAA,KAAK,MAAM,EAAc,CAChC,SAAA,EACA,SAAA,EACA,YAAa,4CACf,CAAC,EACD,YAAaA,EAAAA,KAAK,SAChBA,EAAAA,KAAK,QAAQ,CAAE,YAAa,6CAA8C,QAAS,EAAM,CAAC,CAC5F,CACF,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAAuBA,EAAAA,KAAK,OACvC,CACE,UAAWA,EAAAA,KAAK,MAAM,EAAgB,CACpC,SAAU,EACV,SAAA,EACA,YAAa,4CACf,CAAC,CACH,EACA,CAAE,qBAAsB,EAAM,CAChC"}
@@ -1,17 +0,0 @@
1
- import { Static, Type } from "typebox";
2
- //#region src/schemas/questionnaire.d.ts
3
- export declare const QuestionParamsSchema: Type.TObject<{
4
- questions: Type.TArray<Type.TObject<{
5
- question: Type.TString;
6
- header: Type.TString;
7
- options: Type.TArray<Type.TObject<{
8
- label: Type.TString;
9
- description: Type.TString;
10
- preview: Type.TOptional<Type.TString>;
11
- }>>;
12
- multiSelect: Type.TOptional<Type.TBoolean>;
13
- }>>;
14
- }>;
15
- export type QuestionParams = Static<typeof QuestionParamsSchema>;
16
- //#endregion
17
- //# sourceMappingURL=questionnaire.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionnaire.d.cts","names":[],"sources":["../../src/schemas/questionnaire.ts"],"mappings":";;qBA6Ca,sBAAoB,KAAA;;;;;;;;;;;;YAarB,iBAAiB,cAAc"}
@@ -1,17 +0,0 @@
1
- import { Static, Type } from "typebox";
2
- //#region src/schemas/questionnaire.d.ts
3
- export declare const QuestionParamsSchema: Type.TObject<{
4
- questions: Type.TArray<Type.TObject<{
5
- question: Type.TString;
6
- header: Type.TString;
7
- options: Type.TArray<Type.TObject<{
8
- label: Type.TString;
9
- description: Type.TString;
10
- preview: Type.TOptional<Type.TString>;
11
- }>>;
12
- multiSelect: Type.TOptional<Type.TBoolean>;
13
- }>>;
14
- }>;
15
- export type QuestionParams = Static<typeof QuestionParamsSchema>;
16
- //#endregion
17
- //# sourceMappingURL=questionnaire.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionnaire.d.mts","names":[],"sources":["../../src/schemas/questionnaire.ts"],"mappings":";;qBA6Ca,sBAAoB,KAAA;;;;;;;;;;;;YAarB,iBAAiB,cAAc"}
@@ -1,2 +0,0 @@
1
- import{Type as e}from"typebox";const t=e.Object({label:e.String({maxLength:60,description:`MAX 60 CHARACTERS, hard limit. Concise option label shown to the user, ideally 1-5 words.`}),description:e.String({description:`Explanation of what the option means and its important trade-offs.`}),preview:e.Optional(e.String({description:`Optional markdown preview rendered while this option is focused.`}))},{additionalProperties:!1}),n=e.Object({question:e.String({description:`The complete, clear question to ask the user.`}),header:e.String({maxLength:16,description:`MAX 16 CHARACTERS, short label used when navigating several questions.`}),options:e.Array(t,{minItems:2,maxItems:4,description:`The 2-4 choices offered for this question.`}),multiSelect:e.Optional(e.Boolean({description:`Allow more than one option to be selected.`,default:!1}))},{additionalProperties:!1}),r=e.Object({questions:e.Array(n,{minItems:1,maxItems:4,description:`Questions to ask the user (1-4 questions).`})},{additionalProperties:!1});export{t as OptionSchema,r as QuestionParamsSchema,n as QuestionSchema};
2
- //# sourceMappingURL=questionnaire.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionnaire.mjs","names":[],"sources":["../../src/schemas/questionnaire.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nimport {\n MAX_QUESTIONS,\n MIN_OPTIONS,\n MAX_OPTIONS,\n MAX_HEADER_LENGTH,\n MAX_LABEL_LENGTH,\n} from '../constants/questionnaire';\n\nexport const OptionSchema = Type.Object(\n {\n label: Type.String({\n maxLength: MAX_LABEL_LENGTH,\n description: 'MAX 60 CHARACTERS, hard limit. Concise option label shown to the user, ideally 1-5 words.',\n }),\n description: Type.String({\n description: 'Explanation of what the option means and its important trade-offs.',\n }),\n preview: Type.Optional(\n Type.String({ description: 'Optional markdown preview rendered while this option is focused.' }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport const QuestionSchema = Type.Object(\n {\n question: Type.String({ description: 'The complete, clear question to ask the user.' }),\n header: Type.String({\n maxLength: MAX_HEADER_LENGTH,\n description: 'MAX 16 CHARACTERS, short label used when navigating several questions.',\n }),\n options: Type.Array(OptionSchema, {\n minItems: MIN_OPTIONS,\n maxItems: MAX_OPTIONS,\n description: 'The 2-4 choices offered for this question.',\n }),\n multiSelect: Type.Optional(\n Type.Boolean({ description: 'Allow more than one option to be selected.', default: false }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport const QuestionParamsSchema = Type.Object(\n {\n questions: Type.Array(QuestionSchema, {\n minItems: 1,\n maxItems: MAX_QUESTIONS,\n description: 'Questions to ask the user (1-4 questions).',\n }),\n },\n { additionalProperties: false },\n);\n\nexport type OptionData = Static<typeof OptionSchema>;\nexport type QuestionData = Static<typeof QuestionSchema>;\nexport type QuestionParams = Static<typeof QuestionParamsSchema>;\n"],"mappings":"+BAUA,MAAa,EAAe,EAAK,OAC/B,CACE,MAAO,EAAK,OAAO,CACjB,UAAA,GACA,YAAa,2FACf,CAAC,EACD,YAAa,EAAK,OAAO,CACvB,YAAa,oEACf,CAAC,EACD,QAAS,EAAK,SACZ,EAAK,OAAO,CAAE,YAAa,kEAAmE,CAAC,CACjG,CACF,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAAiB,EAAK,OACjC,CACE,SAAU,EAAK,OAAO,CAAE,YAAa,+CAAgD,CAAC,EACtF,OAAQ,EAAK,OAAO,CAClB,UAAA,GACA,YAAa,wEACf,CAAC,EACD,QAAS,EAAK,MAAM,EAAc,CAChC,SAAA,EACA,SAAA,EACA,YAAa,4CACf,CAAC,EACD,YAAa,EAAK,SAChB,EAAK,QAAQ,CAAE,YAAa,6CAA8C,QAAS,EAAM,CAAC,CAC5F,CACF,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAAuB,EAAK,OACvC,CACE,UAAW,EAAK,MAAM,EAAgB,CACpC,SAAU,EACV,SAAA,EACA,YAAa,4CACf,CAAC,CACH,EACA,CAAE,qBAAsB,EAAM,CAChC"}
@@ -1,2 +0,0 @@
1
- const e=4e3,t=[`option`,`custom`,`multi`];function n(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function r(t){if(typeof t!=`string`)return;let n=t.trim();return n===``?void 0:n.slice(0,e)}function i(i,a,o){if(!n(i))return`an answer was not an object`;let s=i.questionIndex;if(typeof s!=`number`||!Number.isInteger(s))return`an answer carried no question index`;let c=a.questions[s];if(c===void 0)return`no question ${String(s)} was asked`;if(o.has(s))return`question ${String(s)} was answered twice`;o.add(s);let l=i.kind;if(typeof l!=`string`||!t.includes(l))return`question ${String(s)} carried an unknown answer kind`;let u=r(i.notes),d={questionIndex:s,question:c.question,...u===void 0?{}:{notes:u}};if(l===`multi`){let e=i.selected;if(!Array.isArray(e))return`question ${String(s)} selected nothing readable`;let t=e.filter(e=>typeof e==`string`);return t.length===e.length?t.some(e=>!c.options.some(t=>t.label===e))?`question ${String(s)} selected an option it was not offered`:{...d,kind:`multi`,answer:null,selected:[...new Set(t)]}:`question ${String(s)} selected a non-label`}if(l===`option`){let e=i.answer,t=typeof e==`string`?c.options.find(t=>t.label===e):void 0;return t===void 0?`question ${String(s)} chose an option it was not offered`:{...d,kind:`option`,answer:t.label,...t.preview?{preview:t.preview}:{}}}let f=i.answer;return typeof f==`string`?{...d,kind:`custom`,answer:f.slice(0,e)}:`question ${String(s)} typed nothing readable`}function a(e,t){if(!n(e)||!Array.isArray(e.answers)||e.answers.length===0)return{ok:!1,reason:`no answers were carried`};if(e.answers.length>t.questions.length)return{ok:!1,reason:`more answers than questions`};let r=new Set,a=[];for(let n of e.answers){let e=i(n,t,r);if(typeof e==`string`)return{ok:!1,reason:e};a.push(e)}return a.sort((e,t)=>e.questionIndex-t.questionIndex),{ok:!0,answers:a}}exports.MAX_ANSWER_TEXT_LENGTH=e,exports.readAnswerEnvelope=a;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/services/answerEnvelope/index.ts"],"sourcesContent":["import type { QuestionData, QuestionParams } from '../../schemas/questionnaire';\nimport type { AnswerKind, QuestionAnswer } from '../../types/questionnaire';\n\n/**\n * Read a whole-questionnaire answer envelope back against the questions it claims to answer.\n *\n * The envelope arrives on a select response, which is reader input rather than\n * anything the tool authored, so nothing in it is taken on trust: an index has\n * to name a question that was asked, a chosen label has to be one that\n * question offered, and free text is capped. An envelope that fails is refused\n * rather than repaired, because a half-read answer set reaches the model as\n * the reader's decision and there is no way to tell from there that part of it\n * was invented.\n *\n * `preview` is the clearest case: it is read from the option the tool\n * declared, never from the wire, so the model cannot be shown a preview that\n * was never offered.\n *\n * Host-neutral by construction: the questions and the payload both arrive as\n * arguments, so the same arguments always produce the same result.\n */\nexport const MAX_ANSWER_TEXT_LENGTH = 4000;\n\nexport type AnswerEnvelopeResult =\n | { readonly ok: true; readonly answers: QuestionAnswer[] }\n | { readonly ok: false; readonly reason: string };\n\nconst ANSWER_KINDS: readonly string[] = ['option', 'custom', 'multi'] satisfies readonly AnswerKind[];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction optionalNote(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed === '' ? undefined : trimmed.slice(0, MAX_ANSWER_TEXT_LENGTH);\n}\n\n/** One answer, rebuilt from the question it names rather than copied off the wire. */\nfunction readAnswer(entry: unknown, params: QuestionParams, seen: Set<number>): QuestionAnswer | string {\n if (!isRecord(entry)) return 'an answer was not an object';\n const questionIndex = entry.questionIndex;\n if (typeof questionIndex !== 'number' || !Number.isInteger(questionIndex)) {\n return 'an answer carried no question index';\n }\n const question: QuestionData | undefined = params.questions[questionIndex];\n if (question === undefined) return `no question ${String(questionIndex)} was asked`;\n if (seen.has(questionIndex)) return `question ${String(questionIndex)} was answered twice`;\n seen.add(questionIndex);\n\n const kind = entry.kind;\n if (typeof kind !== 'string' || !ANSWER_KINDS.includes(kind)) {\n return `question ${String(questionIndex)} carried an unknown answer kind`;\n }\n const notes = optionalNote(entry.notes);\n const base = { questionIndex, question: question.question, ...(notes === undefined ? {} : { notes }) };\n\n if (kind === 'multi') {\n const selected = entry.selected;\n if (!Array.isArray(selected)) return `question ${String(questionIndex)} selected nothing readable`;\n const labels = selected.filter((label): label is string => typeof label === 'string');\n if (labels.length !== selected.length) return `question ${String(questionIndex)} selected a non-label`;\n if (labels.some((label) => !question.options.some((option) => option.label === label))) {\n return `question ${String(questionIndex)} selected an option it was not offered`;\n }\n return { ...base, kind: 'multi', answer: null, selected: [...new Set(labels)] };\n }\n\n if (kind === 'option') {\n const label = entry.answer;\n const chosen = typeof label === 'string' ? question.options.find((option) => option.label === label) : undefined;\n if (chosen === undefined) return `question ${String(questionIndex)} chose an option it was not offered`;\n // From the option the tool declared, so a preview the reader never saw\n // cannot be put in the model's mouth.\n return { ...base, kind: 'option', answer: chosen.label, ...(chosen.preview ? { preview: chosen.preview } : {}) };\n }\n\n const typed = entry.answer;\n if (typeof typed !== 'string') return `question ${String(questionIndex)} typed nothing readable`;\n return { ...base, kind: 'custom', answer: typed.slice(0, MAX_ANSWER_TEXT_LENGTH) };\n}\n\nexport function readAnswerEnvelope(payload: unknown, params: QuestionParams): AnswerEnvelopeResult {\n if (!isRecord(payload) || !Array.isArray(payload.answers)) return { ok: false, reason: 'no answers were carried' };\n if (payload.answers.length === 0) return { ok: false, reason: 'no answers were carried' };\n if (payload.answers.length > params.questions.length) return { ok: false, reason: 'more answers than questions' };\n\n const seen = new Set<number>();\n const answers: QuestionAnswer[] = [];\n for (const entry of payload.answers) {\n const answer = readAnswer(entry, params, seen);\n if (typeof answer === 'string') return { ok: false, reason: answer };\n answers.push(answer);\n }\n // The model reads them in the order it asked, whatever order they arrived in.\n answers.sort((left, right) => left.questionIndex - right.questionIndex);\n return { ok: true, answers };\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- const e=4e3,t=[`option`,`custom`,`multi`];function n(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function r(t){if(typeof t!=`string`)return;let n=t.trim();return n===``?void 0:n.slice(0,e)}function i(i,a,o){if(!n(i))return`an answer was not an object`;let s=i.questionIndex;if(typeof s!=`number`||!Number.isInteger(s))return`an answer carried no question index`;let c=a.questions[s];if(c===void 0)return`no question ${String(s)} was asked`;if(o.has(s))return`question ${String(s)} was answered twice`;o.add(s);let l=i.kind;if(typeof l!=`string`||!t.includes(l))return`question ${String(s)} carried an unknown answer kind`;let u=r(i.notes),d={questionIndex:s,question:c.question,...u===void 0?{}:{notes:u}};if(l===`multi`){let e=i.selected;if(!Array.isArray(e))return`question ${String(s)} selected nothing readable`;let t=e.filter(e=>typeof e==`string`);return t.length===e.length?t.some(e=>!c.options.some(t=>t.label===e))?`question ${String(s)} selected an option it was not offered`:{...d,kind:`multi`,answer:null,selected:[...new Set(t)]}:`question ${String(s)} selected a non-label`}if(l===`option`){let e=i.answer,t=typeof e==`string`?c.options.find(t=>t.label===e):void 0;return t===void 0?`question ${String(s)} chose an option it was not offered`:{...d,kind:`option`,answer:t.label,...t.preview?{preview:t.preview}:{}}}let f=i.answer;return typeof f==`string`?{...d,kind:`custom`,answer:f.slice(0,e)}:`question ${String(s)} typed nothing readable`}function a(e,t){if(!n(e)||!Array.isArray(e.answers)||e.answers.length===0)return{ok:!1,reason:`no answers were carried`};if(e.answers.length>t.questions.length)return{ok:!1,reason:`more answers than questions`};let r=new Set,a=[];for(let n of e.answers){let e=i(n,t,r);if(typeof e==`string`)return{ok:!1,reason:e};a.push(e)}return a.sort((e,t)=>e.questionIndex-t.questionIndex),{ok:!0,answers:a}}export{e as MAX_ANSWER_TEXT_LENGTH,a as readAnswerEnvelope};
2
- //# sourceMappingURL=index.mjs.map