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
|
@@ -2,7 +2,7 @@ import Fastify from "fastify";
|
|
|
2
2
|
import cors from "@fastify/cors";
|
|
3
3
|
import multipart from "@fastify/multipart";
|
|
4
4
|
import { CronExpressionParser } from "cron-parser";
|
|
5
|
-
import { ZodError } from "zod";
|
|
5
|
+
import { z, ZodError } from "zod";
|
|
6
6
|
import { configureDatabase, configureDatabaseSeeding, runInTransaction } from "./db.js";
|
|
7
7
|
import { HttpError, isHttpError } from "./errors.js";
|
|
8
8
|
import { listActivityEvents, listActivityEventsForTask, recordActivityEvent, removeActivityEvent } from "./repositories/activity-events.js";
|
|
@@ -13,7 +13,7 @@ import { listEventLog } from "./repositories/event-log.js";
|
|
|
13
13
|
import { createDiagnosticMessage, DIAGNOSTIC_LOG_RETENTION_SWEEP_INTERVAL_MS, enforceDiagnosticLogRetention, listDiagnosticLogs, normalizeDiagnosticSource, recordDiagnosticLog, serializeDiagnosticError } from "./repositories/diagnostic-logs.js";
|
|
14
14
|
import { createGoal, getGoalById, listGoals, updateGoal } from "./repositories/goals.js";
|
|
15
15
|
import { getSurfaceLayout, resetSurfaceLayout, saveSurfaceLayout } from "./repositories/surface-layouts.js";
|
|
16
|
-
import { listForgeBoxCatalog } from "./connectors/box-registry.js";
|
|
16
|
+
import { buildConnectorOutputCatalogEntry, listForgeBoxCatalog } from "./connectors/box-registry.js";
|
|
17
17
|
import { createHabit, createHabitCheckIn, deleteHabitCheckIn, getHabitById, listHabits, updateHabit } from "./repositories/habits.js";
|
|
18
18
|
import { listDomains } from "./repositories/domains.js";
|
|
19
19
|
import { buildNotesSummaryByEntity, createNote, getNoteById, listNotes, updateNote } from "./repositories/notes.js";
|
|
@@ -45,12 +45,12 @@ import { getWeeklyReviewPayload } from "./services/reviews.js";
|
|
|
45
45
|
import { finalizeWeeklyReviewClosure } from "./repositories/weekly-reviews.js";
|
|
46
46
|
import { createTaskRunWatchdog } from "./services/task-run-watchdog.js";
|
|
47
47
|
import { suggestTags } from "./services/tagging.js";
|
|
48
|
-
import { CalendarConnectionConflictError, completeMicrosoftCalendarOauth, createCalendarConnection, deleteCalendarEventProjection, discoverCalendarConnection, discoverExistingCalendarConnection, getMicrosoftCalendarOauthSession, listConnectedCalendarConnections, removeCalendarConnection, pushCalendarEventUpdate, readCalendarOverview, syncCalendarConnection, startMicrosoftCalendarOauth, testMicrosoftCalendarOauthConfiguration, listCalendarProviderMetadata, updateCalendarConnectionSelection } from "./services/calendar-runtime.js";
|
|
48
|
+
import { CalendarConnectionConflictError, completeGoogleCalendarOauth, completeMicrosoftCalendarOauth, createCalendarConnection, deleteCalendarEventProjection, discoverCalendarConnection, discoverExistingCalendarConnection, getGoogleCalendarOauthSession, getMicrosoftCalendarOauthSession, listConnectedCalendarConnections, removeCalendarConnection, pushCalendarEventUpdate, readCalendarOverview, syncCalendarConnection, startGoogleCalendarOauth, startMicrosoftCalendarOauth, testMicrosoftCalendarOauthConfiguration, listCalendarProviderMetadata, updateCalendarConnectionSelection } from "./services/calendar-runtime.js";
|
|
49
49
|
import { consumeOpenAiCodexOauthCredentials, getOpenAiCodexOauthSession, startOpenAiCodexOauthSession, submitOpenAiCodexOauthManualInput } from "./services/openai-codex-oauth.js";
|
|
50
50
|
import { PSYCHE_ENTITY_TYPES, createBehaviorSchema, createBeliefEntrySchema, createBehaviorPatternSchema, createEmotionDefinitionSchema, createEventTypeSchema, createModeGuideSessionSchema, createModeProfileSchema, createPsycheValueSchema, createTriggerReportSchema, updateBehaviorSchema, updateBeliefEntrySchema, updateBehaviorPatternSchema, updateEmotionDefinitionSchema, updateEventTypeSchema, updateModeGuideSessionSchema, updateModeProfileSchema, updatePsycheValueSchema, updateTriggerReportSchema } from "./psyche-types.js";
|
|
51
51
|
import { createQuestionnaireInstrumentSchema, publishQuestionnaireVersionSchema, startQuestionnaireRunSchema, updateQuestionnaireRunSchema, updateQuestionnaireVersionSchema } from "./questionnaire-types.js";
|
|
52
52
|
import { createPreferenceCatalogItemSchema, createPreferenceCatalogSchema, createPreferenceContextSchema, createPreferenceItemSchema, enqueueEntityPreferenceItemSchema, mergePreferenceContextsSchema, preferenceWorkspaceQuerySchema, startPreferenceGameSchema, submitAbsoluteSignalSchema, submitPairwiseJudgmentSchema, updatePreferenceCatalogItemSchema, updatePreferenceCatalogSchema, updatePreferenceContextSchema, updatePreferenceItemSchema, updatePreferenceScoreSchema } from "./preferences-types.js";
|
|
53
|
-
import { activityListQuerySchema, activitySourceSchema, createAgentActionSchema, createAgentTokenSchema, createAiConnectorSchema, createAiProcessorLinkSchema, createAiProcessorSchema, runAiConnectorSchema, writeSurfaceLayoutSchema, upsertAiModelConnectionSchema, testAiModelConnectionSchema, submitOpenAiCodexOauthManualCodeSchema, batchCreateEntitiesSchema, batchDeleteEntitiesSchema, batchRestoreEntitiesSchema, batchSearchEntitiesSchema, batchUpdateEntitiesSchema, createGoalSchema, createInsightFeedbackSchema, createInsightSchema, createStrategySchema, createUserSchema, createNoteSchema, createProjectSchema, createManualRewardGrantSchema, createCalendarEventSchema, createHabitCheckInSchema, createCalendarConnectionSchema, createDiagnosticLogSchema, discoverCalendarConnectionSchema, startMicrosoftCalendarOauthSchema, testMicrosoftCalendarOauthConfigurationSchema, createHabitSchema, createTaskTimeboxSchema, createWorkBlockTemplateSchema, createSessionEventSchema, createWorkAdjustmentSchema, createTagSchema, calendarOverviewQuerySchema, notesListQuerySchema, updateTagSchema, createTaskSchema, diagnosticLogListQuerySchema, eventsListQuerySchema, operatorLogWorkSchema, projectBoardPayloadSchema, projectListQuerySchema, entityDeleteQuerySchema, removeActivityEventSchema, resolveApprovalRequestSchema, rewardsLedgerQuerySchema, habitListQuerySchema, taskContextPayloadSchema, taskRunClaimSchema, taskRunFocusSchema, taskRunFinishSchema, taskRunHeartbeatSchema, taskRunListQuerySchema, taskListQuerySchema, tagSuggestionRequestSchema, uncompleteTaskSchema, updateSettingsSchema, updateGoalSchema, updateHabitSchema, updateInsightSchema, updateStrategySchema, updateUserSchema, updateCalendarConnectionSchema, updateCalendarEventSchema, updateNoteSchema, updateProjectSchema, updateRewardRuleSchema, updateTaskTimeboxSchema, updateTaskSchema, updateUserAccessGrantSchema, updateWorkBlockTemplateSchema, updateAiConnectorSchema, updateAiProcessorSchema, runAiProcessorSchema, workAdjustmentResultSchema, finalizeWeeklyReviewResultSchema, goalListQuerySchema, recommendTaskTimeboxesSchema, strategyListQuerySchema } from "./types.js";
|
|
53
|
+
import { activityListQuerySchema, activitySourceSchema, createAgentActionSchema, createAgentTokenSchema, createAiConnectorSchema, createAiProcessorLinkSchema, createAiProcessorSchema, runAiConnectorSchema, writeSurfaceLayoutSchema, upsertAiModelConnectionSchema, testAiModelConnectionSchema, submitOpenAiCodexOauthManualCodeSchema, batchCreateEntitiesSchema, batchDeleteEntitiesSchema, batchRestoreEntitiesSchema, batchSearchEntitiesSchema, batchUpdateEntitiesSchema, createGoalSchema, createInsightFeedbackSchema, createInsightSchema, createStrategySchema, createUserSchema, createNoteSchema, createProjectSchema, createManualRewardGrantSchema, createCalendarEventSchema, createHabitCheckInSchema, createCalendarConnectionSchema, createDiagnosticLogSchema, discoverCalendarConnectionSchema, startGoogleCalendarOauthSchema, startMicrosoftCalendarOauthSchema, testMicrosoftCalendarOauthConfigurationSchema, createHabitSchema, createTaskTimeboxSchema, createWorkBlockTemplateSchema, createSessionEventSchema, createWorkAdjustmentSchema, createTagSchema, calendarOverviewQuerySchema, notesListQuerySchema, updateTagSchema, createTaskSchema, diagnosticLogListQuerySchema, eventsListQuerySchema, operatorLogWorkSchema, projectBoardPayloadSchema, projectListQuerySchema, entityDeleteQuerySchema, removeActivityEventSchema, resolveApprovalRequestSchema, rewardsLedgerQuerySchema, habitListQuerySchema, taskContextPayloadSchema, taskRunClaimSchema, taskRunFocusSchema, taskRunFinishSchema, taskRunHeartbeatSchema, taskRunListQuerySchema, taskListQuerySchema, tagSuggestionRequestSchema, uncompleteTaskSchema, updateSettingsSchema, updateGoalSchema, updateHabitSchema, updateInsightSchema, updateStrategySchema, updateUserSchema, updateCalendarConnectionSchema, updateCalendarEventSchema, updateNoteSchema, updateProjectSchema, updateRewardRuleSchema, updateTaskTimeboxSchema, updateTaskSchema, updateUserAccessGrantSchema, updateWorkBlockTemplateSchema, updateAiConnectorSchema, updateAiProcessorSchema, runAiProcessorSchema, workAdjustmentResultSchema, finalizeWeeklyReviewResultSchema, goalListQuerySchema, recommendTaskTimeboxesSchema, strategyListQuerySchema } from "./types.js";
|
|
54
54
|
import { buildOpenApiDocument } from "./openapi.js";
|
|
55
55
|
import { registerWebRoutes } from "./web.js";
|
|
56
56
|
import { createManagerRuntime } from "./managers/runtime.js";
|
|
@@ -2569,10 +2569,10 @@ const AGENT_ONBOARDING_TOOL_INPUT_CATALOG = [
|
|
|
2569
2569
|
toolName: "forge_connect_calendar_provider",
|
|
2570
2570
|
summary: "Create a Forge calendar connection for Google, Apple, Exchange Online, or custom CalDAV.",
|
|
2571
2571
|
whenToUse: "Use only when the operator explicitly wants Forge connected to an external calendar provider.",
|
|
2572
|
-
inputShape: '{ provider: "google"|"apple"|"caldav"|"microsoft", label: string, username?: string,
|
|
2572
|
+
inputShape: '{ provider: "google"|"apple"|"caldav"|"microsoft", label: string, username?: string, password?: string, serverUrl?: string, authSessionId?: string, selectedCalendarUrls: string[], forgeCalendarUrl?: string, createForgeCalendar?: boolean }',
|
|
2573
2573
|
requiredFields: ["provider", "label", "provider-specific credentials"],
|
|
2574
2574
|
notes: [
|
|
2575
|
-
"Google uses
|
|
2575
|
+
"Google now uses an interactive localhost Authorization Code + PKCE flow. The user signs in interactively on the same machine running Forge, Forge exchanges the authorization code on the backend, and forge_connect_calendar_provider should only be used after a completed Google authSessionId exists.",
|
|
2576
2576
|
"Apple starts from https://caldav.icloud.com and autodiscovers the principal plus calendars after authentication.",
|
|
2577
2577
|
"Exchange Online uses Microsoft Graph. In the current Forge implementation it is read-only: Forge mirrors the selected calendars but does not publish work blocks or timeboxes back to Microsoft.",
|
|
2578
2578
|
"In the current self-hosted local runtime, Exchange Online now uses an interactive Microsoft public-client sign-in flow with PKCE after the operator has saved the Microsoft client ID, tenant, and redirect URI in Settings -> Calendar. Non-interactive callers should treat Microsoft connection setup as a Settings-owned operator action unless a completed authSessionId already exists.",
|
|
@@ -3072,8 +3072,8 @@ function buildAgentOnboardingPayload(request) {
|
|
|
3072
3072
|
saveSuggestionPlacement: "end_of_message",
|
|
3073
3073
|
saveSuggestionTone: "gentle_optional",
|
|
3074
3074
|
maxQuestionsPerTurn: 1,
|
|
3075
|
-
psycheExplorationRule: "When a Psyche entity needs understanding first, begin with one exploratory question before any working formulation, replacement belief, suggested title, or save pitch. Keep the opening reflection to one or two short sentences, stay in plain prose instead of bullets or numbered lists, keep that first reply short, do not mention Forge search or save structure yet, avoid colons or list-shaped phrasing, and wait for the user's answer before offering a fuller formulation.",
|
|
3076
|
-
psycheOpeningQuestionRule: "Prefer a concrete opening question tied to the entity: ask when the value mattered, what happened the last time the pattern appeared, what
|
|
3075
|
+
psycheExplorationRule: "When a Psyche entity needs understanding first, begin with one exploratory question before any working formulation, replacement belief, suggested title, or save pitch. Keep the opening reflection to one or two short sentences, stay in plain prose instead of bullets or numbered lists, keep that first reply short, do not mention Forge search or save structure yet, avoid colons or list-shaped phrasing, prefer what/when/how over why until the experience is grounded, and wait for the user's answer before offering a fuller formulation.",
|
|
3076
|
+
psycheOpeningQuestionRule: "Prefer a concrete opening question tied to the entity: ask when the value mattered, what happened the last time the pattern appeared, what cue or body signal came first before the behavior, what the belief starts saying about self or outcome, what feels most at risk inside the mode, what the part is trying to get the user to do or stop doing, or where the shift began in the incident. Reflect briefly before the question and stay in one follow-up lane at a time.",
|
|
3077
3077
|
duplicateCheckRoute: "/api/v1/entities/search",
|
|
3078
3078
|
uiSuggestionRule: "offer_visual_ui_when_review_or_editing_would_be_easier",
|
|
3079
3079
|
browserFallbackRule: "Do not open the Forge UI or a browser just to create or update normal entities when the batch entity tools can do the job.",
|
|
@@ -5711,6 +5711,37 @@ export async function buildServer(options = {}) {
|
|
|
5711
5711
|
providers: listCalendarProviderMetadata(),
|
|
5712
5712
|
connections: listConnectedCalendarConnections()
|
|
5713
5713
|
}));
|
|
5714
|
+
app.post("/api/v1/calendar/oauth/google/start", async (request) => {
|
|
5715
|
+
requireScopedAccess(request.headers, ["write"], {
|
|
5716
|
+
route: "/api/v1/calendar/oauth/google/start"
|
|
5717
|
+
});
|
|
5718
|
+
return await startGoogleCalendarOauth(startGoogleCalendarOauthSchema.parse(request.body ?? {}), {
|
|
5719
|
+
browserOrigin: typeof request.body?.browserOrigin ===
|
|
5720
|
+
"string"
|
|
5721
|
+
? request.body.browserOrigin
|
|
5722
|
+
: null,
|
|
5723
|
+
openerOrigin: typeof request.headers.origin === "string"
|
|
5724
|
+
? request.headers.origin
|
|
5725
|
+
: typeof request.headers.referer === "string"
|
|
5726
|
+
? request.headers.referer
|
|
5727
|
+
: null,
|
|
5728
|
+
requestBaseOrigin: getRequestOrigin(request)
|
|
5729
|
+
});
|
|
5730
|
+
});
|
|
5731
|
+
app.get("/api/v1/calendar/oauth/google/session/:id", async (request, reply) => {
|
|
5732
|
+
requireScopedAccess(request.headers, ["write"], { route: "/api/v1/calendar/oauth/google/session/:id" });
|
|
5733
|
+
try {
|
|
5734
|
+
return getGoogleCalendarOauthSession(request.params.id);
|
|
5735
|
+
}
|
|
5736
|
+
catch (error) {
|
|
5737
|
+
if (error instanceof Error &&
|
|
5738
|
+
error.message.startsWith("Unknown Google calendar auth session")) {
|
|
5739
|
+
reply.code(404);
|
|
5740
|
+
return { error: "Google calendar auth session not found" };
|
|
5741
|
+
}
|
|
5742
|
+
throw error;
|
|
5743
|
+
}
|
|
5744
|
+
});
|
|
5714
5745
|
app.post("/api/v1/calendar/oauth/microsoft/start", async (request) => {
|
|
5715
5746
|
requireScopedAccess(request.headers, ["write"], {
|
|
5716
5747
|
route: "/api/v1/calendar/oauth/microsoft/start"
|
|
@@ -5783,6 +5814,54 @@ export async function buildServer(options = {}) {
|
|
|
5783
5814
|
setTimeout(() => window.close(), 180);
|
|
5784
5815
|
</script>
|
|
5785
5816
|
</body>
|
|
5817
|
+
</html>`;
|
|
5818
|
+
reply.type("text/html; charset=utf-8");
|
|
5819
|
+
return body;
|
|
5820
|
+
});
|
|
5821
|
+
app.get("/api/v1/calendar/oauth/google/callback", async (request, reply) => {
|
|
5822
|
+
const query = request.query;
|
|
5823
|
+
const result = await completeGoogleCalendarOauth({
|
|
5824
|
+
state: query.state ?? null,
|
|
5825
|
+
code: query.code ?? null,
|
|
5826
|
+
error: query.error ?? null,
|
|
5827
|
+
errorDescription: query.error_description ?? null
|
|
5828
|
+
});
|
|
5829
|
+
const session = result.session;
|
|
5830
|
+
const escapedOrigin = JSON.stringify(result.openerOrigin || "*");
|
|
5831
|
+
const escapedMessage = JSON.stringify({
|
|
5832
|
+
type: "forge:google-calendar-auth",
|
|
5833
|
+
sessionId: session.sessionId,
|
|
5834
|
+
status: session.status
|
|
5835
|
+
});
|
|
5836
|
+
const body = `<!doctype html>
|
|
5837
|
+
<html lang="en">
|
|
5838
|
+
<head>
|
|
5839
|
+
<meta charset="utf-8" />
|
|
5840
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
5841
|
+
<title>Forge Google sign-in</title>
|
|
5842
|
+
<style>
|
|
5843
|
+
body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif;background:#0b1320;color:#f8fafc;display:grid;place-items:center;min-height:100vh}
|
|
5844
|
+
main{max-width:30rem;padding:2rem;border:1px solid rgba(255,255,255,.08);border-radius:24px;background:linear-gradient(180deg,rgba(18,28,38,.98),rgba(11,17,28,.98))}
|
|
5845
|
+
h1{margin:0 0 .75rem;font-size:1.15rem}
|
|
5846
|
+
p{margin:0;color:rgba(248,250,252,.72);line-height:1.6}
|
|
5847
|
+
</style>
|
|
5848
|
+
</head>
|
|
5849
|
+
<body>
|
|
5850
|
+
<main>
|
|
5851
|
+
<h1>${session.status === "authorized" ? "Google account connected" : "Google sign-in needs attention"}</h1>
|
|
5852
|
+
<p>${session.status === "authorized" ? "Forge received your Google account and sent the result back to the calendar setup flow. You can close this window." : (session.error ?? "Forge could not complete Google sign-in. You can close this window and try again from Settings.")}</p>
|
|
5853
|
+
</main>
|
|
5854
|
+
<script>
|
|
5855
|
+
const message = ${escapedMessage};
|
|
5856
|
+
const targetOrigin = ${escapedOrigin};
|
|
5857
|
+
try {
|
|
5858
|
+
if (window.opener && !window.opener.closed) {
|
|
5859
|
+
window.opener.postMessage(message, targetOrigin);
|
|
5860
|
+
}
|
|
5861
|
+
} catch {}
|
|
5862
|
+
setTimeout(() => window.close(), 180);
|
|
5863
|
+
</script>
|
|
5864
|
+
</body>
|
|
5786
5865
|
</html>`;
|
|
5787
5866
|
reply.type("text/html; charset=utf-8");
|
|
5788
5867
|
return body;
|
|
@@ -6959,132 +7038,184 @@ export async function buildServer(options = {}) {
|
|
|
6959
7038
|
secrets: managers.secrets
|
|
6960
7039
|
}, { trigger: "route" });
|
|
6961
7040
|
});
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
7041
|
+
const registerFlowApiRoutes = (basePath, noun, options) => {
|
|
7042
|
+
const collectionKey = options?.collectionKey ?? "connectors";
|
|
7043
|
+
const singularKey = options?.singularKey ?? "connector";
|
|
7044
|
+
const catalogPath = options?.catalogPath ?? `${basePath}/catalog/boxes`;
|
|
7045
|
+
app.get(catalogPath, async (request) => {
|
|
7046
|
+
requireScopedAccess(request.headers, ["read"], {
|
|
7047
|
+
route: catalogPath
|
|
7048
|
+
});
|
|
7049
|
+
return {
|
|
7050
|
+
boxes: [
|
|
7051
|
+
...listForgeBoxCatalog(),
|
|
7052
|
+
...listAiConnectors().flatMap((connector) => connector.publishedOutputs.map((output) => buildConnectorOutputCatalogEntry({
|
|
7053
|
+
connectorId: connector.id,
|
|
7054
|
+
title: connector.title,
|
|
7055
|
+
outputId: output.id
|
|
7056
|
+
})))
|
|
7057
|
+
]
|
|
7058
|
+
};
|
|
6965
7059
|
});
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
7060
|
+
app.get(basePath, async (request) => {
|
|
7061
|
+
requireScopedAccess(request.headers, ["read"], {
|
|
7062
|
+
route: basePath
|
|
7063
|
+
});
|
|
7064
|
+
return {
|
|
7065
|
+
[collectionKey]: listAiConnectors()
|
|
7066
|
+
};
|
|
6973
7067
|
});
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
7068
|
+
app.post(basePath, async (request, reply) => {
|
|
7069
|
+
requireScopedAccess(request.headers, ["write"], {
|
|
7070
|
+
route: basePath
|
|
7071
|
+
});
|
|
7072
|
+
const connector = createAiConnector(createAiConnectorSchema.parse(request.body ?? {}));
|
|
7073
|
+
reply.code(201);
|
|
7074
|
+
return { [singularKey]: connector };
|
|
6981
7075
|
});
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
7076
|
+
app.get(`${basePath}/:id`, async (request, reply) => {
|
|
7077
|
+
requireScopedAccess(request.headers, ["read"], {
|
|
7078
|
+
route: `${basePath}/:id`
|
|
7079
|
+
});
|
|
7080
|
+
const connector = getAiConnectorById(request.params.id);
|
|
7081
|
+
if (!connector) {
|
|
7082
|
+
reply.code(404);
|
|
7083
|
+
return { error: `${noun} not found` };
|
|
7084
|
+
}
|
|
7085
|
+
return {
|
|
7086
|
+
[singularKey]: connector,
|
|
7087
|
+
runs: listAiConnectorRuns(connector.id),
|
|
7088
|
+
conversation: getAiConnectorConversationForConnector(connector.id)
|
|
7089
|
+
};
|
|
6989
7090
|
});
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
});
|
|
7001
|
-
app.patch("/api/v1/ai-connectors/:id", async (request, reply) => {
|
|
7002
|
-
requireScopedAccess(request.headers, ["write"], {
|
|
7003
|
-
route: "/api/v1/ai-connectors/:id"
|
|
7091
|
+
app.patch(`${basePath}/:id`, async (request, reply) => {
|
|
7092
|
+
requireScopedAccess(request.headers, ["write"], {
|
|
7093
|
+
route: `${basePath}/:id`
|
|
7094
|
+
});
|
|
7095
|
+
const connector = updateAiConnector(request.params.id, updateAiConnectorSchema.parse(request.body ?? {}));
|
|
7096
|
+
if (!connector) {
|
|
7097
|
+
reply.code(404);
|
|
7098
|
+
return { error: `${noun} not found` };
|
|
7099
|
+
}
|
|
7100
|
+
return { [singularKey]: connector };
|
|
7004
7101
|
});
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7102
|
+
app.delete(`${basePath}/:id`, async (request, reply) => {
|
|
7103
|
+
requireScopedAccess(request.headers, ["write"], {
|
|
7104
|
+
route: `${basePath}/:id`
|
|
7105
|
+
});
|
|
7106
|
+
const connector = deleteAiConnector(request.params.id);
|
|
7107
|
+
if (!connector) {
|
|
7108
|
+
reply.code(404);
|
|
7109
|
+
return { error: `${noun} not found` };
|
|
7110
|
+
}
|
|
7111
|
+
return { [singularKey]: connector };
|
|
7015
7112
|
});
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7113
|
+
app.post(`${basePath}/:id/run`, async (request, reply) => {
|
|
7114
|
+
requireScopedAccess(request.headers, ["write"], {
|
|
7115
|
+
route: `${basePath}/:id/run`
|
|
7116
|
+
});
|
|
7117
|
+
const connector = getAiConnectorById(request.params.id);
|
|
7118
|
+
if (!connector) {
|
|
7119
|
+
reply.code(404);
|
|
7120
|
+
return { error: `${noun} not found` };
|
|
7121
|
+
}
|
|
7122
|
+
const execution = await runAiConnector(connector.id, runAiConnectorSchema.parse(request.body ?? {}), {
|
|
7123
|
+
llm: managers.llm,
|
|
7124
|
+
secrets: managers.secrets
|
|
7125
|
+
}, "run");
|
|
7126
|
+
return {
|
|
7127
|
+
[singularKey]: execution.connector,
|
|
7128
|
+
run: execution.run,
|
|
7129
|
+
conversation: execution.conversation
|
|
7130
|
+
};
|
|
7026
7131
|
});
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7132
|
+
app.post(`${basePath}/:id/chat`, async (request, reply) => {
|
|
7133
|
+
requireScopedAccess(request.headers, ["write"], {
|
|
7134
|
+
route: `${basePath}/:id/chat`
|
|
7135
|
+
});
|
|
7136
|
+
const connector = getAiConnectorById(request.params.id);
|
|
7137
|
+
if (!connector) {
|
|
7138
|
+
reply.code(404);
|
|
7139
|
+
return { error: `${noun} not found` };
|
|
7140
|
+
}
|
|
7141
|
+
const execution = await runAiConnector(connector.id, runAiConnectorSchema.parse(request.body ?? {}), {
|
|
7142
|
+
llm: managers.llm,
|
|
7143
|
+
secrets: managers.secrets
|
|
7144
|
+
}, "chat");
|
|
7145
|
+
return {
|
|
7146
|
+
[singularKey]: execution.connector,
|
|
7147
|
+
run: execution.run,
|
|
7148
|
+
conversation: execution.conversation
|
|
7149
|
+
};
|
|
7150
|
+
});
|
|
7151
|
+
app.get(`${basePath}/:id/output`, async (request, reply) => {
|
|
7152
|
+
requireScopedAccess(request.headers, ["read"], {
|
|
7153
|
+
route: `${basePath}/:id/output`
|
|
7154
|
+
});
|
|
7155
|
+
const connector = getAiConnectorById(request.params.id);
|
|
7156
|
+
if (!connector) {
|
|
7157
|
+
reply.code(404);
|
|
7158
|
+
return { error: `${noun} not found` };
|
|
7159
|
+
}
|
|
7160
|
+
return {
|
|
7161
|
+
[singularKey]: connector,
|
|
7162
|
+
output: connector.lastRun?.result ?? null
|
|
7163
|
+
};
|
|
7164
|
+
});
|
|
7165
|
+
app.get(`${basePath}/:id/runs`, async (request, reply) => {
|
|
7166
|
+
requireScopedAccess(request.headers, ["read"], {
|
|
7167
|
+
route: `${basePath}/:id/runs`
|
|
7168
|
+
});
|
|
7169
|
+
const connector = getAiConnectorById(request.params.id);
|
|
7170
|
+
if (!connector) {
|
|
7171
|
+
reply.code(404);
|
|
7172
|
+
return { error: `${noun} not found` };
|
|
7173
|
+
}
|
|
7174
|
+
return {
|
|
7175
|
+
runs: listAiConnectorRuns(connector.id)
|
|
7176
|
+
};
|
|
7177
|
+
});
|
|
7178
|
+
};
|
|
7179
|
+
registerFlowApiRoutes("/api/v1/workbench/flows", "Workbench flow", {
|
|
7180
|
+
collectionKey: "flows",
|
|
7181
|
+
singularKey: "flow",
|
|
7182
|
+
catalogPath: "/api/v1/workbench/catalog/boxes"
|
|
7036
7183
|
});
|
|
7037
|
-
app.post("/api/v1/
|
|
7184
|
+
app.post("/api/v1/workbench/run", async (request, reply) => {
|
|
7038
7185
|
requireScopedAccess(request.headers, ["write"], {
|
|
7039
|
-
route: "/api/v1/
|
|
7186
|
+
route: "/api/v1/workbench/run"
|
|
7040
7187
|
});
|
|
7041
|
-
const
|
|
7042
|
-
|
|
7188
|
+
const payload = runAiConnectorSchema
|
|
7189
|
+
.extend({
|
|
7190
|
+
flowId: z.string().trim().min(1)
|
|
7191
|
+
})
|
|
7192
|
+
.parse(request.body ?? {});
|
|
7193
|
+
const flow = getAiConnectorById(payload.flowId);
|
|
7194
|
+
if (!flow) {
|
|
7043
7195
|
reply.code(404);
|
|
7044
|
-
return { error: "
|
|
7196
|
+
return { error: "Workbench flow not found" };
|
|
7045
7197
|
}
|
|
7046
|
-
|
|
7198
|
+
const { flowId, ...runInput } = payload;
|
|
7199
|
+
const execution = await runAiConnector(flow.id, runInput, {
|
|
7047
7200
|
llm: managers.llm,
|
|
7048
7201
|
secrets: managers.secrets
|
|
7049
|
-
}, "
|
|
7050
|
-
});
|
|
7051
|
-
app.get("/api/v1/ai-connectors/:id/output", async (request, reply) => {
|
|
7052
|
-
requireScopedAccess(request.headers, ["read"], {
|
|
7053
|
-
route: "/api/v1/ai-connectors/:id/output"
|
|
7054
|
-
});
|
|
7055
|
-
const connector = getAiConnectorById(request.params.id);
|
|
7056
|
-
if (!connector) {
|
|
7057
|
-
reply.code(404);
|
|
7058
|
-
return { error: "AI connector not found" };
|
|
7059
|
-
}
|
|
7060
|
-
return {
|
|
7061
|
-
connector,
|
|
7062
|
-
output: connector.lastRun?.result ?? null
|
|
7063
|
-
};
|
|
7064
|
-
});
|
|
7065
|
-
app.get("/api/v1/ai-connectors/:id/runs", async (request, reply) => {
|
|
7066
|
-
requireScopedAccess(request.headers, ["read"], {
|
|
7067
|
-
route: "/api/v1/ai-connectors/:id/runs"
|
|
7068
|
-
});
|
|
7069
|
-
const connector = getAiConnectorById(request.params.id);
|
|
7070
|
-
if (!connector) {
|
|
7071
|
-
reply.code(404);
|
|
7072
|
-
return { error: "AI connector not found" };
|
|
7073
|
-
}
|
|
7202
|
+
}, "run");
|
|
7074
7203
|
return {
|
|
7075
|
-
|
|
7204
|
+
flow: execution.connector,
|
|
7205
|
+
run: execution.run,
|
|
7206
|
+
conversation: execution.conversation
|
|
7076
7207
|
};
|
|
7077
7208
|
});
|
|
7078
|
-
app.get("/api/v1/
|
|
7209
|
+
app.get("/api/v1/workbench/flows/by-slug/:slug", async (request, reply) => {
|
|
7079
7210
|
requireScopedAccess(request.headers, ["read"], {
|
|
7080
|
-
route: "/api/v1/
|
|
7211
|
+
route: "/api/v1/workbench/flows/by-slug/:slug"
|
|
7081
7212
|
});
|
|
7082
7213
|
const connector = getAiConnectorBySlug(request.params.slug);
|
|
7083
7214
|
if (!connector) {
|
|
7084
7215
|
reply.code(404);
|
|
7085
|
-
return { error: "
|
|
7216
|
+
return { error: "Workbench flow not found" };
|
|
7086
7217
|
}
|
|
7087
|
-
return { connector };
|
|
7218
|
+
return { flow: connector };
|
|
7088
7219
|
});
|
|
7089
7220
|
app.post("/api/v1/settings/tokens", async (request, reply) => {
|
|
7090
7221
|
const auth = requireOperatorSession(request.headers, { route: "/api/v1/settings/tokens" });
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { getDatabase } from "../db.js";
|
|
2
|
+
import { getFitnessViewData, getSleepViewData } from "../health.js";
|
|
3
|
+
import { listMovementPlaces } from "../movement.js";
|
|
4
|
+
import { createNote, listNotes } from "../repositories/notes.js";
|
|
5
|
+
import { updateTask } from "../repositories/tasks.js";
|
|
6
|
+
import { searchEntities } from "../services/entity-crud.js";
|
|
7
|
+
import { executeCommonWorkbenchTool, mapWorkbenchTools } from "../../../src/lib/workbench/runtime.js";
|
|
8
|
+
import { getWorkbenchNodeCatalog, getWorkbenchNodeDefinition } from "../../../src/lib/workbench/registry.js";
|
|
9
|
+
function createSnapshotForConnectorOutput(boxId) {
|
|
10
|
+
const outputId = boxId.replace(/^connector-output:/, "");
|
|
11
|
+
const rows = getDatabase()
|
|
12
|
+
.prepare(`SELECT id, title, published_outputs_json, last_run_json FROM ai_connectors ORDER BY updated_at DESC`)
|
|
13
|
+
.all();
|
|
14
|
+
for (const row of rows) {
|
|
15
|
+
const outputs = JSON.parse(row.published_outputs_json || "[]");
|
|
16
|
+
const output = outputs.find((entry) => entry.id === outputId);
|
|
17
|
+
if (!output) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const lastRun = row.last_run_json
|
|
21
|
+
? JSON.parse(row.last_run_json)
|
|
22
|
+
: null;
|
|
23
|
+
const published = lastRun?.result?.outputs?.[outputId] ?? null;
|
|
24
|
+
return {
|
|
25
|
+
boxId,
|
|
26
|
+
label: output.label,
|
|
27
|
+
capturedAt: new Date().toISOString(),
|
|
28
|
+
contentText: published?.text ?? `${row.title}\nNo published output has been generated yet.`,
|
|
29
|
+
contentJson: published?.json ?? null,
|
|
30
|
+
tools: []
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function createRuntimeContext(input) {
|
|
36
|
+
const services = {
|
|
37
|
+
entities: {
|
|
38
|
+
search: searchEntities
|
|
39
|
+
},
|
|
40
|
+
notes: {
|
|
41
|
+
create: createNote,
|
|
42
|
+
list: listNotes
|
|
43
|
+
},
|
|
44
|
+
movement: {
|
|
45
|
+
listPlaces: listMovementPlaces
|
|
46
|
+
},
|
|
47
|
+
health: {
|
|
48
|
+
getSleepViewData: getSleepViewData,
|
|
49
|
+
getFitnessViewData: getFitnessViewData
|
|
50
|
+
},
|
|
51
|
+
tasks: {
|
|
52
|
+
update: ((taskId, patch) => updateTask(taskId, patch, { source: "agent", actor: "Workbench" }))
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
actor: input?.actor ?? { userIds: null, source: "api" },
|
|
57
|
+
services,
|
|
58
|
+
routeParams: input?.routeParams,
|
|
59
|
+
filters: input?.filters,
|
|
60
|
+
now: new Date().toISOString()
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function toCatalogEntry(definition) {
|
|
64
|
+
if (!definition) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const toPortDefinition = (port) => ({
|
|
68
|
+
key: port.key,
|
|
69
|
+
label: port.label,
|
|
70
|
+
kind: port.kind,
|
|
71
|
+
required: port.required ?? false,
|
|
72
|
+
expandableKeys: "expandableKeys" in port ? (port.expandableKeys ?? []) : []
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
id: definition.id,
|
|
76
|
+
boxId: definition.id,
|
|
77
|
+
surfaceId: definition.surfaceId,
|
|
78
|
+
routePath: definition.routePath,
|
|
79
|
+
title: definition.title,
|
|
80
|
+
label: definition.title,
|
|
81
|
+
icon: definition.icon ?? null,
|
|
82
|
+
description: definition.description,
|
|
83
|
+
category: definition.category,
|
|
84
|
+
tags: definition.tags,
|
|
85
|
+
capabilityModes: [
|
|
86
|
+
"content",
|
|
87
|
+
...(definition.tools.length > 0 ? ["tool"] : [])
|
|
88
|
+
],
|
|
89
|
+
inputs: definition.inputs.map(toPortDefinition),
|
|
90
|
+
params: definition.params.map(toPortDefinition),
|
|
91
|
+
output: definition.output.map(toPortDefinition),
|
|
92
|
+
tools: definition.tools,
|
|
93
|
+
outputs: definition.output.map(toPortDefinition),
|
|
94
|
+
toolAdapters: definition.tools,
|
|
95
|
+
snapshotResolverKey: undefined
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function listForgeBoxCatalog() {
|
|
99
|
+
return getWorkbenchNodeCatalog();
|
|
100
|
+
}
|
|
101
|
+
export function getForgeBoxCatalogEntry(boxId) {
|
|
102
|
+
return toCatalogEntry(getWorkbenchNodeDefinition(boxId));
|
|
103
|
+
}
|
|
104
|
+
export function buildConnectorOutputCatalogEntry(input) {
|
|
105
|
+
return {
|
|
106
|
+
id: `connector-output:${input.outputId}`,
|
|
107
|
+
boxId: `connector-output:${input.outputId}`,
|
|
108
|
+
surfaceId: null,
|
|
109
|
+
routePath: `/workbench/${input.connectorId}`,
|
|
110
|
+
title: `${input.title} output`,
|
|
111
|
+
label: `${input.title} output`,
|
|
112
|
+
icon: null,
|
|
113
|
+
description: "Published Workbench output.",
|
|
114
|
+
category: "Workbench outputs",
|
|
115
|
+
tags: ["workbench", "output"],
|
|
116
|
+
capabilityModes: ["content"],
|
|
117
|
+
inputs: [],
|
|
118
|
+
params: [],
|
|
119
|
+
output: [
|
|
120
|
+
{
|
|
121
|
+
key: "primary",
|
|
122
|
+
label: "Published output",
|
|
123
|
+
kind: "content",
|
|
124
|
+
required: false,
|
|
125
|
+
expandableKeys: []
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
tools: [],
|
|
129
|
+
outputs: [
|
|
130
|
+
{
|
|
131
|
+
key: "primary",
|
|
132
|
+
label: "Published output",
|
|
133
|
+
kind: "content",
|
|
134
|
+
required: false,
|
|
135
|
+
expandableKeys: []
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
toolAdapters: []
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export function resolveForgeBoxSnapshot(boxId, contextInput, executionInput) {
|
|
142
|
+
if (boxId.startsWith("connector-output:")) {
|
|
143
|
+
return (createSnapshotForConnectorOutput(boxId) ?? {
|
|
144
|
+
boxId,
|
|
145
|
+
label: boxId,
|
|
146
|
+
capturedAt: new Date().toISOString(),
|
|
147
|
+
contentText: "This connector output has not been generated yet.",
|
|
148
|
+
contentJson: null,
|
|
149
|
+
tools: []
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const definition = getWorkbenchNodeDefinition(boxId);
|
|
153
|
+
if (!definition) {
|
|
154
|
+
return {
|
|
155
|
+
boxId,
|
|
156
|
+
label: boxId,
|
|
157
|
+
capturedAt: new Date().toISOString(),
|
|
158
|
+
contentText: "This Workbench node is not registered.",
|
|
159
|
+
contentJson: null,
|
|
160
|
+
tools: []
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const execution = definition.execute({
|
|
164
|
+
nodeId: boxId,
|
|
165
|
+
definition,
|
|
166
|
+
inputs: executionInput?.inputs ?? {},
|
|
167
|
+
params: executionInput?.params ?? {},
|
|
168
|
+
context: createRuntimeContext(contextInput)
|
|
169
|
+
});
|
|
170
|
+
if (execution instanceof Promise) {
|
|
171
|
+
throw new Error("Workbench box execution must be synchronous for snapshot resolution.");
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
boxId: definition.id,
|
|
175
|
+
label: definition.title,
|
|
176
|
+
capturedAt: new Date().toISOString(),
|
|
177
|
+
contentText: execution.primaryText,
|
|
178
|
+
contentJson: execution.payload,
|
|
179
|
+
tools: mapWorkbenchTools(definition.tools)
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
export function executeForgeBoxTool(boxId, toolKey, args, contextInput) {
|
|
183
|
+
const definition = getWorkbenchNodeDefinition(boxId);
|
|
184
|
+
if (!definition) {
|
|
185
|
+
throw new Error(`Unknown Forge box: ${boxId}`);
|
|
186
|
+
}
|
|
187
|
+
return executeCommonWorkbenchTool(createRuntimeContext(contextInput), definition, toolKey, args);
|
|
188
|
+
}
|