workpeg 0.94.3__tar.gz → 0.95.0__tar.gz

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 (73) hide show
  1. {workpeg-0.94.3/src/workpeg.egg-info → workpeg-0.95.0}/PKG-INFO +1 -1
  2. {workpeg-0.94.3 → workpeg-0.95.0}/pyproject.toml +1 -1
  3. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/runtime/scaffold.js +33 -4
  4. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/runtime/workpeg-runtime.js +44 -0
  5. {workpeg-0.94.3 → workpeg-0.95.0/src/workpeg.egg-info}/PKG-INFO +1 -1
  6. {workpeg-0.94.3 → workpeg-0.95.0}/LICENSE +0 -0
  7. {workpeg-0.94.3 → workpeg-0.95.0}/MANIFEST.in +0 -0
  8. {workpeg-0.94.3 → workpeg-0.95.0}/README.md +0 -0
  9. {workpeg-0.94.3 → workpeg-0.95.0}/setup.cfg +0 -0
  10. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/__init__.py +0 -0
  11. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/build.py +0 -0
  12. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/cdn.py +0 -0
  13. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/cli.py +0 -0
  14. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/config.py +0 -0
  15. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/context.py +0 -0
  16. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/create_new.py +0 -0
  17. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/run.py +0 -0
  18. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/runtime.py +0 -0
  19. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/submit.py +0 -0
  20. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/__init__.py +0 -0
  21. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/functions/Dockerfile +0 -0
  22. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/functions/LICENSE +0 -0
  23. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/functions/README.md +0 -0
  24. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/functions/app/__init__.py +0 -0
  25. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/functions/app/main.py +0 -0
  26. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/templates/functions/requirements.txt +0 -0
  27. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/__init__.py +0 -0
  28. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/actions.py +0 -0
  29. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/app.py +0 -0
  30. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/build.py +0 -0
  31. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/compiler/__init__.py +0 -0
  32. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/compiler/ast_parser.py +0 -0
  33. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/compiler/ir.py +0 -0
  34. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/compiler/js_generator.py +0 -0
  35. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/create.py +0 -0
  36. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/fake_cloud.py +0 -0
  37. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/minify.py +0 -0
  38. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/runtime/ai.js +0 -0
  39. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/runtime/pegment.css +0 -0
  40. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/scaffold.py +0 -0
  41. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/serve.py +0 -0
  42. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/state.py +0 -0
  43. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/validators.py +0 -0
  44. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/watcher.py +0 -0
  45. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/__init__.py +0 -0
  46. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/base.py +0 -0
  47. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/canvas.py +0 -0
  48. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/display.py +0 -0
  49. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/forms.py +0 -0
  50. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/futures.py +0 -0
  51. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/gestures.py +0 -0
  52. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/interactive.py +0 -0
  53. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/ui/widgets/layout.py +0 -0
  54. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg/utils.py +0 -0
  55. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg.egg-info/SOURCES.txt +0 -0
  56. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg.egg-info/dependency_links.txt +0 -0
  57. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg.egg-info/entry_points.txt +0 -0
  58. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg.egg-info/requires.txt +0 -0
  59. {workpeg-0.94.3 → workpeg-0.95.0}/src/workpeg.egg-info/top_level.txt +0 -0
  60. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_build.py +0 -0
  61. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_cdn.py +0 -0
  62. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_changelog.py +0 -0
  63. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_changelog_guard.py +0 -0
  64. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_cli.py +0 -0
  65. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_config.py +0 -0
  66. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_context.py +0 -0
  67. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_create_new.py +0 -0
  68. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_release_script.py +0 -0
  69. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_run.py +0 -0
  70. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_runtime.py +0 -0
  71. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_submit.py +0 -0
  72. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_utils.py +0 -0
  73. {workpeg-0.94.3 → workpeg-0.95.0}/tests/test_watch_pipeline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workpeg
3
- Version: 0.94.3
3
+ Version: 0.95.0
4
4
  Summary: Workpeg function runtime and SDK
5
5
  Author-email: Workpeg <support@workpeg.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "workpeg"
