cuelo 0.10.64 → 0.10.65

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 (353) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +28 -30
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/required-server-files.js +1 -1
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/routes-manifest.json +0 -14
  8. package/.next/server/app/_global-error/page.js +3 -3
  9. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/server/app/_global-error.html +1 -1
  11. package/.next/server/app/_global-error.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/server/app/_not-found/page.js +2 -2
  19. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/server/app/_not-found.html +1 -1
  21. package/.next/server/app/_not-found.rsc +2 -2
  22. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  23. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  24. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  25. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  26. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  27. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  28. package/.next/server/app/api/agent/[id]/account/route.js +1 -1
  29. package/.next/server/app/api/agent/[id]/bash-output/route.js +1 -1
  30. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  31. package/.next/server/app/api/agent/[id]/route.js +1 -1
  32. package/.next/server/app/api/agent/new/route.js +1 -1
  33. package/.next/server/app/api/agent/running/route.js +1 -1
  34. package/.next/server/app/api/attachment-settings/route.js +1 -1
  35. package/.next/server/app/api/attachments/[id]/transcription/route.js +2 -2
  36. package/.next/server/app/api/attachments/draft/route.js +1 -1
  37. package/.next/server/app/api/attachments/route.js +2 -2
  38. package/.next/server/app/api/auth/all-providers/route.js +1 -1
  39. package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
  40. package/.next/server/app/api/auth/login/[provider]/route.js +1 -1
  41. package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
  42. package/.next/server/app/api/auth/providers/route.js +1 -1
  43. package/.next/server/app/api/cwd/browse/route.js +1 -1
  44. package/.next/server/app/api/cwd/validate/route.js +1 -1
  45. package/.next/server/app/api/default-cwd/route.js +1 -1
  46. package/.next/server/app/api/display-settings/route.js +1 -1
  47. package/.next/server/app/api/document-text/route.js +1 -1
  48. package/.next/server/app/api/experiments/route.js +1 -1
  49. package/.next/server/app/api/file-index/route.js +1 -1
  50. package/.next/server/app/api/files/[...path]/route.js +1 -1
  51. package/.next/server/app/api/git/diff/route.js +1 -1
  52. package/.next/server/app/api/git/status/route.js +2 -2
  53. package/.next/server/app/api/github/projects/route.js +1 -1
  54. package/.next/server/app/api/gpt6/handles/route.js +1 -1
  55. package/.next/server/app/api/gpt6/reply/route.js +1 -1
  56. package/.next/server/app/api/gpt6/token/route.js +1 -1
  57. package/.next/server/app/api/gpt6/web6-session/route.js +1 -1
  58. package/.next/server/app/api/home/route.js +1 -1
  59. package/.next/server/app/api/live/call/[callId]/route.js +2 -2
  60. package/.next/server/app/api/live/events/route.js +1 -1
  61. package/.next/server/app/api/live/interpret/route.js +2 -2
  62. package/.next/server/app/api/live/offer/route.js +1 -1
  63. package/.next/server/app/api/live/voices/route.js +1 -1
  64. package/.next/server/app/api/mcp/route.js +2 -2
  65. package/.next/server/app/api/model-roles/route.js +1 -1
  66. package/.next/server/app/api/models/route.js +1 -1
  67. package/.next/server/app/api/models-config/catalog/route.js +1 -1
  68. package/.next/server/app/api/models-config/discover/route.js +1 -1
  69. package/.next/server/app/api/models-config/route.js +3 -3
  70. package/.next/server/app/api/models-config/test/route.js +1 -1
  71. package/.next/server/app/api/plugins/route.js +1 -1
  72. package/.next/server/app/api/project-docs/route.js +1 -1
  73. package/.next/server/app/api/project-trust/route.js +1 -1
  74. package/.next/server/app/api/projects/route.js +2 -2
  75. package/.next/server/app/api/runs/[runId]/prelude/route.js +1 -1
  76. package/.next/server/app/api/runs/[runId]/route.js +1 -1
  77. package/.next/server/app/api/runs/[runId]/turns/route.js +1 -1
  78. package/.next/server/app/api/runs/route.js +1 -1
  79. package/.next/server/app/api/sessions/[id]/auto-name/route.js +1 -1
  80. package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
  81. package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +1 -1
  82. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  83. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  84. package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
  85. package/.next/server/app/api/sessions/route.js +1 -1
  86. package/.next/server/app/api/sessions/search/route.js +1 -1
  87. package/.next/server/app/api/settings/route.js +1 -1
  88. package/.next/server/app/api/sidecars/[service]/[...path]/route.js +1 -1
  89. package/.next/server/app/api/skills/check/route.js +1 -1
  90. package/.next/server/app/api/skills/install/route.js +2 -2
  91. package/.next/server/app/api/skills/route.js +1 -1
  92. package/.next/server/app/api/skills/search/route.js +1 -1
  93. package/.next/server/app/api/skills/update/route.js +1 -1
  94. package/.next/server/app/api/subagents/eta/route.js +1 -1
  95. package/.next/server/app/api/theme/route.js +1 -1
  96. package/.next/server/app/api/tool-image/route.js +1 -1
  97. package/.next/server/app/api/update-maintenance/route.js +2 -2
  98. package/.next/server/app/api/updates/route.js +1 -1
  99. package/.next/server/app/api/web-access/recovery/route.js +1 -1
  100. package/.next/server/app/api/web-access/route.js +1 -1
  101. package/.next/server/app/api/web6/consults/route.js +1 -1
  102. package/.next/server/app/api/worktrees/route.js +1 -1
  103. package/.next/server/app/favicon.ico/route.js +1 -1
  104. package/.next/server/app/index.html +1 -1
  105. package/.next/server/app/index.rsc +4 -4
  106. package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
  107. package/.next/server/app/index.segments/_full.segment.rsc +4 -4
  108. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  109. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  110. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  111. package/.next/server/app/manifest.webmanifest/route.js +2 -2
  112. package/.next/server/app/page.js +20 -20
  113. package/.next/server/app/page_client-reference-manifest.js +1 -1
  114. package/.next/server/app/recover/page.js +2 -2
  115. package/.next/server/app/recover/page_client-reference-manifest.js +1 -1
  116. package/.next/server/app/recover.html +1 -1
  117. package/.next/server/app/recover.rsc +2 -2
  118. package/.next/server/app/recover.segments/_full.segment.rsc +2 -2
  119. package/.next/server/app/recover.segments/_head.segment.rsc +1 -1
  120. package/.next/server/app/recover.segments/_index.segment.rsc +2 -2
  121. package/.next/server/app/recover.segments/_tree.segment.rsc +1 -1
  122. package/.next/server/app/recover.segments/recover/__PAGE__.segment.rsc +1 -1
  123. package/.next/server/app/recover.segments/recover.segment.rsc +1 -1
  124. package/.next/server/app-paths-manifest.json +28 -30
  125. package/.next/server/chunks/6775.js +1 -1
  126. package/.next/server/functions-config-manifest.json +0 -2
  127. package/.next/server/middleware-build-manifest.js +1 -1
  128. package/.next/server/pages/404.html +1 -1
  129. package/.next/server/pages/500.html +1 -1
  130. package/.next/server/server-reference-manifest.json +1 -1
  131. package/.next/static/chunks/app/_global-error/page-0975ca1ea02edd84.js +1 -0
  132. package/.next/static/chunks/app/api/agent/[id]/account/route-0975ca1ea02edd84.js +1 -0
  133. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-0975ca1ea02edd84.js +1 -0
  134. package/.next/static/chunks/app/api/agent/[id]/events/route-0975ca1ea02edd84.js +1 -0
  135. package/.next/static/chunks/app/api/agent/[id]/route-0975ca1ea02edd84.js +1 -0
  136. package/.next/static/chunks/app/api/agent/new/route-0975ca1ea02edd84.js +1 -0
  137. package/.next/static/chunks/app/api/agent/running/route-0975ca1ea02edd84.js +1 -0
  138. package/.next/static/chunks/app/api/attachment-settings/route-0975ca1ea02edd84.js +1 -0
  139. package/.next/static/chunks/app/api/attachments/[id]/transcription/route-0975ca1ea02edd84.js +1 -0
  140. package/.next/static/chunks/app/api/attachments/draft/route-0975ca1ea02edd84.js +1 -0
  141. package/.next/static/chunks/app/api/attachments/route-0975ca1ea02edd84.js +1 -0
  142. package/.next/static/chunks/app/api/auth/all-providers/route-0975ca1ea02edd84.js +1 -0
  143. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-0975ca1ea02edd84.js +1 -0
  144. package/.next/static/chunks/app/api/auth/login/[provider]/route-0975ca1ea02edd84.js +1 -0
  145. package/.next/static/chunks/app/api/auth/logout/[provider]/route-0975ca1ea02edd84.js +1 -0
  146. package/.next/static/chunks/app/api/auth/providers/route-0975ca1ea02edd84.js +1 -0
  147. package/.next/static/chunks/app/api/cwd/browse/route-0975ca1ea02edd84.js +1 -0
  148. package/.next/static/chunks/app/api/cwd/validate/route-0975ca1ea02edd84.js +1 -0
  149. package/.next/static/chunks/app/api/default-cwd/route-0975ca1ea02edd84.js +1 -0
  150. package/.next/static/chunks/app/api/display-settings/route-0975ca1ea02edd84.js +1 -0
  151. package/.next/static/chunks/app/api/document-text/route-0975ca1ea02edd84.js +1 -0
  152. package/.next/static/chunks/app/api/experiments/route-0975ca1ea02edd84.js +1 -0
  153. package/.next/static/chunks/app/api/file-index/route-0975ca1ea02edd84.js +1 -0
  154. package/.next/static/chunks/app/api/files/[...path]/route-0975ca1ea02edd84.js +1 -0
  155. package/.next/static/chunks/app/api/git/diff/route-0975ca1ea02edd84.js +1 -0
  156. package/.next/static/chunks/app/api/git/status/route-0975ca1ea02edd84.js +1 -0
  157. package/.next/static/chunks/app/api/github/projects/route-0975ca1ea02edd84.js +1 -0
  158. package/.next/static/chunks/app/api/gpt6/handles/route-0975ca1ea02edd84.js +1 -0
  159. package/.next/static/chunks/app/api/gpt6/reply/route-0975ca1ea02edd84.js +1 -0
  160. package/.next/static/chunks/app/api/gpt6/token/route-0975ca1ea02edd84.js +1 -0
  161. package/.next/static/chunks/app/api/gpt6/web6-session/route-0975ca1ea02edd84.js +1 -0
  162. package/.next/static/chunks/app/api/home/route-0975ca1ea02edd84.js +1 -0
  163. package/.next/static/chunks/app/api/live/call/[callId]/route-0975ca1ea02edd84.js +1 -0
  164. package/.next/static/chunks/app/api/live/events/route-0975ca1ea02edd84.js +1 -0
  165. package/.next/static/chunks/app/api/live/interpret/route-0975ca1ea02edd84.js +1 -0
  166. package/.next/static/chunks/app/api/live/offer/route-0975ca1ea02edd84.js +1 -0
  167. package/.next/static/chunks/app/api/live/voices/route-0975ca1ea02edd84.js +1 -0
  168. package/.next/static/chunks/app/api/mcp/route-0975ca1ea02edd84.js +1 -0
  169. package/.next/static/chunks/app/api/model-roles/route-0975ca1ea02edd84.js +1 -0
  170. package/.next/static/chunks/app/api/models/route-0975ca1ea02edd84.js +1 -0
  171. package/.next/static/chunks/app/api/models-config/catalog/route-0975ca1ea02edd84.js +1 -0
  172. package/.next/static/chunks/app/api/models-config/discover/route-0975ca1ea02edd84.js +1 -0
  173. package/.next/static/chunks/app/api/models-config/route-0975ca1ea02edd84.js +1 -0
  174. package/.next/static/chunks/app/api/models-config/test/route-0975ca1ea02edd84.js +1 -0
  175. package/.next/static/chunks/app/api/plugins/route-0975ca1ea02edd84.js +1 -0
  176. package/.next/static/chunks/app/api/project-docs/route-0975ca1ea02edd84.js +1 -0
  177. package/.next/static/chunks/app/api/project-trust/route-0975ca1ea02edd84.js +1 -0
  178. package/.next/static/chunks/app/api/projects/route-0975ca1ea02edd84.js +1 -0
  179. package/.next/static/chunks/app/api/runs/[runId]/prelude/route-0975ca1ea02edd84.js +1 -0
  180. package/.next/static/chunks/app/api/runs/[runId]/route-0975ca1ea02edd84.js +1 -0
  181. package/.next/static/chunks/app/api/runs/[runId]/turns/route-0975ca1ea02edd84.js +1 -0
  182. package/.next/static/chunks/app/api/runs/route-0975ca1ea02edd84.js +1 -0
  183. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-0975ca1ea02edd84.js +1 -0
  184. package/.next/static/chunks/app/api/sessions/[id]/context/route-0975ca1ea02edd84.js +1 -0
  185. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-0975ca1ea02edd84.js +1 -0
  186. package/.next/static/chunks/app/api/sessions/[id]/export/route-0975ca1ea02edd84.js +1 -0
  187. package/.next/static/chunks/app/api/sessions/[id]/route-0975ca1ea02edd84.js +1 -0
  188. package/.next/static/chunks/app/api/sessions/[id]/state/route-0975ca1ea02edd84.js +1 -0
  189. package/.next/static/chunks/app/api/sessions/route-0975ca1ea02edd84.js +1 -0
  190. package/.next/static/chunks/app/api/sessions/search/route-0975ca1ea02edd84.js +1 -0
  191. package/.next/static/chunks/app/api/settings/route-0975ca1ea02edd84.js +1 -0
  192. package/.next/static/chunks/app/api/sidecars/[service]/[...path]/route-0975ca1ea02edd84.js +1 -0
  193. package/.next/static/chunks/app/api/skills/check/route-0975ca1ea02edd84.js +1 -0
  194. package/.next/static/chunks/app/api/skills/install/route-0975ca1ea02edd84.js +1 -0
  195. package/.next/static/chunks/app/api/skills/route-0975ca1ea02edd84.js +1 -0
  196. package/.next/static/chunks/app/api/skills/search/route-0975ca1ea02edd84.js +1 -0
  197. package/.next/static/chunks/app/api/skills/update/route-0975ca1ea02edd84.js +1 -0
  198. package/.next/static/chunks/app/api/subagents/eta/route-0975ca1ea02edd84.js +1 -0
  199. package/.next/static/chunks/app/api/theme/route-0975ca1ea02edd84.js +1 -0
  200. package/.next/static/chunks/app/api/tool-image/route-0975ca1ea02edd84.js +1 -0
  201. package/.next/static/chunks/app/api/update-maintenance/route-0975ca1ea02edd84.js +1 -0
  202. package/.next/static/chunks/app/api/updates/route-0975ca1ea02edd84.js +1 -0
  203. package/.next/static/chunks/app/api/web-access/recovery/route-0975ca1ea02edd84.js +1 -0
  204. package/.next/static/chunks/app/api/web-access/route-0975ca1ea02edd84.js +1 -0
  205. package/.next/static/chunks/app/api/web6/consults/route-0975ca1ea02edd84.js +1 -0
  206. package/.next/static/chunks/app/api/worktrees/route-0975ca1ea02edd84.js +1 -0
  207. package/.next/static/chunks/app/{layout-8098cf3ae16b7456.js → layout-5b0d76fcb181906f.js} +1 -1
  208. package/.next/static/chunks/app/manifest.webmanifest/route-0975ca1ea02edd84.js +1 -0
  209. package/.next/static/chunks/app/page-337a29e82bebbc7e.js +74 -0
  210. package/.next/static/chunks/next/dist/client/components/builtin/app-error-0975ca1ea02edd84.js +1 -0
  211. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-0975ca1ea02edd84.js +1 -0
  212. package/.next/static/chunks/next/dist/client/components/builtin/not-found-0975ca1ea02edd84.js +1 -0
  213. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-0975ca1ea02edd84.js +1 -0
  214. package/.next/static/ppnj2ZRAoM1bAhcoG2F-v/_buildManifest.js +1 -0
  215. package/.next/trace +108 -108
  216. package/.next/trace-build +1 -1
  217. package/.next/types/routes.d.ts +1 -3
  218. package/.next/types/validator.ts +0 -18
  219. package/README.md +2 -3
  220. package/Tools/CUELO_Setup/files/native-runtime-patch.js +1 -1
  221. package/Tools/OMP_Global_Config/agent/AGENTS.md +1 -3
  222. package/Tools/OMP_Global_Config/agent/extensions/character-voice.ts +41 -229
  223. package/Tools/OMP_Global_Config/agent/prompt-copies/AGENTS.en.md +2 -4
  224. package/Tools/OMP_Global_Config/agent/rules/harness-policy.json +1 -2
  225. package/package.json +1 -1
  226. package/public/audio/completion/voices.json +96 -95
  227. package/.next/server/app/api/character-mode/route.js +0 -1
  228. package/.next/server/app/api/character-mode/route.js.nft.json +0 -1
  229. package/.next/server/app/api/character-mode/route_client-reference-manifest.js +0 -1
  230. package/.next/server/app/api/office-characters/[...path]/route.js +0 -1
  231. package/.next/server/app/api/office-characters/[...path]/route.js.nft.json +0 -1
  232. package/.next/server/app/api/office-characters/[...path]/route_client-reference-manifest.js +0 -1
  233. package/.next/server/chunks/1966.js +0 -2
  234. package/.next/static/_jvVAFFZ2I5elmu3hRLde/_buildManifest.js +0 -1
  235. package/.next/static/chunks/app/_global-error/page-6920e3509ecbcb1e.js +0 -1
  236. package/.next/static/chunks/app/api/agent/[id]/account/route-6920e3509ecbcb1e.js +0 -1
  237. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-6920e3509ecbcb1e.js +0 -1
  238. package/.next/static/chunks/app/api/agent/[id]/events/route-6920e3509ecbcb1e.js +0 -1
  239. package/.next/static/chunks/app/api/agent/[id]/route-6920e3509ecbcb1e.js +0 -1
  240. package/.next/static/chunks/app/api/agent/new/route-6920e3509ecbcb1e.js +0 -1
  241. package/.next/static/chunks/app/api/agent/running/route-6920e3509ecbcb1e.js +0 -1
  242. package/.next/static/chunks/app/api/attachment-settings/route-6920e3509ecbcb1e.js +0 -1
  243. package/.next/static/chunks/app/api/attachments/[id]/transcription/route-6920e3509ecbcb1e.js +0 -1
  244. package/.next/static/chunks/app/api/attachments/draft/route-6920e3509ecbcb1e.js +0 -1
  245. package/.next/static/chunks/app/api/attachments/route-6920e3509ecbcb1e.js +0 -1
  246. package/.next/static/chunks/app/api/auth/all-providers/route-6920e3509ecbcb1e.js +0 -1
  247. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-6920e3509ecbcb1e.js +0 -1
  248. package/.next/static/chunks/app/api/auth/login/[provider]/route-6920e3509ecbcb1e.js +0 -1
  249. package/.next/static/chunks/app/api/auth/logout/[provider]/route-6920e3509ecbcb1e.js +0 -1
  250. package/.next/static/chunks/app/api/auth/providers/route-6920e3509ecbcb1e.js +0 -1
  251. package/.next/static/chunks/app/api/character-mode/route-6920e3509ecbcb1e.js +0 -1
  252. package/.next/static/chunks/app/api/cwd/browse/route-6920e3509ecbcb1e.js +0 -1
  253. package/.next/static/chunks/app/api/cwd/validate/route-6920e3509ecbcb1e.js +0 -1
  254. package/.next/static/chunks/app/api/default-cwd/route-6920e3509ecbcb1e.js +0 -1
  255. package/.next/static/chunks/app/api/display-settings/route-6920e3509ecbcb1e.js +0 -1
  256. package/.next/static/chunks/app/api/document-text/route-6920e3509ecbcb1e.js +0 -1
  257. package/.next/static/chunks/app/api/experiments/route-6920e3509ecbcb1e.js +0 -1
  258. package/.next/static/chunks/app/api/file-index/route-6920e3509ecbcb1e.js +0 -1
  259. package/.next/static/chunks/app/api/files/[...path]/route-6920e3509ecbcb1e.js +0 -1
  260. package/.next/static/chunks/app/api/git/diff/route-6920e3509ecbcb1e.js +0 -1
  261. package/.next/static/chunks/app/api/git/status/route-6920e3509ecbcb1e.js +0 -1
  262. package/.next/static/chunks/app/api/github/projects/route-6920e3509ecbcb1e.js +0 -1
  263. package/.next/static/chunks/app/api/gpt6/handles/route-6920e3509ecbcb1e.js +0 -1
  264. package/.next/static/chunks/app/api/gpt6/reply/route-6920e3509ecbcb1e.js +0 -1
  265. package/.next/static/chunks/app/api/gpt6/token/route-6920e3509ecbcb1e.js +0 -1
  266. package/.next/static/chunks/app/api/gpt6/web6-session/route-6920e3509ecbcb1e.js +0 -1
  267. package/.next/static/chunks/app/api/home/route-6920e3509ecbcb1e.js +0 -1
  268. package/.next/static/chunks/app/api/live/call/[callId]/route-6920e3509ecbcb1e.js +0 -1
  269. package/.next/static/chunks/app/api/live/events/route-6920e3509ecbcb1e.js +0 -1
  270. package/.next/static/chunks/app/api/live/interpret/route-6920e3509ecbcb1e.js +0 -1
  271. package/.next/static/chunks/app/api/live/offer/route-6920e3509ecbcb1e.js +0 -1
  272. package/.next/static/chunks/app/api/live/voices/route-6920e3509ecbcb1e.js +0 -1
  273. package/.next/static/chunks/app/api/mcp/route-6920e3509ecbcb1e.js +0 -1
  274. package/.next/static/chunks/app/api/model-roles/route-6920e3509ecbcb1e.js +0 -1
  275. package/.next/static/chunks/app/api/models/route-6920e3509ecbcb1e.js +0 -1
  276. package/.next/static/chunks/app/api/models-config/catalog/route-6920e3509ecbcb1e.js +0 -1
  277. package/.next/static/chunks/app/api/models-config/discover/route-6920e3509ecbcb1e.js +0 -1
  278. package/.next/static/chunks/app/api/models-config/route-6920e3509ecbcb1e.js +0 -1
  279. package/.next/static/chunks/app/api/models-config/test/route-6920e3509ecbcb1e.js +0 -1
  280. package/.next/static/chunks/app/api/office-characters/[...path]/route-6920e3509ecbcb1e.js +0 -1
  281. package/.next/static/chunks/app/api/plugins/route-6920e3509ecbcb1e.js +0 -1
  282. package/.next/static/chunks/app/api/project-docs/route-6920e3509ecbcb1e.js +0 -1
  283. package/.next/static/chunks/app/api/project-trust/route-6920e3509ecbcb1e.js +0 -1
  284. package/.next/static/chunks/app/api/projects/route-6920e3509ecbcb1e.js +0 -1
  285. package/.next/static/chunks/app/api/runs/[runId]/prelude/route-6920e3509ecbcb1e.js +0 -1
  286. package/.next/static/chunks/app/api/runs/[runId]/route-6920e3509ecbcb1e.js +0 -1
  287. package/.next/static/chunks/app/api/runs/[runId]/turns/route-6920e3509ecbcb1e.js +0 -1
  288. package/.next/static/chunks/app/api/runs/route-6920e3509ecbcb1e.js +0 -1
  289. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-6920e3509ecbcb1e.js +0 -1
  290. package/.next/static/chunks/app/api/sessions/[id]/context/route-6920e3509ecbcb1e.js +0 -1
  291. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-6920e3509ecbcb1e.js +0 -1
  292. package/.next/static/chunks/app/api/sessions/[id]/export/route-6920e3509ecbcb1e.js +0 -1
  293. package/.next/static/chunks/app/api/sessions/[id]/route-6920e3509ecbcb1e.js +0 -1
  294. package/.next/static/chunks/app/api/sessions/[id]/state/route-6920e3509ecbcb1e.js +0 -1
  295. package/.next/static/chunks/app/api/sessions/route-6920e3509ecbcb1e.js +0 -1
  296. package/.next/static/chunks/app/api/sessions/search/route-6920e3509ecbcb1e.js +0 -1
  297. package/.next/static/chunks/app/api/settings/route-6920e3509ecbcb1e.js +0 -1
  298. package/.next/static/chunks/app/api/sidecars/[service]/[...path]/route-6920e3509ecbcb1e.js +0 -1
  299. package/.next/static/chunks/app/api/skills/check/route-6920e3509ecbcb1e.js +0 -1
  300. package/.next/static/chunks/app/api/skills/install/route-6920e3509ecbcb1e.js +0 -1
  301. package/.next/static/chunks/app/api/skills/route-6920e3509ecbcb1e.js +0 -1
  302. package/.next/static/chunks/app/api/skills/search/route-6920e3509ecbcb1e.js +0 -1
  303. package/.next/static/chunks/app/api/skills/update/route-6920e3509ecbcb1e.js +0 -1
  304. package/.next/static/chunks/app/api/subagents/eta/route-6920e3509ecbcb1e.js +0 -1
  305. package/.next/static/chunks/app/api/theme/route-6920e3509ecbcb1e.js +0 -1
  306. package/.next/static/chunks/app/api/tool-image/route-6920e3509ecbcb1e.js +0 -1
  307. package/.next/static/chunks/app/api/update-maintenance/route-6920e3509ecbcb1e.js +0 -1
  308. package/.next/static/chunks/app/api/updates/route-6920e3509ecbcb1e.js +0 -1
  309. package/.next/static/chunks/app/api/web-access/recovery/route-6920e3509ecbcb1e.js +0 -1
  310. package/.next/static/chunks/app/api/web-access/route-6920e3509ecbcb1e.js +0 -1
  311. package/.next/static/chunks/app/api/web6/consults/route-6920e3509ecbcb1e.js +0 -1
  312. package/.next/static/chunks/app/api/worktrees/route-6920e3509ecbcb1e.js +0 -1
  313. package/.next/static/chunks/app/manifest.webmanifest/route-6920e3509ecbcb1e.js +0 -1
  314. package/.next/static/chunks/app/page-76c2b89618aa9bf9.js +0 -74
  315. package/.next/static/chunks/next/dist/client/components/builtin/app-error-6920e3509ecbcb1e.js +0 -1
  316. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-6920e3509ecbcb1e.js +0 -1
  317. package/.next/static/chunks/next/dist/client/components/builtin/not-found-6920e3509ecbcb1e.js +0 -1
  318. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6920e3509ecbcb1e.js +0 -1
  319. package/.next/types/app/api/character-mode/route.ts +0 -351
  320. package/.next/types/app/api/office-characters/[...path]/route.ts +0 -351
  321. package/public/audio/completion/nova/01.wav +0 -0
  322. package/public/audio/completion/nova/02.wav +0 -0
  323. package/public/audio/completion/nova/03.wav +0 -0
  324. package/public/audio/completion/nova/04.wav +0 -0
  325. package/public/audio/completion/nova/05.wav +0 -0
  326. package/public/audio/completion/nova/06.wav +0 -0
  327. package/public/audio/completion/nova/approval/01.wav +0 -0
  328. package/public/audio/completion/nova/approval/02.wav +0 -0
  329. package/public/audio/completion/nova/approval/03.wav +0 -0
  330. package/public/audio/completion/nova/choice/01.wav +0 -0
  331. package/public/audio/completion/nova/choice/02.wav +0 -0
  332. package/public/audio/completion/nova/choice/03.wav +0 -0
  333. package/public/audio/completion/nova/failed/01.wav +0 -0
  334. package/public/audio/completion/nova/failed/02.wav +0 -0
  335. package/public/audio/completion/nova/failed/03.wav +0 -0
  336. package/public/audio/completion/nova/working/01.wav +0 -0
  337. package/public/audio/completion/nova/working/02.wav +0 -0
  338. package/public/audio/completion/nova/working/03.wav +0 -0
  339. package/public/avatars/nova.webp +0 -0
  340. package/public/stickers/nova/approval/01.webp +0 -0
  341. package/public/stickers/nova/approval/02.webp +0 -0
  342. package/public/stickers/nova/approval/03.webp +0 -0
  343. package/public/stickers/nova/choice/01.webp +0 -0
  344. package/public/stickers/nova/choice/02.webp +0 -0
  345. package/public/stickers/nova/choice/03.webp +0 -0
  346. package/public/stickers/nova/done/01.webp +0 -0
  347. package/public/stickers/nova/done/02.webp +0 -0
  348. package/public/stickers/nova/done/03.webp +0 -0
  349. package/public/stickers/nova/failed/01.webp +0 -0
  350. package/public/stickers/nova/failed/02.webp +0 -0
  351. package/public/stickers/nova/failed/03.webp +0 -0
  352. package/public/stickers/nova/working/01.webp +0 -0
  353. /package/.next/static/{_jvVAFFZ2I5elmu3hRLde → ppnj2ZRAoM1bAhcoG2F-v}/_ssgManifest.js +0 -0
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-webpack","duration":86577662,"timestamp":497860,"id":14,"parentId":1,"tags":{},"startTime":1792770308814,"traceId":"f24f5b92a107328b"},{"name":"run-typescript","duration":18728528,"timestamp":87445314,"id":11027,"parentId":1,"tags":{},"startTime":1792770395762,"traceId":"f24f5b92a107328b"},{"name":"static-check","duration":3368999,"timestamp":106252343,"id":11030,"parentId":1,"tags":{},"startTime":1792770414569,"traceId":"f24f5b92a107328b"},{"name":"static-generation","duration":9101298,"timestamp":109710200,"id":11202,"parentId":1,"tags":{},"startTime":1792770418027,"traceId":"f24f5b92a107328b"},{"name":"collect-build-traces","duration":18935947,"timestamp":109688612,"id":11199,"parentId":1,"tags":{},"startTime":1792770418005,"traceId":"f24f5b92a107328b"},{"name":"telemetry-flush","duration":72,"timestamp":128628906,"id":11211,"parentId":1,"tags":{},"startTime":1792770436946,"traceId":"f24f5b92a107328b"},{"name":"next-build","duration":128213521,"timestamp":415480,"id":1,"tags":{"buildMode":"default","version":"16.2.12","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1792770308732,"traceId":"f24f5b92a107328b"}]
1
+ [{"name":"run-webpack","duration":64939044,"timestamp":390610,"id":14,"parentId":1,"tags":{},"startTime":1792795506099,"traceId":"da118ad04cc38e86"},{"name":"run-typescript","duration":13493734,"timestamp":65741166,"id":11002,"parentId":1,"tags":{},"startTime":1792795571449,"traceId":"da118ad04cc38e86"},{"name":"static-check","duration":2547782,"timestamp":79299651,"id":11005,"parentId":1,"tags":{},"startTime":1792795585008,"traceId":"da118ad04cc38e86"},{"name":"static-generation","duration":6922248,"timestamp":81921578,"id":11173,"parentId":1,"tags":{},"startTime":1792795587629,"traceId":"da118ad04cc38e86"},{"name":"collect-build-traces","duration":14515193,"timestamp":81904709,"id":11170,"parentId":1,"tags":{},"startTime":1792795587613,"traceId":"da118ad04cc38e86"},{"name":"telemetry-flush","duration":52,"timestamp":96423025,"id":11182,"parentId":1,"tags":{},"startTime":1792795602131,"traceId":"da118ad04cc38e86"},{"name":"next-build","duration":96095572,"timestamp":327520,"id":1,"tags":{"buildMode":"default","version":"16.2.12","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1792795506035,"traceId":"da118ad04cc38e86"}]
@@ -2,7 +2,7 @@
2
2
  // Do not edit this file manually
3
3
 
4
4
  type AppRoutes = "/" | "/recover"
5
- type AppRouteHandlerRoutes = "/api/agent/[id]" | "/api/agent/[id]/account" | "/api/agent/[id]/bash-output" | "/api/agent/[id]/events" | "/api/agent/new" | "/api/agent/running" | "/api/attachment-settings" | "/api/attachments" | "/api/attachments/[id]/transcription" | "/api/attachments/draft" | "/api/auth/all-providers" | "/api/auth/api-key/[provider]" | "/api/auth/login/[provider]" | "/api/auth/logout/[provider]" | "/api/auth/providers" | "/api/character-mode" | "/api/cwd/browse" | "/api/cwd/validate" | "/api/default-cwd" | "/api/display-settings" | "/api/document-text" | "/api/experiments" | "/api/file-index" | "/api/files/[...path]" | "/api/git/diff" | "/api/git/status" | "/api/github/projects" | "/api/gpt6/handles" | "/api/gpt6/reply" | "/api/gpt6/token" | "/api/gpt6/web6-session" | "/api/home" | "/api/live/call/[callId]" | "/api/live/events" | "/api/live/interpret" | "/api/live/offer" | "/api/live/voices" | "/api/mcp" | "/api/model-roles" | "/api/models" | "/api/models-config" | "/api/models-config/catalog" | "/api/models-config/discover" | "/api/models-config/test" | "/api/office-characters/[...path]" | "/api/plugins" | "/api/project-docs" | "/api/project-trust" | "/api/projects" | "/api/runs" | "/api/runs/[runId]" | "/api/runs/[runId]/prelude" | "/api/runs/[runId]/turns" | "/api/sessions" | "/api/sessions/[id]" | "/api/sessions/[id]/auto-name" | "/api/sessions/[id]/context" | "/api/sessions/[id]/entries/[entryId]/thinking" | "/api/sessions/[id]/export" | "/api/sessions/[id]/state" | "/api/sessions/search" | "/api/settings" | "/api/sidecars/[service]/[...path]" | "/api/skills" | "/api/skills/check" | "/api/skills/install" | "/api/skills/search" | "/api/skills/update" | "/api/subagents/eta" | "/api/theme" | "/api/tool-image" | "/api/update-maintenance" | "/api/updates" | "/api/web-access" | "/api/web-access/recovery" | "/api/web6/consults" | "/api/worktrees"
5
+ type AppRouteHandlerRoutes = "/api/agent/[id]" | "/api/agent/[id]/account" | "/api/agent/[id]/bash-output" | "/api/agent/[id]/events" | "/api/agent/new" | "/api/agent/running" | "/api/attachment-settings" | "/api/attachments" | "/api/attachments/[id]/transcription" | "/api/attachments/draft" | "/api/auth/all-providers" | "/api/auth/api-key/[provider]" | "/api/auth/login/[provider]" | "/api/auth/logout/[provider]" | "/api/auth/providers" | "/api/cwd/browse" | "/api/cwd/validate" | "/api/default-cwd" | "/api/display-settings" | "/api/document-text" | "/api/experiments" | "/api/file-index" | "/api/files/[...path]" | "/api/git/diff" | "/api/git/status" | "/api/github/projects" | "/api/gpt6/handles" | "/api/gpt6/reply" | "/api/gpt6/token" | "/api/gpt6/web6-session" | "/api/home" | "/api/live/call/[callId]" | "/api/live/events" | "/api/live/interpret" | "/api/live/offer" | "/api/live/voices" | "/api/mcp" | "/api/model-roles" | "/api/models" | "/api/models-config" | "/api/models-config/catalog" | "/api/models-config/discover" | "/api/models-config/test" | "/api/plugins" | "/api/project-docs" | "/api/project-trust" | "/api/projects" | "/api/runs" | "/api/runs/[runId]" | "/api/runs/[runId]/prelude" | "/api/runs/[runId]/turns" | "/api/sessions" | "/api/sessions/[id]" | "/api/sessions/[id]/auto-name" | "/api/sessions/[id]/context" | "/api/sessions/[id]/entries/[entryId]/thinking" | "/api/sessions/[id]/export" | "/api/sessions/[id]/state" | "/api/sessions/search" | "/api/settings" | "/api/sidecars/[service]/[...path]" | "/api/skills" | "/api/skills/check" | "/api/skills/install" | "/api/skills/search" | "/api/skills/update" | "/api/subagents/eta" | "/api/theme" | "/api/tool-image" | "/api/update-maintenance" | "/api/updates" | "/api/web-access" | "/api/web-access/recovery" | "/api/web6/consults" | "/api/worktrees"
6
6
  type PageRoutes = never
7
7
  type LayoutRoutes = "/"
8
8
  type RedirectRoutes = never
@@ -27,7 +27,6 @@ interface ParamMap {
27
27
  "/api/auth/login/[provider]": { "provider": string; }
28
28
  "/api/auth/logout/[provider]": { "provider": string; }
29
29
  "/api/auth/providers": {}
30
- "/api/character-mode": {}
31
30
  "/api/cwd/browse": {}
32
31
  "/api/cwd/validate": {}
33
32
  "/api/default-cwd": {}
@@ -56,7 +55,6 @@ interface ParamMap {
56
55
  "/api/models-config/catalog": {}
57
56
  "/api/models-config/discover": {}
58
57
  "/api/models-config/test": {}
59
- "/api/office-characters/[...path]": { "path": string[]; }
60
58
  "/api/plugins": {}
61
59
  "/api/project-docs": {}
62
60
  "/api/project-trust": {}
@@ -200,15 +200,6 @@ type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRou
200
200
  type __Unused = __Check
201
201
  }
202
202
 
203
- // Validate ../../app/api/character-mode/route.ts
204
- {
205
- type __IsExpected<Specific extends RouteHandlerConfig<"/api/character-mode">> = Specific
206
- const handler = {} as typeof import("../../app/api/character-mode/route.js")
207
- type __Check = __IsExpected<typeof handler>
208
- // @ts-ignore
209
- type __Unused = __Check
210
- }
211
-
212
203
  // Validate ../../app/api/cwd/browse/route.ts
213
204
  {
214
205
  type __IsExpected<Specific extends RouteHandlerConfig<"/api/cwd/browse">> = Specific
@@ -461,15 +452,6 @@ type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRou
461
452
  type __Unused = __Check
462
453
  }
463
454
 
464
- // Validate ../../app/api/office-characters/[...path]/route.ts
465
- {
466
- type __IsExpected<Specific extends RouteHandlerConfig<"/api/office-characters/[...path]">> = Specific
467
- const handler = {} as typeof import("../../app/api/office-characters/[...path]/route.js")
468
- type __Check = __IsExpected<typeof handler>
469
- // @ts-ignore
470
- type __Unused = __Check
471
- }
472
-
473
455
  // Validate ../../app/api/plugins/route.ts
474
456
  {
475
457
  type __IsExpected<Specific extends RouteHandlerConfig<"/api/plugins">> = Specific
package/README.md CHANGED
@@ -140,8 +140,7 @@ Anthropic 구독 계정이 모두 주간 한도에 닿으면, 미리 둔 예비
140
140
 
141
141
  **알림과 표현**
142
142
 
143
- - 완료·실패·승인 요청·선택 요청 등 상황에 맞는 캐릭터 스티커와 음성으로 알립니다(RIN · MIO · YUKI · ISANA · NOVA · SHION · HIKARI).
144
- - **설정 → 캐릭터**에서 「기본 / 사무실 모드」를 고르면 PC 서버 전체에 적용됩니다. 사무실 모드는 이 PC의 프로필(`characters-office/`)에 준비한 여러 자리의 얼굴·이름·말투·스티커·알림 음성을 함께 바꿉니다. 세트가 없는 자리는 기본 캐릭터를 쓰며, 각 자리의 모델과 호출 권한은 바뀌지 않습니다. 기본 모드로 돌아가면 기존 캐릭터 이름과 그림을 다시 씁니다.
143
+ - 완료·실패·승인 요청·선택 요청 등 상황에 맞는 캐릭터 스티커와 음성으로 알립니다(RIN · MIO · YUKI · ISANA · MITSU · SHION · HIKARI).
145
144
  - 브라우저 알림과 PWA 설치를 지원합니다.
146
145
  - 직접 저장한 교훈·스킬은 저장한 답변이나 과정 바로 뒤의 카드에서 확인합니다. 교훈 자동 기록을 켠 경우 자동 저장 알림도 작업 과정을 접어도 대화에 남습니다. 요청에 이름이 없고 필요성도 확인되지 않은 MCP 후보는 보류 안내로 나열하지 않습니다.
147
146
  - 교훈 자동 기록의 응답 수·토큰·캐시·보고 비용·소요 시간을 기존 로그에서 확인할 수 있습니다. 본대화의 과거 사용량은 제외하며, 보고되지 않은 값은 0으로 추정하지 않습니다. 모델이나 학습 예산을 자동 변경하지는 않습니다. [하네스 안내](./docs/harness.md)를 참고하세요.
@@ -283,7 +282,7 @@ CUELO는 [@ddallabenetta](https://github.com/ddallabenetta)의 [omp-web](https:/
283
282
 
284
283
  CUELO의 에이전트 엔진은 [omp (oh-my-pi)](https://github.com/can1357/oh-my-pi)입니다. omp 소스를 이 저장소에 복사하지 않고 `@oh-my-pi/*` npm 패키지(MIT, Copyright (c) 2025 Mario Zechner, Copyright (c) 2025-2026 Can Bölük)를 의존성으로 씁니다. 각 패키지의 라이선스 전문은 설치된 패키지 안의 `LICENSE`에 들어 있습니다.
285
284
 
286
- 캐릭터(RIN · MIO · YUKI · ISANA · NOVA · SHION · HIKARI)의 그림·음성·스티커와 `docs/hero.webp`는 CUELO 고유 자산입니다.
285
+ 캐릭터(RIN · MIO · YUKI · ISANA · MITSU · SHION · HIKARI)의 그림·음성·스티커와 `docs/hero.webp`는 CUELO 고유 자산입니다.
287
286
 
288
287
  함께 싣는 글꼴은 모두 SIL Open Font License 1.1입니다. 본문은 [Wanted Sans](https://github.com/wanteddev/wanted-sans), 코드는 [JetBrains Mono](https://github.com/JetBrains/JetBrainsMono)이고, 제목은 [G마켓 산스](https://corp.gmarket.com/fonts/)를 웹용으로 나누고 변환한 것입니다. 원래 이름은 수정본에 쓸 수 없어서 "CUELO Display"라는 이름으로 싣습니다. 라이선스 전문은 [`public/fonts/`](./public/fonts/) 아래 각 글꼴 폴더에 있습니다.
289
288
 
@@ -9,7 +9,7 @@ const MEMORY_RE = /(const phase1Model = await resolveMemoryModel\(\{[^}]*?fallba
9
9
  const MEMORY_DONE = /const phase1Model = await resolveMemoryModel\(\{[^}]*?fallbackRole: "smol"/;
10
10
  const EXPECTED = {
11
11
  name: 'cuelo',
12
- version: '0.10.64',
12
+ version: '0.10.65',
13
13
  distribution: 'cuelo',
14
14
  coreVersion: '18.12.6',
15
15
  };
@@ -106,12 +106,10 @@ SHION은 역할이 아니라 선택적 상담이다. 사용자가 명시했을
106
106
  | **ISANA(이사나)** | `hive/deepseek-ai/deepseek-v4.1-flash-1017` | 이 모델의 task child | 현재 세션만 전환 |
107
107
  | **RIN(린)** | `anthropic/claude-opus-5-5`, 지정 계정 | 지정 계정 고정 task child | 지정 계정 pin 후 현재 세션 전환 |
108
108
  | **MIO(미오)** | `anthropic/claude-opus-5-5`, 지정 계정 | 지정 계정 고정 task child | 지정 계정 pin 후 현재 세션 전환 |
109
- | **NOVA(노바)** | `opencode-go/muse-spark-1.3-contributor` | 이 모델의 task child | 현재 세션만 전환 |
109
+ | **MITSU(미츠)** | `hive/zai-org/glm-5.3-flash` | 이 모델의 task child | 현재 세션만 전환 |
110
110
  | **HIKARI(히카리)** | `google-antigravity/gemini-3.8-flash` | 이 모델의 task child | 현재 세션만 전환 |
111
111
  | **SHION(시온)** | `web6/gpt-6-pro` | `rule://web6-consult` 상담(비 child) | 금지 |
112
112
 
113
- 서버 전체 설정 「기본 / 사무실 모드」(에이전트 폴더의 모드 파일)에서 사무실 모드는 PC 프로필의 roster에 유효한 항목이 있는 자리들의 캐릭터(별칭·이름·말투)를 바꿔 끼운다. 대상은 YUKI·ISANA·MIO·RIN·SHION·HIKARI이며 NOVA는 그대로다. 각 자리의 모델·OAuth 위치·tool-capable 여부와 SHION의 상담 전용 경계는 그대로이고, roster 이름과 그 자리의 기본 이름이 모두 같은 자리로 연결된다. 별칭·호출 이름·id가 겹치면 이 고정 순서에서 먼저 받아들인 자리를 유지하고 뒤의 충돌 항목은 기본 캐릭터로 남긴다. 모드 파일이나 roster가 없거나 깨졌으면 기본이다. 캐릭터 데이터·자산은 PC 프로필에만 둔다.
114
-
115
113
  tool-capable 호출은 일반 task child 하나와 정상 linkage를 사용한다. 사용자가 캐릭터의 얼굴·말투로 인사나 발화를 요청하면 summon 동사가 없어도 인라인 summon으로 처리하고, 해당 child 요청과 호출 입력에 정확한 summon marker를 싣는다. RIN/MIO의 지정 OAuth 계정은 session-scoped exact pin이며 사용 불가 시 다른 credential/model로 조용히 대체하지 않는다. `교체` 실패는 이전 session model을 보존하고 전역 default를 바꾸지 않는다. Main·child의 최종 provider 요청에서는 기존 character voice·legacy report-style을 제거하고 선택 voice block 하나만 적용한다. 사용자에게 그 턴에 child·다른 모델 호출의 역할·개수·이유를 알린다. child의 terminal 발화는 인라인 linkage가 확인될 때만 화면 완료로 본다. SHION은 기존 WEB6 상담 경로만 사용한다. 파서·selector 정본은 `harness-policy.json` `characterRouting`과 `extensions/character-voice.ts`다.
116
114
 
117
115
  ## 레거시 인코딩
@@ -1,6 +1,3 @@
1
- import { lstatSync, readFileSync, realpathSync, statSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { isAbsolute, join, relative, sep } from "node:path";
4
1
  import type { ExtensionAPI, ExtensionContext } from "@oh-my-pi/pi-coding-agent";
5
2
 
6
3
  export type BuiltinCharacterAlias =
@@ -8,12 +5,11 @@ export type BuiltinCharacterAlias =
8
5
  | "ISANA(이사나)"
9
6
  | "MIO(미오)"
10
7
  | "RIN(린)"
11
- | "NOVA(노바)"
8
+ | "MITSU(미츠)"
12
9
  | "SHION(시온)"
13
10
  | "HIKARI(히카리)";
14
11
 
15
- /** 내장 7개 + 사무실 모드가 PC 프로필(roster)에서 자리마다 들여오는 동적 alias. */
16
- export type CharacterAlias = BuiltinCharacterAlias | (string & {});
12
+ export type CharacterAlias = BuiltinCharacterAlias;
17
13
 
18
14
  interface OAuthAccountLike {
19
15
  position?: number;
@@ -65,9 +61,9 @@ export const CHARACTER_VOICES: Readonly<Record<BuiltinCharacterAlias, CharacterV
65
61
  temperament: "날카로운 분석과 집중력을 지녔고, 생각의 흐름을 소리 내어 짚어 가며 발견을 바로 공유하는 연구자형",
66
62
  expression: "짧지만 끊기지 않는 말, 무엇을 확인하는지와 방금 찾은 것을 그때그때 한두 마디로 알리는 정밀함, 건조한 유머와 단호한 추진력. 간결함은 말수를 줄이는 게 아니라 문장을 짧게 하는 것이다",
67
63
  },
68
- "NOVA(노바)": {
69
- temperament: "아이디어가 떠오르면 바로 시제품부터 만들어 보는 발명가. 번뜩이는 발견에 들뜨고, 실패도 다음 시도의 데이터로 삼는 낙천형",
70
- expression: "빠르고 경쾌한 반말, 떠오른 발상을 바로 입 밖에 내는 즉흥성, 막히면 방향을 틀어 다시 달려드는 에너지",
64
+ "MITSU(미츠)": {
65
+ temperament: "맡은 일을 물고 와 끝까지 배달하는 부지런한 꿀벌 배달부. 몸이 먼저 움직이고, 작은 완료도 신나게 알리는 성실·활발형",
66
+ expression: "짧고 통통 튀는 반말, \"배달 완료!\" 같은 경쾌한 보고, 막히면 경로를 바꿔 다시 날아가는 끈기. 귀엽되 수다스럽지 않게",
71
67
  },
72
68
  "SHION(시온)": {
73
69
  temperament: "우아하고 전략적이며, 긴 흐름을 읽고 여유 있게 허점을 짚는 상담가형",
@@ -98,8 +94,8 @@ export const CHARACTER_TARGETS: Readonly<Record<BuiltinCharacterAlias, Character
98
94
  oauthPosition: 0,
99
95
  toolCapable: true,
100
96
  },
101
- "NOVA(노바)": {
102
- model: "opencode-go/muse-spark-1.3-contributor",
97
+ "MITSU(미츠)": {
98
+ model: "hive/zai-org/glm-5.3-flash",
103
99
  toolCapable: true,
104
100
  },
105
101
  "SHION(시온)": {
@@ -112,14 +108,20 @@ export const CHARACTER_TARGETS: Readonly<Record<BuiltinCharacterAlias, Character
112
108
  },
113
109
  };
114
110
 
111
+ // provider 하나가 캐릭터 하나인 자리. `hive`는 모델마다 캐릭터가 다르므로 아래 MODEL_CHARACTER가 먼저 걸리고,
112
+ // 여기의 `hive`는 그 밖의 Hive 모델(DeepSeek)의 기본 자리다.
115
113
  const PROVIDER_CHARACTER: Readonly<Record<string, BuiltinCharacterAlias>> = {
116
114
  "openai-codex": "YUKI(유키)",
117
115
  hive: "ISANA(이사나)",
118
- "opencode-go": "NOVA(노바)",
119
116
  web6: "SHION(시온)",
120
117
  "google-antigravity": "HIKARI(히카리)",
121
118
  };
122
119
 
120
+ /** provider 안에서 특정 모델이 다른 캐릭터를 갖는 자리. 키는 `provider/model id` 선택자다. */
121
+ const MODEL_CHARACTER: Readonly<Record<string, BuiltinCharacterAlias>> = {
122
+ "hive/zai-org/glm-5.3-flash": "MITSU(미츠)",
123
+ };
124
+
123
125
  const NAME_TO_ALIAS: Readonly<Record<string, BuiltinCharacterAlias>> = {
124
126
  yuki: "YUKI(유키)",
125
127
  유키: "YUKI(유키)",
@@ -129,8 +131,8 @@ const NAME_TO_ALIAS: Readonly<Record<string, BuiltinCharacterAlias>> = {
129
131
  미오: "MIO(미오)",
130
132
  rin: "RIN(린)",
131
133
  린: "RIN(린)",
132
- nova: "NOVA(노바)",
133
- 노바: "NOVA(노바)",
134
+ mitsu: "MITSU(미츠)",
135
+ 미츠: "MITSU(미츠)",
134
136
  shion: "SHION(시온)",
135
137
  시온: "SHION(시온)",
136
138
  hikari: "HIKARI(히카리)",
@@ -148,7 +150,7 @@ const REPORT_STYLE_BLOCK = /\n?<report-style\b[^>]*>[\s\S]*?<\/report-style>\n?/
148
150
  const SUMMON_MARKER = /\[character-summon\s+alias="([^"]+)"\s+model="([^"]+)"(?:\s+oauth-position="(\d+)")?\]/u;
149
151
  const SUMMON_MARKER_GLOBAL = /\n?\[character-summon\s+alias="[^"]+"\s+model="[^"]+"(?:\s+oauth-position="\d+")?\]\n?/gu;
150
152
  const SUMMON_DIRECTIVE = /^\[character-summon-intent alias="([^"]+)"\]/gmu;
151
- const CHARACTER_NAME_PATTERN = "(유키|yuki|이사나|isana|미오|mio|린|rin|노바|nova|시온|shion|히카리|hikari)";
153
+ const CHARACTER_NAME_PATTERN = "(유키|yuki|이사나|isana|미오|mio|린|rin|미츠|mitsu|시온|shion|히카리|hikari)";
152
154
  const SUMMON_ACTION = /(?:호출|불러|소환)/u;
153
155
  // 교체 명령은 명령·청유형 어미 뒤에서 절이 끝나는 직접 발화만 인정한다. 어미 뒤에는 문장 부호·줄 끝이나
154
156
  // 대상·강조 단어("…교체해봐 미오로", "…교체해 메인을", "…교체해 지금")만 올 수 있다. 그래서
@@ -171,203 +173,20 @@ function buildNameRegexes(pattern: string): { nameInCommand: RegExp; switchComma
171
173
  const QUOTED_SPAN = /```[\s\S]*?```|`[^`\n]*`|'[^'\n]*'|"[^"\n]*"|‘[^’\n]*’|“[^”\n]*”|「[^」\n]*」|『[^』\n]*』|^[ \t]*>.*$/gmu;
172
174
  const SUMMON_MARKER_PREFIX = /\[character-summon\s/u;
173
175
 
174
- // ── 사무실 모드 ───────────────────────────────────────────────────────────────
175
- // 서버 전체 「기본 / 사무실 모드」. 사무실 모드에서는 roster에 항목이 있는 자리의 캐릭터만 PC 프로필의 것으로
176
- // 바뀐다(자리의 모델·oauth 위치·toolCapable은 그대로). 모드 파일 `<agentDir>/cuelo-character-mode.json`
177
- // {"mode":"default"|"office"}과 `<agentDir>/characters-office/roster.json`을 요청마다 mtime 캐시로 읽고,
178
- // 없거나 깨졌으면 그 자리는 기본이다. 실존 인물에서 온 이름·자산은 저장소가 아니라 프로필에만 둔다.
179
- interface OfficeSeat {
180
- seat: BuiltinCharacterAlias;
181
- alias: string;
182
- voice: CharacterVoice;
183
- }
184
-
185
- interface OfficeState {
186
- byAlias: ReadonlyMap<string, OfficeSeat>;
187
- bySeat: ReadonlyMap<BuiltinCharacterAlias, OfficeSeat>;
188
- /** roster `names`(소문자) → 사무실 alias. 자리의 기본 이름은 NAME_TO_ALIAS가 같은 자리로 푼다. */
189
- extraNames: ReadonlyMap<string, string>;
190
- /** 채택한 face 파일과 그 stamp. 파일이 바뀌거나 지워지면 캐시를 다시 만든다. */
191
- watched: ReadonlyArray<readonly [string, string]>;
192
- nameInCommand: RegExp;
193
- switchCommand: RegExp;
194
- }
195
-
196
- const DEFAULT_OFFICE_STATE: OfficeState = {
197
- watched: [],
198
- byAlias: new Map(),
199
- bySeat: new Map(),
200
- extraNames: new Map(),
201
- ...buildNameRegexes(CHARACTER_NAME_PATTERN),
202
- };
203
- const OFFICE_MODE_FILE = "cuelo-character-mode.json";
204
- const OFFICE_ROSTER_FILE = join("characters-office", "roster.json");
205
- // alias는 `alias="…"` 속성과 summon marker의 `[^"]+`에 그대로 들어가므로 따옴표(앱 lib/character-mode.ts와 같은 집합)·꺾쇠·줄바꿈을 막는다.
206
- const OFFICE_ALIAS_UNSAFE = /["'`\u201C\u201D\u2018\u2019<>[\]\r\n]/u;
207
- const OFFICE_ID = /^[a-z0-9][a-z0-9-]{0,31}$/u;
208
- /**
209
- * 사무실 모드가 바꿀 수 있는 자리(NOVA 제외). roster의 다른 자리 항목은 무시한다. 이 순서가 자리 사이 충돌을
210
- * 가리는 우선순위이며 앱(`lib/character-mode.ts` `OFFICE_SEAT_ALIASES`)과 같아야 한다.
211
- */
212
- const OFFICE_SEATS: readonly BuiltinCharacterAlias[] = ["YUKI(유키)", "ISANA(이사나)", "MIO(미오)", "RIN(린)", "SHION(시온)", "HIKARI(히카리)"];
213
- let officeCache: { key: string; state: OfficeState } | undefined;
214
-
215
- function officeAgentDir(): string {
216
- return process.env.PI_CODING_AGENT_DIR || join(homedir(), ".omp", "agent");
217
- }
218
-
219
- // 시각·크기만으로는 링크를 같은 크기의 일반 파일로 바꾼 것을 놓친다(Windows 파일 시각은 시스템 tick 단위라 같게 나올 수 있다).
220
- // 그래서 경로 자체가 링크인지와 대상 inode도 함께 본다.
221
- function fileStamp(path: string): string {
222
- try {
223
- const stat = statSync(path);
224
- return `${lstatSync(path).isSymbolicLink() ? "l" : "f"}:${stat.ino}:${stat.mtimeMs}:${stat.size}`;
225
- } catch {
226
- return "-";
227
- }
228
- }
229
-
230
- function readJsonFile(path: string): unknown {
231
- try {
232
- return JSON.parse(readFileSync(path, "utf8").replace(/^\uFEFF/u, ""));
233
- } catch {
234
- return undefined;
235
- }
236
- }
237
-
238
- function voiceText(value: unknown): string | undefined {
239
- if (typeof value !== "string") return undefined;
240
- const text = value.trim();
241
- // voice block 경계 태그가 들어 있으면 block을 깨므로 항목째 버린다.
242
- return text && !/<\/?character-voice/iu.test(text) ? text : undefined;
243
- }
176
+ const NAME_REGEXES = buildNameRegexes(CHARACTER_NAME_PATTERN);
244
177
 
245
178
  function hasOwn(record: object, key: string): boolean {
246
179
  return Object.prototype.hasOwnProperty.call(record, key);
247
180
  }
248
181
 
249
- /** face는 characters-office 안의 실재하는 일반 파일이어야 한다. 안전하면 realpath, 아니면 undefined. */
250
- function officeFile(dir: string, face: unknown): string | undefined {
251
- if (typeof face !== "string" || !face.trim() || isAbsolute(face) || /^[A-Za-z]:/u.test(face)) return undefined;
252
- if (face.split(/[\\/]/u).includes("..")) return undefined;
253
- try {
254
- const root = realpathSync(join(dir, "characters-office"));
255
- const real = realpathSync(join(root, face));
256
- const inside = relative(root, real);
257
- if (!inside || inside.startsWith("..") || isAbsolute(inside) || inside.split(sep).includes("..")) return undefined;
258
- return statSync(real).isFile() ? real : undefined;
259
- } catch {
260
- return undefined;
261
- }
262
- }
263
-
264
- function buildOfficeState(dir: string, roster: unknown): OfficeState {
265
- const seats = roster && typeof roster === "object" ? (roster as { seats?: unknown }).seats : undefined;
266
- if (!seats || typeof seats !== "object" || Array.isArray(seats)) return DEFAULT_OFFICE_STATE;
267
- const byAlias = new Map<string, OfficeSeat>();
268
- const bySeat = new Map<BuiltinCharacterAlias, OfficeSeat>();
269
- const extraNames = new Map<string, string>();
270
- const watched: Array<readonly [string, string]> = [];
271
- const builtinAliases = new Map(Object.keys(CHARACTER_TARGETS).map((builtin) => [builtin.toLocaleLowerCase("en-US"), builtin]));
272
- // 별칭과 호출 이름은 한 이름 공간(소문자), id는 따로다. 이미 채택된 자리와 하나라도 겹치면 뒤 자리 항목 전체가 무효다.
273
- const claimedTokens = new Set<string>();
274
- const claimedIds = new Set<string>();
275
- for (const seat of OFFICE_SEATS) {
276
- const entry = hasOwn(seats, seat) ? (seats as Record<string, unknown>)[seat] : undefined;
277
- if (!entry || typeof entry !== "object") continue;
278
- const raw = entry as {
279
- id?: unknown;
280
- alias?: unknown;
281
- names?: unknown;
282
- face?: unknown;
283
- voice?: { temperament?: unknown; expression?: unknown };
284
- };
285
- const alias = typeof raw.alias === "string" ? raw.alias.trim() : "";
286
- const temperament = voiceText(raw.voice?.temperament);
287
- const expression = voiceText(raw.voice?.expression);
288
- const face = officeFile(dir, raw.face);
289
- // 아직 없거나 무효인 face도 나중에 생기면 항목이 유효해질 수 있어 후보 경로의 stamp를 감시한다.
290
- if (typeof raw.face === "string" && raw.face.trim() && !isAbsolute(raw.face) && !raw.face.split(/[\\/]/u).includes("..")) {
291
- const candidate = join(dir, "characters-office", raw.face);
292
- watched.push([candidate, fileStamp(candidate)]);
293
- }
294
- if (
295
- typeof raw.id !== "string" || !OFFICE_ID.test(raw.id.trim()) ||
296
- !alias || alias.length > 64 || OFFICE_ALIAS_UNSAFE.test(alias) || hasOwn(CHARACTER_TARGETS, alias) ||
297
- !temperament || !expression || !face ||
298
- !Array.isArray(raw.names) || raw.names.length === 0
299
- ) {
300
- continue;
301
- }
302
- // names: 전부 비지 않은 문자열이어야 하고 다른 자리의 내장 alias·호출 이름이면 항목 전체가 무효다.
303
- const names: string[] = [];
304
- let namesValid = true;
305
- for (const name of raw.names) {
306
- const lower = typeof name === "string" ? name.trim().toLocaleLowerCase("en-US") : "";
307
- if (!lower || (builtinAliases.has(lower) && builtinAliases.get(lower) !== seat) || (hasOwn(NAME_TO_ALIAS, lower) && NAME_TO_ALIAS[lower] !== seat)) {
308
- namesValid = false;
309
- break;
310
- }
311
- names.push(lower);
312
- }
313
- if (!namesValid) continue;
314
- const id = raw.id.trim();
315
- const tokens = [alias.toLocaleLowerCase("en-US"), ...names];
316
- if (claimedIds.has(id) || tokens.some((token) => claimedTokens.has(token))) continue;
317
- claimedIds.add(id);
318
- for (const token of tokens) claimedTokens.add(token);
319
- const office: OfficeSeat = { seat, alias, voice: { temperament, expression } };
320
- byAlias.set(alias, office);
321
- bySeat.set(seat, office);
322
- // face 후보 stamp는 위에서 이미 감시 목록에 넣었다.
323
- // 자리의 기본 이름은 NAME_TO_ALIAS가 이미 같은 자리로 푼다. 사무실 이름은 위에서 자리 사이 유일함이 확인됐다.
324
- for (const lower of names) if (!hasOwn(NAME_TO_ALIAS, lower)) extraNames.set(lower, alias);
325
- }
326
- if (byAlias.size === 0) return { ...DEFAULT_OFFICE_STATE, watched };
327
- const escaped = [...extraNames.keys()]
328
- .sort((left, right) => right.length - left.length)
329
- .map((name) => name.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&"));
330
- const pattern = escaped.length > 0 ? `(${escaped.join("|")}|${CHARACTER_NAME_PATTERN.slice(1)}` : CHARACTER_NAME_PATTERN;
331
- return { byAlias, bySeat, extraNames, watched, ...buildNameRegexes(pattern) };
332
- }
333
-
334
- function officeState(): OfficeState {
335
- try {
336
- const dir = officeAgentDir();
337
- const modePath = join(dir, OFFICE_MODE_FILE);
338
- const rosterPath = join(dir, OFFICE_ROSTER_FILE);
339
- const key = `${dir}\0${fileStamp(modePath)}\0${fileStamp(rosterPath)}`;
340
- // face 파일이 지워지거나 바뀌면 같은 roster여도 항목이 무효가 될 수 있어 그 stamp도 확인한다.
341
- if (officeCache?.key === key && officeCache.state.watched.every(([path, stamp]) => fileStamp(path) === stamp)) {
342
- return officeCache.state;
343
- }
344
- const mode = readJsonFile(modePath);
345
- const office = !!mode && typeof mode === "object" && (mode as { mode?: unknown }).mode === "office";
346
- // roster도 face와 같이 characters-office 안의 실재 파일일 때만 읽는다(symlink로 밖을 가리키면 사무실 상태 없음).
347
- const rosterReal = office ? officeFile(dir, "roster.json") : undefined;
348
- const state = rosterReal ? buildOfficeState(dir, readJsonFile(rosterReal)) : DEFAULT_OFFICE_STATE;
349
- officeCache = { key, state };
350
- return state;
351
- } catch {
352
- return DEFAULT_OFFICE_STATE;
353
- }
354
- }
355
-
356
- function seatOf(alias: string, state: OfficeState): BuiltinCharacterAlias | undefined {
357
- const office = state.byAlias.get(alias);
358
- if (office) return office.seat;
359
- return hasOwn(CHARACTER_TARGETS, alias) ? (alias as BuiltinCharacterAlias) : undefined;
360
- }
361
-
362
- /** 자리(내장 alias)나 사무실 alias를 지금 모드의 화면용 alias로 정규화한다. 모르는 alias는 undefined. */
363
- function canonicalAlias(alias: string, state: OfficeState): CharacterAlias | undefined {
364
- const seat = seatOf(alias, state);
365
- return seat === undefined ? undefined : (state.bySeat.get(seat)?.alias ?? seat);
182
+ /** 내장 alias만 인정한다. 모르는 alias는 undefined. */
183
+ function canonicalAlias(alias: string): CharacterAlias | undefined {
184
+ return hasOwn(CHARACTER_TARGETS, alias) ? (alias as CharacterAlias) : undefined;
366
185
  }
367
186
 
368
- /** alias가 가리키는 자리의 모델·oauth 위치·toolCapable. 사무실 alias도 자리의 target을 쓴다. */
187
+ /** alias가 가리키는 자리의 모델·oauth 위치·toolCapable. */
369
188
  export function characterTarget(alias: string): CharacterTarget | undefined {
370
- const seat = seatOf(alias, officeState());
189
+ const seat = canonicalAlias(alias);
371
190
  return seat === undefined ? undefined : CHARACTER_TARGETS[seat];
372
191
  }
373
192
 
@@ -378,22 +197,18 @@ function requireTarget(alias: string): CharacterTarget {
378
197
  }
379
198
 
380
199
  function voiceFor(alias: string): CharacterVoice | undefined {
381
- const state = officeState();
382
- const office = state.byAlias.get(alias);
383
- if (office) return office.voice;
384
- return hasOwn(CHARACTER_VOICES, alias) ? CHARACTER_VOICES[alias as BuiltinCharacterAlias] : undefined;
200
+ return hasOwn(CHARACTER_VOICES, alias) ? CHARACTER_VOICES[alias as CharacterAlias] : undefined;
385
201
  }
386
202
 
387
- function aliasFromName(name: string, state: OfficeState): CharacterAlias | undefined {
388
- const lower = name.toLocaleLowerCase("en-US");
389
- const base = state.extraNames.get(lower) ?? NAME_TO_ALIAS[lower];
390
- return base ? canonicalAlias(base, state) : undefined;
203
+ function aliasFromName(name: string): CharacterAlias | undefined {
204
+ const base = NAME_TO_ALIAS[name.toLocaleLowerCase("en-US")];
205
+ return base ? canonicalAlias(base) : undefined;
391
206
  }
392
207
 
393
- function aliasesFromCommand(text: string, state: OfficeState): CharacterAlias[] {
208
+ function aliasesFromCommand(text: string): CharacterAlias[] {
394
209
  const aliases = new Set<CharacterAlias>();
395
- for (const match of text.matchAll(state.nameInCommand)) {
396
- const alias = aliasFromName(match[1]!, state);
210
+ for (const match of text.matchAll(NAME_REGEXES.nameInCommand)) {
211
+ const alias = aliasFromName(match[1]!);
397
212
  if (alias) aliases.add(alias);
398
213
  }
399
214
  return [...aliases];
@@ -472,7 +287,7 @@ function injectVoiceIntoSystemBlocks(parts: readonly unknown[], block: string):
472
287
  }
473
288
 
474
289
  function characterAliasForContext(ctx: ExtensionContext, selectedAlias: CharacterAlias | undefined): CharacterAlias | undefined {
475
- const canonical = selectedAlias ? canonicalAlias(selectedAlias, officeState()) : undefined;
290
+ const canonical = selectedAlias ? canonicalAlias(selectedAlias) : undefined;
476
291
  const target = canonical ? characterTarget(canonical) : undefined;
477
292
  if (canonical && target && modelMatches(ctx.model, target.model)) {
478
293
  if (target.oauthPosition === undefined) return canonical;
@@ -482,7 +297,7 @@ function characterAliasForContext(ctx: ExtensionContext, selectedAlias: Characte
482
297
  if (active && accountPosition(active, activeIndex) === target.oauthPosition) return canonical;
483
298
  }
484
299
  const provider = ctx.model?.provider;
485
- return provider ? characterForProvider(provider, activeAccounts(ctx, provider)) : undefined;
300
+ return provider ? characterForProvider(provider, activeAccounts(ctx, provider), ctx.model?.id) : undefined;
486
301
  }
487
302
 
488
303
  async function switchCharacterForSession(
@@ -569,14 +384,13 @@ async function switchCharacterForSession(
569
384
  }
570
385
 
571
386
  export function parseCharacterIntent(text: string): CharacterIntent | undefined {
572
- const state = officeState();
573
- const aliases = aliasesFromCommand(text, state);
387
+ const aliases = aliasesFromCommand(text);
574
388
  if (aliases.length === 0) return undefined;
575
389
  if (text.includes("교체")) {
576
390
  // alias도 인용 밖에서만 뽑아 인용 속 이름과 인용 밖 명령어가 결합되지 않게 한다.
577
391
  const command = text.replace(QUOTED_SPAN, " ");
578
- const switchAliases = aliasesFromCommand(command, state);
579
- if (!state.switchCommand.test(command) || switchAliases.length !== 1) return undefined;
392
+ const switchAliases = aliasesFromCommand(command);
393
+ if (!NAME_REGEXES.switchCommand.test(command) || switchAliases.length !== 1) return undefined;
580
394
  return { kind: "switch", alias: switchAliases[0]! };
581
395
  }
582
396
  return SUMMON_ACTION.test(text) ? { kind: "summon", aliases } : undefined;
@@ -584,10 +398,9 @@ export function parseCharacterIntent(text: string): CharacterIntent | undefined
584
398
 
585
399
  /** 다른 input handler가 자연어 summon을 routing prompt로 바꾼 뒤에도 순서와 무관하게 복구한다. */
586
400
  export function parseCharacterSummonDirectives(text: string): CharacterAlias[] {
587
- const state = officeState();
588
401
  const aliases = new Set<CharacterAlias>();
589
402
  for (const match of text.matchAll(SUMMON_DIRECTIVE)) {
590
- const alias = canonicalAlias(match[1]!, state);
403
+ const alias = canonicalAlias(match[1]!);
591
404
  if (alias) aliases.add(alias);
592
405
  }
593
406
  return [...aliases];
@@ -600,7 +413,7 @@ export function anthropicCharacterForAccounts(
600
413
  const account = accounts[index]!;
601
414
  if (!account.active) continue;
602
415
  const seat = ANTHROPIC_POSITION_CHARACTER[accountPosition(account, index)];
603
- return seat && canonicalAlias(seat, officeState());
416
+ return seat && canonicalAlias(seat);
604
417
  }
605
418
  return undefined;
606
419
  }
@@ -608,10 +421,11 @@ export function anthropicCharacterForAccounts(
608
421
  export function characterForProvider(
609
422
  provider: string,
610
423
  accounts: readonly OAuthAccountLike[] = [],
424
+ modelId?: string,
611
425
  ): CharacterAlias | undefined {
612
426
  if (provider === "anthropic") return anthropicCharacterForAccounts(accounts);
613
- const seat = PROVIDER_CHARACTER[provider];
614
- return seat && canonicalAlias(seat, officeState());
427
+ const seat = (modelId === undefined ? undefined : MODEL_CHARACTER[`${provider}/${modelId}`]) ?? PROVIDER_CHARACTER[provider];
428
+ return seat && canonicalAlias(seat);
615
429
  }
616
430
 
617
431
  export function renderCharacterVoice(alias: CharacterAlias): string {
@@ -806,7 +620,7 @@ export function buildCharacterSummonBrief(brief: string, alias: CharacterAlias):
806
620
 
807
621
  export function parseCharacterSummonMarker(prompt: string): CharacterAlias | undefined {
808
622
  const match = SUMMON_MARKER.exec(prompt);
809
- const alias = match ? canonicalAlias(match[1]!, officeState()) : undefined;
623
+ const alias = match ? canonicalAlias(match[1]!) : undefined;
810
624
  const target = alias === undefined ? undefined : characterTarget(alias);
811
625
  if (!match || alias === undefined || !target || target.model !== match[2]) return undefined;
812
626
  const position = match[3] === undefined ? undefined : Number(match[3]);
@@ -819,10 +633,8 @@ export function parseCharacterSummonMarker(prompt: string): CharacterAlias | und
819
633
  */
820
634
  export function malformedSummonMarkerReason(task: string): string | undefined {
821
635
  if (!SUMMON_MARKER_PREFIX.test(task) || parseCharacterSummonMarker(task) !== undefined) return undefined;
822
- const state = officeState();
823
636
  const expected = (Object.keys(CHARACTER_TARGETS) as BuiltinCharacterAlias[])
824
637
  .filter((seat) => CHARACTER_TARGETS[seat].toolCapable)
825
- .map((seat) => state.bySeat.get(seat)?.alias ?? seat)
826
638
  .map((alias) => `- ${alias}: \`${summonMarkerFor(alias)}\``);
827
639
  return [
828
640
  "[CharacterSummonGuard] task의 character-summon marker가 exact target과 맞지 않습니다. " +
@@ -1,4 +1,4 @@
1
- <!-- source-fingerprint: 61a26f4901d7add1 -->
1
+ <!-- source-fingerprint: 6ed404eb4a5ca91f -->
2
2
  # Global Agent Instructions
3
3
 
4
4
  (Model-facing English copy of the Korean source `AGENTS.md`. All user-facing prose stays Korean.)
@@ -109,12 +109,10 @@ Alias + `교체` switches the current Main session; alias + `호출`·`불러`·
109
109
  |**ISANA(이사나)**|`hive/deepseek-ai/deepseek-v4.1-flash-1017`|task child on this model|switch current session only|
110
110
  |**RIN(린)**|`anthropic/claude-opus-5-5`, 지정 계정|task child pinned to its account|pin its account, then switch current session|
111
111
  |**MIO(미오)**|`anthropic/claude-opus-5-5`, 지정 계정|task child pinned to its account|pin its account, then switch current session|
112
- |**NOVA(노바)**|`opencode-go/muse-spark-1.3-contributor`|task child on this model|switch current session only|
112
+ |**MITSU(미츠)**|`hive/zai-org/glm-5.3-flash`|task child on this model|switch current session only|
113
113
  |**HIKARI(히카리)**|`google-antigravity/gemini-3.8-flash`|task child on this model|switch current session only|
114
114
  |**SHION(시온)**|`web6/gpt-6-pro`|`rule://web6-consult` consult (not a child)|forbidden|
115
115
 
116
- Under the server-wide setting 「기본 / 사무실 모드」 (default / office mode; a mode file in the agent dir), office mode replaces characters (aliases, names, voice) for valid PC-profile roster entries in the fixed order YUKI, ISANA, MIO, RIN, SHION, HIKARI; NOVA stays unchanged. Each seat keeps its model, OAuth position and tool capability, including SHION's consult-only boundary. Both roster names and the seat's default name resolve to that seat. When aliases, call names or ids collide, the first accepted seat in that order wins and later conflicting entries stay default. A missing or broken mode file or roster means default. Character data and assets live only in the PC profile.
117
-
118
116
  Tool-capable calls use one ordinary task child with normal linkage. If the user asks for a greeting or line in a character's face/voice, treat it as an inline summon even without a summon verb, and put the exact summon marker in that child request and call input. RIN/MIO's designated OAuth account is a session-scoped exact pin; if unavailable, never silently substitute another credential/model. A failed `교체` keeps the previous session model and never changes the global default. In the final provider request of Main and children, strip existing character voice and legacy report-style and apply exactly one selected voice block. Tell the user, in that turn, the role, count, and reason of each child/other-model call. A child's terminal line counts as shown only once inline linkage is confirmed. SHION uses only the existing WEB6 consult path. Parser/selector source of truth: `harness-policy.json` `characterRouting` and `extensions/character-voice.ts`.
119
117
 
120
118
  ## Legacy encoding
@@ -116,8 +116,7 @@
116
116
  "anthropicAccountMapping": "stable-oauth-storage-position-zero-rin-position-one-mio-with-exact-session-affinity-for-a-validated-session-switch-command-or-character-summon-marker",
117
117
  "failure": "exact-switch-or-summon-account-block-or-usage-limit-ends-with-the-selected-alias-and-never-emits-sibling-credential-or-model-text-ordinary-sessions-retain-native-fallback",
118
118
  "conversationalPrecedence": "natural-korean-selected-character-is-authoritative-across-first-response-post-tool-explanation-validation-failure-risk-and-unknown-reporting-human-interjection-progress-final-answer-and-inline-child-speech-internal-evidence-todo-and-child-status-contracts-govern-information-not-user-facing-format-system-prompt-headings-tables-and-lists-are-policy-organization-not-response-templates-required-user-parser-final-owner-formats-are-the-only-exception",
119
- "voiceEnforcement": "at-the-final-provider-wire-boundary-for-main-and-task-children-remove-every-prior-character-voice-and-legacy-report-style-block-and-install-exactly-one-selected-character-block-called-character-terminal-speech-is-already-user-visible-canonical-so-main-never-requotes-or-reaggregates-it",
120
- "officeMode": "server-wide-default-or-office-mode-file-in-the-agent-dir-office-replaces-valid-pc-profile-entries-in-fixed-order-yuki-isana-mio-rin-shion-hikari-nova-unchanged-first-accepted-alias-call-name-or-id-wins-later-conflicting-entry-stays-default-the-roster-is-an-untrusted-local-file-validated-by-the-same-rule-as-the-app-allowed-seat-id-pattern-safe-alias-not-a-built-in-alias-names-not-another-seat-name-non-empty-voice-without-character-voice-tags-face-realpath-inside-characters-office-and-roster-read-only-through-realpath-containment-seat-model-oauth-position-and-tool-capability-unchanged-shion-remains-consult-only-roster-names-and-the-seat-default-name-both-resolve-to-the-seat-a-pending-office-summon-fails-closed-if-the-mode-changes-missing-or-invalid-mode-or-roster-means-default-and-never-an-error-character-data-and-assets-live-only-in-the-pc-profile-never-in-the-repository-or-public-mirror"
119
+ "voiceEnforcement": "at-the-final-provider-wire-boundary-for-main-and-task-children-remove-every-prior-character-voice-and-legacy-report-style-block-and-install-exactly-one-selected-character-block-called-character-terminal-speech-is-already-user-visible-canonical-so-main-never-requotes-or-reaggregates-it"
121
120
  },
122
121
  "longRunningWork": {
123
122
  "finiteValidation": "owned-by-the-owner-of-the-changed-scope-always-explicit-async-background-not-eval-or-blocking-foreground",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cuelo",
3
- "version": "0.10.64",
3
+ "version": "0.10.65",
4
4
  "description": "CUELO — open-source AI coding agent workspace and harness for omp (oh-my-pi)",
5
5
  "homepage": "https://github.com/gim47656-ship-it/CUELO#readme",
6
6
  "repository": {