@omercnet/paseo-omp 0.2.1

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +21 -0
  3. package/README.md +110 -0
  4. package/SUPPORT.md +40 -0
  5. package/TESTING.md +147 -0
  6. package/client/hub-icon.tsx +12 -0
  7. package/client/hub-popover.tsx +132 -0
  8. package/client/hub-status.ts +29 -0
  9. package/client/memory-panel.tsx +71 -0
  10. package/client/memory-popover.tsx +70 -0
  11. package/client/omp-config-surface.tsx +1274 -0
  12. package/client/omp-doc-links.ts +117 -0
  13. package/client/omp-plugin-manager.tsx +833 -0
  14. package/client/provider-diagnostics-state.ts +250 -0
  15. package/client/provider-icon.tsx +27 -0
  16. package/client/provider-image.tsx +66 -0
  17. package/client/quota-popover.tsx +150 -0
  18. package/client/quota-state.ts +131 -0
  19. package/client/sessions-popover.tsx +73 -0
  20. package/docs/alpha-release-checklist.md +70 -0
  21. package/docs/configuration.md +122 -0
  22. package/docs/core-provider-issue-audit.md +108 -0
  23. package/docs/installation.md +73 -0
  24. package/index.client.tsx +272 -0
  25. package/index.server.ts +51 -0
  26. package/package.json +84 -0
  27. package/paseo-plugin.json +5 -0
  28. package/server/hub.ts +145 -0
  29. package/server/memory.ts +86 -0
  30. package/server/mutation-queue.ts +12 -0
  31. package/server/omp-config.ts +126 -0
  32. package/server/omp-plugins.ts +627 -0
  33. package/server/omp-settings.ts +291 -0
  34. package/server/paths.ts +64 -0
  35. package/server/provider/catalog.ts +173 -0
  36. package/server/provider/config-normalization.ts +148 -0
  37. package/server/provider/connection.ts +992 -0
  38. package/server/provider/host-tools.ts +706 -0
  39. package/server/provider/image.ts +143 -0
  40. package/server/provider/mcp-transport.ts +394 -0
  41. package/server/provider/omp-rpc.ts +2739 -0
  42. package/server/provider/omp.svg +5 -0
  43. package/server/provider/provider-options.ts +27 -0
  44. package/server/provider/registration.ts +151 -0
  45. package/server/provider/security.ts +317 -0
  46. package/server/provider/session-descriptors.ts +431 -0
  47. package/server/provider/session.ts +4451 -0
  48. package/server/provider/settings.ts +78 -0
  49. package/server/provider/subsessions.ts +847 -0
  50. package/server/provider/timeline-projector.ts +1764 -0
  51. package/server/provider-diagnostics.ts +1057 -0
  52. package/server/quota.ts +54 -0
  53. package/server/sessions.ts +58 -0
  54. package/shared/hub.ts +43 -0
  55. package/shared/memory.ts +23 -0
  56. package/shared/omp-config.ts +81 -0
  57. package/shared/omp-plugins.ts +223 -0
  58. package/shared/omp-settings.ts +207 -0
  59. package/shared/provider-diagnostics.ts +117 -0
  60. package/shared/provider-image.ts +160 -0
  61. package/shared/quota.ts +22 -0
  62. package/shared/sessions.ts +23 -0
  63. package/tsconfig.json +16 -0
