forge-openclaw-plugin 0.2.93 → 0.2.96

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/index.html CHANGED
@@ -13,14 +13,14 @@
13
13
  />
14
14
  <link rel="icon" type="image/png" href="/forge/assets/favicon-BCHm9dUV.ico" />
15
15
  <link rel="alternate icon" href="/forge/assets/favicon-BCHm9dUV.ico" />
16
- <script type="module" crossorigin src="/forge/assets/index-BNvUaA6y.js"></script>
17
- <link rel="modulepreload" crossorigin href="/forge/assets/vendor-BVU0cZC9.js">
18
- <link rel="modulepreload" crossorigin href="/forge/assets/board-DKxKOwax.js">
19
- <link rel="modulepreload" crossorigin href="/forge/assets/ui-3Wd4pVaA.js">
20
- <link rel="modulepreload" crossorigin href="/forge/assets/motion-CM4AfIqo.js">
21
- <link rel="modulepreload" crossorigin href="/forge/assets/table-BUeQ9wzR.js">
16
+ <script type="module" crossorigin src="/forge/assets/index-lOGIgdyP.js"></script>
17
+ <link rel="modulepreload" crossorigin href="/forge/assets/vendor-BS9OPVNh.js">
18
+ <link rel="modulepreload" crossorigin href="/forge/assets/board-D1HbyD4u.js">
19
+ <link rel="modulepreload" crossorigin href="/forge/assets/ui-DikPZj8S.js">
20
+ <link rel="modulepreload" crossorigin href="/forge/assets/motion-D2OqILg_.js">
21
+ <link rel="modulepreload" crossorigin href="/forge/assets/table-YWWjPjC_.js">
22
22
  <link rel="stylesheet" crossorigin href="/forge/assets/vendor-B-Lq_OG3.css">
23
- <link rel="stylesheet" crossorigin href="/forge/assets/index-NqIbz_lv.css">
23
+ <link rel="stylesheet" crossorigin href="/forge/assets/index-5w2YJv5G.css">
24
24
  </head>
25
25
  <body class="bg-canvas text-ink antialiased">
26
26
  <div id="root"></div>
@@ -30,6 +30,7 @@ export const FORGE_SUPPORTED_PLUGIN_API_ROUTES = [
30
30
  { method: "GET", path: "/api/v1/health/sleep", purpose: "health" },
31
31
  { method: "PATCH", path: "/api/v1/health/sleep/:id", purpose: "health" },
32
32
  { method: "GET", path: "/api/v1/health/fitness", purpose: "health" },
33
+ { method: "GET", path: "/api/v1/health/training-load", purpose: "health" },
33
34
  { method: "PATCH", path: "/api/v1/health/workouts/:id", purpose: "health" },
34
35
  { method: "GET", path: "/api/v1/movement/day", purpose: "movement" },
35
36
  { method: "GET", path: "/api/v1/movement/month", purpose: "movement" },
@@ -176,6 +176,11 @@ export const FORGE_PLUGIN_ROUTE_GROUPS = [
176
176
  upstreamPath: "/api/v1/health/fitness",
177
177
  target: (_match, url) => passthroughSearch("/api/v1/health/fitness", url)
178
178
  }),
179
+ exact("/forge/v1/health/training-load", {
180
+ method: "GET",
181
+ upstreamPath: "/api/v1/health/training-load",
182
+ target: (_match, url) => passthroughSearch("/api/v1/health/training-load", url)
183
+ }),
179
184
  {
180
185
  path: "/forge/v1/movement",
181
186
  match: "prefix",
@@ -752,6 +752,13 @@ export function registerForgePluginTools(api, config) {
752
752
  parameters: scopedReadSchema,
753
753
  path: (params) => withUserIds("/api/v1/health/fitness", params.userIds)
754
754
  });
