forge-openclaw-plugin 0.2.25 → 0.2.26
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/assets/{board-VmF4FAfr.js → board-ta0rUHOf.js} +3 -3
- package/dist/assets/{board-VmF4FAfr.js.map → board-ta0rUHOf.js.map} +1 -1
- package/dist/assets/index-Ro0ZF_az.css +1 -0
- package/dist/assets/index-ytlpSj23.js +79 -0
- package/dist/assets/index-ytlpSj23.js.map +1 -0
- package/dist/assets/{motion-DvkU14p-.js → motion-fBKPB6yw.js} +2 -2
- package/dist/assets/{motion-DvkU14p-.js.map → motion-fBKPB6yw.js.map} +1 -1
- package/dist/assets/{table-DgiPof9E.js → table-C-IGTQni.js} +2 -2
- package/dist/assets/{table-DgiPof9E.js.map → table-C-IGTQni.js.map} +1 -1
- package/dist/assets/{ui-nYfoC0Gq.js → ui-DInOpaYF.js} +2 -2
- package/dist/assets/{ui-nYfoC0Gq.js.map → ui-DInOpaYF.js.map} +1 -1
- package/dist/assets/vendor-lE3tZJcC.js +876 -0
- package/dist/assets/vendor-lE3tZJcC.js.map +1 -0
- package/dist/index.html +7 -8
- package/dist/openclaw/local-runtime.d.ts +3 -1
- package/dist/openclaw/local-runtime.js +51 -15
- package/dist/openclaw/plugin-entry-shared.js +24 -2
- package/dist/openclaw/plugin-sdk-types.d.ts +17 -0
- package/dist/openclaw/tools.js +0 -3
- package/dist/server/server/migrations/001_core.sql +411 -0
- package/dist/server/server/migrations/002_psyche.sql +392 -0
- package/dist/server/server/migrations/003_habits.sql +30 -0
- package/dist/server/server/migrations/004_habit_links.sql +8 -0
- package/dist/server/server/migrations/005_habit_psyche_links.sql +24 -0
- package/dist/server/server/migrations/006_work_adjustments.sql +14 -0
- package/dist/server/server/migrations/007_weekly_review_closures.sql +17 -0
- package/dist/server/server/migrations/008_calendar_execution.sql +147 -0
- package/dist/server/server/migrations/009_true_calendar_events.sql +195 -0
- package/dist/server/server/migrations/010_calendar_selection_state.sql +6 -0
- package/dist/server/server/migrations/011_calendar_timezone_backfill.sql +11 -0
- package/dist/server/server/migrations/012_work_block_ranges.sql +7 -0
- package/dist/server/server/migrations/013_microsoft_local_auth_settings.sql +8 -0
- package/dist/server/server/migrations/014_note_tags_and_ephemeral.sql +8 -0
- package/dist/server/server/migrations/015_multi_user_and_strategies.sql +244 -0
- package/dist/server/server/migrations/016_health_companion.sql +158 -0
- package/dist/server/server/migrations/016_strategy_contracts_and_user_graph.sql +22 -0
- package/dist/server/server/migrations/017_preferences.sql +131 -0
- package/dist/server/server/migrations/018_preference_catalogs.sql +31 -0
- package/dist/server/server/migrations/019_wiki_memory.sql +255 -0
- package/dist/server/server/migrations/020_wiki_page_hierarchy.sql +11 -0
- package/dist/server/server/migrations/021_hide_evidence_from_wiki_index.sql +3 -0
- package/dist/server/server/migrations/022_wiki_ingest_background.sql +85 -0
- package/dist/server/server/migrations/023_diagnostic_logs.sql +28 -0
- package/dist/server/server/migrations/024_questionnaires.sql +96 -0
- package/dist/server/server/migrations/025_ai_model_connections.sql +26 -0
- package/dist/server/server/migrations/026_custom_theme_settings.sql +2 -0
- package/dist/server/server/migrations/027_ai_processors.sql +31 -0
- package/dist/server/server/migrations/028_movement_domain.sql +136 -0
- package/dist/server/server/migrations/029_watch_micro_capture.sql +23 -0
- package/dist/server/server/migrations/030_surface_layouts.sql +5 -0
- package/dist/server/server/migrations/031_ai_processor_runtime_upgrades.sql +10 -0
- package/dist/server/server/migrations/032_ai_connectors.sql +44 -0
- package/dist/server/server/migrations/033_movement_trip_point_sync.sql +36 -0
- package/dist/server/server/migrations/034_movement_segment_sync.sql +49 -0
- package/dist/server/server/migrations/035_google_local_auth_settings.sql +2 -0
- package/dist/server/server/migrations/036_google_local_auth_client_secret.sql +2 -0
- package/dist/server/{app.js → server/src/app.js} +242 -111
- package/dist/server/server/src/connectors/box-registry.js +188 -0
- package/dist/server/{db.js → server/src/db.js} +4 -0
- package/dist/server/server/src/debug.js +19 -0
- package/dist/server/{openapi.js → server/src/openapi.js} +2 -2
- package/dist/server/{repositories → server/src/repositories}/ai-connectors.js +286 -23
- package/dist/server/{repositories → server/src/repositories}/calendar.js +1 -1
- package/dist/server/{repositories → server/src/repositories}/settings.js +51 -3
- package/dist/server/{services → server/src/services}/calendar-runtime.js +775 -58
- package/dist/server/server/src/services/google-calendar-oauth-config.js +176 -0
- package/dist/server/{types.js → server/src/types.js} +137 -19
- package/dist/server/{web.js → server/src/web.js} +21 -2
- package/dist/server/src/components/customization/utility-widgets.js +330 -0
- package/dist/server/src/components/workbench-boxes/health/health-boxes.js +92 -0
- package/dist/server/src/components/workbench-boxes/kanban/kanban-boxes.js +128 -0
- package/dist/server/src/components/workbench-boxes/movement/movement-boxes.js +37 -0
- package/dist/server/src/components/workbench-boxes/notes/notes-boxes.js +114 -0
- package/dist/server/src/components/workbench-boxes/projects/projects-boxes.js +57 -0
- package/dist/server/src/components/workbench-boxes/shared/define-workbench-box.js +4 -0
- package/dist/server/src/components/workbench-boxes/shared/generic-node-view.js +13 -0
- package/dist/server/src/components/workbench-boxes/today/today-boxes.js +63 -0
- package/dist/server/src/lib/api-error.js +37 -0
- package/dist/server/src/lib/api.js +1859 -0
- package/dist/server/src/lib/calendar-name-deduper.js +144 -0
- package/dist/server/src/lib/diagnostics.js +67 -0
- package/dist/server/src/lib/psyche-types.js +1 -0
- package/dist/server/src/lib/questionnaire-types.js +1 -0
- package/dist/server/src/lib/runtime-paths.js +24 -0
- package/dist/server/src/lib/schemas.js +234 -0
- package/dist/server/src/lib/snapshot-normalizer.js +374 -0
- package/dist/server/src/lib/theme-system.js +319 -0
- package/dist/server/src/lib/types.js +1 -0
- package/dist/server/src/lib/utils.js +22 -0
- package/dist/server/src/lib/workbench/boxes.js +16 -0
- package/dist/server/src/lib/workbench/nodes.js +15 -0
- package/dist/server/src/lib/workbench/registry.js +73 -0
- package/dist/server/src/lib/workbench/runtime.js +181 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server/index.js +68 -0
- package/server/migrations/035_google_local_auth_settings.sql +2 -0
- package/server/migrations/036_google_local_auth_client_secret.sql +2 -0
- package/skills/forge-openclaw/SKILL.md +3 -0
- package/skills/forge-openclaw/entity_conversation_playbooks.md +213 -24
- package/skills/forge-openclaw/psyche_entity_playbooks.md +82 -3
- package/dist/assets/index-CFCKDIMH.js +0 -67
- package/dist/assets/index-CFCKDIMH.js.map +0 -1
- package/dist/assets/index-ZPY6U1TU.css +0 -1
- package/dist/assets/vendor-D9PTEPSB.js +0 -824
- package/dist/assets/vendor-D9PTEPSB.js.map +0 -1
- package/dist/assets/viz-Cqb6s--o.js +0 -34
- package/dist/assets/viz-Cqb6s--o.js.map +0 -1
- package/dist/server/connectors/box-registry.js +0 -257
- /package/dist/server/{demo-data.js → server/src/demo-data.js} +0 -0
- /package/dist/server/{discovery-advertiser.js → server/src/discovery-advertiser.js} +0 -0
- /package/dist/server/{e2e-server.js → server/src/e2e-server.js} +0 -0
- /package/dist/server/{errors.js → server/src/errors.js} +0 -0
- /package/dist/server/{health.js → server/src/health.js} +0 -0
- /package/dist/server/{index.js → server/src/index.js} +0 -0
- /package/dist/server/{managers → server/src/managers}/base.js +0 -0
- /package/dist/server/{managers → server/src/managers}/contracts.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/api-gateway-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/audit-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/authentication-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/authorization-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/background-job-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/configuration-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/database-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/event-bus-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/external-service-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/health-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/llm-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/migration-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/openai-responses-provider.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/search-index-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/secrets-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/session-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/storage-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/token-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/transaction-manager.js +0 -0
- /package/dist/server/{managers → server/src/managers}/platform/trusted-network.js +0 -0
- /package/dist/server/{managers → server/src/managers}/runtime.js +0 -0
- /package/dist/server/{managers → server/src/managers}/type-guards.js +0 -0
- /package/dist/server/{movement.js → server/src/movement.js} +0 -0
- /package/dist/server/{preferences-seeds.js → server/src/preferences-seeds.js} +0 -0
- /package/dist/server/{preferences-types.js → server/src/preferences-types.js} +0 -0
- /package/dist/server/{psyche-types.js → server/src/psyche-types.js} +0 -0
- /package/dist/server/{questionnaire-flow.js → server/src/questionnaire-flow.js} +0 -0
- /package/dist/server/{questionnaire-seeds.js → server/src/questionnaire-seeds.js} +0 -0
- /package/dist/server/{questionnaire-types.js → server/src/questionnaire-types.js} +0 -0
- /package/dist/server/{repositories → server/src/repositories}/activity-events.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/ai-processors.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/collaboration.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/deleted-entities.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/diagnostic-logs.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/domains.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/entity-ownership.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/event-log.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/goals.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/habits.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/model-settings.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/notes.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/preferences.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/projects.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/psyche.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/questionnaires.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/rewards.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/strategies.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/surface-layouts.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/tags.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/task-runs.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/tasks.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/users.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/weekly-reviews.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/wiki-memory.js +0 -0
- /package/dist/server/{repositories → server/src/repositories}/work-adjustments.js +0 -0
- /package/dist/server/{seed-demo.js → server/src/seed-demo.js} +0 -0
- /package/dist/server/{services → server/src/services}/context.js +0 -0
- /package/dist/server/{services → server/src/services}/dashboard.js +0 -0
- /package/dist/server/{services → server/src/services}/entity-crud.js +0 -0
- /package/dist/server/{services → server/src/services}/gamification.js +0 -0
- /package/dist/server/{services → server/src/services}/insights.js +0 -0
- /package/dist/server/{services → server/src/services}/openai-codex-oauth.js +0 -0
- /package/dist/server/{services → server/src/services}/projects.js +0 -0
- /package/dist/server/{services → server/src/services}/psyche-observation-calendar.js +0 -0
- /package/dist/server/{services → server/src/services}/psyche.js +0 -0
- /package/dist/server/{services → server/src/services}/relations.js +0 -0
- /package/dist/server/{services → server/src/services}/reviews.js +0 -0
- /package/dist/server/{services → server/src/services}/run-recovery.js +0 -0
- /package/dist/server/{services → server/src/services}/tagging.js +0 -0
- /package/dist/server/{services → server/src/services}/task-run-watchdog.js +0 -0
- /package/dist/server/{services → server/src/services}/work-time.js +0 -0
- /package/dist/server/{watch-mobile.js → server/src/watch-mobile.js} +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { createDecipheriv, createHash } from "node:crypto";
|
|
2
|
+
const GOOGLE_CALLBACK_PATH = "/api/v1/calendar/oauth/google/callback";
|
|
3
|
+
const DEFAULT_APP_PORT = "4317";
|
|
4
|
+
const DEFAULT_APP_BASE_URL = `http://127.0.0.1:${DEFAULT_APP_PORT}`;
|
|
5
|
+
const PACKAGED_DEFAULT_GOOGLE_CREDENTIAL_KEY_MATERIAL = [
|
|
6
|
+
"forge",
|
|
7
|
+
"desktop",
|
|
8
|
+
"oauth",
|
|
9
|
+
"default",
|
|
10
|
+
"google",
|
|
11
|
+
"bundle",
|
|
12
|
+
"2026",
|
|
13
|
+
"local"
|
|
14
|
+
];
|
|
15
|
+
const PACKAGED_DEFAULT_GOOGLE_CLIENT_ID_ENCRYPTED = {
|
|
16
|
+
iv: "2fc1a6723312a10b7d176f13",
|
|
17
|
+
data: "9fbdf9dfcd1cc8674fa46150dd0f4678df8ce1ba52cdf0ceb4d4a76c9c5df01b3d8a21f194201c827524a6e06b0d4a55c7002edb3fa20b76b67f540e46ba28f506a73edaf6559a1d",
|
|
18
|
+
tag: "1965dfe1213ecd888e46ea59241d03a9"
|
|
19
|
+
};
|
|
20
|
+
const PACKAGED_DEFAULT_GOOGLE_CLIENT_SECRET_ENCRYPTED = {
|
|
21
|
+
iv: "5a6ca66625e0ff5559b34f99",
|
|
22
|
+
data: "b80dec231f029d92a13426ad3f0b851e20a5b35ec6691e517744fd65349144e75005f1",
|
|
23
|
+
tag: "9d2cfd8a153d91f60d8c628bbe1c2f25"
|
|
24
|
+
};
|
|
25
|
+
const DEFAULT_DEV_WEB_ORIGINS = [
|
|
26
|
+
"http://127.0.0.1:3027",
|
|
27
|
+
"http://localhost:3027"
|
|
28
|
+
];
|
|
29
|
+
function decryptPackagedGoogleOauthValue(payload) {
|
|
30
|
+
const key = createHash("sha256")
|
|
31
|
+
.update(PACKAGED_DEFAULT_GOOGLE_CREDENTIAL_KEY_MATERIAL.join(":"))
|
|
32
|
+
.digest();
|
|
33
|
+
const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(payload.iv, "hex"));
|
|
34
|
+
decipher.setAuthTag(Buffer.from(payload.tag, "hex"));
|
|
35
|
+
const decrypted = Buffer.concat([
|
|
36
|
+
decipher.update(Buffer.from(payload.data, "hex")),
|
|
37
|
+
decipher.final()
|
|
38
|
+
]);
|
|
39
|
+
return decrypted.toString("utf8");
|
|
40
|
+
}
|
|
41
|
+
const PACKAGED_DEFAULT_GOOGLE_CLIENT_ID = decryptPackagedGoogleOauthValue(PACKAGED_DEFAULT_GOOGLE_CLIENT_ID_ENCRYPTED);
|
|
42
|
+
const PACKAGED_DEFAULT_GOOGLE_CLIENT_SECRET = decryptPackagedGoogleOauthValue(PACKAGED_DEFAULT_GOOGLE_CLIENT_SECRET_ENCRYPTED);
|
|
43
|
+
function runtimeOriginFromEnv(env) {
|
|
44
|
+
const port = env.PORT?.trim() || DEFAULT_APP_PORT;
|
|
45
|
+
return `http://127.0.0.1:${port}`;
|
|
46
|
+
}
|
|
47
|
+
function normalizeOrigin(value, fieldLabel) {
|
|
48
|
+
let url;
|
|
49
|
+
try {
|
|
50
|
+
url = new URL(value);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
throw new Error(`${fieldLabel} must be a full URL.`);
|
|
54
|
+
}
|
|
55
|
+
if (url.protocol !== "http:") {
|
|
56
|
+
throw new Error(`${fieldLabel} must use http in local Forge mode.`);
|
|
57
|
+
}
|
|
58
|
+
if (url.pathname !== "/" && url.pathname !== "") {
|
|
59
|
+
throw new Error(`${fieldLabel} must not include a path.`);
|
|
60
|
+
}
|
|
61
|
+
return url.origin;
|
|
62
|
+
}
|
|
63
|
+
function isLoopbackHostname(hostname) {
|
|
64
|
+
return hostname === "127.0.0.1" || hostname === "localhost";
|
|
65
|
+
}
|
|
66
|
+
function normalizeLoopbackOrigin(value, fieldLabel) {
|
|
67
|
+
const origin = normalizeOrigin(value, fieldLabel);
|
|
68
|
+
const url = new URL(origin);
|
|
69
|
+
if (!isLoopbackHostname(url.hostname)) {
|
|
70
|
+
throw new Error(`${fieldLabel} must use localhost or 127.0.0.1 in local Forge mode.`);
|
|
71
|
+
}
|
|
72
|
+
return origin;
|
|
73
|
+
}
|
|
74
|
+
function normalizeRedirectUri(value, appBaseUrl) {
|
|
75
|
+
let url;
|
|
76
|
+
try {
|
|
77
|
+
url = new URL(value);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
throw new Error("GOOGLE_REDIRECT_URI must be a full URL.");
|
|
81
|
+
}
|
|
82
|
+
if (url.protocol !== "http:") {
|
|
83
|
+
throw new Error("GOOGLE_REDIRECT_URI must use http in local Forge mode.");
|
|
84
|
+
}
|
|
85
|
+
if (!isLoopbackHostname(url.hostname)) {
|
|
86
|
+
throw new Error("GOOGLE_REDIRECT_URI must use localhost or 127.0.0.1 in local Forge mode.");
|
|
87
|
+
}
|
|
88
|
+
if (url.pathname !== GOOGLE_CALLBACK_PATH) {
|
|
89
|
+
throw new Error(`GOOGLE_REDIRECT_URI must end with ${GOOGLE_CALLBACK_PATH}.`);
|
|
90
|
+
}
|
|
91
|
+
if (url.origin !== appBaseUrl) {
|
|
92
|
+
throw new Error(`GOOGLE_REDIRECT_URI must use the same origin as APP_BASE_URL (${appBaseUrl}).`);
|
|
93
|
+
}
|
|
94
|
+
return url.toString();
|
|
95
|
+
}
|
|
96
|
+
function normalizeAllowedOrigins(value, appBaseUrl) {
|
|
97
|
+
const rawValues = value && value.trim().length > 0
|
|
98
|
+
? value
|
|
99
|
+
.split(",")
|
|
100
|
+
.map((entry) => entry.trim())
|
|
101
|
+
.filter((entry) => entry.length > 0)
|
|
102
|
+
: [appBaseUrl, ...DEFAULT_DEV_WEB_ORIGINS];
|
|
103
|
+
const normalized = rawValues.map((entry) => normalizeLoopbackOrigin(entry, "GOOGLE_ALLOWED_ORIGINS"));
|
|
104
|
+
return Array.from(new Set(normalized));
|
|
105
|
+
}
|
|
106
|
+
export function getGoogleCalendarOauthCallbackPath() {
|
|
107
|
+
return GOOGLE_CALLBACK_PATH;
|
|
108
|
+
}
|
|
109
|
+
export function resolveGoogleCalendarOauthPublicConfig(env = process.env, overrides) {
|
|
110
|
+
const runtimeOrigin = runtimeOriginFromEnv(env);
|
|
111
|
+
const appBaseUrl = normalizeLoopbackOrigin(env.APP_BASE_URL?.trim() ||
|
|
112
|
+
env.APP_URL?.trim() ||
|
|
113
|
+
DEFAULT_APP_BASE_URL, env.APP_BASE_URL?.trim() ? "APP_BASE_URL" : "APP_URL");
|
|
114
|
+
const redirectUri = normalizeRedirectUri(env.GOOGLE_REDIRECT_URI?.trim() || `${appBaseUrl}${GOOGLE_CALLBACK_PATH}`, appBaseUrl);
|
|
115
|
+
const allowedOrigins = normalizeAllowedOrigins(env.GOOGLE_ALLOWED_ORIGINS, appBaseUrl);
|
|
116
|
+
const storedClientId = overrides?.clientId?.trim() || "";
|
|
117
|
+
const storedClientSecret = overrides?.clientSecret?.trim() || "";
|
|
118
|
+
const envClientId = env.GOOGLE_CLIENT_ID?.trim() || "";
|
|
119
|
+
const envClientSecret = env.GOOGLE_CLIENT_SECRET?.trim() || "";
|
|
120
|
+
const hasStoredOverride = storedClientId.length > 0 || storedClientSecret.length > 0;
|
|
121
|
+
const hasEnvOverride = envClientId.length > 0 || envClientSecret.length > 0;
|
|
122
|
+
const clientId = hasStoredOverride
|
|
123
|
+
? storedClientId
|
|
124
|
+
: hasEnvOverride
|
|
125
|
+
? envClientId
|
|
126
|
+
: PACKAGED_DEFAULT_GOOGLE_CLIENT_ID.trim();
|
|
127
|
+
const clientSecret = hasStoredOverride
|
|
128
|
+
? storedClientSecret
|
|
129
|
+
: hasEnvOverride
|
|
130
|
+
? envClientSecret
|
|
131
|
+
: PACKAGED_DEFAULT_GOOGLE_CLIENT_SECRET.trim();
|
|
132
|
+
const isConfigured = clientId.length > 0;
|
|
133
|
+
const hasIncompleteStoredOverride = storedClientId.length > 0 !== storedClientSecret.length > 0;
|
|
134
|
+
const setupMessage = hasIncompleteStoredOverride
|
|
135
|
+
? "Google OAuth override is incomplete for this Forge install. Save both the client ID and client secret together, or clear both fields to use the packaged default."
|
|
136
|
+
: isConfigured
|
|
137
|
+
? "Google Calendar sign-in is configured for local Forge. Open Forge on localhost or 127.0.0.1 on the same machine that is running Forge, because Google will redirect back to the local callback on that machine."
|
|
138
|
+
: "Google client ID is not set for this Forge install.";
|
|
139
|
+
return {
|
|
140
|
+
clientId,
|
|
141
|
+
clientSecret,
|
|
142
|
+
storedClientId,
|
|
143
|
+
storedClientSecret,
|
|
144
|
+
appBaseUrl,
|
|
145
|
+
redirectUri,
|
|
146
|
+
allowedOrigins,
|
|
147
|
+
usesPkce: true,
|
|
148
|
+
requiresServerClientSecret: false,
|
|
149
|
+
oauthClientType: "desktop_app",
|
|
150
|
+
authMode: "localhost_pkce",
|
|
151
|
+
isConfigured,
|
|
152
|
+
isReadyForPairing: isConfigured && !hasIncompleteStoredOverride,
|
|
153
|
+
isLocalOnly: true,
|
|
154
|
+
runtimeOrigin,
|
|
155
|
+
setupMessage
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
export function resolveGoogleCalendarOauthPrivateConfig(env = process.env, overrides) {
|
|
159
|
+
return resolveGoogleCalendarOauthPublicConfig(env, overrides);
|
|
160
|
+
}
|
|
161
|
+
export function isGoogleCalendarOriginAllowed(origin, allowedOrigins) {
|
|
162
|
+
try {
|
|
163
|
+
return allowedOrigins.includes(new URL(origin).origin);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export function isGoogleCalendarLoopbackOrigin(origin) {
|
|
170
|
+
try {
|
|
171
|
+
return isLoopbackHostname(new URL(origin).hostname);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -1220,6 +1220,9 @@ export const themePreferenceSchema = z.enum([
|
|
|
1220
1220
|
"solar",
|
|
1221
1221
|
"aurora",
|
|
1222
1222
|
"ember",
|
|
1223
|
+
"paper",
|
|
1224
|
+
"dawn",
|
|
1225
|
+
"atelier",
|
|
1223
1226
|
"custom",
|
|
1224
1227
|
"system"
|
|
1225
1228
|
]);
|
|
@@ -1249,6 +1252,24 @@ export const microsoftCalendarAuthSettingsSchema = z.object({
|
|
|
1249
1252
|
isReadyForSignIn: z.boolean(),
|
|
1250
1253
|
setupMessage: z.string()
|
|
1251
1254
|
});
|
|
1255
|
+
export const googleCalendarAuthSettingsSchema = z.object({
|
|
1256
|
+
clientId: z.string(),
|
|
1257
|
+
clientSecret: z.string(),
|
|
1258
|
+
storedClientId: z.string(),
|
|
1259
|
+
storedClientSecret: z.string(),
|
|
1260
|
+
appBaseUrl: z.string(),
|
|
1261
|
+
redirectUri: z.string(),
|
|
1262
|
+
allowedOrigins: z.array(z.string()),
|
|
1263
|
+
usesPkce: z.literal(true),
|
|
1264
|
+
requiresServerClientSecret: z.literal(false),
|
|
1265
|
+
oauthClientType: z.literal("desktop_app"),
|
|
1266
|
+
authMode: z.literal("localhost_pkce"),
|
|
1267
|
+
isConfigured: z.boolean(),
|
|
1268
|
+
isReadyForPairing: z.boolean(),
|
|
1269
|
+
isLocalOnly: z.literal(true),
|
|
1270
|
+
runtimeOrigin: z.string(),
|
|
1271
|
+
setupMessage: z.string()
|
|
1272
|
+
});
|
|
1252
1273
|
export const aiModelProviderSchema = z.enum([
|
|
1253
1274
|
"openai-api",
|
|
1254
1275
|
"openai-codex",
|
|
@@ -1416,15 +1437,32 @@ export const forgeBoxToolAdapterSchema = z.object({
|
|
|
1416
1437
|
description: trimmedString.default(""),
|
|
1417
1438
|
accessMode: aiProcessorAccessModeSchema.default("read")
|
|
1418
1439
|
});
|
|
1440
|
+
export const forgeBoxPortDefinitionSchema = z.object({
|
|
1441
|
+
key: nonEmptyTrimmedString,
|
|
1442
|
+
label: nonEmptyTrimmedString,
|
|
1443
|
+
kind: nonEmptyTrimmedString.default("content"),
|
|
1444
|
+
required: z.boolean().default(false),
|
|
1445
|
+
expandableKeys: z.array(nonEmptyTrimmedString).default([])
|
|
1446
|
+
});
|
|
1419
1447
|
export const forgeBoxCatalogEntrySchema = z.object({
|
|
1420
|
-
|
|
1448
|
+
id: nonEmptyTrimmedString,
|
|
1449
|
+
boxId: trimmedString.optional(),
|
|
1421
1450
|
surfaceId: trimmedString.nullable(),
|
|
1422
1451
|
routePath: trimmedString.nullable(),
|
|
1423
|
-
|
|
1452
|
+
title: nonEmptyTrimmedString,
|
|
1453
|
+
label: trimmedString.optional(),
|
|
1454
|
+
icon: trimmedString.nullable().optional(),
|
|
1424
1455
|
description: trimmedString.default(""),
|
|
1425
1456
|
category: nonEmptyTrimmedString,
|
|
1426
|
-
|
|
1427
|
-
|
|
1457
|
+
tags: z.array(nonEmptyTrimmedString).default([]),
|
|
1458
|
+
capabilityModes: z.array(forgeBoxCapabilityModeSchema).default(["content"]).optional(),
|
|
1459
|
+
inputs: z.array(forgeBoxPortDefinitionSchema).default([]),
|
|
1460
|
+
params: z.array(forgeBoxPortDefinitionSchema).default([]),
|
|
1461
|
+
output: z.array(forgeBoxPortDefinitionSchema).default([]),
|
|
1462
|
+
tools: z.array(forgeBoxToolAdapterSchema).default([]),
|
|
1463
|
+
outputs: z.array(forgeBoxPortDefinitionSchema).default([]).optional(),
|
|
1464
|
+
toolAdapters: z.array(forgeBoxToolAdapterSchema).default([]).optional(),
|
|
1465
|
+
snapshotResolverKey: trimmedString.optional()
|
|
1428
1466
|
});
|
|
1429
1467
|
export const forgeBoxSnapshotSchema = z.object({
|
|
1430
1468
|
boxId: nonEmptyTrimmedString,
|
|
@@ -1436,11 +1474,16 @@ export const forgeBoxSnapshotSchema = z.object({
|
|
|
1436
1474
|
});
|
|
1437
1475
|
export const aiConnectorKindSchema = z.enum(["functor", "chat"]);
|
|
1438
1476
|
export const aiConnectorNodeTypeSchema = z.enum([
|
|
1477
|
+
"box",
|
|
1439
1478
|
"box_input",
|
|
1479
|
+
"value",
|
|
1440
1480
|
"user_input",
|
|
1441
1481
|
"functor",
|
|
1442
1482
|
"chat",
|
|
1443
|
-
"output"
|
|
1483
|
+
"output",
|
|
1484
|
+
"merge",
|
|
1485
|
+
"template",
|
|
1486
|
+
"pick_key"
|
|
1444
1487
|
]);
|
|
1445
1488
|
export const aiConnectorNodeModelConfigSchema = z.object({
|
|
1446
1489
|
connectionId: trimmedString.nullable().default(null),
|
|
@@ -1462,9 +1505,20 @@ export const aiConnectorNodeSchema = z.object({
|
|
|
1462
1505
|
description: trimmedString.default(""),
|
|
1463
1506
|
boxId: trimmedString.nullable().optional(),
|
|
1464
1507
|
prompt: trimmedString.optional(),
|
|
1508
|
+
promptTemplate: trimmedString.optional(),
|
|
1465
1509
|
systemPrompt: trimmedString.optional(),
|
|
1466
1510
|
outputKey: trimmedString.optional(),
|
|
1467
1511
|
enabledToolKeys: z.array(nonEmptyTrimmedString).default([]),
|
|
1512
|
+
inputs: z.array(forgeBoxPortDefinitionSchema).default([]).optional(),
|
|
1513
|
+
outputs: z.array(forgeBoxPortDefinitionSchema).default([]).optional(),
|
|
1514
|
+
params: z.array(forgeBoxPortDefinitionSchema).default([]).optional(),
|
|
1515
|
+
paramValues: z.record(z.string(), z.unknown()).default({}).optional(),
|
|
1516
|
+
template: trimmedString.optional(),
|
|
1517
|
+
selectedKey: trimmedString.optional(),
|
|
1518
|
+
valueType: z
|
|
1519
|
+
.enum(["string", "number", "boolean", "null", "array", "object"])
|
|
1520
|
+
.optional(),
|
|
1521
|
+
valueLiteral: trimmedString.optional(),
|
|
1468
1522
|
modelConfig: aiConnectorNodeModelConfigSchema.optional()
|
|
1469
1523
|
})
|
|
1470
1524
|
});
|
|
@@ -1488,7 +1542,31 @@ export const aiConnectorRunResultSchema = z.object({
|
|
|
1488
1542
|
label: z.string(),
|
|
1489
1543
|
text: z.string(),
|
|
1490
1544
|
json: z.record(z.string(), z.unknown()).nullable()
|
|
1491
|
-
}))
|
|
1545
|
+
})),
|
|
1546
|
+
debugTrace: z
|
|
1547
|
+
.object({
|
|
1548
|
+
nodes: z.array(z.object({
|
|
1549
|
+
nodeId: nonEmptyTrimmedString,
|
|
1550
|
+
nodeType: aiConnectorNodeTypeSchema,
|
|
1551
|
+
label: nonEmptyTrimmedString,
|
|
1552
|
+
input: z.array(z.object({
|
|
1553
|
+
sourceNodeId: nonEmptyTrimmedString,
|
|
1554
|
+
sourceHandle: trimmedString.nullable(),
|
|
1555
|
+
targetHandle: trimmedString.nullable(),
|
|
1556
|
+
text: z.string(),
|
|
1557
|
+
json: z.record(z.string(), z.unknown()).nullable()
|
|
1558
|
+
})),
|
|
1559
|
+
output: z.object({
|
|
1560
|
+
text: z.string(),
|
|
1561
|
+
json: z.record(z.string(), z.unknown()).nullable()
|
|
1562
|
+
}),
|
|
1563
|
+
tools: z.array(z.string()).default([]),
|
|
1564
|
+
logs: z.array(z.string()).default([]),
|
|
1565
|
+
error: z.string().nullable()
|
|
1566
|
+
})),
|
|
1567
|
+
errors: z.array(z.string()).default([])
|
|
1568
|
+
})
|
|
1569
|
+
.optional()
|
|
1492
1570
|
});
|
|
1493
1571
|
export const aiConnectorRunSchema = z.object({
|
|
1494
1572
|
id: nonEmptyTrimmedString,
|
|
@@ -1792,6 +1870,7 @@ export const settingsPayloadSchema = z.object({
|
|
|
1792
1870
|
psycheAuthRequired: z.boolean()
|
|
1793
1871
|
}),
|
|
1794
1872
|
calendarProviders: z.object({
|
|
1873
|
+
google: googleCalendarAuthSettingsSchema,
|
|
1795
1874
|
microsoft: microsoftCalendarAuthSettingsSchema
|
|
1796
1875
|
}),
|
|
1797
1876
|
modelSettings: modelSettingsPayloadSchema,
|
|
@@ -2008,10 +2087,7 @@ export const createCalendarConnectionSchema = z.discriminatedUnion("provider", [
|
|
|
2008
2087
|
z.object({
|
|
2009
2088
|
provider: z.literal("google"),
|
|
2010
2089
|
label: nonEmptyTrimmedString,
|
|
2011
|
-
|
|
2012
|
-
clientId: nonEmptyTrimmedString,
|
|
2013
|
-
clientSecret: nonEmptyTrimmedString,
|
|
2014
|
-
refreshToken: nonEmptyTrimmedString,
|
|
2090
|
+
authSessionId: nonEmptyTrimmedString,
|
|
2015
2091
|
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).min(1),
|
|
2016
2092
|
forgeCalendarUrl: nonEmptyTrimmedString.url().nullable().optional(),
|
|
2017
2093
|
createForgeCalendar: z.boolean().optional().default(false)
|
|
@@ -2043,13 +2119,6 @@ export const createCalendarConnectionSchema = z.discriminatedUnion("provider", [
|
|
|
2043
2119
|
})
|
|
2044
2120
|
]);
|
|
2045
2121
|
export const discoverCalendarConnectionSchema = z.discriminatedUnion("provider", [
|
|
2046
|
-
z.object({
|
|
2047
|
-
provider: z.literal("google"),
|
|
2048
|
-
username: nonEmptyTrimmedString,
|
|
2049
|
-
clientId: nonEmptyTrimmedString,
|
|
2050
|
-
clientSecret: nonEmptyTrimmedString,
|
|
2051
|
-
refreshToken: nonEmptyTrimmedString
|
|
2052
|
-
}),
|
|
2053
2122
|
z.object({
|
|
2054
2123
|
provider: z.literal("apple"),
|
|
2055
2124
|
username: nonEmptyTrimmedString,
|
|
@@ -2065,6 +2134,10 @@ export const discoverCalendarConnectionSchema = z.discriminatedUnion("provider",
|
|
|
2065
2134
|
export const startMicrosoftCalendarOauthSchema = z.object({
|
|
2066
2135
|
label: nonEmptyTrimmedString.optional()
|
|
2067
2136
|
});
|
|
2137
|
+
export const startGoogleCalendarOauthSchema = z.object({
|
|
2138
|
+
label: nonEmptyTrimmedString.optional(),
|
|
2139
|
+
browserOrigin: trimmedString.optional()
|
|
2140
|
+
});
|
|
2068
2141
|
export const testMicrosoftCalendarOauthConfigurationSchema = z.object({
|
|
2069
2142
|
clientId: nonEmptyTrimmedString.regex(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/, "Microsoft client IDs must use the standard app registration GUID format."),
|
|
2070
2143
|
tenantId: trimmedString.default("common"),
|
|
@@ -2078,6 +2151,14 @@ export const microsoftCalendarOauthSessionSchema = z.object({
|
|
|
2078
2151
|
error: z.string().nullable(),
|
|
2079
2152
|
discovery: calendarDiscoveryPayloadSchema.nullable()
|
|
2080
2153
|
});
|
|
2154
|
+
export const googleCalendarOauthSessionSchema = z.object({
|
|
2155
|
+
sessionId: nonEmptyTrimmedString,
|
|
2156
|
+
status: z.enum(["pending", "authorized", "error", "consumed", "expired"]),
|
|
2157
|
+
authUrl: z.string().url().nullable(),
|
|
2158
|
+
accountLabel: z.string().nullable(),
|
|
2159
|
+
error: z.string().nullable(),
|
|
2160
|
+
discovery: calendarDiscoveryPayloadSchema.nullable()
|
|
2161
|
+
});
|
|
2081
2162
|
export const updateCalendarConnectionSchema = z.object({
|
|
2082
2163
|
label: nonEmptyTrimmedString.optional(),
|
|
2083
2164
|
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).optional()
|
|
@@ -2595,6 +2676,12 @@ export const updateSettingsSchema = z.object({
|
|
|
2595
2676
|
.optional(),
|
|
2596
2677
|
calendarProviders: z
|
|
2597
2678
|
.object({
|
|
2679
|
+
google: z
|
|
2680
|
+
.object({
|
|
2681
|
+
clientId: trimmedString.optional(),
|
|
2682
|
+
clientSecret: trimmedString.optional()
|
|
2683
|
+
})
|
|
2684
|
+
.optional(),
|
|
2598
2685
|
microsoft: z
|
|
2599
2686
|
.object({
|
|
2600
2687
|
clientId: trimmedString.optional(),
|
|
@@ -2603,7 +2690,37 @@ export const updateSettingsSchema = z.object({
|
|
|
2603
2690
|
})
|
|
2604
2691
|
.optional()
|
|
2605
2692
|
})
|
|
2606
|
-
.optional()
|
|
2693
|
+
.optional()
|
|
2694
|
+
.superRefine((value, context) => {
|
|
2695
|
+
if (!value) {
|
|
2696
|
+
return;
|
|
2697
|
+
}
|
|
2698
|
+
const google = value.google;
|
|
2699
|
+
if (!google) {
|
|
2700
|
+
return;
|
|
2701
|
+
}
|
|
2702
|
+
const hasClientIdField = google.clientId !== undefined;
|
|
2703
|
+
const hasClientSecretField = google.clientSecret !== undefined;
|
|
2704
|
+
const hasClientIdValue = (google.clientId?.length ?? 0) > 0;
|
|
2705
|
+
const hasClientSecretValue = (google.clientSecret?.length ?? 0) > 0;
|
|
2706
|
+
if (hasClientIdField !== hasClientSecretField) {
|
|
2707
|
+
const message = "When overriding Google OAuth credentials, provide both the client ID and client secret together, or clear both fields together.";
|
|
2708
|
+
context.addIssue({
|
|
2709
|
+
code: z.ZodIssueCode.custom,
|
|
2710
|
+
path: ["google", hasClientIdField ? "clientSecret" : "clientId"],
|
|
2711
|
+
message
|
|
2712
|
+
});
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2715
|
+
if (hasClientIdValue !== hasClientSecretValue) {
|
|
2716
|
+
const message = "When overriding Google OAuth credentials, provide both the client ID and client secret together, or clear both fields together.";
|
|
2717
|
+
context.addIssue({
|
|
2718
|
+
code: z.ZodIssueCode.custom,
|
|
2719
|
+
path: ["google", hasClientIdValue ? "clientSecret" : "clientId"],
|
|
2720
|
+
message
|
|
2721
|
+
});
|
|
2722
|
+
}
|
|
2723
|
+
}),
|
|
2607
2724
|
modelSettings: z
|
|
2608
2725
|
.object({
|
|
2609
2726
|
forgeAgent: z
|
|
@@ -2748,7 +2865,8 @@ export const runAiConnectorSchema = z.object({
|
|
|
2748
2865
|
userInput: trimmedString.default(""),
|
|
2749
2866
|
context: z.record(z.string(), z.unknown()).default({}),
|
|
2750
2867
|
boxSnapshots: z.record(z.string(), z.unknown()).default({}),
|
|
2751
|
-
conversationId: trimmedString.nullable().default(null)
|
|
2868
|
+
conversationId: trimmedString.nullable().default(null),
|
|
2869
|
+
debug: z.boolean().default(false)
|
|
2752
2870
|
});
|
|
2753
2871
|
export const createAgentTokenSchema = z.object({
|
|
2754
2872
|
label: nonEmptyTrimmedString,
|
|
@@ -2,7 +2,6 @@ import { access, readFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
const distDir = path.join(process.cwd(), "dist");
|
|
4
4
|
const packagedRuntimeDistDir = path.join(process.cwd(), "plugins", "forge-codex", "runtime", "dist");
|
|
5
|
-
const defaultBasePath = process.env.FORGE_BASE_PATH ?? "/forge/";
|
|
6
5
|
const contentTypes = {
|
|
7
6
|
".css": "text/css; charset=utf-8",
|
|
8
7
|
".html": "text/html; charset=utf-8",
|
|
@@ -20,6 +19,18 @@ function normalizeBasePath(value) {
|
|
|
20
19
|
const withLeadingSlash = value.startsWith("/") ? value : `/${value}`;
|
|
21
20
|
return withLeadingSlash.endsWith("/") ? withLeadingSlash : `${withLeadingSlash}/`;
|
|
22
21
|
}
|
|
22
|
+
function normalizeAbsoluteUrl(value) {
|
|
23
|
+
const url = new URL(value);
|
|
24
|
+
url.pathname = normalizeBasePath(url.pathname);
|
|
25
|
+
return url;
|
|
26
|
+
}
|
|
27
|
+
function getDefaultBasePath() {
|
|
28
|
+
return process.env.FORGE_BASE_PATH ?? "/forge/";
|
|
29
|
+
}
|
|
30
|
+
function getDevWebOrigin() {
|
|
31
|
+
const value = process.env.FORGE_DEV_WEB_ORIGIN?.trim();
|
|
32
|
+
return value && value.length > 0 ? value : null;
|
|
33
|
+
}
|
|
23
34
|
function stripBasePath(requestPath, basePath) {
|
|
24
35
|
const normalizedBasePath = normalizeBasePath(basePath);
|
|
25
36
|
if (normalizedBasePath === "/") {
|
|
@@ -57,8 +68,16 @@ async function serveAsset(requestPath, reply) {
|
|
|
57
68
|
reply.code(404);
|
|
58
69
|
return { error: "Not found" };
|
|
59
70
|
}
|
|
71
|
+
const normalizedRequestPath = stripBasePath(requestPath, getDefaultBasePath());
|
|
72
|
+
const devWebOrigin = getDevWebOrigin();
|
|
73
|
+
if (devWebOrigin) {
|
|
74
|
+
const target = new URL(normalizedRequestPath.startsWith("/")
|
|
75
|
+
? normalizedRequestPath.slice(1)
|
|
76
|
+
: normalizedRequestPath, normalizeAbsoluteUrl(devWebOrigin));
|
|
77
|
+
reply.code(307).redirect(target.toString());
|
|
78
|
+
return reply;
|
|
79
|
+
}
|
|
60
80
|
const clientDir = await getClientDir();
|
|
61
|
-
const normalizedRequestPath = stripBasePath(requestPath, defaultBasePath);
|
|
62
81
|
const assetPath = resolveAsset(clientDir, normalizedRequestPath);
|
|
63
82
|
const ext = path.extname(assetPath);
|
|
64
83
|
try {
|