@@ -0,0 +1,126 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import type { RpcInput } from "@getpaseo/plugin";
4
+ import { parse as parseYaml } from "yaml";
5
+ import type { ZodType } from "zod";
6
+ import {
7
+ type listOmpConfig,
8
+ type OmpConfig,
9
+ OmpConfigSchema,
10
+ OmpDevSectionSchema,
11
+ OmpGithubSectionSchema,
12
+ OmpMemorySectionSchema,
13
+ OmpModelRolesSchema,
14
+ OmpRetrySectionSchema,
15
+ OmpThemeSectionSchema,
16
+ } from "../shared/omp-config";
17
+ import { ompAgentDir } from "./paths";
18
+
19
+ /**
20
+ * omp writes its global settings to `~/.omp/agent/config.yml`, falling back to legacy
21
+ * `config.yaml` (mirrors omp's `MAIN_CONFIG_FILENAMES`, canonical filename first). This is an
22
+ * internal, unversioned file: reading it here is best-effort and degrades to "unavailable"
23
+ * instead of throwing when the file is missing, unreadable, or not a YAML mapping.
24
+ */
25
+ const CONFIG_FILENAMES = ["config.yml", "config.yaml"] as const;
26
+
27
+ type OmpConfigResult = { path: string; available: boolean; config: OmpConfig | null };
28
+
29
+ async function readFirstExisting(dir: string): Promise<{ path: string; text: string } | undefined> {
30
+ for (const filename of CONFIG_FILENAMES) {
31
+ const path = join(dir, filename);
32
+ try {
33
+ return { path, text: await readFile(path, "utf8") };
34
+ } catch {
35
+ // Try the next candidate filename.
36
+ }
37
+ }
38
+ return undefined;
39
+ }
40
+
41
+ /** Validates one top-level section independently so an unrelated malformed field never hides the rest. */
42
+ function section<Schema extends ZodType>(
43
+ schema: Schema,
44
+ value: unknown,
45
+ ): Schema["_output"] | undefined {
46
+ if (value === undefined) return undefined;
47
+ const result = schema.safeParse(value);
48
+ return result.success ? result.data : undefined;
49
+ }
50
+
51
+ /**
52
+ * Maps a parsed YAML document onto the safe allowlist in `shared/omp-config.ts`. Every field is
53
+ * read explicitly by name; nothing on the source object is spread, stringified, or forwarded
54
+ * unchecked, so an unrecognized or credential-shaped key never reaches the caller.
55
+ */
56
+ export function parseOmpConfig(raw: unknown): OmpConfig {
57
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return {};
58
+ const record = raw as Record<string, unknown>;
59
+ const config: OmpConfig = {};
60
+
61
+ const setupVersion = section(OmpConfigSchema.shape.setupVersion, record.setupVersion);
62
+ if (setupVersion !== undefined) config.setupVersion = setupVersion;
63
+
64
+ const symbolPreset = section(OmpConfigSchema.shape.symbolPreset, record.symbolPreset);
65
+ if (symbolPreset !== undefined) config.symbolPreset = symbolPreset;
66
+
67
+ const defaultThinkingLevel = section(
68
+ OmpConfigSchema.shape.defaultThinkingLevel,
69
+ record.defaultThinkingLevel,
70
+ );
71
+ if (defaultThinkingLevel !== undefined) config.defaultThinkingLevel = defaultThinkingLevel;
72
+
73
+ const theme = section(OmpThemeSectionSchema, record.theme);
74
+ if (theme !== undefined) config.theme = theme;
75
+
76
+ const memory = section(OmpMemorySectionSchema, record.memory);
77
+ if (memory !== undefined) config.memory = memory;
78
+
79
+ const github = section(OmpGithubSectionSchema, record.github);
80
+ if (github !== undefined) config.github = github;
81
+
82
+ const disabledProviders = section(
83
+ OmpConfigSchema.shape.disabledProviders,
84
+ record.disabledProviders,
85
+ );
86
+ if (disabledProviders !== undefined) config.disabledProviders = disabledProviders;
87
+
88
+ const modelProviderOrder = section(
89
+ OmpConfigSchema.shape.modelProviderOrder,
90
+ record.modelProviderOrder,
91
+ );
92
+ if (modelProviderOrder !== undefined) config.modelProviderOrder = modelProviderOrder;
93
+
94
+ const modelRoles = section(OmpModelRolesSchema, record.modelRoles);
95
+ if (modelRoles !== undefined) config.modelRoles = modelRoles;
96
+
97
+ const enabledModels = section(OmpConfigSchema.shape.enabledModels, record.enabledModels);
98
+ if (enabledModels !== undefined) config.enabledModels = enabledModels;
99
+
100
+ const retry = section(OmpRetrySectionSchema, record.retry);
101
+ if (retry !== undefined) config.retry = retry;
102
+
103
+ const dev = section(OmpDevSectionSchema, record.dev);
104
+ if (dev !== undefined) config.dev = dev;
105
+
106
+ return config;
107
+ }
108
+
109
+ export async function readOmpConfigFrom(dir: string): Promise<OmpConfigResult> {
110
+ const defaultPath = join(dir, CONFIG_FILENAMES[0]);
111
+ const found = await readFirstExisting(dir);
112
+ if (!found) return { path: defaultPath, available: false, config: null };
113
+ try {
114
+ const raw: unknown = parseYaml(found.text);
115
+ return { path: found.path, available: true, config: parseOmpConfig(raw) };
116
+ } catch {
117
+ // Malformed YAML: never log the raw text, degrade to a clear unavailable result.
118
+ return { path: found.path, available: false, config: null };
119
+ }
120
+ }
121
+
122
+ export async function resolveListOmpConfig(
123
+ _input: RpcInput<typeof listOmpConfig>,
124
+ ): Promise<OmpConfigResult> {
125
+ return readOmpConfigFrom(ompAgentDir());
126
+ }