orionfold-relay 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +60 -19
- package/next.config.mjs +52 -1
- package/package.json +2 -1
- package/src/app/apps/page.tsx +1 -1
- package/src/app/inbox/page.tsx +1 -1
- package/src/app/layout.tsx +8 -3
- package/src/app/packs/page.tsx +1 -1
- package/src/app/projects/[id]/page.tsx +0 -11
- package/src/components/apps/last-run-card.tsx +1 -1
- package/src/components/apps/ledger-hero-panel.tsx +1 -1
- package/src/components/charts/time-series-chart.tsx +1 -1
- package/src/components/chat/app-materialized-card.tsx +1 -1
- package/src/components/chat/app-view-editor-card.tsx +1 -1
- package/src/components/chat/chat-command-popover.tsx +2 -2
- package/src/components/chat/chat-empty-state.tsx +1 -1
- package/src/components/chat/chat-message.tsx +2 -1
- package/src/components/chat/chat-session-provider.tsx +2 -2
- package/src/components/chat/conversation-template-picker.tsx +1 -1
- package/src/components/chat/skill-row.tsx +1 -15
- package/src/components/customers/customer-form-sheet.tsx +1 -1
- package/src/components/dashboard/greeting.tsx +1 -1
- package/src/components/dashboard/welcome-landing.tsx +2 -2
- package/src/components/documents/document-upload-dialog.tsx +1 -1
- package/src/components/documents/smart-extracted-text.tsx +1 -1
- package/src/components/instance/instance-section.tsx +1 -1
- package/src/components/instance/upgrade-badge.tsx +1 -1
- package/src/components/notifications/batch-proposal-review.tsx +1 -1
- package/src/components/onboarding/runtime-preference-modal.tsx +32 -3
- package/src/components/packs/pack-update-button.tsx +1 -1
- package/src/components/profiles/profile-detail-view.tsx +1 -1
- package/src/components/projects/project-create-dialog.tsx +1 -1
- package/src/components/projects/project-form-sheet.tsx +2 -2
- package/src/components/schedules/schedule-create-dialog.tsx +1 -1
- package/src/components/schedules/schedule-create-sheet.tsx +1 -1
- package/src/components/schedules/schedule-edit-sheet.tsx +1 -1
- package/src/components/schedules/schedule-form.tsx +1 -1
- package/src/components/settings/data-management-section.tsx +2 -2
- package/src/components/settings/database-snapshots-section.tsx +6 -6
- package/src/components/settings/ollama-section.tsx +2 -2
- package/src/components/settings/presets-section.tsx +2 -2
- package/src/components/settings/providers-runtimes-section.tsx +6 -6
- package/src/components/settings/web-search-section.tsx +1 -1
- package/src/components/shared/command-palette.tsx +2 -2
- package/src/components/shared/trust-tier-badge.tsx +3 -3
- package/src/components/shell/app-bar.tsx +156 -164
- package/src/components/shell/app-shell.tsx +16 -8
- package/src/components/shell/nav-items.ts +72 -30
- package/src/components/tasks/ai-assist-panel.tsx +2 -2
- package/src/components/tasks/task-create-panel.tsx +1 -1
- package/src/components/tasks/task-edit-dialog.tsx +1 -1
- package/src/components/workflows/blueprint-gallery.tsx +1 -1
- package/src/components/workflows/delay-step-body.tsx +1 -1
- package/src/components/workflows/workflow-confirmation-view.tsx +1 -1
- package/src/components/workflows/workflow-form-view.tsx +1 -1
- package/src/components/workspace/discover-workspace-dialog.tsx +1 -1
- package/src/lib/agents/runtime/openai-codex.ts +1 -1
- package/src/lib/apps/apps-events.ts +15 -0
- package/src/lib/apps/use-apps.ts +4 -3
- package/src/lib/channels/slack-adapter.ts +1 -1
- package/src/lib/channels/telegram-adapter.ts +1 -1
- package/src/lib/channels/webhook-adapter.ts +2 -2
- package/src/lib/chat/system-prompt.ts +4 -4
- package/src/lib/chat/tool-catalog.ts +3 -3
- package/src/lib/chat/tools/app-view-tools.ts +3 -2
- package/src/lib/data/seed-data/environment.ts +2 -2
- package/src/lib/db/bootstrap.ts +5 -1
- package/src/lib/packs/templates/relay-agency/pack.yaml +1 -1
- package/src/lib/packs/templates/relay-agency-pro/pack.yaml +6 -6
- package/src/lib/plugins/examples/echo-server/plugin.yaml +1 -1
- package/src/lib/plugins/examples/finance-pack/plugin.yaml +1 -1
- package/src/lib/plugins/examples/reading-radar/plugin.yaml +1 -1
- package/src/lib/plugins/registry.ts +1 -1
- package/src/lib/plugins/sdk/types.ts +1 -1
- package/src/lib/theme.ts +23 -11
- package/src/lib/workflows/blueprints/registry.ts +59 -10
- package/src/app/analytics/page.tsx +0 -40
- package/src/app/api/environment/artifacts/[id]/route.ts +0 -17
- package/src/app/api/environment/artifacts/route.ts +0 -33
- package/src/app/api/environment/checkpoints/[id]/route.ts +0 -86
- package/src/app/api/environment/checkpoints/route.ts +0 -80
- package/src/app/api/environment/profiles/create/route.ts +0 -28
- package/src/app/api/environment/profiles/suggest/route.ts +0 -41
- package/src/app/api/environment/scan/route.ts +0 -70
- package/src/app/api/environment/sync/history/route.ts +0 -20
- package/src/app/api/environment/sync/preview/route.ts +0 -27
- package/src/app/api/environment/sync/route.ts +0 -43
- package/src/app/api/environment/templates/[id]/route.ts +0 -34
- package/src/app/api/environment/templates/route.ts +0 -27
- package/src/app/environment/compare/page.tsx +0 -20
- package/src/app/environment/loading.tsx +0 -56
- package/src/app/environment/page.tsx +0 -61
- package/src/app/environment/skills/page.tsx +0 -20
- package/src/components/analytics/analytics-dashboard.tsx +0 -200
- package/src/components/environment/adoption-prompt.tsx +0 -76
- package/src/components/environment/artifact-card.tsx +0 -93
- package/src/components/environment/artifact-detail-sheet.tsx +0 -136
- package/src/components/environment/artifact-presence-cell.tsx +0 -44
- package/src/components/environment/category-filter-bar.tsx +0 -132
- package/src/components/environment/checkpoint-list.tsx +0 -169
- package/src/components/environment/comparison-matrix.tsx +0 -132
- package/src/components/environment/environment-dashboard.tsx +0 -248
- package/src/components/environment/environment-summary-card.tsx +0 -153
- package/src/components/environment/health-score-card.tsx +0 -86
- package/src/components/environment/persona-indicator.tsx +0 -43
- package/src/components/environment/profile-create-dialog.tsx +0 -178
- package/src/components/environment/project-diff-view.tsx +0 -59
- package/src/components/environment/project-scan-badge.tsx +0 -36
- package/src/components/environment/rollback-confirm-dialog.tsx +0 -105
- package/src/components/environment/scan-status-bar.tsx +0 -48
- package/src/components/environment/skill-catalog.tsx +0 -117
- package/src/components/environment/skill-detail-sheet.tsx +0 -106
- package/src/components/environment/skill-drift-indicator.tsx +0 -42
- package/src/components/environment/suggested-profiles.tsx +0 -162
- package/src/components/environment/summary-cards-row.tsx +0 -91
- package/src/components/environment/sync-action-buttons.tsx +0 -63
- package/src/components/environment/sync-preview-dialog.tsx +0 -205
- package/src/components/environment/template-list.tsx +0 -149
- package/src/components/environment/tool-comparison-view.tsx +0 -75
- package/src/lib/analytics/queries.ts +0 -207
- package/src/lib/environment/comparison.ts +0 -170
- package/src/lib/environment/health-scoring.ts +0 -162
- package/src/lib/environment/skill-portfolio.ts +0 -97
package/dist/cli.js
CHANGED
|
@@ -464,7 +464,7 @@ function bootstrapAinativeDatabase(sqlite3) {
|
|
|
464
464
|
sqlite3.exec(ddl);
|
|
465
465
|
} catch (err2) {
|
|
466
466
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
467
|
-
if (!msg.includes("duplicate column")) {
|
|
467
|
+
if (!msg.includes("duplicate column") && !msg.includes("no such table")) {
|
|
468
468
|
console.error("[bootstrap] ALTER TABLE failed:", msg);
|
|
469
469
|
}
|
|
470
470
|
}
|
|
@@ -1186,7 +1186,7 @@ var CURRENT_PLUGIN_API_VERSION, CAPABILITY_VALUES, ORIGIN_VALUES, PrimitivesBund
|
|
|
1186
1186
|
var init_types = __esm({
|
|
1187
1187
|
"src/lib/plugins/sdk/types.ts"() {
|
|
1188
1188
|
"use strict";
|
|
1189
|
-
CURRENT_PLUGIN_API_VERSION = "0.
|
|
1189
|
+
CURRENT_PLUGIN_API_VERSION = "0.24";
|
|
1190
1190
|
CAPABILITY_VALUES = ["fs", "net", "child_process", "env"];
|
|
1191
1191
|
ORIGIN_VALUES = ["ainative-internal", "third-party"];
|
|
1192
1192
|
PrimitivesBundleManifestSchema = z.object({
|
|
@@ -5795,6 +5795,13 @@ __export(registry_exports3, {
|
|
|
5795
5795
|
import fs11 from "fs";
|
|
5796
5796
|
import path11 from "path";
|
|
5797
5797
|
import yaml7 from "js-yaml";
|
|
5798
|
+
function userDirMtimeMs() {
|
|
5799
|
+
try {
|
|
5800
|
+
return fs11.statSync(USER_BLUEPRINTS_DIR).mtimeMs;
|
|
5801
|
+
} catch {
|
|
5802
|
+
return null;
|
|
5803
|
+
}
|
|
5804
|
+
}
|
|
5798
5805
|
function scanDirectory(dir, isBuiltin2) {
|
|
5799
5806
|
const blueprints = /* @__PURE__ */ new Map();
|
|
5800
5807
|
if (!fs11.existsSync(dir)) return blueprints;
|
|
@@ -5829,8 +5836,13 @@ function loadAll() {
|
|
|
5829
5836
|
return all;
|
|
5830
5837
|
}
|
|
5831
5838
|
function ensureLoaded2() {
|
|
5839
|
+
if (blueprintCache && userDirMtimeMs() !== cachedDirMtimeMs) {
|
|
5840
|
+
blueprintCache = null;
|
|
5841
|
+
}
|
|
5832
5842
|
if (!blueprintCache) {
|
|
5843
|
+
cachedDirMtimeMs = userDirMtimeMs();
|
|
5833
5844
|
blueprintCache = loadAll();
|
|
5845
|
+
applyPluginBlueprints(blueprintCache);
|
|
5834
5846
|
}
|
|
5835
5847
|
return blueprintCache;
|
|
5836
5848
|
}
|
|
@@ -5878,30 +5890,35 @@ function deleteBlueprint(id) {
|
|
|
5878
5890
|
function getUserBlueprintsDir() {
|
|
5879
5891
|
return USER_BLUEPRINTS_DIR;
|
|
5880
5892
|
}
|
|
5893
|
+
function applyPluginBlueprints(cache) {
|
|
5894
|
+
for (const byId of pluginBlueprints.values()) {
|
|
5895
|
+
for (const [id, bp] of byId) cache.set(id, bp);
|
|
5896
|
+
}
|
|
5897
|
+
}
|
|
5881
5898
|
function mergePluginBlueprints(entries) {
|
|
5882
5899
|
const cache = ensureLoaded2();
|
|
5883
5900
|
for (const entry of entries) {
|
|
5884
5901
|
cache.set(entry.blueprint.id, entry.blueprint);
|
|
5885
|
-
if (!
|
|
5886
|
-
|
|
5902
|
+
if (!pluginBlueprints.has(entry.pluginId)) {
|
|
5903
|
+
pluginBlueprints.set(entry.pluginId, /* @__PURE__ */ new Map());
|
|
5887
5904
|
}
|
|
5888
|
-
|
|
5905
|
+
pluginBlueprints.get(entry.pluginId).set(entry.blueprint.id, entry.blueprint);
|
|
5889
5906
|
}
|
|
5890
5907
|
}
|
|
5891
5908
|
function clearPluginBlueprints(pluginId) {
|
|
5892
5909
|
const cache = blueprintCache;
|
|
5893
|
-
const
|
|
5894
|
-
if (!
|
|
5895
|
-
if (cache) for (const id of
|
|
5896
|
-
|
|
5910
|
+
const byId = pluginBlueprints.get(pluginId);
|
|
5911
|
+
if (!byId) return;
|
|
5912
|
+
if (cache) for (const id of byId.keys()) cache.delete(id);
|
|
5913
|
+
pluginBlueprints.delete(pluginId);
|
|
5897
5914
|
}
|
|
5898
5915
|
function clearAllPluginBlueprints() {
|
|
5899
|
-
for (const pluginId of Array.from(
|
|
5916
|
+
for (const pluginId of Array.from(pluginBlueprints.keys())) {
|
|
5900
5917
|
clearPluginBlueprints(pluginId);
|
|
5901
5918
|
}
|
|
5902
5919
|
}
|
|
5903
5920
|
function listPluginBlueprintIds(pluginId) {
|
|
5904
|
-
return Array.from(
|
|
5921
|
+
return Array.from(pluginBlueprints.get(pluginId)?.keys() ?? []);
|
|
5905
5922
|
}
|
|
5906
5923
|
function validateBlueprintRefs(bp, opts2) {
|
|
5907
5924
|
for (const step of bp.steps ?? []) {
|
|
@@ -5923,7 +5940,7 @@ function validateBlueprintRefs(bp, opts2) {
|
|
|
5923
5940
|
}
|
|
5924
5941
|
return { ok: true };
|
|
5925
5942
|
}
|
|
5926
|
-
var BUILTINS_DIR2, USER_BLUEPRINTS_DIR, blueprintCache,
|
|
5943
|
+
var BUILTINS_DIR2, USER_BLUEPRINTS_DIR, blueprintCache, cachedDirMtimeMs, pluginBlueprints;
|
|
5927
5944
|
var init_registry3 = __esm({
|
|
5928
5945
|
"src/lib/workflows/blueprints/registry.ts"() {
|
|
5929
5946
|
"use strict";
|
|
@@ -5941,7 +5958,8 @@ var init_registry3 = __esm({
|
|
|
5941
5958
|
);
|
|
5942
5959
|
USER_BLUEPRINTS_DIR = getAinativeBlueprintsDir();
|
|
5943
5960
|
blueprintCache = null;
|
|
5944
|
-
|
|
5961
|
+
cachedDirMtimeMs = null;
|
|
5962
|
+
pluginBlueprints = /* @__PURE__ */ new Map();
|
|
5945
5963
|
}
|
|
5946
5964
|
});
|
|
5947
5965
|
|
|
@@ -12945,7 +12963,7 @@ var init_registry6 = __esm({
|
|
|
12945
12963
|
init_registry5();
|
|
12946
12964
|
init_installer();
|
|
12947
12965
|
init_schedule_spec();
|
|
12948
|
-
SUPPORTED_API_VERSIONS = /* @__PURE__ */ new Set([CURRENT_PLUGIN_API_VERSION, "0.
|
|
12966
|
+
SUPPORTED_API_VERSIONS = /* @__PURE__ */ new Set([CURRENT_PLUGIN_API_VERSION, "0.23"]);
|
|
12949
12967
|
pluginCache = null;
|
|
12950
12968
|
lastLoadedPluginIds = /* @__PURE__ */ new Set();
|
|
12951
12969
|
PluginTableSchema = z16.object({
|
|
@@ -17617,11 +17635,20 @@ var init_plugin_spec_tools = __esm({
|
|
|
17617
17635
|
}
|
|
17618
17636
|
});
|
|
17619
17637
|
|
|
17638
|
+
// src/lib/apps/apps-events.ts
|
|
17639
|
+
var APPS_CHANGED_EVENT;
|
|
17640
|
+
var init_apps_events = __esm({
|
|
17641
|
+
"src/lib/apps/apps-events.ts"() {
|
|
17642
|
+
"use strict";
|
|
17643
|
+
APPS_CHANGED_EVENT = "relay-apps-changed";
|
|
17644
|
+
}
|
|
17645
|
+
});
|
|
17646
|
+
|
|
17620
17647
|
// src/lib/chat/tools/app-view-tools.ts
|
|
17621
17648
|
import { z as z28 } from "zod";
|
|
17622
17649
|
function dispatchAppsChangedFromTool() {
|
|
17623
17650
|
if (typeof window !== "undefined") {
|
|
17624
|
-
window.dispatchEvent(new CustomEvent(
|
|
17651
|
+
window.dispatchEvent(new CustomEvent(APPS_CHANGED_EVENT));
|
|
17625
17652
|
}
|
|
17626
17653
|
}
|
|
17627
17654
|
function loadManifestOrError(appId) {
|
|
@@ -17758,6 +17785,7 @@ var init_app_view_tools = __esm({
|
|
|
17758
17785
|
"src/lib/chat/tools/app-view-tools.ts"() {
|
|
17759
17786
|
"use strict";
|
|
17760
17787
|
init_tool_registry();
|
|
17788
|
+
init_apps_events();
|
|
17761
17789
|
init_helpers2();
|
|
17762
17790
|
init_registry();
|
|
17763
17791
|
BindingsSchema = ViewSchema.shape.bindings;
|
|
@@ -20155,7 +20183,7 @@ async function handleServerRequest(client, taskId, request) {
|
|
|
20155
20183
|
contentItems: [
|
|
20156
20184
|
{
|
|
20157
20185
|
type: "inputText",
|
|
20158
|
-
text: "Dynamic tool calls are not supported by
|
|
20186
|
+
text: "Dynamic tool calls are not supported by Relay's Codex runtime yet."
|
|
20159
20187
|
}
|
|
20160
20188
|
]
|
|
20161
20189
|
});
|
|
@@ -25775,8 +25803,8 @@ import { execFileSync as execFileSync3 } from "child_process";
|
|
|
25775
25803
|
import yaml12 from "js-yaml";
|
|
25776
25804
|
import semver from "semver";
|
|
25777
25805
|
function relayCoreVersion() {
|
|
25778
|
-
if (semver.valid("0.
|
|
25779
|
-
return "0.
|
|
25806
|
+
if (semver.valid("0.24.0")) {
|
|
25807
|
+
return "0.24.0";
|
|
25780
25808
|
}
|
|
25781
25809
|
try {
|
|
25782
25810
|
const root = getAppRoot(import.meta.dirname, 3);
|
|
@@ -27147,7 +27175,8 @@ var __dirname = dirname5(fileURLToPath4(import.meta.url));
|
|
|
27147
27175
|
var appDir = join21(__dirname, "..");
|
|
27148
27176
|
var launchCwd2 = process.cwd();
|
|
27149
27177
|
var _envLocalPath = join21(launchCwd2, ".env.local");
|
|
27150
|
-
var
|
|
27178
|
+
var _hasDataDirFlag = process.argv.slice(2).some((a) => a === "--data-dir" || a.startsWith("--data-dir="));
|
|
27179
|
+
var _firstRunNeedsEnv = !existsSync13(_envLocalPath) && !process.env.RELAY_DATA_DIR && !_hasDataDirFlag && !isDevMode(launchCwd2);
|
|
27151
27180
|
if (_firstRunNeedsEnv) {
|
|
27152
27181
|
const folderName = basename6(launchCwd2);
|
|
27153
27182
|
const autoDataDir = join21(homedir8(), `.${folderName}`);
|
|
@@ -27187,6 +27216,18 @@ if (existsSync13(_envLocalPath)) {
|
|
|
27187
27216
|
}
|
|
27188
27217
|
}
|
|
27189
27218
|
}
|
|
27219
|
+
function scanDataDirFlag(argv) {
|
|
27220
|
+
for (let i = 0; i < argv.length; i++) {
|
|
27221
|
+
const tok = argv[i];
|
|
27222
|
+
if (tok === "--data-dir") return argv[i + 1];
|
|
27223
|
+
if (tok.startsWith("--data-dir=")) return tok.slice("--data-dir=".length);
|
|
27224
|
+
}
|
|
27225
|
+
return void 0;
|
|
27226
|
+
}
|
|
27227
|
+
var _dataDirFlag = scanDataDirFlag(process.argv.slice(2));
|
|
27228
|
+
if (_dataDirFlag) {
|
|
27229
|
+
process.env.RELAY_DATA_DIR = _dataDirFlag;
|
|
27230
|
+
}
|
|
27190
27231
|
var pkg = JSON.parse(readFileSync9(join21(appDir, "package.json"), "utf-8"));
|
|
27191
27232
|
function getHelpText() {
|
|
27192
27233
|
const dir = getAinativeDataDir();
|
package/next.config.mjs
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import {
|
|
3
|
+
PHASE_PRODUCTION_BUILD,
|
|
4
|
+
PHASE_DEVELOPMENT_SERVER,
|
|
5
|
+
} from "next/constants.js";
|
|
6
|
+
|
|
1
7
|
// When the operator opts into LAN binding (`--hostname` to a non-loopback host,
|
|
2
8
|
// see bin/cli.ts), the CLI sets RELAY_ALLOW_LAN_ORIGINS=true. In dev mode Next
|
|
3
9
|
// otherwise blocks cross-origin requests to /_next/* dev assets from the LAN
|
|
@@ -16,6 +22,26 @@ const RFC1918_DEV_ORIGINS = [
|
|
|
16
22
|
];
|
|
17
23
|
const allowLanDevOrigins = process.env.RELAY_ALLOW_LAN_ORIGINS === "true";
|
|
18
24
|
|
|
25
|
+
// Build-time core version, mirroring tsup's `define` (tsup.config.ts). tsup
|
|
26
|
+
// only builds the CLI bundle (dist/cli.js), so WITHOUT this the Next.js server
|
|
27
|
+
// leaves `__RELAY_CORE_VERSION__` undefined — relayCoreVersion() then falls to
|
|
28
|
+
// its "0.0.0" default and every /packs UI install is rejected with
|
|
29
|
+
// `requires relay-core >=X, but this install is 0.0.0` (fix-packs-ui-install-
|
|
30
|
+
// core-version). We inject it via `compiler.defineServer` below, which Next
|
|
31
|
+
// applies to BOTH bundlers (webpack for `next build`, Turbopack for `next dev`)
|
|
32
|
+
// so the server resolves the real version exactly as the shipped CLI does.
|
|
33
|
+
// `defineServer` (not `define`) because relayCoreVersion() is server-only —
|
|
34
|
+
// keeps the value out of client bundles. Single source of truth: pkg.version.
|
|
35
|
+
//
|
|
36
|
+
// NOTE: pass the RAW version string, NOT `JSON.stringify(...)`. Next's
|
|
37
|
+
// `compiler.define` takes literal values and quotes them itself, unlike tsup's
|
|
38
|
+
// `define` which takes JS-source text. Stringifying here would inject the
|
|
39
|
+
// double-quoted `"0.23.0"`, which fails `semver.valid()` and silently falls
|
|
40
|
+
// back to the "0.0.0" default — reintroducing the exact bug this fixes.
|
|
41
|
+
const CORE_VERSION_DEFINE = JSON.parse(
|
|
42
|
+
readFileSync(new URL("./package.json", import.meta.url), "utf-8")
|
|
43
|
+
).version;
|
|
44
|
+
|
|
19
45
|
/** @type {import('next').NextConfig} */
|
|
20
46
|
const nextConfig = {
|
|
21
47
|
serverExternalPackages: ["better-sqlite3", "pdf-parse", "pdfjs-dist"],
|
|
@@ -41,4 +67,29 @@ const nextConfig = {
|
|
|
41
67
|
},
|
|
42
68
|
};
|
|
43
69
|
|
|
44
|
-
export
|
|
70
|
+
// Phase-aware export. `compiler.defineServer` is a COMPILE-TIME directive — it
|
|
71
|
+
// only does anything while a bundler runs (build + dev). At runtime `next start`
|
|
72
|
+
// re-reads this config but never recompiles, so the define is inert there AND
|
|
73
|
+
// Next's config validator emits a spurious "defineServer.__RELAY_CORE_VERSION__
|
|
74
|
+
// is missing, expected boolean" warning (a false positive from its union-error
|
|
75
|
+
// flattener — the string value is valid; see next/dist/shared/lib/zod.js). That
|
|
76
|
+
// warning would land in every customer's prod server log. So we attach
|
|
77
|
+
// defineServer ONLY in the build/dev phases, keeping the shipped `next start`
|
|
78
|
+
// path warning-free while the version is already baked into `.next`.
|
|
79
|
+
export default function config(phase) {
|
|
80
|
+
if (
|
|
81
|
+
phase === PHASE_PRODUCTION_BUILD ||
|
|
82
|
+
phase === PHASE_DEVELOPMENT_SERVER
|
|
83
|
+
) {
|
|
84
|
+
return {
|
|
85
|
+
...nextConfig,
|
|
86
|
+
compiler: {
|
|
87
|
+
...nextConfig.compiler,
|
|
88
|
+
defineServer: {
|
|
89
|
+
__RELAY_CORE_VERSION__: CORE_VERSION_DEFINE,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return nextConfig;
|
|
95
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orionfold-relay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Orionfold Relay — a local-first, multi-agent orchestration runtime and builder scaffold for AI-native work.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"test:e2e": "vitest run --config vitest.config.e2e.ts",
|
|
69
69
|
"test:ui": "vitest --ui",
|
|
70
70
|
"validate:tokens": "npx tsx design-system/validate-tokens.ts",
|
|
71
|
+
"check:price-drift": "node scripts/check-price-drift.mjs",
|
|
71
72
|
"sync-worktree": "bash bin/sync-worktree.sh",
|
|
72
73
|
"prepublishOnly": "npm run build:cli"
|
|
73
74
|
},
|
package/src/app/apps/page.tsx
CHANGED
|
@@ -100,7 +100,7 @@ function EmptyHero({ starters }: { starters: ReturnType<typeof listStarters> })
|
|
|
100
100
|
<Sparkles className="h-10 w-10 text-primary mb-4" aria-hidden="true" />
|
|
101
101
|
<h2 className="text-lg font-semibold">Teach this instance a new job.</h2>
|
|
102
102
|
<p className="mt-2 max-w-md text-sm text-muted-foreground">
|
|
103
|
-
Describe the thing you do every week. Orionfold Relay composes a profile, blueprint, schedule, and tables into a running app
|
|
103
|
+
Describe the thing you do every week. Orionfold Relay composes a profile, blueprint, schedule, and tables into a running app. No code, no deploys.
|
|
104
104
|
</p>
|
|
105
105
|
<div className="mt-4 flex items-center gap-4">
|
|
106
106
|
<Link
|
package/src/app/inbox/page.tsx
CHANGED
|
@@ -69,7 +69,7 @@ export default async function InboxPage() {
|
|
|
69
69
|
return (
|
|
70
70
|
<PageShell
|
|
71
71
|
title="Inbox"
|
|
72
|
-
description="Governance command center
|
|
72
|
+
description="Governance command center. Review approvals, questions, and agent activity."
|
|
73
73
|
>
|
|
74
74
|
<GovernanceStats
|
|
75
75
|
pending={pendingCount}
|
package/src/app/layout.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import { ChatSessionProvider } from "@/components/chat/chat-session-provider";
|
|
|
12
12
|
import { RuntimePreferenceBootstrapper } from "@/components/onboarding/runtime-preference-bootstrapper";
|
|
13
13
|
import {
|
|
14
14
|
DEFAULT_THEME,
|
|
15
|
+
LEGACY_THEME_COOKIE,
|
|
15
16
|
THEME_COOKIE,
|
|
16
17
|
isResolvedTheme,
|
|
17
18
|
type ResolvedTheme,
|
|
@@ -82,12 +83,16 @@ export default async function RootLayout({
|
|
|
82
83
|
}: {
|
|
83
84
|
children: React.ReactNode;
|
|
84
85
|
}) {
|
|
85
|
-
// Resolve theme server-side from the
|
|
86
|
+
// Resolve theme server-side from the relay-theme cookie. Every client-side
|
|
86
87
|
// theme toggle writes this cookie (see src/lib/theme.ts), so SSR stays in
|
|
87
88
|
// sync with the user's preference and there is no FOUC — and no pre-hydration
|
|
88
|
-
// <script> tag, which is what React 19 warns about.
|
|
89
|
+
// <script> tag, which is what React 19 warns about. Fall back to the legacy
|
|
90
|
+
// ainative-theme cookie so a returning pre-rebrand user does not flash the
|
|
91
|
+
// default theme before the client re-writes the new cookie.
|
|
89
92
|
const cookieStore = await cookies();
|
|
90
|
-
const cookieValue =
|
|
93
|
+
const cookieValue =
|
|
94
|
+
cookieStore.get(THEME_COOKIE)?.value ??
|
|
95
|
+
cookieStore.get(LEGACY_THEME_COOKIE)?.value;
|
|
91
96
|
const theme: ResolvedTheme = isResolvedTheme(cookieValue)
|
|
92
97
|
? cookieValue
|
|
93
98
|
: DEFAULT_THEME;
|
package/src/app/packs/page.tsx
CHANGED
|
@@ -81,7 +81,7 @@ export default async function PacksPage({
|
|
|
81
81
|
return (
|
|
82
82
|
<PageShell
|
|
83
83
|
title="Packs"
|
|
84
|
-
description="Vertical content bundles
|
|
84
|
+
description="Vertical content bundles. An app, profiles, blueprints, tables, and seed data installed in one step."
|
|
85
85
|
filters={
|
|
86
86
|
templates.length > 1 ? (
|
|
87
87
|
<FilterChips active={filter} counts={counts} />
|
|
@@ -11,7 +11,6 @@ import Link from "next/link";
|
|
|
11
11
|
import { FileText } from "lucide-react";
|
|
12
12
|
import { Sparkline } from "@/components/charts/sparkline";
|
|
13
13
|
import { getProjectCompletionTrend } from "@/lib/queries/chart-data";
|
|
14
|
-
import { EnvironmentSummaryCard } from "@/components/environment/environment-summary-card";
|
|
15
14
|
|
|
16
15
|
export const dynamic = "force-dynamic";
|
|
17
16
|
|
|
@@ -160,16 +159,6 @@ export default async function ProjectDetailPage({
|
|
|
160
159
|
</div>
|
|
161
160
|
)}
|
|
162
161
|
|
|
163
|
-
{/* Environment summary */}
|
|
164
|
-
{project.workingDirectory && (
|
|
165
|
-
<div className="mb-6">
|
|
166
|
-
<EnvironmentSummaryCard
|
|
167
|
-
projectId={id}
|
|
168
|
-
workingDirectory={project.workingDirectory}
|
|
169
|
-
/>
|
|
170
|
-
</div>
|
|
171
|
-
)}
|
|
172
|
-
|
|
173
162
|
{/* Recent documents */}
|
|
174
163
|
{recentDocs.length > 0 && (
|
|
175
164
|
<div className="mb-6">
|
|
@@ -100,7 +100,7 @@ function HeroVariant({ task, previousRuns }: HeroProps) {
|
|
|
100
100
|
if (!task) {
|
|
101
101
|
return (
|
|
102
102
|
<div className="surface-card rounded-xl p-6 text-center text-muted-foreground border">
|
|
103
|
-
No digest yet
|
|
103
|
+
No digest yet. Click <strong>Run now</strong> to generate the first one.
|
|
104
104
|
</div>
|
|
105
105
|
);
|
|
106
106
|
}
|
|
@@ -15,7 +15,7 @@ export function LedgerHeroPanel({ series, categories, period }: LedgerHeroPanelP
|
|
|
15
15
|
if (series.length === 0 && categories.length === 0) {
|
|
16
16
|
return (
|
|
17
17
|
<div className="surface-card rounded-xl p-12 text-center text-muted-foreground border">
|
|
18
|
-
No data yet
|
|
18
|
+
No data yet. Add transactions or click <strong>Run now</strong> to ingest a CSV.
|
|
19
19
|
</div>
|
|
20
20
|
);
|
|
21
21
|
}
|
|
@@ -137,7 +137,7 @@ export function AppMaterializedCard({
|
|
|
137
137
|
))}
|
|
138
138
|
</ul>
|
|
139
139
|
<p className="text-[11px] text-muted-foreground/60 pt-1">
|
|
140
|
-
Informational
|
|
140
|
+
Informational. These files are written under your control. No approval required.
|
|
141
141
|
</p>
|
|
142
142
|
</div>
|
|
143
143
|
)}
|
|
@@ -193,7 +193,7 @@ export function AppViewEditorCard({
|
|
|
193
193
|
</p>
|
|
194
194
|
)}
|
|
195
195
|
{status === "cancelled" && (
|
|
196
|
-
<p className="text-xs text-muted-foreground">Cancelled
|
|
196
|
+
<p className="text-xs text-muted-foreground">Cancelled. No changes written.</p>
|
|
197
197
|
)}
|
|
198
198
|
{status === "failed" && errorMessage && (
|
|
199
199
|
<p className="text-xs text-destructive">Failed: {errorMessage}</p>
|
|
@@ -176,7 +176,7 @@ export function ChatCommandPopover({
|
|
|
176
176
|
const activeCount = Array.isArray(body.activeSkillIds)
|
|
177
177
|
? (body.activeSkillIds as string[]).length
|
|
178
178
|
: 1;
|
|
179
|
-
toast.success(`Added ${skillName}
|
|
179
|
+
toast.success(`Added ${skillName}. ${activeCount} skill${activeCount !== 1 ? "s" : ""} active`);
|
|
180
180
|
},
|
|
181
181
|
[conversationId, refetchActive]
|
|
182
182
|
);
|
|
@@ -494,7 +494,7 @@ function ToolCatalogItems({
|
|
|
494
494
|
const showDisabled = !isActive && !canAdd && !!onAddSkill;
|
|
495
495
|
const disabledReason = atCapacity
|
|
496
496
|
? `Max ${resolvedMax} skills active`
|
|
497
|
-
: "Single skill only on this runtime
|
|
497
|
+
: "Single skill only on this runtime. Switch runtime to compose";
|
|
498
498
|
|
|
499
499
|
return (
|
|
500
500
|
<SkillRow
|
|
@@ -99,7 +99,7 @@ export function ChatEmptyState({
|
|
|
99
99
|
</div>
|
|
100
100
|
<h2 className="text-lg font-semibold">Describe an app. Orionfold Relay builds it.</h2>
|
|
101
101
|
<p className="text-sm text-muted-foreground text-center max-w-md">
|
|
102
|
-
Profiles, blueprints, tables, and schedules
|
|
102
|
+
Profiles, blueprints, tables, and schedules, composed from a single prompt.
|
|
103
103
|
Or ask anything about your workspace.
|
|
104
104
|
</p>
|
|
105
105
|
</div>
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { AlertCircle } from "lucide-react";
|
|
19
19
|
import { resolveModelLabel, type ChatQuestion, type QuickAccessItem, type ScreenshotAttachment } from "@/lib/chat/types";
|
|
20
20
|
import type { ComposedAppSummary } from "@/lib/apps/composition-detector";
|
|
21
|
+
import { APPS_CHANGED_EVENT } from "@/lib/apps/apps-events";
|
|
21
22
|
|
|
22
23
|
interface ExtensionFallbackSummary {
|
|
23
24
|
plugin: CreatePluginSpecInputForCard;
|
|
@@ -56,7 +57,7 @@ function ComposedAppCard({ app }: { app: ComposedAppSummary }) {
|
|
|
56
57
|
});
|
|
57
58
|
if (res.ok) {
|
|
58
59
|
setAppStatus("undone");
|
|
59
|
-
window.dispatchEvent(new CustomEvent(
|
|
60
|
+
window.dispatchEvent(new CustomEvent(APPS_CHANGED_EVENT));
|
|
60
61
|
}
|
|
61
62
|
}, [app.appId]);
|
|
62
63
|
|
|
@@ -331,7 +331,7 @@ export function ChatSessionProvider({ children }: { children: ReactNode }) {
|
|
|
331
331
|
void createConversation();
|
|
332
332
|
};
|
|
333
333
|
const handleCompact = () => {
|
|
334
|
-
toast.info("Compact is not wired yet
|
|
334
|
+
toast.info("Compact is not wired yet. Coming soon.");
|
|
335
335
|
};
|
|
336
336
|
const handleExport = async () => {
|
|
337
337
|
const activeConversationId = activeIdRef.current;
|
|
@@ -339,7 +339,7 @@ export function ChatSessionProvider({ children }: { children: ReactNode }) {
|
|
|
339
339
|
? messagesByConversationRef.current[activeConversationId]
|
|
340
340
|
: undefined;
|
|
341
341
|
if (!msgs || msgs.length === 0) {
|
|
342
|
-
toast.error("Nothing to export
|
|
342
|
+
toast.error("Nothing to export. This conversation is empty.");
|
|
343
343
|
return;
|
|
344
344
|
}
|
|
345
345
|
const title = `Chat — ${new Date().toISOString().slice(0, 10)}`;
|
|
@@ -325,7 +325,7 @@ function ParameterForm({
|
|
|
325
325
|
if (blueprint.variables.length === 0) {
|
|
326
326
|
return (
|
|
327
327
|
<p className="text-sm text-muted-foreground">
|
|
328
|
-
This blueprint has no parameters
|
|
328
|
+
This blueprint has no parameters. Starting a conversation now.
|
|
329
329
|
</p>
|
|
330
330
|
);
|
|
331
331
|
}
|
|
@@ -49,11 +49,6 @@ export function SkillRow({
|
|
|
49
49
|
addButton,
|
|
50
50
|
onDeactivate,
|
|
51
51
|
}: SkillRowProps) {
|
|
52
|
-
const syncHref =
|
|
53
|
-
skill.syncStatus !== "synced"
|
|
54
|
-
? `/environment?skill=${encodeURIComponent(skill.name)}`
|
|
55
|
-
: null;
|
|
56
|
-
|
|
57
52
|
return (
|
|
58
53
|
<CommandItem
|
|
59
54
|
key={skill.id}
|
|
@@ -112,7 +107,7 @@ export function SkillRow({
|
|
|
112
107
|
</Badge>
|
|
113
108
|
</div>
|
|
114
109
|
</div>
|
|
115
|
-
{/* Right-side slot:
|
|
110
|
+
{/* Right-side slot: the Add or Deactivate button. */}
|
|
116
111
|
{isActive && onDeactivate ? (
|
|
117
112
|
<button
|
|
118
113
|
type="button"
|
|
@@ -132,15 +127,6 @@ export function SkillRow({
|
|
|
132
127
|
</button>
|
|
133
128
|
) : addButton ? (
|
|
134
129
|
addButton
|
|
135
|
-
) : syncHref ? (
|
|
136
|
-
<a
|
|
137
|
-
href={syncHref}
|
|
138
|
-
aria-label={`Open ${skill.name} in environment dashboard`}
|
|
139
|
-
className="ml-auto shrink-0 text-muted-foreground hover:text-foreground"
|
|
140
|
-
onClick={(e) => e.stopPropagation()}
|
|
141
|
-
>
|
|
142
|
-
↗
|
|
143
|
-
</a>
|
|
144
130
|
) : null}
|
|
145
131
|
</CommandItem>
|
|
146
132
|
);
|
|
@@ -140,7 +140,7 @@ export function CustomerFormSheet({
|
|
|
140
140
|
id="customer-slug"
|
|
141
141
|
value={slug}
|
|
142
142
|
onChange={(e) => setSlug(e.target.value)}
|
|
143
|
-
placeholder="meridian-cre
|
|
143
|
+
placeholder="meridian-cre (derived from name if blank)"
|
|
144
144
|
/>
|
|
145
145
|
<p className="text-xs text-muted-foreground">
|
|
146
146
|
Lowercase letters, numbers, and hyphens. Immutable once set.
|
|
@@ -21,7 +21,7 @@ export function Greeting({ runningCount, awaitingCount, failedCount, activeWorkf
|
|
|
21
21
|
|
|
22
22
|
const summary = parts.length > 0
|
|
23
23
|
? `You have ${parts.join(", ")}.`
|
|
24
|
-
: "All clear
|
|
24
|
+
: "All clear. No tasks need your attention.";
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<div className="surface-card rounded-lg p-5 mb-6">
|
|
@@ -9,7 +9,7 @@ const pillars = [
|
|
|
9
9
|
{
|
|
10
10
|
icon: Sparkles,
|
|
11
11
|
title: "Apps from a sentence",
|
|
12
|
-
description: "Describe what you do every week. Orionfold Relay composes the profile, blueprint, schedule, and tables into a running app
|
|
12
|
+
description: "Describe what you do every week. Orionfold Relay composes the profile, blueprint, schedule, and tables into a running app. No code.",
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
icon: Shield,
|
|
@@ -44,7 +44,7 @@ export function WelcomeLanding({ starters = [] }: WelcomeLandingProps) {
|
|
|
44
44
|
Welcome
|
|
45
45
|
</h1>
|
|
46
46
|
<p className="text-base text-muted-foreground mb-8 max-w-lg">
|
|
47
|
-
Your AI Business Operating System. Describe an app, Orionfold Relay builds it
|
|
47
|
+
Your AI Business Operating System. Describe an app, Orionfold Relay builds it, and runs it on your rules, your budget, your data.
|
|
48
48
|
</p>
|
|
49
49
|
|
|
50
50
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 w-full mb-8">
|
|
@@ -86,7 +86,7 @@ export function DocumentUploadDialog({
|
|
|
86
86
|
<div
|
|
87
87
|
role="button"
|
|
88
88
|
tabIndex={0}
|
|
89
|
-
aria-label="Upload files
|
|
89
|
+
aria-label="Upload files. Click or drag and drop"
|
|
90
90
|
className="border-2 border-dashed border-border rounded-lg p-8 text-center cursor-pointer hover:bg-accent/50 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
91
91
|
onClick={() => inputRef.current?.click()}
|
|
92
92
|
onKeyDown={(e) => {
|
|
@@ -35,7 +35,7 @@ export function SmartExtractedText({ text }: SmartExtractedTextProps) {
|
|
|
35
35
|
return (
|
|
36
36
|
<div className="space-y-3">
|
|
37
37
|
<p className="text-xs text-muted-foreground italic">
|
|
38
|
-
Extracted text
|
|
38
|
+
Extracted text. Original formatting may differ
|
|
39
39
|
</p>
|
|
40
40
|
<div className={PROSE_READER}>
|
|
41
41
|
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
|
@@ -269,7 +269,7 @@ export function InstanceSection() {
|
|
|
269
269
|
const startUpgradeDisabled = busy !== null || !upgradeAvailable;
|
|
270
270
|
const startUpgradeTitle = upgradeAvailable
|
|
271
271
|
? `Merge ${upgradeCount} upstream commit${upgradeCount === 1 ? "" : "s"} into ${config!.branchName}`
|
|
272
|
-
: "No upgrades available
|
|
272
|
+
: "No upgrades available. Click 'Check for upgrades' to refresh";
|
|
273
273
|
const statusMessage = pollFailing && upgrade?.lastPollError
|
|
274
274
|
? upgrade.lastPollError
|
|
275
275
|
: message;
|
|
@@ -131,7 +131,7 @@ export function UpgradeBadge() {
|
|
|
131
131
|
? "Check failing"
|
|
132
132
|
: `${count} update${count === 1 ? "" : "s"}`;
|
|
133
133
|
const tooltip = failing
|
|
134
|
-
? "Upgrade check failing
|
|
134
|
+
? "Upgrade check failing. Click to retry"
|
|
135
135
|
: `${count} upstream update${count === 1 ? "" : "s"} ready to merge`;
|
|
136
136
|
const buttonClass = failing
|
|
137
137
|
? "h-7 px-2 rounded-md border border-amber-500/40 bg-amber-500/10 text-[11px] font-medium text-amber-700 dark:text-amber-400 hover:bg-amber-500/20 transition-colors cursor-pointer inline-flex items-center gap-1.5 group-data-[collapsible=icon]:hidden"
|
|
@@ -121,7 +121,7 @@ export function BatchProposalReview({
|
|
|
121
121
|
<CardHeader className="pb-3">
|
|
122
122
|
<CardTitle className="text-sm flex items-center gap-2">
|
|
123
123
|
<Brain className="h-4 w-4" />
|
|
124
|
-
Workflow Learning
|
|
124
|
+
Workflow Learning: {proposalIds.length} Proposals
|
|
125
125
|
</CardTitle>
|
|
126
126
|
</CardHeader>
|
|
127
127
|
<CardContent className="space-y-4">
|