755
+ registerReadTool(api, config, {
756
+ name: "forge_get_training_load_overview",
757
+ label: "Forge Training Load Overview",
758
+ description: "Read the cardiovascular training-load surface with acute/chronic load, HR zone distribution, weekly intensity targets, and data-quality flags.",
759
+ parameters: scopedReadSchema,
760
+ path: (params) => withUserIds("/api/v1/health/training-load", params.userIds)
761
+ });
755
762
  api.registerTool({
756
763
  name: "forge_update_sleep_session",
757
764
  label: "Forge Update Sleep Session",
@@ -66,7 +66,7 @@ import { registerWebRoutes } from "./web.js";
66
66
  import { createManagerRuntime } from "./managers/runtime.js";
67
67
  import { isManagerError } from "./managers/type-guards.js";
68
68
  import { buildCompanionPairingTransport, getCompanionIrohStatus, stopCompanionIroh } from "./services/companion-iroh.js";
69
- import { createCompanionPairingSession, createCompanionPairingSessionSchema, createSleepSession, createSleepSessionSchema, createWorkoutSession, createWorkoutSessionSchema, deleteSleepSession, deleteWorkoutSession, getCompanionPairingSessionById, getCompanionOverview, getFitnessViewData, getSleepSessionById, getSleepSessionDetailById, getSleepTimelineOverlaysForRange, getSleepViewData, getVitalsViewData, getHealthZoneProfileForUser, getMobileHealthSyncSessionStatus, getWorkoutSessionById, getWorkoutSessionDetailById, heartbeatCompanionPairing, heartbeatCompanionPairingSchema, healthZoneProfilePatchSchema, abortMobileHealthSyncSession, completeMobileHealthSyncSession, ingestMobileHealthSync, ingestMobileHealthSyncChunk, mobileHealthSyncChunkSchema, mobileHealthSyncSessionCompleteSchema, mobileHealthSyncSessionStartSchema, mobileHealthSyncSchema, patchHealthZoneProfileForUser, patchCompanionPairingSourceState, patchCompanionPairingSourceStateSchema, companionSourceKeySchema, requireValidPairing, startMobileHealthSyncSession, revokeAllCompanionPairingSessions, revokeAllCompanionPairingSessionsSchema, revokeCompanionPairingSession, updateMobileCompanionSourceState, updateMobileCompanionSourceStateSchema, verifyCompanionPairing, verifyCompanionPairingSchema, updateSleepMetadata, updateSleepMetadataSchema, updateWorkoutMetadata, updateWorkoutMetadataSchema } from "./health.js";
69
+ import { createCompanionPairingSession, createCompanionPairingSessionSchema, createSleepSession, createSleepSessionSchema, createWorkoutSession, createWorkoutSessionSchema, deleteSleepSession, deleteWorkoutSession, getCompanionPairingSessionById, getCompanionOverview, getFitnessViewData, getSleepSessionById, getSleepSessionDetailById, getSleepTimelineOverlaysForRange, getSleepViewData, getTrainingLoadViewData, getVitalsViewData, getHealthZoneProfileForUser, getMobileHealthSyncSessionStatus, getWorkoutSessionById, getWorkoutSessionDetailById, heartbeatCompanionPairing, heartbeatCompanionPairingSchema, healthZoneProfilePatchSchema, abortMobileHealthSyncSession, completeMobileHealthSyncSession, ingestMobileHealthSync, ingestMobileHealthSyncChunk, mobileHealthSyncChunkSchema, mobileHealthSyncSessionCompleteSchema, mobileHealthSyncSessionStartSchema, mobileHealthSyncSchema, patchHealthZoneProfileForUser, patchCompanionPairingSourceState, patchCompanionPairingSourceStateSchema, companionSourceKeySchema, requireValidPairing, startMobileHealthSyncSession, revokeAllCompanionPairingSessions, revokeAllCompanionPairingSessionsSchema, revokeCompanionPairingSession, updateMobileCompanionSourceState, updateMobileCompanionSourceStateSchema, verifyCompanionPairing, verifyCompanionPairingSchema, updateSleepMetadata, updateSleepMetadataSchema, updateWorkoutMetadata, updateWorkoutMetadataSchema } from "./health.js";
70
70
  import { analyzeMovementUserBoxPreflight, createMovementUserBox, createMovementPlace, deleteMovementUserBox, getMovementAllTimeSummary, getMovementBoxDetail, getMovementDayDetail, getMovementMobileBootstrap, getMovementTimeline, getMovementSelectionAggregate, getMovementSettings, getMovementTripDetail, getMovementMonthSummary, invalidateAutomaticMovementBox, listMovementPlaces, movementAutomaticBoxInvalidateSchema, movementMobileBootstrapSchema, movementMobilePlaceMutationSchema, movementMobileStayPatchSchema, movementMobileUserBoxCreateSchema, movementMobileUserBoxPreflightSchema, movementMobileUserBoxPatchSchema, movementMobileAutomaticBoxInvalidateSchema, movementMobileTimelineSchema, movementPlaceMutationSchema, movementPlacePatchSchema, movementSelectionAggregateSchema, movementStayPatchSchema, movementTripPatchSchema, movementUserBoxCreateSchema, movementUserBoxPreflightSchema, movementUserBoxPatchSchema, movementSettingsPatchSchema, movementTimelineQuerySchema, movementTripPointPatchSchema, deleteMovementStay, deleteMovementTrip, deleteMovementTripPoint, updateMovementPlace, updateMovementSettings, updateMovementStay, updateMovementTrip, updateMovementUserBox, updateMovementTripPoint, resolveMovementTimelineSegmentForBox } from "./movement.js";
71
71
  import { getScreenTimeAllTimeSummary, getScreenTimeDayDetail, getScreenTimeMonthSummary, getScreenTimeSettings, screenTimeSettingsPatchSchema, updateScreenTimeSettings } from "./screen-time.js";
72
72
  import { assertWatchReady, buildWatchBootstrap, ingestWatchCaptureBatch, mobileWatchBootstrapSchema, mobileWatchCaptureBatchSchema, mobileWatchHabitCheckInSchema } from "./watch-mobile.js";
@@ -2246,6 +2246,8 @@ function buildPreferredMutationPath(entityType) {
2246
2246
  return "Read-only surface. Use batch CRUD for sleep_session records or the review enrichment route for reflective notes.";
2247
2247
  case "sports_overview":
2248
2248
  return "Read-only surface. Use batch CRUD for workout_session records or the review enrichment route for reflective notes.";
2249
+ case "training_load":
2250
+ return "Read-only surface. Use it for cardiovascular load, HR zones, acute/chronic stress, VO2max context, and target analysis; use batch CRUD for underlying workout_session records.";
2249
2251
  default:
2250
2252
  return "Read-only surface.";
2251
2253
  }
@@ -2317,6 +2319,8 @@ function buildPreferredReadPath(entityType) {
2317
2319
  return "/api/v1/health/sleep";
2318
2320
  case "sports_overview":
2319
2321
  return "/api/v1/health/fitness";
2322
+ case "training_load":
2323
+ return "/api/v1/health/training-load";
2320
2324
  default:
2321
2325
  return null;
2322
2326
  }
@@ -3037,6 +3041,19 @@ const AGENT_ONBOARDING_ENTITY_CATALOG = [
3037
3041
  "Read this surface before suggesting workout reflections or recovery follow-up."
3038
3042
  ],
3039
3043
  fieldGuide: []
3044
+ }),
3045
+ enrichOnboardingEntityGuide({
3046
+ entityType: "training_load",
3047
+ purpose: "The read-model cardiovascular training-load workspace for acute/chronic load, HR zone distribution, intensity targets, and VO2max context.",
3048
+ minimumCreateFields: [],
3049
+ relationshipRules: [
3050
+ "Use this surface for review and interpretation.",
3051
+ "Create, update, delete, or search the underlying workout_session records through batch CRUD by default."
3052
+ ],
3053
+ searchHints: [
3054
+ "Read this surface before advising on high-intensity balance, recovery load, or cardiovascular training targets."
3055
+ ],
3056
+ fieldGuide: []
3040
3057
  })
