@guuey/config 0.16.7 → 0.16.9
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/app.d.ts +61 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +54 -2
- package/dist/loader.d.ts +11 -3
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +65 -4
- package/dist/schema.d.ts +11 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/system-prompt.d.ts +17 -0
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +33 -0
- package/package.json +2 -2
package/dist/app.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* (agent or mcp-server) is what's deployable; this section is presentation.
|
|
10
10
|
*/
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
+
import { type GuueyAppTheme } from './theme.js';
|
|
12
13
|
/**
|
|
13
14
|
* End-user auth modes an app record accepts — mirrors the platform's
|
|
14
15
|
* `USER_AUTH_MODES` (`@guuey-private/types` `security/user-auth-mode.ts`),
|
|
@@ -47,6 +48,55 @@ export declare const AppAccessV1: z.ZodObject<{
|
|
|
47
48
|
}, z.core.$strict>;
|
|
48
49
|
/** Static TypeScript type for `app.access`. */
|
|
49
50
|
export type GuueyAppAccess = z.infer<typeof AppAccessV1>;
|
|
51
|
+
/**
|
|
52
|
+
* `guuey.json#app.page` — the STANDALONE PAGE's posture, declared in the
|
|
53
|
+
* manifest so `guuey agent apply` converges it (posture-as-code, guuey#286;
|
|
54
|
+
* requested by the first agents-as-code consumer, ggui#558). Field names ARE
|
|
55
|
+
* the platform's `standalonePage` patch vocabulary (`PUT /v1/apps/:id` /
|
|
56
|
+
* the reconcile `config` block, cli-wire `STANDALONE_PAGE_FIELDS`) — no
|
|
57
|
+
* translation; the backend pins the two lists equal
|
|
58
|
+
* (`handlers/reconcile.test.ts`, the APP_USER_AUTH_MODES pattern).
|
|
59
|
+
*
|
|
60
|
+
* Patch semantics, same as the PUT: an absent member is left untouched by a
|
|
61
|
+
* reconcile, `null` clears the member to its default (page on, indexable, no
|
|
62
|
+
* copy/CTA/endpoint). Values are shape-checked only — caps, the https rule
|
|
63
|
+
* and the CTA both-or-neither pairing are the platform validator's
|
|
64
|
+
* (`validateStandalonePagePatch`), so the CLI surfaces its exact message
|
|
65
|
+
* (the same split as `app.theme`'s colour grammar).
|
|
66
|
+
*
|
|
67
|
+
* `slug` stays OUT: claiming has uniqueness/release semantics (a ceremony,
|
|
68
|
+
* not a converged field). But the posture here REACHES the slug ceremony's
|
|
69
|
+
* automatic arm: the first-Live default-slug claim (guuey#249) consults it
|
|
70
|
+
* and skips when `enabled: false` — `--page off` in git means no auto-named
|
|
71
|
+
* public host, ever.
|
|
72
|
+
*/
|
|
73
|
+
export declare const AppPageV1: z.ZodObject<{
|
|
74
|
+
enabled: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
75
|
+
welcomeCopy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
76
|
+
ctaLabel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
77
|
+
ctaUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
78
|
+
identityEndpointUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
79
|
+
noindex: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
80
|
+
}, z.core.$strict>;
|
|
81
|
+
/** Static TypeScript type for `app.page`. */
|
|
82
|
+
export type GuueyAppPage = z.infer<typeof AppPageV1>;
|
|
83
|
+
/**
|
|
84
|
+
* `app.theme` as a file reference — `{ "file": "theme.json" }`, the same
|
|
85
|
+
* convention as `agent.systemPrompt` (guuey#400). The file's CONTENT is the
|
|
86
|
+
* same {@link AppThemeV1} vocabulary — no new grammar. Resolution is
|
|
87
|
+
* CLI-side (the loader reads the file relative to `guuey.json`); the server
|
|
88
|
+
* only ever sees the inline document and 400s an unresolved reference.
|
|
89
|
+
*
|
|
90
|
+
* Discrimination against the inline form is unambiguous: a `{file}`-only
|
|
91
|
+
* strict object can never collide with the theme vocabulary (which
|
|
92
|
+
* requires `mode`/`colors`).
|
|
93
|
+
*/
|
|
94
|
+
export declare const ThemeFileRefV1: z.ZodObject<{
|
|
95
|
+
file: z.ZodString;
|
|
96
|
+
}, z.core.$strict>;
|
|
97
|
+
export type ThemeFileRef = z.infer<typeof ThemeFileRefV1>;
|
|
98
|
+
/** Narrow an `app.theme` value to the `{ file }` reference form. */
|
|
99
|
+
export declare function isThemeFileRef(theme: ThemeFileRef | GuueyAppTheme): theme is ThemeFileRef;
|
|
50
100
|
/**
|
|
51
101
|
* The app section schema. All fields optional in v1 — a project may carry
|
|
52
102
|
* the bare minimum at first and grow the listing as it publishes.
|
|
@@ -71,7 +121,9 @@ export declare const AppSectionV1: z.ZodObject<{
|
|
|
71
121
|
allowedDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
72
122
|
guestAccess: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
73
123
|
}, z.core.$strict>>;
|
|
74
|
-
theme: z.ZodOptional<z.ZodObject<{
|
|
124
|
+
theme: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
125
|
+
file: z.ZodString;
|
|
126
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
75
127
|
name: z.ZodOptional<z.ZodString>;
|
|
76
128
|
mode: z.ZodEnum<{
|
|
77
129
|
light: "light";
|
|
@@ -167,6 +219,14 @@ export declare const AppSectionV1: z.ZodObject<{
|
|
|
167
219
|
comfortable: "comfortable";
|
|
168
220
|
}>;
|
|
169
221
|
}, z.core.$strict>>;
|
|
222
|
+
}, z.core.$strict>]>>;
|
|
223
|
+
page: z.ZodOptional<z.ZodObject<{
|
|
224
|
+
enabled: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
225
|
+
welcomeCopy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
226
|
+
ctaLabel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
227
|
+
ctaUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
228
|
+
identityEndpointUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
229
|
+
noindex: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
170
230
|
}, z.core.$strict>>;
|
|
171
231
|
}, z.core.$strict>;
|
|
172
232
|
/** Static TypeScript type for the app section. */
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AA0C5D;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,8CAA+C,CAAC;AAChF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;kBAWtB,CAAC;AAEH,+CAA+C;AAC/C,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,SAAS;;;;;;;kBAOpB,CAAC;AAEH,6CAA6C;AAC7C,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAErD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc;;kBAA8C,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,oEAAoE;AACpE,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,GAAG,aAAa,GAClC,KAAK,IAAI,YAAY,CAEvB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiBvB,CAAC;AAEH,kDAAkD;AAClD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
package/dist/app.js
CHANGED
|
@@ -75,6 +75,52 @@ export const AppAccessV1 = z.strictObject({
|
|
|
75
75
|
allowedDomains: z.array(z.string().min(1)).optional(),
|
|
76
76
|
guestAccess: z.boolean().nullable().optional(),
|
|
77
77
|
});
|
|
78
|
+
/**
|
|
79
|
+
* `guuey.json#app.page` — the STANDALONE PAGE's posture, declared in the
|
|
80
|
+
* manifest so `guuey agent apply` converges it (posture-as-code, guuey#286;
|
|
81
|
+
* requested by the first agents-as-code consumer, ggui#558). Field names ARE
|
|
82
|
+
* the platform's `standalonePage` patch vocabulary (`PUT /v1/apps/:id` /
|
|
83
|
+
* the reconcile `config` block, cli-wire `STANDALONE_PAGE_FIELDS`) — no
|
|
84
|
+
* translation; the backend pins the two lists equal
|
|
85
|
+
* (`handlers/reconcile.test.ts`, the APP_USER_AUTH_MODES pattern).
|
|
86
|
+
*
|
|
87
|
+
* Patch semantics, same as the PUT: an absent member is left untouched by a
|
|
88
|
+
* reconcile, `null` clears the member to its default (page on, indexable, no
|
|
89
|
+
* copy/CTA/endpoint). Values are shape-checked only — caps, the https rule
|
|
90
|
+
* and the CTA both-or-neither pairing are the platform validator's
|
|
91
|
+
* (`validateStandalonePagePatch`), so the CLI surfaces its exact message
|
|
92
|
+
* (the same split as `app.theme`'s colour grammar).
|
|
93
|
+
*
|
|
94
|
+
* `slug` stays OUT: claiming has uniqueness/release semantics (a ceremony,
|
|
95
|
+
* not a converged field). But the posture here REACHES the slug ceremony's
|
|
96
|
+
* automatic arm: the first-Live default-slug claim (guuey#249) consults it
|
|
97
|
+
* and skips when `enabled: false` — `--page off` in git means no auto-named
|
|
98
|
+
* public host, ever.
|
|
99
|
+
*/
|
|
100
|
+
export const AppPageV1 = z.strictObject({
|
|
101
|
+
enabled: z.boolean().nullable().optional(),
|
|
102
|
+
welcomeCopy: z.string().nullable().optional(),
|
|
103
|
+
ctaLabel: z.string().nullable().optional(),
|
|
104
|
+
ctaUrl: z.string().nullable().optional(),
|
|
105
|
+
identityEndpointUrl: z.string().nullable().optional(),
|
|
106
|
+
noindex: z.boolean().nullable().optional(),
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* `app.theme` as a file reference — `{ "file": "theme.json" }`, the same
|
|
110
|
+
* convention as `agent.systemPrompt` (guuey#400). The file's CONTENT is the
|
|
111
|
+
* same {@link AppThemeV1} vocabulary — no new grammar. Resolution is
|
|
112
|
+
* CLI-side (the loader reads the file relative to `guuey.json`); the server
|
|
113
|
+
* only ever sees the inline document and 400s an unresolved reference.
|
|
114
|
+
*
|
|
115
|
+
* Discrimination against the inline form is unambiguous: a `{file}`-only
|
|
116
|
+
* strict object can never collide with the theme vocabulary (which
|
|
117
|
+
* requires `mode`/`colors`).
|
|
118
|
+
*/
|
|
119
|
+
export const ThemeFileRefV1 = z.strictObject({ file: z.string().min(1) });
|
|
120
|
+
/** Narrow an `app.theme` value to the `{ file }` reference form. */
|
|
121
|
+
export function isThemeFileRef(theme) {
|
|
122
|
+
return 'file' in theme;
|
|
123
|
+
}
|
|
78
124
|
/**
|
|
79
125
|
* The app section schema. All fields optional in v1 — a project may carry
|
|
80
126
|
* the bare minimum at first and grow the listing as it publishes.
|
|
@@ -88,6 +134,12 @@ export const AppSectionV1 = z.strictObject({
|
|
|
88
134
|
customDomain: CustomDomainSchema.optional(),
|
|
89
135
|
/** Access policy converged by `guuey agent apply` — see {@link AppAccessV1}. */
|
|
90
136
|
access: AppAccessV1.optional(),
|
|
91
|
-
/**
|
|
92
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Chat theme AS CODE, converged by `guuey agent apply` — the inline
|
|
139
|
+
* document ({@link AppThemeV1}) or a `{ file }` reference the CLI
|
|
140
|
+
* resolves ({@link ThemeFileRefV1}).
|
|
141
|
+
*/
|
|
142
|
+
theme: z.union([ThemeFileRefV1, AppThemeV1]).optional(),
|
|
143
|
+
/** Standalone-page posture converged by `guuey agent apply` — see {@link AppPageV1}. */
|
|
144
|
+
page: AppPageV1.optional(),
|
|
93
145
|
});
|
package/dist/loader.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GuueyJsonV1 } from './schema.js';
|
|
2
|
+
import { type GuueyAppTheme } from './theme.js';
|
|
2
3
|
/** How many parent directories `findGuueyJson` will walk by default. */
|
|
3
4
|
export declare const DEFAULT_FIND_MAX_DEPTH = 8;
|
|
4
5
|
/**
|
|
@@ -45,6 +46,12 @@ export interface ResolvedGuueyJson {
|
|
|
45
46
|
* (caller falls back to `GUUEY_DEFAULT_SYSTEM_PROMPT`).
|
|
46
47
|
*/
|
|
47
48
|
resolvedSystemPrompt: string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The resolved app theme — the inline document from `app.theme`, or the
|
|
51
|
+
* file's parsed content when it was a `{ file: '...' }` reference
|
|
52
|
+
* (guuey#400), or `undefined` when no theme was set.
|
|
53
|
+
*/
|
|
54
|
+
resolvedTheme: GuueyAppTheme | undefined;
|
|
48
55
|
/** Absolute path the document was loaded from (for diagnostics). */
|
|
49
56
|
sourcePath: string;
|
|
50
57
|
}
|
|
@@ -57,15 +64,16 @@ export interface ResolvedGuueyJson {
|
|
|
57
64
|
* shape; the pod runtime reads the resolved prompt directly.
|
|
58
65
|
*
|
|
59
66
|
* Throws if the file is missing, unreadable, malformed, fails schema
|
|
60
|
-
* validation, OR the systemPrompt.file path resolves to
|
|
61
|
-
* unreadable file.
|
|
67
|
+
* validation, OR the systemPrompt.file / app.theme.file path resolves to
|
|
68
|
+
* a missing or unreadable file.
|
|
62
69
|
*/
|
|
63
70
|
export declare function loadGuueyJson(path: string): ResolvedGuueyJson;
|
|
64
71
|
/**
|
|
65
72
|
* Build the snapshot the deploy upload + pod boot consume.
|
|
66
73
|
*
|
|
67
74
|
* Replaces `agent.systemPrompt = { file }` with `agent.systemPrompt = <inlined>`
|
|
68
|
-
*
|
|
75
|
+
* and `app.theme = { file }` with the file's parsed document so the
|
|
76
|
+
* snapshot is self-contained. Returns a deep-cloned document
|
|
69
77
|
* (caller mutations don't leak back).
|
|
70
78
|
*/
|
|
71
79
|
export declare function buildDeploySnapshot(loaded: ResolvedGuueyJson): GuueyJsonV1;
|
package/dist/loader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEL,WAAW,EAGZ,MAAM,aAAa,CAAC;AAErB,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,GAAE,MAAsB,EAChC,QAAQ,GAAE,MAA+B,GACxC,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAgB3D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAIvE;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,GAAG,EAAE,WAAW,CAAC;IACjB;;;;;OAKG;IACH,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEL,WAAW,EAGZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5D,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,GAAE,MAAsB,EAChC,QAAQ,GAAE,MAA+B,GACxC,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAgB3D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAIvE;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,GAAG,EAAE,WAAW,CAAC;IACjB;;;;;OAKG;IACH,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC;;;;OAIG;IACH,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IACzC,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAK7D;AAmGD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAgB1E"}
|
package/dist/loader.js
CHANGED
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
23
23
|
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
24
24
|
import { GUUEY_JSON_FILENAME, assertSupportedGuueyJsonSchema, parseGuueyJson, } from './schema.js';
|
|
25
|
+
import { isThemeFileRef } from './app.js';
|
|
26
|
+
import { AppThemeV1 } from './theme.js';
|
|
25
27
|
/** How many parent directories `findGuueyJson` will walk by default. */
|
|
26
28
|
export const DEFAULT_FIND_MAX_DEPTH = 8;
|
|
27
29
|
/**
|
|
@@ -94,13 +96,14 @@ export function writeGuueyJsonFile(path, doc) {
|
|
|
94
96
|
* shape; the pod runtime reads the resolved prompt directly.
|
|
95
97
|
*
|
|
96
98
|
* Throws if the file is missing, unreadable, malformed, fails schema
|
|
97
|
-
* validation, OR the systemPrompt.file path resolves to
|
|
98
|
-
* unreadable file.
|
|
99
|
+
* validation, OR the systemPrompt.file / app.theme.file path resolves to
|
|
100
|
+
* a missing or unreadable file.
|
|
99
101
|
*/
|
|
100
102
|
export function loadGuueyJson(path) {
|
|
101
103
|
const doc = readGuueyJsonFile(path);
|
|
102
104
|
const resolvedSystemPrompt = resolveSystemPrompt(doc, path);
|
|
103
|
-
|
|
105
|
+
const resolvedTheme = resolveAppTheme(doc, path);
|
|
106
|
+
return { doc, resolvedSystemPrompt, resolvedTheme, sourcePath: path };
|
|
104
107
|
}
|
|
105
108
|
/**
|
|
106
109
|
* Resolve `agent.systemPrompt` to a final string (or undefined).
|
|
@@ -133,11 +136,61 @@ function resolveSystemPrompt(doc, guueyJsonPath) {
|
|
|
133
136
|
}
|
|
134
137
|
return readFileSync(resolved, 'utf-8');
|
|
135
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Resolve `app.theme` to the inline document (or undefined).
|
|
141
|
+
*
|
|
142
|
+
* - Absent → undefined.
|
|
143
|
+
* - Inline document → returned as-is.
|
|
144
|
+
* - `{ file }` → resolved relative to `guueyJsonPath`'s directory, file
|
|
145
|
+
* read + parsed against the STRICT {@link AppThemeV1} shape (guuey#400).
|
|
146
|
+
* Shape only — colour VALUES stay with the server's one grammar
|
|
147
|
+
* (`validateChatTheme`), so plan/apply surfaces its exact message.
|
|
148
|
+
*
|
|
149
|
+
* File paths must be relative + must not escape the project root (no
|
|
150
|
+
* `..` traversal). Absolute paths are rejected — keeps the snapshot
|
|
151
|
+
* portable across deploy environments.
|
|
152
|
+
*/
|
|
153
|
+
function resolveAppTheme(doc, guueyJsonPath) {
|
|
154
|
+
const theme = doc.app?.theme;
|
|
155
|
+
if (theme === undefined)
|
|
156
|
+
return undefined;
|
|
157
|
+
if (!isThemeFileRef(theme))
|
|
158
|
+
return theme;
|
|
159
|
+
// theme = { file: '...' }
|
|
160
|
+
if (isAbsolute(theme.file)) {
|
|
161
|
+
throw new Error(`app.theme.file must be a relative path (got absolute: ${theme.file})`);
|
|
162
|
+
}
|
|
163
|
+
if (theme.file.split('/').includes('..')) {
|
|
164
|
+
throw new Error(`app.theme.file must not traverse parent directories (got: ${theme.file})`);
|
|
165
|
+
}
|
|
166
|
+
const baseDir = dirname(guueyJsonPath);
|
|
167
|
+
const resolved = resolve(baseDir, theme.file);
|
|
168
|
+
if (!existsSync(resolved)) {
|
|
169
|
+
throw new Error(`app.theme.file references missing file: ${theme.file} (resolved to ${resolved})`);
|
|
170
|
+
}
|
|
171
|
+
const raw = readFileSync(resolved, 'utf-8');
|
|
172
|
+
let json;
|
|
173
|
+
try {
|
|
174
|
+
json = JSON.parse(raw);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
178
|
+
throw new Error(`app.theme.file ${theme.file} is not valid JSON: ${msg}`);
|
|
179
|
+
}
|
|
180
|
+
const parsed = AppThemeV1.safeParse(json);
|
|
181
|
+
if (!parsed.success) {
|
|
182
|
+
const first = parsed.error.issues[0];
|
|
183
|
+
const path = first?.path.join('.') || '(root)';
|
|
184
|
+
throw new Error(`app.theme.file ${theme.file} failed theme validation at "${path}": ${first?.message ?? 'unknown error'}`);
|
|
185
|
+
}
|
|
186
|
+
return parsed.data;
|
|
187
|
+
}
|
|
136
188
|
/**
|
|
137
189
|
* Build the snapshot the deploy upload + pod boot consume.
|
|
138
190
|
*
|
|
139
191
|
* Replaces `agent.systemPrompt = { file }` with `agent.systemPrompt = <inlined>`
|
|
140
|
-
*
|
|
192
|
+
* and `app.theme = { file }` with the file's parsed document so the
|
|
193
|
+
* snapshot is self-contained. Returns a deep-cloned document
|
|
141
194
|
* (caller mutations don't leak back).
|
|
142
195
|
*/
|
|
143
196
|
export function buildDeploySnapshot(loaded) {
|
|
@@ -145,5 +198,13 @@ export function buildDeploySnapshot(loaded) {
|
|
|
145
198
|
if (loaded.resolvedSystemPrompt !== undefined) {
|
|
146
199
|
cloned.agent.systemPrompt = loaded.resolvedSystemPrompt;
|
|
147
200
|
}
|
|
201
|
+
const theme = cloned.app?.theme;
|
|
202
|
+
if (cloned.app !== undefined &&
|
|
203
|
+
theme !== undefined &&
|
|
204
|
+
isThemeFileRef(theme) &&
|
|
205
|
+
loaded.resolvedTheme !== undefined) {
|
|
206
|
+
const themeClone = JSON.parse(JSON.stringify(loaded.resolvedTheme));
|
|
207
|
+
cloned.app.theme = themeClone;
|
|
208
|
+
}
|
|
148
209
|
return cloned;
|
|
149
210
|
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -256,7 +256,9 @@ export declare const GuueyJsonV1: z.ZodObject<{
|
|
|
256
256
|
allowedDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
257
257
|
guestAccess: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
258
258
|
}, z.core.$strict>>;
|
|
259
|
-
theme: z.ZodOptional<z.ZodObject<{
|
|
259
|
+
theme: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
260
|
+
file: z.ZodString;
|
|
261
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
260
262
|
name: z.ZodOptional<z.ZodString>;
|
|
261
263
|
mode: z.ZodEnum<{
|
|
262
264
|
light: "light";
|
|
@@ -352,6 +354,14 @@ export declare const GuueyJsonV1: z.ZodObject<{
|
|
|
352
354
|
comfortable: "comfortable";
|
|
353
355
|
}>;
|
|
354
356
|
}, z.core.$strict>>;
|
|
357
|
+
}, z.core.$strict>]>>;
|
|
358
|
+
page: z.ZodOptional<z.ZodObject<{
|
|
359
|
+
enabled: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
360
|
+
welcomeCopy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
361
|
+
ctaLabel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
362
|
+
ctaUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
363
|
+
identityEndpointUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
364
|
+
noindex: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
355
365
|
}, z.core.$strict>>;
|
|
356
366
|
}, z.core.$strict>>;
|
|
357
367
|
ggui: z.ZodOptional<z.ZodObject<{
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAY5E;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;aAE3B,IAAI,EAAE,gBAAgB,GAAG,oBAAoB;aAC7C,KAAK,EAAE,MAAM;gBADb,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,EAC7C,KAAK,EAAE,MAAM,EAC7B,OAAO,EAAE,MAAM;CAKlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAkBjE;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAY5E;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;aAE3B,IAAI,EAAE,gBAAgB,GAAG,oBAAoB;aAC7C,KAAK,EAAE,MAAM;gBADb,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,EAC7C,KAAK,EAAE,MAAM,EAC7B,OAAO,EAAE,MAAM;CAKlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAkBjE;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmDtB,CAAC;AAEH,kDAAkD;AAClD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAG3D,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAEhD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAExD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,WAAW,CAAC,SAAS,CAAC,CAE1C"}
|
package/dist/system-prompt.d.ts
CHANGED
|
@@ -10,4 +10,21 @@
|
|
|
10
10
|
* handshake.
|
|
11
11
|
*/
|
|
12
12
|
export declare const GUUEY_DEFAULT_SYSTEM_PROMPT: string;
|
|
13
|
+
/**
|
|
14
|
+
* The system prompt the `@guuey/create-agentic-app` scaffold ships in
|
|
15
|
+
* `prompts/system.md` (guuey#463) — distinct from
|
|
16
|
+
* {@link GUUEY_DEFAULT_SYSTEM_PROMPT}, which is the RUNTIME fallback for an
|
|
17
|
+
* agent that supplies no prompt at all. This constant is the single source
|
|
18
|
+
* for the scaffold text: `create-agentic-app`'s `build-templates.mjs` stamps
|
|
19
|
+
* `templates-src/core/prompts/system.md` from it (as `text + '\n'`) and
|
|
20
|
+
* `check-templates.mjs` asserts byte-equality as the publish guard.
|
|
21
|
+
*
|
|
22
|
+
* Why it must be single-sourced: `guuey pull`'s known-default replace rule
|
|
23
|
+
* (guuey#463, the #455 rider) may only overwrite a local `prompts/system.md`
|
|
24
|
+
* whose content is byte-identical to one of these two known defaults —
|
|
25
|
+
* anything else is a builder's own edit and is never clobbered. Editing this
|
|
26
|
+
* text therefore changes what `pull` recognizes as "untouched scaffold";
|
|
27
|
+
* rebuild the templates after any edit and commit the restamped file.
|
|
28
|
+
*/
|
|
29
|
+
export declare const GUUEY_SCAFFOLD_SYSTEM_PROMPT: string;
|
|
13
30
|
//# sourceMappingURL=system-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,QAOhC,CAAC"}
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,QAOhC,CAAC;AAET;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,4BAA4B,QAgBjC,CAAC"}
|
package/dist/system-prompt.js
CHANGED
|
@@ -17,3 +17,36 @@ environment. Follow each tool's own description for guidance on when and how
|
|
|
17
17
|
to use it. Maintain the thread of conversation across turns and ask
|
|
18
18
|
clarifying questions when intent is ambiguous.
|
|
19
19
|
`.trim();
|
|
20
|
+
/**
|
|
21
|
+
* The system prompt the `@guuey/create-agentic-app` scaffold ships in
|
|
22
|
+
* `prompts/system.md` (guuey#463) — distinct from
|
|
23
|
+
* {@link GUUEY_DEFAULT_SYSTEM_PROMPT}, which is the RUNTIME fallback for an
|
|
24
|
+
* agent that supplies no prompt at all. This constant is the single source
|
|
25
|
+
* for the scaffold text: `create-agentic-app`'s `build-templates.mjs` stamps
|
|
26
|
+
* `templates-src/core/prompts/system.md` from it (as `text + '\n'`) and
|
|
27
|
+
* `check-templates.mjs` asserts byte-equality as the publish guard.
|
|
28
|
+
*
|
|
29
|
+
* Why it must be single-sourced: `guuey pull`'s known-default replace rule
|
|
30
|
+
* (guuey#463, the #455 rider) may only overwrite a local `prompts/system.md`
|
|
31
|
+
* whose content is byte-identical to one of these two known defaults —
|
|
32
|
+
* anything else is a builder's own edit and is never clobbered. Editing this
|
|
33
|
+
* text therefore changes what `pull` recognizes as "untouched scaffold";
|
|
34
|
+
* rebuild the templates after any edit and commit the restamped file.
|
|
35
|
+
*/
|
|
36
|
+
export const GUUEY_SCAFFOLD_SYSTEM_PROMPT = `
|
|
37
|
+
You are the agentic-app-template assistant. You have a todo tool server —
|
|
38
|
+
use it to create, list, toggle, and delete the user's todos.
|
|
39
|
+
|
|
40
|
+
Show, don't tell: when a result has structure — a todo list, a form, a
|
|
41
|
+
confirmation — render it as an interactive surface with the ggui render
|
|
42
|
+
loop by default; keep plain prose for one-line answers with nothing to
|
|
43
|
+
show. After changing todos (create, toggle, delete), render the updated
|
|
44
|
+
list, so every turn ends on a surface that reflects the current state.
|
|
45
|
+
Use only the fields the surface's schema declares.
|
|
46
|
+
|
|
47
|
+
An under-specified ask is NEVER answered with a text-only list of
|
|
48
|
+
questions: render the closest useful surface FIRST — the current list,
|
|
49
|
+
the options, a form — and ask your one narrowing question in a short
|
|
50
|
+
line beside it. Clarification happens ON a surface, from the very first
|
|
51
|
+
turn.
|
|
52
|
+
`.trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/config",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.9",
|
|
4
4
|
"description": "Open-source schemas + loaders for the three guuey config files: agent.json (declarative agent definition), guuey.json (hosted-deploy overlay), and the helper types around them. Consumed by @guuey/cli, the guuey backend, and devs writing their own agent or MCP server.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@types/node": "^24.0.0",
|
|
36
36
|
"typescript": "^5.0.0",
|
|
37
37
|
"vitest": "^3.2.7",
|
|
38
|
-
"@guuey/chat": "0.16.
|
|
38
|
+
"@guuey/chat": "0.16.9"
|
|
39
39
|
},
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|