@mulmoclaude/core 0.23.1 → 0.25.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.
- package/assets/helps/collection-skills.md +27 -3
- package/assets/helps/google-calendar-collection.md +79 -0
- package/assets/helps/index.md +1 -0
- package/dist/collection/core/completion.d.ts +18 -0
- package/dist/collection/core/deriveAll.d.ts +14 -9
- package/dist/collection/core/schema.d.ts +9 -4
- package/dist/collection/core/schemaZ.d.ts +126 -43
- package/dist/collection/index.cjs +16 -14
- package/dist/collection/index.cjs.map +1 -1
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.js +3 -2
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/paths.cjs +5 -55
- package/dist/collection/paths.js +1 -51
- package/dist/collection/registry/server/index.cjs +20 -19
- package/dist/collection/registry/server/index.cjs.map +1 -1
- package/dist/collection/registry/server/index.js +3 -2
- package/dist/collection/registry/server/index.js.map +1 -1
- package/dist/collection/server/index.cjs +41 -40
- package/dist/collection/server/index.js +4 -3
- package/dist/collection-watchers/index.cjs +15 -23
- package/dist/collection-watchers/index.cjs.map +1 -1
- package/dist/collection-watchers/index.js +3 -11
- package/dist/collection-watchers/index.js.map +1 -1
- package/dist/collection-watchers/reconciler.d.ts +2 -4
- package/dist/discovery-3K_Wtkvn.js +1636 -0
- package/dist/discovery-3K_Wtkvn.js.map +1 -0
- package/dist/discovery-BZ2ms1tE.cjs +1865 -0
- package/dist/discovery-BZ2ms1tE.cjs.map +1 -0
- package/dist/feeds/index.cjs +4 -4
- package/dist/feeds/index.js +2 -2
- package/dist/feeds/server/index.cjs +16 -15
- package/dist/feeds/server/index.cjs.map +1 -1
- package/dist/feeds/server/index.js +4 -3
- package/dist/feeds/server/index.js.map +1 -1
- package/dist/google/apiClient.d.ts +8 -1
- package/dist/google/calendar.d.ts +35 -0
- package/dist/google/calendarSyncStore.d.ts +7 -0
- package/dist/google/collectionSync.d.ts +70 -0
- package/dist/google/index.cjs +296 -4
- package/dist/google/index.cjs.map +1 -1
- package/dist/google/index.d.ts +4 -2
- package/dist/google/index.js +281 -5
- package/dist/google/index.js.map +1 -1
- package/dist/ids-BR4U1dJD.cjs +150 -0
- package/dist/ids-BR4U1dJD.cjs.map +1 -0
- package/dist/ids-D4e10971.js +85 -0
- package/dist/ids-D4e10971.js.map +1 -0
- package/dist/{ingestTypes-B-dXxUF9.js → ingestTypes-BsGOjR2l.js} +2 -2
- package/dist/{ingestTypes-B-dXxUF9.js.map → ingestTypes-BsGOjR2l.js.map} +1 -1
- package/dist/{ingestTypes-Cev9q77C.cjs → ingestTypes-CygUXsjf.cjs} +3 -3
- package/dist/{ingestTypes-Cev9q77C.cjs.map → ingestTypes-CygUXsjf.cjs.map} +1 -1
- package/dist/{promptSafety-rDWA9_JS.js → promptSafety-Boz5qOs-.js} +48 -102
- package/dist/promptSafety-Boz5qOs-.js.map +1 -0
- package/dist/{promptSafety-DRd15gQ6.cjs → promptSafety-Co4cYQ_Z.cjs} +49 -163
- package/dist/promptSafety-Co4cYQ_Z.cjs.map +1 -0
- package/dist/remote-host/server/index.cjs +6 -4
- package/dist/remote-host/server/index.cjs.map +1 -1
- package/dist/remote-host/server/index.js +6 -4
- package/dist/remote-host/server/index.js.map +1 -1
- package/dist/scheduler/index.cjs +3 -1
- package/dist/scheduler/index.cjs.map +1 -1
- package/dist/scheduler/index.js +3 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/{server-Jaogu3Ky.cjs → server-DLRz-U7F.cjs} +80 -1806
- package/dist/server-DLRz-U7F.cjs.map +1 -0
- package/dist/{server-D2ibbixF.js → server-DZH7OjOD.js} +9 -1531
- package/dist/server-DZH7OjOD.js.map +1 -0
- package/dist/skill-bridge/index.cjs +2 -2
- package/dist/skill-bridge/index.cjs.map +1 -1
- package/dist/skill-bridge/index.js +1 -1
- package/dist/templatePath-27vUZowm.cjs +75 -0
- package/dist/templatePath-27vUZowm.cjs.map +1 -0
- package/dist/templatePath-k_WNbL_Q.js +52 -0
- package/dist/templatePath-k_WNbL_Q.js.map +1 -0
- package/package.json +1 -1
- package/dist/collection/paths.cjs.map +0 -1
- package/dist/collection/paths.js.map +0 -1
- package/dist/promptSafety-DRd15gQ6.cjs.map +0 -1
- package/dist/promptSafety-rDWA9_JS.js.map +0 -1
- package/dist/server-D2ibbixF.js.map +0 -1
- package/dist/server-Jaogu3Ky.cjs.map +0 -1
|
@@ -132,8 +132,8 @@ skipped, never crashes the host):
|
|
|
132
132
|
| `singleton` | Optional. When set, at most one record exists, pinned to this exact id (e.g. `me`). Host pre-fills + locks the create form and hides Add once it exists. |
|
|
133
133
|
| `fields` | Ordered map of field-name → field spec. **Insertion order = column order** in the table. Required. |
|
|
134
134
|
| `actions` | Optional array of per-record buttons (see below). |
|
|
135
|
-
| `completionField` | Optional. Name of the field whose value marks an item as "done" — when set, item-create fires a bell notification that clears once the
|
|
136
|
-
| `completionDoneValues` | Optional. Non-empty array of values that count as "done" for `completionField` (e.g. `["Done"]`, `["paid", "void"]`). Compared as strings.
|
|
135
|
+
| `completionField` | Optional. Name of the field whose value marks an item as "done" — when set, item-create fires a bell notification that clears once the item reads as done. Must name a real field in `fields`. Two forms: paired with `completionDoneValues` (done ⇔ the field's value is in that array), or naming a **`flag` field** (done ⇔ the flag's `where` matches — `completionDoneValues` must then be omitted). |
|
|
136
|
+
| `completionDoneValues` | Optional. Non-empty array of values that count as "done" for `completionField` (e.g. `["Done"]`, `["paid", "void"]`). Compared as strings. Omit when `completionField` names a `flag` field. |
|
|
137
137
|
| `notifyWhen` | Optional. A `when` predicate (`{ "field": "...", "in": [...] }`) that **gates** the completion bell: fire it only for records matching the predicate (e.g. `{ "field": "priority", "in": ["high", "urgent"] }`). Requires `completionField`; `field` must name a real field. Absent ⇒ notify for every open record. |
|
|
138
138
|
| `displayField` | Optional. Name of a field whose value is shown as the human-readable label in the completion notification's title (e.g. `Contacts: Jane Doe` instead of the opaque primaryKey). Must name a real field in `fields`. Falls back to the primaryKey value when unset or when the record's value is empty. |
|
|
139
139
|
| `triggerField` | Optional. Name of a `date` field that **delays** the completion bell until that date arrives (instead of firing on create). Requires `completionField` / `completionDoneValues` (the bell still clears via the done value). Must name a real `date` field. See "Time-gated bells" below. |
|
|
@@ -149,7 +149,7 @@ skipped, never crashes the host):
|
|
|
149
149
|
|
|
150
150
|
`string` · `text` (multi-line) · `email` · `number` · `date` (`YYYY-MM-DD`) ·
|
|
151
151
|
`datetime` (`YYYY-MM-DDTHH:MM`) · `boolean` · `markdown` · `money` · `enum` ·
|
|
152
|
-
`ref` · `embed` · `backlinks` · `rollup` · `table` · `derived` · `image` · `file` · `toggle`
|
|
152
|
+
`ref` · `embed` · `backlinks` · `rollup` · `table` · `derived` · `image` · `file` · `toggle` · `flag`
|
|
153
153
|
|
|
154
154
|
Every field spec needs a `type` and a `label`. Extra keys by type:
|
|
155
155
|
|
|
@@ -249,6 +249,20 @@ Every field spec needs a `type` and a `label`. Extra keys by type:
|
|
|
249
249
|
"done" checkbox. Without it, `status` only shows as a dropdown and a kanban
|
|
250
250
|
column, with no checkbox to tick. `offValue` is the status to return to on
|
|
251
251
|
uncheck (the default open column, e.g. `"Todo"`).
|
|
252
|
+
- **`flag`** — `where: [<conditions>]`. A **computed boolean**: true when the
|
|
253
|
+
record matches every condition (AND). **Never stored** (like `derived`); the
|
|
254
|
+
host recomputes it on every read, so you NEVER write flag values into the
|
|
255
|
+
JSON. Each condition is `{ "field": "<field>", "op": "<op>", "value": "..." }`
|
|
256
|
+
with ops `eq` / `ne` / `in` (array value) / `contains` / `gt` / `gte` / `lt` /
|
|
257
|
+
`lte`, or `{ ..., "valueFrom": { "field": "<sibling>" } }` to compare two
|
|
258
|
+
fields of the same record (`spent > budget`). Condition fields must name
|
|
259
|
+
declared fields; cross-record `valueFrom.record` is not allowed. A flag may
|
|
260
|
+
read `derived` / `rollup` values, and other flags via their stringified
|
|
261
|
+
boolean (`{ "field": "isDone", "op": "eq", "value": "true" }`). Use it for
|
|
262
|
+
generic state summaries — done-ness, pass/fail, qualification:
|
|
263
|
+
`{ "type": "flag", "label": "Passed", "where": [{ "field": "score", "op": "gte", "value": "60" }] }`.
|
|
264
|
+
A flag can also drive completion tracking (stored-field conditions only) —
|
|
265
|
+
see `completionField` above and the "Completion tracking" section below.
|
|
252
266
|
|
|
253
267
|
### Conditional field visibility (`when`)
|
|
254
268
|
|
|
@@ -474,6 +488,16 @@ with any field type whose stringified value is comparable (`enum`, `string`,
|
|
|
474
488
|
["paid", "void"]` on an invoice, or `completionField: "shipped"` +
|
|
475
489
|
`completionDoneValues: ["true"]` on an order.
|
|
476
490
|
|
|
491
|
+
**Flag-form alternative**: `completionField` may instead name a **`flag`
|
|
492
|
+
field** — then done ⇔ the flag's `where` matches, and `completionDoneValues`
|
|
493
|
+
must be **omitted** (declaring it fails validation). Use it when done-ness is
|
|
494
|
+
richer than one field's membership (e.g. `"isDone": { "type": "flag", "where":
|
|
495
|
+
[{ "field": "score", "op": "gte", "value": "60" }] }` + `"completionField":
|
|
496
|
+
"isDone"`). Two extra rules apply only to a completion flag: its `where` may
|
|
497
|
+
reference **stored fields only** (no derived/rollup/toggle/flag/embed/backlinks
|
|
498
|
+
— completion is checked against the raw record), and combining it with `spawn`
|
|
499
|
+
requires an explicit `spawn.when`.
|
|
500
|
+
|
|
477
501
|
Set `displayField` to make the bell title readable: with `displayField:
|
|
478
502
|
"title"` the notification reads `Todos: Buy milk` instead of `Todos: t-0042`.
|
|
479
503
|
It must name a real field; an empty value on a given record falls back to the
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Google Calendar sync — mirror a Google calendar into a collection
|
|
2
|
+
|
|
3
|
+
A collection can keep itself in sync with one of the user's Google calendars.
|
|
4
|
+
Add a `googleCalendar` block to its `schema.json` and the host pulls changed
|
|
5
|
+
events on a schedule and writes them as records — **without calling you**. No
|
|
6
|
+
tool call, no tokens spent per sync, so hourly syncing is free.
|
|
7
|
+
|
|
8
|
+
This is the only calendar mechanism: there is no calendar tool and no bundled
|
|
9
|
+
calendar collection. You author the schema when the user asks for one.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
The user's Google account must be linked (`google` tool, `kind: "status"`). If
|
|
14
|
+
it isn't, sync silently does nothing until they link it in settings.
|
|
15
|
+
|
|
16
|
+
## The block
|
|
17
|
+
|
|
18
|
+
```jsonc
|
|
19
|
+
{
|
|
20
|
+
"fields": {
|
|
21
|
+
"gid": { "type": "string", "label": "ID", "primary": true },
|
|
22
|
+
"title": { "type": "string", "label": "Event" },
|
|
23
|
+
"on": { "type": "datetime", "label": "Start" },
|
|
24
|
+
"until": { "type": "datetime", "label": "End" }
|
|
25
|
+
},
|
|
26
|
+
"primaryKey": "gid",
|
|
27
|
+
"displayField": "title",
|
|
28
|
+
"calendarField": "on",
|
|
29
|
+
"calendarEndField": "until",
|
|
30
|
+
"dataPath": "data/collections/my-schedule/items",
|
|
31
|
+
|
|
32
|
+
"googleCalendar": {
|
|
33
|
+
"calendarId": "primary",
|
|
34
|
+
"map": { "title": "summary", "on": "start", "until": "end" }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- `calendarId` — the calendar to read. `"primary"` (as in the example) and
|
|
40
|
+
omitting the key entirely both mean the user's primary calendar. For any
|
|
41
|
+
other calendar, get its id from the `google` tool
|
|
42
|
+
(`kind: "calendarListCalendars"`).
|
|
43
|
+
- `map` — **your field name → the Google event field**. Pick whatever field
|
|
44
|
+
names suit the collection; the map absorbs the difference. Map at least one
|
|
45
|
+
field: an empty map syncs records that carry only the event id, so the user
|
|
46
|
+
would see rows with no content.
|
|
47
|
+
|
|
48
|
+
Mappable event fields: `summary`, `start`, `end`, `htmlLink`, `colorId`,
|
|
49
|
+
`status`.
|
|
50
|
+
|
|
51
|
+
## The primary field is the event id
|
|
52
|
+
|
|
53
|
+
Do **not** map the primary field. It always receives the Google event id, which
|
|
54
|
+
is what lets a re-sync update an existing record instead of duplicating it.
|
|
55
|
+
Declaring it in `map` is a schema error.
|
|
56
|
+
|
|
57
|
+
Use `datetime` (not `date`) for start/end when events have real clock times —
|
|
58
|
+
the calendar day view then draws each record as a proportional time block.
|
|
59
|
+
|
|
60
|
+
## What sync does
|
|
61
|
+
|
|
62
|
+
- New or edited events are written, keyed by event id (existing records are
|
|
63
|
+
replaced in place).
|
|
64
|
+
- Events deleted in Google are **deleted** from the collection.
|
|
65
|
+
- Only what changed since the last run is fetched, so a big calendar stays
|
|
66
|
+
cheap after the first sync.
|
|
67
|
+
- The first run walks the whole calendar to establish a starting point. Note
|
|
68
|
+
this covers **all** dates — Google does not allow a date window together with
|
|
69
|
+
incremental sync — so a calendar with years of history produces a lot of
|
|
70
|
+
records on that first pass.
|
|
71
|
+
|
|
72
|
+
Records are ordinary collection records: the user can open, filter, and view
|
|
73
|
+
them like any other. Edits they make locally are overwritten the next time
|
|
74
|
+
Google reports a change to that event.
|
|
75
|
+
|
|
76
|
+
## Not for this
|
|
77
|
+
|
|
78
|
+
A `dataSource` (CSV-backed) collection is read-only and cannot declare
|
|
79
|
+
`googleCalendar`. Use a normal `dataPath` collection.
|
package/assets/helps/index.md
CHANGED
|
@@ -71,6 +71,7 @@ See [Wiki](config/helps/wiki.md) for details on how it works.
|
|
|
71
71
|
- [Telegram Bridge](config/helps/telegram.md) — how to talk to MulmoClaude from the Telegram app: creating a bot, starting the bridge, allowlisting chat IDs, commands, and troubleshooting
|
|
72
72
|
- [Remote host](config/helps/remote-host.md) — drive MulmoClaude from a phone at mulmoserver.web.app: Google sign-in connect, host online vs. offline (queued chats, 7-day expiry), photo attachments, and the security model
|
|
73
73
|
- [Feeds](config/helps/feeds.md) — register a self-refreshing data feed (RSS/Atom/JSON) by authoring `feeds/<slug>/schema.json`: schema shape, the `ingest` block, raw-item field mapping, and `maxItems` retention
|
|
74
|
+
- [Google Calendar sync](config/helps/google-calendar-collection.md) — mirror a Google calendar into a collection with a `googleCalendar` block: field mapping, why the primary field holds the event id, and how deletions propagate
|
|
74
75
|
- [GitHub repositories in the workspace](config/helps/github.md) — clone-destination rules under `github/<name>/` and how to handle existing directories with matching or different remotes
|
|
75
76
|
- [Collection skills](config/helps/collection-skills.md) — build a data app (model + UI + relations + computed fields + action buttons) by authoring a `schema.json` collection skill: the DSL, field types, derived formulas, actions, records
|
|
76
77
|
- [Custom views](config/helps/custom-view.md) — give a collection a view the built-ins don't cover (year/quarter overview, Gantt): an HTML file under `views/`, registered in `schema.json`, rendered in a sandboxed iframe over the records
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Where } from './where';
|
|
2
|
+
/** The slice of a parsed schema the done predicate reads — minimal
|
|
3
|
+
* structural shape (like `DerivableSchema`) so the client and server
|
|
4
|
+
* `CollectionSchema` types both satisfy it as-is. */
|
|
5
|
+
export interface CompletionSchemaView {
|
|
6
|
+
/** Optional so legacy-pair callers (and their test fixtures) that
|
|
7
|
+
* never consult field specs keep working; only the flag form needs
|
|
8
|
+
* to look the completion field up. */
|
|
9
|
+
fields?: Record<string, {
|
|
10
|
+
type: string;
|
|
11
|
+
where?: Where;
|
|
12
|
+
}>;
|
|
13
|
+
completionField?: string;
|
|
14
|
+
completionDoneValues?: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
/** True iff the schema declares completion tracking AND `item` is done
|
|
17
|
+
* under whichever completion form the schema uses (see module doc). */
|
|
18
|
+
export declare function itemIsDone(schema: CompletionSchemaView, item: Record<string, unknown>): boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FormulaContext } from './derivedFormula';
|
|
2
|
+
import { Where } from './where';
|
|
2
3
|
/** Minimal field shape the derive loop needs — accepts both the client
|
|
3
4
|
* FieldSpec and the server CollectionFieldSpec. */
|
|
4
5
|
export interface DerivableFieldSpec {
|
|
@@ -7,6 +8,8 @@ export interface DerivableFieldSpec {
|
|
|
7
8
|
to?: string;
|
|
8
9
|
/** When type === "derived": formula evaluated against the record. */
|
|
9
10
|
formula?: string;
|
|
11
|
+
/** When type === "flag": predicate matched against the record. */
|
|
12
|
+
where?: Where;
|
|
10
13
|
}
|
|
11
14
|
/** Minimal schema shape: just the ordered field map. */
|
|
12
15
|
export interface DerivableSchema {
|
|
@@ -21,17 +24,19 @@ export type DeriveRefRecords = Record<string, Record<string, DerivableRecord>>;
|
|
|
21
24
|
* null when dangling / not loaded), keyed by the LOCAL field name —
|
|
22
25
|
* the shape `evaluateDerived` reads for `<field>.<col>` derefs. */
|
|
23
26
|
export declare function resolveRowRefs(schema: DerivableSchema, record: DerivableRecord, refRecords: DeriveRefRecords): NonNullable<FormulaContext["refs"]>;
|
|
24
|
-
/** Evaluate every `derived` field against `base`, saturating
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
/** Evaluate every `derived` and `flag` field against `base`, saturating
|
|
28
|
+
* so a computed field can read another one computed in an earlier pass
|
|
29
|
+
* (`subtotal → tax → total` converges in ≤ field-count passes; a flag
|
|
30
|
+
* may read a derived value, or another flag via its stringified
|
|
31
|
+
* boolean). Cycles can't loop forever — passes are bounded by the
|
|
32
|
+
* number of computed fields and the loop breaks as soon as a pass
|
|
33
|
+
* changes nothing. Failed formulas stay ABSENT (the UI renders them as
|
|
34
|
+
* em-dash); flags are total (always true/false). Returns a copy;
|
|
35
|
+
* `base` is never mutated.
|
|
31
36
|
*
|
|
32
|
-
*
|
|
37
|
+
* Computed keys already present in `base` are stripped before
|
|
33
38
|
* evaluation: computed output is host-truth, never persisted-input
|
|
34
|
-
* fallback. A record JSON can carry a stale (or forged)
|
|
39
|
+
* fallback. A record JSON can carry a stale (or forged) computed value
|
|
35
40
|
* — raw Write/Edit, legacy data — and without the strip, a failing
|
|
36
41
|
* formula would silently surface that value as if the host computed
|
|
37
42
|
* it. */
|
|
@@ -52,10 +52,15 @@ export type CollectionFieldSpec = z.infer<typeof FieldSpecZ>;
|
|
|
52
52
|
* `derived` / display-only types (see `SubFieldSpecZ`). */
|
|
53
53
|
export type CollectionSubFieldSpec = z.infer<typeof SubFieldSpecZ>;
|
|
54
54
|
export type CollectionFieldType = CollectionFieldSpec["type"];
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
/** The computed-boolean variant — a `where` predicate bound to a field
|
|
56
|
+
* name; see `FlagFieldZ`. */
|
|
57
|
+
export type CollectionFlagField = Extract<CollectionFieldSpec, {
|
|
58
|
+
type: "flag";
|
|
59
|
+
}>;
|
|
60
|
+
/** derived/embed/backlinks/rollup/toggle/flag are host-computed or
|
|
61
|
+
* projected — never written to the record JSON, so required / value
|
|
62
|
+
* checks and edit-draft slots must not apply to them. THE single source
|
|
63
|
+
* for "computed" — lives here (zod-free at runtime) so browser code
|
|
59
64
|
* (`./draft`) and the zod record compiler (`./recordZ`, which re-exports
|
|
60
65
|
* it) share one set instead of drifting copies. */
|
|
61
66
|
export declare const COMPUTED_TYPES: ReadonlySet<CollectionFieldType>;
|
|
@@ -12,6 +12,46 @@ export declare const WhenZ: z.ZodObject<{
|
|
|
12
12
|
field: z.ZodString;
|
|
13
13
|
in: z.ZodArray<z.ZodString>;
|
|
14
14
|
}, z.core.$strip>;
|
|
15
|
+
export declare const ValueRefZ: z.ZodObject<{
|
|
16
|
+
record: z.ZodOptional<z.ZodString>;
|
|
17
|
+
field: z.ZodString;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
export declare const WhereCondZ: z.ZodObject<{
|
|
20
|
+
field: z.ZodString;
|
|
21
|
+
op: z.ZodEnum<{
|
|
22
|
+
in: "in";
|
|
23
|
+
eq: "eq";
|
|
24
|
+
ne: "ne";
|
|
25
|
+
gt: "gt";
|
|
26
|
+
gte: "gte";
|
|
27
|
+
lt: "lt";
|
|
28
|
+
lte: "lte";
|
|
29
|
+
contains: "contains";
|
|
30
|
+
}>;
|
|
31
|
+
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
32
|
+
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
33
|
+
record: z.ZodOptional<z.ZodString>;
|
|
34
|
+
field: z.ZodString;
|
|
35
|
+
}, z.core.$strip>>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export declare const WhereZ: z.ZodArray<z.ZodObject<{
|
|
38
|
+
field: z.ZodString;
|
|
39
|
+
op: z.ZodEnum<{
|
|
40
|
+
in: "in";
|
|
41
|
+
eq: "eq";
|
|
42
|
+
ne: "ne";
|
|
43
|
+
gt: "gt";
|
|
44
|
+
gte: "gte";
|
|
45
|
+
lt: "lt";
|
|
46
|
+
lte: "lte";
|
|
47
|
+
contains: "contains";
|
|
48
|
+
}>;
|
|
49
|
+
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
50
|
+
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
51
|
+
record: z.ZodOptional<z.ZodString>;
|
|
52
|
+
field: z.ZodString;
|
|
53
|
+
}, z.core.$strip>>;
|
|
54
|
+
}, z.core.$strip>>;
|
|
15
55
|
export declare const SubFieldSpecZ: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
16
56
|
label: z.ZodString;
|
|
17
57
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -210,6 +250,33 @@ export declare const FieldSpecZ: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
210
250
|
in: z.ZodArray<z.ZodString>;
|
|
211
251
|
}, z.core.$strip>>;
|
|
212
252
|
type: z.ZodLiteral<"toggle">;
|
|
253
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
254
|
+
where: z.ZodArray<z.ZodObject<{
|
|
255
|
+
field: z.ZodString;
|
|
256
|
+
op: z.ZodEnum<{
|
|
257
|
+
in: "in";
|
|
258
|
+
eq: "eq";
|
|
259
|
+
ne: "ne";
|
|
260
|
+
gt: "gt";
|
|
261
|
+
gte: "gte";
|
|
262
|
+
lt: "lt";
|
|
263
|
+
lte: "lte";
|
|
264
|
+
contains: "contains";
|
|
265
|
+
}>;
|
|
266
|
+
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
267
|
+
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
268
|
+
record: z.ZodOptional<z.ZodString>;
|
|
269
|
+
field: z.ZodString;
|
|
270
|
+
}, z.core.$strip>>;
|
|
271
|
+
}, z.core.$strip>>;
|
|
272
|
+
label: z.ZodString;
|
|
273
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
274
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
275
|
+
when: z.ZodOptional<z.ZodObject<{
|
|
276
|
+
field: z.ZodString;
|
|
277
|
+
in: z.ZodArray<z.ZodString>;
|
|
278
|
+
}, z.core.$strip>>;
|
|
279
|
+
type: z.ZodLiteral<"flag">;
|
|
213
280
|
}, z.core.$strip>], "type">;
|
|
214
281
|
/** A schema-declared record action, rendered as a button in the read-only
|
|
215
282
|
* detail view. Domain-free: the host validates the shape; the meaning
|
|
@@ -434,6 +501,24 @@ export declare const AgentIngestZ: z.ZodObject<{
|
|
|
434
501
|
role: z.ZodString;
|
|
435
502
|
template: z.ZodString;
|
|
436
503
|
}, z.core.$strip>;
|
|
504
|
+
/** The Google event fields a collection may pull from. `id` is absent on
|
|
505
|
+
* purpose — it always lands in the primary field, since upsert-by-event-id
|
|
506
|
+
* is what makes the sync idempotent. */
|
|
507
|
+
export declare const GOOGLE_CALENDAR_SOURCE_FIELDS: readonly ["summary", "start", "end", "htmlLink", "colorId", "status"];
|
|
508
|
+
/** Marks a collection as the destination of the LLM-free Google Calendar
|
|
509
|
+
* sync (#2095). `map` is collectionField → Google event field, so the user's
|
|
510
|
+
* collection keeps whatever field names it already uses. */
|
|
511
|
+
export declare const GoogleCalendarSyncZ: z.ZodObject<{
|
|
512
|
+
calendarId: z.ZodOptional<z.ZodString>;
|
|
513
|
+
map: z.ZodRecord<z.ZodString, z.ZodEnum<{
|
|
514
|
+
summary: "summary";
|
|
515
|
+
start: "start";
|
|
516
|
+
end: "end";
|
|
517
|
+
htmlLink: "htmlLink";
|
|
518
|
+
colorId: "colorId";
|
|
519
|
+
status: "status";
|
|
520
|
+
}>>;
|
|
521
|
+
}, z.core.$strip>;
|
|
437
522
|
/** `ingest` is a discriminated union on `kind`: the three declarative
|
|
438
523
|
* retrievers fetch-and-map; `agent` dispatches a hidden worker. Optional on
|
|
439
524
|
* every schema — skill-backed collections usually omit it; only feeds
|
|
@@ -469,46 +554,6 @@ export declare const IngestZ: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
469
554
|
role: z.ZodString;
|
|
470
555
|
template: z.ZodString;
|
|
471
556
|
}, z.core.$strip>], "kind">;
|
|
472
|
-
export declare const ValueRefZ: z.ZodObject<{
|
|
473
|
-
record: z.ZodOptional<z.ZodString>;
|
|
474
|
-
field: z.ZodString;
|
|
475
|
-
}, z.core.$strip>;
|
|
476
|
-
export declare const WhereCondZ: z.ZodObject<{
|
|
477
|
-
field: z.ZodString;
|
|
478
|
-
op: z.ZodEnum<{
|
|
479
|
-
in: "in";
|
|
480
|
-
eq: "eq";
|
|
481
|
-
ne: "ne";
|
|
482
|
-
gt: "gt";
|
|
483
|
-
gte: "gte";
|
|
484
|
-
lt: "lt";
|
|
485
|
-
lte: "lte";
|
|
486
|
-
contains: "contains";
|
|
487
|
-
}>;
|
|
488
|
-
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
489
|
-
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
490
|
-
record: z.ZodOptional<z.ZodString>;
|
|
491
|
-
field: z.ZodString;
|
|
492
|
-
}, z.core.$strip>>;
|
|
493
|
-
}, z.core.$strip>;
|
|
494
|
-
export declare const WhereZ: z.ZodArray<z.ZodObject<{
|
|
495
|
-
field: z.ZodString;
|
|
496
|
-
op: z.ZodEnum<{
|
|
497
|
-
in: "in";
|
|
498
|
-
eq: "eq";
|
|
499
|
-
ne: "ne";
|
|
500
|
-
gt: "gt";
|
|
501
|
-
gte: "gte";
|
|
502
|
-
lt: "lt";
|
|
503
|
-
lte: "lte";
|
|
504
|
-
contains: "contains";
|
|
505
|
-
}>;
|
|
506
|
-
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
507
|
-
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
508
|
-
record: z.ZodOptional<z.ZodString>;
|
|
509
|
-
field: z.ZodString;
|
|
510
|
-
}, z.core.$strip>>;
|
|
511
|
-
}, z.core.$strip>>;
|
|
512
557
|
export declare const DynamicIconSourceZ: z.ZodObject<{
|
|
513
558
|
collection: z.ZodString;
|
|
514
559
|
from: z.ZodOptional<z.ZodEnum<{
|
|
@@ -616,12 +661,12 @@ export declare const DynamicIconSpecZ: z.ZodObject<{
|
|
|
616
661
|
* workspace-relative and containment-checked exactly like `dataPath`. The
|
|
617
662
|
* row-id column is the schema's existing `primaryKey` — there is
|
|
618
663
|
* deliberately no second key concept here.
|
|
619
|
-
* See plans/feat-collection-csv-duckdb-source.md. */
|
|
664
|
+
* See plans/done/feat-collection-csv-duckdb-source.md. */
|
|
620
665
|
export declare const DataSourceZ: z.ZodObject<{
|
|
621
666
|
type: z.ZodLiteral<"csv">;
|
|
622
667
|
path: z.ZodString;
|
|
623
668
|
}, z.core.$strip>;
|
|
624
|
-
export declare const CollectionSchemaZ: z.ZodObject<{
|
|
669
|
+
export declare const CollectionSchemaZ: z.ZodPreprocess<z.ZodObject<{
|
|
625
670
|
title: z.ZodString;
|
|
626
671
|
icon: z.ZodString;
|
|
627
672
|
dataPath: z.ZodOptional<z.ZodString>;
|
|
@@ -799,6 +844,33 @@ export declare const CollectionSchemaZ: z.ZodObject<{
|
|
|
799
844
|
in: z.ZodArray<z.ZodString>;
|
|
800
845
|
}, z.core.$strip>>;
|
|
801
846
|
type: z.ZodLiteral<"toggle">;
|
|
847
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
848
|
+
where: z.ZodArray<z.ZodObject<{
|
|
849
|
+
field: z.ZodString;
|
|
850
|
+
op: z.ZodEnum<{
|
|
851
|
+
in: "in";
|
|
852
|
+
eq: "eq";
|
|
853
|
+
ne: "ne";
|
|
854
|
+
gt: "gt";
|
|
855
|
+
gte: "gte";
|
|
856
|
+
lt: "lt";
|
|
857
|
+
lte: "lte";
|
|
858
|
+
contains: "contains";
|
|
859
|
+
}>;
|
|
860
|
+
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
861
|
+
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
862
|
+
record: z.ZodOptional<z.ZodString>;
|
|
863
|
+
field: z.ZodString;
|
|
864
|
+
}, z.core.$strip>>;
|
|
865
|
+
}, z.core.$strip>>;
|
|
866
|
+
label: z.ZodString;
|
|
867
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
868
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
869
|
+
when: z.ZodOptional<z.ZodObject<{
|
|
870
|
+
field: z.ZodString;
|
|
871
|
+
in: z.ZodArray<z.ZodString>;
|
|
872
|
+
}, z.core.$strip>>;
|
|
873
|
+
type: z.ZodLiteral<"flag">;
|
|
802
874
|
}, z.core.$strip>], "type">>;
|
|
803
875
|
actions: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
804
876
|
role: z.ZodString;
|
|
@@ -1002,6 +1074,17 @@ export declare const CollectionSchemaZ: z.ZodObject<{
|
|
|
1002
1074
|
role: z.ZodString;
|
|
1003
1075
|
template: z.ZodString;
|
|
1004
1076
|
}, z.core.$strip>], "kind">>;
|
|
1077
|
+
googleCalendar: z.ZodOptional<z.ZodObject<{
|
|
1078
|
+
calendarId: z.ZodOptional<z.ZodString>;
|
|
1079
|
+
map: z.ZodRecord<z.ZodString, z.ZodEnum<{
|
|
1080
|
+
summary: "summary";
|
|
1081
|
+
start: "start";
|
|
1082
|
+
end: "end";
|
|
1083
|
+
htmlLink: "htmlLink";
|
|
1084
|
+
colorId: "colorId";
|
|
1085
|
+
status: "status";
|
|
1086
|
+
}>>;
|
|
1087
|
+
}, z.core.$strip>>;
|
|
1005
1088
|
dynamicIcon: z.ZodOptional<z.ZodObject<{
|
|
1006
1089
|
source: z.ZodObject<{
|
|
1007
1090
|
collection: z.ZodString;
|
|
@@ -1053,4 +1136,4 @@ export declare const CollectionSchemaZ: z.ZodObject<{
|
|
|
1053
1136
|
}, z.core.$strip>>;
|
|
1054
1137
|
fallback: z.ZodOptional<z.ZodString>;
|
|
1055
1138
|
}, z.core.$strip>>;
|
|
1056
|
-
}, z.core.$strip
|
|
1139
|
+
}, z.core.$strip>>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_ids = require("../ids-BR4U1dJD.cjs");
|
|
3
|
+
const require_promptSafety = require("../promptSafety-Co4cYQ_Z.cjs");
|
|
3
4
|
const require_errorMessage = require("../errorMessage--LvXe_Jx.cjs");
|
|
4
5
|
//#region src/collection/core/presentCollection.ts
|
|
5
6
|
var TOOL_NAME = "presentCollection";
|
|
@@ -225,7 +226,7 @@ function rowDraftToRecord(rowDraft, subFields) {
|
|
|
225
226
|
function draftToRecord(state, schema) {
|
|
226
227
|
const record = {};
|
|
227
228
|
for (const [key, field] of Object.entries(schema.fields)) {
|
|
228
|
-
if (
|
|
229
|
+
if (require_ids.COMPUTED_TYPES.has(field.type)) continue;
|
|
229
230
|
if (field.type === "boolean") {
|
|
230
231
|
if (shouldEmitBoolean(state, key, field)) record[key] = state.bool[key] === true;
|
|
231
232
|
continue;
|
|
@@ -281,7 +282,7 @@ function firstMissingTableSubField(field, rows) {
|
|
|
281
282
|
* value, and the computed/projected kinds (COMPUTED_TYPES — the shared
|
|
282
283
|
* set, so a future computed type can't drift past this check) have no
|
|
283
284
|
* draft input at all. */
|
|
284
|
-
var NEVER_MISSING_TYPES = /* @__PURE__ */ new Set(["boolean", ...
|
|
285
|
+
var NEVER_MISSING_TYPES = /* @__PURE__ */ new Set(["boolean", ...require_ids.COMPUTED_TYPES]);
|
|
285
286
|
function validateOneField(key, field, draft, record) {
|
|
286
287
|
if (!require_promptSafety.fieldVisible(field, record)) return null;
|
|
287
288
|
if (field.type === "table" && field.of) {
|
|
@@ -436,16 +437,16 @@ function shortHexId() {
|
|
|
436
437
|
return crypto.randomUUID().replace(/-/g, "").slice(0, 8);
|
|
437
438
|
}
|
|
438
439
|
//#endregion
|
|
439
|
-
exports.AGENT_INGEST_KIND =
|
|
440
|
-
exports.COMPUTED_TYPES =
|
|
440
|
+
exports.AGENT_INGEST_KIND = require_ids.AGENT_INGEST_KIND;
|
|
441
|
+
exports.COMPUTED_TYPES = require_ids.COMPUTED_TYPES;
|
|
441
442
|
exports.ENUM_ALERT = ENUM_ALERT;
|
|
442
443
|
exports.ENUM_NEUTRAL = ENUM_NEUTRAL;
|
|
443
444
|
exports.ENUM_NUDGE = ENUM_NUDGE;
|
|
444
|
-
exports.FEED_SCHEDULES =
|
|
445
|
-
exports.INGEST_KINDS =
|
|
445
|
+
exports.FEED_SCHEDULES = require_ids.FEED_SCHEDULES;
|
|
446
|
+
exports.INGEST_KINDS = require_ids.INGEST_KINDS;
|
|
446
447
|
exports.MINUTES_PER_DAY = require_promptSafety.MINUTES_PER_DAY;
|
|
447
|
-
exports.SAFE_RECORD_ID_PATTERN =
|
|
448
|
-
exports.SAFE_SLUG_PATTERN =
|
|
448
|
+
exports.SAFE_RECORD_ID_PATTERN = require_ids.SAFE_RECORD_ID_PATTERN;
|
|
449
|
+
exports.SAFE_SLUG_PATTERN = require_ids.SAFE_SLUG_PATTERN;
|
|
449
450
|
exports.TOOL_DEFINITION = TOOL_DEFINITION;
|
|
450
451
|
exports.TOOL_NAME = TOOL_NAME;
|
|
451
452
|
exports.actionVisible = require_promptSafety.actionVisible;
|
|
@@ -466,7 +467,7 @@ exports.daySlice = require_promptSafety.daySlice;
|
|
|
466
467
|
exports.defangForPrompt = require_promptSafety.defangForPrompt;
|
|
467
468
|
exports.deriveAll = require_promptSafety.deriveAll;
|
|
468
469
|
exports.draftToRecord = draftToRecord;
|
|
469
|
-
exports.embedTargetId =
|
|
470
|
+
exports.embedTargetId = require_ids.embedTargetId;
|
|
470
471
|
exports.emptyRow = emptyRow;
|
|
471
472
|
exports.enumColorClasses = enumColorClasses;
|
|
472
473
|
exports.enumSortValue = enumSortValue;
|
|
@@ -477,12 +478,13 @@ exports.executePresentCollection = executePresentCollection;
|
|
|
477
478
|
exports.fieldVisible = require_promptSafety.fieldVisible;
|
|
478
479
|
exports.firstDateField = require_promptSafety.firstDateField;
|
|
479
480
|
exports.firstMissingRequiredField = firstMissingRequiredField;
|
|
480
|
-
exports.isFieldDrivenEvery =
|
|
481
|
-
exports.isReadOnlySchema =
|
|
482
|
-
exports.isSafeRecordId =
|
|
483
|
-
exports.isSafeSlug =
|
|
481
|
+
exports.isFieldDrivenEvery = require_ids.isFieldDrivenEvery;
|
|
482
|
+
exports.isReadOnlySchema = require_ids.isReadOnlySchema;
|
|
483
|
+
exports.isSafeRecordId = require_ids.isSafeRecordId;
|
|
484
|
+
exports.isSafeSlug = require_ids.isSafeSlug;
|
|
484
485
|
exports.isSortableField = isSortableField;
|
|
485
486
|
exports.itemIdOf = itemIdOf;
|
|
487
|
+
exports.itemIsDone = require_promptSafety.itemIsDone;
|
|
486
488
|
exports.itemLabelOf = itemLabelOf;
|
|
487
489
|
exports.labelFieldFor = labelFieldFor;
|
|
488
490
|
exports.matchesWhere = require_promptSafety.matchesWhere;
|