@inneranimalmedia/agentsam-sdk 2.6.10 → 2.6.11

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 (261) hide show
  1. package/README.md +3 -0
  2. package/TRADEMARKS.md +22 -0
  3. package/apps/README.md +3 -0
  4. package/apps/cad-creator/LICENSE +21 -0
  5. package/apps/cad-creator/README.md +4 -1
  6. package/apps/cad-creator/shared/cad/package.json +1 -1
  7. package/apps/client-cms-editor/LICENSE +21 -0
  8. package/apps/client-cms-editor/README.md +3 -0
  9. package/apps/client-cms-editor/backend/package.json +2 -2
  10. package/apps/client-cms-editor/frontend/package.json +3 -3
  11. package/apps/client-cms-editor/package-lock.json +43 -43
  12. package/apps/client-cms-editor/package.json +3 -3
  13. package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +1 -1
  14. package/apps/client-cms-editor/reference/harvest/README.md +1 -1
  15. package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +1 -1
  16. package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +1 -1
  17. package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +1 -1
  18. package/apps/client-cms-editor/shared/cms/package.json +1 -1
  19. package/docs/MINI.md +4 -2
  20. package/docs/REPO_FILE_MAP.txt +0 -1
  21. package/docs/SOURCE_ARCHITECTURE.md +1 -1
  22. package/docs/architecture/DUAL_ANALYTICS_PRODUCT.md +140 -0
  23. package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
  24. package/docs/engineering/go-portability/01-product-project-deployment-authority.md +69 -0
  25. package/docs/engineering/provider-internal-renames/01-lane-initialization.md +20 -0
  26. package/docs/engineering/provider-internal-renames/01a-runtime-environment-contract.md +115 -0
  27. package/docs/engineering/provider-internal-renames/02-cfoa.md +57 -0
  28. package/docs/engineering/provider-internal-renames/03-gclioa.md +32 -0
  29. package/docs/engineering/provider-internal-renames/04-goaude.md +50 -0
  30. package/docs/engineering/provider-internal-renames/05-gdrv.md +33 -0
  31. package/docs/engineering/provider-internal-renames/06-verification.md +103 -0
  32. package/docs/engineering/provider-internal-renames/README.md +77 -0
  33. package/docs/engineering/provider-internal-renames/runtime-environment-contract.json +220 -0
  34. package/docs/engineering/test-diagnostics/go-cli-test-hang-20261003.md +49 -0
  35. package/docs/engineering/test-diagnostics/go-skip-deploy-docker-fix.md +90 -0
  36. package/docs/knowledge-service-verification.md +3 -3
  37. package/docs/plans/AGENTSAM-SUSPEND-QUEUE-KNOWLEDGE-RDP-2026-10-03.md +870 -0
  38. package/docs/plans/LOCAL-STUDIO-GRADUATION-2026-09-26.md +9 -9
  39. package/docs/plans/MACHINE-FIRST-APPS-TUI-2026-09-24.md +11 -11
  40. package/docs/plans/RECONCILIATION-2026-09-19.md +6 -6
  41. package/docs/plans/SAM_WORK_PROTOCOL.md +667 -0
  42. package/docs/plans/TOMORROW-EXTENSIVE-TODO-2026-09-26.md +2 -2
  43. package/docs/plans/UNIVERSAL-INGEST-MACHINE-FIRST-2026-09-24.md +3 -3
  44. package/examples/hyperspace-demo/src/main.tsx +227 -110
  45. package/migrations/d1/0020_agentsam_receipt_catalog.sql +35 -0
  46. package/migrations/runtime/0006_agent_run_suspend_activity.sql +53 -0
  47. package/migrations/runtime/0007_queue_control.sql +40 -0
  48. package/migrations/runtime/0008_agent_run_dependencies.sql +24 -0
  49. package/migrations/runtime/0008_analytics_legacy_bootstrap.sql +43 -0
  50. package/migrations/runtime/0009_analytics_authority.sql +108 -0
  51. package/package.json +26 -11
  52. package/packages/agentsam-brand/README.md +3 -0
  53. package/packages/agentsam-brand/package.json +2 -2
  54. package/packages/agentsam-contracts/dist/adapter.d.ts +22 -0
  55. package/packages/agentsam-contracts/dist/adapter.js +0 -0
  56. package/packages/agentsam-contracts/dist/agent.d.ts +66 -0
  57. package/packages/agentsam-contracts/dist/agent.js +15 -0
  58. package/packages/agentsam-contracts/dist/artifacts.d.ts +70 -0
  59. package/packages/agentsam-contracts/dist/artifacts.js +0 -0
  60. package/packages/agentsam-contracts/dist/authority.d.ts +21 -0
  61. package/packages/agentsam-contracts/dist/authority.js +0 -0
  62. package/packages/agentsam-contracts/dist/context.d.ts +14 -0
  63. package/packages/agentsam-contracts/dist/context.js +0 -0
  64. package/packages/agentsam-contracts/dist/errors.d.ts +121 -0
  65. package/packages/agentsam-contracts/dist/errors.js +5 -0
  66. package/packages/agentsam-contracts/dist/events.d.ts +53 -0
  67. package/packages/agentsam-contracts/dist/events.js +0 -0
  68. package/packages/agentsam-contracts/dist/execution.d.ts +38 -0
  69. package/packages/agentsam-contracts/dist/execution.js +0 -0
  70. package/packages/agentsam-contracts/dist/hooks.d.ts +31 -0
  71. package/packages/agentsam-contracts/dist/hooks.js +0 -0
  72. package/packages/agentsam-contracts/dist/identity.d.ts +15 -0
  73. package/packages/agentsam-contracts/dist/identity.js +0 -0
  74. package/packages/agentsam-contracts/dist/index.d.ts +16 -0
  75. package/packages/agentsam-contracts/dist/index.js +164 -0
  76. package/packages/agentsam-contracts/dist/models.d.ts +9 -0
  77. package/packages/agentsam-contracts/dist/models.js +0 -0
  78. package/packages/agentsam-contracts/dist/providers.d.ts +27 -0
  79. package/packages/agentsam-contracts/dist/providers.js +0 -0
  80. package/packages/agentsam-contracts/dist/repository.d.ts +56 -0
  81. package/packages/agentsam-contracts/dist/repository.js +15 -0
  82. package/packages/agentsam-contracts/dist/run.d.ts +113 -0
  83. package/packages/agentsam-contracts/dist/run.js +132 -0
  84. package/packages/agentsam-contracts/dist/tools.d.ts +82 -0
  85. package/packages/agentsam-contracts/dist/tools.js +0 -0
  86. package/packages/agentsam-contracts/dist/widgets.d.ts +38 -0
  87. package/packages/agentsam-contracts/dist/widgets.js +0 -0
  88. package/packages/agentsam-contracts/package.json +9 -1
  89. package/packages/agentsam-contracts/scripts/build.mjs +1 -1
  90. package/packages/agentsam-contracts/src/agent.ts +78 -3
  91. package/packages/agentsam-contracts/src/index.ts +2 -0
  92. package/packages/agentsam-contracts/src/run.ts +320 -0
  93. package/packages/agentsam-contracts/src/widgets.ts +58 -0
  94. package/packages/agentsam-contracts/test/contracts.test.mjs +1 -1
  95. package/packages/agentsam-contracts/test/run-contract.test.mjs +94 -0
  96. package/packages/agentsam-errors/package.json +1 -1
  97. package/packages/agentsam-goap/README.md +3 -0
  98. package/packages/agentsam-goap/package.json +2 -2
  99. package/packages/agentsam-hooks/package.json +2 -2
  100. package/packages/agentsam-hooks/src/adapters/agents.js +48 -22
  101. package/packages/agentsam-hooks/src/index.d.ts +16 -0
  102. package/packages/agentsam-knowledge/package.json +1 -1
  103. package/packages/agentsam-knowledge/src/backends/index.js +1 -1
  104. package/packages/agentsam-merch/README.md +62 -0
  105. package/packages/agentsam-merch/bin/agentsam-merch.mjs +16 -0
  106. package/packages/agentsam-merch/package.json +65 -0
  107. package/packages/agentsam-merch/profiles/completeful/dtg-back-large.json +42 -0
  108. package/packages/agentsam-merch/profiles/completeful/laser-engraving.json +39 -0
  109. package/packages/agentsam-merch/profiles/generic/embroidery-digitization.json +22 -0
  110. package/packages/agentsam-merch/schemas/collection-candidate.schema.json +66 -0
  111. package/packages/agentsam-merch/schemas/manufacturing-profile.schema.json +221 -0
  112. package/packages/agentsam-merch/src/adapters-completeful.js +50 -0
  113. package/packages/agentsam-merch/src/cli.js +93 -0
  114. package/packages/agentsam-merch/src/collection-lab.js +60 -0
  115. package/packages/agentsam-merch/src/compatibility.js +501 -0
  116. package/packages/agentsam-merch/src/derivatives.js +112 -0
  117. package/packages/agentsam-merch/src/index.d.ts +316 -0
  118. package/packages/agentsam-merch/src/index.js +46 -0
  119. package/packages/agentsam-merch/src/node/index.d.ts +58 -0
  120. package/packages/agentsam-merch/src/node/index.js +6 -0
  121. package/packages/agentsam-merch/src/node/raster.js +142 -0
  122. package/packages/agentsam-merch/src/node/vector.js +239 -0
  123. package/packages/agentsam-merch/src/product-concepts.js +118 -0
  124. package/packages/agentsam-merch/src/profile-registry.js +104 -0
  125. package/packages/agentsam-merch/src/profile.js +158 -0
  126. package/packages/agentsam-merch/src/transforms.js +215 -0
  127. package/packages/agentsam-merch/test/merch.test.mjs +332 -0
  128. package/packages/agentsam-merch/test/node-transforms.test.mjs +149 -0
  129. package/packages/agentsam-nav/dist/browser.global.js +71 -34
  130. package/packages/agentsam-nav/dist/browser.js +3179 -781
  131. package/packages/agentsam-nav/dist/index.js +3171 -773
  132. package/packages/agentsam-nav/package.json +1 -1
  133. package/packages/agentsam-queue-control/README.md +4 -1
  134. package/packages/agentsam-queue-control/package.json +4 -3
  135. package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +111 -11
  136. package/packages/agentsam-queue-control/src/adapters/cloudflare.js +34 -6
  137. package/packages/agentsam-queue-control/src/adapters/memory.js +11 -2
  138. package/packages/agentsam-queue-control/src/adapters/sqlite.js +259 -0
  139. package/packages/agentsam-queue-control/src/contracts.js +207 -3
  140. package/packages/agentsam-queue-control/src/control-plane.js +62 -2
  141. package/packages/agentsam-queue-control/src/index.js +1 -0
  142. package/packages/agentsam-queue-control/test/queue-control.test.mjs +310 -0
  143. package/packages/agentsam-queue-control/test/sqlite-adapter.test.mjs +91 -0
  144. package/packages/agentsam-rapid-rust/README.md +3 -0
  145. package/packages/agentsam-repository/README.md +3 -0
  146. package/packages/agentsam-repository/package.json +1 -1
  147. package/packages/agentsam-vault/package.json +1 -1
  148. package/packages/agentsam-workbench/README.md +43 -0
  149. package/packages/agentsam-workbench/package.json +13 -3
  150. package/packages/agentsam-workbench/src/agent/AgentConversationSurface.tsx +108 -0
  151. package/packages/agentsam-workbench/src/agent/AgentPanel.tsx +25 -8
  152. package/packages/agentsam-workbench/src/agent/AgentRuntimeField.tsx +152 -0
  153. package/packages/agentsam-workbench/src/agent/Composer.tsx +10 -1
  154. package/packages/agentsam-workbench/src/agent/RunMode.ts +26 -0
  155. package/packages/agentsam-workbench/src/agent/Thread.tsx +18 -3
  156. package/packages/agentsam-workbench/src/agent/index.ts +3 -0
  157. package/packages/agentsam-workbench/src/index.ts +4 -0
  158. package/packages/agentsam-workbench/src/manufacturing/PreflightIndicator.tsx +203 -0
  159. package/packages/agentsam-workbench/src/manufacturing/index.ts +2 -0
  160. package/packages/agentsam-workbench/src/manufacturing/loading.ts +147 -0
  161. package/packages/agentsam-workbench/src/widgets/BuiltinWidget.tsx +22 -0
  162. package/packages/agentsam-workbench/src/widgets/CountdownWidget.tsx +68 -0
  163. package/packages/agentsam-workbench/src/widgets/WidgetFrame.tsx +56 -0
  164. package/packages/agentsam-workbench/src/widgets/countdown.ts +25 -0
  165. package/packages/agentsam-workbench/src/widgets/index.ts +6 -0
  166. package/packages/agentsam-workbench/src/widgets/registry.ts +13 -0
  167. package/packages/agentsam-workbench/src/widgets/useCountdown.ts +128 -0
  168. package/packages/agentsam-workbench/src/widgets/widgets.css +102 -0
  169. package/packages/connectors/{cloudflare → cfoa}/package.json +3 -3
  170. package/packages/heuristic-theme/package.json +1 -1
  171. package/packages/identity/README.md +3 -0
  172. package/packages/identity/backend/README.md +3 -0
  173. package/packages/identity/package.json +1 -1
  174. package/packages/identity/src/frontend/auth-portal/README.md +3 -0
  175. package/packages/identity/src/index.js +1 -1
  176. package/packages/identity/src/oauth/README.md +4 -1
  177. package/packages/identity/src/oauth/credentials.js +1 -1
  178. package/packages/identity/src/server/worker-router.js +1 -1
  179. package/packages/identity/tests/google-desktop-identity-login.test.mjs +1 -1
  180. package/packages/identity/tests/lane1-packed-consumer.test.mjs +1 -1
  181. package/packages/identity/tests/oauth-presets-accounts-ssot.test.mjs +1 -1
  182. package/packages/providers/completeful/package.json +1 -1
  183. package/packages/theme-church-site/package.json +1 -1
  184. package/packages/theme-companions-site/package.json +1 -1
  185. package/packages/theme-floors-site/package.json +1 -1
  186. package/packages/theme-fuelnfree-site/package.json +1 -1
  187. package/packages/theme-handyman-site/package.json +1 -1
  188. package/packages/theme-insurance-site/package.json +1 -1
  189. package/packages/theme-scenes/package.json +1 -1
  190. package/packages/theme-shinshu-site/package.json +1 -1
  191. package/packages/work-graph/package.json +1 -1
  192. package/protocol/models/README.md +3 -0
  193. package/protocol/receipts/agentsam.receipt.v1.json +95 -0
  194. package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +6 -6
  195. package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +6 -6
  196. package/skills/README.md +3 -0
  197. package/src/acp/agent-executor.js +106 -0
  198. package/src/acp/client.js +316 -0
  199. package/src/acp/dependencies.js +426 -0
  200. package/src/acp/http.js +207 -0
  201. package/src/acp/index.js +22 -0
  202. package/src/acp/runs.js +125 -0
  203. package/src/acp/runtime-selection.js +180 -0
  204. package/src/cli/command-catalog.js +3 -0
  205. package/src/cli.js +24 -0
  206. package/src/commands/cloudflare-login.js +1 -1
  207. package/src/commands/cloudflare.js +2 -2
  208. package/src/commands/connections.js +1 -1
  209. package/src/commands/go.js +76 -6
  210. package/src/commands/merch.js +5 -0
  211. package/src/commands/mini.js +1 -1
  212. package/src/commands/receipts.js +140 -0
  213. package/src/commands/run.js +253 -0
  214. package/src/go/container.js +1 -1
  215. package/src/go/contract.js +61 -18
  216. package/src/go/discover.js +0 -4
  217. package/src/go/index.js +13 -1
  218. package/src/go/probe.js +109 -0
  219. package/src/go/{cloudflare.js → providers/cloudflare.js} +36 -136
  220. package/src/go/verify.js +1 -1
  221. package/src/indexing/ingest/inventory.js +1 -1
  222. package/src/lib/deploy/local-studio.js +2 -2
  223. package/src/lib/mini/scaffold.js +1 -1
  224. package/src/lib/whoami-capabilities.js +1 -1
  225. package/src/local/runtime-store.js +8 -0
  226. package/src/mcp/cloudflare-bundles.js +1 -1
  227. package/src/plugins/index.js +1 -0
  228. package/src/plugins/registry.js +59 -6
  229. package/src/receipts/contract.js +68 -0
  230. package/src/receipts/index.js +20 -0
  231. package/src/receipts/prune.js +64 -0
  232. package/src/receipts/sinks.js +285 -0
  233. package/templates/mini/gadget/app.js +15 -40
  234. package/templates/mini/gadget/index.html +7 -7
  235. package/templates/mini/shared/style.css +1 -1
  236. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
  237. /package/packages/connectors/{cloudflare → cfoa}/OAUTH_STORAGE_AUDIT.md +0 -0
  238. /package/packages/connectors/{cloudflare → cfoa}/src/api-client.js +0 -0
  239. /package/packages/connectors/{cloudflare → cfoa}/src/capabilities.js +0 -0
  240. /package/packages/connectors/{cloudflare → cfoa}/src/credential.js +0 -0
  241. /package/packages/connectors/{cloudflare → cfoa}/src/families/brand-protection.js +0 -0
  242. /package/packages/connectors/{cloudflare → cfoa}/src/families/keyless.js +0 -0
  243. /package/packages/connectors/{cloudflare → cfoa}/src/families/pages.js +0 -0
  244. /package/packages/connectors/{cloudflare → cfoa}/src/families/scanner.js +0 -0
  245. /package/packages/connectors/{cloudflare → cfoa}/src/families/snippets.js +0 -0
  246. /package/packages/connectors/{cloudflare → cfoa}/src/families/tag-gateway.js +0 -0
  247. /package/packages/connectors/{cloudflare → cfoa}/src/families/tags.js +0 -0
  248. /package/packages/connectors/{cloudflare → cfoa}/src/families/token-validation.js +0 -0
  249. /package/packages/connectors/{cloudflare → cfoa}/src/families/vectorize.js +0 -0
  250. /package/packages/connectors/{cloudflare → cfoa}/src/families/workflows.js +0 -0
  251. /package/packages/connectors/{cloudflare → cfoa}/src/index.js +0 -0
  252. /package/packages/connectors/{cloudflare → cfoa}/src/oauth-persist.js +0 -0
  253. /package/packages/connectors/{cloudflare → cfoa}/src/owner.js +0 -0
  254. /package/packages/connectors/{cloudflare → cfoa}/src/permission-options.js +0 -0
  255. /package/packages/connectors/{cloudflare → cfoa}/src/routes.js +0 -0
  256. /package/packages/connectors/{cloudflare → cfoa}/src/scope-catalog.js +0 -0
  257. /package/packages/connectors/{cloudflare → cfoa}/src/vault.js +0 -0
  258. /package/packages/connectors/{cloudflare → cfoa}/tests/capabilities.test.mjs +0 -0
  259. /package/packages/connectors/{cloudflare → cfoa}/tests/connector.test.mjs +0 -0
  260. /package/packages/connectors/{cloudflare → cfoa}/tests/oauth-persist.test.mjs +0 -0
  261. /package/packages/identity/src/oauth/{google-desktop-exchange.js → goaude.js} +0 -0
