@ggui-ai/mcp-server-handlers 0.11.0 → 0.12.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/ops-apps/set-app-theme.d.ts +35 -0
- package/dist/ops-apps/set-app-theme.d.ts.map +1 -1
- package/dist/ops-apps/set-app-theme.js +36 -0
- package/dist/ops-themes/delete-theme.d.ts +29 -0
- package/dist/ops-themes/delete-theme.d.ts.map +1 -0
- package/dist/ops-themes/delete-theme.js +41 -0
- package/dist/ops-themes/index.d.ts +9 -0
- package/dist/ops-themes/index.d.ts.map +1 -0
- package/dist/ops-themes/index.js +8 -0
- package/dist/ops-themes/list-themes.d.ts +36 -0
- package/dist/ops-themes/list-themes.d.ts.map +1 -0
- package/dist/ops-themes/list-themes.js +51 -0
- package/dist/ops-themes/register-theme.d.ts +57 -0
- package/dist/ops-themes/register-theme.d.ts.map +1 -0
- package/dist/ops-themes/register-theme.js +142 -0
- package/dist/ops-themes/types.d.ts +63 -0
- package/dist/ops-themes/types.d.ts.map +1 -0
- package/dist/ops-themes/types.js +50 -0
- package/dist/renders/amend.d.ts +5 -0
- package/dist/renders/amend.d.ts.map +1 -1
- package/dist/renders/amend.js +15 -0
- package/dist/renders/blueprint-matcher.d.ts +10 -0
- package/dist/renders/blueprint-matcher.d.ts.map +1 -1
- package/dist/renders/blueprint-matcher.js +8 -0
- package/dist/renders/cache-trace-sink.d.ts +28 -0
- package/dist/renders/cache-trace-sink.d.ts.map +1 -1
- package/dist/renders/cache-trace-sink.js +80 -0
- package/dist/renders/decide-handshake.d.ts +19 -1
- package/dist/renders/decide-handshake.d.ts.map +1 -1
- package/dist/renders/decide-handshake.js +20 -4
- package/dist/renders/handshake.d.ts +14 -0
- package/dist/renders/handshake.d.ts.map +1 -1
- package/dist/renders/index.d.ts +2 -2
- package/dist/renders/index.d.ts.map +1 -1
- package/dist/renders/index.js +2 -2
- package/dist/renders/match-precision/pairs.d.ts.map +1 -1
- package/dist/renders/match-precision/pairs.js +12 -7
- package/dist/renders/match-precision/run-probe.js +42 -5
- package/dist/renders/payload-trace-sink.d.ts +24 -24
- package/dist/renders/payload-trace-sink.d.ts.map +1 -1
- package/dist/renders/payload-trace-sink.js +24 -30
- package/dist/renders/props-mutation-core.d.ts +14 -0
- package/dist/renders/props-mutation-core.d.ts.map +1 -1
- package/dist/renders/props-mutation-core.js +36 -2
- package/dist/renders/render.d.ts +43 -0
- package/dist/renders/render.d.ts.map +1 -1
- package/dist/renders/render.js +60 -4
- package/dist/renders/slice-meta-derivation.d.ts +29 -0
- package/dist/renders/slice-meta-derivation.d.ts.map +1 -1
- package/dist/renders/slice-meta-derivation.js +39 -10
- package/dist/renders/submit-action.d.ts +6 -4
- package/dist/renders/submit-action.d.ts.map +1 -1
- package/dist/renders/submit-action.js +6 -4
- package/dist/renders/update.d.ts +18 -0
- package/dist/renders/update.d.ts.map +1 -1
- package/dist/renders/update.js +21 -2
- package/package.json +13 -8
|
@@ -27,6 +27,11 @@ declare const inputSchema: {
|
|
|
27
27
|
}>;
|
|
28
28
|
cssVariables: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
29
29
|
name: z.ZodOptional<z.ZodString>;
|
|
30
|
+
base: z.ZodOptional<z.ZodObject<{
|
|
31
|
+
documentHash: z.ZodString;
|
|
32
|
+
light: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
33
|
+
dark: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
34
|
+
}, z.core.$strict>>;
|
|
30
35
|
}, z.core.$strict>;
|
|
31
36
|
};
|
|
32
37
|
declare const outputSchema: {
|
|
@@ -38,17 +43,47 @@ declare const outputSchema: {
|
|
|
38
43
|
}>;
|
|
39
44
|
cssVariables: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
40
45
|
name: z.ZodOptional<z.ZodString>;
|
|
46
|
+
base: z.ZodOptional<z.ZodObject<{
|
|
47
|
+
documentHash: z.ZodString;
|
|
48
|
+
light: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
49
|
+
dark: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
50
|
+
}, z.core.$strict>>;
|
|
41
51
|
}, z.core.$strict>;
|
|
42
52
|
readonly updatedAt: z.ZodString;
|
|
53
|
+
/**
|
|
54
|
+
* Migration nudge (ggui#598 slice 3): present when the overlay is
|
|
55
|
+
* BRAND-SHAPED — ≥3 color families over a name that resolves to no
|
|
56
|
+
* registered theme. The write still succeeds (overlays stay legal);
|
|
57
|
+
* the tier just stops being silent about brands living in it.
|
|
58
|
+
*/
|
|
59
|
+
readonly warning: z.ZodOptional<z.ZodString>;
|
|
43
60
|
};
|
|
44
61
|
export interface SetAppThemeOutput {
|
|
45
62
|
readonly appId: string;
|
|
46
63
|
readonly theme: z.infer<typeof appThemeSchema>;
|
|
47
64
|
readonly updatedAt: string;
|
|
65
|
+
readonly warning?: string;
|
|
48
66
|
}
|
|
49
67
|
export interface SetAppThemeDeps {
|
|
50
68
|
readonly apps: AppsSource;
|
|
69
|
+
/**
|
|
70
|
+
* Known theme ids (built-in presets + registered) for the
|
|
71
|
+
* brand-shaped-overlay WARN's name resolution. Absent = names cannot
|
|
72
|
+
* be resolved, so brand-scale coverage always draws the nudge.
|
|
73
|
+
*/
|
|
74
|
+
readonly knownThemeIds?: readonly string[];
|
|
51
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Detect a BRAND-SHAPED overlay (ggui#598 slice 3): ≥3 distinct color
|
|
78
|
+
* families in the variable map while the overlay's `name` resolves to
|
|
79
|
+
* no known theme. A brand living in the accent tier is the round-3
|
|
80
|
+
* mechanism — the overlay inherits every unmapped token from someone
|
|
81
|
+
* else's ladder. The WARN names the registration path; it never
|
|
82
|
+
* blocks. Exported for its unit pins.
|
|
83
|
+
*
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
export declare function detectBrandShapedOverlay(theme: z.infer<typeof appThemeSchema>, deps: Pick<SetAppThemeDeps, 'knownThemeIds'>): string | undefined;
|
|
52
87
|
export declare function createSetAppThemeHandler(deps: SetAppThemeDeps): SharedHandler<typeof inputSchema, typeof outputSchema, SetAppThemeOutput>;
|
|
53
88
|
export {};
|
|
54
89
|
//# sourceMappingURL=set-app-theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-app-theme.d.ts","sourceRoot":"","sources":["../../src/ops-apps/set-app-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,QAAA,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"set-app-theme.d.ts","sourceRoot":"","sources":["../../src/ops-apps/set-app-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;CAUP,CAAC;AAEX,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;IAIhB;;;;;OAKG;;CAEK,CAAC;AAEX,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,EACrC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,GAC3C,MAAM,GAAG,SAAS,CAkBpB;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,eAAe,GACpB,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,iBAAiB,CAAC,CAoC3E"}
|
|
@@ -29,7 +29,41 @@ const outputSchema = {
|
|
|
29
29
|
appId: z.string(),
|
|
30
30
|
theme: appThemeSchema,
|
|
31
31
|
updatedAt: z.string(),
|
|
32
|
+
/**
|
|
33
|
+
* Migration nudge (ggui#598 slice 3): present when the overlay is
|
|
34
|
+
* BRAND-SHAPED — ≥3 color families over a name that resolves to no
|
|
35
|
+
* registered theme. The write still succeeds (overlays stay legal);
|
|
36
|
+
* the tier just stops being silent about brands living in it.
|
|
37
|
+
*/
|
|
38
|
+
warning: z.string().optional(),
|
|
32
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Detect a BRAND-SHAPED overlay (ggui#598 slice 3): ≥3 distinct color
|
|
42
|
+
* families in the variable map while the overlay's `name` resolves to
|
|
43
|
+
* no known theme. A brand living in the accent tier is the round-3
|
|
44
|
+
* mechanism — the overlay inherits every unmapped token from someone
|
|
45
|
+
* else's ladder. The WARN names the registration path; it never
|
|
46
|
+
* blocks. Exported for its unit pins.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export function detectBrandShapedOverlay(theme, deps) {
|
|
51
|
+
const families = new Set();
|
|
52
|
+
for (const key of Object.keys(theme.cssVariables)) {
|
|
53
|
+
const m = key.match(/^--ggui-color-([a-zA-Z]+)/);
|
|
54
|
+
if (m)
|
|
55
|
+
families.add(m[1].toLowerCase());
|
|
56
|
+
}
|
|
57
|
+
if (families.size < 3)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (theme.name !== undefined &&
|
|
60
|
+
deps.knownThemeIds !== undefined &&
|
|
61
|
+
deps.knownThemeIds.includes(theme.name)) {
|
|
62
|
+
// Brand-scale accents over a COVERED registered base — legitimate.
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
return `This overlay carries ${families.size} color families over ${theme.name !== undefined ? `an unregistered name ("${theme.name}")` : 'no named base'} — brand-scale theming belongs in a REGISTERED theme (runtime theme registration), where coverage is validated and every token is yours; overlays are accents over a covered base. The write succeeded; unmapped tokens will paint the default ladder.`;
|
|
66
|
+
}
|
|
33
67
|
export function createSetAppThemeHandler(deps) {
|
|
34
68
|
return {
|
|
35
69
|
name: 'ggui_ops_set_app_theme',
|
|
@@ -53,9 +87,11 @@ export function createSetAppThemeHandler(deps) {
|
|
|
53
87
|
ownerSub,
|
|
54
88
|
theme: parsed.theme,
|
|
55
89
|
});
|
|
90
|
+
const warning = detectBrandShapedOverlay(parsed.theme, deps);
|
|
56
91
|
return {
|
|
57
92
|
appId: written.appId,
|
|
58
93
|
theme: parsed.theme,
|
|
94
|
+
...(warning !== undefined ? { warning } : {}),
|
|
59
95
|
updatedAt: written.updatedAt,
|
|
60
96
|
};
|
|
61
97
|
},
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggui_ops_delete_theme` — remove one runtime theme registration
|
|
3
|
+
* (ggui#598-C). Idempotent-with-report: `deleted` says whether a
|
|
4
|
+
* registration existed. Renders referencing a deleted theme fall back
|
|
5
|
+
* per the resolution ladder — deletion never breaks a mounted frame.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { ThemeStore } from '@ggui-ai/mcp-server-core';
|
|
9
|
+
import type { SharedHandler } from '../types.js';
|
|
10
|
+
import { type AppsSource } from '../ops-apps/types.js';
|
|
11
|
+
declare const inputSchema: {
|
|
12
|
+
readonly appId: z.ZodString;
|
|
13
|
+
readonly themeId: z.ZodString;
|
|
14
|
+
};
|
|
15
|
+
declare const outputSchema: {
|
|
16
|
+
readonly themeId: z.ZodString;
|
|
17
|
+
readonly deleted: z.ZodBoolean;
|
|
18
|
+
};
|
|
19
|
+
export interface DeleteThemeOutput {
|
|
20
|
+
readonly themeId: string;
|
|
21
|
+
readonly deleted: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface DeleteThemeDeps {
|
|
24
|
+
readonly apps: AppsSource;
|
|
25
|
+
readonly themeStore: ThemeStore;
|
|
26
|
+
}
|
|
27
|
+
export declare function createDeleteThemeHandler(deps: DeleteThemeDeps): SharedHandler<typeof inputSchema, typeof outputSchema, DeleteThemeOutput>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=delete-theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-theme.d.ts","sourceRoot":"","sources":["../../src/ops-themes/delete-theme.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEzE,QAAA,MAAM,WAAW;;;CAMP,CAAC;AAEX,QAAA,MAAM,YAAY;;;CAKR,CAAC;AAEX,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,eAAe,GACpB,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,iBAAiB,CAAC,CAwB3E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggui_ops_delete_theme` — remove one runtime theme registration
|
|
3
|
+
* (ggui#598-C). Idempotent-with-report: `deleted` says whether a
|
|
4
|
+
* registration existed. Renders referencing a deleted theme fall back
|
|
5
|
+
* per the resolution ladder — deletion never breaks a mounted frame.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { resolveOwnerSub } from '../ops-apps/identity.js';
|
|
9
|
+
import { AppNotFoundError } from '../ops-apps/types.js';
|
|
10
|
+
const inputSchema = {
|
|
11
|
+
appId: z
|
|
12
|
+
.string()
|
|
13
|
+
.min(1)
|
|
14
|
+
.describe('Target app — must be one the calling user owns.'),
|
|
15
|
+
themeId: z.string().min(1).describe('The registered theme id to remove.'),
|
|
16
|
+
};
|
|
17
|
+
const outputSchema = {
|
|
18
|
+
themeId: z.string(),
|
|
19
|
+
deleted: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.describe('True iff a registration existed and was removed.'),
|
|
22
|
+
};
|
|
23
|
+
export function createDeleteThemeHandler(deps) {
|
|
24
|
+
return {
|
|
25
|
+
name: 'ggui_ops_delete_theme',
|
|
26
|
+
title: 'Delete theme',
|
|
27
|
+
audience: ['ops'],
|
|
28
|
+
description: 'Remove one registered runtime theme from an app the caller owns. Idempotent — `deleted` reports whether a registration existed. The id becomes registerable again.',
|
|
29
|
+
inputSchema,
|
|
30
|
+
outputSchema,
|
|
31
|
+
async handler(rawInput, ctx) {
|
|
32
|
+
const ownerSub = resolveOwnerSub('ggui_ops_delete_theme', ctx);
|
|
33
|
+
const parsed = z.object(inputSchema).parse(rawInput);
|
|
34
|
+
const app = await deps.apps.get({ appId: parsed.appId, ownerSub });
|
|
35
|
+
if (!app)
|
|
36
|
+
throw new AppNotFoundError(parsed.appId);
|
|
37
|
+
const deleted = await deps.themeStore.delete(parsed.appId, parsed.themeId);
|
|
38
|
+
return { themeId: parsed.themeId, deleted };
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ops-themes — runtime theme registration tools (ggui#598-C).
|
|
3
|
+
* Subpath entry, mirroring the other ops families.
|
|
4
|
+
*/
|
|
5
|
+
export { createRegisterThemeHandler, type RegisterThemeDeps, type RegisterThemeOutput, type ThemeCoverageResultLike, } from './register-theme.js';
|
|
6
|
+
export { createListThemesHandler, type ListThemesDeps, type ListThemesOutput, } from './list-themes.js';
|
|
7
|
+
export { createDeleteThemeHandler, type DeleteThemeDeps, type DeleteThemeOutput, } from './delete-theme.js';
|
|
8
|
+
export { ThemeCoverageError, ThemeDocumentError, ThemeIdentityError, ThemeQuotaError, mapStorePutError, type ThemeCoverageValidator, } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ops-themes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,0BAA0B,EAC1B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,KAAK,sBAAsB,GAC5B,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ops-themes — runtime theme registration tools (ggui#598-C).
|
|
3
|
+
* Subpath entry, mirroring the other ops families.
|
|
4
|
+
*/
|
|
5
|
+
export { createRegisterThemeHandler, } from './register-theme.js';
|
|
6
|
+
export { createListThemesHandler, } from './list-themes.js';
|
|
7
|
+
export { createDeleteThemeHandler, } from './delete-theme.js';
|
|
8
|
+
export { ThemeCoverageError, ThemeDocumentError, ThemeIdentityError, ThemeQuotaError, mapStorePutError, } from './types.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggui_ops_list_themes` — the caller's registered themes for one of
|
|
3
|
+
* their apps (ggui#598-C). Metadata only — the registration document
|
|
4
|
+
* itself never rides a list (bounded output; fetch-by-id is a later
|
|
5
|
+
* surface if a reader ever needs the bytes back).
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { ThemeStore } from '@ggui-ai/mcp-server-core';
|
|
9
|
+
import type { SharedHandler } from '../types.js';
|
|
10
|
+
import { type AppsSource } from '../ops-apps/types.js';
|
|
11
|
+
declare const inputSchema: {
|
|
12
|
+
readonly appId: z.ZodString;
|
|
13
|
+
};
|
|
14
|
+
declare const outputSchema: {
|
|
15
|
+
readonly themes: z.ZodArray<z.ZodObject<{
|
|
16
|
+
themeId: z.ZodString;
|
|
17
|
+
documentHash: z.ZodString;
|
|
18
|
+
registeredAt: z.ZodNumber;
|
|
19
|
+
updatedAt: z.ZodNumber;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
};
|
|
22
|
+
export interface ListThemesOutput {
|
|
23
|
+
readonly themes: readonly {
|
|
24
|
+
readonly themeId: string;
|
|
25
|
+
readonly documentHash: string;
|
|
26
|
+
readonly registeredAt: number;
|
|
27
|
+
readonly updatedAt: number;
|
|
28
|
+
}[];
|
|
29
|
+
}
|
|
30
|
+
export interface ListThemesDeps {
|
|
31
|
+
readonly apps: AppsSource;
|
|
32
|
+
readonly themeStore: ThemeStore;
|
|
33
|
+
}
|
|
34
|
+
export declare function createListThemesHandler(deps: ListThemesDeps): SharedHandler<typeof inputSchema, typeof outputSchema, ListThemesOutput>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=list-themes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-themes.d.ts","sourceRoot":"","sources":["../../src/ops-themes/list-themes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEzE,QAAA,MAAM,WAAW;;CAKP,CAAC;AAEX,QAAA,MAAM,YAAY;;;;;;;CAWR,CAAC;AAEX,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,EAAE,CAAC;CACL;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,cAAc,GACnB,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,gBAAgB,CAAC,CA4B1E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggui_ops_list_themes` — the caller's registered themes for one of
|
|
3
|
+
* their apps (ggui#598-C). Metadata only — the registration document
|
|
4
|
+
* itself never rides a list (bounded output; fetch-by-id is a later
|
|
5
|
+
* surface if a reader ever needs the bytes back).
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { resolveOwnerSub } from '../ops-apps/identity.js';
|
|
9
|
+
import { AppNotFoundError } from '../ops-apps/types.js';
|
|
10
|
+
const inputSchema = {
|
|
11
|
+
appId: z
|
|
12
|
+
.string()
|
|
13
|
+
.min(1)
|
|
14
|
+
.describe('Target app — must be one the calling user owns.'),
|
|
15
|
+
};
|
|
16
|
+
const outputSchema = {
|
|
17
|
+
themes: z.array(z.object({
|
|
18
|
+
themeId: z.string(),
|
|
19
|
+
documentHash: z
|
|
20
|
+
.string()
|
|
21
|
+
.describe('sha256 over the stored registration bytes.'),
|
|
22
|
+
registeredAt: z.number().describe('First-registration ms epoch.'),
|
|
23
|
+
updatedAt: z.number().describe('Last-write ms epoch.'),
|
|
24
|
+
})),
|
|
25
|
+
};
|
|
26
|
+
export function createListThemesHandler(deps) {
|
|
27
|
+
return {
|
|
28
|
+
name: 'ggui_ops_list_themes',
|
|
29
|
+
title: 'List themes',
|
|
30
|
+
audience: ['ops'],
|
|
31
|
+
description: "The app's registered runtime themes — id, documentHash, and timestamps, themeId-sorted. Registration documents themselves are not included.",
|
|
32
|
+
inputSchema,
|
|
33
|
+
outputSchema,
|
|
34
|
+
async handler(rawInput, ctx) {
|
|
35
|
+
const ownerSub = resolveOwnerSub('ggui_ops_list_themes', ctx);
|
|
36
|
+
const parsed = z.object(inputSchema).parse(rawInput);
|
|
37
|
+
const app = await deps.apps.get({ appId: parsed.appId, ownerSub });
|
|
38
|
+
if (!app)
|
|
39
|
+
throw new AppNotFoundError(parsed.appId);
|
|
40
|
+
const rows = await deps.themeStore.list(parsed.appId);
|
|
41
|
+
return {
|
|
42
|
+
themes: rows.map((r) => ({
|
|
43
|
+
themeId: r.themeId,
|
|
44
|
+
documentHash: r.documentHash,
|
|
45
|
+
registeredAt: r.registeredAt,
|
|
46
|
+
updatedAt: r.updatedAt,
|
|
47
|
+
})),
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ThemeStore } from '@ggui-ai/mcp-server-core';
|
|
3
|
+
import type { SharedHandler } from '../types.js';
|
|
4
|
+
import { type AppsSource } from '../ops-apps/types.js';
|
|
5
|
+
import { type ThemeCoverageValidator } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Structural mirror of the coverage validator's result — the shape the
|
|
8
|
+
* injected gate returns (kept here so `types.ts` and the composer can
|
|
9
|
+
* reference one definition without a design-package import).
|
|
10
|
+
*/
|
|
11
|
+
export interface ThemeCoverageResultLike {
|
|
12
|
+
readonly covered: boolean;
|
|
13
|
+
readonly uncovered: {
|
|
14
|
+
readonly light: readonly string[];
|
|
15
|
+
readonly dark: readonly string[];
|
|
16
|
+
};
|
|
17
|
+
readonly inheritMatched: readonly string[];
|
|
18
|
+
readonly excluded: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
declare const inputSchema: {
|
|
21
|
+
readonly appId: z.ZodString;
|
|
22
|
+
readonly themeId: z.ZodString;
|
|
23
|
+
readonly registration: z.ZodObject<{
|
|
24
|
+
light: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
25
|
+
dark: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
};
|
|
28
|
+
declare const outputSchema: {
|
|
29
|
+
readonly themeId: z.ZodString;
|
|
30
|
+
readonly documentHash: z.ZodString;
|
|
31
|
+
readonly updated: z.ZodBoolean;
|
|
32
|
+
readonly coverage: z.ZodObject<{
|
|
33
|
+
inheritMatched: z.ZodArray<z.ZodString>;
|
|
34
|
+
excluded: z.ZodArray<z.ZodString>;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
};
|
|
37
|
+
export interface RegisterThemeOutput {
|
|
38
|
+
readonly themeId: string;
|
|
39
|
+
readonly documentHash: string;
|
|
40
|
+
readonly updated: boolean;
|
|
41
|
+
readonly coverage: {
|
|
42
|
+
readonly inheritMatched: readonly string[];
|
|
43
|
+
readonly excluded: readonly string[];
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export interface RegisterThemeDeps {
|
|
47
|
+
readonly apps: AppsSource;
|
|
48
|
+
readonly themeStore: ThemeStore;
|
|
49
|
+
readonly coverageValidator: ThemeCoverageValidator;
|
|
50
|
+
/** The consumed-token manifest (`consumed-tokens.manifest.json` tokens). */
|
|
51
|
+
readonly manifestTokens: readonly string[];
|
|
52
|
+
/** Built-in theme ids — registration refuses collisions outright. */
|
|
53
|
+
readonly staticThemeIds: readonly string[];
|
|
54
|
+
}
|
|
55
|
+
export declare function createRegisterThemeHandler(deps: RegisterThemeDeps): SharedHandler<typeof inputSchema, typeof outputSchema, RegisterThemeOutput>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=register-theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-theme.d.ts","sourceRoot":"","sources":["../../src/ops-themes/register-theme.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAKL,KAAK,sBAAsB,EAC5B,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;KAClC,CAAC;IACF,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAQD,QAAA,MAAM,WAAW;;;;;;;CAmBP,CAAC;AAEX,QAAA,MAAM,YAAY;;;;;;;;CAgBR,CAAC;AAEX,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;KACtC,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;IACnD,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,qEAAqE;IACrE,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAKD,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,iBAAiB,GACtB,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,mBAAmB,CAAC,CAmF7E"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggui_ops_register_theme` — register (or update) a runtime theme for
|
|
3
|
+
* an app the caller owns (ggui#598-C).
|
|
4
|
+
*
|
|
5
|
+
* Gate order — each wall is a distinct named refusal:
|
|
6
|
+
* 1. tenancy — the app must be the caller's (uniform not-found).
|
|
7
|
+
* 2. identity — the frozen id grammar, then collision with any
|
|
8
|
+
* built-in theme id (`theme_identity`).
|
|
9
|
+
* 3. coverage — the injected validator vs the consumed-token
|
|
10
|
+
* manifest (`theme_coverage`; uncovered lists ride
|
|
11
|
+
* verbatim — never-quiet).
|
|
12
|
+
* 4. policy — the store may refuse the write (a deployment-policy
|
|
13
|
+
* seam, e.g. a per-app registration cap; surfaced as
|
|
14
|
+
* `theme_quota` with the store's own message).
|
|
15
|
+
*
|
|
16
|
+
* What gets stored: the `{light, dark}` registration serialized ONCE
|
|
17
|
+
* here to CANONICAL JSON (RFC 8785) — those bytes are the identity
|
|
18
|
+
* (`documentHash` = sha256) and the store returns them verbatim.
|
|
19
|
+
* Identity is deliberately canonical: two key-orderings of one
|
|
20
|
+
* semantic document are ONE registration version (the same
|
|
21
|
+
* representation-independence rule the contract and props-schema
|
|
22
|
+
* hashes obey).
|
|
23
|
+
*
|
|
24
|
+
* The output is never-quiet about inheritance: what the document
|
|
25
|
+
* inherited (`inheritMatched`) and what the manifest excluded from
|
|
26
|
+
* the obligation (`excluded`) are IN the result, not just implied.
|
|
27
|
+
*/
|
|
28
|
+
import { createHash } from 'node:crypto';
|
|
29
|
+
import canonicalize from 'canonicalize';
|
|
30
|
+
import { z } from 'zod';
|
|
31
|
+
import { isValidThemeId } from '@ggui-ai/mcp-server-core';
|
|
32
|
+
import { resolveOwnerSub } from '../ops-apps/identity.js';
|
|
33
|
+
import { AppNotFoundError } from '../ops-apps/types.js';
|
|
34
|
+
import { mapStorePutError, ThemeCoverageError, ThemeDocumentError, ThemeIdentityError, } from './types.js';
|
|
35
|
+
const dtcgDocSchema = z
|
|
36
|
+
.record(z.string(), z.unknown())
|
|
37
|
+
.describe('A DTCG design-token document for one mode. Validated for token coverage at registration — the response names every uncovered token.');
|
|
38
|
+
const inputSchema = {
|
|
39
|
+
appId: z
|
|
40
|
+
.string()
|
|
41
|
+
.min(1)
|
|
42
|
+
.describe('Target app — must be one the calling user owns. Discover via `ggui_ops_list_apps`.'),
|
|
43
|
+
themeId: z
|
|
44
|
+
.string()
|
|
45
|
+
.min(3)
|
|
46
|
+
.max(64)
|
|
47
|
+
.describe('Theme id: lowercase kebab, alphanumeric-bounded, 3-64 chars. Must not collide with a built-in theme id. Re-registering an existing id replaces its document.'),
|
|
48
|
+
registration: z
|
|
49
|
+
.object({ light: dtcgDocSchema, dark: dtcgDocSchema })
|
|
50
|
+
.describe('Both modes, required. Register what dark IS, even when identical to light — silent mode fallback is not part of runtime registration.'),
|
|
51
|
+
};
|
|
52
|
+
const outputSchema = {
|
|
53
|
+
themeId: z.string(),
|
|
54
|
+
documentHash: z
|
|
55
|
+
.string()
|
|
56
|
+
.describe('sha256 over the stored registration bytes — the identity join key.'),
|
|
57
|
+
updated: z
|
|
58
|
+
.boolean()
|
|
59
|
+
.describe('True when an existing registration was replaced; false on first registration.'),
|
|
60
|
+
coverage: z.object({
|
|
61
|
+
inheritMatched: z
|
|
62
|
+
.array(z.string())
|
|
63
|
+
.describe('Obligated tokens satisfied via explicit inherit patterns.'),
|
|
64
|
+
excluded: z
|
|
65
|
+
.array(z.string())
|
|
66
|
+
.describe('Manifest tokens excluded from the coverage obligation.'),
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
const sha256 = (s) => createHash('sha256').update(s, 'utf8').digest('hex');
|
|
70
|
+
export function createRegisterThemeHandler(deps) {
|
|
71
|
+
return {
|
|
72
|
+
name: 'ggui_ops_register_theme',
|
|
73
|
+
title: 'Register theme',
|
|
74
|
+
audience: ['ops'],
|
|
75
|
+
description: 'Register (or update) a runtime theme for an app the caller owns. The document must cover the consumed-token manifest — refusals name every uncovered token, per mode. The theme id obeys a fixed grammar and must not collide with a built-in id. Returns the stored documentHash (the identity join key) and the coverage detail (inherited + excluded tokens).',
|
|
76
|
+
inputSchema,
|
|
77
|
+
outputSchema,
|
|
78
|
+
async handler(rawInput, ctx) {
|
|
79
|
+
const ownerSub = resolveOwnerSub('ggui_ops_register_theme', ctx);
|
|
80
|
+
const parsed = z.object(inputSchema).parse(rawInput);
|
|
81
|
+
// 1. Tenancy — uniform not-found, no existence leak.
|
|
82
|
+
const app = await deps.apps.get({ appId: parsed.appId, ownerSub });
|
|
83
|
+
if (!app)
|
|
84
|
+
throw new AppNotFoundError(parsed.appId);
|
|
85
|
+
// 2. Identity — grammar first, then built-in collision.
|
|
86
|
+
if (!isValidThemeId(parsed.themeId)) {
|
|
87
|
+
throw new ThemeIdentityError('grammar', parsed.themeId);
|
|
88
|
+
}
|
|
89
|
+
if (deps.staticThemeIds.includes(parsed.themeId)) {
|
|
90
|
+
throw new ThemeIdentityError('collision', parsed.themeId);
|
|
91
|
+
}
|
|
92
|
+
// 3. Document — the validator's parser owns DTCG shape; a throw
|
|
93
|
+
// here means the document itself does not parse. Named wall,
|
|
94
|
+
// never a bare 500 (a fat-fingered document is user error).
|
|
95
|
+
// 4. Coverage — the registration gate.
|
|
96
|
+
let coverage;
|
|
97
|
+
try {
|
|
98
|
+
coverage = deps.coverageValidator(parsed.registration, deps.manifestTokens);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
throw new ThemeDocumentError(err instanceof Error ? err.message : String(err));
|
|
102
|
+
}
|
|
103
|
+
if (!coverage.covered) {
|
|
104
|
+
throw new ThemeCoverageError(coverage.uncovered);
|
|
105
|
+
}
|
|
106
|
+
// 5. Persist — CANONICAL bytes are the identity (RFC 8785, the
|
|
107
|
+
// contractHash/propsSchemaHash precedent): two key-orderings of
|
|
108
|
+
// one semantic document are ONE registration version. Raw
|
|
109
|
+
// stringify here would re-open the #579 representation class at
|
|
110
|
+
// the front door.
|
|
111
|
+
const document = canonicalize(parsed.registration);
|
|
112
|
+
if (document === undefined) {
|
|
113
|
+
throw new ThemeDocumentError('registration is not canonicalizable JSON');
|
|
114
|
+
}
|
|
115
|
+
const documentHash = sha256(document);
|
|
116
|
+
const existing = await deps.themeStore.get(parsed.appId, parsed.themeId);
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
try {
|
|
119
|
+
await deps.themeStore.put({
|
|
120
|
+
appId: parsed.appId,
|
|
121
|
+
themeId: parsed.themeId,
|
|
122
|
+
document,
|
|
123
|
+
documentHash,
|
|
124
|
+
registeredAt: existing?.registeredAt ?? now,
|
|
125
|
+
updatedAt: now,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
mapStorePutError(err);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
themeId: parsed.themeId,
|
|
133
|
+
documentHash,
|
|
134
|
+
updated: existing !== null,
|
|
135
|
+
coverage: {
|
|
136
|
+
inheritMatched: coverage.inheritMatched,
|
|
137
|
+
excluded: coverage.excluded,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ops-themes — runtime theme registration tools (ggui#598-C).
|
|
3
|
+
*
|
|
4
|
+
* Dependency posture: EVERYTHING injected. This package never imports
|
|
5
|
+
* the design package — the composer supplies the coverage validator,
|
|
6
|
+
* the consumed-token manifest, and the static preset-id list; the
|
|
7
|
+
* store arrives behind the frozen `ThemeStore` port. The handlers own
|
|
8
|
+
* orchestration + the refusal taxonomy, nothing else.
|
|
9
|
+
*
|
|
10
|
+
* Refusal taxonomy (one named class per wall — an operator must never
|
|
11
|
+
* guess which wall they hit):
|
|
12
|
+
* - `theme_coverage` — the document fails coverage conformance; the
|
|
13
|
+
* uncovered token lists ride verbatim.
|
|
14
|
+
* - `theme_identity` — the id fails the frozen grammar, or collides
|
|
15
|
+
* with a statically-compiled theme id.
|
|
16
|
+
* - `theme_quota` — a deployment-policy seam refused the write (the
|
|
17
|
+
* store decorator names its own limit in the message).
|
|
18
|
+
* Storage-integrity failures are deliberately NOT mapped: they bubble
|
|
19
|
+
* untouched as server faults.
|
|
20
|
+
*/
|
|
21
|
+
import type { ThemeCoverageResultLike } from './register-theme.js';
|
|
22
|
+
/**
|
|
23
|
+
* Structural seam for the registration gate — shaped after the design
|
|
24
|
+
* package's `validateThemeCoverage` without importing it. The composer
|
|
25
|
+
* binds the real validator; tests bind stubs.
|
|
26
|
+
*/
|
|
27
|
+
export type ThemeCoverageValidator = (docs: {
|
|
28
|
+
readonly light: Record<string, unknown>;
|
|
29
|
+
readonly dark: Record<string, unknown>;
|
|
30
|
+
}, manifestTokens: readonly string[]) => ThemeCoverageResultLike;
|
|
31
|
+
export declare class ThemeCoverageError extends Error {
|
|
32
|
+
readonly uncovered: {
|
|
33
|
+
readonly light: readonly string[];
|
|
34
|
+
readonly dark: readonly string[];
|
|
35
|
+
};
|
|
36
|
+
readonly code: "theme_coverage";
|
|
37
|
+
constructor(uncovered: {
|
|
38
|
+
readonly light: readonly string[];
|
|
39
|
+
readonly dark: readonly string[];
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export declare class ThemeIdentityError extends Error {
|
|
43
|
+
readonly reason: 'grammar' | 'collision';
|
|
44
|
+
readonly code: "theme_identity";
|
|
45
|
+
constructor(reason: 'grammar' | 'collision', themeId: string);
|
|
46
|
+
}
|
|
47
|
+
export declare class ThemeDocumentError extends Error {
|
|
48
|
+
readonly code: "theme_document";
|
|
49
|
+
constructor(underlying: string);
|
|
50
|
+
}
|
|
51
|
+
export declare class ThemeQuotaError extends Error {
|
|
52
|
+
readonly code: "theme_quota";
|
|
53
|
+
constructor(detail: string);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Map a store-thrown deployment-policy refusal onto the wire taxonomy
|
|
57
|
+
* WITHOUT importing the deployment's class: the policy seam is
|
|
58
|
+
* name-structural (any store decorator refusing a write names itself
|
|
59
|
+
* `ThemeQuotaExceededError`). Everything else rethrows untouched —
|
|
60
|
+
* integrity faults must never be dressed as user errors.
|
|
61
|
+
*/
|
|
62
|
+
export declare function mapStorePutError(err: unknown): never;
|
|
63
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ops-themes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,CACnC,IAAI,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACzF,cAAc,EAAE,SAAS,MAAM,EAAE,KAC9B,uBAAuB,CAAC;AAE7B,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;KAClC;IALH,QAAQ,CAAC,IAAI,EAAG,gBAAgB,CAAU;gBAE/B,SAAS,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;KAClC;CASJ;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW;IAF1C,QAAQ,CAAC,IAAI,EAAG,gBAAgB,CAAU;gBAE/B,MAAM,EAAE,SAAS,GAAG,WAAW,EACxC,OAAO,EAAE,MAAM;CASlB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAG,gBAAgB,CAAU;gBAC9B,UAAU,EAAE,MAAM;CAO/B;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAU;gBAC3B,MAAM,EAAE,MAAM;CAI3B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAKpD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export class ThemeCoverageError extends Error {
|
|
2
|
+
uncovered;
|
|
3
|
+
code = 'theme_coverage';
|
|
4
|
+
constructor(uncovered) {
|
|
5
|
+
super(`theme_coverage: the registration document does not cover the consumed-token manifest — ` +
|
|
6
|
+
`uncovered light: [${uncovered.light.join(', ')}], dark: [${uncovered.dark.join(', ')}]. ` +
|
|
7
|
+
`Emit each listed token or claim it via an explicit $extensions["ai.ggui.coverage"].inherit pattern.`);
|
|
8
|
+
this.uncovered = uncovered;
|
|
9
|
+
this.name = 'ThemeCoverageError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class ThemeIdentityError extends Error {
|
|
13
|
+
reason;
|
|
14
|
+
code = 'theme_identity';
|
|
15
|
+
constructor(reason, themeId) {
|
|
16
|
+
super(reason === 'grammar'
|
|
17
|
+
? `theme_identity: ${JSON.stringify(themeId)} fails the theme-id grammar — lowercase kebab, alphanumeric-bounded, 3-64 chars`
|
|
18
|
+
: `theme_identity: ${JSON.stringify(themeId)} collides with a built-in theme id — pick a distinct id`);
|
|
19
|
+
this.reason = reason;
|
|
20
|
+
this.name = 'ThemeIdentityError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class ThemeDocumentError extends Error {
|
|
24
|
+
code = 'theme_document';
|
|
25
|
+
constructor(underlying) {
|
|
26
|
+
super(`theme_document: the registration does not parse as a DTCG theme document — ` +
|
|
27
|
+
`fix the document shape and re-submit. Underlying: ${underlying}`);
|
|
28
|
+
this.name = 'ThemeDocumentError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class ThemeQuotaError extends Error {
|
|
32
|
+
code = 'theme_quota';
|
|
33
|
+
constructor(detail) {
|
|
34
|
+
super(`theme_quota: ${detail}`);
|
|
35
|
+
this.name = 'ThemeQuotaError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Map a store-thrown deployment-policy refusal onto the wire taxonomy
|
|
40
|
+
* WITHOUT importing the deployment's class: the policy seam is
|
|
41
|
+
* name-structural (any store decorator refusing a write names itself
|
|
42
|
+
* `ThemeQuotaExceededError`). Everything else rethrows untouched —
|
|
43
|
+
* integrity faults must never be dressed as user errors.
|
|
44
|
+
*/
|
|
45
|
+
export function mapStorePutError(err) {
|
|
46
|
+
if (err instanceof Error && err.name === 'ThemeQuotaExceededError') {
|
|
47
|
+
throw new ThemeQuotaError(err.message);
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
package/dist/renders/amend.d.ts
CHANGED
|
@@ -41,12 +41,17 @@ declare const outputSchema: {
|
|
|
41
41
|
readonly resourceUri: z.ZodString;
|
|
42
42
|
/** No-op feedback channel — same semantics as ggui_update's. */
|
|
43
43
|
readonly warning: z.ZodOptional<z.ZodString>;
|
|
44
|
+
/** ggui#560 — schema attestation, same semantics as ggui_update's. */
|
|
45
|
+
readonly propsSchemaHash: z.ZodOptional<z.ZodString>;
|
|
46
|
+
readonly propsSchemaProfile: z.ZodOptional<z.ZodString>;
|
|
44
47
|
};
|
|
45
48
|
interface AmendOutput {
|
|
46
49
|
sessionId: string;
|
|
47
50
|
updated: boolean;
|
|
48
51
|
resourceUri: string;
|
|
49
52
|
warning?: string;
|
|
53
|
+
propsSchemaHash?: string;
|
|
54
|
+
propsSchemaProfile?: string;
|
|
50
55
|
}
|
|
51
56
|
/**
|
|
52
57
|
* Build the OSS `ggui_amend` handler. Additive, like `update:` — server
|