From c4fa421885f403a3296911d5cf9c2a4fb64ada72 Mon Sep 17 00:00:00 2001 From: tiye Date: Sat, 14 Nov 2026 05:56:49 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E7=BB=9F=E4=B8=80=20Gen=20Code=20=E8=8D=89?= =?UTF-8?q?=E7=A8=BF=E7=9A=84=E7=B1=BB=E5=9E=8B=E5=8C=96=E8=A7=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- calcit.cirru | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/calcit.cirru b/calcit.cirru index c739365..6aafcdf 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -343,11 +343,7 @@ cursor $ decode-map-as schema/read-open-field-or states :cursor $ [] List respo.schema/CoordKey - state $ decode-map-as - let - value $ schema/read-open-field-or states :data initial-state - if (struct? value) (&struct:to-map value) value - , 'gen-code.schema/GenCodeState + state $ schema/read-draft $ schema/read-open-field-or states :data initial-state loading? $ :loading? state wire-dispatch $ fn (dispatch!) hint-fn $ Fn @@ -646,9 +642,7 @@ (:err _) store-data (:ok raw) let - state $ decode-map-as - if (struct? raw) (&struct:to-map raw) raw - , 'gen-code.schema/GenCodeState + state $ read-draft raw if (:loading? state) struct-with store-data $ :states $ decode-map-as assoc-in (:states store-data) ([] :drafter :data) (assoc state :loading? false) @@ -737,6 +731,13 @@ :: (&enum:nth op 0) & $ &enum:params op :examples $ [] :schema $ quote $ Fn GenCodeOp (-> AnyEnum) (:open :reflect) + 'read-draft $ %{} 'CodeEntry (:doc |) + :code $ quote $ defn read-draft (raw) + decode-map-as + if (struct? raw) (&struct:to-map raw) raw + , 'gen-code.schema/GenCodeState + :examples $ [] + :schema $ quote $ Fn Input (-> GenCodeState) (:generics Input) 'read-open-field-or $ %{} 'CodeEntry :doc "|Read an open Map/Struct field; missing and nil values use the fallback, while false and Option payloads remain unchanged." :code $ quote $ defn read-open-field-or (value field fallback) From 4275bf474cc05b0e657f63a8f1493a2f965ab604 Mon Sep 17 00:00:00 2001 From: tiye Date: Sat, 14 Nov 2026 09:01:51 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=B8=BA=20Gen=20Code=20=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E5=85=B7=E5=90=8D=E9=87=8D=E7=BD=AE=E6=B4=BE?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- calcit.cirru | 66 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 428bd70..6dc4359 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Respo **0.19.3**、JS-FFI **0.2.12** / Router **0.12.0**。消费者需统一精 `use-gen-code` 返回插件,`.render` 生成界面,`.reset-state` 向传入的 dispatch 发送一个 `:: :states cursor state` 事件。提交回调接收代码字符串和 dispatch,继续遵守单事件合同。 -类型化宿主可用 `use-gen-code-with-dispatch` 并传入从 `GenCodeOp` 到宿主操作类型的转换函数。内置 Demo 直接派发具名事件。原 `use-gen-code` 仍为旧宿主发送匿名事件。 +类型化宿主可用 `use-gen-code-with-dispatch` 并传入从 `GenCodeOp` 到宿主操作类型的转换函数。内置 Demo 直接派发具名事件。原 `use-gen-code` 仍为旧宿主发送匿名事件。 类型化宿主可调用 `(.reset-state-with plugin emit!)`,其中 `emit!` 接收具名 `GenCodeOp`,可复用传给 `use-gen-code-with-dispatch` 的转换函数。 开放 Map/Struct 字段读取如实返回 Dynamic:缺失或显式 nil 使用 fallback,false 和 Option 载荷原样保留。不能直接换为会展开 Option 的 field-or。外部同名 StoreData 仅作为数据输入,转 Map、检查 states 和嵌套状态,再重建本地类型;名称不代表身份,见 [#41](https://github.com/calcit-lang/gen-code/issues/41)。 diff --git a/calcit.cirru b/calcit.cirru index 6aafcdf..f3e2703 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -81,6 +81,13 @@ match self $ :plugin r cursor state d! $ gen-code.schema/plugin-op-to-wire $ gen-code.schema/GenCodeOp :states cursor initial-state + .reset-state-with $ fn (self emit!) + hint-fn $ Fn GenCodePluginData0 + Fn schema/GenCodeOp $ -> Unit + -> Unit + match self $ + :plugin r cursor state + emit! $ gen-code.schema/GenCodeOp :states cursor initial-state :examples $ [] :schema $ quote Impl '*abort-control $ %{} 'CodeEntry (:doc |) @@ -121,33 +128,52 @@ Fn AnyEnum $ -> Unit -> Unit :generics T + .reset-state-with $ Fn T + Fn gen-code.schema/GenCodeOp $ -> Unit + -> Unit + :generics T :examples $ [] :schema $ quote Trait 'GenCodePluginData $ %{} 'CodeEntry (:doc |) :code $ quote $ def GenCodePluginData (impl-traits GenCodePluginData0 %gen-code-actions) :examples $ [] :schema $ quote EnumDef - :tests $ [] $ %{} 'TestEntry (:name |render-and-reset-contract) - :code $ quote $ let - *renders $ ref 0 - *reset $ ref $ :: :states ([] :initial) initial-state - render-node $ fn () - hint-fn $ Fn $ -> respo.schema/Element - swap! *renders inc + :tests $ [] + %{} 'TestEntry (:name |render-and-reset-contract) + :code $ quote $ let + *renders $ ref 0 + *reset $ ref $ :: :states ([] :initial) initial-state + render-node $ fn () + hint-fn $ Fn $ -> respo.schema/Element + swap! *renders inc + div $ {} + plugin $ %:: GenCodePluginData :plugin render-node ([] :drafter) initial-state + node $ .render plugin + assert= div $ {} - plugin $ %:: GenCodePluginData :plugin render-node ([] :drafter) initial-state - node $ .render plugin - assert= - div $ {} - , node - .reset-state plugin $ fn (op) - hint-fn $ Fn AnyEnum $ -> Unit - reset! *reset op - , &unit - assert= 1 @*renders - assert= - :: :states ([] :drafter) initial-state - , @*reset + , node + .reset-state plugin $ fn (op) + hint-fn $ Fn AnyEnum $ -> Unit + reset! *reset op + , &unit + assert= 1 @*renders + assert= + :: :states ([] :drafter) initial-state + , @*reset + %{} 'TestEntry (:name |nominal-reset) + :code $ quote $ let + captured $ ref $ gen-code.schema/GenCodeOp :states ([] :initial) initial-state + plugin $ %:: GenCodePluginData :plugin + fn () $ div $ {} + [] :drafter + , initial-state + .reset-state-with plugin $ fn (op) + hint-fn $ Fn schema/GenCodeOp $ -> Unit + reset! captured op + , &unit + assert= + gen-code.schema/GenCodeOp :states ([] :drafter) initial-state + , @captured 'GenCodePluginData0 $ %{} 'CodeEntry (:doc |) :code $ quote $ defenum GenCodePluginData0 :plugin From 8e871dbad65902c2b5561bd073ef12a49a95d968 Mon Sep 17 00:00:00 2001 From: tiye Date: Sat, 14 Nov 2026 11:18:46 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=A3=80=E6=9F=A5=20Gen=20Code=20=E6=B5=81?= =?UTF-8?q?=E5=BC=8F=E6=96=87=E6=9C=AC=E7=9A=84=E5=AE=BF=E4=B8=BB=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- calcit.cirru | 4 +++- tests/stream-contract.mjs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/calcit.cirru b/calcit.cirru index f3e2703..6dc56ab 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -847,7 +847,9 @@ 'read-genai-chunk $ %{} 'CodeEntry :doc "|Read the stream text from its typed host boundary." :code $ quote $ defn read-genai-chunk (value) - .-text $ unsafe-coerce value GenAIChunkHost + .-text $ js-cast + if (js/Reflect.has value |text) value $ js-object $ :text js/undefined + , GenAIChunkHost :examples $ [] :schema $ quote $ Fn JsObject -> $ JsNullish String diff --git a/tests/stream-contract.mjs b/tests/stream-contract.mjs index 0c51960..4873549 100644 --- a/tests/stream-contract.mjs +++ b/tests/stream-contract.mjs @@ -106,6 +106,7 @@ const patches = []; const keyboardPatches = []; const fakeChat = { async *sendMessageStream() { + yield {}; yield { text: '["println","|offline"]' }; }, };