@robbeverhelst/do 1.273.0 → 1.275.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/do.js +961 -845
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -5698,6 +5698,7 @@ var healthProfiles = pgTable("health_profiles", {
5698
5698
  bloodGroup: text("blood_group"),
5699
5699
  allergies: text("allergies").array().notNull().default(sql`'{}'::text[]`),
5700
5700
  heightCm: numeric("height_cm", { mode: "number" }),
5701
+ sex: text("sex"),
5701
5702
  alcohol: text("alcohol"),
5702
5703
  smoking: text("smoking"),
5703
5704
  exercise: text("exercise"),
@@ -21290,909 +21291,937 @@ var houseUpkeepYearSchema = object({
21290
21291
  });
21291
21292
  var houseUpkeepYearQuerySchema = object({ year: exports_coerce.number().int().min(2000).max(2100).optional() }).strict();
21292
21293
 
21293
- // ../../packages/schema/src/contracts/health-records.ts
21294
- var BODY_REGION_VALUES = [
21295
- "head",
21296
- "face",
21297
- "eyes",
21298
- "ears",
21299
- "nose",
21300
- "mouth",
21301
- "throat",
21302
- "neck",
21303
- "chest",
21304
- "upper_back",
21305
- "lower_back",
21306
- "epigastric",
21307
- "ruq",
21308
- "luq",
21309
- "periumbilical",
21310
- "rlq",
21311
- "llq",
21312
- "lower_abdomen",
21313
- "pelvis",
21314
- "shoulder_l",
21315
- "shoulder_r",
21316
- "arm_l",
21317
- "arm_r",
21318
- "elbow_l",
21319
- "elbow_r",
21320
- "wrist_l",
21321
- "wrist_r",
21322
- "hand_l",
21323
- "hand_r",
21324
- "hip_l",
21325
- "hip_r",
21326
- "thigh_l",
21327
- "thigh_r",
21328
- "knee_l",
21329
- "knee_r",
21330
- "calf_l",
21331
- "calf_r",
21332
- "ankle_l",
21333
- "ankle_r",
21334
- "foot_l",
21335
- "foot_r",
21336
- "skin",
21337
- "whole_body"
21338
- ];
21339
- var bodyRegionSchema = _enum2(BODY_REGION_VALUES);
21340
- var RED_FLAG_VALUES = [
21341
- "fever",
21342
- "vomiting",
21343
- "black_stools",
21344
- "blood",
21345
- "weight_loss",
21346
- "night_pain",
21347
- "chest_pain",
21348
- "short_of_breath"
21349
- ];
21350
- var redFlagSchema = _enum2(RED_FLAG_VALUES);
21351
- var redFlagsSchema = partialRecord(redFlagSchema, boolean3());
21352
- var HEALTH_CONDITION_STATUS_VALUES = [
21353
- "active",
21354
- "managed",
21355
- "resolved",
21356
- "suspected"
21357
- ];
21358
- var healthConditionStatusSchema = _enum2(HEALTH_CONDITION_STATUS_VALUES);
21359
- var HEALTH_EPISODE_STATUS_VALUES = ["open", "watching", "resolved"];
21360
- var healthEpisodeStatusSchema = _enum2(HEALTH_EPISODE_STATUS_VALUES);
21361
- var HEALTH_ENCOUNTER_KIND_VALUES = [
21362
- "gp",
21363
- "specialist",
21364
- "physio",
21365
- "dentist",
21366
- "lab_draw",
21367
- "er",
21368
- "tele",
21369
- "other"
21370
- ];
21371
- var healthEncounterKindSchema = _enum2(HEALTH_ENCOUNTER_KIND_VALUES);
21372
- var healthMedicationKindSchema = _enum2(["drug", "supplement"]);
21373
- var healthMedicationScheduleSchema = _enum2(["scheduled", "as_needed"]);
21374
- var HEALTH_DOSE_EFFECT_VALUES = ["none", "a_little", "helped", "worse"];
21375
- var healthDoseEffectSchema = _enum2(HEALTH_DOSE_EFFECT_VALUES);
21376
- var healthEntrySourceSchema = _enum2(["chat", "manual", "import"]);
21377
- var severitySchema = number2().int().min(0).max(10);
21378
- var fuzzyDateSchema = string2().regex(/^\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12]\d|3[01]))?)?$/, "must be YYYY, YYYY-MM or YYYY-MM-DD");
21379
- var civilDateSchema2 = string2().regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD");
21380
- var title = string2().trim().min(1).max(200);
21381
- var text2 = (max) => string2().trim().min(1).max(max);
21382
- var instant = exports_coerce.date();
21383
- var spine = {
21384
- title: string2(),
21385
- createdAt: exports_coerce.date(),
21386
- updatedAt: exports_coerce.date()
21387
- };
21388
- var healthCareTeamMemberSchema = object({
21389
- contactId: string2(),
21390
- name: string2(),
21391
- phone: string2().nullable(),
21392
- label: string2().nullable()
21294
+ // ../../packages/schema/src/contracts/agent-chat.ts
21295
+ var agentConnectionSourceSchema = _enum2(["space", "env"]);
21296
+ var agentGatewayStatusSchema = _enum2(["connected", "offline", "not_connected"]);
21297
+ var agentGatewayStateSchema = object({
21298
+ status: agentGatewayStatusSchema,
21299
+ connectedAt: exports_coerce.date().nullable(),
21300
+ seenAt: exports_coerce.date().nullable(),
21301
+ disconnectedAt: exports_coerce.date().nullable()
21393
21302
  });
21394
- var healthConditionViewSchema = createSelectSchema(healthConditions, {
21395
- bodyRegions: array(string2())
21396
- }).extend({
21397
- ...spine,
21398
- careTeam: array(healthCareTeamMemberSchema).default([])
21303
+ var agentConnectionSchema = object({
21304
+ connected: boolean3(),
21305
+ source: agentConnectionSourceSchema.nullable(),
21306
+ endpoint: string2().nullable(),
21307
+ model: string2().nullable(),
21308
+ hasKey: boolean3(),
21309
+ agentId: string2().nullable(),
21310
+ agentName: string2().nullable().default(null),
21311
+ autoFile: boolean3(),
21312
+ updatedAt: exports_coerce.date().nullable(),
21313
+ gateway: agentGatewayStateSchema.nullable().default(null)
21399
21314
  });
21400
- var healthEpisodeViewSchema = createSelectSchema(healthEpisodes, {
21401
- startedAt: exports_coerce.date(),
21402
- endedAt: exports_coerce.date().nullable(),
21403
- redFlags: redFlagsSchema,
21404
- redFlagsCheckedAt: exports_coerce.date().nullable()
21405
- }).extend({
21406
- ...spine,
21407
- latestSeverity: number2().int().nullable(),
21408
- lastEntryAt: exports_coerce.date().nullable()
21315
+ var agentEndpointSchema = string2().trim().max(2000).url().refine((value) => /^https?:\/\//i.test(value), "endpoint must be an http(s) URL");
21316
+ var saveAgentConnectionInputSchema = object({
21317
+ endpoint: agentEndpointSchema.nullable(),
21318
+ apiKey: string2().trim().min(1).max(4000).nullable().optional(),
21319
+ model: string2().trim().min(1).max(200).nullable().optional(),
21320
+ agentId: string2().trim().min(1).max(64).nullable().optional(),
21321
+ autoFile: boolean3().optional()
21322
+ }).strict().refine((input) => input.endpoint !== null || Boolean(input.agentId), {
21323
+ message: "a connection without an endpoint names its agent",
21324
+ path: ["agentId"]
21409
21325
  });
21410
- var healthSymptomEntrySchema = createSelectSchema(healthSymptomEntries, {
21411
- occurredAt: exports_coerce.date(),
21412
- recordedAt: exports_coerce.date(),
21413
- qualifiers: record(string2(), unknown())
21326
+ var agentPageContextSchema = object({
21327
+ route: string2().trim().min(1).max(500).startsWith("/"),
21328
+ nodeId: string2().trim().min(1).max(64).nullable(),
21329
+ focusArea: object({
21330
+ id: string2().trim().min(1).max(64),
21331
+ title: string2().trim().min(1).max(200)
21332
+ }).nullish()
21333
+ }).strict();
21334
+ var echoDeviceSchema = _enum2(["phone", "desktop"]);
21335
+ var agentChatInputSchema = object({
21336
+ message: string2().trim().max(8000),
21337
+ context: agentPageContextSchema,
21338
+ threadId: string2().trim().min(1).max(64).optional(),
21339
+ steer: boolean3().optional(),
21340
+ attachments: array(string2().trim().min(1).max(64)).max(20).optional(),
21341
+ replyTo: string2().trim().min(1).max(64).optional(),
21342
+ device: echoDeviceSchema.optional()
21343
+ }).strict().refine((input) => input.message.length > 0 || (input.attachments?.length ?? 0) > 0, {
21344
+ message: "write something or attach a file",
21345
+ path: ["message"]
21414
21346
  });
21415
- var healthEncounterViewSchema = createSelectSchema(healthEncounters, {
21416
- at: exports_coerce.date(),
21417
- followUpAt: exports_coerce.date().nullable(),
21418
- questions: array(string2())
21419
- }).extend({
21420
- ...spine,
21421
- providerName: string2().nullable()
21347
+ var agentChatStopInputSchema = object({ threadId: string2().trim().min(1).max(64) }).strict();
21348
+ var agentChatStopResultSchema = object({ stop: _enum2(["sent", "offline"]) });
21349
+ var agentChatEventSchema = discriminatedUnion("type", [
21350
+ object({
21351
+ type: literal("turn"),
21352
+ id: string2(),
21353
+ threadId: string2(),
21354
+ since: string2().nullable()
21355
+ }),
21356
+ object({ type: literal("delta"), text: string2() }),
21357
+ object({ type: literal("done") }),
21358
+ object({ type: literal("error"), message: string2() }),
21359
+ object({
21360
+ type: literal("posted"),
21361
+ threadId: string2(),
21362
+ postId: string2(),
21363
+ delivery: _enum2(["sent", "waiting"])
21364
+ })
21365
+ ]);
21366
+ var agentChangeValueSchema = union([
21367
+ string2(),
21368
+ number2(),
21369
+ boolean3(),
21370
+ _null3(),
21371
+ array(string2())
21372
+ ]);
21373
+ var agentChangeFieldSchema = object({
21374
+ field: string2(),
21375
+ before: agentChangeValueSchema,
21376
+ after: agentChangeValueSchema,
21377
+ beforeLabel: string2().nullable().optional(),
21378
+ afterLabel: string2().nullable().optional()
21422
21379
  });
21423
- var healthMedicationViewSchema = createSelectSchema(healthMedications).extend({
21424
- ...spine,
21425
- lastTakenAt: exports_coerce.date().nullable()
21380
+ var agentChangeSchema = object({
21381
+ entity: changeEntitySchema,
21382
+ id: string2(),
21383
+ op: changeOpSchema,
21384
+ changedAt: exports_coerce.date(),
21385
+ title: string2().nullable(),
21386
+ actor: actorRefSchema,
21387
+ cursor: string2().optional(),
21388
+ fields: array(agentChangeFieldSchema).optional(),
21389
+ checkIn: object({
21390
+ value: number2(),
21391
+ unit: string2().nullable(),
21392
+ measurementType: habitMeasurementTypeSchema
21393
+ }).optional()
21426
21394
  });
21427
- var healthMedicationDoseSchema = createSelectSchema(healthMedicationDoses, {
21428
- takenAt: exports_coerce.date(),
21429
- createdAt: exports_coerce.date()
21430
- }).extend({
21431
- medicationTitle: string2()
21395
+ var agentChangesPageSchema = object({
21396
+ data: array(agentChangeSchema),
21397
+ nextCursor: string2()
21432
21398
  });
21433
- var healthEpisodeDetailSchema = healthEpisodeViewSchema.extend({
21434
- entries: array(healthSymptomEntrySchema),
21435
- doses: array(healthMedicationDoseSchema),
21436
- encounters: array(healthEncounterViewSchema),
21437
- condition: healthConditionViewSchema.nullable()
21399
+ var agentChangesQuerySchema = object({
21400
+ since: string2().refine((s) => s === "now" || /^\d+-\d+$/.test(s), {
21401
+ message: "since must be a cursor from a prior page's nextCursor, or 'now'"
21402
+ }),
21403
+ node: string2().trim().min(1).max(64).optional()
21438
21404
  });
21439
- var healthProfileSchema = createSelectSchema(healthProfiles, {
21440
- allergies: array(string2()),
21441
- updatedAt: exports_coerce.date()
21442
- }).extend({
21443
- notes: string2().nullable().default(null)
21405
+ var agentConfirmationKindSchema = _enum2(["delete", "cancel", "google", "orca", "bulk"]);
21406
+ var agentConfirmationStatusSchema = _enum2([
21407
+ "pending",
21408
+ "confirmed",
21409
+ "done",
21410
+ "failed",
21411
+ "declined"
21412
+ ]);
21413
+ var agentConfirmationItemSchema = object({
21414
+ id: string2(),
21415
+ title: string2().nullable(),
21416
+ area: string2().nullable().optional(),
21417
+ dueAt: exports_coerce.date().nullable().optional()
21444
21418
  });
21445
- var healthConsentStateSchema = object({
21446
- granted: boolean3(),
21447
- version: string2().nullable(),
21448
- grantedAt: exports_coerce.date().nullable()
21419
+ var agentConfirmationSchema = object({
21420
+ id: string2(),
21421
+ kind: agentConfirmationKindSchema,
21422
+ summary: string2(),
21423
+ items: array(agentConfirmationItemSchema),
21424
+ method: string2(),
21425
+ path: string2(),
21426
+ status: agentConfirmationStatusSchema,
21427
+ agent: object({ id: string2(), name: string2().nullable() }),
21428
+ createdAt: exports_coerce.date(),
21429
+ decidedAt: exports_coerce.date().nullable()
21449
21430
  });
21450
- var HEALTH_CONSENT_VERSION = "2026-10-18";
21451
- var subject = { subjectNodeId: ulidSchema.nullish() };
21452
- var createHealthConditionInputSchema = object({
21453
- id: ulidSchema.optional(),
21454
- title,
21455
- status: healthConditionStatusSchema.optional(),
21456
- onset: fuzzyDateSchema.nullish(),
21457
- resolvedOn: civilDateSchema2.nullish(),
21458
- bodyRegions: array(bodyRegionSchema).max(10).optional(),
21459
- code: text2(40).nullish(),
21460
- notes: text2(4000).nullish(),
21461
- ...subject
21462
- }).strict();
21463
- var addHealthCareTeamInputSchema = object({ contactId: ulidSchema, label: text2(60).nullish() }).strict();
21464
- var updateHealthConditionInputSchema = createHealthConditionInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21465
- var episodeFields = object({
21466
- id: ulidSchema.optional(),
21467
- title,
21468
- status: healthEpisodeStatusSchema.optional(),
21469
- startedAt: instant.optional(),
21470
- bodyRegion: bodyRegionSchema.nullish(),
21471
- triggerText: text2(500).nullish(),
21472
- summary: text2(500).nullish(),
21473
- conditionId: ulidSchema.nullish(),
21474
- ...subject
21431
+ var agentUndoInputSchema = object({
21432
+ id: string2().trim().min(1).max(64),
21433
+ since: string2().regex(/^\d+-\d+$/, "since must be a change-feed cursor")
21475
21434
  }).strict();
21476
- var createHealthEpisodeInputSchema = episodeFields.extend({ endedAt: instant.nullish() }).strict().superRefine((v, ctx) => {
21477
- if (!v.endedAt)
21478
- return;
21479
- if (v.status && v.status !== "resolved") {
21480
- ctx.addIssue({
21481
- code: "custom",
21482
- path: ["endedAt"],
21483
- message: "only a resolved episode has an end"
21484
- });
21485
- }
21486
- if (v.endedAt.getTime() > Date.now()) {
21487
- ctx.addIssue({ code: "custom", path: ["endedAt"], message: "can't end in the future" });
21488
- }
21489
- if (v.endedAt.getTime() < (v.startedAt ?? new Date).getTime()) {
21490
- ctx.addIssue({ code: "custom", path: ["endedAt"], message: "can't end before it started" });
21491
- }
21435
+ var agentUndoResultSchema = object({
21436
+ id: string2(),
21437
+ undone: _enum2(["removed", "restored"])
21492
21438
  });
21493
- var updateHealthEpisodeInputSchema = episodeFields.omit({ id: true, subjectNodeId: true }).extend({
21494
- endedAt: instant.nullish(),
21495
- redFlags: redFlagsSchema.optional()
21496
- }).partial().strict();
21497
- var symptomFields = {
21498
- symptom: text2(200),
21499
- occurredAt: instant.optional(),
21500
- bodyRegion: bodyRegionSchema.nullish(),
21501
- severity: severitySchema.nullish(),
21502
- severityGuessed: boolean3().optional(),
21503
- qualifiers: record(string2(), unknown()).optional(),
21504
- note: text2(2000).nullish(),
21505
- source: healthEntrySourceSchema.optional()
21506
- };
21507
- var logHealthSymptomInputSchema = object({ id: ulidSchema.optional(), ...symptomFields }).strict();
21508
- var correctHealthSymptomInputSchema = object({ id: ulidSchema.optional(), ...symptomFields }).partial().strict().refine((v) => Object.keys(v).some((k) => k !== "id" && k !== "source"), {
21509
- message: "a correction must change something"
21439
+ var agentRedoResultSchema = object({
21440
+ id: string2(),
21441
+ redone: literal(true)
21510
21442
  });
21511
- var createHealthEncounterInputSchema = object({
21512
- id: ulidSchema.optional(),
21513
- title: title.optional(),
21514
- kind: healthEncounterKindSchema.optional(),
21515
- at: instant,
21516
- episodeId: ulidSchema.nullish(),
21517
- providerContactId: ulidSchema.nullish(),
21518
- placeId: ulidSchema.nullish(),
21519
- eventId: ulidSchema.nullish(),
21520
- reason: text2(500).nullish(),
21521
- questions: array(text2(300)).max(30).optional(),
21522
- outcome: text2(4000).nullish(),
21523
- followUpAt: instant.nullish(),
21524
- ...subject
21525
- }).strict();
21526
- var updateHealthEncounterInputSchema = createHealthEncounterInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21527
- var createHealthMedicationInputSchema = object({
21528
- id: ulidSchema.optional(),
21529
- title,
21530
- kind: healthMedicationKindSchema.optional(),
21531
- schedule: healthMedicationScheduleSchema.optional(),
21532
- ingredient: text2(200).nullish(),
21533
- dose: text2(100).nullish(),
21534
- form: text2(100).nullish(),
21535
- startedOn: civilDateSchema2.nullish(),
21536
- stoppedOn: civilDateSchema2.nullish(),
21537
- reason: text2(500).nullish(),
21538
- prescribedByContactId: ulidSchema.nullish(),
21539
- habitId: ulidSchema.nullish(),
21540
- ...subject
21541
- }).strict();
21542
- var updateHealthMedicationInputSchema = createHealthMedicationInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21543
- var logHealthDoseInputSchema = object({
21544
- id: ulidSchema.optional(),
21545
- takenAt: instant.optional(),
21546
- amount: text2(100).nullish(),
21547
- effect: healthDoseEffectSchema.nullish(),
21548
- note: text2(1000).nullish(),
21549
- episodeId: ulidSchema.nullish(),
21550
- source: healthEntrySourceSchema.optional()
21443
+ var agentFilingSchema = object({
21444
+ confident: boolean3().default(false),
21445
+ areaId: string2().nullable().optional(),
21446
+ owner: string2().nullable().optional(),
21447
+ date: string2().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional()
21448
+ });
21449
+
21450
+ // ../../packages/schema/src/contracts/agent-gateway.ts
21451
+ var AGENT_GATEWAY_VERSION = 1;
21452
+ var AGENT_GATEWAY_MAX_FRAME_BYTES = 1024 * 1024;
21453
+ var threadSlugSchema = string2().regex(/^[a-z0-9][a-z0-9-]{0,39}$/, "a thread slug is lower-case, like `build`");
21454
+ var postLevelSchema = _enum2(["needs_you", "told", "for_later", "silent"]);
21455
+ var postKindSchema = _enum2(["message", "brief", "card", "run"]);
21456
+ var runStatusSchema = _enum2(["running", "needs_you", "done", "failed", "stopped"]);
21457
+ var externalIdSchema = string2().min(1).max(200).regex(/^[\x21-\x7e]+$/, "printable ASCII without spaces");
21458
+ var AGENT_POST_TEXT_MAX = 64000;
21459
+ var postTextSchema = string2().max(AGENT_POST_TEXT_MAX);
21460
+ var briefVerbSchema = object({
21461
+ label: string2().trim().min(1).max(24),
21462
+ href: string2().max(2000).regex(/^(\/(?!\/)|https:\/\/)/, "a path in do (`/tasks`) or an https link").optional(),
21463
+ say: string2().trim().min(1).max(500).optional()
21464
+ }).strict().refine((v) => v.href === undefined !== (v.say === undefined), {
21465
+ message: "a verb has either href or say"
21466
+ });
21467
+ var briefRowSchema = object({
21468
+ text: string2().trim().min(1).max(200),
21469
+ meta: string2().trim().max(200).optional(),
21470
+ icon: string2().max(24).optional(),
21471
+ verb: briefVerbSchema.optional()
21551
21472
  }).strict();
21552
- var updateHealthDoseInputSchema = logHealthDoseInputSchema.omit({ id: true, source: true }).partial().strict();
21553
- var updateHealthProfileInputSchema = object({
21554
- bloodGroup: string2().regex(/^(A|B|AB|O)[+-]$/, "must be like A+ or O-").nullish(),
21555
- allergies: array(text2(100)).max(30).optional(),
21556
- heightCm: number2().min(30).max(260).nullish(),
21557
- alcohol: text2(200).nullish(),
21558
- smoking: text2(200).nullish(),
21559
- exercise: text2(200).nullish(),
21560
- notes: text2(2000).nullish(),
21561
- emergencyContactId: ulidSchema.nullish(),
21562
- primaryGpContactId: ulidSchema.nullish()
21473
+ var BRIEF_ROWS_MAX = 8;
21474
+ var briefSchema = object({
21475
+ label: string2().trim().min(1).max(40),
21476
+ title: string2().trim().min(1).max(200),
21477
+ rows: array(briefRowSchema).max(BRIEF_ROWS_MAX).default([])
21563
21478
  }).strict();
21564
- var grantHealthConsentInputSchema = object({ version: literal(HEALTH_CONSENT_VERSION) }).strict();
21565
- var healthEpisodeListQuerySchema = object({
21566
- status: healthEpisodeStatusSchema.optional()
21479
+ var gatewayMemberSchema = object({
21480
+ id: string2().min(1),
21481
+ name: string2(),
21482
+ role: baseRoleSchema
21567
21483
  });
21568
- var upsertHealthEpisodeInputSchema = episodeFields;
21569
- var logDoseFields = logHealthDoseInputSchema.omit({ episodeId: true, source: true }).extend({
21570
- medicationId: ulidSchema.optional(),
21571
- medication: text2(200).optional()
21484
+ var gatewayThreadSchema = object({
21485
+ id: ulidSchema,
21486
+ memberId: string2().min(1),
21487
+ slug: threadSlugSchema.nullable(),
21488
+ title: string2().nullable(),
21489
+ standing: boolean3(),
21490
+ deleted: boolean3().optional()
21572
21491
  });
21573
- var logHealthInputSchema = object({
21574
- episodeId: ulidSchema.optional(),
21575
- episode: upsertHealthEpisodeInputSchema.optional(),
21576
- symptom: logHealthSymptomInputSchema.omit({ source: true }).optional(),
21577
- dose: logDoseFields.refine((d) => !!d.medicationId !== !!d.medication, {
21578
- message: "name the medication by medicationId or by medication, not both"
21579
- }).optional()
21580
- }).strict().refine((v) => !!v.symptom || !!v.dose, { message: "log a symptom, a dose, or both" }).refine((v) => !(v.episodeId && v.episode), {
21581
- message: "name the episode by episodeId or describe it in episode, not both"
21582
- }).refine((v) => !v.symptom || !!v.episodeId || !!v.episode, {
21583
- message: "a symptom needs an episode (episodeId, or episode to find or start one)"
21492
+ var AGENT_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
21493
+ var AGENT_ATTACHMENTS_MAX = 20;
21494
+ var attachmentKindSchema = _enum2(["image", "voice", "audio", "video", "file"]);
21495
+ var gatewayAttachmentSchema = object({
21496
+ id: ulidSchema,
21497
+ kind: attachmentKindSchema,
21498
+ mime: string2().min(1),
21499
+ name: string2(),
21500
+ size: number2().int().nonnegative(),
21501
+ durationMs: number2().int().nonnegative().optional(),
21502
+ transcript: string2().optional()
21584
21503
  });
21585
- var correctHealthInputSchema = object({ entryId: ulidSchema, change: correctHealthSymptomInputSchema }).strict();
21586
- var HEALTH_CHECK_IN_TRENDS = ["better", "same", "worse"];
21587
- var healthCheckInTrendSchema = _enum2(HEALTH_CHECK_IN_TRENDS);
21588
- var healthCheckInInputSchema = object({ trend: healthCheckInTrendSchema }).strict();
21589
- var HEALTH_UNDO_KIND_VALUES = ["entry", "dose", "episode"];
21590
- var healthUndoInputSchema = object({ kind: _enum2(HEALTH_UNDO_KIND_VALUES), id: ulidSchema }).strict();
21591
- var HEALTH_RECEIPT_KIND_VALUES = [
21592
- "symptom",
21593
- "correction",
21594
- "dose",
21595
- "episode",
21596
- "encounter"
21597
- ];
21598
- var healthReceiptItemSchema = object({
21599
- kind: _enum2(HEALTH_RECEIPT_KIND_VALUES),
21600
- id: string2(),
21601
- line: string2(),
21602
- guessed: array(string2()),
21603
- undo: healthUndoInputSchema
21504
+ var AGENT_VOICE_MAX_MS = 5 * 60 * 1000;
21505
+ var AGENT_TRANSCRIPT_MAX = 20000;
21506
+ var inboundMessageSchema = object({
21507
+ id: ulidSchema,
21508
+ threadId: ulidSchema,
21509
+ member: object({ id: string2().min(1), name: string2() }),
21510
+ text: string2(),
21511
+ createdAt: string2().datetime(),
21512
+ attachments: array(gatewayAttachmentSchema).default([]),
21513
+ replyToPostId: ulidSchema.optional(),
21514
+ context: agentPageContextSchema.optional(),
21515
+ history: array(object({ role: _enum2(["member", "agent"]), text: string2() })).optional(),
21516
+ steer: boolean3().optional()
21604
21517
  });
21605
- var healthReceiptSchema = object({
21606
- episode: object({ id: string2(), title: string2(), created: boolean3() }).nullable(),
21607
- items: array(healthReceiptItemSchema),
21608
- entry: healthSymptomEntrySchema.nullable(),
21609
- dose: healthMedicationDoseSchema.nullable()
21518
+ var threadTargetSchema = union([
21519
+ object({ id: ulidSchema }).strict(),
21520
+ object({ slug: threadSlugSchema, memberId: string2().min(1).optional() }).strict()
21521
+ ]);
21522
+ var runStepSchema = object({
21523
+ label: string2().min(1).max(60),
21524
+ state: _enum2(["pending", "active", "done"]).default("pending")
21610
21525
  });
21611
- var healthCourseDaySchema = object({
21612
- day: string2(),
21613
- severity: number2().int().nullable(),
21614
- entries: number2().int()
21526
+ var postRunSchema = object({
21527
+ status: runStatusSchema,
21528
+ steps: array(runStepSchema).max(12).optional()
21615
21529
  });
21616
- var healthTriedSchema = object({
21617
- medicationId: string2(),
21618
- title: string2(),
21619
- doses: number2().int(),
21620
- effects: array(healthDoseEffectSchema),
21621
- lastTakenAt: exports_coerce.date()
21530
+ var POST_RECEIPT_ABOUT_VALUES = ["red_flags"];
21531
+ var postReceiptInputSchema = object({
21532
+ nodeId: ulidSchema,
21533
+ parts: array(ulidSchema).min(1).max(10).optional(),
21534
+ about: _enum2(POST_RECEIPT_ABOUT_VALUES).optional()
21535
+ }).strict();
21536
+ var postReceiptSchema = object({
21537
+ nodeId: string2(),
21538
+ nodeType: string2(),
21539
+ parts: array(string2()).optional(),
21540
+ about: _enum2(POST_RECEIPT_ABOUT_VALUES).optional()
21622
21541
  });
21623
- var healthSummaryLabSchema = object({
21624
- id: string2(),
21625
- specimenAt: exports_coerce.date(),
21626
- labName: string2().nullable(),
21627
- results: array(object({
21628
- name: string2(),
21629
- valueNum: number2().nullable(),
21630
- valueText: string2().nullable(),
21631
- unit: string2().nullable(),
21632
- refLow: number2().nullable(),
21633
- refHigh: number2().nullable(),
21634
- flag: _enum2(["low", "normal", "high"]).nullable()
21635
- }))
21542
+ var POST_TITLE_MAX = 200;
21543
+ var postTitleSchema = string2().trim().min(1).max(POST_TITLE_MAX);
21544
+ var agentPostInputSchema = object({
21545
+ externalId: externalIdSchema,
21546
+ thread: threadTargetSchema,
21547
+ text: postTextSchema,
21548
+ kind: postKindSchema.default("message"),
21549
+ title: postTitleSchema.optional(),
21550
+ level: postLevelSchema.nullish(),
21551
+ replyToMessageId: ulidSchema.optional(),
21552
+ attachments: array(ulidSchema).max(AGENT_ATTACHMENTS_MAX).default([]),
21553
+ final: boolean3().default(true),
21554
+ run: postRunSchema.optional(),
21555
+ recovered: boolean3().optional(),
21556
+ brief: briefSchema.optional(),
21557
+ receipt: postReceiptInputSchema.optional()
21636
21558
  });
21637
- var HEALTH_TREND_KEYS = ["sleep", "weight"];
21638
- var healthTrendSchema = object({
21639
- key: _enum2(HEALTH_TREND_KEYS),
21640
- label: string2(),
21641
- unit: string2(),
21642
- points: array(object({ day: string2(), value: number2() }))
21559
+ var agentPostEditSchema = object({
21560
+ text: postTextSchema.optional(),
21561
+ title: postTitleSchema.optional(),
21562
+ final: boolean3().optional(),
21563
+ level: postLevelSchema.optional(),
21564
+ run: postRunSchema.optional(),
21565
+ brief: briefSchema.optional()
21566
+ }).refine((e) => Object.values(e).some((v) => v !== undefined), {
21567
+ message: "send text, title, final, level, run or brief"
21643
21568
  });
21644
- var healthSummarySchema = object({
21645
- generatedAt: exports_coerce.date(),
21646
- episode: healthEpisodeViewSchema.nullable(),
21647
- course: array(healthCourseDaySchema),
21648
- entries: array(healthSymptomEntrySchema),
21649
- tried: array(healthTriedSchema),
21650
- conditions: array(healthConditionViewSchema),
21651
- medications: array(healthMedicationViewSchema),
21652
- profile: healthProfileSchema,
21653
- gp: object({ id: string2(), name: string2(), phone: string2().nullable() }).nullable(),
21654
- nextVisit: healthEncounterViewSchema.nullable(),
21655
- questions: array(string2()),
21656
- labs: array(healthSummaryLabSchema).default([]),
21657
- trends: array(healthTrendSchema).default([])
21569
+ var agentPostResultSchema = object({ postId: ulidSchema, created: boolean3() });
21570
+ var promptOptionSchema = object({
21571
+ id: string2().min(1).max(40),
21572
+ label: string2().min(1).max(80),
21573
+ style: _enum2(["primary", "danger", ""]).default("")
21658
21574
  });
21659
- var healthSummaryQuerySchema = object({ episodeId: ulidSchema.optional() });
21660
-
21661
- // ../../packages/schema/src/contracts/health-labs.ts
21662
- var LAB_GROUP_VALUES = [
21663
- "vitamins_iron",
21664
- "blood_count",
21665
- "kidney",
21666
- "liver",
21667
- "thyroid",
21668
- "lipids",
21669
- "sugar",
21670
- "inflammation",
21671
- "hormones",
21672
- "other"
21673
- ];
21674
- var labGroupSchema = _enum2(LAB_GROUP_VALUES);
21675
- var HEALTH_LAB_FLAG_VALUES = ["low", "normal", "high"];
21676
- var healthLabFlagSchema = _enum2(HEALTH_LAB_FLAG_VALUES);
21677
- var healthLabPanelStatusSchema = _enum2(["draft", "confirmed"]);
21678
- var labAnalyteKeySchema = string2().regex(/^[a-z0-9]+(_[a-z0-9]+)*$/, "must be lowercase words joined by _").max(80);
21679
- var title2 = string2().trim().min(1).max(200);
21680
- var text3 = (max) => string2().trim().min(1).max(max);
21681
- var instant2 = exports_coerce.date();
21682
- var amount = number2().finite();
21683
- var healthLabResultSchema = createSelectSchema(healthLabResults, {
21684
- valueNum: number2().nullable(),
21685
- refLow: number2().nullable(),
21686
- refHigh: number2().nullable()
21575
+ var agentPromptSchema = object({
21576
+ promptId: string2().min(1).max(100),
21577
+ threadId: ulidSchema,
21578
+ kind: _enum2(["exec_approval", "clarify", "slash_confirm"]),
21579
+ text: postTextSchema,
21580
+ options: array(promptOptionSchema).min(1).max(12),
21581
+ allowText: boolean3().default(false),
21582
+ expiresAt: string2().datetime(),
21583
+ command: string2().optional(),
21584
+ description: string2().optional()
21687
21585
  });
21688
- var healthLabPanelViewSchema = createSelectSchema(healthLabPanels, {
21689
- specimenAt: exports_coerce.date()
21690
- }).extend({
21691
- title: string2(),
21692
- createdAt: exports_coerce.date(),
21693
- updatedAt: exports_coerce.date(),
21694
- orderedByName: string2().nullable(),
21695
- results: array(healthLabResultSchema),
21696
- unmatched: array(string2()).optional()
21586
+ var agentGatewayErrorCodeSchema = _enum2([
21587
+ "bad_request",
21588
+ "not_found",
21589
+ "thread_not_found",
21590
+ "not_member",
21591
+ "too_large",
21592
+ "rate_limited",
21593
+ "unsupported",
21594
+ "internal"
21595
+ ]);
21596
+ var agentGatewayErrorSchema = object({
21597
+ code: agentGatewayErrorCodeSchema,
21598
+ message: string2(),
21599
+ retryable: boolean3()
21600
+ });
21601
+ var frame = (type, shape) => object({
21602
+ v: literal(AGENT_GATEWAY_VERSION),
21603
+ type: literal(type),
21604
+ id: string2().min(1).max(64),
21605
+ ...shape
21606
+ });
21607
+ var readyFrameSchema = frame("ready", {
21608
+ space: object({
21609
+ id: string2().min(1),
21610
+ name: string2(),
21611
+ ownerMemberId: string2().min(1)
21612
+ }),
21613
+ agent: object({
21614
+ id: string2().min(1),
21615
+ name: string2(),
21616
+ homeSlug: threadSlugSchema
21617
+ }),
21618
+ members: array(gatewayMemberSchema),
21619
+ threads: array(gatewayThreadSchema),
21620
+ heartbeatSec: number2().int().positive(),
21621
+ hints: array(string2()).default([])
21622
+ });
21623
+ var membersFrameSchema = frame("members", { members: array(gatewayMemberSchema) });
21624
+ var threadsFrameSchema = frame("threads", { threads: array(gatewayThreadSchema) });
21625
+ var messageFrameSchema = frame("message", { message: inboundMessageSchema });
21626
+ var promptAnswerFrameSchema = frame("prompt.answer", {
21627
+ promptId: string2().min(1),
21628
+ optionId: string2().min(1),
21629
+ text: string2().optional(),
21630
+ memberId: string2().min(1),
21631
+ threadId: ulidSchema
21632
+ });
21633
+ var confirmationOutcomeFrameSchema = frame("confirmation.outcome", {
21634
+ confirmationId: string2().min(1),
21635
+ memberId: string2().min(1),
21636
+ threadId: ulidSchema.nullable(),
21637
+ outcome: _enum2(["done", "failed", "declined"]),
21638
+ text: string2()
21697
21639
  });
21698
- var healthLabPointSchema = object({
21699
- resultId: string2(),
21700
- panelId: string2(),
21701
- specimenAt: exports_coerce.date(),
21702
- labName: string2().nullable(),
21703
- status: healthLabPanelStatusSchema,
21704
- valueNum: number2().nullable(),
21705
- valueText: string2().nullable(),
21706
- unit: string2().nullable(),
21707
- refLow: number2().nullable(),
21708
- refHigh: number2().nullable(),
21709
- flag: healthLabFlagSchema.nullable(),
21710
- fileId: string2().nullable(),
21711
- fileMime: string2().nullable().default(null),
21712
- source: healthEntrySourceSchema.default("manual")
21640
+ var interruptFrameSchema = frame("interrupt", {
21641
+ threadId: ulidSchema,
21642
+ memberId: string2().min(1)
21713
21643
  });
21714
- var healthLabAnalyteViewSchema = object({
21715
- analyte: string2(),
21716
- name: string2(),
21717
- group: labGroupSchema,
21718
- loinc: string2().nullable(),
21719
- unit: string2().nullable(),
21720
- points: array(healthLabPointSchema),
21721
- target: object({
21722
- low: number2().nullable(),
21723
- high: number2().nullable(),
21724
- byContactId: string2().nullable(),
21725
- byName: string2().nullable(),
21726
- note: string2().nullable()
21727
- }).nullable(),
21728
- medication: object({
21729
- id: string2(),
21730
- title: string2(),
21731
- dose: string2().nullable(),
21732
- schedule: healthMedicationScheduleSchema,
21733
- habitId: string2().nullable()
21734
- }).nullable()
21644
+ var ackFrameSchema = frame("ack", {
21645
+ ref: string2().min(1),
21646
+ ok: boolean3(),
21647
+ postId: ulidSchema.optional(),
21648
+ created: boolean3().optional(),
21649
+ error: agentGatewayErrorSchema.optional()
21735
21650
  });
21736
- var healthLabOverviewSchema = object({
21737
- draws: number2().int(),
21738
- firstAt: exports_coerce.date().nullable(),
21739
- lastAt: exports_coerce.date().nullable(),
21740
- lastLab: string2().nullable(),
21741
- analytes: array(healthLabAnalyteViewSchema)
21651
+ var unseenPostSchema = object({
21652
+ postId: ulidSchema,
21653
+ threadId: ulidSchema,
21654
+ memberId: string2().min(1),
21655
+ title: string2(),
21656
+ threadTitle: string2().nullable(),
21657
+ path: string2().startsWith("/"),
21658
+ url: string2().url().nullable(),
21659
+ pushedAt: string2().datetime()
21742
21660
  });
21743
- var healthLabResultInputSchema = object({
21744
- id: ulidSchema.optional(),
21745
- analyte: labAnalyteKeySchema.optional(),
21746
- name: title2,
21747
- group: labGroupSchema.optional(),
21748
- loinc: text3(20).nullish(),
21749
- valueNum: amount.nullish(),
21750
- valueText: text3(200).nullish(),
21751
- unit: text3(40).nullish(),
21752
- refLow: amount.nullish(),
21753
- refHigh: amount.nullish(),
21754
- flag: healthLabFlagSchema.nullish(),
21755
- comment: text3(1000).nullish()
21756
- }).strict().refine((r) => r.valueNum != null || r.valueText != null, {
21757
- message: "a result needs valueNum or valueText"
21661
+ var postUnseenFrameSchema = frame("post.unseen", { post: unseenPostSchema });
21662
+ var agentGatewayServerFrameSchema = discriminatedUnion("type", [
21663
+ readyFrameSchema,
21664
+ membersFrameSchema,
21665
+ threadsFrameSchema,
21666
+ messageFrameSchema,
21667
+ promptAnswerFrameSchema,
21668
+ interruptFrameSchema,
21669
+ confirmationOutcomeFrameSchema,
21670
+ ackFrameSchema,
21671
+ postUnseenFrameSchema
21672
+ ]);
21673
+ var messageAckFrameSchema = frame("message.ack", { messageId: ulidSchema });
21674
+ var postFrameSchema = frame("post", { post: agentPostInputSchema });
21675
+ var postEditFrameSchema = frame("post.edit", {
21676
+ postId: ulidSchema,
21677
+ edit: agentPostEditSchema
21758
21678
  });
21759
- var createHealthLabPanelInputSchema = object({
21760
- id: ulidSchema.optional(),
21761
- title: title2.optional(),
21762
- specimenAt: instant2,
21763
- labName: text3(200).nullish(),
21764
- orderedByContactId: ulidSchema.nullish(),
21765
- encounterId: ulidSchema.nullish(),
21766
- fileId: ulidSchema.nullish(),
21767
- status: healthLabPanelStatusSchema.optional(),
21768
- source: healthEntrySourceSchema.optional(),
21769
- note: text3(2000).nullish(),
21770
- results: array(healthLabResultInputSchema).max(200).optional(),
21771
- subjectNodeId: ulidSchema.nullish()
21772
- }).strict();
21773
- var updateHealthLabPanelInputSchema = createHealthLabPanelInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21774
- var healthLabImportFieldsSchema = object({ text: string2().max(200000).optional() }).strict();
21775
- var healthLabImportResultSchema = object({
21776
- format: _enum2(["kmehr", "pdf"]),
21777
- found: number2().int(),
21778
- panel: healthLabPanelViewSchema
21679
+ var postDeleteFrameSchema = frame("post.delete", { postId: ulidSchema });
21680
+ var typingFrameSchema = frame("typing", { threadId: ulidSchema, on: boolean3() });
21681
+ var promptFrameSchema = frame("prompt", { prompt: agentPromptSchema });
21682
+ var promptCloseFrameSchema = frame("prompt.close", {
21683
+ promptId: string2().min(1),
21684
+ optionId: string2().optional(),
21685
+ expired: boolean3()
21779
21686
  });
21780
- var setHealthLabAnalyteInputSchema = object({
21781
- targetLow: amount.nullish(),
21782
- targetHigh: amount.nullish(),
21783
- targetByContactId: ulidSchema.nullish(),
21784
- medicationId: ulidSchema.nullish(),
21785
- note: text3(1000).nullish()
21786
- }).strict().refine((t) => t.targetLow == null || t.targetHigh == null || t.targetLow <= t.targetHigh, {
21787
- message: "targetLow must not be above targetHigh"
21687
+ var attachmentTranscriptFrameSchema = frame("attachment.transcript", {
21688
+ attachmentId: ulidSchema,
21689
+ text: string2().trim().min(1).max(AGENT_TRANSCRIPT_MAX)
21788
21690
  });
21691
+ var postUnseenAckFrameSchema = frame("post.unseen.ack", { postId: ulidSchema });
21692
+ var agentGatewayClientFrameSchema = discriminatedUnion("type", [
21693
+ messageAckFrameSchema,
21694
+ postUnseenAckFrameSchema,
21695
+ postFrameSchema,
21696
+ postEditFrameSchema,
21697
+ postDeleteFrameSchema,
21698
+ typingFrameSchema,
21699
+ promptFrameSchema,
21700
+ promptCloseFrameSchema,
21701
+ attachmentTranscriptFrameSchema
21702
+ ]);
21703
+ var SERVER_FRAME_TYPES = new Set(agentGatewayServerFrameSchema.options.map((o) => o.shape.type.value));
21704
+ var CLIENT_FRAME_TYPES = new Set(agentGatewayClientFrameSchema.options.map((o) => o.shape.type.value));
21705
+ var agentThreadsResponseSchema = object({ threads: array(gatewayThreadSchema) });
21706
+ function homeSlugFor(agentName) {
21707
+ const slug = agentName.normalize("NFKD").replace(/[\u0300-\u036F]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "");
21708
+ return slug || "agent";
21709
+ }
21789
21710
 
21790
- // ../../packages/schema/src/contracts/agent-chat.ts
21791
- var agentConnectionSourceSchema = _enum2(["space", "env"]);
21792
- var agentGatewayStatusSchema = _enum2(["connected", "offline", "not_connected"]);
21793
- var agentGatewayStateSchema = object({
21794
- status: agentGatewayStatusSchema,
21795
- connectedAt: exports_coerce.date().nullable(),
21796
- seenAt: exports_coerce.date().nullable(),
21797
- disconnectedAt: exports_coerce.date().nullable()
21711
+ // ../../packages/schema/src/contracts/health-records.ts
21712
+ var BODY_REGION_VALUES = [
21713
+ "head",
21714
+ "face",
21715
+ "eyes",
21716
+ "ears",
21717
+ "nose",
21718
+ "mouth",
21719
+ "throat",
21720
+ "neck",
21721
+ "chest",
21722
+ "upper_back",
21723
+ "lower_back",
21724
+ "epigastric",
21725
+ "ruq",
21726
+ "luq",
21727
+ "periumbilical",
21728
+ "rlq",
21729
+ "llq",
21730
+ "lower_abdomen",
21731
+ "pelvis",
21732
+ "shoulder_l",
21733
+ "shoulder_r",
21734
+ "arm_l",
21735
+ "arm_r",
21736
+ "elbow_l",
21737
+ "elbow_r",
21738
+ "wrist_l",
21739
+ "wrist_r",
21740
+ "hand_l",
21741
+ "hand_r",
21742
+ "hip_l",
21743
+ "hip_r",
21744
+ "thigh_l",
21745
+ "thigh_r",
21746
+ "knee_l",
21747
+ "knee_r",
21748
+ "calf_l",
21749
+ "calf_r",
21750
+ "ankle_l",
21751
+ "ankle_r",
21752
+ "foot_l",
21753
+ "foot_r",
21754
+ "skin",
21755
+ "whole_body"
21756
+ ];
21757
+ var bodyRegionSchema = _enum2(BODY_REGION_VALUES);
21758
+ var RED_FLAG_VALUES = [
21759
+ "fever",
21760
+ "vomiting",
21761
+ "black_stools",
21762
+ "blood",
21763
+ "weight_loss",
21764
+ "night_pain",
21765
+ "chest_pain",
21766
+ "short_of_breath"
21767
+ ];
21768
+ var redFlagSchema = _enum2(RED_FLAG_VALUES);
21769
+ var redFlagsSchema = partialRecord(redFlagSchema, boolean3());
21770
+ var HEALTH_CONDITION_STATUS_VALUES = [
21771
+ "active",
21772
+ "managed",
21773
+ "resolved",
21774
+ "suspected"
21775
+ ];
21776
+ var healthConditionStatusSchema = _enum2(HEALTH_CONDITION_STATUS_VALUES);
21777
+ var HEALTH_EPISODE_STATUS_VALUES = ["open", "watching", "resolved"];
21778
+ var healthEpisodeStatusSchema = _enum2(HEALTH_EPISODE_STATUS_VALUES);
21779
+ var HEALTH_ENCOUNTER_KIND_VALUES = [
21780
+ "gp",
21781
+ "specialist",
21782
+ "physio",
21783
+ "dentist",
21784
+ "lab_draw",
21785
+ "er",
21786
+ "tele",
21787
+ "other"
21788
+ ];
21789
+ var healthEncounterKindSchema = _enum2(HEALTH_ENCOUNTER_KIND_VALUES);
21790
+ var healthMedicationKindSchema = _enum2(["drug", "supplement"]);
21791
+ var healthMedicationScheduleSchema = _enum2(["scheduled", "as_needed"]);
21792
+ var HEALTH_DOSE_EFFECT_VALUES = ["none", "a_little", "helped", "worse"];
21793
+ var healthDoseEffectSchema = _enum2(HEALTH_DOSE_EFFECT_VALUES);
21794
+ var healthEntrySourceSchema = _enum2(["chat", "manual", "import"]);
21795
+ var severitySchema = number2().int().min(0).max(10);
21796
+ var fuzzyDateSchema = string2().regex(/^\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12]\d|3[01]))?)?$/, "must be YYYY, YYYY-MM or YYYY-MM-DD");
21797
+ var civilDateSchema2 = string2().regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD");
21798
+ var title = string2().trim().min(1).max(200);
21799
+ var text2 = (max) => string2().trim().min(1).max(max);
21800
+ var instant = exports_coerce.date();
21801
+ var spine = {
21802
+ title: string2(),
21803
+ createdAt: exports_coerce.date(),
21804
+ updatedAt: exports_coerce.date()
21805
+ };
21806
+ var healthCareTeamMemberSchema = object({
21807
+ contactId: string2(),
21808
+ name: string2(),
21809
+ phone: string2().nullable(),
21810
+ label: string2().nullable()
21798
21811
  });
21799
- var agentConnectionSchema = object({
21800
- connected: boolean3(),
21801
- source: agentConnectionSourceSchema.nullable(),
21802
- endpoint: string2().nullable(),
21803
- model: string2().nullable(),
21804
- hasKey: boolean3(),
21805
- agentId: string2().nullable(),
21806
- agentName: string2().nullable().default(null),
21807
- autoFile: boolean3(),
21808
- updatedAt: exports_coerce.date().nullable(),
21809
- gateway: agentGatewayStateSchema.nullable().default(null)
21812
+ var healthConditionViewSchema = createSelectSchema(healthConditions, {
21813
+ bodyRegions: array(string2())
21814
+ }).extend({
21815
+ ...spine,
21816
+ careTeam: array(healthCareTeamMemberSchema).default([])
21810
21817
  });
21811
- var agentEndpointSchema = string2().trim().max(2000).url().refine((value) => /^https?:\/\//i.test(value), "endpoint must be an http(s) URL");
21812
- var saveAgentConnectionInputSchema = object({
21813
- endpoint: agentEndpointSchema.nullable(),
21814
- apiKey: string2().trim().min(1).max(4000).nullable().optional(),
21815
- model: string2().trim().min(1).max(200).nullable().optional(),
21816
- agentId: string2().trim().min(1).max(64).nullable().optional(),
21817
- autoFile: boolean3().optional()
21818
- }).strict().refine((input) => input.endpoint !== null || Boolean(input.agentId), {
21819
- message: "a connection without an endpoint names its agent",
21820
- path: ["agentId"]
21818
+ var healthEpisodeViewSchema = createSelectSchema(healthEpisodes, {
21819
+ startedAt: exports_coerce.date(),
21820
+ endedAt: exports_coerce.date().nullable(),
21821
+ redFlags: redFlagsSchema,
21822
+ redFlagsCheckedAt: exports_coerce.date().nullable()
21823
+ }).extend({
21824
+ ...spine,
21825
+ latestSeverity: number2().int().nullable(),
21826
+ lastEntryAt: exports_coerce.date().nullable()
21821
21827
  });
21822
- var agentPageContextSchema = object({
21823
- route: string2().trim().min(1).max(500).startsWith("/"),
21824
- nodeId: string2().trim().min(1).max(64).nullable(),
21825
- focusArea: object({
21826
- id: string2().trim().min(1).max(64),
21827
- title: string2().trim().min(1).max(200)
21828
- }).nullish()
21829
- }).strict();
21830
- var echoDeviceSchema = _enum2(["phone", "desktop"]);
21831
- var agentChatInputSchema = object({
21832
- message: string2().trim().max(8000),
21833
- context: agentPageContextSchema,
21834
- threadId: string2().trim().min(1).max(64).optional(),
21835
- steer: boolean3().optional(),
21836
- attachments: array(string2().trim().min(1).max(64)).max(20).optional(),
21837
- replyTo: string2().trim().min(1).max(64).optional(),
21838
- device: echoDeviceSchema.optional()
21839
- }).strict().refine((input) => input.message.length > 0 || (input.attachments?.length ?? 0) > 0, {
21840
- message: "write something or attach a file",
21841
- path: ["message"]
21828
+ var healthSymptomEntrySchema = createSelectSchema(healthSymptomEntries, {
21829
+ occurredAt: exports_coerce.date(),
21830
+ recordedAt: exports_coerce.date(),
21831
+ qualifiers: record(string2(), unknown())
21842
21832
  });
21843
- var agentChatStopInputSchema = object({ threadId: string2().trim().min(1).max(64) }).strict();
21844
- var agentChatStopResultSchema = object({ stop: _enum2(["sent", "offline"]) });
21845
- var agentChatEventSchema = discriminatedUnion("type", [
21846
- object({
21847
- type: literal("turn"),
21848
- id: string2(),
21849
- threadId: string2(),
21850
- since: string2().nullable()
21851
- }),
21852
- object({ type: literal("delta"), text: string2() }),
21853
- object({ type: literal("done") }),
21854
- object({ type: literal("error"), message: string2() }),
21855
- object({
21856
- type: literal("posted"),
21857
- threadId: string2(),
21858
- postId: string2(),
21859
- delivery: _enum2(["sent", "waiting"])
21860
- })
21861
- ]);
21862
- var agentChangeValueSchema = union([
21863
- string2(),
21864
- number2(),
21865
- boolean3(),
21866
- _null3(),
21867
- array(string2())
21868
- ]);
21869
- var agentChangeFieldSchema = object({
21870
- field: string2(),
21871
- before: agentChangeValueSchema,
21872
- after: agentChangeValueSchema,
21873
- beforeLabel: string2().nullable().optional(),
21874
- afterLabel: string2().nullable().optional()
21833
+ var healthEncounterViewSchema = createSelectSchema(healthEncounters, {
21834
+ at: exports_coerce.date(),
21835
+ followUpAt: exports_coerce.date().nullable(),
21836
+ questions: array(string2())
21837
+ }).extend({
21838
+ ...spine,
21839
+ providerName: string2().nullable()
21875
21840
  });
21876
- var agentChangeSchema = object({
21877
- entity: changeEntitySchema,
21878
- id: string2(),
21879
- op: changeOpSchema,
21880
- changedAt: exports_coerce.date(),
21881
- title: string2().nullable(),
21882
- actor: actorRefSchema,
21883
- cursor: string2().optional(),
21884
- fields: array(agentChangeFieldSchema).optional(),
21885
- checkIn: object({
21886
- value: number2(),
21887
- unit: string2().nullable(),
21888
- measurementType: habitMeasurementTypeSchema
21889
- }).optional()
21841
+ var healthMedicationViewSchema = createSelectSchema(healthMedications).extend({
21842
+ ...spine,
21843
+ lastTakenAt: exports_coerce.date().nullable()
21890
21844
  });
21891
- var agentChangesPageSchema = object({
21892
- data: array(agentChangeSchema),
21893
- nextCursor: string2()
21845
+ var healthMedicationDoseSchema = createSelectSchema(healthMedicationDoses, {
21846
+ takenAt: exports_coerce.date(),
21847
+ createdAt: exports_coerce.date()
21848
+ }).extend({
21849
+ medicationTitle: string2()
21894
21850
  });
21895
- var agentChangesQuerySchema = object({
21896
- since: string2().refine((s) => s === "now" || /^\d+-\d+$/.test(s), {
21897
- message: "since must be a cursor from a prior page's nextCursor, or 'now'"
21898
- }),
21899
- node: string2().trim().min(1).max(64).optional()
21851
+ var healthEpisodeDetailSchema = healthEpisodeViewSchema.extend({
21852
+ entries: array(healthSymptomEntrySchema),
21853
+ doses: array(healthMedicationDoseSchema),
21854
+ encounters: array(healthEncounterViewSchema),
21855
+ condition: healthConditionViewSchema.nullable()
21900
21856
  });
21901
- var agentConfirmationKindSchema = _enum2(["delete", "cancel", "google", "orca", "bulk"]);
21902
- var agentConfirmationStatusSchema = _enum2([
21903
- "pending",
21904
- "confirmed",
21905
- "done",
21906
- "failed",
21907
- "declined"
21908
- ]);
21909
- var agentConfirmationItemSchema = object({
21910
- id: string2(),
21911
- title: string2().nullable(),
21912
- area: string2().nullable().optional(),
21913
- dueAt: exports_coerce.date().nullable().optional()
21857
+ var healthProfileSchema = createSelectSchema(healthProfiles, {
21858
+ allergies: array(string2()),
21859
+ updatedAt: exports_coerce.date()
21860
+ }).extend({
21861
+ notes: string2().nullable().default(null),
21862
+ sex: string2().nullable().default(null)
21914
21863
  });
21915
- var agentConfirmationSchema = object({
21916
- id: string2(),
21917
- kind: agentConfirmationKindSchema,
21918
- summary: string2(),
21919
- items: array(agentConfirmationItemSchema),
21920
- method: string2(),
21921
- path: string2(),
21922
- status: agentConfirmationStatusSchema,
21923
- agent: object({ id: string2(), name: string2().nullable() }),
21924
- createdAt: exports_coerce.date(),
21925
- decidedAt: exports_coerce.date().nullable()
21864
+ var healthConsentStateSchema = object({
21865
+ granted: boolean3(),
21866
+ version: string2().nullable(),
21867
+ grantedAt: exports_coerce.date().nullable()
21926
21868
  });
21927
- var agentUndoInputSchema = object({
21928
- id: string2().trim().min(1).max(64),
21929
- since: string2().regex(/^\d+-\d+$/, "since must be a change-feed cursor")
21869
+ var HEALTH_CONSENT_VERSION = "2026-10-18";
21870
+ var subject = { subjectNodeId: ulidSchema.nullish() };
21871
+ var createHealthConditionInputSchema = object({
21872
+ id: ulidSchema.optional(),
21873
+ title,
21874
+ status: healthConditionStatusSchema.optional(),
21875
+ onset: fuzzyDateSchema.nullish(),
21876
+ resolvedOn: civilDateSchema2.nullish(),
21877
+ bodyRegions: array(bodyRegionSchema).max(10).optional(),
21878
+ code: text2(40).nullish(),
21879
+ notes: text2(4000).nullish(),
21880
+ ...subject
21930
21881
  }).strict();
21931
- var agentUndoResultSchema = object({
21932
- id: string2(),
21933
- undone: _enum2(["removed", "restored"])
21934
- });
21935
- var agentRedoResultSchema = object({
21936
- id: string2(),
21937
- redone: literal(true)
21938
- });
21939
- var agentFilingSchema = object({
21940
- confident: boolean3().default(false),
21941
- areaId: string2().nullable().optional(),
21942
- owner: string2().nullable().optional(),
21943
- date: string2().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional()
21882
+ var addHealthCareTeamInputSchema = object({ contactId: ulidSchema, label: text2(60).nullish() }).strict();
21883
+ var updateHealthConditionInputSchema = createHealthConditionInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21884
+ var episodeFields = object({
21885
+ id: ulidSchema.optional(),
21886
+ title,
21887
+ status: healthEpisodeStatusSchema.optional(),
21888
+ startedAt: instant.optional(),
21889
+ bodyRegion: bodyRegionSchema.nullish(),
21890
+ triggerText: text2(500).nullish(),
21891
+ summary: text2(500).nullish(),
21892
+ conditionId: ulidSchema.nullish(),
21893
+ ...subject
21894
+ }).strict();
21895
+ var createHealthEpisodeInputSchema = episodeFields.extend({ endedAt: instant.nullish() }).strict().superRefine((v, ctx) => {
21896
+ if (!v.endedAt)
21897
+ return;
21898
+ if (v.status && v.status !== "resolved") {
21899
+ ctx.addIssue({
21900
+ code: "custom",
21901
+ path: ["endedAt"],
21902
+ message: "only a resolved episode has an end"
21903
+ });
21904
+ }
21905
+ if (v.endedAt.getTime() > Date.now()) {
21906
+ ctx.addIssue({ code: "custom", path: ["endedAt"], message: "can't end in the future" });
21907
+ }
21908
+ if (v.endedAt.getTime() < (v.startedAt ?? new Date).getTime()) {
21909
+ ctx.addIssue({ code: "custom", path: ["endedAt"], message: "can't end before it started" });
21910
+ }
21944
21911
  });
21945
-
21946
- // ../../packages/schema/src/contracts/agent-gateway.ts
21947
- var AGENT_GATEWAY_VERSION = 1;
21948
- var AGENT_GATEWAY_MAX_FRAME_BYTES = 1024 * 1024;
21949
- var threadSlugSchema = string2().regex(/^[a-z0-9][a-z0-9-]{0,39}$/, "a thread slug is lower-case, like `build`");
21950
- var postLevelSchema = _enum2(["needs_you", "told", "for_later", "silent"]);
21951
- var postKindSchema = _enum2(["message", "brief", "card", "run"]);
21952
- var runStatusSchema = _enum2(["running", "needs_you", "done", "failed", "stopped"]);
21953
- var externalIdSchema = string2().min(1).max(200).regex(/^[\x21-\x7e]+$/, "printable ASCII without spaces");
21954
- var AGENT_POST_TEXT_MAX = 64000;
21955
- var postTextSchema = string2().max(AGENT_POST_TEXT_MAX);
21956
- var briefVerbSchema = object({
21957
- label: string2().trim().min(1).max(24),
21958
- href: string2().max(2000).regex(/^(\/(?!\/)|https:\/\/)/, "a path in do (`/tasks`) or an https link").optional(),
21959
- say: string2().trim().min(1).max(500).optional()
21960
- }).strict().refine((v) => v.href === undefined !== (v.say === undefined), {
21961
- message: "a verb has either href or say"
21912
+ var updateHealthEpisodeInputSchema = episodeFields.omit({ id: true, subjectNodeId: true }).extend({
21913
+ endedAt: instant.nullish(),
21914
+ redFlags: redFlagsSchema.optional()
21915
+ }).partial().strict();
21916
+ var symptomFields = {
21917
+ symptom: text2(200),
21918
+ occurredAt: instant.optional(),
21919
+ bodyRegion: bodyRegionSchema.nullish(),
21920
+ severity: severitySchema.nullish(),
21921
+ severityGuessed: boolean3().optional(),
21922
+ qualifiers: record(string2(), unknown()).optional(),
21923
+ note: text2(2000).nullish(),
21924
+ source: healthEntrySourceSchema.optional()
21925
+ };
21926
+ var logHealthSymptomInputSchema = object({ id: ulidSchema.optional(), ...symptomFields }).strict();
21927
+ var correctHealthSymptomInputSchema = object({ id: ulidSchema.optional(), ...symptomFields }).partial().strict().refine((v) => Object.keys(v).some((k) => k !== "id" && k !== "source"), {
21928
+ message: "a correction must change something"
21962
21929
  });
21963
- var briefRowSchema = object({
21964
- text: string2().trim().min(1).max(200),
21965
- meta: string2().trim().max(200).optional(),
21966
- icon: string2().max(24).optional(),
21967
- verb: briefVerbSchema.optional()
21930
+ var createHealthEncounterInputSchema = object({
21931
+ id: ulidSchema.optional(),
21932
+ title: title.optional(),
21933
+ kind: healthEncounterKindSchema.optional(),
21934
+ at: instant,
21935
+ episodeId: ulidSchema.nullish(),
21936
+ providerContactId: ulidSchema.nullish(),
21937
+ placeId: ulidSchema.nullish(),
21938
+ eventId: ulidSchema.nullish(),
21939
+ reason: text2(500).nullish(),
21940
+ questions: array(text2(300)).max(30).optional(),
21941
+ outcome: text2(4000).nullish(),
21942
+ followUpAt: instant.nullish(),
21943
+ ...subject
21968
21944
  }).strict();
21969
- var BRIEF_ROWS_MAX = 8;
21970
- var briefSchema = object({
21971
- label: string2().trim().min(1).max(40),
21972
- title: string2().trim().min(1).max(200),
21973
- rows: array(briefRowSchema).max(BRIEF_ROWS_MAX).default([])
21945
+ var updateHealthEncounterInputSchema = createHealthEncounterInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21946
+ var createHealthMedicationInputSchema = object({
21947
+ id: ulidSchema.optional(),
21948
+ title,
21949
+ kind: healthMedicationKindSchema.optional(),
21950
+ schedule: healthMedicationScheduleSchema.optional(),
21951
+ ingredient: text2(200).nullish(),
21952
+ dose: text2(100).nullish(),
21953
+ form: text2(100).nullish(),
21954
+ startedOn: civilDateSchema2.nullish(),
21955
+ stoppedOn: civilDateSchema2.nullish(),
21956
+ reason: text2(500).nullish(),
21957
+ prescribedByContactId: ulidSchema.nullish(),
21958
+ habitId: ulidSchema.nullish(),
21959
+ ...subject
21974
21960
  }).strict();
21975
- var gatewayMemberSchema = object({
21976
- id: string2().min(1),
21977
- name: string2(),
21978
- role: baseRoleSchema
21979
- });
21980
- var gatewayThreadSchema = object({
21981
- id: ulidSchema,
21982
- memberId: string2().min(1),
21983
- slug: threadSlugSchema.nullable(),
21984
- title: string2().nullable(),
21985
- standing: boolean3(),
21986
- deleted: boolean3().optional()
21987
- });
21988
- var AGENT_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
21989
- var AGENT_ATTACHMENTS_MAX = 20;
21990
- var attachmentKindSchema = _enum2(["image", "voice", "audio", "video", "file"]);
21991
- var gatewayAttachmentSchema = object({
21992
- id: ulidSchema,
21993
- kind: attachmentKindSchema,
21994
- mime: string2().min(1),
21995
- name: string2(),
21996
- size: number2().int().nonnegative(),
21997
- durationMs: number2().int().nonnegative().optional(),
21998
- transcript: string2().optional()
21999
- });
22000
- var AGENT_VOICE_MAX_MS = 5 * 60 * 1000;
22001
- var AGENT_TRANSCRIPT_MAX = 20000;
22002
- var inboundMessageSchema = object({
22003
- id: ulidSchema,
22004
- threadId: ulidSchema,
22005
- member: object({ id: string2().min(1), name: string2() }),
22006
- text: string2(),
22007
- createdAt: string2().datetime(),
22008
- attachments: array(gatewayAttachmentSchema).default([]),
22009
- replyToPostId: ulidSchema.optional(),
22010
- context: agentPageContextSchema.optional(),
22011
- history: array(object({ role: _enum2(["member", "agent"]), text: string2() })).optional(),
22012
- steer: boolean3().optional()
22013
- });
22014
- var threadTargetSchema = union([
22015
- object({ id: ulidSchema }).strict(),
22016
- object({ slug: threadSlugSchema, memberId: string2().min(1).optional() }).strict()
22017
- ]);
22018
- var runStepSchema = object({
22019
- label: string2().min(1).max(60),
22020
- state: _enum2(["pending", "active", "done"]).default("pending")
22021
- });
22022
- var postRunSchema = object({
22023
- status: runStatusSchema,
22024
- steps: array(runStepSchema).max(12).optional()
21961
+ var updateHealthMedicationInputSchema = createHealthMedicationInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
21962
+ var logHealthDoseInputSchema = object({
21963
+ id: ulidSchema.optional(),
21964
+ takenAt: instant.optional(),
21965
+ amount: text2(100).nullish(),
21966
+ effect: healthDoseEffectSchema.nullish(),
21967
+ note: text2(1000).nullish(),
21968
+ episodeId: ulidSchema.nullish(),
21969
+ source: healthEntrySourceSchema.optional()
21970
+ }).strict();
21971
+ var updateHealthDoseInputSchema = logHealthDoseInputSchema.omit({ id: true, source: true }).partial().strict();
21972
+ var updateHealthProfileInputSchema = object({
21973
+ bloodGroup: string2().regex(/^(A|B|AB|O)[+-]$/, "must be like A+ or O-").nullish(),
21974
+ allergies: array(text2(100)).max(30).optional(),
21975
+ heightCm: number2().min(30).max(260).nullish(),
21976
+ sex: text2(40).nullish(),
21977
+ alcohol: text2(200).nullish(),
21978
+ smoking: text2(200).nullish(),
21979
+ exercise: text2(200).nullish(),
21980
+ notes: text2(2000).nullish(),
21981
+ emergencyContactId: ulidSchema.nullish(),
21982
+ primaryGpContactId: ulidSchema.nullish()
21983
+ }).strict();
21984
+ var grantHealthConsentInputSchema = object({ version: literal(HEALTH_CONSENT_VERSION) }).strict();
21985
+ var healthEpisodeListQuerySchema = object({
21986
+ status: healthEpisodeStatusSchema.optional()
22025
21987
  });
22026
- var postReceiptInputSchema = object({ nodeId: ulidSchema }).strict();
22027
- var postReceiptSchema = object({ nodeId: string2(), nodeType: string2() });
22028
- var POST_TITLE_MAX = 200;
22029
- var postTitleSchema = string2().trim().min(1).max(POST_TITLE_MAX);
22030
- var agentPostInputSchema = object({
22031
- externalId: externalIdSchema,
22032
- thread: threadTargetSchema,
22033
- text: postTextSchema,
22034
- kind: postKindSchema.default("message"),
22035
- title: postTitleSchema.optional(),
22036
- level: postLevelSchema.nullish(),
22037
- replyToMessageId: ulidSchema.optional(),
22038
- attachments: array(ulidSchema).max(AGENT_ATTACHMENTS_MAX).default([]),
22039
- final: boolean3().default(true),
22040
- run: postRunSchema.optional(),
22041
- recovered: boolean3().optional(),
22042
- brief: briefSchema.optional(),
22043
- receipt: postReceiptInputSchema.optional()
21988
+ var upsertHealthEpisodeInputSchema = episodeFields;
21989
+ var logDoseFields = logHealthDoseInputSchema.omit({ episodeId: true, source: true }).extend({
21990
+ medicationId: ulidSchema.optional(),
21991
+ medication: text2(200).optional()
22044
21992
  });
22045
- var agentPostEditSchema = object({
22046
- text: postTextSchema.optional(),
22047
- title: postTitleSchema.optional(),
22048
- final: boolean3().optional(),
22049
- level: postLevelSchema.optional(),
22050
- run: postRunSchema.optional(),
22051
- brief: briefSchema.optional()
22052
- }).refine((e) => Object.values(e).some((v) => v !== undefined), {
22053
- message: "send text, title, final, level, run or brief"
21993
+ var logHealthInputSchema = object({
21994
+ episodeId: ulidSchema.optional(),
21995
+ episode: upsertHealthEpisodeInputSchema.optional(),
21996
+ symptom: logHealthSymptomInputSchema.omit({ source: true }).optional(),
21997
+ dose: logDoseFields.refine((d) => !!d.medicationId !== !!d.medication, {
21998
+ message: "name the medication by medicationId or by medication, not both"
21999
+ }).optional(),
22000
+ thread: threadTargetSchema.optional()
22001
+ }).strict().refine((v) => !!v.symptom || !!v.dose, { message: "log a symptom, a dose, or both" }).refine((v) => !(v.episodeId && v.episode), {
22002
+ message: "name the episode by episodeId or describe it in episode, not both"
22003
+ }).refine((v) => !v.symptom || !!v.episodeId || !!v.episode, {
22004
+ message: "a symptom needs an episode (episodeId, or episode to find or start one)"
22054
22005
  });
22055
- var agentPostResultSchema = object({ postId: ulidSchema, created: boolean3() });
22056
- var promptOptionSchema = object({
22057
- id: string2().min(1).max(40),
22058
- label: string2().min(1).max(80),
22059
- style: _enum2(["primary", "danger", ""]).default("")
22006
+ var correctHealthInputSchema = object({ entryId: ulidSchema, change: correctHealthSymptomInputSchema }).strict();
22007
+ var HEALTH_CHECK_IN_TRENDS = ["better", "same", "worse"];
22008
+ var healthCheckInTrendSchema = _enum2(HEALTH_CHECK_IN_TRENDS);
22009
+ var healthCheckInInputSchema = object({ trend: healthCheckInTrendSchema }).strict();
22010
+ var HEALTH_UNDO_KIND_VALUES = ["entry", "dose", "episode"];
22011
+ var healthUndoInputSchema = object({ kind: _enum2(HEALTH_UNDO_KIND_VALUES), id: ulidSchema }).strict();
22012
+ var HEALTH_RECEIPT_KIND_VALUES = [
22013
+ "symptom",
22014
+ "correction",
22015
+ "dose",
22016
+ "episode",
22017
+ "encounter"
22018
+ ];
22019
+ var healthReceiptItemSchema = object({
22020
+ kind: _enum2(HEALTH_RECEIPT_KIND_VALUES),
22021
+ id: string2(),
22022
+ line: string2(),
22023
+ guessed: array(string2()),
22024
+ undo: healthUndoInputSchema
22060
22025
  });
22061
- var agentPromptSchema = object({
22062
- promptId: string2().min(1).max(100),
22063
- threadId: ulidSchema,
22064
- kind: _enum2(["exec_approval", "clarify", "slash_confirm"]),
22065
- text: postTextSchema,
22066
- options: array(promptOptionSchema).min(1).max(12),
22067
- allowText: boolean3().default(false),
22068
- expiresAt: string2().datetime(),
22069
- command: string2().optional(),
22070
- description: string2().optional()
22026
+ var healthReceiptSchema = object({
22027
+ episode: object({ id: string2(), title: string2(), created: boolean3() }).nullable(),
22028
+ items: array(healthReceiptItemSchema),
22029
+ entry: healthSymptomEntrySchema.nullable(),
22030
+ dose: healthMedicationDoseSchema.nullable(),
22031
+ postId: string2().nullable().optional()
22071
22032
  });
22072
- var agentGatewayErrorCodeSchema = _enum2([
22073
- "bad_request",
22074
- "not_found",
22075
- "thread_not_found",
22076
- "not_member",
22077
- "too_large",
22078
- "rate_limited",
22079
- "unsupported",
22080
- "internal"
22081
- ]);
22082
- var agentGatewayErrorSchema = object({
22083
- code: agentGatewayErrorCodeSchema,
22084
- message: string2(),
22085
- retryable: boolean3()
22033
+ var healthRedFlagsInputSchema = object({
22034
+ answers: redFlagsSchema.refine((a) => Object.keys(a).length > 0, {
22035
+ message: "answer at least one red flag"
22036
+ }),
22037
+ thread: threadTargetSchema.optional()
22038
+ }).strict();
22039
+ var healthRedFlagsResultSchema = object({
22040
+ episodeId: string2(),
22041
+ redFlags: redFlagsSchema,
22042
+ checkedAt: exports_coerce.date(),
22043
+ postId: string2().nullable()
22086
22044
  });
22087
- var frame = (type, shape) => object({
22088
- v: literal(AGENT_GATEWAY_VERSION),
22089
- type: literal(type),
22090
- id: string2().min(1).max(64),
22091
- ...shape
22045
+ var healthCourseDaySchema = object({
22046
+ day: string2(),
22047
+ severity: number2().int().nullable(),
22048
+ entries: number2().int()
22092
22049
  });
22093
- var readyFrameSchema = frame("ready", {
22094
- space: object({
22095
- id: string2().min(1),
22096
- name: string2(),
22097
- ownerMemberId: string2().min(1)
22098
- }),
22099
- agent: object({
22100
- id: string2().min(1),
22101
- name: string2(),
22102
- homeSlug: threadSlugSchema
22103
- }),
22104
- members: array(gatewayMemberSchema),
22105
- threads: array(gatewayThreadSchema),
22106
- heartbeatSec: number2().int().positive(),
22107
- hints: array(string2()).default([])
22050
+ var healthTriedSchema = object({
22051
+ medicationId: string2(),
22052
+ title: string2(),
22053
+ doses: number2().int(),
22054
+ effects: array(healthDoseEffectSchema),
22055
+ lastTakenAt: exports_coerce.date(),
22056
+ amount: string2().nullable().default(null)
22108
22057
  });
22109
- var membersFrameSchema = frame("members", { members: array(gatewayMemberSchema) });
22110
- var threadsFrameSchema = frame("threads", { threads: array(gatewayThreadSchema) });
22111
- var messageFrameSchema = frame("message", { message: inboundMessageSchema });
22112
- var promptAnswerFrameSchema = frame("prompt.answer", {
22113
- promptId: string2().min(1),
22114
- optionId: string2().min(1),
22115
- text: string2().optional(),
22116
- memberId: string2().min(1),
22117
- threadId: ulidSchema
22058
+ var healthSummaryLabSchema = object({
22059
+ id: string2(),
22060
+ specimenAt: exports_coerce.date(),
22061
+ labName: string2().nullable(),
22062
+ results: array(object({
22063
+ name: string2(),
22064
+ valueNum: number2().nullable(),
22065
+ valueText: string2().nullable(),
22066
+ unit: string2().nullable(),
22067
+ refLow: number2().nullable(),
22068
+ refHigh: number2().nullable(),
22069
+ flag: _enum2(["low", "normal", "high"]).nullable()
22070
+ }))
22118
22071
  });
22119
- var confirmationOutcomeFrameSchema = frame("confirmation.outcome", {
22120
- confirmationId: string2().min(1),
22121
- memberId: string2().min(1),
22122
- threadId: ulidSchema.nullable(),
22123
- outcome: _enum2(["done", "failed", "declined"]),
22124
- text: string2()
22072
+ var HEALTH_TREND_KEYS = ["sleep", "weight"];
22073
+ var healthTrendSchema = object({
22074
+ key: _enum2(HEALTH_TREND_KEYS),
22075
+ label: string2(),
22076
+ unit: string2(),
22077
+ points: array(object({ day: string2(), value: number2() }))
22125
22078
  });
22126
- var interruptFrameSchema = frame("interrupt", {
22127
- threadId: ulidSchema,
22128
- memberId: string2().min(1)
22079
+ var healthSummarySchema = object({
22080
+ generatedAt: exports_coerce.date(),
22081
+ patient: object({ name: string2().nullable() }).default({ name: null }),
22082
+ episode: healthEpisodeViewSchema.nullable(),
22083
+ course: array(healthCourseDaySchema),
22084
+ entries: array(healthSymptomEntrySchema),
22085
+ tried: array(healthTriedSchema),
22086
+ conditions: array(healthConditionViewSchema),
22087
+ medications: array(healthMedicationViewSchema),
22088
+ profile: healthProfileSchema,
22089
+ gp: object({ id: string2(), name: string2(), phone: string2().nullable() }).nullable(),
22090
+ nextVisit: healthEncounterViewSchema.nullable(),
22091
+ questions: array(string2()),
22092
+ labs: array(healthSummaryLabSchema).default([]),
22093
+ trends: array(healthTrendSchema).default([])
22129
22094
  });
22130
- var ackFrameSchema = frame("ack", {
22131
- ref: string2().min(1),
22132
- ok: boolean3(),
22133
- postId: ulidSchema.optional(),
22134
- created: boolean3().optional(),
22135
- error: agentGatewayErrorSchema.optional()
22095
+ var healthSummaryQuerySchema = object({ episodeId: ulidSchema.optional() });
22096
+
22097
+ // ../../packages/schema/src/contracts/health-labs.ts
22098
+ var LAB_GROUP_VALUES = [
22099
+ "vitamins_iron",
22100
+ "blood_count",
22101
+ "kidney",
22102
+ "liver",
22103
+ "thyroid",
22104
+ "lipids",
22105
+ "sugar",
22106
+ "inflammation",
22107
+ "hormones",
22108
+ "other"
22109
+ ];
22110
+ var labGroupSchema = _enum2(LAB_GROUP_VALUES);
22111
+ var HEALTH_LAB_FLAG_VALUES = ["low", "normal", "high"];
22112
+ var healthLabFlagSchema = _enum2(HEALTH_LAB_FLAG_VALUES);
22113
+ var healthLabPanelStatusSchema = _enum2(["draft", "confirmed"]);
22114
+ var labAnalyteKeySchema = string2().regex(/^[a-z0-9]+(_[a-z0-9]+)*$/, "must be lowercase words joined by _").max(80);
22115
+ var title2 = string2().trim().min(1).max(200);
22116
+ var text3 = (max) => string2().trim().min(1).max(max);
22117
+ var instant2 = exports_coerce.date();
22118
+ var amount = number2().finite();
22119
+ var healthLabResultSchema = createSelectSchema(healthLabResults, {
22120
+ valueNum: number2().nullable(),
22121
+ refLow: number2().nullable(),
22122
+ refHigh: number2().nullable()
22136
22123
  });
22137
- var unseenPostSchema = object({
22138
- postId: ulidSchema,
22139
- threadId: ulidSchema,
22140
- memberId: string2().min(1),
22124
+ var healthLabPanelViewSchema = createSelectSchema(healthLabPanels, {
22125
+ specimenAt: exports_coerce.date()
22126
+ }).extend({
22141
22127
  title: string2(),
22142
- threadTitle: string2().nullable(),
22143
- path: string2().startsWith("/"),
22144
- url: string2().url().nullable(),
22145
- pushedAt: string2().datetime()
22128
+ createdAt: exports_coerce.date(),
22129
+ updatedAt: exports_coerce.date(),
22130
+ orderedByName: string2().nullable(),
22131
+ results: array(healthLabResultSchema),
22132
+ unmatched: array(string2()).optional()
22146
22133
  });
22147
- var postUnseenFrameSchema = frame("post.unseen", { post: unseenPostSchema });
22148
- var agentGatewayServerFrameSchema = discriminatedUnion("type", [
22149
- readyFrameSchema,
22150
- membersFrameSchema,
22151
- threadsFrameSchema,
22152
- messageFrameSchema,
22153
- promptAnswerFrameSchema,
22154
- interruptFrameSchema,
22155
- confirmationOutcomeFrameSchema,
22156
- ackFrameSchema,
22157
- postUnseenFrameSchema
22158
- ]);
22159
- var messageAckFrameSchema = frame("message.ack", { messageId: ulidSchema });
22160
- var postFrameSchema = frame("post", { post: agentPostInputSchema });
22161
- var postEditFrameSchema = frame("post.edit", {
22162
- postId: ulidSchema,
22163
- edit: agentPostEditSchema
22134
+ var healthLabPointSchema = object({
22135
+ resultId: string2(),
22136
+ panelId: string2(),
22137
+ specimenAt: exports_coerce.date(),
22138
+ labName: string2().nullable(),
22139
+ status: healthLabPanelStatusSchema,
22140
+ valueNum: number2().nullable(),
22141
+ valueText: string2().nullable(),
22142
+ unit: string2().nullable(),
22143
+ refLow: number2().nullable(),
22144
+ refHigh: number2().nullable(),
22145
+ flag: healthLabFlagSchema.nullable(),
22146
+ fileId: string2().nullable(),
22147
+ fileMime: string2().nullable().default(null),
22148
+ source: healthEntrySourceSchema.default("manual")
22164
22149
  });
22165
- var postDeleteFrameSchema = frame("post.delete", { postId: ulidSchema });
22166
- var typingFrameSchema = frame("typing", { threadId: ulidSchema, on: boolean3() });
22167
- var promptFrameSchema = frame("prompt", { prompt: agentPromptSchema });
22168
- var promptCloseFrameSchema = frame("prompt.close", {
22169
- promptId: string2().min(1),
22170
- optionId: string2().optional(),
22171
- expired: boolean3()
22150
+ var healthLabAnalyteViewSchema = object({
22151
+ analyte: string2(),
22152
+ name: string2(),
22153
+ group: labGroupSchema,
22154
+ loinc: string2().nullable(),
22155
+ unit: string2().nullable(),
22156
+ points: array(healthLabPointSchema),
22157
+ target: object({
22158
+ low: number2().nullable(),
22159
+ high: number2().nullable(),
22160
+ byContactId: string2().nullable(),
22161
+ byName: string2().nullable(),
22162
+ note: string2().nullable()
22163
+ }).nullable(),
22164
+ medication: object({
22165
+ id: string2(),
22166
+ title: string2(),
22167
+ dose: string2().nullable(),
22168
+ schedule: healthMedicationScheduleSchema,
22169
+ habitId: string2().nullable()
22170
+ }).nullable()
22172
22171
  });
22173
- var attachmentTranscriptFrameSchema = frame("attachment.transcript", {
22174
- attachmentId: ulidSchema,
22175
- text: string2().trim().min(1).max(AGENT_TRANSCRIPT_MAX)
22172
+ var healthLabOverviewSchema = object({
22173
+ draws: number2().int(),
22174
+ firstAt: exports_coerce.date().nullable(),
22175
+ lastAt: exports_coerce.date().nullable(),
22176
+ lastLab: string2().nullable(),
22177
+ analytes: array(healthLabAnalyteViewSchema)
22178
+ });
22179
+ var healthLabResultInputSchema = object({
22180
+ id: ulidSchema.optional(),
22181
+ analyte: labAnalyteKeySchema.optional(),
22182
+ name: title2,
22183
+ group: labGroupSchema.optional(),
22184
+ loinc: text3(20).nullish(),
22185
+ valueNum: amount.nullish(),
22186
+ valueText: text3(200).nullish(),
22187
+ unit: text3(40).nullish(),
22188
+ refLow: amount.nullish(),
22189
+ refHigh: amount.nullish(),
22190
+ flag: healthLabFlagSchema.nullish(),
22191
+ comment: text3(1000).nullish()
22192
+ }).strict().refine((r) => r.valueNum != null || r.valueText != null, {
22193
+ message: "a result needs valueNum or valueText"
22194
+ });
22195
+ var createHealthLabPanelInputSchema = object({
22196
+ id: ulidSchema.optional(),
22197
+ title: title2.optional(),
22198
+ specimenAt: instant2,
22199
+ labName: text3(200).nullish(),
22200
+ orderedByContactId: ulidSchema.nullish(),
22201
+ encounterId: ulidSchema.nullish(),
22202
+ fileId: ulidSchema.nullish(),
22203
+ status: healthLabPanelStatusSchema.optional(),
22204
+ source: healthEntrySourceSchema.optional(),
22205
+ note: text3(2000).nullish(),
22206
+ results: array(healthLabResultInputSchema).max(200).optional(),
22207
+ subjectNodeId: ulidSchema.nullish()
22208
+ }).strict();
22209
+ var updateHealthLabPanelInputSchema = createHealthLabPanelInputSchema.omit({ id: true, subjectNodeId: true }).partial().strict();
22210
+ var healthLabImportFieldsSchema = object({ text: string2().max(200000).optional() }).strict();
22211
+ var healthLabImportResultSchema = object({
22212
+ format: _enum2(["kmehr", "pdf"]),
22213
+ found: number2().int(),
22214
+ panel: healthLabPanelViewSchema
22215
+ });
22216
+ var setHealthLabAnalyteInputSchema = object({
22217
+ targetLow: amount.nullish(),
22218
+ targetHigh: amount.nullish(),
22219
+ targetByContactId: ulidSchema.nullish(),
22220
+ medicationId: ulidSchema.nullish(),
22221
+ note: text3(1000).nullish()
22222
+ }).strict().refine((t) => t.targetLow == null || t.targetHigh == null || t.targetLow <= t.targetHigh, {
22223
+ message: "targetLow must not be above targetHigh"
22176
22224
  });
22177
- var postUnseenAckFrameSchema = frame("post.unseen.ack", { postId: ulidSchema });
22178
- var agentGatewayClientFrameSchema = discriminatedUnion("type", [
22179
- messageAckFrameSchema,
22180
- postUnseenAckFrameSchema,
22181
- postFrameSchema,
22182
- postEditFrameSchema,
22183
- postDeleteFrameSchema,
22184
- typingFrameSchema,
22185
- promptFrameSchema,
22186
- promptCloseFrameSchema,
22187
- attachmentTranscriptFrameSchema
22188
- ]);
22189
- var SERVER_FRAME_TYPES = new Set(agentGatewayServerFrameSchema.options.map((o) => o.shape.type.value));
22190
- var CLIENT_FRAME_TYPES = new Set(agentGatewayClientFrameSchema.options.map((o) => o.shape.type.value));
22191
- var agentThreadsResponseSchema = object({ threads: array(gatewayThreadSchema) });
22192
- function homeSlugFor(agentName) {
22193
- const slug = agentName.normalize("NFKD").replace(/[\u0300-\u036F]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "");
22194
- return slug || "agent";
22195
- }
22196
22225
 
22197
22226
  // ../../packages/schema/src/contracts/files.ts
22198
22227
  var FILE_TEXT_MAX = 1e6;
@@ -22865,10 +22894,11 @@ var timeBlockStepSchema = object({
22865
22894
  at: exports_coerce.date().nullable()
22866
22895
  });
22867
22896
  var timeBlockEvidenceSchema = object({
22868
- source: _enum2(["habit", "check_in", "you", "agent", "plan"]),
22897
+ source: _enum2(["habit", "check_in", "you", "agent", "device", "github", "do", "plan"]),
22869
22898
  label: string2(),
22870
22899
  at: exports_coerce.date().nullable(),
22871
- agentName: string2().nullable()
22900
+ agentName: string2().nullable(),
22901
+ via: string2().nullable().optional()
22872
22902
  });
22873
22903
  var timeBlockReplacementSchema = object({
22874
22904
  id: string2(),
@@ -24465,6 +24495,12 @@ var moneyBudgetCopyResultSchema = object({
24465
24495
  copied: number2().int(),
24466
24496
  kept: number2().int()
24467
24497
  });
24498
+ var draftMoneyBudgetInputSchema = object({ month: moneyMonthSchema, months: number2().int().min(1).max(12).optional() }).strict();
24499
+ var moneyBudgetDraftResultSchema = object({
24500
+ lines: array(object({ id: ulidSchema, categoryId: ulidSchema, name: string2(), planned: amount3 })),
24501
+ kept: number2().int(),
24502
+ months: number2().int()
24503
+ });
24468
24504
  var moneyBudgetRowSchema = object({
24469
24505
  categoryId: ulidSchema,
24470
24506
  name: string2(),
@@ -25255,7 +25291,9 @@ var runChecklistSchema = object({
25255
25291
  total: number2().int().min(0).max(5000).nullish(),
25256
25292
  items: array(object({ id: ref, label: shortText.nullish() }).strict()).max(5000).optional(),
25257
25293
  done: array(ref).max(5000),
25258
- notes: record(ref, shortText).optional()
25294
+ notes: record(ref, shortText).optional(),
25295
+ carrying: array(ref).max(5000).optional(),
25296
+ legend: shortText.nullish()
25259
25297
  }).strict();
25260
25298
  var runTeamMemberSchema = object({
25261
25299
  species: name,
@@ -25271,7 +25309,13 @@ var runAchievementsSchema = object({
25271
25309
  source: _enum2(["steam", "xbox", "psn", "manual"]).default("manual"),
25272
25310
  total: number2().int().min(0).max(5000).nullish(),
25273
25311
  enabled: boolean3().default(true),
25274
- unlocked: array(object({ name, on: isoDate.nullish(), hint: shortText.nullish() }).strict()).max(5000)
25312
+ unlocked: array(object({ name, on: isoDate.nullish(), hint: shortText.nullish() }).strict()).max(5000),
25313
+ locked: array(object({ name, hint: shortText.nullish() }).strict()).max(5000).optional()
25314
+ }).strict();
25315
+ var runRareFindsSchema = object({
25316
+ place: shortText.nullish(),
25317
+ items: array(shortText).max(200),
25318
+ note: text5.nullish()
25275
25319
  }).strict();
25276
25320
  var runInstallSchema = object({
25277
25321
  edition: shortText.nullish(),
@@ -25298,6 +25342,7 @@ var runFacetSchema = object({
25298
25342
  checklists: array(runChecklistSchema).max(30).optional(),
25299
25343
  uniques: array(runUniqueSchema).max(1000).optional(),
25300
25344
  achievements: runAchievementsSchema.nullish(),
25345
+ rareFinds: runRareFindsSchema.nullish(),
25301
25346
  install: runInstallSchema.nullish(),
25302
25347
  money: object({ goal: shortText.nullish(), purpose: shortText.nullish() }).strict().nullish(),
25303
25348
  links: array(object({ label: name, url: string2().url().max(2000) }).strict()).max(50).optional()
@@ -25324,6 +25369,7 @@ var runValueSectionValues = [
25324
25369
  "arc",
25325
25370
  "nextSteps",
25326
25371
  "achievements",
25372
+ "rareFinds",
25327
25373
  "install",
25328
25374
  "money"
25329
25375
  ];
@@ -25338,7 +25384,15 @@ var runChangeSchema = discriminatedUnion("op", [
25338
25384
  }).strict(),
25339
25385
  object({
25340
25386
  op: literal("merge"),
25341
- section: _enum2(["character", "arc", "nextSteps", "achievements", "install", "money"]),
25387
+ section: _enum2([
25388
+ "character",
25389
+ "arc",
25390
+ "nextSteps",
25391
+ "achievements",
25392
+ "rareFinds",
25393
+ "install",
25394
+ "money"
25395
+ ]),
25342
25396
  value: record(string2(), unknown()),
25343
25397
  label: label.optional()
25344
25398
  }).strict(),
@@ -28172,7 +28226,7 @@ function parseCapture2(input, now) {
28172
28226
 
28173
28227
  // src/meta.ts
28174
28228
  var CLI_NAME = "do";
28175
- var VERSION = "1.273.0";
28229
+ var VERSION = "1.275.0";
28176
28230
  var API_PREFIX = "/api/v1";
28177
28231
  var DEFAULT_API_URL = "http://localhost:3001";
28178
28232
 
@@ -29319,11 +29373,16 @@ var HEALTH_COMMAND_SPECS = [
29319
29373
  name: "notes",
29320
29374
  type: "string",
29321
29375
  description: 'Anything else a doctor should know, in your words ("Kell negative"); "" clears it.'
29376
+ },
29377
+ {
29378
+ name: "sex",
29379
+ type: "string",
29380
+ description: `Sex, in your words, for the doctor's page ("female"); "" clears it.`
29322
29381
  }
29323
29382
  ],
29324
29383
  scopes: WRITE2,
29325
29384
  returns: "HealthProfile",
29326
- notes: "Body: UpdateHealthProfileInput. An absent key keeps a field; null clears it. Lifestyle is `alcohol`, `smoking`, `exercise`, and `notes` anything else: the member's own words. Notes go on For the doctor's background."
29385
+ notes: "Body: UpdateHealthProfileInput. An absent key keeps a field; null clears it. Lifestyle is `alcohol`, `smoking`, `exercise`, and `notes` anything else: the member's own words. Notes go on For the doctor's background; `sex` on its patient line."
29327
29386
  },
29328
29387
  {
29329
29388
  path: ["health", "record"],
@@ -29332,7 +29391,7 @@ var HEALTH_COMMAND_SPECS = [
29332
29391
  flags: [DATA_FLAG],
29333
29392
  scopes: WRITE2,
29334
29393
  returns: "HealthReceipt",
29335
- notes: 'Body: LogHealthInput, e.g. {"episode":{"title":"Sprained ankle","bodyRegion":"ankle_l"},"symptom":{"symptom":"worse on the stairs","severity":6,"severityGuessed":true},"dose":{"medication":"Ibuprofen"}}. The receipt lists each part with a line, what was guessed, and its undo.'
29394
+ notes: 'Body: LogHealthInput, e.g. {"episode":{"title":"Sprained ankle","bodyRegion":"ankle_l"},"symptom":{"symptom":"worse on the stairs","severity":6,"severityGuessed":true},"dose":{"medication":"Ibuprofen"}}. The receipt lists each part with a line, what was guessed, and its undo. With "thread":{"slug":"<agent>"} (only an agent key that converses) the receipt card is posted there too, and postId names it.'
29336
29395
  },
29337
29396
  {
29338
29397
  path: ["health", "fix"],
@@ -29354,6 +29413,23 @@ var HEALTH_COMMAND_SPECS = [
29354
29413
  returns: "HealthReceipt",
29355
29414
  notes: "One a day: a second check-in the same day corrects the first. The receipt carries its undo."
29356
29415
  },
29416
+ {
29417
+ path: ["health", "red-flags"],
29418
+ summary: "Record the red-flag screen answered in chat: do health red-flags <episode> --no fever,vomiting.",
29419
+ args: [{ name: "episode", required: true, description: "The Episode's id." }],
29420
+ flags: [
29421
+ { name: "no", type: "string", description: "The flags said no to, comma-separated." },
29422
+ { name: "yes", type: "string", description: "The flags said yes to, comma-separated." },
29423
+ {
29424
+ name: "thread",
29425
+ type: "string",
29426
+ description: "Post the confirmation card in this thread (by slug); the agent's key only."
29427
+ }
29428
+ ],
29429
+ scopes: WRITE2,
29430
+ returns: "HealthRedFlagsResult",
29431
+ notes: "Flags: fever, vomiting, black_stools, blood, weight_loss, night_pain, chest_pain, short_of_breath. Answers merge into those asked before; the Episode is marked checked today, and For the doctor shows it."
29432
+ },
29357
29433
  {
29358
29434
  path: ["health", "undo"],
29359
29435
  summary: "Take back what a receipt wrote: do health undo entry|dose|episode <id>.",
@@ -32805,6 +32881,18 @@ var COMMAND_SPECS = [
32805
32881
  returns: "{ ok, removed }",
32806
32882
  notes: "DELETE /api/v1/money/budget/lines/{id}."
32807
32883
  },
32884
+ {
32885
+ path: ["money", "budget-draft"],
32886
+ summary: "Draft a month's household plan from the months before it (the agent's lines).",
32887
+ args: [],
32888
+ flags: [
32889
+ { name: "month", type: "string", description: "The month to plan, YYYY-MM." },
32890
+ { name: "months", type: "string", description: "How many months back to read (default 3)." }
32891
+ ],
32892
+ scopes: ["finance:write"],
32893
+ returns: "{ lines, kept, months }",
32894
+ notes: "POST /api/v1/money/budget/draft. Undo by taking the lines out: `do money budget-remove <id>`."
32895
+ },
32808
32896
  {
32809
32897
  path: ["money", "budget-copy"],
32810
32898
  summary: "Copy a month's plan into another (lines already there are kept).",
@@ -37252,6 +37340,14 @@ var HANDLERS = {
37252
37340
  await requireClient().delete(`/money/budget/lines/${id}`);
37253
37341
  return { data: { ok: true, removed: id }, render: renderRecord };
37254
37342
  },
37343
+ "money budget-draft": async ({ flags, requireClient }) => {
37344
+ const months = flagString(flags, "months");
37345
+ const body = parseInput(draftMoneyBudgetInputSchema, {
37346
+ month: requireFlag(flags, "month", "money budget-draft needs --month <YYYY-MM>"),
37347
+ ...months ? { months: Number(months) } : {}
37348
+ });
37349
+ return { data: await requireClient().post("/money/budget/draft", body), render: renderRecord };
37350
+ },
37255
37351
  "money budget-copy": async ({ flags, requireClient }) => {
37256
37352
  const body = parseInput(copyMoneyBudgetInputSchema, {
37257
37353
  from: requireFlag(flags, "from", "money budget-copy needs --from <YYYY-MM>"),
@@ -37496,6 +37592,23 @@ var HANDLERS = {
37496
37592
  render: renderRecord
37497
37593
  };
37498
37594
  },
37595
+ "health red-flags": async ({ args, flags, requireClient }) => {
37596
+ const episodeId = requireArg(args, 0, "episode");
37597
+ const list = (name) => (flagString(flags, name) ?? "").split(",").map((f) => f.trim()).filter(Boolean);
37598
+ const answers = Object.fromEntries([
37599
+ ...list("no").map((f) => [f, false]),
37600
+ ...list("yes").map((f) => [f, true])
37601
+ ]);
37602
+ const thread = flagString(flags, "thread");
37603
+ const body = parseInput(healthRedFlagsInputSchema, {
37604
+ answers,
37605
+ ...thread ? { thread: { slug: thread } } : {}
37606
+ });
37607
+ return {
37608
+ data: await requireClient().post(`/health/episodes/${episodeId}/red-flags`, body),
37609
+ render: renderRecord
37610
+ };
37611
+ },
37499
37612
  "health undo": async ({ args, requireClient }) => {
37500
37613
  const body = parseInput(healthUndoInputSchema, {
37501
37614
  kind: requireArg(args, 0, "kind"),
@@ -37537,6 +37650,9 @@ var HANDLERS = {
37537
37650
  const notes = flagString(flags, "notes");
37538
37651
  if (notes !== undefined)
37539
37652
  fields.notes = notes.trim() ? notes : null;
37653
+ const sex = flagString(flags, "sex");
37654
+ if (sex !== undefined)
37655
+ fields.sex = sex.trim() ? sex.trim() : null;
37540
37656
  const body = parseInput(updateHealthProfileInputSchema, fields);
37541
37657
  return { data: await requireClient().patch("/health/profile", body), render: renderRecord };
37542
37658
  },