@guuey/config 0.1.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/LICENSE +21 -0
- package/README.md +18 -0
- package/dist/agent-loader.d.ts +65 -0
- package/dist/agent-loader.d.ts.map +1 -0
- package/dist/agent-loader.js +155 -0
- package/dist/agent.d.ts +284 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +426 -0
- package/dist/app.d.ts +26 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +54 -0
- package/dist/ggui.d.ts +36 -0
- package/dist/ggui.d.ts.map +1 -0
- package/dist/ggui.js +51 -0
- package/dist/hosting.d.ts +78 -0
- package/dist/hosting.d.ts.map +1 -0
- package/dist/hosting.js +30 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/loader.d.ts +70 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +144 -0
- package/dist/mcp-proxy.d.ts +123 -0
- package/dist/mcp-proxy.d.ts.map +1 -0
- package/dist/mcp-proxy.js +133 -0
- package/dist/mcp-servers.d.ts +173 -0
- package/dist/mcp-servers.d.ts.map +1 -0
- package/dist/mcp-servers.js +147 -0
- package/dist/registry.d.ts +35 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +80 -0
- package/dist/schema.d.ts +204 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +125 -0
- package/dist/system-prompt.d.ts +13 -0
- package/dist/system-prompt.d.ts.map +1 -0
- package/dist/system-prompt.js +19 -0
- package/package.json +56 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guuey hosted control-plane types — agent sizing, deployment
|
|
3
|
+
* lifecycle, and the streaming events Guuey's backend emits during
|
|
4
|
+
* deploys.
|
|
5
|
+
*
|
|
6
|
+
* These types describe Guuey hosting concerns: `DeployTarget`
|
|
7
|
+
* includes the `'ggui'` vendor literal, `DeployEvent` is streamed by
|
|
8
|
+
* Guuey's AppSync subscription, and `HostingConfig` is a shape on
|
|
9
|
+
* `guuey.json`. They lived in `@ggui-ai/protocol` until 2026-04-18
|
|
10
|
+
* as a historical artefact — they were never vendor-neutral wire
|
|
11
|
+
* types. Relocated here as part of the overlay-type cleanup in the
|
|
12
|
+
* two-file manifest model. See
|
|
13
|
+
* `docs/plans/2026-04-17-ggui-oss-split.md` §8 for the lock.
|
|
14
|
+
*
|
|
15
|
+
* Open packages must not import from this module. Consumers today
|
|
16
|
+
* are all closed (`@guuey-private/types`, `cloud/`). If an open
|
|
17
|
+
* package ever needs one of these types, re-evaluate the
|
|
18
|
+
* classification before adding the import — most likely the open
|
|
19
|
+
* code should not depend on hosted-control-plane shapes at all.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Agent container size — describes workload intensity.
|
|
23
|
+
* Developers pick a size; Guuey maps it to CPU/memory internally.
|
|
24
|
+
*
|
|
25
|
+
* Exported as a tuple so `schema.ts` can reuse the same canonical list
|
|
26
|
+
* when building the `deploy.size` zod enum. Keeping one source of truth
|
|
27
|
+
* for the literal set avoids the two drifting — the hosting type and
|
|
28
|
+
* the `guuey.json` overlay must always agree on what sizes exist.
|
|
29
|
+
*/
|
|
30
|
+
export declare const AGENT_SIZES: readonly ["xs", "sm", "md", "lg", "xl"];
|
|
31
|
+
export type AgentSize = (typeof AGENT_SIZES)[number];
|
|
32
|
+
/**
|
|
33
|
+
* Deployment target — where the agent runs. `'ggui'` is the Guuey
|
|
34
|
+
* hosted platform; the other literals are recognised but not
|
|
35
|
+
* first-party.
|
|
36
|
+
*/
|
|
37
|
+
export type DeployTarget = 'ggui' | 'fly' | 'railway' | 'self';
|
|
38
|
+
/**
|
|
39
|
+
* Deployment lifecycle status — superset of all states.
|
|
40
|
+
*
|
|
41
|
+
* Transient states (building, pushing, deploying, health_checking)
|
|
42
|
+
* exist only in {@link DeployEvent} streams. The backend stores only
|
|
43
|
+
* settled states (not_deployed, live, failed, stopped, rolled_back).
|
|
44
|
+
* The persisted enum is intentionally narrower.
|
|
45
|
+
*/
|
|
46
|
+
export type DeploymentStatus = 'not_deployed' | 'building' | 'pushing' | 'deploying' | 'health_checking' | 'live' | 'failed' | 'stopped' | 'rolled_back';
|
|
47
|
+
/**
|
|
48
|
+
* Progress event emitted during deployment.
|
|
49
|
+
* Streamed to CLI and Platform Dashboard via AppSync subscription.
|
|
50
|
+
*/
|
|
51
|
+
export interface DeployEvent {
|
|
52
|
+
/** App being deployed */
|
|
53
|
+
appId: string;
|
|
54
|
+
/** Unique build identifier */
|
|
55
|
+
buildId: string;
|
|
56
|
+
/** Current deployment phase */
|
|
57
|
+
status: DeploymentStatus;
|
|
58
|
+
/** Human-readable progress message */
|
|
59
|
+
message: string;
|
|
60
|
+
/** ISO 8601 timestamp */
|
|
61
|
+
timestamp: string;
|
|
62
|
+
/** Deployment version number (set when deploying or later) */
|
|
63
|
+
version?: number;
|
|
64
|
+
/** Live endpoint URL (set when status = 'live') */
|
|
65
|
+
url?: string;
|
|
66
|
+
/** Error details (set when status = 'failed') */
|
|
67
|
+
error?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Hosting configuration field in `guuey.json`.
|
|
71
|
+
*/
|
|
72
|
+
export interface HostingConfig {
|
|
73
|
+
/** Agent container size (default: 'xs' for free, 'sm' for paid) */
|
|
74
|
+
size?: AgentSize;
|
|
75
|
+
/** Deployment target (default: 'ggui') */
|
|
76
|
+
target?: DeployTarget;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=hosting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosting.d.ts","sourceRoot":"","sources":["../src/hosting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,yCAA0C,CAAC;AACnE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,UAAU,GACV,SAAS,GACT,WAAW,GACX,iBAAiB,GACjB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,aAAa,CAAC;AAElB;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB"}
|
package/dist/hosting.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guuey hosted control-plane types — agent sizing, deployment
|
|
3
|
+
* lifecycle, and the streaming events Guuey's backend emits during
|
|
4
|
+
* deploys.
|
|
5
|
+
*
|
|
6
|
+
* These types describe Guuey hosting concerns: `DeployTarget`
|
|
7
|
+
* includes the `'ggui'` vendor literal, `DeployEvent` is streamed by
|
|
8
|
+
* Guuey's AppSync subscription, and `HostingConfig` is a shape on
|
|
9
|
+
* `guuey.json`. They lived in `@ggui-ai/protocol` until 2026-04-18
|
|
10
|
+
* as a historical artefact — they were never vendor-neutral wire
|
|
11
|
+
* types. Relocated here as part of the overlay-type cleanup in the
|
|
12
|
+
* two-file manifest model. See
|
|
13
|
+
* `docs/plans/2026-04-17-ggui-oss-split.md` §8 for the lock.
|
|
14
|
+
*
|
|
15
|
+
* Open packages must not import from this module. Consumers today
|
|
16
|
+
* are all closed (`@guuey-private/types`, `cloud/`). If an open
|
|
17
|
+
* package ever needs one of these types, re-evaluate the
|
|
18
|
+
* classification before adding the import — most likely the open
|
|
19
|
+
* code should not depend on hosted-control-plane shapes at all.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Agent container size — describes workload intensity.
|
|
23
|
+
* Developers pick a size; Guuey maps it to CPU/memory internally.
|
|
24
|
+
*
|
|
25
|
+
* Exported as a tuple so `schema.ts` can reuse the same canonical list
|
|
26
|
+
* when building the `deploy.size` zod enum. Keeping one source of truth
|
|
27
|
+
* for the literal set avoids the two drifting — the hosting type and
|
|
28
|
+
* the `guuey.json` overlay must always agree on what sizes exist.
|
|
29
|
+
*/
|
|
30
|
+
export const AGENT_SIZES = ['xs', 'sm', 'md', 'lg', 'xl'];
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@guuey/config` — schemas + loaders for `guuey.json` (the merged
|
|
3
|
+
* platform config file).
|
|
4
|
+
*
|
|
5
|
+
* Post-2026-05-25 slice 7.2: `agent.json` was merged into
|
|
6
|
+
* `guuey.json#agent`. See `docs/plans/2026-05-25-platform-architecture.md`
|
|
7
|
+
* §3.1 + §14.2 for the canonical shape + field-by-field migration.
|
|
8
|
+
*
|
|
9
|
+
* Consumers: `@guuey/cli`, guuey backend (cliApi handlers,
|
|
10
|
+
* nocode-runtime, deploy-controller), framework adapters under
|
|
11
|
+
* `oss/packages/frameworks/*`.
|
|
12
|
+
*/
|
|
13
|
+
export * from './schema.js';
|
|
14
|
+
export * from './agent.js';
|
|
15
|
+
export * from './app.js';
|
|
16
|
+
export * from './ggui.js';
|
|
17
|
+
export * from './loader.js';
|
|
18
|
+
export * from './hosting.js';
|
|
19
|
+
export * from './system-prompt.js';
|
|
20
|
+
export * from './registry.js';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@guuey/config` — schemas + loaders for `guuey.json` (the merged
|
|
3
|
+
* platform config file).
|
|
4
|
+
*
|
|
5
|
+
* Post-2026-05-25 slice 7.2: `agent.json` was merged into
|
|
6
|
+
* `guuey.json#agent`. See `docs/plans/2026-05-25-platform-architecture.md`
|
|
7
|
+
* §3.1 + §14.2 for the canonical shape + field-by-field migration.
|
|
8
|
+
*
|
|
9
|
+
* Consumers: `@guuey/cli`, guuey backend (cliApi handlers,
|
|
10
|
+
* nocode-runtime, deploy-controller), framework adapters under
|
|
11
|
+
* `oss/packages/frameworks/*`.
|
|
12
|
+
*/
|
|
13
|
+
export * from './schema.js';
|
|
14
|
+
export * from './agent.js';
|
|
15
|
+
export * from './app.js';
|
|
16
|
+
export * from './ggui.js';
|
|
17
|
+
export * from './loader.js';
|
|
18
|
+
export * from './hosting.js';
|
|
19
|
+
export * from './system-prompt.js';
|
|
20
|
+
export * from './registry.js';
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { GuueyJsonV1 } from './schema.js';
|
|
2
|
+
/** How many parent directories `findGuueyJson` will walk by default. */
|
|
3
|
+
export declare const DEFAULT_FIND_MAX_DEPTH = 8;
|
|
4
|
+
/**
|
|
5
|
+
* Walk up from `startDir` (default: `process.cwd()`) looking for a
|
|
6
|
+
* `guuey.json`. Returns the absolute path to the first match, or
|
|
7
|
+
* `null` if no file is found within `maxDepth` levels.
|
|
8
|
+
*
|
|
9
|
+
* Stops when the filesystem root is reached, regardless of `maxDepth`.
|
|
10
|
+
* Never throws — a missing file is a valid result (not in a guuey project),
|
|
11
|
+
* not an error.
|
|
12
|
+
*/
|
|
13
|
+
export declare function findGuueyJson(startDir?: string, maxDepth?: number): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Read + parse `guuey.json` from `path`. Throws if the file is missing,
|
|
16
|
+
* unreadable, malformed JSON, or fails schema validation.
|
|
17
|
+
*
|
|
18
|
+
* Does NOT resolve `agent.systemPrompt.file` references. Use
|
|
19
|
+
* {@link loadGuueyJson} for file resolution.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readGuueyJsonFile(path: string): GuueyJsonV1;
|
|
22
|
+
/**
|
|
23
|
+
* Write a `guuey.json` to disk at `path` with stable 2-space indentation
|
|
24
|
+
* and a trailing newline.
|
|
25
|
+
*
|
|
26
|
+
* Validates the document against {@link GuueyJsonV1} before writing — bad
|
|
27
|
+
* data never lands on disk.
|
|
28
|
+
*/
|
|
29
|
+
export declare function writeGuueyJsonFile(path: string, doc: GuueyJsonV1): void;
|
|
30
|
+
/**
|
|
31
|
+
* Result of resolving file-references inside a `guuey.json` document.
|
|
32
|
+
*
|
|
33
|
+
* `doc` is the original document (with `{ file: '...' }` references intact);
|
|
34
|
+
* `resolvedSystemPrompt` is the inlined string the pod will use at boot.
|
|
35
|
+
*/
|
|
36
|
+
export interface ResolvedGuueyJson {
|
|
37
|
+
/** The original parsed document. */
|
|
38
|
+
doc: GuueyJsonV1;
|
|
39
|
+
/**
|
|
40
|
+
* The resolved system prompt — either the inline string from
|
|
41
|
+
* `agent.systemPrompt`, or the file contents when it was a
|
|
42
|
+
* `{ file: '...' }` reference, or `undefined` when no prompt was set
|
|
43
|
+
* (caller falls back to `GUUEY_DEFAULT_SYSTEM_PROMPT`).
|
|
44
|
+
*/
|
|
45
|
+
resolvedSystemPrompt: string | undefined;
|
|
46
|
+
/** Absolute path the document was loaded from (for diagnostics). */
|
|
47
|
+
sourcePath: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load + parse `guuey.json` from `path`, then resolve any
|
|
51
|
+
* `agent.systemPrompt.file` reference into an inlined string.
|
|
52
|
+
*
|
|
53
|
+
* The resolved prompt is returned alongside the parsed document so callers
|
|
54
|
+
* can choose how to use it. The deploy snapshot inlines it into a string
|
|
55
|
+
* shape; the pod runtime reads the resolved prompt directly.
|
|
56
|
+
*
|
|
57
|
+
* Throws if the file is missing, unreadable, malformed, fails schema
|
|
58
|
+
* validation, OR the systemPrompt.file path resolves to a missing or
|
|
59
|
+
* unreadable file.
|
|
60
|
+
*/
|
|
61
|
+
export declare function loadGuueyJson(path: string): ResolvedGuueyJson;
|
|
62
|
+
/**
|
|
63
|
+
* Build the snapshot the deploy upload + pod boot consume.
|
|
64
|
+
*
|
|
65
|
+
* Replaces `agent.systemPrompt = { file }` with `agent.systemPrompt = <inlined>`
|
|
66
|
+
* so the snapshot is self-contained. Returns a deep-cloned document
|
|
67
|
+
* (caller mutations don't leak back).
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildDeploySnapshot(loaded: ResolvedGuueyJson): GuueyJsonV1;
|
|
70
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEL,WAAW,EAEZ,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;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAa3D;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,CAI7D;AAyCD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAM1E"}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-only filesystem helpers for `guuey.json`.
|
|
3
|
+
*
|
|
4
|
+
* Pure-parse helpers (`parseGuueyJson` / `safeParseGuueyJson`) live in
|
|
5
|
+
* `./schema.ts` and are safe to import from non-Node contexts. This
|
|
6
|
+
* module adds the file-resolution layer: reading `guuey.json` from disk,
|
|
7
|
+
* inlining `agent.systemPrompt.file` references, and producing the
|
|
8
|
+
* snapshot the deploy upload + pod boot both read.
|
|
9
|
+
*
|
|
10
|
+
* Intended callers:
|
|
11
|
+
*
|
|
12
|
+
* - `@guuey/cli` — `guuey deploy` reads + inlines + POSTs the snapshot.
|
|
13
|
+
* - `@guuey/cli` — `guuey pull` writes back from a hosted record.
|
|
14
|
+
* - Guuey control-plane services that re-validate a submitted snapshot
|
|
15
|
+
* server-side before persisting to `AgentDeployment`.
|
|
16
|
+
* - `nocode-runtime` / `@guuey/host` — pod reads the snapshot back at boot
|
|
17
|
+
* (from the env-injected JSON, not directly from disk).
|
|
18
|
+
*
|
|
19
|
+
* The open `ggui` ecosystem must NOT import from this package — `guuey.json`
|
|
20
|
+
* is Guuey platform config, not protocol shape.
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
23
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
24
|
+
import { GUUEY_JSON_FILENAME, parseGuueyJson, } from './schema.js';
|
|
25
|
+
/** How many parent directories `findGuueyJson` will walk by default. */
|
|
26
|
+
export const DEFAULT_FIND_MAX_DEPTH = 8;
|
|
27
|
+
/**
|
|
28
|
+
* Walk up from `startDir` (default: `process.cwd()`) looking for a
|
|
29
|
+
* `guuey.json`. Returns the absolute path to the first match, or
|
|
30
|
+
* `null` if no file is found within `maxDepth` levels.
|
|
31
|
+
*
|
|
32
|
+
* Stops when the filesystem root is reached, regardless of `maxDepth`.
|
|
33
|
+
* Never throws — a missing file is a valid result (not in a guuey project),
|
|
34
|
+
* not an error.
|
|
35
|
+
*/
|
|
36
|
+
export function findGuueyJson(startDir = process.cwd(), maxDepth = DEFAULT_FIND_MAX_DEPTH) {
|
|
37
|
+
let dir = resolve(startDir);
|
|
38
|
+
for (let i = 0; i <= maxDepth; i++) {
|
|
39
|
+
const candidate = join(dir, GUUEY_JSON_FILENAME);
|
|
40
|
+
if (existsSync(candidate))
|
|
41
|
+
return candidate;
|
|
42
|
+
const parent = dirname(dir);
|
|
43
|
+
if (parent === dir)
|
|
44
|
+
return null;
|
|
45
|
+
dir = parent;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read + parse `guuey.json` from `path`. Throws if the file is missing,
|
|
51
|
+
* unreadable, malformed JSON, or fails schema validation.
|
|
52
|
+
*
|
|
53
|
+
* Does NOT resolve `agent.systemPrompt.file` references. Use
|
|
54
|
+
* {@link loadGuueyJson} for file resolution.
|
|
55
|
+
*/
|
|
56
|
+
export function readGuueyJsonFile(path) {
|
|
57
|
+
if (!existsSync(path)) {
|
|
58
|
+
throw new Error(`guuey.json not found at ${path}`);
|
|
59
|
+
}
|
|
60
|
+
const raw = readFileSync(path, 'utf-8');
|
|
61
|
+
let json;
|
|
62
|
+
try {
|
|
63
|
+
json = JSON.parse(raw);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
67
|
+
throw new Error(`guuey.json at ${path} is not valid JSON: ${msg}`);
|
|
68
|
+
}
|
|
69
|
+
return parseGuueyJson(json);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Write a `guuey.json` to disk at `path` with stable 2-space indentation
|
|
73
|
+
* and a trailing newline.
|
|
74
|
+
*
|
|
75
|
+
* Validates the document against {@link GuueyJsonV1} before writing — bad
|
|
76
|
+
* data never lands on disk.
|
|
77
|
+
*/
|
|
78
|
+
export function writeGuueyJsonFile(path, doc) {
|
|
79
|
+
const validated = parseGuueyJson(doc);
|
|
80
|
+
const serialized = JSON.stringify(validated, null, 2) + '\n';
|
|
81
|
+
writeFileSync(path, serialized, 'utf-8');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Load + parse `guuey.json` from `path`, then resolve any
|
|
85
|
+
* `agent.systemPrompt.file` reference into an inlined string.
|
|
86
|
+
*
|
|
87
|
+
* The resolved prompt is returned alongside the parsed document so callers
|
|
88
|
+
* can choose how to use it. The deploy snapshot inlines it into a string
|
|
89
|
+
* shape; the pod runtime reads the resolved prompt directly.
|
|
90
|
+
*
|
|
91
|
+
* Throws if the file is missing, unreadable, malformed, fails schema
|
|
92
|
+
* validation, OR the systemPrompt.file path resolves to a missing or
|
|
93
|
+
* unreadable file.
|
|
94
|
+
*/
|
|
95
|
+
export function loadGuueyJson(path) {
|
|
96
|
+
const doc = readGuueyJsonFile(path);
|
|
97
|
+
const resolvedSystemPrompt = resolveSystemPrompt(doc, path);
|
|
98
|
+
return { doc, resolvedSystemPrompt, sourcePath: path };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolve `agent.systemPrompt` to a final string (or undefined).
|
|
102
|
+
*
|
|
103
|
+
* - Absent → undefined (caller applies platform default).
|
|
104
|
+
* - Inline string → returned as-is.
|
|
105
|
+
* - `{ file }` → resolved relative to `guueyJsonPath`'s directory, file read.
|
|
106
|
+
*
|
|
107
|
+
* File paths must be relative + must not escape the project root (no
|
|
108
|
+
* `..` traversal). Absolute paths are rejected — keeps the snapshot
|
|
109
|
+
* portable across deploy environments.
|
|
110
|
+
*/
|
|
111
|
+
function resolveSystemPrompt(doc, guueyJsonPath) {
|
|
112
|
+
const sp = doc.agent.systemPrompt;
|
|
113
|
+
if (sp === undefined)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (typeof sp === 'string')
|
|
116
|
+
return sp;
|
|
117
|
+
// sp = { file: '...' }
|
|
118
|
+
if (isAbsolute(sp.file)) {
|
|
119
|
+
throw new Error(`agent.systemPrompt.file must be a relative path (got absolute: ${sp.file})`);
|
|
120
|
+
}
|
|
121
|
+
if (sp.file.split('/').includes('..')) {
|
|
122
|
+
throw new Error(`agent.systemPrompt.file must not traverse parent directories (got: ${sp.file})`);
|
|
123
|
+
}
|
|
124
|
+
const baseDir = dirname(guueyJsonPath);
|
|
125
|
+
const resolved = resolve(baseDir, sp.file);
|
|
126
|
+
if (!existsSync(resolved)) {
|
|
127
|
+
throw new Error(`agent.systemPrompt.file references missing file: ${sp.file} (resolved to ${resolved})`);
|
|
128
|
+
}
|
|
129
|
+
return readFileSync(resolved, 'utf-8');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Build the snapshot the deploy upload + pod boot consume.
|
|
133
|
+
*
|
|
134
|
+
* Replaces `agent.systemPrompt = { file }` with `agent.systemPrompt = <inlined>`
|
|
135
|
+
* so the snapshot is self-contained. Returns a deep-cloned document
|
|
136
|
+
* (caller mutations don't leak back).
|
|
137
|
+
*/
|
|
138
|
+
export function buildDeploySnapshot(loaded) {
|
|
139
|
+
const cloned = JSON.parse(JSON.stringify(loaded.doc));
|
|
140
|
+
if (loaded.resolvedSystemPrompt !== undefined) {
|
|
141
|
+
cloned.agent.systemPrompt = loaded.resolvedSystemPrompt;
|
|
142
|
+
}
|
|
143
|
+
return cloned;
|
|
144
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mcpProxies` — Guuey hosted overlay shape for managed MCP relays.
|
|
3
|
+
*
|
|
4
|
+
* Relocated 2026-04-21 from `@ggui-ai/protocol/types/mcp-proxy.ts` as
|
|
5
|
+
* part of the OSS split §8.2 classification fix. These types describe
|
|
6
|
+
* a GUUEY HOSTING CONCEPT (a managed proxy that relays MCP calls with
|
|
7
|
+
* upstream OAuth linking), not a vendor-neutral protocol shape, and
|
|
8
|
+
* therefore belong in the closed `@guuey/config`
|
|
9
|
+
* package alongside the rest of `guuey.json`.
|
|
10
|
+
*
|
|
11
|
+
* ## The classification decision
|
|
12
|
+
*
|
|
13
|
+
* `mcpProxies` is the declaration block a developer adds to
|
|
14
|
+
* `guuey.json` to tell Guuey hosting: *"on behalf of this project,
|
|
15
|
+
* relay these external MCP providers, using this OAuth linking
|
|
16
|
+
* config, exposing these discovered servers."* That is
|
|
17
|
+
* platform-layer plumbing — Guuey runs the relay, handles the
|
|
18
|
+
* credential storage, dispatches the discovery — and it does not
|
|
19
|
+
* describe anything an OSS-only `ggui` deployment emits or consumes.
|
|
20
|
+
*
|
|
21
|
+
* Per §8.2: the OSS `ggui` server does NOT read `guuey.json`.
|
|
22
|
+
* Consumers that need overlay values (the closed `guuey` CLI,
|
|
23
|
+
* Guuey-hosted Lambdas, the Guuey-internal control-plane UI) are
|
|
24
|
+
* the only call sites allowed to import from this package. Open
|
|
25
|
+
* packages that historically read `mcpProxies` (`@ggui-ai/server`'s
|
|
26
|
+
* Claude-passthrough feature) retain their feature code but inline
|
|
27
|
+
* the minimal structural shape they actually use — it stays a
|
|
28
|
+
* Guuey-platform plumbing path, not a protocol contract.
|
|
29
|
+
*
|
|
30
|
+
* ## Scope of this module
|
|
31
|
+
*
|
|
32
|
+
* - {@link McpProxyLinkingConfig} — upstream OAuth config for
|
|
33
|
+
* proxies that relay calls on behalf of an external account
|
|
34
|
+
* (e.g. Claude.ai). Keys surface in the Guuey control plane's
|
|
35
|
+
* credential-linking UI.
|
|
36
|
+
* - {@link McpProxyConfig} — a single proxy's discovery + proxy
|
|
37
|
+
* URL pattern + optional server filter + optional linking block.
|
|
38
|
+
* - {@link McpProxiesConfig} — the top-level record keyed by
|
|
39
|
+
* proxy id (`claude_ai`, `guuey`, future `omo`...). Exactly the
|
|
40
|
+
* shape `guuey.json#mcpProxies` carries.
|
|
41
|
+
*
|
|
42
|
+
* ## Vendor-neutral constants stay in `@ggui-ai/protocol`
|
|
43
|
+
*
|
|
44
|
+
* Claude.ai-specific constants and discovery-response wire types
|
|
45
|
+
* (`CLAUDE_AI_*`, `DiscoveredMcpServer`, `ClaudeAiDiscoveryResponse`)
|
|
46
|
+
* remain in `@ggui-ai/protocol/types/mcp-proxy.ts` — those describe
|
|
47
|
+
* Anthropic's public API, not Guuey-overlay config.
|
|
48
|
+
*
|
|
49
|
+
* ## Strictness
|
|
50
|
+
*
|
|
51
|
+
* Zod validation matches the rest of `guuey.json`: strict objects,
|
|
52
|
+
* non-empty strings, URL validation on linking endpoints. Unknown
|
|
53
|
+
* keys on nested objects fail parse (prevents silent drift toward
|
|
54
|
+
* a "what else can we stuff into guuey.json" shape).
|
|
55
|
+
*/
|
|
56
|
+
import { z } from 'zod';
|
|
57
|
+
/**
|
|
58
|
+
* OAuth linking config for proxies that relay on behalf of an
|
|
59
|
+
* external account. Omit for proxies where Guuey session auth is
|
|
60
|
+
* the only identity needed (e.g. a Guuey-native proxy).
|
|
61
|
+
*/
|
|
62
|
+
declare const McpProxyLinkingSchema: z.ZodObject<{
|
|
63
|
+
authUrl: z.ZodURL;
|
|
64
|
+
tokenUrl: z.ZodURL;
|
|
65
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
66
|
+
clientId: z.ZodOptional<z.ZodString>;
|
|
67
|
+
manualRedirectUrl: z.ZodOptional<z.ZodURL>;
|
|
68
|
+
}, z.core.$strict>;
|
|
69
|
+
/**
|
|
70
|
+
* Configuration for a single MCP proxy in `guuey.json#mcpProxies`.
|
|
71
|
+
*
|
|
72
|
+
* `discovery` + `proxy` are both URL-valued, but `proxy` is a URL
|
|
73
|
+
* PATTERN (contains `{server_id}` which is substituted at call
|
|
74
|
+
* time). Both are validated as URLs — `{server_id}` is accepted
|
|
75
|
+
* by URL parsers as opaque path segment.
|
|
76
|
+
*/
|
|
77
|
+
declare const McpProxyConfigSchema: z.ZodObject<{
|
|
78
|
+
discovery: z.ZodURL;
|
|
79
|
+
proxy: z.ZodURL;
|
|
80
|
+
linking: z.ZodOptional<z.ZodObject<{
|
|
81
|
+
authUrl: z.ZodURL;
|
|
82
|
+
tokenUrl: z.ZodURL;
|
|
83
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
84
|
+
clientId: z.ZodOptional<z.ZodString>;
|
|
85
|
+
manualRedirectUrl: z.ZodOptional<z.ZodURL>;
|
|
86
|
+
}, z.core.$strict>>;
|
|
87
|
+
servers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
88
|
+
}, z.core.$strict>;
|
|
89
|
+
/**
|
|
90
|
+
* The `mcpProxies` section of `guuey.json`. Keys are proxy
|
|
91
|
+
* identifiers (`claude_ai`, `guuey`, future `omo`, …).
|
|
92
|
+
*
|
|
93
|
+
* Record shape intentionally — new proxy ids are additive; a fixed
|
|
94
|
+
* literal union here would force a schema change every time a new
|
|
95
|
+
* hosted-relay integration lands.
|
|
96
|
+
*/
|
|
97
|
+
export declare const McpProxiesSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
98
|
+
discovery: z.ZodURL;
|
|
99
|
+
proxy: z.ZodURL;
|
|
100
|
+
linking: z.ZodOptional<z.ZodObject<{
|
|
101
|
+
authUrl: z.ZodURL;
|
|
102
|
+
tokenUrl: z.ZodURL;
|
|
103
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
104
|
+
clientId: z.ZodOptional<z.ZodString>;
|
|
105
|
+
manualRedirectUrl: z.ZodOptional<z.ZodURL>;
|
|
106
|
+
}, z.core.$strict>>;
|
|
107
|
+
servers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
108
|
+
}, z.core.$strict>>;
|
|
109
|
+
/** Linking block type derived from the zod schema. */
|
|
110
|
+
export type McpProxyLinkingConfig = z.infer<typeof McpProxyLinkingSchema>;
|
|
111
|
+
/** Single-proxy config type derived from the zod schema. */
|
|
112
|
+
export type McpProxyConfig = z.infer<typeof McpProxyConfigSchema>;
|
|
113
|
+
/** Full `mcpProxies` overlay type derived from the zod schema. */
|
|
114
|
+
export type McpProxiesConfig = z.infer<typeof McpProxiesSchema>;
|
|
115
|
+
/**
|
|
116
|
+
* Parse a raw JSON value into a validated {@link McpProxiesConfig}.
|
|
117
|
+
* Throws a `ZodError` on invalid input.
|
|
118
|
+
*/
|
|
119
|
+
export declare function parseMcpProxies(raw: unknown): McpProxiesConfig;
|
|
120
|
+
/** Safe-parse variant — see {@link parseMcpProxies}. */
|
|
121
|
+
export declare function safeParseMcpProxies(raw: unknown): ReturnType<typeof McpProxiesSchema.safeParse>;
|
|
122
|
+
export {};
|
|
123
|
+
//# sourceMappingURL=mcp-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-proxy.d.ts","sourceRoot":"","sources":["../src/mcp-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,QAAA,MAAM,qBAAqB;;;;;;kBAuBzB,CAAC;AAEH;;;;;;;GAOG;AACH,QAAA,MAAM,oBAAoB;;;;;;;;;;;kBAmBxB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;mBAG5B,CAAC;AAEF,sDAAsD;AACtD,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,4DAA4D;AAC5D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,kEAAkE;AAClE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAE9D;AAED,wDAAwD;AACxD,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAE/C"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mcpProxies` — Guuey hosted overlay shape for managed MCP relays.
|
|
3
|
+
*
|
|
4
|
+
* Relocated 2026-04-21 from `@ggui-ai/protocol/types/mcp-proxy.ts` as
|
|
5
|
+
* part of the OSS split §8.2 classification fix. These types describe
|
|
6
|
+
* a GUUEY HOSTING CONCEPT (a managed proxy that relays MCP calls with
|
|
7
|
+
* upstream OAuth linking), not a vendor-neutral protocol shape, and
|
|
8
|
+
* therefore belong in the closed `@guuey/config`
|
|
9
|
+
* package alongside the rest of `guuey.json`.
|
|
10
|
+
*
|
|
11
|
+
* ## The classification decision
|
|
12
|
+
*
|
|
13
|
+
* `mcpProxies` is the declaration block a developer adds to
|
|
14
|
+
* `guuey.json` to tell Guuey hosting: *"on behalf of this project,
|
|
15
|
+
* relay these external MCP providers, using this OAuth linking
|
|
16
|
+
* config, exposing these discovered servers."* That is
|
|
17
|
+
* platform-layer plumbing — Guuey runs the relay, handles the
|
|
18
|
+
* credential storage, dispatches the discovery — and it does not
|
|
19
|
+
* describe anything an OSS-only `ggui` deployment emits or consumes.
|
|
20
|
+
*
|
|
21
|
+
* Per §8.2: the OSS `ggui` server does NOT read `guuey.json`.
|
|
22
|
+
* Consumers that need overlay values (the closed `guuey` CLI,
|
|
23
|
+
* Guuey-hosted Lambdas, the Guuey-internal control-plane UI) are
|
|
24
|
+
* the only call sites allowed to import from this package. Open
|
|
25
|
+
* packages that historically read `mcpProxies` (`@ggui-ai/server`'s
|
|
26
|
+
* Claude-passthrough feature) retain their feature code but inline
|
|
27
|
+
* the minimal structural shape they actually use — it stays a
|
|
28
|
+
* Guuey-platform plumbing path, not a protocol contract.
|
|
29
|
+
*
|
|
30
|
+
* ## Scope of this module
|
|
31
|
+
*
|
|
32
|
+
* - {@link McpProxyLinkingConfig} — upstream OAuth config for
|
|
33
|
+
* proxies that relay calls on behalf of an external account
|
|
34
|
+
* (e.g. Claude.ai). Keys surface in the Guuey control plane's
|
|
35
|
+
* credential-linking UI.
|
|
36
|
+
* - {@link McpProxyConfig} — a single proxy's discovery + proxy
|
|
37
|
+
* URL pattern + optional server filter + optional linking block.
|
|
38
|
+
* - {@link McpProxiesConfig} — the top-level record keyed by
|
|
39
|
+
* proxy id (`claude_ai`, `guuey`, future `omo`...). Exactly the
|
|
40
|
+
* shape `guuey.json#mcpProxies` carries.
|
|
41
|
+
*
|
|
42
|
+
* ## Vendor-neutral constants stay in `@ggui-ai/protocol`
|
|
43
|
+
*
|
|
44
|
+
* Claude.ai-specific constants and discovery-response wire types
|
|
45
|
+
* (`CLAUDE_AI_*`, `DiscoveredMcpServer`, `ClaudeAiDiscoveryResponse`)
|
|
46
|
+
* remain in `@ggui-ai/protocol/types/mcp-proxy.ts` — those describe
|
|
47
|
+
* Anthropic's public API, not Guuey-overlay config.
|
|
48
|
+
*
|
|
49
|
+
* ## Strictness
|
|
50
|
+
*
|
|
51
|
+
* Zod validation matches the rest of `guuey.json`: strict objects,
|
|
52
|
+
* non-empty strings, URL validation on linking endpoints. Unknown
|
|
53
|
+
* keys on nested objects fail parse (prevents silent drift toward
|
|
54
|
+
* a "what else can we stuff into guuey.json" shape).
|
|
55
|
+
*/
|
|
56
|
+
import { z } from 'zod';
|
|
57
|
+
/**
|
|
58
|
+
* OAuth linking config for proxies that relay on behalf of an
|
|
59
|
+
* external account. Omit for proxies where Guuey session auth is
|
|
60
|
+
* the only identity needed (e.g. a Guuey-native proxy).
|
|
61
|
+
*/
|
|
62
|
+
const McpProxyLinkingSchema = z.strictObject({
|
|
63
|
+
/** OAuth authorize endpoint. */
|
|
64
|
+
authUrl: z.url(),
|
|
65
|
+
/** OAuth token endpoint. */
|
|
66
|
+
tokenUrl: z.url(),
|
|
67
|
+
/**
|
|
68
|
+
* OAuth scopes to request. Empty array means "use the upstream's
|
|
69
|
+
* default scope set"; it does NOT mean "no scopes at all."
|
|
70
|
+
*/
|
|
71
|
+
scopes: z.array(z.string().min(1)),
|
|
72
|
+
/**
|
|
73
|
+
* OAuth client_id to use. When omitted, the proxy uses a
|
|
74
|
+
* well-known public client_id (e.g. Claude Code's registered
|
|
75
|
+
* client for Claude.ai).
|
|
76
|
+
*/
|
|
77
|
+
clientId: z.string().min(1).optional(),
|
|
78
|
+
/**
|
|
79
|
+
* Manual redirect URL for environments without a localhost
|
|
80
|
+
* callback. The upstream AS redirects here and renders the
|
|
81
|
+
* authorization code for the user to copy-paste. Used by
|
|
82
|
+
* production web flows.
|
|
83
|
+
*/
|
|
84
|
+
manualRedirectUrl: z.url().optional(),
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* Configuration for a single MCP proxy in `guuey.json#mcpProxies`.
|
|
88
|
+
*
|
|
89
|
+
* `discovery` + `proxy` are both URL-valued, but `proxy` is a URL
|
|
90
|
+
* PATTERN (contains `{server_id}` which is substituted at call
|
|
91
|
+
* time). Both are validated as URLs — `{server_id}` is accepted
|
|
92
|
+
* by URL parsers as opaque path segment.
|
|
93
|
+
*/
|
|
94
|
+
const McpProxyConfigSchema = z.strictObject({
|
|
95
|
+
/** Discovery URL — fetches available MCP servers for this proxy. */
|
|
96
|
+
discovery: z.url(),
|
|
97
|
+
/**
|
|
98
|
+
* Proxy URL pattern — `{server_id}` is substituted with the
|
|
99
|
+
* discovered server id at relay time. Validated as URL; the
|
|
100
|
+
* placeholder survives URL parsing as an opaque path segment.
|
|
101
|
+
*/
|
|
102
|
+
proxy: z.url(),
|
|
103
|
+
/**
|
|
104
|
+
* OAuth linking config for upstream account linking. Omit for
|
|
105
|
+
* Guuey-native proxies where the session token is sufficient.
|
|
106
|
+
*/
|
|
107
|
+
linking: McpProxyLinkingSchema.optional(),
|
|
108
|
+
/**
|
|
109
|
+
* Filter which discovered servers to expose, matched by display
|
|
110
|
+
* name. When omitted, all discovered servers are exposed.
|
|
111
|
+
*/
|
|
112
|
+
servers: z.array(z.string().min(1)).optional(),
|
|
113
|
+
});
|
|
114
|
+
/**
|
|
115
|
+
* The `mcpProxies` section of `guuey.json`. Keys are proxy
|
|
116
|
+
* identifiers (`claude_ai`, `guuey`, future `omo`, …).
|
|
117
|
+
*
|
|
118
|
+
* Record shape intentionally — new proxy ids are additive; a fixed
|
|
119
|
+
* literal union here would force a schema change every time a new
|
|
120
|
+
* hosted-relay integration lands.
|
|
121
|
+
*/
|
|
122
|
+
export const McpProxiesSchema = z.record(z.string().min(1), McpProxyConfigSchema);
|
|
123
|
+
/**
|
|
124
|
+
* Parse a raw JSON value into a validated {@link McpProxiesConfig}.
|
|
125
|
+
* Throws a `ZodError` on invalid input.
|
|
126
|
+
*/
|
|
127
|
+
export function parseMcpProxies(raw) {
|
|
128
|
+
return McpProxiesSchema.parse(raw);
|
|
129
|
+
}
|
|
130
|
+
/** Safe-parse variant — see {@link parseMcpProxies}. */
|
|
131
|
+
export function safeParseMcpProxies(raw) {
|
|
132
|
+
return McpProxiesSchema.safeParse(raw);
|
|
133
|
+
}
|