@desplega.ai/agent-swarm 2.4.3 → 2.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-adapter-1885dpr7.js → acp-adapter-2wdkktv6.js} +1 -2
- package/dist/{actions-pn76n32q.js → actions-c40ebcm4.js} +18 -18
- package/dist/{amp-adapter-af84rx1d.js → amp-adapter-wb67m95z.js} +2 -2
- package/dist/{app-6sv8mhzm.js → app-353vre8g.js} +3 -3
- package/dist/{assistant-sc2tf825.js → assistant-sj1njh23.js} +21 -21
- package/dist/{boot-reembed-y3m0ydzj.js → boot-reembed-b9c3az3c.js} +1 -1
- package/dist/{boot-reembed-gvxjs2py.js → boot-reembed-qdkvxeem.js} +1 -1
- package/dist/{boot-scrub-sweep-1j9mk05f.js → boot-scrub-sweep-m3wh8eks.js} +2 -2
- package/dist/{boot-seeds-37sp626b.js → boot-seeds-j2273s54.js} +4 -4
- package/dist/{claude-adapter-rp0jtnwr.js → claude-adapter-m7q0a085.js} +2 -2
- package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-5ptb6tzs.js} +2 -2
- package/dist/{claude-managed-setup-rdt248k7.js → claude-managed-setup-smrqk5j5.js} +3 -3
- package/dist/{claude-sdk-session-53rcw5we.js → claude-sdk-session-38xnz21e.js} +8284 -8267
- package/dist/{cli-6eyncg0y.js → cli-018r4jq6.js} +34 -6
- package/dist/{cli-sds5zzs8.js → cli-1f3qzw6y.js} +78 -12
- package/dist/{cli-f0p0f6ja.js → cli-1sp861s4.js} +7 -7
- package/dist/{cli-dm8p2dpf.js → cli-1syn2xy1.js} +10 -10
- package/dist/{cli-tkf4x6ha.js → cli-37j04k05.js} +11 -11
- package/dist/{cli-v87dr6e3.js → cli-3a45zcgm.js} +1 -1
- package/dist/{cli-1n9gdg56.js → cli-43x64hv3.js} +4 -4
- package/dist/{cli-p0qerd2r.js → cli-4zfqgjc5.js} +2 -2
- package/dist/{cli-aa3tb29r.js → cli-7c9qs530.js} +1 -1
- package/dist/{cli-9qtjfd60.js → cli-848hxdwj.js} +1 -1
- package/dist/{cli-1xsraagq.js → cli-94gwyg7m.js} +8 -8
- package/dist/{cli-0dxxwfkt.js → cli-9hstj09h.js} +17 -14
- package/dist/{cli-1012xb7j.js → cli-9yqgm9nd.js} +22 -22
- package/dist/{cli-pygdsgh8.js → cli-a92r1127.js} +1 -1
- package/dist/{cli-8vverzf7.js → cli-ba8ne1es.js} +5 -0
- package/dist/{cli-bxrqvpg5.js → cli-be2161h1.js} +7 -7
- package/dist/{cli-npfe9t1s.js → cli-bnes4z6b.js} +2 -2
- package/dist/{cli-aypbg9r2.js → cli-cxxe61f6.js} +1 -1
- package/dist/{cli-vq9gqarq.js → cli-dk44dxec.js} +1 -1
- package/dist/{cli-836ehxmt.js → cli-eww120g8.js} +3 -2
- package/dist/{cli-a0kcty51.js → cli-f01h25yt.js} +1 -1
- package/dist/{cli-mzkwkbdy.js → cli-f0g3pgvf.js} +1 -1
- package/dist/{cli-1ma335fz.js → cli-ftc1g5tj.js} +2 -2
- package/dist/{cli-4yef8ghv.js → cli-fv5hepyy.js} +3 -3
- package/dist/{cli-58vwn100.js → cli-g35m2xwm.js} +4 -4
- package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
- package/dist/{cli-gx0j2khs.js → cli-j99azg3g.js} +3 -3
- package/dist/{cli-er83cjbn.js → cli-k8g16gz3.js} +416 -116
- package/dist/{cli-qp2m4btv.js → cli-kpw04va0.js} +2 -2
- package/dist/{cli-8y99kfey.js → cli-ms85309d.js} +33 -15
- package/dist/{cli-kgnkyabk.js → cli-n72rg53p.js} +1555 -645
- package/dist/{cli-e4d78xsv.js → cli-p14m2cnp.js} +1 -1
- package/dist/{cli-1eszr343.js → cli-qfxc84gh.js} +1 -1
- package/dist/{cli-wk28hzqn.js → cli-qwhy2qma.js} +1 -1
- package/dist/{cli-73ezfhha.js → cli-st8aw1m6.js} +228 -11
- package/dist/{cli-zvbb4n0e.js → cli-tw4p90jb.js} +92 -192
- package/dist/{cli-038fga5k.js → cli-v0yrfmdh.js} +148 -183
- package/dist/{cli-6aen3ezb.js → cli-v8fjakwf.js} +1 -1
- package/dist/{cli-99jez72r.js → cli-w9etnnxk.js} +6 -1
- package/dist/{cli-vcgscaan.js → cli-wt0jf9hm.js} +217 -80
- package/dist/{cli-s9rr4gr2.js → cli-xpa64rek.js} +1065 -305
- package/dist/{cli-h0mgxann.js → cli-z7d29rw9.js} +2 -2
- package/dist/cli.js +45 -20
- package/dist/{codex-adapter-2zrmab9b.js → codex-adapter-tn6k5mkg.js} +1 -1
- package/dist/{codex-session-runner-kbkz62vc.js → codex-session-runner-7vjt7jbw.js} +1 -1
- package/dist/{commands-hd574th6.js → commands-t7rz9146.js} +2 -2
- package/dist/{controller-pz5mcfg4.js → controller-m2jasma5.js} +2 -2
- package/dist/{controllers-connect-5rgq2hfk.js → controllers-connect-9ftpex99.js} +19 -19
- package/dist/{cursor-adapter-mgaprq0j.js → cursor-adapter-mjv79e4z.js} +1 -1
- package/dist/{db-6nf1207q.js → db-6sfrn9g3.js} +1 -1
- package/dist/{db-h06dxp05.js → db-rn673r06.js} +3 -3
- package/dist/{dispatcher-zthpy4m1.js → dispatcher-c155xz0p.js} +17 -17
- package/dist/{dsh-adapter-64dhw0j7.js → dsh-adapter-3mmszc1x.js} +1 -1
- package/dist/{external-channel-x01t7ke6.js → external-channel-35k6tkv8.js} +2 -2
- package/dist/{grok-adapter-h21jv594.js → grok-adapter-tfrq7tg1.js} +2 -3
- package/dist/handlers-7gw64dxw.js +39 -0
- package/dist/{heartbeat-zzfksckz.js → heartbeat-dyg4npkp.js} +20 -20
- package/dist/{hook-z4zhzj1f.js → hook-drspbwpe.js} +1 -1
- package/dist/{hook-3xfqhh2s.js → hook-x26b31bg.js} +1 -1
- package/dist/{http-q813tmya.js → http-pk972xyw.js} +571 -294
- package/dist/{index-va3y63es.js → index-6srwvd5b.js} +1 -2
- package/dist/{index-x8xbyn1t.js → index-arytgj5q.js} +1 -1
- package/dist/{index-wbbs14c5.js → index-bgdyvcnv.js} +17 -17
- package/dist/{index-s98037v0.js → index-cbxkmfc5.js} +1 -2
- package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
- package/dist/{index-m0a4ydqj.js → index-gabbcdn2.js} +17 -17
- package/dist/{index-220tk9bw.js → index-jwxkkex2.js} +139 -76
- package/dist/index-tfb26zhy.js +41 -0
- package/dist/{keepalive-y5t1my7m.js → keepalive-7yrng7px.js} +3 -3
- package/dist/{lead-2xwtq66b.js → lead-7e02z839.js} +29 -30
- package/dist/{maintenance-ybfsaedv.js → maintenance-e6cemdqt.js} +1 -1
- package/dist/{node-3v3f08f7.js → node-de6akczr.js} +10 -9
- package/dist/{oauth-refresh-sweep-909jmn12.js → oauth-refresh-sweep-yw3xdbcj.js} +2 -2
- package/dist/{onboard-xn6fkkys.js → onboard-0a9y5yrc.js} +2 -2
- package/dist/{otel-impl-e6mn0z13.js → otel-impl-trjpkfb7.js} +1 -1
- package/dist/{pricing-refresh-ygd362ep.js → pricing-refresh-d2b5my0y.js} +3 -3
- package/dist/{rbac-roles-mb470p4e.js → rbac-roles-hey3yv9d.js} +2 -2
- package/dist/{rbac-roles-c9axvfnz.js → rbac-roles-nxh5ahwk.js} +2 -2
- package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
- package/dist/{render-v2-g0306nh1.js → render-v2-rr3p2atg.js} +3 -3
- package/dist/{resume-v315hnq6.js → resume-2efkf1s1.js} +5 -5
- package/dist/{session-access-2zg285a1.js → session-access-s2mttxpw.js} +6 -4
- package/dist/{setup-a4mtf02k.js → setup-vypma5yt.js} +1 -1
- package/dist/{work-objects-9fr0fgtn.js → work-objects-rvhckdkp.js} +20 -20
- package/dist/{worker-qae22jeb.js → worker-5snytpbd.js} +29 -30
- package/dist/worker-token-xf11yyds.js +136 -0
- package/openapi.json +303 -13
- package/package.json +8 -8
- package/src/apps/action-runner.ts +4 -0
- package/src/apps/catalog.generated.json +209 -4
- package/src/apps/page-validator.ts +21 -3
- package/src/be/chunking.ts +42 -9
- package/src/be/db/tasks/draft-text.ts +15 -0
- package/src/be/db/tasks/read.ts +14 -1
- package/src/be/db.ts +5 -1
- package/src/be/memory/index-content.ts +36 -17
- package/src/be/memory/providers/openai-embedding.ts +115 -61
- package/src/be/memory/providers/sqlite-store.ts +69 -23
- package/src/be/memory/reranker.ts +31 -1
- package/src/be/memory/search-candidates.ts +47 -0
- package/src/be/memory/types.ts +14 -0
- package/src/be/migrations/232_agent_session_tokens.sql +41 -0
- package/src/be/scripts/typecheck.ts +2 -0
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +116 -55
- package/src/be/seed-scripts/index.ts +2 -2
- package/src/be/swarm-config-guard.ts +40 -1
- package/src/be/task-attachment-store.ts +30 -0
- package/src/be/users.ts +169 -12
- package/src/cli.tsx +24 -0
- package/src/commands/worker-token.ts +164 -0
- package/src/extensions/catalog.generated.json +4 -4
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +7 -0
- package/src/fs/provider.ts +13 -1
- package/src/heartbeat/heartbeat.ts +31 -11
- package/src/http/apps.ts +43 -5
- package/src/http/codex-oauth-keep-warm.ts +27 -9
- package/src/http/config.ts +5 -3
- package/src/http/core.ts +2 -0
- package/src/http/fs.ts +54 -34
- package/src/http/mcp-body.ts +37 -0
- package/src/http/mcp-user.ts +3 -5
- package/src/http/mcp.ts +6 -7
- package/src/http/memory.ts +26 -15
- package/src/http/page-proxy.ts +61 -5
- package/src/http/pages-public.ts +27 -44
- package/src/http/pages.ts +4 -4
- package/src/http/script-runs.ts +2 -0
- package/src/http/session-access.ts +51 -2
- package/src/http/sessions.ts +249 -10
- package/src/http/tasks.ts +4 -32
- package/src/http/users.ts +12 -1
- package/src/integrations/chat-sdk/adapters.ts +7 -3
- package/src/integrations/chat-sdk/attachments.ts +90 -12
- package/src/integrations/chat-sdk/facts.ts +120 -0
- package/src/integrations/chat-sdk/inbound.ts +156 -8
- package/src/integrations/chat-sdk/limits.ts +24 -0
- package/src/integrations/chat-sdk/outbound-files.ts +186 -0
- package/src/integrations/chat-sdk/outbound.ts +234 -4
- package/src/integrations/chat-sdk/relay.ts +4 -1
- package/src/integrations/chat-sdk/router.ts +28 -2
- package/src/integrations/chat-sdk/steering.ts +9 -0
- package/src/integrations/chat-sdk/templates.ts +14 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
- package/src/mcp-limits.ts +20 -0
- package/src/pages/browser-sdk.ts +8 -3
- package/src/pages/feedback-overlay.ts +1 -1
- package/src/providers/acp-adapter.ts +33 -13
- package/src/providers/acp-swarm-events.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/codex-adapter.ts +106 -119
- package/src/providers/codex-agents-md.ts +35 -229
- package/src/providers/codex-oauth/storage.ts +1 -1
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/rbac/legacy-policy.ts +3 -1
- package/src/rbac/permissions.ts +4 -0
- package/src/realtime/transport.ts +1 -2
- package/src/script-workflows/workflow-ctx.ts +1 -0
- package/src/scripts-runtime/types/stdlib.d.ts +2 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +8 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
- package/src/server-user.ts +2 -0
- package/src/server.ts +2 -0
- package/src/slack/assistant.ts +2 -2
- package/src/slack/files.ts +2 -0
- package/src/slack/handlers.ts +4 -4
- package/src/slack/inbound-files.ts +39 -6
- package/src/slack/thread-buffer.ts +2 -1
- package/src/tasks/task-terminal-effects.ts +21 -17
- package/src/tests/acp-adapter.test.ts +10 -23
- package/src/tests/acp-fake-agent.ts +36 -0
- package/src/tests/acp-swarm-events.test.ts +1 -1
- package/src/tests/agent-session-tokens.test.ts +452 -0
- package/src/tests/apps-action-parent-task.test.ts +295 -0
- package/src/tests/apps-card-grid.test.ts +197 -0
- package/src/tests/apps-catalog-additions.test.ts +120 -0
- package/src/tests/apps-tree.test.ts +129 -0
- package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
- package/src/tests/chat-sdk-config.test.ts +11 -0
- package/src/tests/chat-sdk-facts.test.ts +23 -0
- package/src/tests/chat-sdk-inbound.test.ts +558 -4
- package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
- package/src/tests/codex-adapter.test.ts +167 -242
- package/src/tests/codex-oauth-keep-warm.test.ts +85 -1
- package/src/tests/config-api-only-keys.test.ts +9 -0
- package/src/tests/config-session-auth.test.ts +14 -0
- package/src/tests/cors-allowlist.test.ts +1 -1
- package/src/tests/docs-index-footprint.test.js +2 -2
- package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
- package/src/tests/grok-adapter.test.ts +3 -3
- package/src/tests/heartbeat-checklist.test.ts +33 -0
- package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
- package/src/tests/heartbeat-jev-gate.test.ts +265 -1
- package/src/tests/kv-page-proxy.test.ts +91 -5
- package/src/tests/launch-password-rejection.test.ts +2 -2
- package/src/tests/mcp-input-caps.test.ts +294 -0
- package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
- package/src/tests/memory-embedding-input-cap.test.ts +114 -0
- package/src/tests/memory.test.ts +14 -0
- package/src/tests/migration-232-agent-session-tokens.test.ts +67 -0
- package/src/tests/page-guest-session.test.ts +19 -8
- package/src/tests/page-proxy-authed.test.ts +1 -1
- package/src/tests/page-proxy.test.ts +17 -10
- package/src/tests/page-session.test.ts +102 -1
- package/src/tests/pages-authed-mode.test.ts +82 -12
- package/src/tests/pages-password-mode.test.ts +5 -5
- package/src/tests/rbac-engine.test.ts +1 -0
- package/src/tests/realtime-transport.test.ts +13 -7
- package/src/tests/runtime-child-token-cleanup.test.ts +3 -3
- package/src/tests/script-connections.test.ts +2 -0
- package/src/tests/script-runs-http.test.ts +84 -0
- package/src/tests/scripts-http.test.ts +10 -1
- package/src/tests/session-route-posture.test.ts +2 -0
- package/src/tests/swarm-config-export-to-env.test.ts +22 -3
- package/src/tests/task-audio-transcription.test.ts +299 -0
- package/src/tests/task-completion-memory-chunking.test.ts +434 -0
- package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
- package/src/tests/transcription.test.ts +299 -0
- package/src/tests/worker-token-cli.test.ts +76 -0
- package/src/tests/workflow-executors.test.ts +4 -2
- package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
- package/src/tests/workflow-system-one-decision.test.ts +2 -1
- package/src/tests/workflow-system-one-extraction.test.ts +805 -0
- package/src/tools/chat-access.ts +10 -0
- package/src/tools/chat-post.ts +31 -11
- package/src/tools/chat-reply.ts +32 -10
- package/src/tools/memory-search.ts +3 -1
- package/src/tools/system-one-decide.ts +17 -4
- package/src/types.ts +8 -1
- package/src/utils/config-env-export.ts +3 -1
- package/src/utils/page-session.ts +133 -20
- package/src/utils/request-auth-context.ts +2 -1
- package/src/utils/transcription.ts +246 -0
- package/src/workflows/definition.ts +7 -1
- package/src/workflows/engine.ts +18 -12
- package/src/workflows/executors/index.ts +1 -0
- package/src/workflows/executors/registry.ts +2 -0
- package/src/workflows/executors/system-one-decision.ts +84 -262
- package/src/workflows/executors/system-one-extract-wire.ts +57 -0
- package/src/workflows/executors/system-one-extraction.ts +830 -0
- package/src/workflows/executors/system-one-providers.ts +316 -114
- package/src/workflows/executors/system-one-transport.ts +264 -0
- package/templates/extensions/slack-reply-gate/README.md +24 -22
- package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
- package/templates/extensions/slack-reply-gate/manifest.json +2 -2
- package/templates/official/lead/HEARTBEAT.md +1 -1
- package/templates/skills/apps/SKILL.md +31 -7
- package/templates/skills/apps/content.md +31 -7
- package/templates/skills/chat-sdk/content.md +6 -2
- package/templates/skills/code-quality/content.md +2 -1
- package/templates/skills/heartbeat-runbook/content.md +8 -8
- package/templates/skills/pages/content.md +6 -4
- package/templates/skills/swarm-scripts/SKILL.md +2 -2
- package/templates/skills/swarm-scripts/content.md +2 -2
- package/dist/cli-v1sjhn52.js +0 -7
- package/dist/handlers-2qjw434w.js +0 -39
- package/dist/index-d0g18bax.js +0 -41
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"Markdown",
|
|
14
14
|
"SearchInput",
|
|
15
15
|
"Select",
|
|
16
|
+
"NumberInput",
|
|
16
17
|
"Button",
|
|
17
18
|
"Metric",
|
|
18
19
|
"Alert",
|
|
@@ -31,9 +32,11 @@
|
|
|
31
32
|
"Form",
|
|
32
33
|
"Drawer",
|
|
33
34
|
"DetailList",
|
|
35
|
+
"CardGrid",
|
|
34
36
|
"Kanban",
|
|
35
37
|
"Calendar",
|
|
36
38
|
"ContributionGraph",
|
|
39
|
+
"Tree",
|
|
37
40
|
"ElementRef",
|
|
38
41
|
"ElementSlot"
|
|
39
42
|
],
|
|
@@ -48,7 +51,7 @@
|
|
|
48
51
|
],
|
|
49
52
|
"components": {
|
|
50
53
|
"Stack": {
|
|
51
|
-
"description": "THE primary layout primitive — a flex column (default) or row of its children. `gap`/`padding` use the shared spacing scale (none|xs|sm|md|lg|xl, default gap md); `align` is the cross axis, `justify` the main axis, `wrap` lets a row reflow. For rows, set `collapseBelow` (sm|md|lg) so the row stacks vertically on narrow viewports — filter bars should always set it. `motion` (rise|fade|none, default rise) is the entrance of the direct children on first paint: a 200ms fade plus a 4px rise, staggered 30ms; it never replays on data polls, nested Stacks inherit the parent's entrance, and reduced-motion viewers get a short fade. Use this as the page root and for every section; `Container` is the legacy 2-prop alias kept for older pages.",
|
|
54
|
+
"description": "THE primary layout primitive — a flex column (default) or row of its children. `gap`/`padding` use the shared spacing scale (none|xs|sm|md|lg|xl, default gap md); `align` is the cross axis, `justify` the main axis, `wrap` lets a row reflow. For rows, set `collapseBelow` (sm|md|lg) so the row stacks vertically on narrow viewports — filter bars should always set it. `motion` (rise|fade|none, default rise) is the entrance of the direct children on first paint: a 200ms fade plus a 4px rise, staggered 30ms; it never replays on data polls, nested Stacks inherit the parent's entrance, and reduced-motion viewers get a short fade. Use this as the page root and for every section; `Container` is the legacy 2-prop alias kept for older pages. `fill: true` makes this Stack grow to fill the remaining height of a `fill`-aware parent instead of sizing to content — chain it from the page root down to a scrolling leaf to build a viewport-height layout with no page scroll; a non-`fill` sibling keeps its natural height and the `fill` sibling absorbs whatever is left.",
|
|
52
55
|
"slots": ["default"],
|
|
53
56
|
"props": {
|
|
54
57
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
@@ -84,6 +87,9 @@
|
|
|
84
87
|
"motion": {
|
|
85
88
|
"type": "string",
|
|
86
89
|
"enum": ["rise", "fade", "none"]
|
|
90
|
+
},
|
|
91
|
+
"fill": {
|
|
92
|
+
"type": "boolean"
|
|
87
93
|
}
|
|
88
94
|
},
|
|
89
95
|
"additionalProperties": false
|
|
@@ -144,7 +150,7 @@
|
|
|
144
150
|
}
|
|
145
151
|
},
|
|
146
152
|
"Split": {
|
|
147
|
-
"description": "Two-pane layout. POSITIONAL children: the FIRST child is the left pane, the SECOND is the right pane, and any further children stack inside the right pane. `ratio` sizes them (1-1|1-2|2-1|1-3|3-1, default 2-1 = wide left). Below `collapseBelow` (sm|md|lg, default md) the panes stack vertically; `reverse` only flips that stacked order (right pane first on narrow screens).",
|
|
153
|
+
"description": "Two-pane layout. POSITIONAL children: the FIRST child is the left pane, the SECOND is the right pane, and any further children stack inside the right pane. `ratio` sizes them (1-1|1-2|2-1|1-3|3-1, default 2-1 = wide left). Below `collapseBelow` (sm|md|lg, default md) the panes stack vertically; `reverse` only flips that stacked order (right pane first on narrow screens). `fill: true` makes this Split grow to fill the remaining height of a `fill`-aware parent (same contract as `Stack.fill`) — both panes stretch to the full row height, so nesting a `fill` Split inside one pane of another `fill` Split is the standard way to build a 3+ column viewport-height layout (ratio is only ever 2 panes).",
|
|
148
154
|
"slots": ["default"],
|
|
149
155
|
"props": {
|
|
150
156
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
@@ -168,6 +174,9 @@
|
|
|
168
174
|
"padding": {
|
|
169
175
|
"type": "string",
|
|
170
176
|
"enum": ["none", "xs", "sm", "md", "lg", "xl"]
|
|
177
|
+
},
|
|
178
|
+
"fill": {
|
|
179
|
+
"type": "boolean"
|
|
171
180
|
}
|
|
172
181
|
},
|
|
173
182
|
"additionalProperties": false
|
|
@@ -385,7 +394,7 @@
|
|
|
385
394
|
}
|
|
386
395
|
},
|
|
387
396
|
"Select": {
|
|
388
|
-
"description": "Dropdown filter/picker. `options` are plain strings or `{ value, label?, icon?, hint? }` objects. Writes the chosen value into state at `/ui/<id>/value` (clearing writes `null`); bind it into a Table with `\"filters\": { \"<column>\": { \"$state\": \"/ui/<id>/value\" } }`. `clearable` (default true) shows a clear button. `searchable` adds a type-to-filter field (on by default past 8 options; `searchPlaceholder` sets its hint). `multiple` picks several: the value is a string array (empty = nothing picked), which a Table filter reads as \"cell is one of\".",
|
|
397
|
+
"description": "Dropdown filter/picker. `options` are plain strings or `{ value, label?, icon?, hint? }` objects. Writes the chosen value into state at `/ui/<id>/value` (clearing writes `null`); bind it into a Table with `\"filters\": { \"<column>\": { \"$state\": \"/ui/<id>/value\" } }`. `clearable` (default true) shows a clear button. `searchable` adds a type-to-filter field (on by default past 8 options; `searchPlaceholder` sets its hint). `multiple` picks several: the value is a string array (empty = nothing picked), which a Table filter reads as \"cell is one of\". `defaultValue` seeds `/ui/<id>/value` the first time it is read, before any interaction (a one-entry array with `multiple`).",
|
|
389
398
|
"props": {
|
|
390
399
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
391
400
|
"type": "object",
|
|
@@ -482,12 +491,41 @@
|
|
|
482
491
|
},
|
|
483
492
|
"searchPlaceholder": {
|
|
484
493
|
"type": "string"
|
|
494
|
+
},
|
|
495
|
+
"defaultValue": {
|
|
496
|
+
"type": "string"
|
|
485
497
|
}
|
|
486
498
|
},
|
|
487
499
|
"required": ["id", "options"],
|
|
488
500
|
"additionalProperties": false
|
|
489
501
|
}
|
|
490
502
|
},
|
|
503
|
+
"NumberInput": {
|
|
504
|
+
"description": "Labelled numeric text field (decimal keyboard on touch devices, no debounce). Writes the parsed number into state at `/ui/<id>/value` on every change, or `null` when the field is empty; non-numeric text (a bare '-' mid-edit, letters) leaves the stored value untouched until it parses. `min`/`max` clamp the stored value, and the visible text snaps to that clamped value when the field loses focus.",
|
|
505
|
+
"props": {
|
|
506
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
507
|
+
"type": "object",
|
|
508
|
+
"properties": {
|
|
509
|
+
"id": {
|
|
510
|
+
"type": "string"
|
|
511
|
+
},
|
|
512
|
+
"label": {
|
|
513
|
+
"type": "string"
|
|
514
|
+
},
|
|
515
|
+
"placeholder": {
|
|
516
|
+
"type": "string"
|
|
517
|
+
},
|
|
518
|
+
"min": {
|
|
519
|
+
"type": "number"
|
|
520
|
+
},
|
|
521
|
+
"max": {
|
|
522
|
+
"type": "number"
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
"required": ["id"],
|
|
526
|
+
"additionalProperties": false
|
|
527
|
+
}
|
|
528
|
+
},
|
|
491
529
|
"Button": {
|
|
492
530
|
"description": "Interactive button. Wire to actions via `on.press`. `variant: \"destructive-outline\"` is the canonical red-outlined destructive look (standalone deletes should use it, not solid red). `disabled` accepts a constant or a bound boolean; `busyWith: \"<actionName>\"` swaps the label for a spinner (presses ignored) while that custom action is running, then shows a check plus `successLabel` for ~1.5s when it finishes ok. `icon` + `iconPosition` (start|end) add an icon from the curated set; `size` sm|default|lg. `shortcut` (one key, e.g. `\"n\"`) shows a keycap inside the button and presses it from anywhere on the page (not while typing in a field, not with Ctrl/Cmd/Alt). `hint` is a hover tooltip.",
|
|
493
531
|
"props": {
|
|
@@ -1243,7 +1281,7 @@
|
|
|
1243
1281
|
}
|
|
1244
1282
|
},
|
|
1245
1283
|
"Table": {
|
|
1246
|
-
"description": "Data table. Bind `data`/`loading`/`error` to a named query (`/queries/<name>/...`). `rowActions` chains receive `{ \"$row\": \"<col>\" }` (or `{ \"$row\": \"\" }` for the whole row) and `{ \"$rowIndex\": true }`. Destructive row actions always confirm via a dialog; override the copy with `confirm: { title, description, confirmLabel }`. `search` (case-insensitive substring across every listed column) and `filters` (per-column equality, `null`/`\"\"` disables one; an array means \"one of\", which is what a multiple `Chips` writes, and an empty array disables it) narrow the polled rows client-side — bind them to a `SearchInput` / `Select` via `/ui/<id>/value`, or pin a constant (e.g. `\"filters\": { \"pinned\": true }`). Columns take `pinned: \"left\"|\"right\"` to survive horizontal scroll; `pagination` pages large row sets (auto past 200 rows); `density: \"compact\"` tightens row height. Column kinds: `status` (lifecycle values like pending/in_progress/completed/failed get the dashboard status icon, anything else a `tones` pill), `user` / `agent` (avatar + name), `relative` (smart time with the exact time on hover), `duration` (ms → 1m 23s), `progress` (bar, `max` default 100), `copy` (value + copy button), `switch` (runs the column's `onChange` chain with `$row` set to the new value; read-only without it), `link` (http(s) URL, opens in a new tab), `json` (compact single-line `JSON.stringify` preview, truncated). Columns also take `align`, `truncate: \"middle\"` (ids, paths), a header `icon` and `tooltip` (a row field shown on hover). `onRowClick` runs a chain with `$row` when a row is clicked — pair it with `app.navigate` + a Drawer and bind `selectedId` to the drawer param to highlight the open row. `rowId` names the id field (default `id`). Below 768px the table renders as a phone list (`mobile: \"list\"`, fields picked by `mobileFields: { title, subtitle?, meta?, status? }`); `mobile: \"scroll\"` keeps the grid. `emptyState: { icon?, title, body? }` replaces the empty message. Row actions take `icon` and `placement: \"menu\"` (collected into a More menu).",
|
|
1284
|
+
"description": "Data table. Bind `data`/`loading`/`error` to a named query (`/queries/<name>/...`). `rowActions` chains receive `{ \"$row\": \"<col>\" }` (or `{ \"$row\": \"\" }` for the whole row) and `{ \"$rowIndex\": true }`. Destructive row actions always confirm via a dialog; override the copy with `confirm: { title, description, confirmLabel }`. `search` (case-insensitive substring across every listed column) and `filters` (per-column equality, `null`/`\"\"` disables one; an array means \"one of\", which is what a multiple `Chips` writes, and an empty array disables it) narrow the polled rows client-side — bind them to a `SearchInput` / `Select` via `/ui/<id>/value`, or pin a constant (e.g. `\"filters\": { \"pinned\": true }`). Columns take `pinned: \"left\"|\"right\"` to survive horizontal scroll; `pagination` pages large row sets (auto past 200 rows); `density: \"compact\"` tightens row height. Column kinds: `status` (lifecycle values like pending/in_progress/completed/failed get the dashboard status icon, anything else a `tones` pill), `user` / `agent` (avatar + name), `relative` (smart time with the exact time on hover), `duration` (ms → 1m 23s), `progress` (bar, `max` default 100), `copy` (value + copy button), `switch` (runs the column's `onChange` chain with `$row` set to the new value; read-only without it), `link` (http(s) URL, opens in a new tab), `json` (compact single-line `JSON.stringify` preview, truncated). Columns also take `align`, `truncate: \"middle\"` (ids, paths), a header `icon` and `tooltip` (a row field shown on hover), and `format` — a `{{field}}` template (e.g. `\"{{name}} · v{{version}}\"`) that combines several row fields into one cell and overrides `key`/`kind` rendering on desktop and in the phone list (placeholder names match `[w.]+`, no hyphens or spaces; sorting uses the composed text; `search` and `filters` still read the column's `key`). `onRowClick` runs a chain with `$row` when a row is clicked — pair it with `app.navigate` + a Drawer and bind `selectedId` to the drawer param to highlight the open row. `rowId` names the id field (default `id`). Below 768px the table renders as a phone list (`mobile: \"list\"`, fields picked by `mobileFields: { title, subtitle?, meta?, status? }`); `mobile: \"scroll\"` keeps the grid. `emptyState: { icon?, title, body? }` replaces the empty message. Row actions take `icon` and `placement: \"menu\"` (collected into a More menu).",
|
|
1247
1285
|
"props": {
|
|
1248
1286
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
1249
1287
|
"type": "object",
|
|
@@ -1317,6 +1355,9 @@
|
|
|
1317
1355
|
"type": "string",
|
|
1318
1356
|
"enum": ["left", "right"]
|
|
1319
1357
|
},
|
|
1358
|
+
"format": {
|
|
1359
|
+
"type": "string"
|
|
1360
|
+
},
|
|
1320
1361
|
"align": {
|
|
1321
1362
|
"type": "string",
|
|
1322
1363
|
"enum": ["start", "end"]
|
|
@@ -2037,6 +2078,140 @@
|
|
|
2037
2078
|
"additionalProperties": false
|
|
2038
2079
|
}
|
|
2039
2080
|
},
|
|
2081
|
+
"CardGrid": {
|
|
2082
|
+
"description": "Responsive grid of data-bound cards, one per row — the visual counterpart to `Table` for record browsers (projects, documents, media). Bind `data`/`loading`/`error` to a named query like Table. `titleKey` picks the row field shown as the card title. `imageKey` picks a row field holding an absolute http(s) image URL and adds an image tile to every card (a non-URL value or a failed load shows a placeholder); omit it for text-only cards. `fields` render as an unlabeled `·`-joined meta line under the title; each field's `kind` is one of `text`, `string`, `enum`, `number`, `boolean`, `date`, `badge` (with `tones`) or `json`. `onClick` is an action chain (params may use `$row` / `$rowIndex`) dispatched on card click or Enter/Space, commonly `app.navigate` into a detail page. `columns` is the same responsive shorthand as `Grid.columns` (default `{ base: 1, sm: 2, md: 3 }`). Renders 200 cards at a time with a Show more button.",
|
|
2083
|
+
"props": {
|
|
2084
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
2085
|
+
"type": "object",
|
|
2086
|
+
"properties": {
|
|
2087
|
+
"data": {
|
|
2088
|
+
"type": "array",
|
|
2089
|
+
"items": {
|
|
2090
|
+
"type": "object",
|
|
2091
|
+
"propertyNames": {
|
|
2092
|
+
"type": "string"
|
|
2093
|
+
},
|
|
2094
|
+
"additionalProperties": {}
|
|
2095
|
+
}
|
|
2096
|
+
},
|
|
2097
|
+
"titleKey": {
|
|
2098
|
+
"type": "string"
|
|
2099
|
+
},
|
|
2100
|
+
"imageKey": {
|
|
2101
|
+
"type": "string"
|
|
2102
|
+
},
|
|
2103
|
+
"fields": {
|
|
2104
|
+
"type": "array",
|
|
2105
|
+
"items": {
|
|
2106
|
+
"type": "object",
|
|
2107
|
+
"properties": {
|
|
2108
|
+
"key": {
|
|
2109
|
+
"type": "string"
|
|
2110
|
+
},
|
|
2111
|
+
"kind": {
|
|
2112
|
+
"type": "string",
|
|
2113
|
+
"enum": ["text", "string", "number", "boolean", "date", "badge", "enum", "json"]
|
|
2114
|
+
},
|
|
2115
|
+
"tones": {
|
|
2116
|
+
"type": "object",
|
|
2117
|
+
"propertyNames": {
|
|
2118
|
+
"type": "string"
|
|
2119
|
+
},
|
|
2120
|
+
"additionalProperties": {
|
|
2121
|
+
"type": "string",
|
|
2122
|
+
"enum": [
|
|
2123
|
+
"neutral",
|
|
2124
|
+
"success",
|
|
2125
|
+
"active",
|
|
2126
|
+
"error",
|
|
2127
|
+
"info",
|
|
2128
|
+
"pending",
|
|
2129
|
+
"warning",
|
|
2130
|
+
"paused"
|
|
2131
|
+
]
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
},
|
|
2135
|
+
"required": ["key"],
|
|
2136
|
+
"additionalProperties": false
|
|
2137
|
+
}
|
|
2138
|
+
},
|
|
2139
|
+
"columns": {
|
|
2140
|
+
"anyOf": [
|
|
2141
|
+
{
|
|
2142
|
+
"type": "integer",
|
|
2143
|
+
"minimum": 1,
|
|
2144
|
+
"maximum": 6
|
|
2145
|
+
},
|
|
2146
|
+
{
|
|
2147
|
+
"type": "object",
|
|
2148
|
+
"properties": {
|
|
2149
|
+
"base": {
|
|
2150
|
+
"type": "integer",
|
|
2151
|
+
"minimum": 1,
|
|
2152
|
+
"maximum": 6
|
|
2153
|
+
},
|
|
2154
|
+
"sm": {
|
|
2155
|
+
"type": "integer",
|
|
2156
|
+
"minimum": 1,
|
|
2157
|
+
"maximum": 6
|
|
2158
|
+
},
|
|
2159
|
+
"md": {
|
|
2160
|
+
"type": "integer",
|
|
2161
|
+
"minimum": 1,
|
|
2162
|
+
"maximum": 6
|
|
2163
|
+
},
|
|
2164
|
+
"lg": {
|
|
2165
|
+
"type": "integer",
|
|
2166
|
+
"minimum": 1,
|
|
2167
|
+
"maximum": 6
|
|
2168
|
+
}
|
|
2169
|
+
},
|
|
2170
|
+
"additionalProperties": false
|
|
2171
|
+
}
|
|
2172
|
+
]
|
|
2173
|
+
},
|
|
2174
|
+
"onClick": {
|
|
2175
|
+
"type": "array",
|
|
2176
|
+
"items": {
|
|
2177
|
+
"type": "object",
|
|
2178
|
+
"properties": {
|
|
2179
|
+
"action": {
|
|
2180
|
+
"type": "string"
|
|
2181
|
+
},
|
|
2182
|
+
"params": {
|
|
2183
|
+
"type": "object",
|
|
2184
|
+
"propertyNames": {
|
|
2185
|
+
"type": "string"
|
|
2186
|
+
},
|
|
2187
|
+
"additionalProperties": {}
|
|
2188
|
+
}
|
|
2189
|
+
},
|
|
2190
|
+
"required": ["action"],
|
|
2191
|
+
"additionalProperties": false
|
|
2192
|
+
}
|
|
2193
|
+
},
|
|
2194
|
+
"loading": {
|
|
2195
|
+
"type": "boolean"
|
|
2196
|
+
},
|
|
2197
|
+
"error": {
|
|
2198
|
+
"anyOf": [
|
|
2199
|
+
{
|
|
2200
|
+
"type": "string"
|
|
2201
|
+
},
|
|
2202
|
+
{
|
|
2203
|
+
"type": "null"
|
|
2204
|
+
}
|
|
2205
|
+
]
|
|
2206
|
+
},
|
|
2207
|
+
"emptyMessage": {
|
|
2208
|
+
"type": "string"
|
|
2209
|
+
}
|
|
2210
|
+
},
|
|
2211
|
+
"required": ["titleKey"],
|
|
2212
|
+
"additionalProperties": false
|
|
2213
|
+
}
|
|
2214
|
+
},
|
|
2040
2215
|
"Kanban": {
|
|
2041
2216
|
"description": "Kanban board: one card per row, grouped into `columns` by the row's `columnField`. Bind `data`/`loading` to a named query. `titleField` is the card title; `cardFields` add label/value lines with the DetailList field kinds (badge tones, status, user, relative, copy, ...). Dragging a card to another column runs `onMove` with `$row` = the moved row, `columnField` already set to the new column — typically `[{ \"action\": \"app.mutate\", \"params\": { \"model\": \"<m>\", \"op\": \"update\", \"rowId\": { \"$row\": \"id\" }, \"values\": { \"<columnField>\": { \"$row\": \"<columnField>\" } } } }]`. Without `onMove` the board is read-only. `onCardClick` runs with `$row` (e.g. an `app.navigate` that opens a Drawer).",
|
|
2042
2217
|
"props": {
|
|
@@ -2277,6 +2452,33 @@
|
|
|
2277
2452
|
"additionalProperties": false
|
|
2278
2453
|
}
|
|
2279
2454
|
},
|
|
2455
|
+
"Tree": {
|
|
2456
|
+
"description": "Collapsible tree view of a json-render flat element map. Bind `nodes` to a doc-shaped value (`{ root: string | string[], elements: Record<key,{type,children?}> }`) — usually `{ \"$state\": \"/queries/<name>/data/0/<jsonColumn>\" }`. Each row shows `key — type`; clicking one writes the node key to `/ui/<id>/value`, and the row bound to that path renders selected. A malformed or absent `nodes` value renders an empty state. Rows scroll inside a fixed-height viewport — `maxHeight` overrides the default `480px` — or set `fill: true` to grow inside a `fill`-aware parent and scroll within whatever height that gives it instead (ignores `maxHeight`). Outlines are cut at 2,000 rows with a notice; branches deeper than 32 levels keep a disabled chevron.",
|
|
2457
|
+
"props": {
|
|
2458
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
2459
|
+
"type": "object",
|
|
2460
|
+
"properties": {
|
|
2461
|
+
"id": {
|
|
2462
|
+
"type": "string"
|
|
2463
|
+
},
|
|
2464
|
+
"nodes": {
|
|
2465
|
+
"description": "json-render flat element map: { root: string | string[], elements: Record<key,{type,children?}> } — usually a {$state} binding to a query row's json column"
|
|
2466
|
+
},
|
|
2467
|
+
"label": {
|
|
2468
|
+
"type": "string"
|
|
2469
|
+
},
|
|
2470
|
+
"maxHeight": {
|
|
2471
|
+
"description": "CSS max-height for the scrollable row list, e.g. '480px' (default '480px')",
|
|
2472
|
+
"type": "string"
|
|
2473
|
+
},
|
|
2474
|
+
"fill": {
|
|
2475
|
+
"type": "boolean"
|
|
2476
|
+
}
|
|
2477
|
+
},
|
|
2478
|
+
"required": ["id", "nodes"],
|
|
2479
|
+
"additionalProperties": false
|
|
2480
|
+
}
|
|
2481
|
+
},
|
|
2280
2482
|
"ElementRef": {
|
|
2281
2483
|
"description": "Reference a reusable element from this app or an exported element from another app. Consumer children are inserted at the target's ElementSlot.",
|
|
2282
2484
|
"slots": ["default"],
|
|
@@ -2507,6 +2709,9 @@
|
|
|
2507
2709
|
"type": "string"
|
|
2508
2710
|
},
|
|
2509
2711
|
"additionalProperties": {}
|
|
2712
|
+
},
|
|
2713
|
+
"parentTaskId": {
|
|
2714
|
+
"type": "string"
|
|
2510
2715
|
}
|
|
2511
2716
|
},
|
|
2512
2717
|
"required": ["name"],
|
|
@@ -14,6 +14,9 @@ interface JsonSchema {
|
|
|
14
14
|
const?: unknown;
|
|
15
15
|
items?: JsonSchema;
|
|
16
16
|
anyOf?: JsonSchema[];
|
|
17
|
+
// A bare `z.unknown()` prop (e.g. Tree.nodes) serializes to a schema carrying
|
|
18
|
+
// only `description` and no `type` — a valid, type-less JSON Schema.
|
|
19
|
+
description?: string;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export interface AppCatalog {
|
|
@@ -42,7 +45,15 @@ export const ELEMENT_KEYS = new Set([
|
|
|
42
45
|
"repeat",
|
|
43
46
|
"watch",
|
|
44
47
|
]);
|
|
45
|
-
|
|
48
|
+
// Components whose `id` claims a `/ui/<id>/...` state slot.
|
|
49
|
+
const UI_STATE_COMPONENTS = new Set([
|
|
50
|
+
"SearchInput",
|
|
51
|
+
"Select",
|
|
52
|
+
"NumberInput",
|
|
53
|
+
"Tabs",
|
|
54
|
+
"Chips",
|
|
55
|
+
"Tree",
|
|
56
|
+
]);
|
|
46
57
|
|
|
47
58
|
/**
|
|
48
59
|
* Props that hold a plain action chain (an array of `{ action, params }`),
|
|
@@ -54,6 +65,7 @@ const PROP_ACTION_CHAINS: Record<string, readonly string[]> = {
|
|
|
54
65
|
Form: ["onSubmit"],
|
|
55
66
|
Kanban: ["onMove", "onCardClick"],
|
|
56
67
|
Calendar: ["onSelect"],
|
|
68
|
+
CardGrid: ["onClick"],
|
|
57
69
|
};
|
|
58
70
|
|
|
59
71
|
/**
|
|
@@ -149,7 +161,10 @@ function isActionSentinel(value: unknown): boolean {
|
|
|
149
161
|
if (!isPlainObject(value) || Object.keys(value).length !== 1) return false;
|
|
150
162
|
if (typeof value.$row === "string") return true;
|
|
151
163
|
if (value.$rowIndex === true) return true;
|
|
152
|
-
|
|
164
|
+
if (typeof value.$form === "string") return true;
|
|
165
|
+
// Chain-derived scope published by a component that runs a task chain —
|
|
166
|
+
// see `action-params.ts`'s `$chain` sentinel.
|
|
167
|
+
return typeof value.$chain === "string";
|
|
153
168
|
}
|
|
154
169
|
|
|
155
170
|
function appendPath(path: string, part: string | number): string {
|
|
@@ -220,7 +235,10 @@ function validateSchema(
|
|
|
220
235
|
? { issues: [], stateRefs: [] }
|
|
221
236
|
: {
|
|
222
237
|
issues: [
|
|
223
|
-
issue(
|
|
238
|
+
issue(
|
|
239
|
+
path,
|
|
240
|
+
"$row, $rowIndex, $form, and $chain bindings are only allowed in action params",
|
|
241
|
+
),
|
|
224
242
|
],
|
|
225
243
|
stateRefs: [],
|
|
226
244
|
};
|
package/src/be/chunking.ts
CHANGED
|
@@ -42,20 +42,53 @@ export function chunkContent(text: string): MemoryChunk[] {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return filtered.map((c, i) => ({
|
|
52
|
-
content: c.headings.length > 0 ? `${c.headings.join(" > ")}\n\n${c.content}` : c.content,
|
|
45
|
+
const packed = packSmallSections(rawChunks);
|
|
46
|
+
return packed.map((c, i) => ({
|
|
47
|
+
content: c.content,
|
|
53
48
|
chunkIndex: i,
|
|
54
|
-
totalChunks:
|
|
49
|
+
totalChunks: packed.length,
|
|
55
50
|
headings: c.headings,
|
|
56
51
|
}));
|
|
57
52
|
}
|
|
58
53
|
|
|
54
|
+
function renderSection(section: Section): string {
|
|
55
|
+
return section.headings.length > 0
|
|
56
|
+
? `${section.headings.join(" > ")}\n\n${section.content}`
|
|
57
|
+
: section.content;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Render each section with its heading path. A section below MIN_CHUNK_SIZE
|
|
62
|
+
* is too small to embed on its own, so consecutive small sections share a
|
|
63
|
+
* chunk up to MAX_CHUNK_SIZE. No section content is dropped.
|
|
64
|
+
*/
|
|
65
|
+
function packSmallSections(sections: Section[]): Section[] {
|
|
66
|
+
const out: Section[] = [];
|
|
67
|
+
let pending: { parts: string[]; length: number; headings: string[] } | null = null;
|
|
68
|
+
const flush = () => {
|
|
69
|
+
if (pending) out.push({ content: pending.parts.join("\n\n"), headings: pending.headings });
|
|
70
|
+
pending = null;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
for (const section of sections) {
|
|
74
|
+
const rendered = renderSection(section);
|
|
75
|
+
if (section.content.trim().length >= MIN_CHUNK_SIZE) {
|
|
76
|
+
flush();
|
|
77
|
+
out.push({ content: rendered, headings: section.headings });
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (pending && pending.length + 2 + rendered.length > MAX_CHUNK_SIZE) flush();
|
|
81
|
+
if (pending) {
|
|
82
|
+
pending.parts.push(rendered);
|
|
83
|
+
pending.length += 2 + rendered.length;
|
|
84
|
+
} else {
|
|
85
|
+
pending = { parts: [rendered], length: rendered.length, headings: section.headings };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
flush();
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
|
|
59
92
|
interface Section {
|
|
60
93
|
content: string;
|
|
61
94
|
headings: string[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getDbClient } from "../runtime";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Append a block to a draft's task text (an uploaded voice note's transcript),
|
|
5
|
+
* as its own paragraph. Only a draft: nobody has read its text yet. One
|
|
6
|
+
* statement, so parallel uploads never drop each other's block. Returns
|
|
7
|
+
* whether the task was still a draft.
|
|
8
|
+
*/
|
|
9
|
+
export async function appendDraftTaskText(taskId: string, block: string): Promise<boolean> {
|
|
10
|
+
const result = await getDbClient().run(
|
|
11
|
+
"UPDATE agent_tasks SET task = task || ?, lastUpdatedAt = ? WHERE id = ? AND status = 'draft'",
|
|
12
|
+
[`\n\n${block}`, new Date().toISOString(), taskId],
|
|
13
|
+
);
|
|
14
|
+
return result.changes > 0;
|
|
15
|
+
}
|
package/src/be/db/tasks/read.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
parseModelTier,
|
|
19
19
|
ReasoningEffortSchema,
|
|
20
20
|
RoutingAffinitySchema,
|
|
21
|
+
TERMINAL_TASK_STATUSES,
|
|
21
22
|
} from "../../../types";
|
|
22
23
|
import { parseProviderMeta } from "../../../utils/provider-metadata";
|
|
23
24
|
import { scrubSecrets } from "../../../utils/secret-scrubber";
|
|
@@ -1688,14 +1689,26 @@ export async function getLatestLeadTaskInThread(
|
|
|
1688
1689
|
export async function getAgentWorkingOnContextKey(
|
|
1689
1690
|
contextKey: string,
|
|
1690
1691
|
source?: string,
|
|
1692
|
+
/** ISO time: when set, only tasks still open or finished at or after it count. */
|
|
1693
|
+
endedSince?: string,
|
|
1691
1694
|
): Promise<Agent | null> {
|
|
1692
1695
|
const taskRow = await getDbClient().get<AgentTaskRow>(
|
|
1693
1696
|
`SELECT agentId FROM agent_tasks
|
|
1694
1697
|
WHERE contextKey = ?
|
|
1695
1698
|
AND (? IS NULL OR source = ?)
|
|
1699
|
+
AND (? IS NULL
|
|
1700
|
+
OR status NOT IN (${TERMINAL_TASK_STATUSES.map(() => "?").join(", ")})
|
|
1701
|
+
OR finishedAt >= ?)
|
|
1696
1702
|
ORDER BY createdAt DESC, rowid DESC
|
|
1697
1703
|
LIMIT 1`,
|
|
1698
|
-
[
|
|
1704
|
+
[
|
|
1705
|
+
contextKey,
|
|
1706
|
+
source ?? null,
|
|
1707
|
+
source ?? null,
|
|
1708
|
+
endedSince ?? null,
|
|
1709
|
+
...TERMINAL_TASK_STATUSES,
|
|
1710
|
+
endedSince ?? null,
|
|
1711
|
+
],
|
|
1699
1712
|
);
|
|
1700
1713
|
|
|
1701
1714
|
if (taskRow?.agentId) return getAgentById(taskRow.agentId);
|
package/src/be/db.ts
CHANGED
|
@@ -2676,7 +2676,11 @@ export async function createTaskExtended(
|
|
|
2676
2676
|
}
|
|
2677
2677
|
|
|
2678
2678
|
// Attribution
|
|
2679
|
-
if (
|
|
2679
|
+
if (
|
|
2680
|
+
parent.requestedByUserId &&
|
|
2681
|
+
!options.requestedByUserId &&
|
|
2682
|
+
options.inheritParentRequester !== false
|
|
2683
|
+
) {
|
|
2680
2684
|
options.requestedByUserId = parent.requestedByUserId;
|
|
2681
2685
|
requestedByUserIdInherited = true;
|
|
2682
2686
|
}
|
|
@@ -37,6 +37,12 @@ export interface IndexMemoryContentParams {
|
|
|
37
37
|
* out, the writer has no authority. Throws `MemoryKeyError`.
|
|
38
38
|
*/
|
|
39
39
|
writer?: MemoryKeyWriter;
|
|
40
|
+
/**
|
|
41
|
+
* With `key`: replace this owner's existing document under the key (same
|
|
42
|
+
* scope and source) in the same transaction as the insert, instead of
|
|
43
|
+
* failing on the unique key index. A re-write may change the chunk count.
|
|
44
|
+
*/
|
|
45
|
+
replaceExisting?: boolean;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
export interface IndexMemoryContentResult {
|
|
@@ -48,6 +54,14 @@ export interface IndexMemoryContentResult {
|
|
|
48
54
|
chunks: number;
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Key shared by every chunk of one task's completion memory, so the chunks
|
|
59
|
+
* group as one document (access counting, chunk listing, search collapse).
|
|
60
|
+
*/
|
|
61
|
+
export function taskCompletionMemoryKey(taskId: string): string {
|
|
62
|
+
return `/task-completions/${taskId.toLowerCase().replace(/[^a-z0-9._-]/g, "-")}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
export async function indexMemoryContent(
|
|
52
66
|
params: IndexMemoryContentParams,
|
|
53
67
|
): Promise<IndexMemoryContentResult> {
|
|
@@ -111,23 +125,28 @@ export async function indexMemoryContent(
|
|
|
111
125
|
}
|
|
112
126
|
|
|
113
127
|
// Atomic batch insert: all chunks or none
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
const inputs = contentChunks.map((chunk) => ({
|
|
129
|
+
agentId: agentId || null,
|
|
130
|
+
content: chunk.content,
|
|
131
|
+
name,
|
|
132
|
+
scope,
|
|
133
|
+
source,
|
|
134
|
+
sourcePath: sourcePath || null,
|
|
135
|
+
sourceTaskId: sourceTaskId || null,
|
|
136
|
+
chunkIndex: chunk.chunkIndex,
|
|
137
|
+
totalChunks: chunk.totalChunks,
|
|
138
|
+
tags: tags || [],
|
|
139
|
+
contextKey: params.contextKey ?? null,
|
|
140
|
+
intent: params.intent ?? "index memory content",
|
|
141
|
+
key: rowKey,
|
|
142
|
+
}));
|
|
143
|
+
const memories =
|
|
144
|
+
params.replaceExisting && params.key
|
|
145
|
+
? await store.replaceDocument(
|
|
146
|
+
{ key: params.key, scope, agentId: agentId || null, source },
|
|
147
|
+
inputs,
|
|
148
|
+
)
|
|
149
|
+
: await store.storeBatch(inputs);
|
|
131
150
|
|
|
132
151
|
// Resolve and store deterministic links (wikilinks, PR refs, agent-fs paths)
|
|
133
152
|
if (agentId) {
|