7
- version = "0.94.3"
7
+ version = "0.95.0"
8
8
  description = "Workpeg function runtime and SDK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -308,8 +308,8 @@
308
308
 
309
309
  // A built-in rail row (Search / Workpeg AI) — the same look as a host
310
310
  // NavItem: icon + fading label, the collapse re-centre via the padding var.
311
- function navRow(iconName, label, href) {
312
- return el("a", "wps-nav-row", {
311
+ function navRow(iconName, label, href, extraClass) {
312
+ return el("a", "wps-nav-row" + (extraClass ? " " + extraClass : ""), {
313
313
  attrs: { href: href, title: label },
314
314
  children: [
315
315
  icon(iconName, 18),
@@ -564,6 +564,16 @@
564
564
  "display:var(--wp-topnav-chat, none);align-items:center;"
565
565
  + "font-size:16px;font-weight:600;color:var(--color-text-primary)";
566
566
 
567
+ // "New chat" — only on an open conversation (/chats/<id>), a fresh-compose
568
+ // shortcut that starts a new chat without hunting for the sidebar row.
569
+ // Gated by STYLES on .pg-chat-route.wpai-chat-open (the same classes the
570
+ // runtime + ai.js already flip), so a scaffold.js CDN update delivers it
571
+ // out of band — no pegment var, no rebuild.
572
+ var newChat = el("div", "wps-newchat", { children: [
573
+ topAction("edit", "New chat", function () {
574
+ navigate(bizHref("/chats/new"));
575
+ })] });
576
+
567
577
  var history = el("div", "", { children: [
568
578
  topAction("history", "Chat history", function () {
569
579
  try { WP().toggleAIHistory(); } catch (e) { /* no runtime */ }
@@ -590,7 +600,7 @@
590
600
  el("div", "wps-topnav-row", { children: [
591
601
  el("div", "wps-topnav-left", { children: [hostWrap, chatTitle] }),
592
602
  el("div", "wps-topnav-actions", { children: [
593
- history, spy, appsBtn, ai] })
603
+ newChat, history, spy, appsBtn, ai] })
594
604
  ] })
595
605
  ] });
596
606
  // Inline padding (not stylesheet) so pegment's .wpai-* !important
@@ -625,7 +635,19 @@
625
635
  // screens.
626
636
  var mid = el("div", "wps-side-mid", { children: [slots.nav] });
627
637
  var foot = el("div", "wps-foot");
628
- var aiRow = navRow("sparkles", "Workpeg AI", bizHref("/chats/new"));
638
+ var aiRow = navRow("sparkles", "Workpeg AI", bizHref("/chats/new"),
639
+ "wps-ai-row");
640
+ // On any /chats/* route this row IS the active surface (styled via
641
+ // .pg-chat-route in STYLES). A click must not reset an open conversation
642
+ // back to /chats/new — preventDefault so the runtime's link router skips
643
+ // navigating (it bails on defaultPrevented). Off the chat route the row
644
+ // navigates normally, opening a fresh chat.
645
+ aiRow.addEventListener("click", function (e) {
646
+ var de = document.documentElement;
647
+ if (de && de.classList && de.classList.contains("pg-chat-route")) {
648
+ e.preventDefault();
649
+ }
650
+ });
629
651
  var rail = el("div", "pg-container pg-container-sidebar wps-sidebar", {
630
652
  children: [
631
653
  el("div", "wps-side-col", { children: [
@@ -778,6 +800,10 @@
778
800
  "transition:padding-left 0.18s " + EASE + ";flex-shrink:0}",
779
801
  ".wps-nav-row:hover{background:var(--color-bg-active)}",
780
802
  ".wps-nav-row[aria-current=\"page\"]{background:var(--color-bg-active)}",
803
+ /* Workpeg AI stays active across the whole /chats/* surface, not just the
804
+ exact /chats/new href aria-current marks — driven by .pg-chat-route on
805
+ <html>, which the runtime flips on the reserved route. */
806
+ ":root.pg-chat-route .wps-ai-row{background:var(--color-bg-active)}",
781
807
  ".wps-nav-row .ti{color:var(--color-icon-primary);flex-shrink:0}",
782
808
  ".wps-nav-label{flex:1;min-width:0;overflow:hidden;white-space:nowrap;",
783
809
  "margin-left:8px;opacity:var(--pg-collapse-op);",
@@ -893,6 +919,9 @@
893
919
  ".wps-topnav-left{min-width:0;overflow:hidden;display:flex;",
894
920
  "align-items:center}",
895
921
  ".wps-topnav-actions{display:flex;align-items:center;gap:8px}",
922
+ /* New chat only shows on an open conversation (same state as History) */
923
+ ".wps-newchat{display:none}",
924
+ ":root.pg-chat-route.wpai-chat-open .wps-newchat{display:flex}",
896
925
  ".wps-chrome-btn{display:flex;align-items:center;justify-content:center;",
897
926
  "width:32px;height:32px;border-radius:var(--radius);cursor:pointer;",
898
927
  "flex-shrink:0;border:none;background:transparent;padding:0;",
@@ -157,6 +157,43 @@
157
157
  // target only Workpeg domains, resolve a path against apiBase, and send the
158
158
  // Peg-Namespace whoami header. workpeg.get/post/... in Python compile here.
159
159
 
160
+ // The workpeg.* endpoint allowlist. Being on a Workpeg host is necessary
161
+ // but no longer sufficient: a namespaced call must ALSO resolve to one of
162
+ // these sanctioned surfaces, so a Peg can't reach arbitrary platform
163
+ // endpoints (/v1/users/me/, another business's data, …) through this
164
+ // client. Each rule may pin the host's first label and/or a pathname regex;
165
+ // a call is allowed if it satisfies any rule. Matched against the
166
+ // URL-NORMALIZED pathname, so ".." can't tunnel out of an allowed prefix.
167
+ // Extend this list as new first-class surfaces are opened to Pegs.
168
+ Workpeg._wpAllowlist = [
169
+ // Tables & rows data API — a table, its rows, bulk-create, search and
170
+ // permissions all live under /v1/businesses/<biz>/tables/. The business
171
+ // segment may be empty (off a business page); the server rejects that,
172
+ // and it stays a tables-shaped URL either way.
173
+ { path: /^\/v1\/businesses\/[^/]*\/tables\// },
174
+ // The CDN — assets, pegment, bundles, peg media (any path).
175
+ { host: "cdn" },
176
+ ];
177
+
178
+ Workpeg._wpAllowedEndpoint = function (full) {
179
+ var u;
180
+ try {
181
+ u = new URL(full);
182
+ } catch (e) {
183
+ return false;
184
+ }
185
+ // First label of a Workpeg host (the caller has already vouched the host
186
+ // is ours), e.g. "cdn" of cdn.workpeg.com; pathname is normalized by URL.
187
+ var firstLabel = u.hostname.toLowerCase().split(".")[0];
188
+ for (var i = 0; i < Workpeg._wpAllowlist.length; i++) {
189
+ var rule = Workpeg._wpAllowlist[i];
190
+ if (rule.host && rule.host !== firstLabel) continue;
191
+ if (rule.path && !rule.path.test(u.pathname)) continue;
192
+ return true;
193
+ }
194
+ return false;
195
+ };
196
+
160
197
  Workpeg._wpBuildUrl = function (method, url) {
161
198
  var full = /^(https?:)?\/\//i.test(String(url))
162
199
  ? String(url)
@@ -167,6 +204,13 @@
167
204
  full + "); use http." + method.toLowerCase() + "() for the open web."
168
205
  );
169
206
  }
207
+ // …and only the allowlisted Workpeg surfaces (tables, rows, CDN).
208
+ if (!Workpeg._wpAllowedEndpoint(full)) {
209
+ throw new Error(
210
+ "workpeg." + method.toLowerCase() + "() may only reach the tables, " +
211
+ "rows and CDN endpoints, not " + full + "."
212
+ );
213
+ }
170
214
  return full;
171
215
  };
172
216
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workpeg
3
- Version: 0.94.3
3
+ Version: 0.95.0
4
4
  Summary: Workpeg function runtime and SDK
5
5
  Author-email: Workpeg <support@workpeg.com>
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes