@guuey/chat 0.12.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/policy.d.ts +12 -2
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +0 -1
- package/dist/react/guuey-chat.d.ts +7 -3
- package/dist/react/guuey-chat.d.ts.map +1 -1
- package/dist/react/guuey-chat.js +39 -22
- package/dist/strings.d.ts +0 -1
- package/dist/strings.d.ts.map +1 -1
- package/dist/strings.js +23 -0
- package/dist/theme.d.ts +166 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +93 -0
- package/package.json +4 -4
- package/src/index.ts +6 -0
- package/src/policy.ts +13 -3
- package/src/react/guuey-chat.tsx +50 -27
- package/src/strings.ts +23 -0
- package/src/theme.ts +106 -0
package/dist/index.d.ts
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* rendering, tests, and RN bundlers consume the view-model directly.
|
|
12
12
|
*/
|
|
13
13
|
export { newestViewKey, planTranscript, } from "./plan.js";
|
|
14
|
-
export { calmPolicy, debugPolicy, type TranscriptPolicy, } from "./policy.js";
|
|
14
|
+
export { calmPolicy, type TranscriptPolicyOverrides, debugPolicy, type TranscriptPolicy, } from "./policy.js";
|
|
15
15
|
export { defaultChatStrings, humanizeToolName, type ChatStrings, } from "./strings.js";
|
|
16
16
|
export { transcriptInputsFromHistory } from "./history-inputs.js";
|
|
17
17
|
export { buildHitlAnswer, grantModeDisplay, hitlPromptsFromFold, type HitlAnswerRecord, type HitlPromptAction, } from "./hitl.js";
|
|
18
18
|
export { OAUTH_LINK_PARAMS, OAUTH_RETURN_PARAMS, OAUTH_SCHEME, oauthAuthorizeAsk, oauthAuthorizeHref, parseOAuthReturn, stripOAuthReturn, type OAuthAuthorizeAsk, type OAuthReturn, } from "./oauth.js";
|
|
19
|
-
export { DEFAULT_CHAT_THEME, GUUEY_CHAT_THEME, GuueyChatPalette, GuueyChatTheme, resolveTheme, } from "./theme.js";
|
|
19
|
+
export { DEFAULT_CHAT_THEME, GUUEY_CHAT_THEME, GuueyChatAccentRamp, GuueyChatErrorRamp, GuueyChatPalette, GuueyChatRamps, GuueyChatRampSet, GuueyChatTheme, GuueyChatToneRamp, resolveTheme, } from "./theme.js";
|
|
20
20
|
export type { ChatDebugEvent, CitationsItem, CodeItem, CompactionItem, DataResultItem, DisplayItem, ErrorItem, HistoryBoundaryItem, ItemKey, HitlPromptInput, HitlPromptItem, MediaItem, NoticeItem, ProfilePromptInput, ProfilePromptItem, PromptItem, PromptItemInput, ReasoningItem, StatusLineItem, TextItem, ToolGroupItem, ToolItem, TranscriptInputs, TranscriptMessage, TranscriptOverrides, TranscriptPlan, PlanViewSummary, UnknownItem, UserMessageItem, ViewMountItem, ViewRefItem, } from "./types.js";
|
|
21
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,aAAa,EACb,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,UAAU,EACV,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,eAAe,EACf,cAAc,EACd,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,cAAc,EACd,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,aAAa,EACb,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,UAAU,EACV,KAAK,yBAAyB,EAC9B,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,eAAe,EACf,cAAc,EACd,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,cAAc,EACd,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -16,4 +16,4 @@ export { defaultChatStrings, humanizeToolName, } from "./strings.js";
|
|
|
16
16
|
export { transcriptInputsFromHistory } from "./history-inputs.js";
|
|
17
17
|
export { buildHitlAnswer, grantModeDisplay, hitlPromptsFromFold, } from "./hitl.js";
|
|
18
18
|
export { OAUTH_LINK_PARAMS, OAUTH_RETURN_PARAMS, OAUTH_SCHEME, oauthAuthorizeAsk, oauthAuthorizeHref, parseOAuthReturn, stripOAuthReturn, } from "./oauth.js";
|
|
19
|
-
export { DEFAULT_CHAT_THEME, GUUEY_CHAT_THEME, GuueyChatPalette, GuueyChatTheme, resolveTheme, } from "./theme.js";
|
|
19
|
+
export { DEFAULT_CHAT_THEME, GUUEY_CHAT_THEME, GuueyChatAccentRamp, GuueyChatErrorRamp, GuueyChatPalette, GuueyChatRamps, GuueyChatRampSet, GuueyChatTheme, GuueyChatToneRamp, resolveTheme, } from "./theme.js";
|
package/dist/policy.d.ts
CHANGED
|
@@ -115,8 +115,18 @@ export interface TranscriptPolicy {
|
|
|
115
115
|
raw: boolean;
|
|
116
116
|
};
|
|
117
117
|
}
|
|
118
|
+
/** Deep-ish merge for the one level of nesting policies actually have. */
|
|
119
|
+
/**
|
|
120
|
+
* Per-section partial overrides — the shape `withOverrides` actually
|
|
121
|
+
* merges (each section spreads over its base), so the type tells the
|
|
122
|
+
* truth: `{ view: { presentation: 'chips' } }` is valid without
|
|
123
|
+
* restating the section's other fields (guuey#321 surfaced the lie).
|
|
124
|
+
*/
|
|
125
|
+
export type TranscriptPolicyOverrides = {
|
|
126
|
+
[K in keyof TranscriptPolicy]?: Partial<TranscriptPolicy[K]>;
|
|
127
|
+
};
|
|
118
128
|
/** The `calm` preset — the end-user default (spec §5). */
|
|
119
|
-
export declare function calmPolicy(overrides?:
|
|
129
|
+
export declare function calmPolicy(overrides?: TranscriptPolicyOverrides): TranscriptPolicy;
|
|
120
130
|
/** The `debug` preset — the builder surface (Studio's test chat, spec §5). */
|
|
121
|
-
export declare function debugPolicy(overrides?:
|
|
131
|
+
export declare function debugPolicy(overrides?: TranscriptPolicyOverrides): TranscriptPolicy;
|
|
122
132
|
//# sourceMappingURL=policy.d.ts.map
|
package/dist/policy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,WAAW,CAAC;IACrB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU;IACV,WAAW,EAAE;QAAE,eAAe,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,+EAA+E;IAC/E,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5B,UAAU;IACV,SAAS,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,UAAU;IACV,IAAI,EAAE;QACJ,eAAe,EAAE,OAAO,CAAC;QACzB,WAAW,EAAE,OAAO,CAAC;QACrB,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;KAC7C,CAAC;IACF,iEAAiE;IACjE,SAAS,EAAE;QAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAC;IACzC,UAAU;IACV,UAAU,EAAE;QACV,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;QACzB,+EAA+E;QAC/E,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;;;;;;OAOG;IACH,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAA;KAAE,CAAC;IAC9D,UAAU;IACV,KAAK,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IACxD,UAAU;IACV,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,UAAU;IACV,SAAS,EAAE;QAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC,WAAW;IACX,MAAM,EAAE;QAAE,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/D;;;;;;;;;;;OAWG;IACH,KAAK,EAAE;QACL,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;KAC1C,CAAC;IACF,oFAAoF;IACpF,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,4EAA4E;IAC5E,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1B,WAAW;IACX,UAAU,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,WAAW;IACX,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
package/dist/policy.js
CHANGED
|
@@ -48,7 +48,7 @@ import { type CSSProperties } from "react";
|
|
|
48
48
|
import { type AgentInvokeAdapters } from "@guuey/agent-client";
|
|
49
49
|
import type { AgHitlAnswer, AgPausedAsk } from "@silverprotocol/core";
|
|
50
50
|
import type { UiResourceReader } from "@guuey/mcp-apps-host";
|
|
51
|
-
import { type
|
|
51
|
+
import { type TranscriptPolicyOverrides } from "../policy.js";
|
|
52
52
|
import { type ChatStrings } from "../strings.js";
|
|
53
53
|
import { type GuueyChatTheme } from "../theme.js";
|
|
54
54
|
import type { ChatDebugEvent, ErrorItem, PlanViewSummary, PromptItem, ViewRefItem } from "../types.js";
|
|
@@ -146,8 +146,12 @@ export interface GuueyChatProps {
|
|
|
146
146
|
adapters?: AgentInvokeAdapters;
|
|
147
147
|
/** Policy preset (spec §5). Default `"calm"`. */
|
|
148
148
|
preset?: "calm" | "debug";
|
|
149
|
-
/**
|
|
150
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Knob overrides applied on top of the preset (spec §3's columns) —
|
|
151
|
+
* per-SECTION partials (`{ view: { presentation: "chips" } }` needs no
|
|
152
|
+
* other view fields; guuey#321 made the type tell the merge's truth).
|
|
153
|
+
*/
|
|
154
|
+
policy?: TranscriptPolicyOverrides;
|
|
151
155
|
/** Per-slot component overrides (spec §3's override column). */
|
|
152
156
|
components?: Partial<TranscriptComponents>;
|
|
153
157
|
/** String overrides — merged over the preset's `ChatStrings` (§4.2). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guuey-chat.d.ts","sourceRoot":"","sources":["../../src/react/guuey-chat.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,EASL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AACf,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,KAAK,EAAsC,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAA2B,KAAK,
|
|
1
|
+
{"version":3,"file":"guuey-chat.d.ts","sourceRoot":"","sources":["../../src/react/guuey-chat.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,EASL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AACf,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,KAAK,EAAsC,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAA2B,KAAK,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEvF,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,eAAe,EACf,UAAU,EAEV,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIlG;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,EAC7C,IAAI,EAAE,SAAS,EACf,QAAQ,GAAE,IAAI,CAAC,aAAa,EAAE,YAAY,GAAG,sBAAsB,CAAM,GACxE,qBAAqB,CAAC,WAAW,CAAC,CAgBpC;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1E,gCAAgC;IAChC,aAAa,IAAI,IAAI,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;;;;;OAQG;IACH,aAAa,IAAI,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3C,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wDAAwD;IACxD,MAAM,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,oEAAoE;IACpE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC/C,uEAAuE;IACvE,SAAS,CAAC,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAC/C;;;;OAIG;IACH,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAC/D,IAAI,CAAC;IACV;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;IAChE;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5D,qDAAqD;IACrD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAQD,eAAO,MAAM,SAAS,4GA6cpB,CAAC"}
|
package/dist/react/guuey-chat.js
CHANGED
|
@@ -48,7 +48,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
48
48
|
import { forwardRef, useCallback, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, } from "react";
|
|
49
49
|
import { createUiActionRelay, createUiResourceReader, createWebAdapters, } from "@guuey/agent-client";
|
|
50
50
|
import { useAgentInvoke } from "@guuey/agent-client/react";
|
|
51
|
-
import { unavailableToolCallResult } from "@guuey/mcp-apps-host";
|
|
51
|
+
import { unavailableToolCallResult, withActionStaging } from "@guuey/mcp-apps-host";
|
|
52
52
|
import { calmPolicy, debugPolicy } from "../policy.js";
|
|
53
53
|
import { useStructuralIdentity } from "./structural-identity.js";
|
|
54
54
|
import { defaultChatStrings } from "../strings.js";
|
|
@@ -205,6 +205,24 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
|
|
|
205
205
|
// `viewProps.hostContext` keys win; `theme` is only defaulted. Hosts
|
|
206
206
|
// mounting views DIRECTLY (a canvas over the roster) announce on their
|
|
207
207
|
// own <GuueyView hostContext> — this covers the kit's own mounts.
|
|
208
|
+
// ── Composer ─────────────────────────────────────────────────────────
|
|
209
|
+
const [input, setInput] = useState("");
|
|
210
|
+
const inputRef = useRef(null);
|
|
211
|
+
// Browser form-field heuristics (a11y/autofill lints) flag a field with
|
|
212
|
+
// neither id nor name on every embedding site. useId keeps the id unique
|
|
213
|
+
// when several chats mount on one page — a static id would collide.
|
|
214
|
+
const composerId = useId();
|
|
215
|
+
const busy = invoke.status !== "ready";
|
|
216
|
+
const available = endpointUrl !== null;
|
|
217
|
+
const canSend = available && !busy && input.trim() !== "";
|
|
218
|
+
// ── The imperative seam (guuey#210) ──────────────────────────────────
|
|
219
|
+
// ONE stable handle for the component's whole life (hosts capture it in
|
|
220
|
+
// `onReady` and keep it), reading live truth through a ref so a call
|
|
221
|
+
// always sees the CURRENT gate — never a stale closure's.
|
|
222
|
+
const liveRef = useRef({ available, busy, invoke, onReady });
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
liveRef.current = { available, busy, invoke, onReady };
|
|
225
|
+
});
|
|
208
226
|
// The DEFAULT ACTION RELAY (guuey#335 — the founder-hit Confirm bug):
|
|
209
227
|
// pod-then-persisted, built over the SAME identity as the reader, thread
|
|
210
228
|
// read through the ref at CALL time. Without it, a kit-mounted render's
|
|
@@ -242,10 +260,27 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
|
|
|
242
260
|
byteSize: JSON.stringify(params)?.length ?? 0,
|
|
243
261
|
});
|
|
244
262
|
}, []);
|
|
263
|
+
// Post-turn action STAGING (guuey#356 — the widget's ratified #198/#215/
|
|
264
|
+
// #218 policy, ONE copy in the kit): with no live turn, an allowlisted
|
|
265
|
+
// semantic card action stages its human-readable projection into the
|
|
266
|
+
// composer (append, never clobber — the staged-composer semantic) and the
|
|
267
|
+
// view hears the queued acceptance; everything else rides the relay path
|
|
268
|
+
// untouched. Rides viewSlotProps too, so canvas hosts get it for free.
|
|
269
|
+
const stagedDefaultOnCallTool = useMemo(() => {
|
|
270
|
+
if (defaultOnCallTool === undefined)
|
|
271
|
+
return undefined;
|
|
272
|
+
return withActionStaging(defaultOnCallTool, {
|
|
273
|
+
isTurnLive: () => liveRef.current.busy,
|
|
274
|
+
stage: (text) => {
|
|
275
|
+
setInput((prev) => (prev.trim() === "" ? text : `${prev.trimEnd()} ${text}`));
|
|
276
|
+
inputRef.current?.focus();
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}, [defaultOnCallTool]);
|
|
245
280
|
const effectiveViewProps = useMemo(() => viewPropsWithThemeAnnounce(viewProps, mode, {
|
|
246
|
-
...(
|
|
281
|
+
...(stagedDefaultOnCallTool !== undefined ? { onCallTool: stagedDefaultOnCallTool } : {}),
|
|
247
282
|
onUpdateModelContext: defaultOnUpdateModelContext,
|
|
248
|
-
}), [viewProps, mode,
|
|
283
|
+
}), [viewProps, mode, stagedDefaultOnCallTool, defaultOnUpdateModelContext]);
|
|
249
284
|
// The canvas-host door (guuey#335): a host mounting views DIRECTLY from
|
|
250
285
|
// the roster (the chat-rail shell) needs the SAME slot wiring the kit's
|
|
251
286
|
// inline mounts get — theme announce, action relay, context sink. Read
|
|
@@ -256,29 +291,11 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
|
|
|
256
291
|
staticSlotPropsRef.current =
|
|
257
292
|
typeof effectiveViewProps === "function"
|
|
258
293
|
? {
|
|
259
|
-
...(
|
|
294
|
+
...(stagedDefaultOnCallTool !== undefined ? { onCallTool: stagedDefaultOnCallTool } : {}),
|
|
260
295
|
onUpdateModelContext: defaultOnUpdateModelContext,
|
|
261
296
|
hostContext: { theme: mode },
|
|
262
297
|
}
|
|
263
298
|
: (effectiveViewProps ?? {});
|
|
264
|
-
// ── Composer ─────────────────────────────────────────────────────────
|
|
265
|
-
const [input, setInput] = useState("");
|
|
266
|
-
const inputRef = useRef(null);
|
|
267
|
-
// Browser form-field heuristics (a11y/autofill lints) flag a field with
|
|
268
|
-
// neither id nor name on every embedding site. useId keeps the id unique
|
|
269
|
-
// when several chats mount on one page — a static id would collide.
|
|
270
|
-
const composerId = useId();
|
|
271
|
-
const busy = invoke.status !== "ready";
|
|
272
|
-
const available = endpointUrl !== null;
|
|
273
|
-
const canSend = available && !busy && input.trim() !== "";
|
|
274
|
-
// ── The imperative seam (guuey#210) ──────────────────────────────────
|
|
275
|
-
// ONE stable handle for the component's whole life (hosts capture it in
|
|
276
|
-
// `onReady` and keep it), reading live truth through a ref so a call
|
|
277
|
-
// always sees the CURRENT gate — never a stale closure's.
|
|
278
|
-
const liveRef = useRef({ available, busy, invoke, onReady });
|
|
279
|
-
useEffect(() => {
|
|
280
|
-
liveRef.current = { available, busy, invoke, onReady };
|
|
281
|
-
});
|
|
282
299
|
const handle = useMemo(() => ({
|
|
283
300
|
send: (text) => {
|
|
284
301
|
const live = liveRef.current;
|
package/dist/strings.d.ts
CHANGED
|
@@ -106,7 +106,6 @@ export interface ChatStrings {
|
|
|
106
106
|
send: string;
|
|
107
107
|
stop: string;
|
|
108
108
|
}
|
|
109
|
-
/** Humanize a wire tool name: `render_weather-card` → `render weather card`. */
|
|
110
109
|
export declare function humanizeToolName(wireName: string): string;
|
|
111
110
|
export declare const defaultChatStrings: ChatStrings;
|
|
112
111
|
//# sourceMappingURL=strings.d.ts.map
|
package/dist/strings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"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"}
|
package/dist/strings.js
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
/** Humanize a wire tool name: `render_weather-card` → `render weather card`. */
|
|
2
|
+
/**
|
|
3
|
+
* The ggui generative-UI rail's tool vocabulary, in end-user words
|
|
4
|
+
* (guuey#307): raw wire names ("mcp ggui ggui handshake") read as
|
|
5
|
+
* internals on every card-bearing conversation — and the rail is the
|
|
6
|
+
* platform default (mcp.ggui.ai), so the kit owns its voice the same
|
|
7
|
+
* way it owns the card machinery.
|
|
8
|
+
*/
|
|
9
|
+
const GGUI_RAIL_TITLES = {
|
|
10
|
+
ggui_handshake: "Preparing interactive card",
|
|
11
|
+
ggui_render: "Rendering card",
|
|
12
|
+
ggui_consume: "Updating interactive card",
|
|
13
|
+
ggui_update: "Updating card",
|
|
14
|
+
};
|
|
2
15
|
export function humanizeToolName(wireName) {
|
|
16
|
+
// MCP wire shape: `mcp__<server>__<tool>` (double-underscore separators).
|
|
17
|
+
const mcp = /^mcp__([^_].*?)__(.+)$/.exec(wireName);
|
|
18
|
+
if (mcp) {
|
|
19
|
+
const [, server, tool] = mcp;
|
|
20
|
+
if (server === "ggui" && GGUI_RAIL_TITLES[tool])
|
|
21
|
+
return GGUI_RAIL_TITLES[tool];
|
|
22
|
+
const prettyServer = server.charAt(0).toUpperCase() + server.slice(1).replace(/[_-]+/g, " ");
|
|
23
|
+
const prettyTool = tool.replace(/[_-]+/g, " ").trim();
|
|
24
|
+
return `${prettyServer} · ${prettyTool}`;
|
|
25
|
+
}
|
|
3
26
|
return wireName.replace(/[_-]+/g, " ").trim();
|
|
4
27
|
}
|
|
5
28
|
export const defaultChatStrings = {
|
package/dist/theme.d.ts
CHANGED
|
@@ -34,8 +34,122 @@ export declare const GuueyChatPalette: z.ZodObject<{
|
|
|
34
34
|
error: z.ZodString;
|
|
35
35
|
}, z.core.$loose>;
|
|
36
36
|
export type GuueyChatPalette = z.infer<typeof GuueyChatPalette>;
|
|
37
|
+
/**
|
|
38
|
+
* STATED ramp slots (theme-as-code, guuey#341 spec §3 — never derived).
|
|
39
|
+
* Closed per-family sets: `accent` carries the full ladder (the
|
|
40
|
+
* 500/600/700 floor is a WRITE/COMPILE rule, not a schema rule — the
|
|
41
|
+
* schema admits any stated subset so a stale stored document still parses);
|
|
42
|
+
* the status families carry their tone-500 slot. Ramps live BESIDE the
|
|
43
|
+
* palettes (`theme.ramps.{light,dark}`), never inside them — the flat
|
|
44
|
+
* palette record is a load-bearing invariant (token lists are DERIVED from
|
|
45
|
+
* its shape by every platform gate).
|
|
46
|
+
*/
|
|
47
|
+
export declare const GuueyChatAccentRamp: z.ZodObject<{
|
|
48
|
+
"100": z.ZodOptional<z.ZodString>;
|
|
49
|
+
"300": z.ZodOptional<z.ZodString>;
|
|
50
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
51
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
52
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
53
|
+
"800": z.ZodOptional<z.ZodString>;
|
|
54
|
+
"900": z.ZodOptional<z.ZodString>;
|
|
55
|
+
}, z.core.$loose>;
|
|
56
|
+
export type GuueyChatAccentRamp = z.infer<typeof GuueyChatAccentRamp>;
|
|
57
|
+
export declare const GuueyChatErrorRamp: z.ZodObject<{
|
|
58
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
59
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
60
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
61
|
+
}, z.core.$loose>;
|
|
62
|
+
export type GuueyChatErrorRamp = z.infer<typeof GuueyChatErrorRamp>;
|
|
63
|
+
export declare const GuueyChatToneRamp: z.ZodObject<{
|
|
64
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
65
|
+
}, z.core.$loose>;
|
|
66
|
+
export type GuueyChatToneRamp = z.infer<typeof GuueyChatToneRamp>;
|
|
67
|
+
/** One mode's stated ramp families — every family optional. */
|
|
68
|
+
export declare const GuueyChatRampSet: z.ZodObject<{
|
|
69
|
+
accent: z.ZodOptional<z.ZodObject<{
|
|
70
|
+
"100": z.ZodOptional<z.ZodString>;
|
|
71
|
+
"300": z.ZodOptional<z.ZodString>;
|
|
72
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
73
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
74
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
75
|
+
"800": z.ZodOptional<z.ZodString>;
|
|
76
|
+
"900": z.ZodOptional<z.ZodString>;
|
|
77
|
+
}, z.core.$loose>>;
|
|
78
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
79
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
80
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
81
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
82
|
+
}, z.core.$loose>>;
|
|
83
|
+
success: z.ZodOptional<z.ZodObject<{
|
|
84
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
85
|
+
}, z.core.$loose>>;
|
|
86
|
+
warning: z.ZodOptional<z.ZodObject<{
|
|
87
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
88
|
+
}, z.core.$loose>>;
|
|
89
|
+
info: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
91
|
+
}, z.core.$loose>>;
|
|
92
|
+
}, z.core.$loose>;
|
|
93
|
+
export type GuueyChatRampSet = z.infer<typeof GuueyChatRampSet>;
|
|
94
|
+
export declare const GuueyChatRamps: z.ZodObject<{
|
|
95
|
+
light: z.ZodOptional<z.ZodObject<{
|
|
96
|
+
accent: z.ZodOptional<z.ZodObject<{
|
|
97
|
+
"100": z.ZodOptional<z.ZodString>;
|
|
98
|
+
"300": z.ZodOptional<z.ZodString>;
|
|
99
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
100
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
101
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
102
|
+
"800": z.ZodOptional<z.ZodString>;
|
|
103
|
+
"900": z.ZodOptional<z.ZodString>;
|
|
104
|
+
}, z.core.$loose>>;
|
|
105
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
106
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
107
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
108
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
109
|
+
}, z.core.$loose>>;
|
|
110
|
+
success: z.ZodOptional<z.ZodObject<{
|
|
111
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
112
|
+
}, z.core.$loose>>;
|
|
113
|
+
warning: z.ZodOptional<z.ZodObject<{
|
|
114
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
115
|
+
}, z.core.$loose>>;
|
|
116
|
+
info: z.ZodOptional<z.ZodObject<{
|
|
117
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
118
|
+
}, z.core.$loose>>;
|
|
119
|
+
}, z.core.$loose>>;
|
|
120
|
+
dark: z.ZodOptional<z.ZodObject<{
|
|
121
|
+
accent: z.ZodOptional<z.ZodObject<{
|
|
122
|
+
"100": z.ZodOptional<z.ZodString>;
|
|
123
|
+
"300": z.ZodOptional<z.ZodString>;
|
|
124
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
125
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
126
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
127
|
+
"800": z.ZodOptional<z.ZodString>;
|
|
128
|
+
"900": z.ZodOptional<z.ZodString>;
|
|
129
|
+
}, z.core.$loose>>;
|
|
130
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
131
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
132
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
133
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
134
|
+
}, z.core.$loose>>;
|
|
135
|
+
success: z.ZodOptional<z.ZodObject<{
|
|
136
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
137
|
+
}, z.core.$loose>>;
|
|
138
|
+
warning: z.ZodOptional<z.ZodObject<{
|
|
139
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
140
|
+
}, z.core.$loose>>;
|
|
141
|
+
info: z.ZodOptional<z.ZodObject<{
|
|
142
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
143
|
+
}, z.core.$loose>>;
|
|
144
|
+
}, z.core.$loose>>;
|
|
145
|
+
}, z.core.$loose>;
|
|
146
|
+
export type GuueyChatRamps = z.infer<typeof GuueyChatRamps>;
|
|
37
147
|
export declare const GuueyChatTheme: z.ZodObject<{
|
|
38
148
|
name: z.ZodString;
|
|
149
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
150
|
+
light: "light";
|
|
151
|
+
dark: "dark";
|
|
152
|
+
}>>;
|
|
39
153
|
colors: z.ZodObject<{
|
|
40
154
|
light: z.ZodObject<{
|
|
41
155
|
accent: z.ZodString;
|
|
@@ -58,6 +172,58 @@ export declare const GuueyChatTheme: z.ZodObject<{
|
|
|
58
172
|
error: z.ZodString;
|
|
59
173
|
}, z.core.$loose>;
|
|
60
174
|
}, z.core.$loose>;
|
|
175
|
+
ramps: z.ZodOptional<z.ZodObject<{
|
|
176
|
+
light: z.ZodOptional<z.ZodObject<{
|
|
177
|
+
accent: z.ZodOptional<z.ZodObject<{
|
|
178
|
+
"100": z.ZodOptional<z.ZodString>;
|
|
179
|
+
"300": z.ZodOptional<z.ZodString>;
|
|
180
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
181
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
182
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
183
|
+
"800": z.ZodOptional<z.ZodString>;
|
|
184
|
+
"900": z.ZodOptional<z.ZodString>;
|
|
185
|
+
}, z.core.$loose>>;
|
|
186
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
187
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
188
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
189
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
190
|
+
}, z.core.$loose>>;
|
|
191
|
+
success: z.ZodOptional<z.ZodObject<{
|
|
192
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
193
|
+
}, z.core.$loose>>;
|
|
194
|
+
warning: z.ZodOptional<z.ZodObject<{
|
|
195
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
196
|
+
}, z.core.$loose>>;
|
|
197
|
+
info: z.ZodOptional<z.ZodObject<{
|
|
198
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
199
|
+
}, z.core.$loose>>;
|
|
200
|
+
}, z.core.$loose>>;
|
|
201
|
+
dark: z.ZodOptional<z.ZodObject<{
|
|
202
|
+
accent: z.ZodOptional<z.ZodObject<{
|
|
203
|
+
"100": z.ZodOptional<z.ZodString>;
|
|
204
|
+
"300": z.ZodOptional<z.ZodString>;
|
|
205
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
206
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
207
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
208
|
+
"800": z.ZodOptional<z.ZodString>;
|
|
209
|
+
"900": z.ZodOptional<z.ZodString>;
|
|
210
|
+
}, z.core.$loose>>;
|
|
211
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
212
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
213
|
+
"600": z.ZodOptional<z.ZodString>;
|
|
214
|
+
"700": z.ZodOptional<z.ZodString>;
|
|
215
|
+
}, z.core.$loose>>;
|
|
216
|
+
success: z.ZodOptional<z.ZodObject<{
|
|
217
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
218
|
+
}, z.core.$loose>>;
|
|
219
|
+
warning: z.ZodOptional<z.ZodObject<{
|
|
220
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
221
|
+
}, z.core.$loose>>;
|
|
222
|
+
info: z.ZodOptional<z.ZodObject<{
|
|
223
|
+
"500": z.ZodOptional<z.ZodString>;
|
|
224
|
+
}, z.core.$loose>>;
|
|
225
|
+
}, z.core.$loose>>;
|
|
226
|
+
}, z.core.$loose>>;
|
|
61
227
|
typography: z.ZodObject<{
|
|
62
228
|
fontFamily: z.ZodOptional<z.ZodString>;
|
|
63
229
|
monoFontFamily: z.ZodOptional<z.ZodString>;
|
package/dist/theme.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;iBAWnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;iBAWnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;iBAUtB,CAAC;AACX,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,eAAO,MAAM,kBAAkB;;;;iBAMrB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,eAAO,MAAM,iBAAiB;;iBAAqD,CAAC;AACpF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;iBAQnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8BjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,cA0BhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,cA0B9B,CAAC;AA4CF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,OAAO,EAClB,IAAI,GAAE,cAAmC,GACxC,cAAc,CAuBhB"}
|
package/dist/theme.js
CHANGED
|
@@ -35,11 +35,67 @@ export const GuueyChatPalette = z
|
|
|
35
35
|
error: z.string(),
|
|
36
36
|
})
|
|
37
37
|
.loose();
|
|
38
|
+
/**
|
|
39
|
+
* STATED ramp slots (theme-as-code, guuey#341 spec §3 — never derived).
|
|
40
|
+
* Closed per-family sets: `accent` carries the full ladder (the
|
|
41
|
+
* 500/600/700 floor is a WRITE/COMPILE rule, not a schema rule — the
|
|
42
|
+
* schema admits any stated subset so a stale stored document still parses);
|
|
43
|
+
* the status families carry their tone-500 slot. Ramps live BESIDE the
|
|
44
|
+
* palettes (`theme.ramps.{light,dark}`), never inside them — the flat
|
|
45
|
+
* palette record is a load-bearing invariant (token lists are DERIVED from
|
|
46
|
+
* its shape by every platform gate).
|
|
47
|
+
*/
|
|
48
|
+
export const GuueyChatAccentRamp = z
|
|
49
|
+
.object({
|
|
50
|
+
"100": z.string().optional(),
|
|
51
|
+
"300": z.string().optional(),
|
|
52
|
+
"500": z.string().optional(),
|
|
53
|
+
"600": z.string().optional(),
|
|
54
|
+
"700": z.string().optional(),
|
|
55
|
+
"800": z.string().optional(),
|
|
56
|
+
"900": z.string().optional(),
|
|
57
|
+
})
|
|
58
|
+
.loose();
|
|
59
|
+
export const GuueyChatErrorRamp = z
|
|
60
|
+
.object({
|
|
61
|
+
"500": z.string().optional(),
|
|
62
|
+
"600": z.string().optional(),
|
|
63
|
+
"700": z.string().optional(),
|
|
64
|
+
})
|
|
65
|
+
.loose();
|
|
66
|
+
export const GuueyChatToneRamp = z.object({ "500": z.string().optional() }).loose();
|
|
67
|
+
/** One mode's stated ramp families — every family optional. */
|
|
68
|
+
export const GuueyChatRampSet = z
|
|
69
|
+
.object({
|
|
70
|
+
accent: GuueyChatAccentRamp.optional(),
|
|
71
|
+
error: GuueyChatErrorRamp.optional(),
|
|
72
|
+
success: GuueyChatToneRamp.optional(),
|
|
73
|
+
warning: GuueyChatToneRamp.optional(),
|
|
74
|
+
info: GuueyChatToneRamp.optional(),
|
|
75
|
+
})
|
|
76
|
+
.loose();
|
|
77
|
+
export const GuueyChatRamps = z
|
|
78
|
+
.object({
|
|
79
|
+
light: GuueyChatRampSet.optional(),
|
|
80
|
+
dark: GuueyChatRampSet.optional(),
|
|
81
|
+
})
|
|
82
|
+
.loose();
|
|
38
83
|
export const GuueyChatTheme = z
|
|
39
84
|
.object({
|
|
40
85
|
name: z.string(),
|
|
86
|
+
/**
|
|
87
|
+
* The app's CANONICAL presentation mode (theme-as-code §3) — what the
|
|
88
|
+
* ggui stamp pins its render slice to. OPTIONAL and default-less on
|
|
89
|
+
* purpose: absent = "not stated", and the platform's legacy polarity
|
|
90
|
+
* derivation stands. Distinct from the VIEWER's runtime light/dark
|
|
91
|
+
* choice, which stays a component prop — chat components never read
|
|
92
|
+
* this field.
|
|
93
|
+
*/
|
|
94
|
+
mode: z.enum(["light", "dark"]).optional(),
|
|
41
95
|
/** BOTH palettes always present — mode is the consumer's runtime choice. */
|
|
42
96
|
colors: z.object({ light: GuueyChatPalette, dark: GuueyChatPalette }).loose(),
|
|
97
|
+
/** Stated ramp slots per mode — see {@link GuueyChatRamps}. */
|
|
98
|
+
ramps: GuueyChatRamps.optional(),
|
|
43
99
|
typography: z
|
|
44
100
|
.object({
|
|
45
101
|
fontFamily: z.string().optional(),
|
|
@@ -126,10 +182,12 @@ const PartialPalette = GuueyChatPalette.partial();
|
|
|
126
182
|
const PartialTheme = z
|
|
127
183
|
.object({
|
|
128
184
|
name: z.string().optional(),
|
|
185
|
+
mode: GuueyChatTheme.shape.mode.optional(),
|
|
129
186
|
colors: z
|
|
130
187
|
.object({ light: PartialPalette.optional(), dark: PartialPalette.optional() })
|
|
131
188
|
.loose()
|
|
132
189
|
.optional(),
|
|
190
|
+
ramps: GuueyChatRamps.optional(),
|
|
133
191
|
typography: GuueyChatTheme.shape.typography.optional(),
|
|
134
192
|
shape: GuueyChatTheme.shape.shape.partial().loose().optional(),
|
|
135
193
|
})
|
|
@@ -167,12 +225,19 @@ export function resolveTheme(candidate, base = DEFAULT_CHAT_THEME) {
|
|
|
167
225
|
if (!parsed.success)
|
|
168
226
|
return { ...base, colors: { light: { ...base.colors.light }, dark: { ...base.colors.dark } } };
|
|
169
227
|
const p = parsed.data;
|
|
228
|
+
const mode = p.mode ?? base.mode;
|
|
229
|
+
const ramps = mergeRamps(base.ramps, p.ramps);
|
|
170
230
|
return {
|
|
171
231
|
name: p.name ?? base.name,
|
|
232
|
+
// `mode`/`ramps` are default-less (the package themes state neither):
|
|
233
|
+
// they appear on the resolved theme only when SOME layer stated them —
|
|
234
|
+
// an absent statement must stay visibly absent, not become a default.
|
|
235
|
+
...(mode !== undefined ? { mode } : {}),
|
|
172
236
|
colors: {
|
|
173
237
|
light: mergePalette(base.colors.light, p.colors?.light),
|
|
174
238
|
dark: mergePalette(base.colors.dark, p.colors?.dark),
|
|
175
239
|
},
|
|
240
|
+
...(ramps !== undefined ? { ramps } : {}),
|
|
176
241
|
typography: { ...base.typography, ...(p.typography ?? {}) },
|
|
177
242
|
shape: {
|
|
178
243
|
radius: p.shape?.radius ?? base.shape.radius,
|
|
@@ -180,3 +245,31 @@ export function resolveTheme(candidate, base = DEFAULT_CHAT_THEME) {
|
|
|
180
245
|
},
|
|
181
246
|
};
|
|
182
247
|
}
|
|
248
|
+
/** Slot-level merge of two ramp statements (candidate slots win per slot). */
|
|
249
|
+
function mergeRampSet(base, over) {
|
|
250
|
+
if (base === undefined)
|
|
251
|
+
return over;
|
|
252
|
+
if (over === undefined)
|
|
253
|
+
return base;
|
|
254
|
+
const merged = { ...base };
|
|
255
|
+
for (const family of ["accent", "error", "success", "warning", "info"]) {
|
|
256
|
+
const b = base[family];
|
|
257
|
+
const o = over[family];
|
|
258
|
+
if (o === undefined)
|
|
259
|
+
continue;
|
|
260
|
+
merged[family] = b === undefined ? o : { ...b, ...o };
|
|
261
|
+
}
|
|
262
|
+
return merged;
|
|
263
|
+
}
|
|
264
|
+
function mergeRamps(base, over) {
|
|
265
|
+
if (base === undefined)
|
|
266
|
+
return over;
|
|
267
|
+
if (over === undefined)
|
|
268
|
+
return base;
|
|
269
|
+
const light = mergeRampSet(base.light, over.light);
|
|
270
|
+
const dark = mergeRampSet(base.dark, over.dark);
|
|
271
|
+
return {
|
|
272
|
+
...(light !== undefined ? { light } : {}),
|
|
273
|
+
...(dark !== undefined ? { dark } : {}),
|
|
274
|
+
};
|
|
275
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "The default end-user transcript UI for guuey agents — the headless view-model (planTranscript), calm/debug presets, the GuueyChatTheme token schema, the ChatStrings i18n seam, and (at ./react) the component kit that renders it: per-category components, <Transcript>, the live + history input assemblers, and stick-to-bottom/windowed/accessible transcript behavior; at ./native, the React Native renderer over the same view-model.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"@silverprotocol/core": "0.5.1",
|
|
40
40
|
"@silverprotocol/richtext": "0.5.1",
|
|
41
41
|
"zod": "^4.3.6",
|
|
42
|
-
"@guuey/agent-client": "0.
|
|
43
|
-
"@guuey/mcp-apps-host": "0.
|
|
42
|
+
"@guuey/agent-client": "0.14.0",
|
|
43
|
+
"@guuey/mcp-apps-host": "0.14.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"react": ">=18",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"react-dom": "^19.0.0",
|
|
66
66
|
"react-native": "0.81.5",
|
|
67
67
|
"typescript": "^5.0.0",
|
|
68
|
-
"vitest": "^3.
|
|
68
|
+
"vitest": "^3.2.7"
|
|
69
69
|
},
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export {
|
|
|
16
16
|
} from "./plan.js";
|
|
17
17
|
export {
|
|
18
18
|
calmPolicy,
|
|
19
|
+
type TranscriptPolicyOverrides,
|
|
19
20
|
debugPolicy,
|
|
20
21
|
type TranscriptPolicy,
|
|
21
22
|
} from "./policy.js";
|
|
@@ -46,8 +47,13 @@ export {
|
|
|
46
47
|
export {
|
|
47
48
|
DEFAULT_CHAT_THEME,
|
|
48
49
|
GUUEY_CHAT_THEME,
|
|
50
|
+
GuueyChatAccentRamp,
|
|
51
|
+
GuueyChatErrorRamp,
|
|
49
52
|
GuueyChatPalette,
|
|
53
|
+
GuueyChatRamps,
|
|
54
|
+
GuueyChatRampSet,
|
|
50
55
|
GuueyChatTheme,
|
|
56
|
+
GuueyChatToneRamp,
|
|
51
57
|
resolveTheme,
|
|
52
58
|
} from "./theme.js";
|
|
53
59
|
export type {
|
package/src/policy.ts
CHANGED
|
@@ -85,7 +85,17 @@ export interface TranscriptPolicy {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/** Deep-ish merge for the one level of nesting policies actually have. */
|
|
88
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Per-section partial overrides — the shape `withOverrides` actually
|
|
90
|
+
* merges (each section spreads over its base), so the type tells the
|
|
91
|
+
* truth: `{ view: { presentation: 'chips' } }` is valid without
|
|
92
|
+
* restating the section's other fields (guuey#321 surfaced the lie).
|
|
93
|
+
*/
|
|
94
|
+
export type TranscriptPolicyOverrides = {
|
|
95
|
+
[K in keyof TranscriptPolicy]?: Partial<TranscriptPolicy[K]>;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
function withOverrides(base: TranscriptPolicy, overrides?: TranscriptPolicyOverrides): TranscriptPolicy {
|
|
89
99
|
if (!overrides) return base;
|
|
90
100
|
return {
|
|
91
101
|
...base,
|
|
@@ -135,12 +145,12 @@ function calmBase(): TranscriptPolicy {
|
|
|
135
145
|
}
|
|
136
146
|
|
|
137
147
|
/** The `calm` preset — the end-user default (spec §5). */
|
|
138
|
-
export function calmPolicy(overrides?:
|
|
148
|
+
export function calmPolicy(overrides?: TranscriptPolicyOverrides): TranscriptPolicy {
|
|
139
149
|
return withOverrides(calmBase(), overrides);
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
/** The `debug` preset — the builder surface (Studio's test chat, spec §5). */
|
|
143
|
-
export function debugPolicy(overrides?:
|
|
153
|
+
export function debugPolicy(overrides?: TranscriptPolicyOverrides): TranscriptPolicy {
|
|
144
154
|
const base = calmBase();
|
|
145
155
|
const debug: TranscriptPolicy = {
|
|
146
156
|
...base,
|
package/src/react/guuey-chat.tsx
CHANGED
|
@@ -64,9 +64,9 @@ import {
|
|
|
64
64
|
} from "@guuey/agent-client";
|
|
65
65
|
import type { AgHitlAnswer, AgPausedAsk } from "@silverprotocol/core";
|
|
66
66
|
import { useAgentInvoke } from "@guuey/agent-client/react";
|
|
67
|
-
import { unavailableToolCallResult } from "@guuey/mcp-apps-host";
|
|
67
|
+
import { unavailableToolCallResult, withActionStaging } from "@guuey/mcp-apps-host";
|
|
68
68
|
import type { McpToolCallResult, UiActionRequest, UiResourceReader } from "@guuey/mcp-apps-host";
|
|
69
|
-
import { calmPolicy, debugPolicy, type
|
|
69
|
+
import { calmPolicy, debugPolicy, type TranscriptPolicyOverrides } from "../policy.js";
|
|
70
70
|
import { useStructuralIdentity } from "./structural-identity.js";
|
|
71
71
|
import { defaultChatStrings, type ChatStrings } from "../strings.js";
|
|
72
72
|
import { DEFAULT_CHAT_THEME, type GuueyChatTheme } from "../theme.js";
|
|
@@ -192,8 +192,12 @@ export interface GuueyChatProps {
|
|
|
192
192
|
adapters?: AgentInvokeAdapters;
|
|
193
193
|
/** Policy preset (spec §5). Default `"calm"`. */
|
|
194
194
|
preset?: "calm" | "debug";
|
|
195
|
-
/**
|
|
196
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Knob overrides applied on top of the preset (spec §3's columns) —
|
|
197
|
+
* per-SECTION partials (`{ view: { presentation: "chips" } }` needs no
|
|
198
|
+
* other view fields; guuey#321 made the type tell the merge's truth).
|
|
199
|
+
*/
|
|
200
|
+
policy?: TranscriptPolicyOverrides;
|
|
197
201
|
/** Per-slot component overrides (spec §3's override column). */
|
|
198
202
|
components?: Partial<TranscriptComponents>;
|
|
199
203
|
/** String overrides — merged over the preset's `ChatStrings` (§4.2). */
|
|
@@ -443,6 +447,26 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
|
|
|
443
447
|
// `viewProps.hostContext` keys win; `theme` is only defaulted. Hosts
|
|
444
448
|
// mounting views DIRECTLY (a canvas over the roster) announce on their
|
|
445
449
|
// own <GuueyView hostContext> — this covers the kit's own mounts.
|
|
450
|
+
// ── Composer ─────────────────────────────────────────────────────────
|
|
451
|
+
const [input, setInput] = useState("");
|
|
452
|
+
const inputRef = useRef<HTMLTextAreaElement | null>(null);
|
|
453
|
+
// Browser form-field heuristics (a11y/autofill lints) flag a field with
|
|
454
|
+
// neither id nor name on every embedding site. useId keeps the id unique
|
|
455
|
+
// when several chats mount on one page — a static id would collide.
|
|
456
|
+
const composerId = useId();
|
|
457
|
+
const busy = invoke.status !== "ready";
|
|
458
|
+
const available = endpointUrl !== null;
|
|
459
|
+
const canSend = available && !busy && input.trim() !== "";
|
|
460
|
+
|
|
461
|
+
// ── The imperative seam (guuey#210) ──────────────────────────────────
|
|
462
|
+
// ONE stable handle for the component's whole life (hosts capture it in
|
|
463
|
+
// `onReady` and keep it), reading live truth through a ref so a call
|
|
464
|
+
// always sees the CURRENT gate — never a stale closure's.
|
|
465
|
+
const liveRef = useRef({ available, busy, invoke, onReady });
|
|
466
|
+
useEffect(() => {
|
|
467
|
+
liveRef.current = { available, busy, invoke, onReady };
|
|
468
|
+
});
|
|
469
|
+
|
|
446
470
|
// The DEFAULT ACTION RELAY (guuey#335 — the founder-hit Confirm bug):
|
|
447
471
|
// pod-then-persisted, built over the SAME identity as the reader, thread
|
|
448
472
|
// read through the ref at CALL time. Without it, a kit-mounted render's
|
|
@@ -480,13 +504,32 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
|
|
|
480
504
|
});
|
|
481
505
|
}, []);
|
|
482
506
|
|
|
507
|
+
// Post-turn action STAGING (guuey#356 — the widget's ratified #198/#215/
|
|
508
|
+
// #218 policy, ONE copy in the kit): with no live turn, an allowlisted
|
|
509
|
+
// semantic card action stages its human-readable projection into the
|
|
510
|
+
// composer (append, never clobber — the staged-composer semantic) and the
|
|
511
|
+
// view hears the queued acceptance; everything else rides the relay path
|
|
512
|
+
// untouched. Rides viewSlotProps too, so canvas hosts get it for free.
|
|
513
|
+
const stagedDefaultOnCallTool = useMemo<
|
|
514
|
+
((request: UiActionRequest) => Promise<McpToolCallResult>) | undefined
|
|
515
|
+
>(() => {
|
|
516
|
+
if (defaultOnCallTool === undefined) return undefined;
|
|
517
|
+
return withActionStaging(defaultOnCallTool, {
|
|
518
|
+
isTurnLive: () => liveRef.current.busy,
|
|
519
|
+
stage: (text) => {
|
|
520
|
+
setInput((prev) => (prev.trim() === "" ? text : `${prev.trimEnd()} ${text}`));
|
|
521
|
+
inputRef.current?.focus();
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
}, [defaultOnCallTool]);
|
|
525
|
+
|
|
483
526
|
const effectiveViewProps = useMemo<TranscriptItemContext["viewProps"]>(
|
|
484
527
|
() =>
|
|
485
528
|
viewPropsWithThemeAnnounce(viewProps, mode, {
|
|
486
|
-
...(
|
|
529
|
+
...(stagedDefaultOnCallTool !== undefined ? { onCallTool: stagedDefaultOnCallTool } : {}),
|
|
487
530
|
onUpdateModelContext: defaultOnUpdateModelContext,
|
|
488
531
|
}),
|
|
489
|
-
[viewProps, mode,
|
|
532
|
+
[viewProps, mode, stagedDefaultOnCallTool, defaultOnUpdateModelContext],
|
|
490
533
|
);
|
|
491
534
|
|
|
492
535
|
// The canvas-host door (guuey#335): a host mounting views DIRECTLY from
|
|
@@ -499,32 +542,12 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
|
|
|
499
542
|
staticSlotPropsRef.current =
|
|
500
543
|
typeof effectiveViewProps === "function"
|
|
501
544
|
? {
|
|
502
|
-
...(
|
|
545
|
+
...(stagedDefaultOnCallTool !== undefined ? { onCallTool: stagedDefaultOnCallTool } : {}),
|
|
503
546
|
onUpdateModelContext: defaultOnUpdateModelContext,
|
|
504
547
|
hostContext: { theme: mode },
|
|
505
548
|
}
|
|
506
549
|
: (effectiveViewProps ?? {});
|
|
507
550
|
|
|
508
|
-
// ── Composer ─────────────────────────────────────────────────────────
|
|
509
|
-
const [input, setInput] = useState("");
|
|
510
|
-
const inputRef = useRef<HTMLTextAreaElement | null>(null);
|
|
511
|
-
// Browser form-field heuristics (a11y/autofill lints) flag a field with
|
|
512
|
-
// neither id nor name on every embedding site. useId keeps the id unique
|
|
513
|
-
// when several chats mount on one page — a static id would collide.
|
|
514
|
-
const composerId = useId();
|
|
515
|
-
const busy = invoke.status !== "ready";
|
|
516
|
-
const available = endpointUrl !== null;
|
|
517
|
-
const canSend = available && !busy && input.trim() !== "";
|
|
518
|
-
|
|
519
|
-
// ── The imperative seam (guuey#210) ──────────────────────────────────
|
|
520
|
-
// ONE stable handle for the component's whole life (hosts capture it in
|
|
521
|
-
// `onReady` and keep it), reading live truth through a ref so a call
|
|
522
|
-
// always sees the CURRENT gate — never a stale closure's.
|
|
523
|
-
const liveRef = useRef({ available, busy, invoke, onReady });
|
|
524
|
-
useEffect(() => {
|
|
525
|
-
liveRef.current = { available, busy, invoke, onReady };
|
|
526
|
-
});
|
|
527
|
-
|
|
528
551
|
const handle = useMemo<GuueyChatHandle>(
|
|
529
552
|
() => ({
|
|
530
553
|
send: (text: string): boolean => {
|
package/src/strings.ts
CHANGED
|
@@ -123,7 +123,30 @@ export interface ChatStrings {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/** Humanize a wire tool name: `render_weather-card` → `render weather card`. */
|
|
126
|
+
/**
|
|
127
|
+
* The ggui generative-UI rail's tool vocabulary, in end-user words
|
|
128
|
+
* (guuey#307): raw wire names ("mcp ggui ggui handshake") read as
|
|
129
|
+
* internals on every card-bearing conversation — and the rail is the
|
|
130
|
+
* platform default (mcp.ggui.ai), so the kit owns its voice the same
|
|
131
|
+
* way it owns the card machinery.
|
|
132
|
+
*/
|
|
133
|
+
const GGUI_RAIL_TITLES: Record<string, string> = {
|
|
134
|
+
ggui_handshake: "Preparing interactive card",
|
|
135
|
+
ggui_render: "Rendering card",
|
|
136
|
+
ggui_consume: "Updating interactive card",
|
|
137
|
+
ggui_update: "Updating card",
|
|
138
|
+
};
|
|
139
|
+
|
|
126
140
|
export function humanizeToolName(wireName: string): string {
|
|
141
|
+
// MCP wire shape: `mcp__<server>__<tool>` (double-underscore separators).
|
|
142
|
+
const mcp = /^mcp__([^_].*?)__(.+)$/.exec(wireName);
|
|
143
|
+
if (mcp) {
|
|
144
|
+
const [, server, tool] = mcp;
|
|
145
|
+
if (server === "ggui" && GGUI_RAIL_TITLES[tool]) return GGUI_RAIL_TITLES[tool];
|
|
146
|
+
const prettyServer = server.charAt(0).toUpperCase() + server.slice(1).replace(/[_-]+/g, " ");
|
|
147
|
+
const prettyTool = tool.replace(/[_-]+/g, " ").trim();
|
|
148
|
+
return `${prettyServer} · ${prettyTool}`;
|
|
149
|
+
}
|
|
127
150
|
return wireName.replace(/[_-]+/g, " ").trim();
|
|
128
151
|
}
|
|
129
152
|
|
package/src/theme.ts
CHANGED
|
@@ -38,11 +38,77 @@ export const GuueyChatPalette = z
|
|
|
38
38
|
.loose();
|
|
39
39
|
export type GuueyChatPalette = z.infer<typeof GuueyChatPalette>;
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* STATED ramp slots (theme-as-code, guuey#341 spec §3 — never derived).
|
|
43
|
+
* Closed per-family sets: `accent` carries the full ladder (the
|
|
44
|
+
* 500/600/700 floor is a WRITE/COMPILE rule, not a schema rule — the
|
|
45
|
+
* schema admits any stated subset so a stale stored document still parses);
|
|
46
|
+
* the status families carry their tone-500 slot. Ramps live BESIDE the
|
|
47
|
+
* palettes (`theme.ramps.{light,dark}`), never inside them — the flat
|
|
48
|
+
* palette record is a load-bearing invariant (token lists are DERIVED from
|
|
49
|
+
* its shape by every platform gate).
|
|
50
|
+
*/
|
|
51
|
+
export const GuueyChatAccentRamp = z
|
|
52
|
+
.object({
|
|
53
|
+
"100": z.string().optional(),
|
|
54
|
+
"300": z.string().optional(),
|
|
55
|
+
"500": z.string().optional(),
|
|
56
|
+
"600": z.string().optional(),
|
|
57
|
+
"700": z.string().optional(),
|
|
58
|
+
"800": z.string().optional(),
|
|
59
|
+
"900": z.string().optional(),
|
|
60
|
+
})
|
|
61
|
+
.loose();
|
|
62
|
+
export type GuueyChatAccentRamp = z.infer<typeof GuueyChatAccentRamp>;
|
|
63
|
+
|
|
64
|
+
export const GuueyChatErrorRamp = z
|
|
65
|
+
.object({
|
|
66
|
+
"500": z.string().optional(),
|
|
67
|
+
"600": z.string().optional(),
|
|
68
|
+
"700": z.string().optional(),
|
|
69
|
+
})
|
|
70
|
+
.loose();
|
|
71
|
+
export type GuueyChatErrorRamp = z.infer<typeof GuueyChatErrorRamp>;
|
|
72
|
+
|
|
73
|
+
export const GuueyChatToneRamp = z.object({ "500": z.string().optional() }).loose();
|
|
74
|
+
export type GuueyChatToneRamp = z.infer<typeof GuueyChatToneRamp>;
|
|
75
|
+
|
|
76
|
+
/** One mode's stated ramp families — every family optional. */
|
|
77
|
+
export const GuueyChatRampSet = z
|
|
78
|
+
.object({
|
|
79
|
+
accent: GuueyChatAccentRamp.optional(),
|
|
80
|
+
error: GuueyChatErrorRamp.optional(),
|
|
81
|
+
success: GuueyChatToneRamp.optional(),
|
|
82
|
+
warning: GuueyChatToneRamp.optional(),
|
|
83
|
+
info: GuueyChatToneRamp.optional(),
|
|
84
|
+
})
|
|
85
|
+
.loose();
|
|
86
|
+
export type GuueyChatRampSet = z.infer<typeof GuueyChatRampSet>;
|
|
87
|
+
|
|
88
|
+
export const GuueyChatRamps = z
|
|
89
|
+
.object({
|
|
90
|
+
light: GuueyChatRampSet.optional(),
|
|
91
|
+
dark: GuueyChatRampSet.optional(),
|
|
92
|
+
})
|
|
93
|
+
.loose();
|
|
94
|
+
export type GuueyChatRamps = z.infer<typeof GuueyChatRamps>;
|
|
95
|
+
|
|
41
96
|
export const GuueyChatTheme = z
|
|
42
97
|
.object({
|
|
43
98
|
name: z.string(),
|
|
99
|
+
/**
|
|
100
|
+
* The app's CANONICAL presentation mode (theme-as-code §3) — what the
|
|
101
|
+
* ggui stamp pins its render slice to. OPTIONAL and default-less on
|
|
102
|
+
* purpose: absent = "not stated", and the platform's legacy polarity
|
|
103
|
+
* derivation stands. Distinct from the VIEWER's runtime light/dark
|
|
104
|
+
* choice, which stays a component prop — chat components never read
|
|
105
|
+
* this field.
|
|
106
|
+
*/
|
|
107
|
+
mode: z.enum(["light", "dark"]).optional(),
|
|
44
108
|
/** BOTH palettes always present — mode is the consumer's runtime choice. */
|
|
45
109
|
colors: z.object({ light: GuueyChatPalette, dark: GuueyChatPalette }).loose(),
|
|
110
|
+
/** Stated ramp slots per mode — see {@link GuueyChatRamps}. */
|
|
111
|
+
ramps: GuueyChatRamps.optional(),
|
|
46
112
|
typography: z
|
|
47
113
|
.object({
|
|
48
114
|
fontFamily: z.string().optional(),
|
|
@@ -133,10 +199,12 @@ const PartialPalette = GuueyChatPalette.partial();
|
|
|
133
199
|
const PartialTheme = z
|
|
134
200
|
.object({
|
|
135
201
|
name: z.string().optional(),
|
|
202
|
+
mode: GuueyChatTheme.shape.mode.optional(),
|
|
136
203
|
colors: z
|
|
137
204
|
.object({ light: PartialPalette.optional(), dark: PartialPalette.optional() })
|
|
138
205
|
.loose()
|
|
139
206
|
.optional(),
|
|
207
|
+
ramps: GuueyChatRamps.optional(),
|
|
140
208
|
typography: GuueyChatTheme.shape.typography.optional(),
|
|
141
209
|
shape: GuueyChatTheme.shape.shape.partial().loose().optional(),
|
|
142
210
|
})
|
|
@@ -180,12 +248,19 @@ export function resolveTheme(
|
|
|
180
248
|
const parsed = PartialTheme.safeParse(candidate);
|
|
181
249
|
if (!parsed.success) return { ...base, colors: { light: { ...base.colors.light }, dark: { ...base.colors.dark } } };
|
|
182
250
|
const p = parsed.data;
|
|
251
|
+
const mode = p.mode ?? base.mode;
|
|
252
|
+
const ramps = mergeRamps(base.ramps, p.ramps);
|
|
183
253
|
return {
|
|
184
254
|
name: p.name ?? base.name,
|
|
255
|
+
// `mode`/`ramps` are default-less (the package themes state neither):
|
|
256
|
+
// they appear on the resolved theme only when SOME layer stated them —
|
|
257
|
+
// an absent statement must stay visibly absent, not become a default.
|
|
258
|
+
...(mode !== undefined ? { mode } : {}),
|
|
185
259
|
colors: {
|
|
186
260
|
light: mergePalette(base.colors.light, p.colors?.light),
|
|
187
261
|
dark: mergePalette(base.colors.dark, p.colors?.dark),
|
|
188
262
|
},
|
|
263
|
+
...(ramps !== undefined ? { ramps } : {}),
|
|
189
264
|
typography: { ...base.typography, ...(p.typography ?? {}) },
|
|
190
265
|
shape: {
|
|
191
266
|
radius: p.shape?.radius ?? base.shape.radius,
|
|
@@ -193,3 +268,34 @@ export function resolveTheme(
|
|
|
193
268
|
},
|
|
194
269
|
};
|
|
195
270
|
}
|
|
271
|
+
|
|
272
|
+
/** Slot-level merge of two ramp statements (candidate slots win per slot). */
|
|
273
|
+
function mergeRampSet(
|
|
274
|
+
base: GuueyChatRampSet | undefined,
|
|
275
|
+
over: GuueyChatRampSet | undefined,
|
|
276
|
+
): GuueyChatRampSet | undefined {
|
|
277
|
+
if (base === undefined) return over;
|
|
278
|
+
if (over === undefined) return base;
|
|
279
|
+
const merged: GuueyChatRampSet = { ...base };
|
|
280
|
+
for (const family of ["accent", "error", "success", "warning", "info"] as const) {
|
|
281
|
+
const b = base[family];
|
|
282
|
+
const o = over[family];
|
|
283
|
+
if (o === undefined) continue;
|
|
284
|
+
merged[family] = b === undefined ? o : { ...b, ...o };
|
|
285
|
+
}
|
|
286
|
+
return merged;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function mergeRamps(
|
|
290
|
+
base: GuueyChatRamps | undefined,
|
|
291
|
+
over: GuueyChatRamps | undefined,
|
|
292
|
+
): GuueyChatRamps | undefined {
|
|
293
|
+
if (base === undefined) return over;
|
|
294
|
+
if (over === undefined) return base;
|
|
295
|
+
const light = mergeRampSet(base.light, over.light);
|
|
296
|
+
const dark = mergeRampSet(base.dark, over.dark);
|
|
297
|
+
return {
|
|
298
|
+
...(light !== undefined ? { light } : {}),
|
|
299
|
+
...(dark !== undefined ? { dark } : {}),
|
|
300
|
+
};
|
|
301
|
+
}
|