forge-openclaw-plugin 0.2.25 → 0.2.27
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/README.md +59 -3
- package/dist/assets/{board-VmF4FAfr.js → board-C6jCchjI.js} +3 -3
- package/dist/assets/{board-VmF4FAfr.js.map → board-C6jCchjI.js.map} +1 -1
- package/dist/assets/index-DVvS8iiU.css +1 -0
- package/dist/assets/index-zYB-9Dfo.js +85 -0
- package/dist/assets/index-zYB-9Dfo.js.map +1 -0
- package/dist/assets/knowledge-graph-layout.worker-DRvzPxhP.js +2 -0
- package/dist/assets/knowledge-graph-layout.worker-DRvzPxhP.js.map +1 -0
- package/dist/assets/{motion-DvkU14p-.js → motion-DFHrH2rd.js} +2 -2
- package/dist/assets/{motion-DvkU14p-.js.map → motion-DFHrH2rd.js.map} +1 -1
- package/dist/assets/{table-DgiPof9E.js → table-ZL7Di_u3.js} +2 -2
- package/dist/assets/{table-DgiPof9E.js.map → table-ZL7Di_u3.js.map} +1 -1
- package/dist/assets/{ui-nYfoC0Gq.js → ui-CKNPpz7q.js} +2 -2
- package/dist/assets/{ui-nYfoC0Gq.js.map → ui-CKNPpz7q.js.map} +1 -1
- package/dist/assets/vendor-DoNZuFhn.js +1247 -0
- package/dist/assets/vendor-DoNZuFhn.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 +67 -15
- package/dist/openclaw/plugin-entry-shared.js +24 -2
- package/dist/openclaw/plugin-sdk-types.d.ts +17 -0
- package/dist/openclaw/routes.d.ts +27 -0
- package/dist/openclaw/routes.js +16 -12
- 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/server/migrations/037_workbench_public_inputs_and_run_inputs.sql +5 -0
- package/dist/server/server/migrations/038_data_management_settings.sql +11 -0
- package/dist/server/server/migrations/039_life_force_and_action_points.sql +114 -0
- package/dist/server/server/migrations/040_screen_time_domain.sql +89 -0
- package/dist/server/server/migrations/041_companion_source_states.sql +21 -0
- package/dist/server/server/migrations/042_movement_boxes.sql +47 -0
- package/dist/server/server/migrations/043_movement_box_overlap_overrides.sql +26 -0
- package/dist/server/{app.js → server/src/app.js} +2112 -414
- package/dist/server/server/src/connectors/box-registry.js +223 -0
- package/dist/server/server/src/data-management-types.js +107 -0
- package/dist/server/{db.js → server/src/db.js} +72 -4
- package/dist/server/server/src/debug.js +19 -0
- package/dist/server/{demo-data.js → server/src/demo-data.js} +2 -2
- package/dist/server/{health.js → server/src/health.js} +702 -18
- package/dist/server/{managers → server/src/managers}/platform/llm-manager.js +7 -4
- package/dist/server/server/src/managers/platform/mock-workbench-provider.js +149 -0
- package/dist/server/{managers → server/src/managers}/platform/secrets-manager.js +18 -1
- package/dist/server/{managers → server/src/managers}/runtime.js +9 -0
- package/dist/server/{movement.js → server/src/movement.js} +1971 -112
- package/dist/server/{openapi.js → server/src/openapi.js} +491 -3
- package/dist/server/{psyche-types.js → server/src/psyche-types.js} +9 -1
- package/dist/server/{repositories → server/src/repositories}/activity-events.js +8 -0
- package/dist/server/{repositories → server/src/repositories}/ai-connectors.js +758 -47
- package/dist/server/{repositories → server/src/repositories}/calendar.js +1 -1
- package/dist/server/{repositories → server/src/repositories}/habits.js +37 -1
- package/dist/server/{repositories → server/src/repositories}/model-settings.js +13 -3
- package/dist/server/{repositories → server/src/repositories}/notes.js +3 -0
- package/dist/server/{repositories → server/src/repositories}/settings.js +431 -21
- package/dist/server/{repositories → server/src/repositories}/tasks.js +170 -10
- package/dist/server/server/src/runtime-data-root.js +82 -0
- package/dist/server/server/src/screen-time.js +802 -0
- package/dist/server/{services → server/src/services}/calendar-runtime.js +775 -58
- package/dist/server/server/src/services/data-management.js +788 -0
- package/dist/server/{services → server/src/services}/entity-crud.js +205 -2
- package/dist/server/server/src/services/google-calendar-oauth-config.js +176 -0
- package/dist/server/server/src/services/knowledge-graph.js +1455 -0
- package/dist/server/server/src/services/life-force-model.js +197 -0
- package/dist/server/server/src/services/life-force.js +1270 -0
- package/dist/server/server/src/services/psyche-observation-calendar.js +413 -0
- package/dist/server/{types.js → server/src/types.js} +420 -29
- package/dist/server/server/src/web.js +332 -0
- package/dist/server/src/components/customization/utility-widgets.js +439 -0
- package/dist/server/src/components/ui/info-tooltip.js +25 -0
- package/dist/server/src/components/workbench-boxes/calendar/calendar-boxes.js +78 -0
- package/dist/server/src/components/workbench-boxes/goals/goals-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/habits/habits-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/health/health-boxes.js +147 -0
- package/dist/server/src/components/workbench-boxes/insights/insights-boxes.js +50 -0
- package/dist/server/src/components/workbench-boxes/kanban/kanban-boxes.js +136 -0
- package/dist/server/src/components/workbench-boxes/movement/movement-boxes.js +47 -0
- package/dist/server/src/components/workbench-boxes/notes/notes-boxes.js +132 -0
- package/dist/server/src/components/workbench-boxes/overview/overview-boxes.js +65 -0
- package/dist/server/src/components/workbench-boxes/preferences/preferences-boxes.js +78 -0
- package/dist/server/src/components/workbench-boxes/projects/projects-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/psyche/psyche-boxes.js +88 -0
- package/dist/server/src/components/workbench-boxes/questionnaires/questionnaires-boxes.js +61 -0
- package/dist/server/src/components/workbench-boxes/review/review-boxes.js +53 -0
- package/dist/server/src/components/workbench-boxes/shared/define-workbench-box.js +6 -0
- package/dist/server/src/components/workbench-boxes/shared/generic-node-view.js +49 -0
- package/dist/server/src/components/workbench-boxes/strategies/strategies-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/tasks/tasks-boxes.js +76 -0
- package/dist/server/src/components/workbench-boxes/today/today-boxes.js +78 -0
- package/dist/server/src/components/workbench-boxes/wiki/wiki-boxes.js +60 -0
- package/dist/server/src/lib/api-error.js +37 -0
- package/dist/server/src/lib/api.js +2118 -0
- package/dist/server/src/lib/calendar-name-deduper.js +144 -0
- package/dist/server/src/lib/data-management-types.js +1 -0
- package/dist/server/src/lib/diagnostics.js +67 -0
- package/dist/server/src/lib/entity-visuals.js +279 -0
- package/dist/server/src/lib/knowledge-graph-types.js +276 -0
- package/dist/server/src/lib/knowledge-graph.js +470 -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 +238 -0
- package/dist/server/src/lib/snapshot-normalizer.js +416 -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/contracts.js +229 -0
- package/dist/server/src/lib/workbench/nodes.js +215 -0
- package/dist/server/src/lib/workbench/registry.js +120 -0
- package/dist/server/src/lib/workbench/runtime.js +397 -0
- package/dist/server/src/lib/workbench/tool-catalog.js +68 -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/server/migrations/037_workbench_public_inputs_and_run_inputs.sql +5 -0
- package/server/migrations/038_data_management_settings.sql +11 -0
- package/server/migrations/039_life_force_and_action_points.sql +114 -0
- package/server/migrations/040_screen_time_domain.sql +89 -0
- package/server/migrations/041_companion_source_states.sql +21 -0
- package/server/migrations/042_movement_boxes.sql +47 -0
- package/server/migrations/043_movement_box_overlap_overrides.sql +26 -0
- package/skills/forge-openclaw/SKILL.md +27 -11
- package/skills/forge-openclaw/entity_conversation_playbooks.md +411 -46
- package/skills/forge-openclaw/psyche_entity_playbooks.md +195 -20
- 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/services/psyche-observation-calendar.js +0 -46
- package/dist/server/web.js +0 -98
- /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/{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/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/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}/type-guards.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/{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}/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}/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}/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}/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.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,439 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
import { CalendarDays, CloudSun, ExternalLink, Music4, NotebookPen, Save, TimerReset } from "lucide-react";
|
|
5
|
+
import { createNote, createWikiPage } from "../../lib/api.js";
|
|
6
|
+
import { buildStaticWorkbenchExecution } from "../../lib/workbench/runtime.js";
|
|
7
|
+
import { createContextOutput, createNoteTool, createSummaryOutput } from "../../lib/workbench/contracts.js";
|
|
8
|
+
import { cn } from "../../lib/utils.js";
|
|
9
|
+
import { createGenericWorkbenchNodeView } from "../workbench-boxes/shared/generic-node-view.js";
|
|
10
|
+
function formatMonthGrid(baseDate) {
|
|
11
|
+
const start = new Date(baseDate.getFullYear(), baseDate.getMonth(), 1);
|
|
12
|
+
const startOffset = (start.getDay() + 6) % 7;
|
|
13
|
+
const cursor = new Date(start);
|
|
14
|
+
cursor.setDate(cursor.getDate() - startOffset);
|
|
15
|
+
return Array.from({ length: 35 }, (_, index) => {
|
|
16
|
+
const current = new Date(cursor);
|
|
17
|
+
current.setDate(cursor.getDate() + index);
|
|
18
|
+
return current;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function readStoredValue(key, fallback) {
|
|
22
|
+
if (typeof window === "undefined") {
|
|
23
|
+
return fallback;
|
|
24
|
+
}
|
|
25
|
+
return window.localStorage.getItem(key) ?? fallback;
|
|
26
|
+
}
|
|
27
|
+
function writeStoredValue(key, value) {
|
|
28
|
+
if (typeof window === "undefined") {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
window.localStorage.setItem(key, value);
|
|
32
|
+
}
|
|
33
|
+
export function TimeWidget({ compact }) {
|
|
34
|
+
const [now, setNow] = useState(() => new Date());
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const timer = window.setInterval(() => setNow(new Date()), 30_000);
|
|
37
|
+
return () => window.clearInterval(timer);
|
|
38
|
+
}, []);
|
|
39
|
+
return (_jsxs("div", { className: "flex h-full flex-col justify-between gap-4 rounded-[20px] bg-white/[0.03] p-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-white/45", children: [_jsx(TimerReset, { className: "size-4" }), _jsx("span", { className: "text-[12px] uppercase tracking-[0.16em]", children: "Local time" })] }), _jsx("div", { className: cn("font-display text-white", compact ? "text-3xl" : "text-5xl"), children: new Intl.DateTimeFormat(undefined, {
|
|
40
|
+
hour: "2-digit",
|
|
41
|
+
minute: "2-digit"
|
|
42
|
+
}).format(now) }), _jsx("div", { className: "text-sm text-white/58", children: new Intl.DateTimeFormat(undefined, {
|
|
43
|
+
weekday: "long",
|
|
44
|
+
month: "long",
|
|
45
|
+
day: "numeric"
|
|
46
|
+
}).format(now) })] }));
|
|
47
|
+
}
|
|
48
|
+
export function MiniCalendarWidget({ compact }) {
|
|
49
|
+
const today = new Date();
|
|
50
|
+
const days = useMemo(() => formatMonthGrid(today), [today]);
|
|
51
|
+
const weekdayLabels = compact
|
|
52
|
+
? ["M", "T", "W", "T", "F", "S", "S"]
|
|
53
|
+
: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
54
|
+
return (_jsxs("div", { className: "grid gap-3 rounded-[20px] bg-white/[0.03] p-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-white", children: [_jsx(CalendarDays, { className: "size-4 text-[var(--primary)]" }), new Intl.DateTimeFormat(undefined, {
|
|
55
|
+
month: "long",
|
|
56
|
+
year: "numeric"
|
|
57
|
+
}).format(today)] }), _jsx("div", { className: "text-[12px] text-white/45", children: compact ? "Mini" : "Month view" })] }), _jsxs("div", { className: "grid grid-cols-7 gap-1.5", children: [weekdayLabels.map((label) => (_jsx("div", { className: "text-center text-[11px] uppercase tracking-[0.14em] text-white/35", children: label }, label))), days.map((day) => {
|
|
58
|
+
const isCurrentMonth = day.getMonth() === today.getMonth();
|
|
59
|
+
const isToday = day.toDateString() === today.toDateString();
|
|
60
|
+
return (_jsx("div", { className: cn("flex min-h-9 items-center justify-center rounded-xl text-sm", isToday
|
|
61
|
+
? "bg-[var(--primary)] text-slate-950"
|
|
62
|
+
: isCurrentMonth
|
|
63
|
+
? "bg-white/[0.04] text-white/78"
|
|
64
|
+
: "bg-transparent text-white/24"), children: day.getDate() }, day.toISOString()));
|
|
65
|
+
})] })] }));
|
|
66
|
+
}
|
|
67
|
+
export function SpotifyWidget({ surfaceId }) {
|
|
68
|
+
const storageKey = `forge.utility.spotify.${surfaceId}`;
|
|
69
|
+
const [url, setUrl] = useState(() => readStoredValue(storageKey, "https://open.spotify.com/"));
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
writeStoredValue(storageKey, url);
|
|
72
|
+
}, [storageKey, url]);
|
|
73
|
+
return (_jsxs("div", { className: "grid h-full gap-3 rounded-[20px] bg-white/[0.03] p-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-white", children: [_jsx(Music4, { className: "size-4 text-[var(--secondary)]" }), _jsx("span", { className: "text-sm font-semibold", children: "Spotify link" })] }), _jsx("input", { value: url, onChange: (event) => setUrl(event.target.value), className: "w-full rounded-2xl border border-white/10 bg-white/[0.04] px-3 py-2.5 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.35)]", placeholder: "Paste a playlist, album, or artist URL" }), _jsxs("a", { href: url, target: "_blank", rel: "noreferrer", className: "inline-flex min-h-10 items-center justify-center gap-2 rounded-2xl bg-[rgba(78,222,163,0.14)] px-3 py-2 text-sm font-medium text-[var(--secondary)] transition hover:bg-[rgba(78,222,163,0.22)]", children: ["Open Spotify", _jsx(ExternalLink, { className: "size-4" })] })] }));
|
|
74
|
+
}
|
|
75
|
+
export function WeatherWidget({ compact }) {
|
|
76
|
+
const [weather, setWeather] = useState(null);
|
|
77
|
+
const [status, setStatus] = useState("Locating…");
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
80
|
+
setStatus("Location unavailable");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
let cancelled = false;
|
|
84
|
+
navigator.geolocation.getCurrentPosition(async (position) => {
|
|
85
|
+
try {
|
|
86
|
+
const response = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}¤t=temperature_2m,weather_code`);
|
|
87
|
+
const payload = (await response.json());
|
|
88
|
+
if (cancelled || !payload.current) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
setWeather({
|
|
92
|
+
temperature: Number(payload.current.temperature_2m ?? 0),
|
|
93
|
+
weatherCode: Number(payload.current.weather_code ?? 0)
|
|
94
|
+
});
|
|
95
|
+
setStatus("Live");
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
if (!cancelled) {
|
|
99
|
+
setStatus("Weather unavailable");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}, () => {
|
|
103
|
+
if (!cancelled) {
|
|
104
|
+
setStatus("Permission denied");
|
|
105
|
+
}
|
|
106
|
+
}, { maximumAge: 300000, timeout: 6000 });
|
|
107
|
+
return () => {
|
|
108
|
+
cancelled = true;
|
|
109
|
+
};
|
|
110
|
+
}, []);
|
|
111
|
+
return (_jsxs("div", { className: "flex h-full flex-col justify-between gap-4 rounded-[20px] bg-white/[0.03] p-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-white", children: [_jsx(CloudSun, { className: "size-4 text-[var(--tertiary)]" }), _jsx("span", { className: "text-sm font-semibold", children: "Weather" })] }), weather ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: cn("font-display text-white", compact ? "text-3xl" : "text-5xl"), children: [Math.round(weather.temperature), "\u00B0"] }), _jsxs("div", { className: "text-sm text-white/58", children: ["Code ", weather.weatherCode, " \u00B7 ", status] })] })) : (_jsx("div", { className: "text-sm text-white/58", children: status }))] }));
|
|
112
|
+
}
|
|
113
|
+
export function QuickCaptureWidget({ compact, defaultUserId }) {
|
|
114
|
+
const queryClient = useQueryClient();
|
|
115
|
+
const titleRef = useRef(null);
|
|
116
|
+
const contentRef = useRef(null);
|
|
117
|
+
const [title, setTitle] = useState("");
|
|
118
|
+
const [content, setContent] = useState("");
|
|
119
|
+
const noteMutation = useMutation({
|
|
120
|
+
mutationFn: async () => createNote({
|
|
121
|
+
contentMarkdown: `# ${title.trim() || "Quick note"}\n\n${content.trim()}`,
|
|
122
|
+
author: "Forge quick capture",
|
|
123
|
+
userId: defaultUserId ?? null,
|
|
124
|
+
links: []
|
|
125
|
+
}),
|
|
126
|
+
onSuccess: async () => {
|
|
127
|
+
setTitle("");
|
|
128
|
+
setContent("");
|
|
129
|
+
await queryClient.invalidateQueries({ queryKey: ["notes-index"] });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
const wikiMutation = useMutation({
|
|
133
|
+
mutationFn: async () => createWikiPage({
|
|
134
|
+
title: title.trim() || "Quick capture",
|
|
135
|
+
contentMarkdown: content.trim(),
|
|
136
|
+
summary: content.trim().slice(0, 180),
|
|
137
|
+
author: "Forge quick capture"
|
|
138
|
+
}),
|
|
139
|
+
onSuccess: async () => {
|
|
140
|
+
setTitle("");
|
|
141
|
+
setContent("");
|
|
142
|
+
await queryClient.invalidateQueries({ queryKey: ["wiki-pages"] });
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
function wrapSelection(prefix, suffix = prefix) {
|
|
146
|
+
const node = contentRef.current;
|
|
147
|
+
if (!node) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const start = node.selectionStart ?? 0;
|
|
151
|
+
const end = node.selectionEnd ?? 0;
|
|
152
|
+
const selected = content.slice(start, end);
|
|
153
|
+
const next = `${content.slice(0, start)}${prefix}${selected}${suffix}${content.slice(end)}`;
|
|
154
|
+
setContent(next);
|
|
155
|
+
requestAnimationFrame(() => {
|
|
156
|
+
node.focus();
|
|
157
|
+
node.selectionStart = start + prefix.length;
|
|
158
|
+
node.selectionEnd = end + prefix.length;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return (_jsxs("div", { className: "grid h-full min-h-0 gap-3 rounded-[20px] bg-white/[0.03] p-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-white", children: [_jsx(NotebookPen, { className: "size-4 text-[var(--primary)]" }), _jsx("span", { className: "text-sm font-semibold", children: "Quick capture" })] }), _jsx("input", { ref: titleRef, value: title, onChange: (event) => setTitle(event.target.value), className: "w-full rounded-2xl border border-white/10 bg-white/[0.04] px-3 py-2.5 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.35)]", placeholder: "Title" }), _jsx("div", { className: "flex flex-wrap gap-2", children: [
|
|
162
|
+
{ label: "B", action: () => wrapSelection("**") },
|
|
163
|
+
{ label: "I", action: () => wrapSelection("_") },
|
|
164
|
+
{ label: "H1", action: () => wrapSelection("# ", "") },
|
|
165
|
+
{ label: "[]", action: () => wrapSelection("- [ ] ", "") }
|
|
166
|
+
].map((tool) => (_jsx("button", { type: "button", className: "inline-flex min-h-8 items-center justify-center rounded-xl bg-white/[0.05] px-2.5 text-[12px] font-semibold text-white/72 transition hover:bg-white/[0.08] hover:text-white", onClick: tool.action, children: tool.label }, tool.label))) }), _jsx("textarea", { ref: contentRef, value: content, onChange: (event) => setContent(event.target.value), className: cn("min-h-0 w-full rounded-[20px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.35)]", compact ? "h-28" : "h-40"), placeholder: "Write a quick note or rough wiki draft" }), _jsxs("div", { className: "grid gap-2 sm:grid-cols-2", children: [_jsxs("button", { type: "button", className: "inline-flex min-h-10 items-center justify-center gap-2 rounded-2xl bg-[rgba(192,193,255,0.16)] px-3 py-2 text-sm font-medium text-[var(--primary)] transition hover:bg-[rgba(192,193,255,0.24)] disabled:opacity-50", disabled: !content.trim() || noteMutation.isPending, onClick: () => noteMutation.mutate(), children: [_jsx(Save, { className: "size-4" }), "Save as note"] }), _jsxs("button", { type: "button", className: "inline-flex min-h-10 items-center justify-center gap-2 rounded-2xl bg-[rgba(255,185,95,0.16)] px-3 py-2 text-sm font-medium text-[var(--tertiary)] transition hover:bg-[rgba(255,185,95,0.24)] disabled:opacity-50", disabled: !content.trim() || wikiMutation.isPending, onClick: () => wikiMutation.mutate(), children: [_jsx(NotebookPen, { className: "size-4" }), "Save as wiki"] })] })] }));
|
|
167
|
+
}
|
|
168
|
+
const timeWidgetDefinition = {
|
|
169
|
+
id: "surface:utility:time",
|
|
170
|
+
surfaceId: "utility",
|
|
171
|
+
routePath: null,
|
|
172
|
+
title: "Clock",
|
|
173
|
+
icon: "timer",
|
|
174
|
+
description: "Live local time widget.",
|
|
175
|
+
category: "Utilities",
|
|
176
|
+
tags: ["utility", "clock"],
|
|
177
|
+
inputs: [],
|
|
178
|
+
params: [],
|
|
179
|
+
output: [
|
|
180
|
+
createSummaryOutput({
|
|
181
|
+
label: "Current time",
|
|
182
|
+
description: "Formatted local time string published by the clock widget."
|
|
183
|
+
}),
|
|
184
|
+
createContextOutput({
|
|
185
|
+
key: "clock",
|
|
186
|
+
label: "Clock state",
|
|
187
|
+
description: "Structured clock state including the current ISO timestamp.",
|
|
188
|
+
modelName: "ForgeClockState"
|
|
189
|
+
})
|
|
190
|
+
],
|
|
191
|
+
tools: [],
|
|
192
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
193
|
+
title: "Clock",
|
|
194
|
+
description: "Live local time widget.",
|
|
195
|
+
inputs: [],
|
|
196
|
+
params: [],
|
|
197
|
+
output: [
|
|
198
|
+
createSummaryOutput({
|
|
199
|
+
label: "Current time",
|
|
200
|
+
description: "Formatted local time string published by the clock widget."
|
|
201
|
+
}),
|
|
202
|
+
createContextOutput({
|
|
203
|
+
key: "clock",
|
|
204
|
+
label: "Clock state",
|
|
205
|
+
description: "Structured clock state including the current ISO timestamp.",
|
|
206
|
+
modelName: "ForgeClockState"
|
|
207
|
+
})
|
|
208
|
+
],
|
|
209
|
+
tools: []
|
|
210
|
+
}),
|
|
211
|
+
WebView: TimeWidget,
|
|
212
|
+
execute: (input) => buildStaticWorkbenchExecution(input, {
|
|
213
|
+
clock: {
|
|
214
|
+
now: input.context.now
|
|
215
|
+
}
|
|
216
|
+
}, new Intl.DateTimeFormat(undefined, {
|
|
217
|
+
hour: "2-digit",
|
|
218
|
+
minute: "2-digit"
|
|
219
|
+
}).format(new Date(input.context.now)))
|
|
220
|
+
};
|
|
221
|
+
TimeWidget.workbench = timeWidgetDefinition;
|
|
222
|
+
const calendarWidgetDefinition = {
|
|
223
|
+
id: "surface:utility:mini-calendar",
|
|
224
|
+
surfaceId: "utility",
|
|
225
|
+
routePath: null,
|
|
226
|
+
title: "Mini calendar",
|
|
227
|
+
icon: "calendar",
|
|
228
|
+
description: "Compact month calendar widget.",
|
|
229
|
+
category: "Utilities",
|
|
230
|
+
tags: ["utility", "calendar"],
|
|
231
|
+
inputs: [],
|
|
232
|
+
params: [],
|
|
233
|
+
output: [
|
|
234
|
+
createSummaryOutput({
|
|
235
|
+
label: "Month view",
|
|
236
|
+
description: "Summary of the compact month calendar widget."
|
|
237
|
+
}),
|
|
238
|
+
createContextOutput({
|
|
239
|
+
key: "calendarView",
|
|
240
|
+
label: "Calendar view",
|
|
241
|
+
description: "Structured mini-calendar state including the current month anchor.",
|
|
242
|
+
modelName: "ForgeMiniCalendarView"
|
|
243
|
+
})
|
|
244
|
+
],
|
|
245
|
+
tools: [],
|
|
246
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
247
|
+
title: "Mini calendar",
|
|
248
|
+
description: "Compact month calendar widget.",
|
|
249
|
+
inputs: [],
|
|
250
|
+
params: [],
|
|
251
|
+
output: [
|
|
252
|
+
createSummaryOutput({
|
|
253
|
+
label: "Month view",
|
|
254
|
+
description: "Summary of the compact month calendar widget."
|
|
255
|
+
}),
|
|
256
|
+
createContextOutput({
|
|
257
|
+
key: "calendarView",
|
|
258
|
+
label: "Calendar view",
|
|
259
|
+
description: "Structured mini-calendar state including the current month anchor.",
|
|
260
|
+
modelName: "ForgeMiniCalendarView"
|
|
261
|
+
})
|
|
262
|
+
],
|
|
263
|
+
tools: []
|
|
264
|
+
}),
|
|
265
|
+
WebView: MiniCalendarWidget,
|
|
266
|
+
execute: (input) => buildStaticWorkbenchExecution(input, {
|
|
267
|
+
calendarView: {
|
|
268
|
+
now: input.context.now
|
|
269
|
+
}
|
|
270
|
+
}, "Compact month calendar")
|
|
271
|
+
};
|
|
272
|
+
MiniCalendarWidget.workbench = calendarWidgetDefinition;
|
|
273
|
+
const spotifyWidgetDefinition = {
|
|
274
|
+
id: "surface:utility:spotify",
|
|
275
|
+
surfaceId: "utility",
|
|
276
|
+
routePath: null,
|
|
277
|
+
title: "Spotify",
|
|
278
|
+
icon: "music",
|
|
279
|
+
description: "Pinned music link widget.",
|
|
280
|
+
category: "Utilities",
|
|
281
|
+
tags: ["utility", "spotify"],
|
|
282
|
+
inputs: [
|
|
283
|
+
{
|
|
284
|
+
key: "surfaceId",
|
|
285
|
+
label: "Surface id",
|
|
286
|
+
kind: "text",
|
|
287
|
+
required: false
|
|
288
|
+
}
|
|
289
|
+
],
|
|
290
|
+
params: [],
|
|
291
|
+
output: [
|
|
292
|
+
createSummaryOutput({
|
|
293
|
+
label: "Spotify link",
|
|
294
|
+
description: "Summary of the pinned music link widget."
|
|
295
|
+
}),
|
|
296
|
+
createContextOutput({
|
|
297
|
+
key: "spotifyLink",
|
|
298
|
+
label: "Spotify state",
|
|
299
|
+
description: "Structured Spotify widget state and pinned surface context.",
|
|
300
|
+
modelName: "ForgeSpotifyWidgetState"
|
|
301
|
+
})
|
|
302
|
+
],
|
|
303
|
+
tools: [],
|
|
304
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
305
|
+
title: "Spotify",
|
|
306
|
+
description: "Pinned music link widget.",
|
|
307
|
+
inputs: [{ key: "surfaceId", label: "Surface id", kind: "text" }],
|
|
308
|
+
params: [],
|
|
309
|
+
output: [
|
|
310
|
+
createSummaryOutput({
|
|
311
|
+
label: "Spotify link",
|
|
312
|
+
description: "Summary of the pinned music link widget."
|
|
313
|
+
}),
|
|
314
|
+
createContextOutput({
|
|
315
|
+
key: "spotifyLink",
|
|
316
|
+
label: "Spotify state",
|
|
317
|
+
description: "Structured Spotify widget state and pinned surface context.",
|
|
318
|
+
modelName: "ForgeSpotifyWidgetState"
|
|
319
|
+
})
|
|
320
|
+
],
|
|
321
|
+
tools: []
|
|
322
|
+
}),
|
|
323
|
+
WebView: SpotifyWidget,
|
|
324
|
+
execute: (input) => buildStaticWorkbenchExecution(input, {
|
|
325
|
+
spotifyLink: {
|
|
326
|
+
surfaceId: input.inputs.surfaceId ?? null
|
|
327
|
+
}
|
|
328
|
+
}, "Pinned Spotify link")
|
|
329
|
+
};
|
|
330
|
+
SpotifyWidget.workbench = spotifyWidgetDefinition;
|
|
331
|
+
const weatherWidgetDefinition = {
|
|
332
|
+
id: "surface:utility:weather",
|
|
333
|
+
surfaceId: "utility",
|
|
334
|
+
routePath: null,
|
|
335
|
+
title: "Weather",
|
|
336
|
+
icon: "weather",
|
|
337
|
+
description: "Location-aware weather widget.",
|
|
338
|
+
category: "Utilities",
|
|
339
|
+
tags: ["utility", "weather"],
|
|
340
|
+
inputs: [],
|
|
341
|
+
params: [],
|
|
342
|
+
output: [
|
|
343
|
+
createSummaryOutput({
|
|
344
|
+
label: "Weather summary",
|
|
345
|
+
description: "Summary of the weather widget state."
|
|
346
|
+
}),
|
|
347
|
+
createContextOutput({
|
|
348
|
+
key: "weather",
|
|
349
|
+
label: "Weather payload",
|
|
350
|
+
description: "Structured weather widget payload.",
|
|
351
|
+
modelName: "ForgeWeatherWidgetState"
|
|
352
|
+
})
|
|
353
|
+
],
|
|
354
|
+
tools: [],
|
|
355
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
356
|
+
title: "Weather",
|
|
357
|
+
description: "Location-aware weather widget.",
|
|
358
|
+
inputs: [],
|
|
359
|
+
params: [],
|
|
360
|
+
output: [
|
|
361
|
+
createSummaryOutput({
|
|
362
|
+
label: "Weather summary",
|
|
363
|
+
description: "Summary of the weather widget state."
|
|
364
|
+
}),
|
|
365
|
+
createContextOutput({
|
|
366
|
+
key: "weather",
|
|
367
|
+
label: "Weather payload",
|
|
368
|
+
description: "Structured weather widget payload.",
|
|
369
|
+
modelName: "ForgeWeatherWidgetState"
|
|
370
|
+
})
|
|
371
|
+
],
|
|
372
|
+
tools: []
|
|
373
|
+
}),
|
|
374
|
+
WebView: WeatherWidget,
|
|
375
|
+
execute: (input) => buildStaticWorkbenchExecution(input, { weather: null }, "Weather widget")
|
|
376
|
+
};
|
|
377
|
+
WeatherWidget.workbench = weatherWidgetDefinition;
|
|
378
|
+
const quickCaptureWidgetDefinition = {
|
|
379
|
+
id: "surface:utility:quick-capture",
|
|
380
|
+
surfaceId: "utility",
|
|
381
|
+
routePath: null,
|
|
382
|
+
title: "Quick capture",
|
|
383
|
+
icon: "capture",
|
|
384
|
+
description: "Draft a quick note or wiki page.",
|
|
385
|
+
category: "Capture",
|
|
386
|
+
tags: ["capture", "notes"],
|
|
387
|
+
inputs: [
|
|
388
|
+
{
|
|
389
|
+
key: "defaultUserId",
|
|
390
|
+
label: "Default user id",
|
|
391
|
+
kind: "text",
|
|
392
|
+
required: false
|
|
393
|
+
}
|
|
394
|
+
],
|
|
395
|
+
params: [],
|
|
396
|
+
output: [
|
|
397
|
+
createSummaryOutput({
|
|
398
|
+
label: "Draft summary",
|
|
399
|
+
description: "Summary of the quick-capture draft state."
|
|
400
|
+
}),
|
|
401
|
+
createContextOutput({
|
|
402
|
+
key: "draft",
|
|
403
|
+
label: "Draft context",
|
|
404
|
+
description: "Structured quick-capture draft context.",
|
|
405
|
+
modelName: "ForgeQuickCaptureDraft"
|
|
406
|
+
})
|
|
407
|
+
],
|
|
408
|
+
tools: [
|
|
409
|
+
createNoteTool("Create a Forge evidence note from captured markdown.")
|
|
410
|
+
],
|
|
411
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
412
|
+
title: "Quick capture",
|
|
413
|
+
description: "Draft a quick note or wiki page.",
|
|
414
|
+
inputs: [{ key: "defaultUserId", label: "Default user id", kind: "text" }],
|
|
415
|
+
params: [],
|
|
416
|
+
output: [
|
|
417
|
+
createSummaryOutput({
|
|
418
|
+
label: "Draft summary",
|
|
419
|
+
description: "Summary of the quick-capture draft state."
|
|
420
|
+
}),
|
|
421
|
+
createContextOutput({
|
|
422
|
+
key: "draft",
|
|
423
|
+
label: "Draft context",
|
|
424
|
+
description: "Structured quick-capture draft context.",
|
|
425
|
+
modelName: "ForgeQuickCaptureDraft"
|
|
426
|
+
})
|
|
427
|
+
],
|
|
428
|
+
tools: [
|
|
429
|
+
createNoteTool("Create a Forge evidence note from captured markdown.")
|
|
430
|
+
]
|
|
431
|
+
}),
|
|
432
|
+
WebView: QuickCaptureWidget,
|
|
433
|
+
execute: (input) => buildStaticWorkbenchExecution(input, {
|
|
434
|
+
draft: {
|
|
435
|
+
defaultUserId: input.inputs.defaultUserId ?? null
|
|
436
|
+
}
|
|
437
|
+
}, "Quick capture can draft notes and wiki pages.")
|
|
438
|
+
};
|
|
439
|
+
QuickCaptureWidget.workbench = quickCaptureWidgetDefinition;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
3
|
+
import { CircleHelp } from "lucide-react";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
export function FieldHint({ children, className }) {
|
|
6
|
+
return _jsx("div", { className: cn("text-sm leading-6 text-white/50", className), children: children });
|
|
7
|
+
}
|
|
8
|
+
export function InfoTooltip({ content, label = "Explain this field", className }) {
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const containerRef = useRef(null);
|
|
11
|
+
const tooltipId = useId();
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!open) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const handlePointerDown = (event) => {
|
|
17
|
+
if (!containerRef.current?.contains(event.target)) {
|
|
18
|
+
setOpen(false);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
22
|
+
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
23
|
+
}, [open]);
|
|
24
|
+
return (_jsxs("span", { ref: containerRef, className: cn("relative inline-flex items-center", className), onMouseEnter: () => setOpen(true), onMouseLeave: () => setOpen(false), children: [_jsx("button", { type: "button", "aria-label": label, "aria-describedby": open ? tooltipId : undefined, "aria-expanded": open, className: "inline-flex size-5 items-center justify-center rounded-full text-white/42 transition hover:bg-white/[0.06] hover:text-white/78 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgba(192,193,255,0.35)]", onFocus: () => setOpen(true), onBlur: () => setOpen(false), onClick: () => setOpen((current) => !current), children: _jsx(CircleHelp, { className: "size-3.5" }) }), _jsx("span", { id: tooltipId, role: "tooltip", className: cn("pointer-events-none absolute right-0 top-[calc(100%+0.55rem)] z-40 w-[min(16rem,calc(100vw-2.5rem))] max-w-[calc(100vw-2.5rem)] rounded-[18px] border border-white/8 bg-[rgba(12,17,30,0.96)] px-3 py-2.5 text-sm leading-6 text-white/74 shadow-[0_18px_48px_rgba(3,8,18,0.42)] transition", open ? "translate-y-0 opacity-100" : "translate-y-1 opacity-0"), children: content })] }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { buildSearchWorkbenchExecution, buildStaticWorkbenchExecution } from "../../../lib/workbench/runtime.js";
|
|
3
|
+
import { createSearchEntitiesTool, createSearchInputs, createSearchOutputs, createSearchParams, createSummaryOutput } from "../../../lib/workbench/contracts.js";
|
|
4
|
+
import { createGenericWorkbenchNodeView } from "../shared/generic-node-view.js";
|
|
5
|
+
import { defineWorkbenchBox } from "../shared/define-workbench-box.js";
|
|
6
|
+
function Slot({ children }) {
|
|
7
|
+
return _jsx(_Fragment, { children: children });
|
|
8
|
+
}
|
|
9
|
+
function defineCalendarBox(id, title, description, tags, execute, output, tools, options) {
|
|
10
|
+
const inputs = options?.inputs ?? [];
|
|
11
|
+
const params = options?.params ?? [];
|
|
12
|
+
return defineWorkbenchBox(Slot, {
|
|
13
|
+
id,
|
|
14
|
+
surfaceId: "calendar",
|
|
15
|
+
routePath: "/calendar",
|
|
16
|
+
title,
|
|
17
|
+
icon: "calendar",
|
|
18
|
+
description,
|
|
19
|
+
category: "Calendar",
|
|
20
|
+
tags,
|
|
21
|
+
inputs,
|
|
22
|
+
params,
|
|
23
|
+
output,
|
|
24
|
+
tools,
|
|
25
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
inputs,
|
|
29
|
+
params,
|
|
30
|
+
output,
|
|
31
|
+
tools
|
|
32
|
+
}),
|
|
33
|
+
execute
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export const CalendarOverviewBox = defineCalendarBox("surface:calendar:overview", "Calendar overview", "Main calendar surface for mirrored events, work blocks, and planned timeboxes.", ["calendar", "overview"], (input) => buildStaticWorkbenchExecution(input, {
|
|
37
|
+
surfaces: ["events", "work_blocks", "timeboxes"]
|
|
38
|
+
}, "Calendar overview spanning mirrored events, work blocks, and timeboxes."), [createSummaryOutput({ label: "Calendar summary", description: "Summary of mirrored events, work blocks, and timeboxes." })], []);
|
|
39
|
+
export const CalendarEventsBox = defineCalendarBox("surface:calendar:events", "Calendar events", "Mirrored calendar events and Forge-managed calendar records.", ["calendar", "events", "mirrored"], (input) => buildSearchWorkbenchExecution(input, {
|
|
40
|
+
query: "",
|
|
41
|
+
entityTypes: ["calendar_event"],
|
|
42
|
+
limit: 20
|
|
43
|
+
}), createSearchOutputs({
|
|
44
|
+
itemKind: "calendar_event",
|
|
45
|
+
itemLabel: "Calendar event"
|
|
46
|
+
}), [createSearchEntitiesTool("Search calendar-backed Forge entities and planning records.")], {
|
|
47
|
+
inputs: createSearchInputs({
|
|
48
|
+
itemKind: "calendar_event",
|
|
49
|
+
itemLabel: "Calendar event",
|
|
50
|
+
defaultEntityTypes: ["calendar_event"],
|
|
51
|
+
defaultLimit: 20
|
|
52
|
+
}),
|
|
53
|
+
params: createSearchParams({
|
|
54
|
+
itemKind: "calendar_event",
|
|
55
|
+
defaultEntityTypes: ["calendar_event"],
|
|
56
|
+
defaultLimit: 20
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
export const CalendarPlanningBox = defineCalendarBox("surface:calendar:planning", "Planning blocks", "Planned task timeboxes and reusable work block templates.", ["calendar", "planning", "timeboxes"], (input) => buildSearchWorkbenchExecution(input, {
|
|
60
|
+
query: "",
|
|
61
|
+
entityTypes: ["task_timebox", "work_block_template"],
|
|
62
|
+
limit: 20
|
|
63
|
+
}), createSearchOutputs({
|
|
64
|
+
itemKind: "calendar_plan",
|
|
65
|
+
itemLabel: "Planning record"
|
|
66
|
+
}), [createSearchEntitiesTool("Search calendar-backed Forge entities and planning records.")], {
|
|
67
|
+
inputs: createSearchInputs({
|
|
68
|
+
itemKind: "calendar_plan",
|
|
69
|
+
itemLabel: "Planning record",
|
|
70
|
+
defaultEntityTypes: ["task_timebox", "work_block_template"],
|
|
71
|
+
defaultLimit: 20
|
|
72
|
+
}),
|
|
73
|
+
params: createSearchParams({
|
|
74
|
+
itemKind: "calendar_plan",
|
|
75
|
+
defaultEntityTypes: ["task_timebox", "work_block_template"],
|
|
76
|
+
defaultLimit: 20
|
|
77
|
+
})
|
|
78
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { buildSearchWorkbenchExecution, buildStaticWorkbenchExecution } from "../../../lib/workbench/runtime.js";
|
|
3
|
+
import { createSearchEntitiesTool, createSearchInputs, createSearchOutputs, createSearchParams, createSummaryOutput } from "../../../lib/workbench/contracts.js";
|
|
4
|
+
import { createGenericWorkbenchNodeView } from "../shared/generic-node-view.js";
|
|
5
|
+
import { defineWorkbenchBox } from "../shared/define-workbench-box.js";
|
|
6
|
+
function Slot({ children }) {
|
|
7
|
+
return _jsx(_Fragment, { children: children });
|
|
8
|
+
}
|
|
9
|
+
function defineGoalBox(id, title, description, tags, execute, output, tools = [], options) {
|
|
10
|
+
const inputs = options?.inputs ?? [];
|
|
11
|
+
const params = options?.params ?? [];
|
|
12
|
+
return defineWorkbenchBox(Slot, {
|
|
13
|
+
id,
|
|
14
|
+
surfaceId: "goals",
|
|
15
|
+
routePath: "/goals",
|
|
16
|
+
title,
|
|
17
|
+
icon: "goal",
|
|
18
|
+
description,
|
|
19
|
+
category: "Goals",
|
|
20
|
+
tags,
|
|
21
|
+
inputs,
|
|
22
|
+
params,
|
|
23
|
+
output,
|
|
24
|
+
tools,
|
|
25
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
inputs,
|
|
29
|
+
params,
|
|
30
|
+
output,
|
|
31
|
+
tools
|
|
32
|
+
}),
|
|
33
|
+
execute
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export const GoalsHeroBox = defineGoalBox("surface:goals:hero", "Goals hero", "Goals page header and long-horizon direction context.", ["goals", "hero"], (input) => buildStaticWorkbenchExecution(input, null, "Goals page header."), [createSummaryOutput({ label: "Goals summary", description: "High-level goals page framing." })]);
|
|
37
|
+
export const GoalsSearchResultsBox = defineGoalBox("surface:goals:search-results", "Goals list and results", "Goal browser, linked context, and search results.", ["goals", "search"], (input) => buildSearchWorkbenchExecution(input, {
|
|
38
|
+
query: "",
|
|
39
|
+
entityTypes: ["goal"],
|
|
40
|
+
limit: 20
|
|
41
|
+
}), createSearchOutputs({
|
|
42
|
+
itemKind: "goal",
|
|
43
|
+
itemLabel: "Goal"
|
|
44
|
+
}), [createSearchEntitiesTool("Search goal entities by query and entity types.")], {
|
|
45
|
+
inputs: createSearchInputs({
|
|
46
|
+
itemKind: "goal",
|
|
47
|
+
itemLabel: "Goal",
|
|
48
|
+
defaultEntityTypes: ["goal"],
|
|
49
|
+
defaultLimit: 20
|
|
50
|
+
}),
|
|
51
|
+
params: createSearchParams({
|
|
52
|
+
itemKind: "goal",
|
|
53
|
+
defaultEntityTypes: ["goal"],
|
|
54
|
+
defaultLimit: 20
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
export const GoalsSummaryBox = defineGoalBox("surface:goals:summary", "Goals summary", "Goal collection summary and state context.", ["goals", "summary"], (input) => buildStaticWorkbenchExecution(input, null, "Goal collection summary."), [
|
|
58
|
+
createSummaryOutput({
|
|
59
|
+
label: "Goals summary",
|
|
60
|
+
description: "Summary of the goal collection and its current state."
|
|
61
|
+
})
|
|
62
|
+
]);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { buildSearchWorkbenchExecution, buildStaticWorkbenchExecution } from "../../../lib/workbench/runtime.js";
|
|
3
|
+
import { createSearchEntitiesTool, createSearchInputs, createSearchOutputs, createSearchParams, createSummaryOutput } from "../../../lib/workbench/contracts.js";
|
|
4
|
+
import { createGenericWorkbenchNodeView } from "../shared/generic-node-view.js";
|
|
5
|
+
import { defineWorkbenchBox } from "../shared/define-workbench-box.js";
|
|
6
|
+
function Slot({ children }) {
|
|
7
|
+
return _jsx(_Fragment, { children: children });
|
|
8
|
+
}
|
|
9
|
+
function defineHabitBox(id, title, description, tags, execute, output, tools = [], options) {
|
|
10
|
+
const inputs = options?.inputs ?? [];
|
|
11
|
+
const params = options?.params ?? [];
|
|
12
|
+
return defineWorkbenchBox(Slot, {
|
|
13
|
+
id,
|
|
14
|
+
surfaceId: "habits",
|
|
15
|
+
routePath: "/habits",
|
|
16
|
+
title,
|
|
17
|
+
icon: "habit",
|
|
18
|
+
description,
|
|
19
|
+
category: "Habits",
|
|
20
|
+
tags,
|
|
21
|
+
inputs,
|
|
22
|
+
params,
|
|
23
|
+
output,
|
|
24
|
+
tools,
|
|
25
|
+
NodeView: createGenericWorkbenchNodeView({
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
inputs,
|
|
29
|
+
params,
|
|
30
|
+
output,
|
|
31
|
+
tools
|
|
32
|
+
}),
|
|
33
|
+
execute
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export const HabitsHeroBox = defineHabitBox("surface:habits:hero", "Habits hero", "Habits page header and recurring execution context.", ["habits", "hero"], (input) => buildStaticWorkbenchExecution(input, null, "Habits page header."), [createSummaryOutput({ label: "Habits summary", description: "High-level habits page framing." })]);
|
|
37
|
+
export const HabitsSearchResultsBox = defineHabitBox("surface:habits:search-results", "Habits list and results", "Habit browser, due habits, and recurring check-in context.", ["habits", "search", "check-ins"], (input) => buildSearchWorkbenchExecution(input, {
|
|
38
|
+
query: "",
|
|
39
|
+
entityTypes: ["habit"],
|
|
40
|
+
limit: 20
|
|
41
|
+
}), createSearchOutputs({
|
|
42
|
+
itemKind: "habit",
|
|
43
|
+
itemLabel: "Habit"
|
|
44
|
+
}), [createSearchEntitiesTool("Search habit entities by query and entity types.")], {
|
|
45
|
+
inputs: createSearchInputs({
|
|
46
|
+
itemKind: "habit",
|
|
47
|
+
itemLabel: "Habit",
|
|
48
|
+
defaultEntityTypes: ["habit"],
|
|
49
|
+
defaultLimit: 20
|
|
50
|
+
}),
|
|
51
|
+
params: createSearchParams({
|
|
52
|
+
itemKind: "habit",
|
|
53
|
+
defaultEntityTypes: ["habit"],
|
|
54
|
+
defaultLimit: 20
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
export const HabitsSummaryBox = defineHabitBox("surface:habits:summary", "Habits summary", "Habit streaks, due state, and collection-level rhythm context.", ["habits", "summary", "streaks"], (input) => buildStaticWorkbenchExecution(input, null, "Habit collection summary."), [
|
|
58
|
+
createSummaryOutput({
|
|
59
|
+
label: "Habit summary",
|
|
60
|
+
description: "Summary of habit streaks, due state, and collection rhythm."
|
|
61
|
+
})
|
|
62
|
+
]);
|