@@ -0,0 +1,203 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+
3
+ export type PreflightStatus =
4
+ | 'ready'
5
+ | 'ready_with_warning'
6
+ | 'ready_with_transform'
7
+ | 'prepared_for_digitization'
8
+ | 'needs_variant'
9
+ | 'unsupported';
10
+
11
+ export interface PreflightIssueView {
12
+ code: string;
13
+ message: string;
14
+ action?: string | null;
15
+ }
16
+
17
+ export interface PreflightIndicatorProps {
18
+ status: PreflightStatus;
19
+ effectivePpi?: number | null;
20
+ readyPpi?: number | null;
21
+ minimumPpi?: number | null;
22
+ issues?: readonly PreflightIssueView[];
23
+ actions?: readonly string[];
24
+ onAction?: (action: string) => void;
25
+ compact?: boolean;
26
+ title?: ReactNode;
27
+ className?: string;
28
+ style?: CSSProperties;
29
+ }
30
+
31
+ const STATUS_COPY: Record<PreflightStatus, { label: string; tone: string }> = {
32
+ ready: { label: 'Production ready', tone: 'ready' },
33
+ ready_with_warning: { label: 'Usable with warning', tone: 'warning' },
34
+ ready_with_transform: { label: 'Quick fix available', tone: 'transform' },
35
+ prepared_for_digitization: { label: 'Prepared for digitization', tone: 'handoff' },
36
+ needs_variant: { label: 'Needs another asset variant', tone: 'error' },
37
+ unsupported: { label: 'Unsupported for this process', tone: 'error' },
38
+ };
39
+
40
+ const ACTION_LABELS: Record<string, string> = {
41
+ trim_alpha: 'Auto-Crop Alpha',
42
+ vectorize_monochrome: 'Convert to Monochrome Vector',
43
+ scale_to_safe_zone: 'Scale to Fit Safe Zone',
44
+ normalize_svg: 'Normalize SVG',
45
+ outline_text: 'Outline Text',
46
+ lossless_optimize: 'Optimize Losslessly',
47
+ };
48
+
49
+ function labelForAction(action: string) {
50
+ if (ACTION_LABELS[action]) return ACTION_LABELS[action];
51
+ if (action.startsWith('normalize_color_space:')) return 'Normalize Color';
52
+ if (action.startsWith('convert:')) return 'Convert Format';
53
+ if (action.startsWith('rasterize:')) return 'Rasterize for Print';
54
+ return action
55
+ .replace(/[:_-]+/g, ' ')
56
+ .replace(/\b\w/g, (value) => value.toUpperCase());
57
+ }
58
+
59
+ function qualityPercent(
60
+ effectivePpi: number | null | undefined,
61
+ readyPpi: number | null | undefined,
62
+ ) {
63
+ if (!effectivePpi || !readyPpi) return null;
64
+ return Math.max(0, Math.min(100, (effectivePpi / readyPpi) * 100));
65
+ }
66
+
67
+ export function PreflightIndicator({
68
+ status,
69
+ effectivePpi,
70
+ readyPpi,
71
+ minimumPpi,
72
+ issues = [],
73
+ actions = [],
74
+ onAction,
75
+ compact = false,
76
+ title = 'Print quality',
77
+ className,
78
+ style,
79
+ }: PreflightIndicatorProps) {
80
+ const state = STATUS_COPY[status];
81
+ const quality = qualityPercent(effectivePpi, readyPpi);
82
+ const uniqueActions = [...new Set(actions)];
83
+
84
+ return (
85
+ <section
86
+ className={className}
87
+ data-agentsam-preflight=""
88
+ data-preflight-status={status}
89
+ data-preflight-tone={state.tone}
90
+ style={{
91
+ border: '1px solid var(--agentsam-preflight-border, rgba(90, 92, 98, 0.24))',
92
+ borderRadius: 12,
93
+ padding: compact ? 10 : 14,
94
+ background: 'var(--agentsam-preflight-bg, rgba(255,255,255,0.72))',
95
+ display: 'grid',
96
+ gap: compact ? 8 : 10,
97
+ ...style,
98
+ }}
99
+ >
100
+ <div
101
+ style={{
102
+ display: 'flex',
103
+ alignItems: 'baseline',
104
+ justifyContent: 'space-between',
105
+ gap: 12,
106
+ }}
107
+ >
108
+ <strong style={{ fontSize: compact ? 12 : 13, fontWeight: 650 }}>{title}</strong>
109
+ <span
110
+ data-preflight-state=""
111
+ style={{
112
+ fontSize: 11,
113
+ opacity: 0.72,
114
+ textAlign: 'right',
115
+ }}
116
+ >
117
+ {state.label}
118
+ </span>
119
+ </div>
120
+
121
+ {quality != null ? (
122
+ <div style={{ display: 'grid', gap: 5 }}>
123
+ <div
124
+ aria-label={`Effective print resolution ${Math.round(effectivePpi!)} PPI`}
125
+ role="meter"
126
+ aria-valuemin={0}
127
+ aria-valuemax={readyPpi || 300}
128
+ aria-valuenow={Math.round(effectivePpi!)}
129
+ style={{
130
+ height: 5,
131
+ borderRadius: 999,
132
+ overflow: 'hidden',
133
+ background: 'var(--agentsam-preflight-track, rgba(90,92,98,0.14))',
134
+ }}
135
+ >
136
+ <div
137
+ style={{
138
+ height: '100%',
139
+ width: `${quality}%`,
140
+ borderRadius: 'inherit',
141
+ background:
142
+ status === 'needs_variant' || status === 'unsupported'
143
+ ? 'var(--agentsam-preflight-error, #9f4d4d)'
144
+ : status === 'ready_with_warning'
145
+ ? 'var(--agentsam-preflight-warning, #a87320)'
146
+ : 'var(--agentsam-preflight-ready, #54745b)',
147
+ transition: 'width 120ms ease',
148
+ }}
149
+ />
150
+ </div>
151
+ <div
152
+ style={{
153
+ display: 'flex',
154
+ gap: 10,
155
+ fontSize: 11,
156
+ opacity: 0.72,
157
+ }}
158
+ >
159
+ <span>{Math.round(effectivePpi!)} PPI effective</span>
160
+ {readyPpi ? <span>{Math.round(readyPpi)} target</span> : null}
161
+ {minimumPpi && minimumPpi !== readyPpi ? (
162
+ <span>{Math.round(minimumPpi)} minimum</span>
163
+ ) : null}
164
+ </div>
165
+ </div>
166
+ ) : null}
167
+
168
+ {!compact && issues.length ? (
169
+ <div style={{ display: 'grid', gap: 4 }}>
170
+ {issues.slice(0, 3).map((issue) => (
171
+ <div key={issue.code} style={{ fontSize: 12, lineHeight: 1.35, opacity: 0.82 }}>
172
+ {issue.message}
173
+ </div>
174
+ ))}
175
+ </div>
176
+ ) : null}
177
+
178
+ {uniqueActions.length && onAction ? (
179
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
180
+ {uniqueActions.slice(0, compact ? 2 : 4).map((action) => (
181
+ <button
182
+ key={action}
183
+ type="button"
184
+ onClick={() => onAction(action)}
185
+ style={{
186
+ border: '1px solid var(--agentsam-preflight-button-border, rgba(70,72,76,0.24))',
187
+ borderRadius: 8,
188
+ padding: compact ? '5px 8px' : '6px 9px',
189
+ background: 'var(--agentsam-preflight-button-bg, rgba(255,255,255,0.82))',
190
+ color: 'inherit',
191
+ font: 'inherit',
192
+ fontSize: 11,
193
+ cursor: 'pointer',
194
+ }}
195
+ >
196
+ {labelForAction(action)}
197
+ </button>
198
+ ))}
199
+ </div>
200
+ ) : null}
201
+ </section>
202
+ );
203
+ }
@@ -0,0 +1,2 @@
1
+ export * from './PreflightIndicator';
2
+ export * from './loading';
@@ -0,0 +1,147 @@
1
+ import type {
2
+ LoadingSceneController,
3
+ LoadingSceneSemantic,
4
+ MetricPointProgress,
5
+ } from '@inneranimalmedia/agentsam-loading-scene';
6
+
7
+ export type ManufacturingLoadingState =
8
+ | 'UPLOADING'
9
+ | 'PREFLIGHT_CHECK'
10
+ | 'NORMALIZING_COLOR'
11
+ | 'VECTORIZING'
12
+ | 'COMPILING_MANUFACTURING'
13
+ | 'DIGITIZATION_HANDOFF';
14
+
15
+ export type ReceiptLoadingState =
16
+ | 'VERIFYING_HASHES'
17
+ | 'PERSISTING_RECEIPT'
18
+ | 'CLEANING_WORKSPACE';
19
+
20
+ interface PipelineStateConfig {
21
+ semantic: LoadingSceneSemantic;
22
+ label: string;
23
+ detail: string;
24
+ }
25
+
26
+ const MANUFACTURING_STATES: Record<ManufacturingLoadingState, PipelineStateConfig> = {
27
+ UPLOADING: {
28
+ semantic: 'asset_ingest',
29
+ label: 'Ingesting master artwork',
30
+ detail: 'Raster/vector parser',
31
+ },
32
+ PREFLIGHT_CHECK: {
33
+ semantic: 'preflight',
34
+ label: 'Evaluating physical print resolution',
35
+ detail: 'Calculating effective PPI from placement geometry',
36
+ },
37
+ NORMALIZING_COLOR: {
38
+ semantic: 'color_normalization',
39
+ label: 'Normalizing production color',
40
+ detail: 'Color profile and transparency normalization',
41
+ },
42
+ VECTORIZING: {
43
+ semantic: 'vectorization',
44
+ label: 'Tracing production paths',
45
+ detail: 'Raster boundary to monochrome vector',
46
+ },
47
+ COMPILING_MANUFACTURING: {
48
+ semantic: 'manufacturing_compile',
49
+ label: 'Compiling manufacturing derivative',
50
+ detail: 'Provider profile validation and export',
51
+ },
52
+ DIGITIZATION_HANDOFF: {
53
+ semantic: 'digitization_handoff',
54
+ label: 'Preparing digitization handoff',
55
+ detail: 'Embroidery source is prepared, not yet a stitch file',
56
+ },
57
+ };
58
+
59
+ const RECEIPT_STATES: Record<ReceiptLoadingState, PipelineStateConfig> = {
60
+ VERIFYING_HASHES: {
61
+ semantic: 'verification',
62
+ label: 'Verifying snapshot integrity',
63
+ detail: 'Pre/post hashes and stale-write evidence',
64
+ },
65
+ PERSISTING_RECEIPT: {
66
+ semantic: 'receipt_persistence',
67
+ label: 'Persisting receipt envelope',
68
+ detail: 'agentsam.receipt.v1 to durable catalog storage',
69
+ },
70
+ CLEANING_WORKSPACE: {
71
+ semantic: 'workspace_cleanup',
72
+ label: 'Cleaning ephemeral workspace',
73
+ detail: 'Reclaiming local temporary storage',
74
+ },
75
+ };
76
+
77
+ export interface PipelineTransitionOptions {
78
+ label?: string;
79
+ detail?: string;
80
+ progress?: number | null;
81
+ metricPoints?: MetricPointProgress;
82
+ }
83
+
84
+ function createController<TState extends string>(
85
+ controller: LoadingSceneController,
86
+ states: Record<TState, PipelineStateConfig>,
87
+ operationId: string,
88
+ ) {
89
+ let started = false;
90
+ let completed = false;
91
+
92
+ function transitionTo(state: TState, options: PipelineTransitionOptions = {}) {
93
+ const config = states[state];
94
+ if (!config || completed) return;
95
+
96
+ const payload = {
97
+ operationId,
98
+ semantic: config.semantic,
99
+ label: options.label || config.label,
100
+ detail: options.detail || config.detail,
101
+ progress: options.progress,
102
+ metricPoints: options.metricPoints,
103
+ };
104
+
105
+ if (!started) {
106
+ controller.start({ ...payload, scope: 'asset' });
107
+ started = true;
108
+ return;
109
+ }
110
+
111
+ controller.activity(payload);
112
+ }
113
+
114
+ return {
115
+ transitionTo,
116
+ complete() {
117
+ if (!started || completed) return;
118
+ completed = true;
119
+ controller.complete(operationId);
120
+ },
121
+ fail(detail?: string) {
122
+ if (!started || completed) return;
123
+ completed = true;
124
+ controller.fail(operationId, detail);
125
+ },
126
+ destroy() {
127
+ if (started && !completed) controller.complete(operationId);
128
+ completed = true;
129
+ },
130
+ };
131
+ }
132
+
133
+ export function createManufacturingLoadingController(
134
+ controller: LoadingSceneController,
135
+ { operationId = 'manufacturing-preflight' }: { operationId?: string } = {},
136
+ ) {
137
+ return createController(controller, MANUFACTURING_STATES, operationId);
138
+ }
139
+
140
+ export function createReceiptPipelineLoadingController(
141
+ controller: LoadingSceneController,
142
+ { operationId = 'receipt-pipeline' }: { operationId?: string } = {},
143
+ ) {
144
+ return createController(controller, RECEIPT_STATES, operationId);
145
+ }
146
+
147
+ export { MANUFACTURING_STATES, RECEIPT_STATES };
@@ -0,0 +1,22 @@
1
+ import { CountdownWidget } from './CountdownWidget';
2
+
3
+ export interface BuiltinWidgetProps {
4
+ widgetId: string;
5
+ compact?: boolean;
6
+ configuration?: Record<string, unknown>;
7
+ }
8
+
9
+ export function BuiltinWidget({
10
+ widgetId,
11
+ compact = false,
12
+ configuration = {},
13
+ }: BuiltinWidgetProps) {
14
+ if (widgetId === 'countdown') {
15
+ const requested = Number(configuration.durationMs);
16
+ const durationMs = Number.isFinite(requested) && requested > 0
17
+ ? requested
18
+ : 5 * 60_000;
19
+ return <CountdownWidget durationMs={durationMs} compact={compact} />;
20
+ }
21
+ return null;
22
+ }
@@ -0,0 +1,68 @@
1
+ import type { CSSProperties } from 'react';
2
+ import { formatCountdown } from './countdown';
3
+ import { useCountdown } from './useCountdown';
4
+
5
+ export interface CountdownWidgetProps {
6
+ durationMs: number;
7
+ label?: string;
8
+ autoStart?: boolean;
9
+ compact?: boolean;
10
+ onComplete?: () => void;
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ }
14
+
15
+ export function CountdownWidget({
16
+ durationMs,
17
+ label = 'Time remaining',
18
+ autoStart = false,
19
+ compact = false,
20
+ onComplete,
21
+ className,
22
+ style,
23
+ }: CountdownWidgetProps) {
24
+ const countdown = useCountdown({ durationMs, autoStart, onComplete });
25
+ const primaryLabel =
26
+ countdown.phase === 'running'
27
+ ? 'Pause'
28
+ : countdown.phase === 'paused'
29
+ ? 'Resume'
30
+ : countdown.phase === 'complete'
31
+ ? 'Start again'
32
+ : 'Start';
33
+
34
+ const onPrimary = () => {
35
+ if (countdown.phase === 'running') countdown.pause();
36
+ else if (countdown.phase === 'paused') countdown.resume();
37
+ else countdown.start();
38
+ };
39
+
40
+ return (
41
+ <div
42
+ className={['agentsam-countdown', className].filter(Boolean).join(' ')}
43
+ data-countdown-phase={countdown.phase}
44
+ data-compact={compact ? 'true' : 'false'}
45
+ style={style}
46
+ >
47
+ <div
48
+ className="agentsam-countdown__time"
49
+ role="timer"
50
+ aria-label={label}
51
+ aria-live="off"
52
+ >
53
+ {formatCountdown(countdown.remainingMs)}
54
+ </div>
55
+ <div className="agentsam-countdown__controls">
56
+ <button type="button" className="agentsam-widget-button agentsam-widget-button--primary" onClick={onPrimary}>
57
+ {primaryLabel}
58
+ </button>
59
+ <button type="button" className="agentsam-widget-button" onClick={() => countdown.reset()}>
60
+ Reset
61
+ </button>
62
+ </div>
63
+ <span className="agentsam-countdown__status" role="status" aria-live="polite">
64
+ {countdown.phase === 'complete' ? 'Timer complete.' : ''}
65
+ </span>
66
+ </div>
67
+ );
68
+ }
@@ -0,0 +1,56 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import type { AgentSamWidgetSize, AgentSamWidgetState } from '@inneranimalmedia/agentsam-contracts/widgets';
3
+
4
+ export interface WidgetFrameProps {
5
+ title: ReactNode;
6
+ description?: ReactNode;
7
+ size?: AgentSamWidgetSize;
8
+ state?: AgentSamWidgetState;
9
+ actions?: ReactNode;
10
+ children: ReactNode;
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ }
14
+
15
+ function stateLabel(state: AgentSamWidgetState | undefined): string | null {
16
+ if (!state || state.status === 'ready') return null;
17
+ if (state.status === 'empty') return 'No data';
18
+ if (state.status === 'stale') return 'Stale';
19
+ return 'Unavailable';
20
+ }
21
+
22
+ export function WidgetFrame({
23
+ title,
24
+ description,
25
+ size = 'small',
26
+ state,
27
+ actions,
28
+ children,
29
+ className,
30
+ style,
31
+ }: WidgetFrameProps) {
32
+ const label = stateLabel(state);
33
+ const errorMessage = state && (state.status === 'stale' || state.status === 'error')
34
+ ? state.error.message
35
+ : null;
36
+
37
+ return (
38
+ <section
39
+ className={['agentsam-widget', className].filter(Boolean).join(' ')}
40
+ data-widget-size={size}
41
+ data-widget-state={state?.status ?? 'ready'}
42
+ style={style}
43
+ >
44
+ <header className="agentsam-widget__header">
45
+ <div className="agentsam-widget__heading">
46
+ <h2 className="agentsam-widget__title">{title}</h2>
47
+ {description ? <p className="agentsam-widget__description">{description}</p> : null}
48
+ </div>
49
+ {label ? <span className="agentsam-widget__state">{label}</span> : null}
50
+ </header>
51
+ <div className="agentsam-widget__body">{children}</div>
52
+ {errorMessage ? <p className="agentsam-widget__message" role="status">{errorMessage}</p> : null}
53
+ {actions ? <footer className="agentsam-widget__actions">{actions}</footer> : null}
54
+ </section>
55
+ );
56
+ }
@@ -0,0 +1,25 @@
1
+ export type CountdownPhase = 'idle' | 'running' | 'paused' | 'complete';
2
+
3
+ export function normalizeCountdownDuration(durationMs: number): number {
4
+ if (!Number.isFinite(durationMs)) return 0;
5
+ return Math.max(0, Math.round(durationMs));
6
+ }
7
+
8
+ export function remainingFromDeadline(deadlineMs: number, nowMs = Date.now()): number {
9
+ return Math.max(0, Math.round(deadlineMs - nowMs));
10
+ }
11
+
12
+ export function formatCountdown(remainingMs: number): string {
13
+ const totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000));
14
+ const hours = Math.floor(totalSeconds / 3600);
15
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
16
+ const seconds = totalSeconds % 60;
17
+
18
+ if (hours > 0) {
19
+ return [hours, minutes, seconds]
20
+ .map((part, index) => (index === 0 ? String(part) : String(part).padStart(2, '0')))
21
+ .join(':');
22
+ }
23
+
24
+ return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
25
+ }
@@ -0,0 +1,6 @@
1
+ export * from './countdown';
2
+ export * from './useCountdown';
3
+ export * from './WidgetFrame';
4
+ export * from './CountdownWidget';
5
+ export * from './registry';
6
+ export * from './BuiltinWidget';
@@ -0,0 +1,13 @@
1
+ import type { AgentSamWidgetDefinition } from '@inneranimalmedia/agentsam-contracts/widgets';
2
+
3
+ export const BUILTIN_WIDGET_DEFINITIONS = Object.freeze([
4
+ Object.freeze({
5
+ id: 'countdown',
6
+ kind: 'countdown',
7
+ title: 'Countdown',
8
+ description: 'Compact deadline-based timer for focus blocks, launch windows, and task checkpoints.',
9
+ icon: 'clock-3',
10
+ sizes: ['small', 'medium'] as const,
11
+ deeplink: '/widgets',
12
+ } satisfies AgentSamWidgetDefinition),
13
+ ] satisfies readonly AgentSamWidgetDefinition[]);
@@ -0,0 +1,128 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import {
3
+ normalizeCountdownDuration,
4
+ remainingFromDeadline,
5
+ type CountdownPhase,
6
+ } from './countdown';
7
+
8
+ export interface UseCountdownOptions {
9
+ durationMs: number;
10
+ autoStart?: boolean;
11
+ tickMs?: number;
12
+ onComplete?: () => void;
13
+ }
14
+
15
+ export interface CountdownController {
16
+ phase: CountdownPhase;
17
+ durationMs: number;
18
+ remainingMs: number;
19
+ deadlineMs: number | null;
20
+ start: () => void;
21
+ pause: () => void;
22
+ resume: () => void;
23
+ reset: (durationMs?: number) => void;
24
+ }
25
+
26
+ export function useCountdown({
27
+ durationMs: durationInput,
28
+ autoStart = false,
29
+ tickMs = 250,
30
+ onComplete,
31
+ }: UseCountdownOptions): CountdownController {
32
+ const normalizedInput = normalizeCountdownDuration(durationInput);
33
+ const [durationMs, setDurationMs] = useState(normalizedInput);
34
+ const [remainingMs, setRemainingMs] = useState(normalizedInput);
35
+ const [deadlineMs, setDeadlineMs] = useState<number | null>(null);
36
+ const [phase, setPhase] = useState<CountdownPhase>(autoStart && normalizedInput > 0 ? 'running' : 'idle');
37
+ const onCompleteRef = useRef(onComplete);
38
+ const completionReportedRef = useRef(false);
39
+
40
+ useEffect(() => {
41
+ onCompleteRef.current = onComplete;
42
+ }, [onComplete]);
43
+
44
+ useEffect(() => {
45
+ setDurationMs(normalizedInput);
46
+ if (phase === 'idle') setRemainingMs(normalizedInput);
47
+ // A completed countdown stays at 00:00 until the user starts or resets it.
48
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ }, [normalizedInput]);
50
+
51
+ const begin = useCallback((baseRemainingMs: number) => {
52
+ const nextRemaining = normalizeCountdownDuration(baseRemainingMs);
53
+ if (nextRemaining <= 0) {
54
+ setRemainingMs(0);
55
+ setDeadlineMs(null);
56
+ setPhase('complete');
57
+ return;
58
+ }
59
+
60
+ completionReportedRef.current = false;
61
+ setRemainingMs(nextRemaining);
62
+ setDeadlineMs(Date.now() + nextRemaining);
63
+ setPhase('running');
64
+ }, []);
65
+
66
+ const start = useCallback(() => {
67
+ begin(phase === 'complete' || remainingMs <= 0 ? durationMs : remainingMs);
68
+ }, [begin, durationMs, phase, remainingMs]);
69
+
70
+ const pause = useCallback(() => {
71
+ if (phase !== 'running' || deadlineMs === null) return;
72
+ const nextRemaining = remainingFromDeadline(deadlineMs);
73
+ setRemainingMs(nextRemaining);
74
+ setDeadlineMs(null);
75
+ setPhase(nextRemaining <= 0 ? 'complete' : 'paused');
76
+ }, [deadlineMs, phase]);
77
+
78
+ const resume = useCallback(() => {
79
+ if (phase !== 'paused') return;
80
+ begin(remainingMs);
81
+ }, [begin, phase, remainingMs]);
82
+
83
+ const reset = useCallback((nextDurationMs = normalizedInput) => {
84
+ const nextDuration = normalizeCountdownDuration(nextDurationMs);
85
+ completionReportedRef.current = false;
86
+ setDurationMs(nextDuration);
87
+ setRemainingMs(nextDuration);
88
+ setDeadlineMs(null);
89
+ setPhase('idle');
90
+ }, [normalizedInput]);
91
+
92
+ useEffect(() => {
93
+ if (!autoStart || normalizedInput <= 0) return;
94
+ if (phase === 'running' && deadlineMs === null) begin(normalizedInput);
95
+ }, [autoStart, begin, deadlineMs, normalizedInput, phase]);
96
+
97
+ useEffect(() => {
98
+ if (phase !== 'running' || deadlineMs === null) return;
99
+
100
+ const tick = () => {
101
+ const nextRemaining = remainingFromDeadline(deadlineMs);
102
+ setRemainingMs(nextRemaining);
103
+ if (nextRemaining > 0) return;
104
+
105
+ setDeadlineMs(null);
106
+ setPhase('complete');
107
+ if (!completionReportedRef.current) {
108
+ completionReportedRef.current = true;
109
+ onCompleteRef.current?.();
110
+ }
111
+ };
112
+
113
+ tick();
114
+ const interval = setInterval(tick, Math.max(50, tickMs));
115
+ return () => clearInterval(interval);
116
+ }, [deadlineMs, phase, tickMs]);
117
+
118
+ return {
119
+ phase,
120
+ durationMs,
121
+ remainingMs,
122
+ deadlineMs,
123
+ start,
124
+ pause,
125
+ resume,
126
+ reset,
127
+ };
128
+ }