3041
3058
  ];
3042
3059
  const AGENT_ONBOARDING_CONVERSATION_RULES = [
@@ -3054,6 +3071,7 @@ const AGENT_ONBOARDING_CONVERSATION_RULES = [
3054
3071
  "Do not over-therapize logistical entities. For tasks, calendar events, work blocks, timeboxes, and task runs, one brief confirming sentence plus one question is usually enough.",
3055
3072
  "After each substantive answer, briefly say what is becoming clearer and ask only for the next thing that still changes the record shape or usefulness.",
3056
3073
  "For strategic, reflective, or emotionally meaningful non-Psyche records, ask what feels important to keep true before you ask for labels, dates, or taxonomy.",
3074
+ "For reflection-sensitive non-Psyche records such as questionnaire_instrument, questionnaire_run, self_observation, reflective note, wiki_page, sleep_session, workout_session, preference_judgment, and preference_signal, first ask what the reflection should help the user understand, decide, notice, remember, or change later; then keep the API posture exact: batch CRUD for normal stored records, questionnaire run actions for answer lifecycle, self-observation calendar reads plus observed-note writes, and wiki routes for wiki pages.",
3057
3075
  "For reusable records such as tags, event types, emotion definitions, preference contexts, or questionnaires, ask what distinction or decision the record should help with before you ask for wording.",
3058
3076
  "When useful, help the user name, define, and connect the record in that order: offer a working label, clarify what belongs inside it, then ask about links only after the record itself feels steady.",
3059
3077
  "When the meaning is clearer than the wording, offer a tentative title or formulation yourself and invite correction instead of forcing the user to wordsmith alone.",
@@ -3082,7 +3100,7 @@ const AGENT_ONBOARDING_CONVERSATION_RULES = [
3082
3100
  "Once the route family is clear, say it plainly enough that another agent could follow the same path without guessing.",
3083
3101
  "For Movement specifically, treat missing-data corrections as user-defined overlay boxes unless the user is editing an already-recorded stay or trip. When the user already gave a clear instruction like 'that missing block was home', act after only the last ambiguity is resolved.",
3084
3102
  "For action workflows such as task_run, work_adjustment, questionnaire_run, preference_judgment, preference_signal, and self_observation, keep the question focused on the missing action detail and do not downgrade the request into generic batch CRUD.",
3085
- "For read-model-only health surfaces such as sleep_overview and sports_overview, use the dedicated overview reads first when the user wants review, pattern interpretation, recovery context, or training-load context. Move to sleep_session or workout_session writes only after one specific stored session needs enrichment.",
3103
+ "For read-model-only health surfaces such as sleep_overview, sports_overview, and training_load, use the dedicated overview reads first when the user wants review, pattern interpretation, recovery context, training-load context, or cardiovascular target analysis. Move to sleep_session or workout_session writes only after one specific stored session needs enrichment.",
3086
3104
  "For normal stored Preferences and questionnaire records, use batch CRUD by default; switch to dedicated action routes only for judgments, signals, run answers, clone/draft/publish lifecycle, or visual comparison gameplay.",
3087
3105
  "When the user wants to remember a book, article, paper, source, concept, person, conversation, project reference, recurring explanation, or personal manual, consider wiki_page before note or self_observation.",
3088
3106
  "For meaning-bearing updates, especially in Psyche, briefly say what feels newly true before you ask for the one structural detail that still changes the save."
@@ -3375,6 +3393,18 @@ const AGENT_ONBOARDING_ENTITY_CONVERSATION_PLAYBOOKS = [
3375
3393
  "Move to a workout_session write only when one specific workout needs reflective context, tags, notes, or links."
3376
3394
  ]
3377
3395
  },
3396
+ {
3397
+ focus: "training_load",
3398
+ openingQuestion: "What training decision should the load picture help with right now?",
3399
+ coachingGoal: "Review cardiovascular load, HR zones, acute/chronic stress, high-intensity pressure, VO2max context, and target distribution before suggesting training changes.",
3400
+ askSequence: [
3401
+ "Ask what decision the user wants from the load surface only if it is not already clear.",
3402
+ "Use the dedicated training-load overview before asking the user to reconstruct workout metrics from memory.",
3403
+ "Separate data-quality limits from true physiological interpretation.",
3404
+ "Translate the load pattern into a concrete next training constraint or target.",
3405
+ "Move to a workout_session write only when one specific workout needs reflective context, tags, notes, or links."
3406
+ ]
3407
+ },
3378
3408
  {
3379
3409
  focus: "preference_catalog",
3380
3410
  openingQuestion: "What decision or taste question should this catalog help with?",
@@ -4230,6 +4260,19 @@ const AGENT_ONBOARDING_TOOL_INPUT_CATALOG = [
4230
4260
  ],
4231
4261
  example: '{"userIds":["user_operator"]}'
4232
4262
  },
4263
+ {
4264
+ toolName: "forge_get_training_load_overview",
4265
+ summary: "Read the cardiovascular training-load surface with acute/chronic load, HR zone distribution, weekly intensity targets, and data-quality flags.",
4266
+ whenToUse: "Use when the operator wants to analyze training stress, zone balance, VO2max context, combat-sport load, or what to optimize next.",
4267
+ inputShape: "{ userIds?: string[] }",
4268
+ requiredFields: [],
4269
+ notes: [
4270
+ "The API path is /api/v1/health/training-load and the UI route is /training-load.",
4271
+ "This is a read-model-only surface. Workout records remain ordinary workout_session entities for batch CRUD.",
4272
+ "Forge uses HRR zone analytics and TRIMP-like internal load from stored workout evidence."
4273
+ ],
4274
+ example: '{"userIds":["user_operator"]}'
4275
+ },
4233
4276
  {
4234
4277
  toolName: "forge_update_sleep_session",
4235
4278
  summary: "Patch one sleep session with reflective notes, tags, or linked Forge context.",
@@ -5013,6 +5056,8 @@ function buildAgentOnboardingPayload(request) {
5013
5056
  sleep_overview: "/api/v1/health/sleep",
5014
5057
  sportsOverview: "/api/v1/health/fitness",
5015
5058
  sports_overview: "/api/v1/health/fitness",
5059
+ trainingLoad: "/api/v1/health/training-load",
5060
+ training_load: "/api/v1/health/training-load",
5016
5061
  selfObservation: "/api/v1/psyche/self-observation/calendar",
5017
5062
  self_observation: "/api/v1/psyche/self-observation/calendar",
5018
5063
  calendarOverview: "/api/v1/calendar/overview",
@@ -5122,6 +5167,7 @@ function buildAgentOnboardingPayload(request) {
5122
5167
  weeklyReview: "/api/v1/reviews/weekly",
5123
5168
  sleepOverview: "/api/v1/health/sleep",
5124
5169
  sportsOverview: "/api/v1/health/fitness",
5170
+ trainingLoad: "/api/v1/health/training-load",
5125
5171
  lifeForce: "/api/v1/life-force",
5126
5172
  lifeForceProfile: "/api/v1/life-force/profile",
5127
5173
  lifeForceWeekdayTemplate: "/api/v1/life-force/templates/:weekday",
@@ -5173,6 +5219,7 @@ function buildAgentOnboardingPayload(request) {
5173
5219
  "forge_get_psyche_overview",
5174
5220
  "forge_get_sleep_overview",
5175
5221
  "forge_get_sports_overview",
5222
+ "forge_get_training_load_overview",
5176
5223
  "forge_get_xp_metrics",
5177
5224
  "forge_get_weekly_review"
5178
5225
  ],
@@ -5203,6 +5250,7 @@ function buildAgentOnboardingPayload(request) {
5203
5250
  healthWorkflow: [
5204
5251
  "forge_get_sleep_overview",
5205
5252
  "forge_get_sports_overview",
5253
+ "forge_get_training_load_overview",
5206
5254
  "forge_update_sleep_session",
5207
5255
  "forge_update_workout_session"
5208
5256
  ],
@@ -6210,6 +6258,16 @@ function compactFitness(fitness) {
6210
6258
  detailRoute: "/api/v1/health/fitness"
6211
6259
  };
6212
6260
  }
6261
+ function compactTrainingLoad(trainingLoad) {
6262
+ return {
6263
+ summary: trainingLoad.summary,
6264
+ intensityDistribution: trainingLoad.recentIntensityDistribution,
6265
+ weeklyLoad: trainingLoad.weeklyLoad.slice(-8),
6266
+ topActivities: trainingLoad.activityBreakdown.slice(0, 6),
6267
+ targetModel: trainingLoad.targetModel,
6268
+ detailRoute: "/api/v1/health/training-load"
6269
+ };
6270
+ }
6213
6271
  function compactVitals(vitals) {
6214
6272
  return {
6215
6273
  summary: vitals.summary,
@@ -6490,6 +6548,7 @@ function buildOperatorOverview(request) {
6490
6548
  const yesterday = compactDailyContext(getTodayContext(addDays(now, -1), { userIds }));
6491
6549
  const sleep = compactSleep(getSleepViewData(userIds));
6492
6550
  const fitness = compactFitness(getFitnessViewData(userIds));
6551
+ const trainingLoad = compactTrainingLoad(getTrainingLoadViewData(userIds));
6493
6552
  const vitals = compactVitals(getVitalsViewData(userIds));
6494
6553
  const lifeForce = compactLifeForce(buildLifeForcePayload(now, userIds));
6495
6554
  const psyche = canReadPsyche ? compactPsyche(getPsycheOverview(userIds)) : null;
@@ -6571,6 +6630,7 @@ function buildOperatorOverview(request) {
6571
6630
  notes,
6572
6631
  sleep,
6573
6632
  fitness,
6633
+ trainingLoad,
6574
6634
  vitals,
6575
6635
  lifeForce,
6576
6636
  domains: listDomains().map((domain) => ({
@@ -7249,6 +7309,9 @@ export async function buildServer(options = {}) {
7249
7309
  app.get("/api/v1/health/fitness", async (request) => ({
7250
7310
  fitness: getFitnessViewData(resolveScopedUserIds(request.query))
7251
7311
  }));
7312
+ app.get("/api/v1/health/training-load", async (request) => ({
7313
+ trainingLoad: getTrainingLoadViewData(resolveScopedUserIds(request.query))
7314
+ }));
7252
7315
  app.get("/api/v1/health/vitals", async (request) => ({
7253
7316
  vitals: getVitalsViewData(resolveScopedUserIds(request.query))
7254
7317
  }));