@toothfairyai/tfdesign 0.4.4 → 0.4.6
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.
|
@@ -9,8 +9,8 @@ import { execFile as execFile5, spawn as spawn3 } from "node:child_process";
|
|
|
9
9
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
12
|
-
import
|
|
13
|
-
import
|
|
12
|
+
import path29 from "node:path";
|
|
13
|
+
import fs8 from "node:fs";
|
|
14
14
|
import os4 from "node:os";
|
|
15
15
|
import net2 from "node:net";
|
|
16
16
|
|
|
@@ -6495,8 +6495,8 @@ function getErrorMap() {
|
|
|
6495
6495
|
|
|
6496
6496
|
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
6497
6497
|
var makeIssue = (params) => {
|
|
6498
|
-
const { data, path:
|
|
6499
|
-
const fullPath = [...
|
|
6498
|
+
const { data, path: path30, errorMaps, issueData } = params;
|
|
6499
|
+
const fullPath = [...path30, ...issueData.path || []];
|
|
6500
6500
|
const fullIssue = {
|
|
6501
6501
|
...issueData,
|
|
6502
6502
|
path: fullPath
|
|
@@ -6612,11 +6612,11 @@ var errorUtil;
|
|
|
6612
6612
|
|
|
6613
6613
|
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
6614
6614
|
var ParseInputLazyPath = class {
|
|
6615
|
-
constructor(parent, value,
|
|
6615
|
+
constructor(parent, value, path30, key) {
|
|
6616
6616
|
this._cachedPath = [];
|
|
6617
6617
|
this.parent = parent;
|
|
6618
6618
|
this.data = value;
|
|
6619
|
-
this._path =
|
|
6619
|
+
this._path = path30;
|
|
6620
6620
|
this._key = key;
|
|
6621
6621
|
}
|
|
6622
6622
|
get path() {
|
|
@@ -14368,9 +14368,9 @@ function parseDeclarations(body) {
|
|
|
14368
14368
|
return out;
|
|
14369
14369
|
}
|
|
14370
14370
|
function resolveFontSizePx(decls) {
|
|
14371
|
-
const
|
|
14372
|
-
if (!
|
|
14373
|
-
const m = /^(-?\d*\.?\d+)\s*(px|rem)\b/i.exec(
|
|
14371
|
+
const fs9 = findLastDecl(decls, "font-size");
|
|
14372
|
+
if (!fs9) return null;
|
|
14373
|
+
const m = /^(-?\d*\.?\d+)\s*(px|rem)\b/i.exec(fs9.value);
|
|
14374
14374
|
if (!m) return null;
|
|
14375
14375
|
const v = parseFloat(m[1]);
|
|
14376
14376
|
const unit = m[2].toLowerCase();
|
|
@@ -16959,37 +16959,37 @@ function isPlainObject2(value) {
|
|
|
16959
16959
|
const proto = Object.getPrototypeOf(value);
|
|
16960
16960
|
return proto === Object.prototype || proto === null;
|
|
16961
16961
|
}
|
|
16962
|
-
function asString(value,
|
|
16962
|
+
function asString(value, path30, issues, max = MAX_SHORT_TEXT_LENGTH) {
|
|
16963
16963
|
if (typeof value !== "string") {
|
|
16964
|
-
issues.push({ path:
|
|
16964
|
+
issues.push({ path: path30, message: `${path30} must be a string` });
|
|
16965
16965
|
return void 0;
|
|
16966
16966
|
}
|
|
16967
16967
|
if (value.length === 0) {
|
|
16968
|
-
issues.push({ path:
|
|
16968
|
+
issues.push({ path: path30, message: `${path30} is required` });
|
|
16969
16969
|
}
|
|
16970
16970
|
if (value.length > max) {
|
|
16971
|
-
issues.push({ path:
|
|
16971
|
+
issues.push({ path: path30, message: `${path30} exceeds max length (${max})` });
|
|
16972
16972
|
}
|
|
16973
16973
|
return value;
|
|
16974
16974
|
}
|
|
16975
|
-
function asOptionalString(value,
|
|
16975
|
+
function asOptionalString(value, path30, issues, max = MAX_SHORT_TEXT_LENGTH) {
|
|
16976
16976
|
if (value === void 0) return void 0;
|
|
16977
|
-
return asString(value,
|
|
16977
|
+
return asString(value, path30, issues, max);
|
|
16978
16978
|
}
|
|
16979
|
-
function asBoolean(value,
|
|
16979
|
+
function asBoolean(value, path30, issues) {
|
|
16980
16980
|
if (typeof value !== "boolean") {
|
|
16981
|
-
issues.push({ path:
|
|
16981
|
+
issues.push({ path: path30, message: `${path30} must be a boolean` });
|
|
16982
16982
|
return void 0;
|
|
16983
16983
|
}
|
|
16984
16984
|
return value;
|
|
16985
16985
|
}
|
|
16986
|
-
function asOptionalBoolean(value,
|
|
16986
|
+
function asOptionalBoolean(value, path30, issues) {
|
|
16987
16987
|
if (value === void 0) return void 0;
|
|
16988
|
-
return asBoolean(value,
|
|
16988
|
+
return asBoolean(value, path30, issues);
|
|
16989
16989
|
}
|
|
16990
|
-
function validateEnum(value, allowed,
|
|
16990
|
+
function validateEnum(value, allowed, path30, issues) {
|
|
16991
16991
|
if (typeof value !== "string" || !allowed.has(value)) {
|
|
16992
|
-
issues.push({ path:
|
|
16992
|
+
issues.push({ path: path30, message: `${path30} is not allowed` });
|
|
16993
16993
|
return void 0;
|
|
16994
16994
|
}
|
|
16995
16995
|
return value;
|
|
@@ -16998,26 +16998,26 @@ function isIsoDateString(value) {
|
|
|
16998
16998
|
const time = Date.parse(value);
|
|
16999
16999
|
return Number.isFinite(time) && new Date(time).toISOString() === value;
|
|
17000
17000
|
}
|
|
17001
|
-
function validateIsoDate(value,
|
|
17002
|
-
const text = asString(value,
|
|
17001
|
+
function validateIsoDate(value, path30, issues) {
|
|
17002
|
+
const text = asString(value, path30, issues, MAX_SHORT_TEXT_LENGTH);
|
|
17003
17003
|
if (text !== void 0 && !isIsoDateString(text)) {
|
|
17004
|
-
issues.push({ path:
|
|
17004
|
+
issues.push({ path: path30, message: `${path30} must be an ISO-8601 timestamp` });
|
|
17005
17005
|
}
|
|
17006
17006
|
return text;
|
|
17007
17007
|
}
|
|
17008
|
-
function validateRelativePath(value,
|
|
17008
|
+
function validateRelativePath(value, path30, issues) {
|
|
17009
17009
|
if (value.length > MAX_PATH_LENGTH) {
|
|
17010
|
-
issues.push({ path:
|
|
17010
|
+
issues.push({ path: path30, message: `${path30} exceeds max length (${MAX_PATH_LENGTH})` });
|
|
17011
17011
|
}
|
|
17012
17012
|
if (value.includes("\0")) {
|
|
17013
|
-
issues.push({ path:
|
|
17013
|
+
issues.push({ path: path30, message: `${path30} cannot contain null bytes` });
|
|
17014
17014
|
}
|
|
17015
17015
|
const normalized = value.replace(/\\/g, "/");
|
|
17016
17016
|
if (normalized.startsWith("/") || /^[A-Za-z]:/.test(normalized)) {
|
|
17017
|
-
issues.push({ path:
|
|
17017
|
+
issues.push({ path: path30, message: `${path30} cannot be an absolute path` });
|
|
17018
17018
|
}
|
|
17019
17019
|
if (normalized.split("/").some((part) => part === "..")) {
|
|
17020
|
-
issues.push({ path:
|
|
17020
|
+
issues.push({ path: path30, message: `${path30} cannot contain path traversal` });
|
|
17021
17021
|
}
|
|
17022
17022
|
}
|
|
17023
17023
|
function validateNoDaemonOwnedFields(raw, issues) {
|
|
@@ -17027,17 +17027,17 @@ function validateNoDaemonOwnedFields(raw, issues) {
|
|
|
17027
17027
|
}
|
|
17028
17028
|
}
|
|
17029
17029
|
}
|
|
17030
|
-
function validateOnlyAllowedKeys(raw, allowed,
|
|
17030
|
+
function validateOnlyAllowedKeys(raw, allowed, path30, issues) {
|
|
17031
17031
|
for (const key of Object.keys(raw)) {
|
|
17032
17032
|
if (!allowed.has(key)) {
|
|
17033
|
-
issues.push({ path: `${
|
|
17033
|
+
issues.push({ path: `${path30}.${key}`, message: `${path30}.${key} is not allowed` });
|
|
17034
17034
|
}
|
|
17035
17035
|
}
|
|
17036
17036
|
}
|
|
17037
|
-
function validateBoundedJsonInternal(value,
|
|
17037
|
+
function validateBoundedJsonInternal(value, path30, issues, depth) {
|
|
17038
17038
|
if (value === null || typeof value === "boolean" || typeof value === "number") {
|
|
17039
17039
|
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
17040
|
-
issues.push({ path:
|
|
17040
|
+
issues.push({ path: path30, message: `${path30} must be a finite number` });
|
|
17041
17041
|
return false;
|
|
17042
17042
|
}
|
|
17043
17043
|
return true;
|
|
@@ -17045,8 +17045,8 @@ function validateBoundedJsonInternal(value, path29, issues, depth) {
|
|
|
17045
17045
|
if (typeof value === "string") {
|
|
17046
17046
|
if (value.length > LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxStringLength) {
|
|
17047
17047
|
issues.push({
|
|
17048
|
-
path:
|
|
17049
|
-
message: `${
|
|
17048
|
+
path: path30,
|
|
17049
|
+
message: `${path30} exceeds max string length (${LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxStringLength})`
|
|
17050
17050
|
});
|
|
17051
17051
|
return false;
|
|
17052
17052
|
}
|
|
@@ -17054,128 +17054,128 @@ function validateBoundedJsonInternal(value, path29, issues, depth) {
|
|
|
17054
17054
|
}
|
|
17055
17055
|
if (Array.isArray(value)) {
|
|
17056
17056
|
if (depth > LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxDepth) {
|
|
17057
|
-
issues.push({ path:
|
|
17057
|
+
issues.push({ path: path30, message: `${path30} exceeds max JSON depth (${LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxDepth})` });
|
|
17058
17058
|
return false;
|
|
17059
17059
|
}
|
|
17060
17060
|
if (value.length > LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxArrayLength) {
|
|
17061
17061
|
issues.push({
|
|
17062
|
-
path:
|
|
17063
|
-
message: `${
|
|
17062
|
+
path: path30,
|
|
17063
|
+
message: `${path30} exceeds max array length (${LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxArrayLength})`
|
|
17064
17064
|
});
|
|
17065
17065
|
return false;
|
|
17066
17066
|
}
|
|
17067
|
-
return value.every((item, index) => validateBoundedJsonInternal(item, `${
|
|
17067
|
+
return value.every((item, index) => validateBoundedJsonInternal(item, `${path30}.${index}`, issues, depth + 1));
|
|
17068
17068
|
}
|
|
17069
17069
|
if (isPlainObject2(value)) {
|
|
17070
17070
|
if (depth > LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxDepth) {
|
|
17071
|
-
issues.push({ path:
|
|
17071
|
+
issues.push({ path: path30, message: `${path30} exceeds max JSON depth (${LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxDepth})` });
|
|
17072
17072
|
return false;
|
|
17073
17073
|
}
|
|
17074
17074
|
const entries = Object.entries(value);
|
|
17075
17075
|
if (entries.length > LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxObjectKeys) {
|
|
17076
17076
|
issues.push({
|
|
17077
|
-
path:
|
|
17078
|
-
message: `${
|
|
17077
|
+
path: path30,
|
|
17078
|
+
message: `${path30} exceeds max object keys (${LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxObjectKeys})`
|
|
17079
17079
|
});
|
|
17080
17080
|
return false;
|
|
17081
17081
|
}
|
|
17082
17082
|
let valid = true;
|
|
17083
17083
|
for (const [key, child] of entries) {
|
|
17084
17084
|
if (FORBIDDEN_JSON_KEYS.has(key.toLowerCase())) {
|
|
17085
|
-
issues.push({ path: `${
|
|
17085
|
+
issues.push({ path: `${path30}.${key}`, message: `${path30}.${key} uses a forbidden key` });
|
|
17086
17086
|
valid = false;
|
|
17087
17087
|
}
|
|
17088
|
-
valid = validateBoundedJsonInternal(child, `${
|
|
17088
|
+
valid = validateBoundedJsonInternal(child, `${path30}.${key}`, issues, depth + 1) && valid;
|
|
17089
17089
|
}
|
|
17090
17090
|
return valid;
|
|
17091
17091
|
}
|
|
17092
|
-
issues.push({ path:
|
|
17092
|
+
issues.push({ path: path30, message: `${path30} must be JSON-serializable` });
|
|
17093
17093
|
return false;
|
|
17094
17094
|
}
|
|
17095
|
-
function validateBoundedJsonValue(value,
|
|
17095
|
+
function validateBoundedJsonValue(value, path30 = "value") {
|
|
17096
17096
|
const issues = [];
|
|
17097
|
-
if (validateBoundedJsonInternal(value,
|
|
17097
|
+
if (validateBoundedJsonInternal(value, path30, issues, 1)) {
|
|
17098
17098
|
const serialized = JSON.stringify(value);
|
|
17099
17099
|
if (Buffer.byteLength(serialized, "utf8") <= LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxSerializedBytes) {
|
|
17100
17100
|
return ok(value);
|
|
17101
17101
|
}
|
|
17102
17102
|
issues.push({
|
|
17103
|
-
path:
|
|
17104
|
-
message: `${
|
|
17103
|
+
path: path30,
|
|
17104
|
+
message: `${path30} exceeds max serialized size (${LIVE_ARTIFACT_BOUNDED_JSON_CONSTRAINTS.maxSerializedBytes} bytes)`
|
|
17105
17105
|
});
|
|
17106
17106
|
}
|
|
17107
17107
|
return fail(issues);
|
|
17108
17108
|
}
|
|
17109
|
-
function validateBoundedJsonObject(value,
|
|
17110
|
-
const result = validateBoundedJsonValue(value,
|
|
17109
|
+
function validateBoundedJsonObject(value, path30 = "value") {
|
|
17110
|
+
const result = validateBoundedJsonValue(value, path30);
|
|
17111
17111
|
if (!result.ok) return result;
|
|
17112
17112
|
if (!isPlainObject2(result.value)) {
|
|
17113
|
-
return fail([{ path:
|
|
17113
|
+
return fail([{ path: path30, message: `${path30} must be a JSON object` }]);
|
|
17114
17114
|
}
|
|
17115
17115
|
return ok(result.value);
|
|
17116
17116
|
}
|
|
17117
|
-
function validateSourceInputPaths(value,
|
|
17117
|
+
function validateSourceInputPaths(value, path30, issues) {
|
|
17118
17118
|
if (typeof value === "string") {
|
|
17119
|
-
validateRelativePath(value,
|
|
17119
|
+
validateRelativePath(value, path30, issues);
|
|
17120
17120
|
return;
|
|
17121
17121
|
}
|
|
17122
17122
|
if (Array.isArray(value)) {
|
|
17123
|
-
value.forEach((item, index) => validateSourceInputPaths(item, `${
|
|
17123
|
+
value.forEach((item, index) => validateSourceInputPaths(item, `${path30}.${index}`, issues));
|
|
17124
17124
|
return;
|
|
17125
17125
|
}
|
|
17126
17126
|
if (isPlainObject2(value)) {
|
|
17127
17127
|
for (const [key, child] of Object.entries(value)) {
|
|
17128
|
-
if (/path|file|glob|ref/i.test(key)) validateSourceInputPaths(child, `${
|
|
17128
|
+
if (/path|file|glob|ref/i.test(key)) validateSourceInputPaths(child, `${path30}.${key}`, issues);
|
|
17129
17129
|
}
|
|
17130
17130
|
}
|
|
17131
17131
|
}
|
|
17132
|
-
function validatePreview(value,
|
|
17132
|
+
function validatePreview(value, path30, issues) {
|
|
17133
17133
|
if (!isPlainObject2(value)) {
|
|
17134
|
-
issues.push({ path:
|
|
17134
|
+
issues.push({ path: path30, message: `${path30} must be an object` });
|
|
17135
17135
|
return void 0;
|
|
17136
17136
|
}
|
|
17137
|
-
const type = validateEnum(value.type, PREVIEW_TYPES, `${
|
|
17138
|
-
const entry = asString(value.entry, `${
|
|
17139
|
-
if (entry !== void 0) validateRelativePath(entry, `${
|
|
17137
|
+
const type = validateEnum(value.type, PREVIEW_TYPES, `${path30}.type`, issues);
|
|
17138
|
+
const entry = asString(value.entry, `${path30}.entry`, issues, MAX_PATH_LENGTH);
|
|
17139
|
+
if (entry !== void 0) validateRelativePath(entry, `${path30}.entry`, issues);
|
|
17140
17140
|
if (type === void 0 || entry === void 0) return void 0;
|
|
17141
17141
|
return { type, entry };
|
|
17142
17142
|
}
|
|
17143
17143
|
var SAFE_MAPPING_SEGMENT = /^[A-Za-z_][A-Za-z0-9_-]*$|^(?:0|[1-9][0-9]*)$/;
|
|
17144
17144
|
var UNSAFE_MAPPING_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
17145
|
-
function validateMappingPath(value,
|
|
17145
|
+
function validateMappingPath(value, path30, issues) {
|
|
17146
17146
|
const normalized = value.startsWith("$.") ? value.slice(2) : value;
|
|
17147
17147
|
if (normalized.length === 0 || normalized.startsWith(".") || normalized.endsWith(".") || normalized.includes("..")) {
|
|
17148
|
-
issues.push({ path:
|
|
17148
|
+
issues.push({ path: path30, message: `${path30} must be a dot-separated JSON path` });
|
|
17149
17149
|
return;
|
|
17150
17150
|
}
|
|
17151
17151
|
for (const segment of normalized.split(".")) {
|
|
17152
17152
|
if (!SAFE_MAPPING_SEGMENT.test(segment) || UNSAFE_MAPPING_SEGMENTS.has(segment)) {
|
|
17153
|
-
issues.push({ path:
|
|
17153
|
+
issues.push({ path: path30, message: `${path30} contains unsupported JSON path segment: ${segment}` });
|
|
17154
17154
|
return;
|
|
17155
17155
|
}
|
|
17156
17156
|
}
|
|
17157
17157
|
}
|
|
17158
|
-
function validateSource(value,
|
|
17158
|
+
function validateSource(value, path30, issues) {
|
|
17159
17159
|
if (!isPlainObject2(value)) {
|
|
17160
|
-
issues.push({ path:
|
|
17160
|
+
issues.push({ path: path30, message: `${path30} must be an object` });
|
|
17161
17161
|
return void 0;
|
|
17162
17162
|
}
|
|
17163
|
-
validateOnlyAllowedKeys(value, SOURCE_KEYS,
|
|
17164
|
-
const type = validateEnum(value.type, SOURCE_TYPES, `${
|
|
17165
|
-
const toolName = asOptionalString(value.toolName, `${
|
|
17166
|
-
const inputResult = validateBoundedJsonObject(value.input, `${
|
|
17163
|
+
validateOnlyAllowedKeys(value, SOURCE_KEYS, path30, issues);
|
|
17164
|
+
const type = validateEnum(value.type, SOURCE_TYPES, `${path30}.type`, issues);
|
|
17165
|
+
const toolName = asOptionalString(value.toolName, `${path30}.toolName`, issues, MAX_ID_LENGTH);
|
|
17166
|
+
const inputResult = validateBoundedJsonObject(value.input, `${path30}.input`);
|
|
17167
17167
|
if (!inputResult.ok) issues.push(...inputResult.issues);
|
|
17168
|
-
else validateSourceInputPaths(inputResult.value, `${
|
|
17168
|
+
else validateSourceInputPaths(inputResult.value, `${path30}.input`, issues);
|
|
17169
17169
|
let connector;
|
|
17170
17170
|
if (value.connector !== void 0) {
|
|
17171
17171
|
if (!isPlainObject2(value.connector)) {
|
|
17172
|
-
issues.push({ path: `${
|
|
17172
|
+
issues.push({ path: `${path30}.connector`, message: `${path30}.connector must be an object` });
|
|
17173
17173
|
} else {
|
|
17174
|
-
validateOnlyAllowedKeys(value.connector, CONNECTOR_REFERENCE_KEYS, `${
|
|
17175
|
-
const connectorId = asString(value.connector.connectorId, `${
|
|
17176
|
-
const accountLabel = asOptionalString(value.connector.accountLabel, `${
|
|
17177
|
-
const connectorToolName = asString(value.connector.toolName, `${
|
|
17178
|
-
const approvalPolicy = value.connector.approvalPolicy === void 0 ? void 0 : validateEnum(value.connector.approvalPolicy, CONNECTOR_APPROVAL_POLICIES, `${
|
|
17174
|
+
validateOnlyAllowedKeys(value.connector, CONNECTOR_REFERENCE_KEYS, `${path30}.connector`, issues);
|
|
17175
|
+
const connectorId = asString(value.connector.connectorId, `${path30}.connector.connectorId`, issues, MAX_ID_LENGTH);
|
|
17176
|
+
const accountLabel = asOptionalString(value.connector.accountLabel, `${path30}.connector.accountLabel`, issues, MAX_SHORT_TEXT_LENGTH);
|
|
17177
|
+
const connectorToolName = asString(value.connector.toolName, `${path30}.connector.toolName`, issues, MAX_ID_LENGTH);
|
|
17178
|
+
const approvalPolicy = value.connector.approvalPolicy === void 0 ? void 0 : validateEnum(value.connector.approvalPolicy, CONNECTOR_APPROVAL_POLICIES, `${path30}.connector.approvalPolicy`, issues);
|
|
17179
17179
|
if (connectorId !== void 0 && connectorToolName !== void 0) {
|
|
17180
17180
|
const nextConnector = { connectorId, toolName: connectorToolName };
|
|
17181
17181
|
if (accountLabel !== void 0) nextConnector.accountLabel = accountLabel;
|
|
@@ -17187,17 +17187,17 @@ function validateSource(value, path29, issues) {
|
|
|
17187
17187
|
let outputMapping;
|
|
17188
17188
|
if (value.outputMapping !== void 0) {
|
|
17189
17189
|
if (!isPlainObject2(value.outputMapping)) {
|
|
17190
|
-
issues.push({ path: `${
|
|
17190
|
+
issues.push({ path: `${path30}.outputMapping`, message: `${path30}.outputMapping must be an object` });
|
|
17191
17191
|
} else {
|
|
17192
|
-
validateOnlyAllowedKeys(value.outputMapping, OUTPUT_MAPPING_KEYS, `${
|
|
17192
|
+
validateOnlyAllowedKeys(value.outputMapping, OUTPUT_MAPPING_KEYS, `${path30}.outputMapping`, issues);
|
|
17193
17193
|
const mapping = {};
|
|
17194
17194
|
if (value.outputMapping.dataPaths !== void 0) {
|
|
17195
17195
|
if (!Array.isArray(value.outputMapping.dataPaths) || value.outputMapping.dataPaths.length > MAX_MAPPING_PATHS) {
|
|
17196
|
-
issues.push({ path: `${
|
|
17196
|
+
issues.push({ path: `${path30}.outputMapping.dataPaths`, message: `${path30}.outputMapping.dataPaths must be a bounded array` });
|
|
17197
17197
|
} else {
|
|
17198
17198
|
mapping.dataPaths = [];
|
|
17199
17199
|
value.outputMapping.dataPaths.forEach((item, index) => {
|
|
17200
|
-
const itemPath = `${
|
|
17200
|
+
const itemPath = `${path30}.outputMapping.dataPaths.${index}`;
|
|
17201
17201
|
if (!isPlainObject2(item)) {
|
|
17202
17202
|
issues.push({ path: itemPath, message: `${itemPath} must be an object` });
|
|
17203
17203
|
return;
|
|
@@ -17211,21 +17211,21 @@ function validateSource(value, path29, issues) {
|
|
|
17211
17211
|
}
|
|
17212
17212
|
}
|
|
17213
17213
|
if (value.outputMapping.transform !== void 0) {
|
|
17214
|
-
const transform = validateEnum(value.outputMapping.transform, OUTPUT_TRANSFORMS, `${
|
|
17214
|
+
const transform = validateEnum(value.outputMapping.transform, OUTPUT_TRANSFORMS, `${path30}.outputMapping.transform`, issues);
|
|
17215
17215
|
if (transform !== void 0) mapping.transform = transform;
|
|
17216
17216
|
}
|
|
17217
17217
|
outputMapping = mapping;
|
|
17218
17218
|
}
|
|
17219
17219
|
}
|
|
17220
|
-
const refreshPermission = validateEnum(value.refreshPermission, REFRESH_PERMISSIONS, `${
|
|
17220
|
+
const refreshPermission = validateEnum(value.refreshPermission, REFRESH_PERMISSIONS, `${path30}.refreshPermission`, issues);
|
|
17221
17221
|
if (type === "connector_tool" && connector === void 0) {
|
|
17222
|
-
issues.push({ path: `${
|
|
17222
|
+
issues.push({ path: `${path30}.connector`, message: `${path30}.connector is required for connector_tool sources` });
|
|
17223
17223
|
}
|
|
17224
17224
|
if (type === "connector_tool" && toolName !== void 0 && connector !== void 0 && toolName !== connector.toolName) {
|
|
17225
|
-
issues.push({ path: `${
|
|
17225
|
+
issues.push({ path: `${path30}.toolName`, message: `${path30}.toolName must match ${path30}.connector.toolName` });
|
|
17226
17226
|
}
|
|
17227
17227
|
if (type === "daemon_tool" && toolName === void 0) {
|
|
17228
|
-
issues.push({ path: `${
|
|
17228
|
+
issues.push({ path: `${path30}.toolName`, message: `${path30}.toolName is required for daemon_tool sources` });
|
|
17229
17229
|
}
|
|
17230
17230
|
if (type === void 0 || !inputResult.ok || refreshPermission === void 0) return void 0;
|
|
17231
17231
|
const source = { type, input: inputResult.value, refreshPermission };
|
|
@@ -17234,24 +17234,24 @@ function validateSource(value, path29, issues) {
|
|
|
17234
17234
|
if (outputMapping !== void 0) source.outputMapping = outputMapping;
|
|
17235
17235
|
return source;
|
|
17236
17236
|
}
|
|
17237
|
-
function validateRefreshSourceMetadata(value,
|
|
17237
|
+
function validateRefreshSourceMetadata(value, path30, issues) {
|
|
17238
17238
|
if (!isPlainObject2(value)) {
|
|
17239
|
-
issues.push({ path:
|
|
17239
|
+
issues.push({ path: path30, message: `${path30} must be an object` });
|
|
17240
17240
|
return void 0;
|
|
17241
17241
|
}
|
|
17242
|
-
validateOnlyAllowedKeys(value, REFRESH_SOURCE_METADATA_KEYS,
|
|
17243
|
-
const sourceType = validateEnum(value.sourceType, REFRESH_SOURCE_TYPES, `${
|
|
17244
|
-
const toolName = asOptionalString(value.toolName, `${
|
|
17242
|
+
validateOnlyAllowedKeys(value, REFRESH_SOURCE_METADATA_KEYS, path30, issues);
|
|
17243
|
+
const sourceType = validateEnum(value.sourceType, REFRESH_SOURCE_TYPES, `${path30}.sourceType`, issues);
|
|
17244
|
+
const toolName = asOptionalString(value.toolName, `${path30}.toolName`, issues, MAX_ID_LENGTH);
|
|
17245
17245
|
let connector;
|
|
17246
17246
|
if (value.connector !== void 0) {
|
|
17247
17247
|
if (!isPlainObject2(value.connector)) {
|
|
17248
|
-
issues.push({ path: `${
|
|
17248
|
+
issues.push({ path: `${path30}.connector`, message: `${path30}.connector must be an object` });
|
|
17249
17249
|
} else {
|
|
17250
|
-
validateOnlyAllowedKeys(value.connector, CONNECTOR_REFERENCE_KEYS, `${
|
|
17251
|
-
const connectorId = asString(value.connector.connectorId, `${
|
|
17252
|
-
const accountLabel = asOptionalString(value.connector.accountLabel, `${
|
|
17253
|
-
const connectorToolName = asString(value.connector.toolName, `${
|
|
17254
|
-
const approvalPolicy = value.connector.approvalPolicy === void 0 ? void 0 : validateEnum(value.connector.approvalPolicy, CONNECTOR_APPROVAL_POLICIES, `${
|
|
17250
|
+
validateOnlyAllowedKeys(value.connector, CONNECTOR_REFERENCE_KEYS, `${path30}.connector`, issues);
|
|
17251
|
+
const connectorId = asString(value.connector.connectorId, `${path30}.connector.connectorId`, issues, MAX_ID_LENGTH);
|
|
17252
|
+
const accountLabel = asOptionalString(value.connector.accountLabel, `${path30}.connector.accountLabel`, issues, MAX_SHORT_TEXT_LENGTH);
|
|
17253
|
+
const connectorToolName = asString(value.connector.toolName, `${path30}.connector.toolName`, issues, MAX_ID_LENGTH);
|
|
17254
|
+
const approvalPolicy = value.connector.approvalPolicy === void 0 ? void 0 : validateEnum(value.connector.approvalPolicy, CONNECTOR_APPROVAL_POLICIES, `${path30}.connector.approvalPolicy`, issues);
|
|
17255
17255
|
if (connectorId !== void 0 && connectorToolName !== void 0) {
|
|
17256
17256
|
connector = { connectorId, toolName: connectorToolName };
|
|
17257
17257
|
if (accountLabel !== void 0) connector.accountLabel = accountLabel;
|
|
@@ -17265,46 +17265,46 @@ function validateRefreshSourceMetadata(value, path29, issues) {
|
|
|
17265
17265
|
if (connector !== void 0) source.connector = connector;
|
|
17266
17266
|
return source;
|
|
17267
17267
|
}
|
|
17268
|
-
function validateRefreshErrorRecord(value,
|
|
17268
|
+
function validateRefreshErrorRecord(value, path30, issues) {
|
|
17269
17269
|
if (!isPlainObject2(value)) {
|
|
17270
|
-
issues.push({ path:
|
|
17270
|
+
issues.push({ path: path30, message: `${path30} must be an object` });
|
|
17271
17271
|
return void 0;
|
|
17272
17272
|
}
|
|
17273
|
-
const code = asOptionalString(value.code, `${
|
|
17274
|
-
const message = asString(value.message, `${
|
|
17275
|
-
const errorPath = asOptionalString(value.path, `${
|
|
17273
|
+
const code = asOptionalString(value.code, `${path30}.code`, issues, MAX_REFRESH_ERROR_CODE_LENGTH);
|
|
17274
|
+
const message = asString(value.message, `${path30}.message`, issues, MAX_REFRESH_ERROR_MESSAGE_LENGTH);
|
|
17275
|
+
const errorPath = asOptionalString(value.path, `${path30}.path`, issues, MAX_PATH_LENGTH);
|
|
17276
17276
|
if (message === void 0) return void 0;
|
|
17277
17277
|
const record = { message };
|
|
17278
17278
|
if (code !== void 0) record.code = code;
|
|
17279
17279
|
if (errorPath !== void 0) record.path = errorPath;
|
|
17280
17280
|
return record;
|
|
17281
17281
|
}
|
|
17282
|
-
function validateOptionalInteger(value,
|
|
17282
|
+
function validateOptionalInteger(value, path30, issues, min, max) {
|
|
17283
17283
|
if (value === void 0) return void 0;
|
|
17284
17284
|
if (typeof value !== "number" || !Number.isInteger(value) || value < min || value > max) {
|
|
17285
|
-
issues.push({ path:
|
|
17285
|
+
issues.push({ path: path30, message: `${path30} must be an integer between ${min} and ${max}` });
|
|
17286
17286
|
return void 0;
|
|
17287
17287
|
}
|
|
17288
17288
|
return value;
|
|
17289
17289
|
}
|
|
17290
|
-
function validateDocument(value,
|
|
17290
|
+
function validateDocument(value, path30, issues) {
|
|
17291
17291
|
if (!isPlainObject2(value)) {
|
|
17292
|
-
issues.push({ path:
|
|
17292
|
+
issues.push({ path: path30, message: `${path30} must be an object` });
|
|
17293
17293
|
return void 0;
|
|
17294
17294
|
}
|
|
17295
|
-
if (value.format !== "html_template_v1") issues.push({ path: `${
|
|
17296
|
-
if (value.templatePath !== "template.html") issues.push({ path: `${
|
|
17297
|
-
if (value.generatedPreviewPath !== "index.html") issues.push({ path: `${
|
|
17298
|
-
if (value.dataPath !== "data.json") issues.push({ path: `${
|
|
17299
|
-
const dataJsonResult = validateBoundedJsonObject(value.dataJson, `${
|
|
17295
|
+
if (value.format !== "html_template_v1") issues.push({ path: `${path30}.format`, message: `${path30}.format must be html_template_v1` });
|
|
17296
|
+
if (value.templatePath !== "template.html") issues.push({ path: `${path30}.templatePath`, message: `${path30}.templatePath must be template.html` });
|
|
17297
|
+
if (value.generatedPreviewPath !== "index.html") issues.push({ path: `${path30}.generatedPreviewPath`, message: `${path30}.generatedPreviewPath must be index.html` });
|
|
17298
|
+
if (value.dataPath !== "data.json") issues.push({ path: `${path30}.dataPath`, message: `${path30}.dataPath must be data.json` });
|
|
17299
|
+
const dataJsonResult = validateBoundedJsonObject(value.dataJson, `${path30}.dataJson`);
|
|
17300
17300
|
if (!dataJsonResult.ok) issues.push(...dataJsonResult.issues);
|
|
17301
17301
|
let dataSchemaJson;
|
|
17302
17302
|
if (value.dataSchemaJson !== void 0) {
|
|
17303
|
-
const schemaResult = validateBoundedJsonObject(value.dataSchemaJson, `${
|
|
17303
|
+
const schemaResult = validateBoundedJsonObject(value.dataSchemaJson, `${path30}.dataSchemaJson`);
|
|
17304
17304
|
if (schemaResult.ok) dataSchemaJson = schemaResult.value;
|
|
17305
17305
|
else issues.push(...schemaResult.issues);
|
|
17306
17306
|
}
|
|
17307
|
-
const sourceJson = value.sourceJson === void 0 ? void 0 : validateSource(value.sourceJson, `${
|
|
17307
|
+
const sourceJson = value.sourceJson === void 0 ? void 0 : validateSource(value.sourceJson, `${path30}.sourceJson`, issues);
|
|
17308
17308
|
if (value.format !== "html_template_v1" || value.templatePath !== "template.html" || value.generatedPreviewPath !== "index.html" || value.dataPath !== "data.json" || !dataJsonResult.ok) {
|
|
17309
17309
|
return void 0;
|
|
17310
17310
|
}
|
|
@@ -17319,24 +17319,24 @@ function validateDocument(value, path29, issues) {
|
|
|
17319
17319
|
if (sourceJson !== void 0) document.sourceJson = sourceJson;
|
|
17320
17320
|
return document;
|
|
17321
17321
|
}
|
|
17322
|
-
function validatePersistedLiveArtifact(value,
|
|
17322
|
+
function validatePersistedLiveArtifact(value, path30 = "liveArtifact") {
|
|
17323
17323
|
const issues = [];
|
|
17324
|
-
if (!isPlainObject2(value)) return fail([{ path:
|
|
17325
|
-
if (value.schemaVersion !== 1) issues.push({ path: `${
|
|
17326
|
-
const id = asString(value.id, `${
|
|
17327
|
-
const projectId = asString(value.projectId, `${
|
|
17328
|
-
const sessionId = asOptionalString(value.sessionId, `${
|
|
17329
|
-
const createdByRunId = asOptionalString(value.createdByRunId, `${
|
|
17330
|
-
const title = asString(value.title, `${
|
|
17331
|
-
const slug = asString(value.slug, `${
|
|
17332
|
-
const status = validateEnum(value.status, LIVE_ARTIFACT_STATUSES, `${
|
|
17333
|
-
const pinned = asBoolean(value.pinned, `${
|
|
17334
|
-
const preview = validatePreview(value.preview, `${
|
|
17335
|
-
const refreshStatus = validateEnum(value.refreshStatus, LIVE_ARTIFACT_REFRESH_STATUSES, `${
|
|
17336
|
-
const createdAt = validateIsoDate(value.createdAt, `${
|
|
17337
|
-
const updatedAt = validateIsoDate(value.updatedAt, `${
|
|
17338
|
-
const lastRefreshedAt = value.lastRefreshedAt === void 0 ? void 0 : validateIsoDate(value.lastRefreshedAt, `${
|
|
17339
|
-
const document = validateDocument(value.document, `${
|
|
17324
|
+
if (!isPlainObject2(value)) return fail([{ path: path30, message: `${path30} must be an object` }]);
|
|
17325
|
+
if (value.schemaVersion !== 1) issues.push({ path: `${path30}.schemaVersion`, message: `${path30}.schemaVersion must be 1` });
|
|
17326
|
+
const id = asString(value.id, `${path30}.id`, issues, MAX_ID_LENGTH);
|
|
17327
|
+
const projectId = asString(value.projectId, `${path30}.projectId`, issues, MAX_ID_LENGTH);
|
|
17328
|
+
const sessionId = asOptionalString(value.sessionId, `${path30}.sessionId`, issues, MAX_ID_LENGTH);
|
|
17329
|
+
const createdByRunId = asOptionalString(value.createdByRunId, `${path30}.createdByRunId`, issues, MAX_ID_LENGTH);
|
|
17330
|
+
const title = asString(value.title, `${path30}.title`, issues, MAX_TITLE_LENGTH2);
|
|
17331
|
+
const slug = asString(value.slug, `${path30}.slug`, issues, MAX_SLUG_LENGTH);
|
|
17332
|
+
const status = validateEnum(value.status, LIVE_ARTIFACT_STATUSES, `${path30}.status`, issues);
|
|
17333
|
+
const pinned = asBoolean(value.pinned, `${path30}.pinned`, issues);
|
|
17334
|
+
const preview = validatePreview(value.preview, `${path30}.preview`, issues);
|
|
17335
|
+
const refreshStatus = validateEnum(value.refreshStatus, LIVE_ARTIFACT_REFRESH_STATUSES, `${path30}.refreshStatus`, issues);
|
|
17336
|
+
const createdAt = validateIsoDate(value.createdAt, `${path30}.createdAt`, issues);
|
|
17337
|
+
const updatedAt = validateIsoDate(value.updatedAt, `${path30}.updatedAt`, issues);
|
|
17338
|
+
const lastRefreshedAt = value.lastRefreshedAt === void 0 ? void 0 : validateIsoDate(value.lastRefreshedAt, `${path30}.lastRefreshedAt`, issues);
|
|
17339
|
+
const document = validateDocument(value.document, `${path30}.document`, issues);
|
|
17340
17340
|
if (issues.length > 0 || id === void 0 || projectId === void 0 || title === void 0 || slug === void 0 || status === void 0 || pinned === void 0 || preview === void 0 || refreshStatus === void 0 || createdAt === void 0 || updatedAt === void 0 || document === void 0) {
|
|
17341
17341
|
return fail(issues);
|
|
17342
17342
|
}
|
|
@@ -17359,28 +17359,28 @@ function validatePersistedLiveArtifact(value, path29 = "liveArtifact") {
|
|
|
17359
17359
|
if (lastRefreshedAt !== void 0) liveArtifact.lastRefreshedAt = lastRefreshedAt;
|
|
17360
17360
|
return ok(liveArtifact);
|
|
17361
17361
|
}
|
|
17362
|
-
function validateLiveArtifactRefreshLogEntry(value,
|
|
17362
|
+
function validateLiveArtifactRefreshLogEntry(value, path30 = "refreshLogEntry") {
|
|
17363
17363
|
const issues = [];
|
|
17364
|
-
if (!isPlainObject2(value)) return fail([{ path:
|
|
17365
|
-
if (value.schemaVersion !== 1) issues.push({ path: `${
|
|
17366
|
-
const projectId = asString(value.projectId, `${
|
|
17367
|
-
const artifactId = asString(value.artifactId, `${
|
|
17368
|
-
const refreshId = asString(value.refreshId, `${
|
|
17369
|
-
const sequence = validateOptionalInteger(value.sequence, `${
|
|
17370
|
-
const step = asString(value.step, `${
|
|
17371
|
-
const status = validateEnum(value.status, REFRESH_STEP_STATUSES, `${
|
|
17372
|
-
const startedAt = validateIsoDate(value.startedAt, `${
|
|
17373
|
-
const finishedAt = value.finishedAt === void 0 ? void 0 : validateIsoDate(value.finishedAt, `${
|
|
17374
|
-
const durationMs2 = validateOptionalInteger(value.durationMs, `${
|
|
17375
|
-
const source = value.source === void 0 ? void 0 : validateRefreshSourceMetadata(value.source, `${
|
|
17376
|
-
const error = value.error === void 0 ? void 0 : validateRefreshErrorRecord(value.error, `${
|
|
17364
|
+
if (!isPlainObject2(value)) return fail([{ path: path30, message: `${path30} must be an object` }]);
|
|
17365
|
+
if (value.schemaVersion !== 1) issues.push({ path: `${path30}.schemaVersion`, message: `${path30}.schemaVersion must be 1` });
|
|
17366
|
+
const projectId = asString(value.projectId, `${path30}.projectId`, issues, MAX_ID_LENGTH);
|
|
17367
|
+
const artifactId = asString(value.artifactId, `${path30}.artifactId`, issues, MAX_ID_LENGTH);
|
|
17368
|
+
const refreshId = asString(value.refreshId, `${path30}.refreshId`, issues, MAX_ID_LENGTH);
|
|
17369
|
+
const sequence = validateOptionalInteger(value.sequence, `${path30}.sequence`, issues, 0, Number.MAX_SAFE_INTEGER);
|
|
17370
|
+
const step = asString(value.step, `${path30}.step`, issues, MAX_REFRESH_STEP_LENGTH);
|
|
17371
|
+
const status = validateEnum(value.status, REFRESH_STEP_STATUSES, `${path30}.status`, issues);
|
|
17372
|
+
const startedAt = validateIsoDate(value.startedAt, `${path30}.startedAt`, issues);
|
|
17373
|
+
const finishedAt = value.finishedAt === void 0 ? void 0 : validateIsoDate(value.finishedAt, `${path30}.finishedAt`, issues);
|
|
17374
|
+
const durationMs2 = validateOptionalInteger(value.durationMs, `${path30}.durationMs`, issues, 0, Number.MAX_SAFE_INTEGER);
|
|
17375
|
+
const source = value.source === void 0 ? void 0 : validateRefreshSourceMetadata(value.source, `${path30}.source`, issues);
|
|
17376
|
+
const error = value.error === void 0 ? void 0 : validateRefreshErrorRecord(value.error, `${path30}.error`, issues);
|
|
17377
17377
|
let metadata;
|
|
17378
17378
|
if (value.metadata !== void 0) {
|
|
17379
|
-
const metadataResult = validateBoundedJsonObject(value.metadata, `${
|
|
17379
|
+
const metadataResult = validateBoundedJsonObject(value.metadata, `${path30}.metadata`);
|
|
17380
17380
|
if (metadataResult.ok) metadata = metadataResult.value;
|
|
17381
17381
|
else issues.push(...metadataResult.issues);
|
|
17382
17382
|
}
|
|
17383
|
-
const createdAt = validateIsoDate(value.createdAt, `${
|
|
17383
|
+
const createdAt = validateIsoDate(value.createdAt, `${path30}.createdAt`, issues);
|
|
17384
17384
|
if (issues.length > 0 || projectId === void 0 || artifactId === void 0 || refreshId === void 0 || sequence === void 0 || step === void 0 || status === void 0 || startedAt === void 0 || createdAt === void 0) {
|
|
17385
17385
|
return fail(issues);
|
|
17386
17386
|
}
|
|
@@ -17402,17 +17402,17 @@ function validateLiveArtifactRefreshLogEntry(value, path29 = "refreshLogEntry")
|
|
|
17402
17402
|
if (metadata !== void 0) entry.metadata = metadata;
|
|
17403
17403
|
return ok(entry);
|
|
17404
17404
|
}
|
|
17405
|
-
function validateLiveArtifactCreateInput(value,
|
|
17405
|
+
function validateLiveArtifactCreateInput(value, path30 = "input") {
|
|
17406
17406
|
const issues = [];
|
|
17407
|
-
if (!isPlainObject2(value)) return fail([{ path:
|
|
17407
|
+
if (!isPlainObject2(value)) return fail([{ path: path30, message: `${path30} must be an object` }]);
|
|
17408
17408
|
validateNoDaemonOwnedFields(value, issues);
|
|
17409
|
-
const title = asString(value.title, `${
|
|
17410
|
-
const slug = asOptionalString(value.slug, `${
|
|
17411
|
-
const sessionId = asOptionalString(value.sessionId, `${
|
|
17412
|
-
const pinned = asOptionalBoolean(value.pinned, `${
|
|
17413
|
-
const status = value.status === void 0 ? void 0 : validateEnum(value.status, LIVE_ARTIFACT_STATUSES, `${
|
|
17414
|
-
const preview = validatePreview(value.preview, `${
|
|
17415
|
-
const document = validateDocument(value.document, `${
|
|
17409
|
+
const title = asString(value.title, `${path30}.title`, issues, MAX_TITLE_LENGTH2);
|
|
17410
|
+
const slug = asOptionalString(value.slug, `${path30}.slug`, issues, MAX_SLUG_LENGTH);
|
|
17411
|
+
const sessionId = asOptionalString(value.sessionId, `${path30}.sessionId`, issues, MAX_ID_LENGTH);
|
|
17412
|
+
const pinned = asOptionalBoolean(value.pinned, `${path30}.pinned`, issues);
|
|
17413
|
+
const status = value.status === void 0 ? void 0 : validateEnum(value.status, LIVE_ARTIFACT_STATUSES, `${path30}.status`, issues);
|
|
17414
|
+
const preview = validatePreview(value.preview, `${path30}.preview`, issues);
|
|
17415
|
+
const document = validateDocument(value.document, `${path30}.document`, issues);
|
|
17416
17416
|
if (issues.length > 0 || title === void 0 || preview === void 0 || document === void 0) return fail(issues);
|
|
17417
17417
|
const input = { title, preview, document };
|
|
17418
17418
|
if (slug !== void 0) input.slug = slug;
|
|
@@ -17421,16 +17421,16 @@ function validateLiveArtifactCreateInput(value, path29 = "input") {
|
|
|
17421
17421
|
if (status !== void 0) input.status = status;
|
|
17422
17422
|
return ok(input);
|
|
17423
17423
|
}
|
|
17424
|
-
function validateLiveArtifactUpdateInput(value,
|
|
17424
|
+
function validateLiveArtifactUpdateInput(value, path30 = "input") {
|
|
17425
17425
|
const issues = [];
|
|
17426
|
-
if (!isPlainObject2(value)) return fail([{ path:
|
|
17426
|
+
if (!isPlainObject2(value)) return fail([{ path: path30, message: `${path30} must be an object` }]);
|
|
17427
17427
|
validateNoDaemonOwnedFields(value, issues);
|
|
17428
|
-
const title = asOptionalString(value.title, `${
|
|
17429
|
-
const slug = asOptionalString(value.slug, `${
|
|
17430
|
-
const pinned = asOptionalBoolean(value.pinned, `${
|
|
17431
|
-
const status = value.status === void 0 ? void 0 : validateEnum(value.status, LIVE_ARTIFACT_STATUSES, `${
|
|
17432
|
-
const preview = value.preview === void 0 ? void 0 : validatePreview(value.preview, `${
|
|
17433
|
-
const document = value.document === void 0 ? void 0 : validateDocument(value.document, `${
|
|
17428
|
+
const title = asOptionalString(value.title, `${path30}.title`, issues, MAX_TITLE_LENGTH2);
|
|
17429
|
+
const slug = asOptionalString(value.slug, `${path30}.slug`, issues, MAX_SLUG_LENGTH);
|
|
17430
|
+
const pinned = asOptionalBoolean(value.pinned, `${path30}.pinned`, issues);
|
|
17431
|
+
const status = value.status === void 0 ? void 0 : validateEnum(value.status, LIVE_ARTIFACT_STATUSES, `${path30}.status`, issues);
|
|
17432
|
+
const preview = value.preview === void 0 ? void 0 : validatePreview(value.preview, `${path30}.preview`, issues);
|
|
17433
|
+
const document = value.document === void 0 ? void 0 : validateDocument(value.document, `${path30}.document`, issues);
|
|
17434
17434
|
if (issues.length > 0) return fail(issues);
|
|
17435
17435
|
const input = {};
|
|
17436
17436
|
if (title !== void 0) input.title = title;
|
|
@@ -17464,9 +17464,9 @@ var LiveArtifactRefreshAbortError = class extends Error {
|
|
|
17464
17464
|
if (options.step !== void 0) this.step = options.step;
|
|
17465
17465
|
}
|
|
17466
17466
|
};
|
|
17467
|
-
function validateTimeoutMs(value,
|
|
17467
|
+
function validateTimeoutMs(value, path30) {
|
|
17468
17468
|
if (!Number.isSafeInteger(value) || value < 1) {
|
|
17469
|
-
throw new RangeError(`${
|
|
17469
|
+
throw new RangeError(`${path30} must be a positive safe integer`);
|
|
17470
17470
|
}
|
|
17471
17471
|
return value;
|
|
17472
17472
|
}
|
|
@@ -17589,8 +17589,8 @@ function asBoundedRefreshOutput(value) {
|
|
|
17589
17589
|
}
|
|
17590
17590
|
var SAFE_MAPPING_SEGMENT2 = /^[A-Za-z_][A-Za-z0-9_-]*$|^(?:0|[1-9][0-9]*)$/;
|
|
17591
17591
|
var UNSAFE_MAPPING_SEGMENTS2 = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
17592
|
-
function parseMappingPath(
|
|
17593
|
-
const normalized =
|
|
17592
|
+
function parseMappingPath(path30, field) {
|
|
17593
|
+
const normalized = path30.startsWith("$.") ? path30.slice(2) : path30;
|
|
17594
17594
|
if (normalized.length === 0 || normalized.startsWith(".") || normalized.endsWith(".") || normalized.includes("..")) {
|
|
17595
17595
|
throw new Error(`${field} must be a dot-separated JSON path`);
|
|
17596
17596
|
}
|
|
@@ -17605,9 +17605,9 @@ function parseMappingPath(path29, field) {
|
|
|
17605
17605
|
function isJsonObject(value) {
|
|
17606
17606
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
17607
17607
|
}
|
|
17608
|
-
function readMappedValue(root,
|
|
17608
|
+
function readMappedValue(root, path30) {
|
|
17609
17609
|
let current = root;
|
|
17610
|
-
for (const segment of parseMappingPath(
|
|
17610
|
+
for (const segment of parseMappingPath(path30, "outputMapping.dataPaths.from")) {
|
|
17611
17611
|
if (Array.isArray(current)) {
|
|
17612
17612
|
const index = Number(segment);
|
|
17613
17613
|
if (!Number.isSafeInteger(index) || index < 0) throw new Error(`outputMapping.dataPaths.from array segment is invalid: ${segment}`);
|
|
@@ -17624,8 +17624,8 @@ function readMappedValue(root, path29) {
|
|
|
17624
17624
|
function makeContainer(nextSegment) {
|
|
17625
17625
|
return /^(?:0|[1-9][0-9]*)$/.test(nextSegment) ? [] : {};
|
|
17626
17626
|
}
|
|
17627
|
-
function writeMappedValue(root,
|
|
17628
|
-
const segments = parseMappingPath(
|
|
17627
|
+
function writeMappedValue(root, path30, value) {
|
|
17628
|
+
const segments = parseMappingPath(path30, "outputMapping.dataPaths.to");
|
|
17629
17629
|
let current = root;
|
|
17630
17630
|
for (let index = 0; index < segments.length; index += 1) {
|
|
17631
17631
|
const segment = segments[index];
|
|
@@ -18215,8 +18215,8 @@ function toSummary(artifact) {
|
|
|
18215
18215
|
hasDocument: _document !== void 0
|
|
18216
18216
|
};
|
|
18217
18217
|
}
|
|
18218
|
-
function validationError(
|
|
18219
|
-
return new LiveArtifactStoreValidationError(message, [{ path:
|
|
18218
|
+
function validationError(path30, message) {
|
|
18219
|
+
return new LiveArtifactStoreValidationError(message, [{ path: path30, message }]);
|
|
18220
18220
|
}
|
|
18221
18221
|
function toIsoDate(value) {
|
|
18222
18222
|
return value instanceof Date ? value.toISOString() : value;
|
|
@@ -20447,8 +20447,8 @@ var ComposioConnectorProvider = class {
|
|
|
20447
20447
|
}
|
|
20448
20448
|
};
|
|
20449
20449
|
}
|
|
20450
|
-
async requestJson(
|
|
20451
|
-
const response = await this.request(
|
|
20450
|
+
async requestJson(path30, input) {
|
|
20451
|
+
const response = await this.request(path30, input);
|
|
20452
20452
|
if (!response.ok) {
|
|
20453
20453
|
const message = await getComposioErrorMessage(response);
|
|
20454
20454
|
throw new ConnectorServiceError("CONNECTOR_EXECUTION_FAILED", message ?? `Composio request failed with HTTP ${response.status}`, response.status === 401 ? 401 : 502, { httpStatus: response.status });
|
|
@@ -20459,14 +20459,14 @@ var ComposioConnectorProvider = class {
|
|
|
20459
20459
|
}
|
|
20460
20460
|
return value;
|
|
20461
20461
|
}
|
|
20462
|
-
async request(
|
|
20462
|
+
async request(path30, input) {
|
|
20463
20463
|
const apiKey = this.getApiKey();
|
|
20464
20464
|
if (!apiKey) {
|
|
20465
20465
|
throw new ConnectorServiceError("CONNECTOR_EXECUTION_FAILED", "Composio provider is not configured", 503, { setting: "apiKey" });
|
|
20466
20466
|
}
|
|
20467
20467
|
const timeout = AbortSignal.timeout(DEFAULT_COMPOSIO_TIMEOUT_MS);
|
|
20468
20468
|
const signal = input.signal ? AbortSignal.any([input.signal, timeout]) : timeout;
|
|
20469
|
-
return fetch(`${this.getBaseUrl().replace(/\/+$/, "")}${
|
|
20469
|
+
return fetch(`${this.getBaseUrl().replace(/\/+$/, "")}${path30}`, {
|
|
20470
20470
|
method: input.method,
|
|
20471
20471
|
headers: {
|
|
20472
20472
|
accept: "application/json",
|
|
@@ -20779,45 +20779,45 @@ function runtimeSafetyForTool(tool) {
|
|
|
20779
20779
|
if (classified.sideEffect !== "read" || classified.approval !== "auto") return classified;
|
|
20780
20780
|
return tool.safety;
|
|
20781
20781
|
}
|
|
20782
|
-
function assertJsonSchemaMatches(value, schema,
|
|
20782
|
+
function assertJsonSchemaMatches(value, schema, path30 = "input") {
|
|
20783
20783
|
if (schema === void 0) return;
|
|
20784
20784
|
const type = schema.type;
|
|
20785
20785
|
if (typeof type === "string") {
|
|
20786
20786
|
const actualType = Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
|
|
20787
20787
|
if (type === "number") {
|
|
20788
|
-
if (typeof value !== "number") throw new Error(`${
|
|
20788
|
+
if (typeof value !== "number") throw new Error(`${path30} must be a number`);
|
|
20789
20789
|
} else if (type === "integer") {
|
|
20790
|
-
if (typeof value !== "number" || !Number.isInteger(value)) throw new Error(`${
|
|
20790
|
+
if (typeof value !== "number" || !Number.isInteger(value)) throw new Error(`${path30} must be an integer`);
|
|
20791
20791
|
} else if (type !== actualType) {
|
|
20792
|
-
throw new Error(`${
|
|
20792
|
+
throw new Error(`${path30} must be a ${type}`);
|
|
20793
20793
|
}
|
|
20794
20794
|
}
|
|
20795
20795
|
if (type === "object") {
|
|
20796
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${
|
|
20796
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${path30} must be an object`);
|
|
20797
20797
|
const objectValue = value;
|
|
20798
20798
|
const required = Array.isArray(schema.required) ? schema.required.filter((item) => typeof item === "string") : [];
|
|
20799
20799
|
for (const key of required) {
|
|
20800
|
-
if (objectValue[key] === void 0) throw new Error(`${
|
|
20800
|
+
if (objectValue[key] === void 0) throw new Error(`${path30}.${key} is required by connector input schema`);
|
|
20801
20801
|
}
|
|
20802
20802
|
const properties = schema.properties;
|
|
20803
20803
|
const propertySchemas = properties !== null && typeof properties === "object" && !Array.isArray(properties) ? properties : {};
|
|
20804
20804
|
if (schema.additionalProperties === false) {
|
|
20805
20805
|
for (const key of Object.keys(objectValue)) {
|
|
20806
|
-
if (propertySchemas[key] === void 0) throw new Error(`${
|
|
20806
|
+
if (propertySchemas[key] === void 0) throw new Error(`${path30}.${key} is not allowed by connector input schema`);
|
|
20807
20807
|
}
|
|
20808
20808
|
}
|
|
20809
20809
|
for (const [key, childSchema] of Object.entries(propertySchemas)) {
|
|
20810
20810
|
if (objectValue[key] !== void 0 && childSchema !== null && typeof childSchema === "object" && !Array.isArray(childSchema)) {
|
|
20811
|
-
assertJsonSchemaMatches(objectValue[key], childSchema, `${
|
|
20811
|
+
assertJsonSchemaMatches(objectValue[key], childSchema, `${path30}.${key}`);
|
|
20812
20812
|
}
|
|
20813
20813
|
}
|
|
20814
20814
|
}
|
|
20815
20815
|
if (type === "string" && typeof value === "string") {
|
|
20816
|
-
if (typeof schema.maxLength === "number" && value.length > schema.maxLength) throw new Error(`${
|
|
20816
|
+
if (typeof schema.maxLength === "number" && value.length > schema.maxLength) throw new Error(`${path30} exceeds connector input schema maxLength`);
|
|
20817
20817
|
}
|
|
20818
20818
|
if ((type === "number" || type === "integer") && typeof value === "number") {
|
|
20819
|
-
if (typeof schema.minimum === "number" && value < schema.minimum) throw new Error(`${
|
|
20820
|
-
if (typeof schema.maximum === "number" && value > schema.maximum) throw new Error(`${
|
|
20819
|
+
if (typeof schema.minimum === "number" && value < schema.minimum) throw new Error(`${path30} is below connector input schema minimum`);
|
|
20820
|
+
if (typeof schema.maximum === "number" && value > schema.maximum) throw new Error(`${path30} exceeds connector input schema maximum`);
|
|
20821
20821
|
}
|
|
20822
20822
|
}
|
|
20823
20823
|
function defaultConnectedAccountLabel(definition) {
|
|
@@ -22717,24 +22717,52 @@ function safeVercelProjectName(raw) {
|
|
|
22717
22717
|
return String(raw).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || `od-${randomUUID4().slice(0, 8)}`;
|
|
22718
22718
|
}
|
|
22719
22719
|
|
|
22720
|
+
// apps/daemon/src/layout.ts
|
|
22721
|
+
import fs7 from "node:fs";
|
|
22722
|
+
import path28 from "node:path";
|
|
22723
|
+
var REPO_DATA_DIR = ".od";
|
|
22724
|
+
var PACKAGE_DATA_DIR = ".tfdesign";
|
|
22725
|
+
function detectLayout(moduleDir) {
|
|
22726
|
+
const base = path28.basename(moduleDir);
|
|
22727
|
+
const daemonDir = base === "dist" || base === "src" ? path28.dirname(moduleDir) : moduleDir;
|
|
22728
|
+
const candidate = path28.resolve(daemonDir, "../..");
|
|
22729
|
+
const repo = fs7.existsSync(path28.join(candidate, "pnpm-workspace.yaml")) && fs7.existsSync(path28.join(candidate, "apps", "daemon"));
|
|
22730
|
+
return repo ? { root: candidate, repo: true } : { root: daemonDir, repo: false };
|
|
22731
|
+
}
|
|
22732
|
+
function defaultDataRoot(moduleDir, cwd = process.cwd()) {
|
|
22733
|
+
const layout = detectLayout(moduleDir);
|
|
22734
|
+
return path28.join(
|
|
22735
|
+
layout.repo ? layout.root : cwd,
|
|
22736
|
+
layout.repo ? REPO_DATA_DIR : PACKAGE_DATA_DIR
|
|
22737
|
+
);
|
|
22738
|
+
}
|
|
22739
|
+
function expandDataRoot(raw, cwd = process.cwd()) {
|
|
22740
|
+
if (raw.startsWith("~/"))
|
|
22741
|
+
return path28.join(process.env.HOME ?? "~", raw.slice(2));
|
|
22742
|
+
return path28.isAbsolute(raw) ? raw : path28.resolve(cwd, raw);
|
|
22743
|
+
}
|
|
22744
|
+
function resolveDataRoot(moduleDir, cwd = process.cwd()) {
|
|
22745
|
+
const raw = process.env.TFDESIGN_DATA_DIR || process.env.OD_DATA_DIR;
|
|
22746
|
+
return raw ? expandDataRoot(raw, cwd) : defaultDataRoot(moduleDir, cwd);
|
|
22747
|
+
}
|
|
22748
|
+
|
|
22720
22749
|
// apps/daemon/src/server.ts
|
|
22721
22750
|
var __filename = fileURLToPath2(import.meta.url);
|
|
22722
|
-
var __dirname =
|
|
22751
|
+
var __dirname = path29.dirname(__filename);
|
|
22723
22752
|
var require2 = createRequire(import.meta.url);
|
|
22724
22753
|
function resolveProjectRoot(moduleDir) {
|
|
22725
|
-
|
|
22726
|
-
const daemonDir = base === "dist" || base === "src" ? path28.dirname(moduleDir) : moduleDir;
|
|
22727
|
-
return path28.resolve(daemonDir, "../..");
|
|
22754
|
+
return detectLayout(moduleDir).root;
|
|
22728
22755
|
}
|
|
22729
22756
|
function resolveDaemonCliPath() {
|
|
22730
22757
|
try {
|
|
22731
22758
|
const packageJsonPath = require2.resolve("@open-design/daemon/package.json");
|
|
22732
|
-
return
|
|
22759
|
+
return path29.join(path29.dirname(packageJsonPath), "dist", "cli.js");
|
|
22733
22760
|
} catch {
|
|
22734
|
-
return
|
|
22761
|
+
return path29.join(__dirname, "cli.js");
|
|
22735
22762
|
}
|
|
22736
22763
|
}
|
|
22737
|
-
var
|
|
22764
|
+
var LAYOUT = detectLayout(__dirname);
|
|
22765
|
+
var PROJECT_ROOT = LAYOUT.root;
|
|
22738
22766
|
var RESOURCE_ROOT_ENV = "OD_RESOURCE_ROOT";
|
|
22739
22767
|
function buildDeckWorkflowReminder(message, metadata) {
|
|
22740
22768
|
if (!message || typeof message !== "string") return "";
|
|
@@ -22773,9 +22801,9 @@ function composeLiveInstructionPrompt({
|
|
|
22773
22801
|
}
|
|
22774
22802
|
function resolveCodexGeneratedImagesDir(agentId, metadata, env = process.env, homeDir = os4.homedir()) {
|
|
22775
22803
|
if (!shouldRenderCodexImagegenOverride(agentId, metadata)) return null;
|
|
22776
|
-
const rawCodexHome = typeof env?.CODEX_HOME === "string" && env.CODEX_HOME.trim().length > 0 ? env.CODEX_HOME.trim() :
|
|
22777
|
-
const codexHome = rawCodexHome.startsWith("~/") ?
|
|
22778
|
-
return
|
|
22804
|
+
const rawCodexHome = typeof env?.CODEX_HOME === "string" && env.CODEX_HOME.trim().length > 0 ? env.CODEX_HOME.trim() : path29.join(homeDir, ".codex");
|
|
22805
|
+
const codexHome = rawCodexHome.startsWith("~/") ? path29.join(homeDir, rawCodexHome.slice(2)) : rawCodexHome;
|
|
22806
|
+
return path29.resolve(codexHome, "generated_images");
|
|
22779
22807
|
}
|
|
22780
22808
|
function isMissingPathError(err) {
|
|
22781
22809
|
return err && typeof err === "object" && "code" in err && err.code === "ENOENT";
|
|
@@ -22787,7 +22815,7 @@ function collectProtectedDirRoots(protectedDirs, {
|
|
|
22787
22815
|
const roots = [];
|
|
22788
22816
|
for (const raw of Array.isArray(protectedDirs) ? protectedDirs : []) {
|
|
22789
22817
|
if (typeof raw !== "string" || raw.trim().length === 0) continue;
|
|
22790
|
-
const resolved =
|
|
22818
|
+
const resolved = path29.resolve(raw);
|
|
22791
22819
|
roots.push(resolved);
|
|
22792
22820
|
try {
|
|
22793
22821
|
const canonical = realpathSync2(resolved);
|
|
@@ -22806,16 +22834,16 @@ function findContainingProtectedRoot(candidate, protectedRoots) {
|
|
|
22806
22834
|
}
|
|
22807
22835
|
function validateCodexGeneratedImagesDir(codexGeneratedImagesDir, {
|
|
22808
22836
|
protectedDirs = [],
|
|
22809
|
-
mkdirSync: mkdirSync2 =
|
|
22810
|
-
lstatSync =
|
|
22811
|
-
statSync: statSync3 =
|
|
22812
|
-
realpathSync: realpathSync2 =
|
|
22837
|
+
mkdirSync: mkdirSync2 = fs8.mkdirSync,
|
|
22838
|
+
lstatSync = fs8.lstatSync,
|
|
22839
|
+
statSync: statSync3 = fs8.statSync,
|
|
22840
|
+
realpathSync: realpathSync2 = fs8.realpathSync.native,
|
|
22813
22841
|
warn = console.warn
|
|
22814
22842
|
} = {}) {
|
|
22815
22843
|
if (typeof codexGeneratedImagesDir !== "string" || codexGeneratedImagesDir.trim().length === 0) {
|
|
22816
22844
|
return null;
|
|
22817
22845
|
}
|
|
22818
|
-
const resolved =
|
|
22846
|
+
const resolved = path29.resolve(codexGeneratedImagesDir);
|
|
22819
22847
|
const protectedRoots = collectProtectedDirRoots(protectedDirs, {
|
|
22820
22848
|
realpathSync: realpathSync2,
|
|
22821
22849
|
statSync: statSync3
|
|
@@ -22841,7 +22869,7 @@ function validateCodexGeneratedImagesDir(codexGeneratedImagesDir, {
|
|
|
22841
22869
|
warnSkipped(`${resolved} is not a directory`);
|
|
22842
22870
|
return null;
|
|
22843
22871
|
}
|
|
22844
|
-
const parent =
|
|
22872
|
+
const parent = path29.dirname(resolved);
|
|
22845
22873
|
const protectedParentRoot = findContainingProtectedRoot(
|
|
22846
22874
|
parent,
|
|
22847
22875
|
protectedRoots
|
|
@@ -22852,9 +22880,9 @@ function validateCodexGeneratedImagesDir(codexGeneratedImagesDir, {
|
|
|
22852
22880
|
}
|
|
22853
22881
|
mkdirSync2(parent, { recursive: true });
|
|
22854
22882
|
const canonicalParent = realpathSync2(parent);
|
|
22855
|
-
const canonicalCandidate =
|
|
22883
|
+
const canonicalCandidate = path29.join(
|
|
22856
22884
|
canonicalParent,
|
|
22857
|
-
|
|
22885
|
+
path29.basename(resolved)
|
|
22858
22886
|
);
|
|
22859
22887
|
const protectedCanonicalParentRoot = findContainingProtectedRoot(
|
|
22860
22888
|
canonicalCandidate,
|
|
@@ -22898,13 +22926,10 @@ function resolveChatExtraAllowedDirs({
|
|
|
22898
22926
|
brandGuidelinesDir,
|
|
22899
22927
|
linkedDirs = [],
|
|
22900
22928
|
codexGeneratedImagesDir,
|
|
22901
|
-
existsSync: existsSync3 =
|
|
22929
|
+
existsSync: existsSync3 = fs8.existsSync
|
|
22902
22930
|
}) {
|
|
22903
22931
|
const isCodex = typeof agentId === "string" && agentId.trim().toLowerCase() === "codex";
|
|
22904
|
-
const candidates = isCodex ? [codexGeneratedImagesDir] : [
|
|
22905
|
-
brandGuidelinesDir,
|
|
22906
|
-
...Array.isArray(linkedDirs) ? linkedDirs : []
|
|
22907
|
-
];
|
|
22932
|
+
const candidates = isCodex ? [codexGeneratedImagesDir] : [brandGuidelinesDir, ...Array.isArray(linkedDirs) ? linkedDirs : []];
|
|
22908
22933
|
return Array.from(
|
|
22909
22934
|
new Set(
|
|
22910
22935
|
candidates.filter(
|
|
@@ -23032,27 +23057,27 @@ function formatAttachmentPosition(position) {
|
|
|
23032
23057
|
return `x=${position.x}, y=${position.y}, width=${position.width}, height=${position.height}`;
|
|
23033
23058
|
}
|
|
23034
23059
|
function isPathWithin(base, target) {
|
|
23035
|
-
const relativePath =
|
|
23036
|
-
return relativePath === "" || relativePath.length > 0 && !relativePath.startsWith("..") && !
|
|
23060
|
+
const relativePath = path29.relative(path29.resolve(base), path29.resolve(target));
|
|
23061
|
+
return relativePath === "" || relativePath.length > 0 && !relativePath.startsWith("..") && !path29.isAbsolute(relativePath);
|
|
23037
23062
|
}
|
|
23038
23063
|
function resolveProcessResourcesPath() {
|
|
23039
23064
|
if (typeof process.resourcesPath === "string" && process.resourcesPath.length > 0) {
|
|
23040
23065
|
return process.resourcesPath;
|
|
23041
23066
|
}
|
|
23042
|
-
const resourcesMarker = `${
|
|
23067
|
+
const resourcesMarker = `${path29.sep}Contents${path29.sep}Resources${path29.sep}`;
|
|
23043
23068
|
const markerIndex = process.execPath.indexOf(resourcesMarker);
|
|
23044
23069
|
if (markerIndex !== -1) {
|
|
23045
23070
|
return process.execPath.slice(0, markerIndex + resourcesMarker.length - 1);
|
|
23046
23071
|
}
|
|
23047
23072
|
const normalizedExecPath = process.execPath.toLowerCase();
|
|
23048
|
-
const windowsResourceBinMarker = `${
|
|
23073
|
+
const windowsResourceBinMarker = `${path29.sep}resources${path29.sep}open-design${path29.sep}bin${path29.sep}`.toLowerCase();
|
|
23049
23074
|
const windowsMarkerIndex = normalizedExecPath.indexOf(
|
|
23050
23075
|
windowsResourceBinMarker
|
|
23051
23076
|
);
|
|
23052
23077
|
if (windowsMarkerIndex !== -1) {
|
|
23053
23078
|
return process.execPath.slice(
|
|
23054
23079
|
0,
|
|
23055
|
-
windowsMarkerIndex + `${
|
|
23080
|
+
windowsMarkerIndex + `${path29.sep}resources`.length
|
|
23056
23081
|
);
|
|
23057
23082
|
}
|
|
23058
23083
|
return null;
|
|
@@ -23062,8 +23087,8 @@ function resolveDaemonResourceRoot({
|
|
|
23062
23087
|
safeBases = [PROJECT_ROOT, resolveProcessResourcesPath()]
|
|
23063
23088
|
} = {}) {
|
|
23064
23089
|
if (!configured || configured.length === 0) return null;
|
|
23065
|
-
const resolved =
|
|
23066
|
-
const normalizedSafeBases = safeBases.filter((base) => typeof base === "string" && base.length > 0).map((base) =>
|
|
23090
|
+
const resolved = path29.resolve(configured);
|
|
23091
|
+
const normalizedSafeBases = safeBases.filter((base) => typeof base === "string" && base.length > 0).map((base) => path29.resolve(base));
|
|
23067
23092
|
if (!normalizedSafeBases.some((base) => isPathWithin(base, resolved))) {
|
|
23068
23093
|
throw new Error(
|
|
23069
23094
|
`${RESOURCE_ROOT_ENV} must be under the workspace root or app resources path`
|
|
@@ -23072,78 +23097,84 @@ function resolveDaemonResourceRoot({
|
|
|
23072
23097
|
return resolved;
|
|
23073
23098
|
}
|
|
23074
23099
|
function resolveDaemonResourceDir(resourceRoot, segment, fallback) {
|
|
23075
|
-
return resourceRoot ?
|
|
23100
|
+
return resourceRoot ? path29.join(resourceRoot, segment) : fallback;
|
|
23076
23101
|
}
|
|
23077
23102
|
var DAEMON_RESOURCE_ROOT = resolveDaemonResourceRoot();
|
|
23078
|
-
var STATIC_DIR =
|
|
23103
|
+
var STATIC_DIR = path29.join(PROJECT_ROOT, "apps", "web", "out");
|
|
23079
23104
|
var OD_BIN = resolveDaemonCliPath();
|
|
23080
23105
|
var OD_NODE_BIN = process.execPath;
|
|
23081
23106
|
var BRAND_GUIDELINES_DIR = resolveDaemonResourceDir(
|
|
23082
23107
|
DAEMON_RESOURCE_ROOT,
|
|
23083
23108
|
"brand-guidelines",
|
|
23084
|
-
|
|
23109
|
+
path29.join(PROJECT_ROOT, "brand-guidelines")
|
|
23085
23110
|
);
|
|
23086
23111
|
var CRAFT_DIR = resolveDaemonResourceDir(
|
|
23087
23112
|
DAEMON_RESOURCE_ROOT,
|
|
23088
23113
|
"craft",
|
|
23089
|
-
|
|
23114
|
+
path29.join(PROJECT_ROOT, "craft")
|
|
23090
23115
|
);
|
|
23091
23116
|
var FRAMES_DIR = resolveDaemonResourceDir(
|
|
23092
23117
|
DAEMON_RESOURCE_ROOT,
|
|
23093
23118
|
"frames",
|
|
23094
|
-
|
|
23119
|
+
path29.join(PROJECT_ROOT, "assets", "frames")
|
|
23095
23120
|
);
|
|
23096
23121
|
var BUNDLED_PETS_DIR = resolveDaemonResourceDir(
|
|
23097
23122
|
DAEMON_RESOURCE_ROOT,
|
|
23098
23123
|
"community-pets",
|
|
23099
|
-
|
|
23124
|
+
path29.join(PROJECT_ROOT, "assets", "community-pets")
|
|
23100
23125
|
);
|
|
23101
23126
|
var PROMPT_TEMPLATES_DIR = resolveDaemonResourceDir(
|
|
23102
23127
|
DAEMON_RESOURCE_ROOT,
|
|
23103
23128
|
"prompt-templates",
|
|
23104
|
-
|
|
23129
|
+
path29.join(PROJECT_ROOT, "prompt-templates")
|
|
23105
23130
|
);
|
|
23106
23131
|
var PROMPT_TEMPLATE_ASSETS_DIR = resolveDaemonResourceDir(
|
|
23107
23132
|
DAEMON_RESOURCE_ROOT,
|
|
23108
|
-
|
|
23109
|
-
|
|
23133
|
+
path29.join("assets", "prompt-templates"),
|
|
23134
|
+
path29.join(PROJECT_ROOT, "assets", "prompt-templates")
|
|
23110
23135
|
);
|
|
23111
23136
|
function resolveDataDir(raw, projectRoot) {
|
|
23112
|
-
if (!raw) return
|
|
23113
|
-
const expanded = raw.startsWith("~/") ?
|
|
23114
|
-
const resolved =
|
|
23137
|
+
if (!raw) return path29.join(projectRoot, ".od");
|
|
23138
|
+
const expanded = raw.startsWith("~/") ? path29.join(os4.homedir(), raw.slice(2)) : raw;
|
|
23139
|
+
const resolved = path29.isAbsolute(expanded) ? expanded : path29.resolve(projectRoot, expanded);
|
|
23115
23140
|
try {
|
|
23116
|
-
|
|
23117
|
-
|
|
23141
|
+
fs8.mkdirSync(resolved, { recursive: true });
|
|
23142
|
+
fs8.accessSync(resolved, fs8.constants.W_OK);
|
|
23118
23143
|
} catch (err) {
|
|
23119
23144
|
const e = err;
|
|
23120
23145
|
throw new Error(`OD_DATA_DIR "${resolved}" is not writable: ${e.message}`);
|
|
23121
23146
|
}
|
|
23122
23147
|
return resolved;
|
|
23123
23148
|
}
|
|
23124
|
-
var RUNTIME_DATA_DIR = resolveDataDir(
|
|
23125
|
-
|
|
23126
|
-
|
|
23127
|
-
|
|
23149
|
+
var RUNTIME_DATA_DIR = resolveDataDir(
|
|
23150
|
+
process.env.TFDESIGN_DATA_DIR || process.env.OD_DATA_DIR || defaultDataRoot(__dirname),
|
|
23151
|
+
PROJECT_ROOT
|
|
23152
|
+
);
|
|
23153
|
+
function dataRoot() {
|
|
23154
|
+
return RUNTIME_DATA_DIR;
|
|
23155
|
+
}
|
|
23156
|
+
var ARTIFACTS_DIR = path29.join(RUNTIME_DATA_DIR, "artifacts");
|
|
23157
|
+
var DEFAULT_PROJECTS_DIR = path29.join(RUNTIME_DATA_DIR, "projects");
|
|
23158
|
+
var USER_PROMPT_TEMPLATES_DIR = path29.join(
|
|
23128
23159
|
RUNTIME_DATA_DIR,
|
|
23129
23160
|
"prompt-templates"
|
|
23130
23161
|
);
|
|
23131
|
-
var USER_BRAND_GUIDELINES_DIR =
|
|
23162
|
+
var USER_BRAND_GUIDELINES_DIR = path29.join(
|
|
23132
23163
|
RUNTIME_DATA_DIR,
|
|
23133
23164
|
"brand-guidelines"
|
|
23134
23165
|
);
|
|
23135
|
-
var BRAND_ASSETS_DIR =
|
|
23136
|
-
|
|
23166
|
+
var BRAND_ASSETS_DIR = path29.join(RUNTIME_DATA_DIR, "brand-assets");
|
|
23167
|
+
fs8.mkdirSync(BRAND_ASSETS_DIR, { recursive: true });
|
|
23137
23168
|
function resolveProjectsDir(dataDir) {
|
|
23138
|
-
const overrideFile =
|
|
23169
|
+
const overrideFile = path29.join(dataDir, "projects-dir.json");
|
|
23139
23170
|
try {
|
|
23140
|
-
const raw =
|
|
23171
|
+
const raw = fs8.readFileSync(overrideFile, "utf8");
|
|
23141
23172
|
const parsed = JSON.parse(raw);
|
|
23142
23173
|
if (parsed && typeof parsed.projectsDir === "string" && parsed.projectsDir.trim()) {
|
|
23143
|
-
const expanded = parsed.projectsDir.startsWith("~/") ?
|
|
23144
|
-
const resolved =
|
|
23145
|
-
|
|
23146
|
-
|
|
23174
|
+
const expanded = parsed.projectsDir.startsWith("~/") ? path29.join(os4.homedir(), parsed.projectsDir.slice(2)) : parsed.projectsDir;
|
|
23175
|
+
const resolved = path29.isAbsolute(expanded) ? expanded : path29.resolve(dataDir, expanded);
|
|
23176
|
+
fs8.mkdirSync(resolved, { recursive: true });
|
|
23177
|
+
fs8.accessSync(resolved, fs8.constants.W_OK);
|
|
23147
23178
|
return resolved;
|
|
23148
23179
|
}
|
|
23149
23180
|
} catch {
|
|
@@ -23151,11 +23182,14 @@ function resolveProjectsDir(dataDir) {
|
|
|
23151
23182
|
return DEFAULT_PROJECTS_DIR;
|
|
23152
23183
|
}
|
|
23153
23184
|
var PROJECTS_DIR = resolveProjectsDir(RUNTIME_DATA_DIR);
|
|
23154
|
-
|
|
23155
|
-
var PROJECTS_DIR_OVERRIDE_FILE =
|
|
23156
|
-
|
|
23185
|
+
fs8.mkdirSync(PROJECTS_DIR, { recursive: true });
|
|
23186
|
+
var PROJECTS_DIR_OVERRIDE_FILE = path29.join(
|
|
23187
|
+
RUNTIME_DATA_DIR,
|
|
23188
|
+
"projects-dir.json"
|
|
23189
|
+
);
|
|
23190
|
+
if (!fs8.existsSync(PROJECTS_DIR_OVERRIDE_FILE) && process.env.OD_FORCE_STORAGE_UNCONFIGURED !== "1") {
|
|
23157
23191
|
try {
|
|
23158
|
-
|
|
23192
|
+
fs8.writeFileSync(
|
|
23159
23193
|
PROJECTS_DIR_OVERRIDE_FILE,
|
|
23160
23194
|
JSON.stringify({ projectsDir: DEFAULT_PROJECTS_DIR }, null, 2),
|
|
23161
23195
|
"utf8"
|
|
@@ -23518,9 +23552,9 @@ function openNativeFolderDialog() {
|
|
|
23518
23552
|
function createSseErrorPayload(code, message, init = {}) {
|
|
23519
23553
|
return { message, error: createCompatApiError(code, message, init) };
|
|
23520
23554
|
}
|
|
23521
|
-
var UPLOAD_DIR =
|
|
23522
|
-
|
|
23523
|
-
|
|
23555
|
+
var UPLOAD_DIR = path29.join(os4.tmpdir(), "od-uploads");
|
|
23556
|
+
fs8.mkdirSync(UPLOAD_DIR, { recursive: true });
|
|
23557
|
+
fs8.mkdirSync(ARTIFACTS_DIR, { recursive: true });
|
|
23524
23558
|
var upload = multer({
|
|
23525
23559
|
storage: multer.diskStorage({
|
|
23526
23560
|
destination: UPLOAD_DIR,
|
|
@@ -23555,7 +23589,10 @@ var brandAssetUpload = multer({
|
|
|
23555
23589
|
filename: (_req, file, cb) => {
|
|
23556
23590
|
file.originalname = decodeMultipartFilename(file.originalname);
|
|
23557
23591
|
const safe = sanitizeName(file.originalname);
|
|
23558
|
-
cb(
|
|
23592
|
+
cb(
|
|
23593
|
+
null,
|
|
23594
|
+
`${Date.now()}-${Math.random().toString(36).slice(2, 8)}-${safe}`
|
|
23595
|
+
);
|
|
23559
23596
|
}
|
|
23560
23597
|
}),
|
|
23561
23598
|
limits: { fileSize: 20 * 1024 * 1024 }
|
|
@@ -23792,12 +23829,16 @@ async function startServer({
|
|
|
23792
23829
|
} catch (error) {
|
|
23793
23830
|
console.warn("[od] Failed to reconcile projects from disk:", error);
|
|
23794
23831
|
}
|
|
23795
|
-
if (
|
|
23832
|
+
if (fs8.existsSync(STATIC_DIR)) {
|
|
23796
23833
|
app.use(express.static(STATIC_DIR));
|
|
23797
23834
|
}
|
|
23798
23835
|
app.get("/api/health", async (_req, res) => {
|
|
23799
23836
|
const versionInfo = await readCurrentAppVersionInfo();
|
|
23800
|
-
res.json({
|
|
23837
|
+
res.json({
|
|
23838
|
+
ok: true,
|
|
23839
|
+
version: versionInfo.version,
|
|
23840
|
+
dataRoot: RUNTIME_DATA_DIR
|
|
23841
|
+
});
|
|
23801
23842
|
});
|
|
23802
23843
|
app.get("/api/version", async (_req, res) => {
|
|
23803
23844
|
const version = await readCurrentAppVersionInfo();
|
|
@@ -23894,8 +23935,8 @@ async function startServer({
|
|
|
23894
23935
|
} catch (err) {
|
|
23895
23936
|
return sendApiError(res, 500, "CLI_RESOLVE_FAILED", String(err));
|
|
23896
23937
|
}
|
|
23897
|
-
const cliExists =
|
|
23898
|
-
const nodeExists =
|
|
23938
|
+
const cliExists = fs8.existsSync(cliPath);
|
|
23939
|
+
const nodeExists = fs8.existsSync(process.execPath);
|
|
23899
23940
|
const hints = [];
|
|
23900
23941
|
if (!cliExists) {
|
|
23901
23942
|
hints.push(
|
|
@@ -24173,7 +24214,7 @@ async function startServer({
|
|
|
24173
24214
|
return res.status(400).json({ error: "zip file required" });
|
|
24174
24215
|
const originalName = req.file.originalname || "Claude Design export.zip";
|
|
24175
24216
|
if (!/\.zip$/i.test(originalName)) {
|
|
24176
|
-
|
|
24217
|
+
fs8.promises.unlink(req.file.path).catch(() => {
|
|
24177
24218
|
});
|
|
24178
24219
|
return res.status(400).json({ error: "expected a .zip file" });
|
|
24179
24220
|
}
|
|
@@ -24184,7 +24225,7 @@ async function startServer({
|
|
|
24184
24225
|
req.file.path,
|
|
24185
24226
|
projectDir(PROJECTS_DIR, id)
|
|
24186
24227
|
);
|
|
24187
|
-
|
|
24228
|
+
fs8.promises.unlink(req.file.path).catch(() => {
|
|
24188
24229
|
});
|
|
24189
24230
|
const project = insertProject(db, {
|
|
24190
24231
|
id,
|
|
@@ -24216,7 +24257,7 @@ async function startServer({
|
|
|
24216
24257
|
files: imported.files
|
|
24217
24258
|
});
|
|
24218
24259
|
} catch (err) {
|
|
24219
|
-
if (req.file?.path)
|
|
24260
|
+
if (req.file?.path) fs8.promises.unlink(req.file.path).catch(() => {
|
|
24220
24261
|
});
|
|
24221
24262
|
res.status(400).json({ error: String(err) });
|
|
24222
24263
|
}
|
|
@@ -24225,7 +24266,7 @@ async function startServer({
|
|
|
24225
24266
|
app.post("/api/import/folder", async (req, res) => {
|
|
24226
24267
|
try {
|
|
24227
24268
|
const folderPath = typeof req.body?.folderPath === "string" ? req.body.folderPath : "";
|
|
24228
|
-
if (!folderPath || !
|
|
24269
|
+
if (!folderPath || !path29.isAbsolute(path29.normalize(folderPath))) {
|
|
24229
24270
|
return res.status(400).json({ error: "an absolute folderPath is required" });
|
|
24230
24271
|
}
|
|
24231
24272
|
const validated = validateProjectBaseDir(folderPath, {
|
|
@@ -24236,7 +24277,7 @@ async function startServer({
|
|
|
24236
24277
|
return res.status(400).json({ error: validated.error });
|
|
24237
24278
|
}
|
|
24238
24279
|
const realSource = validated.baseDir;
|
|
24239
|
-
if (PROJECTS_DIR && realSource.startsWith(PROJECTS_DIR +
|
|
24280
|
+
if (PROJECTS_DIR && realSource.startsWith(PROJECTS_DIR + path29.sep)) {
|
|
24240
24281
|
reconcileProjectsFromDisk(db, PROJECTS_DIR);
|
|
24241
24282
|
}
|
|
24242
24283
|
const existing = findProjectByDir(db, realSource, PROJECTS_DIR);
|
|
@@ -24272,7 +24313,7 @@ async function startServer({
|
|
|
24272
24313
|
});
|
|
24273
24314
|
const id = randomId();
|
|
24274
24315
|
const now = Date.now();
|
|
24275
|
-
const baseName =
|
|
24316
|
+
const baseName = path29.basename(realSource) || "Imported folder";
|
|
24276
24317
|
const project = insertProject(db, {
|
|
24277
24318
|
id,
|
|
24278
24319
|
name: baseName,
|
|
@@ -24731,7 +24772,10 @@ async function startServer({
|
|
|
24731
24772
|
});
|
|
24732
24773
|
app.get("/api/brand-guidelines", async (_req, res) => {
|
|
24733
24774
|
try {
|
|
24734
|
-
const systems = await listBrandGuidelines(
|
|
24775
|
+
const systems = await listBrandGuidelines(
|
|
24776
|
+
BRAND_GUIDELINES_DIR,
|
|
24777
|
+
USER_BRAND_GUIDELINES_DIR
|
|
24778
|
+
);
|
|
24735
24779
|
res.json({
|
|
24736
24780
|
brandGuidelines: systems.map(({ body, ...rest }) => rest)
|
|
24737
24781
|
});
|
|
@@ -24741,7 +24785,11 @@ async function startServer({
|
|
|
24741
24785
|
});
|
|
24742
24786
|
app.get("/api/brand-guidelines/:id", async (req, res) => {
|
|
24743
24787
|
try {
|
|
24744
|
-
const body = await readBrandGuideline(
|
|
24788
|
+
const body = await readBrandGuideline(
|
|
24789
|
+
BRAND_GUIDELINES_DIR,
|
|
24790
|
+
USER_BRAND_GUIDELINES_DIR,
|
|
24791
|
+
req.params.id
|
|
24792
|
+
);
|
|
24745
24793
|
if (body === null)
|
|
24746
24794
|
return res.status(404).json({ error: "brand guideline not found" });
|
|
24747
24795
|
res.json({ id: req.params.id, body });
|
|
@@ -24751,7 +24799,11 @@ async function startServer({
|
|
|
24751
24799
|
});
|
|
24752
24800
|
app.get("/api/brand-guidelines/:id/preview", async (req, res) => {
|
|
24753
24801
|
try {
|
|
24754
|
-
const body = await readBrandGuideline(
|
|
24802
|
+
const body = await readBrandGuideline(
|
|
24803
|
+
BRAND_GUIDELINES_DIR,
|
|
24804
|
+
USER_BRAND_GUIDELINES_DIR,
|
|
24805
|
+
req.params.id
|
|
24806
|
+
);
|
|
24755
24807
|
if (body === null)
|
|
24756
24808
|
return res.status(404).type("text/plain").send("not found");
|
|
24757
24809
|
const html = renderBrandGuidelinePreview(req.params.id, body);
|
|
@@ -24762,7 +24814,11 @@ async function startServer({
|
|
|
24762
24814
|
});
|
|
24763
24815
|
app.get("/api/brand-guidelines/:id/showcase", async (req, res) => {
|
|
24764
24816
|
try {
|
|
24765
|
-
const body = await readBrandGuideline(
|
|
24817
|
+
const body = await readBrandGuideline(
|
|
24818
|
+
BRAND_GUIDELINES_DIR,
|
|
24819
|
+
USER_BRAND_GUIDELINES_DIR,
|
|
24820
|
+
req.params.id
|
|
24821
|
+
);
|
|
24766
24822
|
if (body === null)
|
|
24767
24823
|
return res.status(404).type("text/plain").send("not found");
|
|
24768
24824
|
const html = renderBrandGuidelineShowcase(req.params.id, body);
|
|
@@ -24773,7 +24829,10 @@ async function startServer({
|
|
|
24773
24829
|
});
|
|
24774
24830
|
app.post("/api/brand-guidelines", async (req, res) => {
|
|
24775
24831
|
try {
|
|
24776
|
-
const created = await createUserBrandGuideline(
|
|
24832
|
+
const created = await createUserBrandGuideline(
|
|
24833
|
+
USER_BRAND_GUIDELINES_DIR,
|
|
24834
|
+
req.body ?? {}
|
|
24835
|
+
);
|
|
24777
24836
|
res.status(201).json({ brandGuideline: created });
|
|
24778
24837
|
} catch (err) {
|
|
24779
24838
|
res.status(500).json({ error: String(err) });
|
|
@@ -24786,7 +24845,8 @@ async function startServer({
|
|
|
24786
24845
|
req.params.id,
|
|
24787
24846
|
req.body ?? {}
|
|
24788
24847
|
);
|
|
24789
|
-
if (!updated)
|
|
24848
|
+
if (!updated)
|
|
24849
|
+
return res.status(404).json({ error: "brand guideline not found" });
|
|
24790
24850
|
res.json({ brandGuideline: updated });
|
|
24791
24851
|
} catch (err) {
|
|
24792
24852
|
res.status(500).json({ error: String(err) });
|
|
@@ -24794,8 +24854,12 @@ async function startServer({
|
|
|
24794
24854
|
});
|
|
24795
24855
|
app.delete("/api/brand-guidelines/:id", async (req, res) => {
|
|
24796
24856
|
try {
|
|
24797
|
-
const removed = await deleteUserBrandGuideline(
|
|
24798
|
-
|
|
24857
|
+
const removed = await deleteUserBrandGuideline(
|
|
24858
|
+
USER_BRAND_GUIDELINES_DIR,
|
|
24859
|
+
req.params.id
|
|
24860
|
+
);
|
|
24861
|
+
if (!removed)
|
|
24862
|
+
return res.status(404).json({ error: "brand guideline not found" });
|
|
24799
24863
|
res.json({ ok: true });
|
|
24800
24864
|
} catch (err) {
|
|
24801
24865
|
res.status(500).json({ error: String(err) });
|
|
@@ -24821,7 +24885,9 @@ async function startServer({
|
|
|
24821
24885
|
res.json(result);
|
|
24822
24886
|
} catch (err) {
|
|
24823
24887
|
const message = err instanceof Error ? err.message : String(err);
|
|
24824
|
-
const status = /non-public|blocked|unsupported protocol|invalid url|not html|too many redirects|fetch failed/i.test(
|
|
24888
|
+
const status = /non-public|blocked|unsupported protocol|invalid url|not html|too many redirects|fetch failed/i.test(
|
|
24889
|
+
message
|
|
24890
|
+
) ? 422 : 500;
|
|
24825
24891
|
res.status(status).json({ error: message });
|
|
24826
24892
|
}
|
|
24827
24893
|
});
|
|
@@ -24830,7 +24896,8 @@ async function startServer({
|
|
|
24830
24896
|
const repo = typeof req.body?.repo === "string" ? req.body.repo.trim() : "";
|
|
24831
24897
|
const url = typeof req.body?.url === "string" ? req.body.url.trim() : "";
|
|
24832
24898
|
const target = repo || url;
|
|
24833
|
-
if (!target)
|
|
24899
|
+
if (!target)
|
|
24900
|
+
return res.status(400).json({ error: "repo or url is required" });
|
|
24834
24901
|
const { id } = startGithubExtractionJob(target);
|
|
24835
24902
|
res.status(202).json({ runId: id, status: "running" });
|
|
24836
24903
|
} catch (err) {
|
|
@@ -24847,19 +24914,30 @@ async function startServer({
|
|
|
24847
24914
|
const body = typeof req.body?.body === "string" ? req.body.body : "";
|
|
24848
24915
|
const instruction = typeof req.body?.instruction === "string" ? req.body.instruction : "";
|
|
24849
24916
|
const history = Array.isArray(req.body?.history) ? req.body.history.filter((h) => typeof h === "string") : [];
|
|
24850
|
-
if (!body.trim())
|
|
24851
|
-
|
|
24917
|
+
if (!body.trim())
|
|
24918
|
+
return res.status(400).json({ error: "body is required" });
|
|
24919
|
+
if (!instruction.trim())
|
|
24920
|
+
return res.status(400).json({ error: "instruction is required" });
|
|
24852
24921
|
const refined = await refineDesignMd(body, instruction, history);
|
|
24853
24922
|
res.json({ body: refined });
|
|
24854
24923
|
} catch (err) {
|
|
24855
24924
|
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
24856
24925
|
}
|
|
24857
24926
|
});
|
|
24858
|
-
app.post(
|
|
24859
|
-
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
24927
|
+
app.post(
|
|
24928
|
+
"/api/brand-guidelines/upload-image",
|
|
24929
|
+
brandAssetUpload.single("image"),
|
|
24930
|
+
(req, res) => {
|
|
24931
|
+
const file = req.file;
|
|
24932
|
+
if (!file)
|
|
24933
|
+
return res.status(400).json({ error: "image file is required" });
|
|
24934
|
+
res.json({
|
|
24935
|
+
url: `/brand-assets/${file.filename}`,
|
|
24936
|
+
name: file.originalname,
|
|
24937
|
+
size: file.size
|
|
24938
|
+
});
|
|
24939
|
+
}
|
|
24940
|
+
);
|
|
24863
24941
|
app.get("/api/brand-guidelines/:id/file", async (req, res) => {
|
|
24864
24942
|
try {
|
|
24865
24943
|
const file = await readBrandGuidelineFile(
|
|
@@ -24904,14 +24982,14 @@ async function startServer({
|
|
|
24904
24982
|
}
|
|
24905
24983
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:T]/g, "-").slice(0, 19);
|
|
24906
24984
|
const slug = sanitizeSlug(identifier || title || "artifact");
|
|
24907
|
-
const dir =
|
|
24908
|
-
|
|
24909
|
-
const file =
|
|
24910
|
-
|
|
24985
|
+
const dir = path29.join(ARTIFACTS_DIR, `${stamp}-${slug}`);
|
|
24986
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
24987
|
+
const file = path29.join(dir, "index.html");
|
|
24988
|
+
fs8.writeFileSync(file, html, "utf8");
|
|
24911
24989
|
const findings = lintArtifact(html);
|
|
24912
24990
|
res.json({
|
|
24913
24991
|
path: file,
|
|
24914
|
-
url: `/artifacts/${
|
|
24992
|
+
url: `/artifacts/${path29.basename(dir)}/index.html`,
|
|
24915
24993
|
lint: findings
|
|
24916
24994
|
});
|
|
24917
24995
|
} catch (err) {
|
|
@@ -25954,7 +26032,7 @@ async function startServer({
|
|
|
25954
26032
|
const project = getProject(db, req.params.id);
|
|
25955
26033
|
await ensureProject(PROJECTS_DIR, req.params.id, project?.metadata);
|
|
25956
26034
|
if (req.file) {
|
|
25957
|
-
const buf2 = await
|
|
26035
|
+
const buf2 = await fs8.promises.readFile(req.file.path);
|
|
25958
26036
|
const desiredName = sanitizeName(
|
|
25959
26037
|
req.body?.name || req.file.originalname
|
|
25960
26038
|
);
|
|
@@ -25965,7 +26043,7 @@ async function startServer({
|
|
|
25965
26043
|
buf2,
|
|
25966
26044
|
{ metadata: project?.metadata }
|
|
25967
26045
|
);
|
|
25968
|
-
|
|
26046
|
+
fs8.promises.unlink(req.file.path).catch(() => {
|
|
25969
26047
|
});
|
|
25970
26048
|
const body2 = { file: meta2 };
|
|
25971
26049
|
return res.json(body2);
|
|
@@ -26112,7 +26190,7 @@ async function startServer({
|
|
|
26112
26190
|
res.json({
|
|
26113
26191
|
projectsDir: PROJECTS_DIR,
|
|
26114
26192
|
defaultProjectsDir: DEFAULT_PROJECTS_DIR,
|
|
26115
|
-
configured: process.env.OD_FORCE_STORAGE_UNCONFIGURED === "1" ? false :
|
|
26193
|
+
configured: process.env.OD_FORCE_STORAGE_UNCONFIGURED === "1" ? false : fs8.existsSync(path29.join(RUNTIME_DATA_DIR, "projects-dir.json")),
|
|
26116
26194
|
// Whether the current location is still the DEFAULT. The daemon
|
|
26117
26195
|
// records the default as the chosen location on first boot (see the
|
|
26118
26196
|
// auto-write next to PROJECTS_DIR), so `configured` is true out of
|
|
@@ -26134,16 +26212,16 @@ async function startServer({
|
|
|
26134
26212
|
if (typeof requested !== "string" || !requested.trim()) {
|
|
26135
26213
|
return res.status(400).json({ error: "projectsDir is required" });
|
|
26136
26214
|
}
|
|
26137
|
-
const expanded = requested.startsWith("~/") ?
|
|
26138
|
-
const resolved =
|
|
26215
|
+
const expanded = requested.startsWith("~/") ? path29.join(os4.homedir(), requested.slice(2)) : requested;
|
|
26216
|
+
const resolved = path29.isAbsolute(expanded) ? expanded : path29.resolve(RUNTIME_DATA_DIR, expanded);
|
|
26139
26217
|
try {
|
|
26140
|
-
|
|
26141
|
-
|
|
26218
|
+
fs8.mkdirSync(resolved, { recursive: true });
|
|
26219
|
+
fs8.accessSync(resolved, fs8.constants.W_OK);
|
|
26142
26220
|
} catch (e) {
|
|
26143
26221
|
return res.status(400).json({ error: `Path is not writable: ${e.message}` });
|
|
26144
26222
|
}
|
|
26145
|
-
const overrideFile =
|
|
26146
|
-
|
|
26223
|
+
const overrideFile = path29.join(RUNTIME_DATA_DIR, "projects-dir.json");
|
|
26224
|
+
fs8.writeFileSync(
|
|
26147
26225
|
overrideFile,
|
|
26148
26226
|
JSON.stringify({ projectsDir: requested }, null, 2),
|
|
26149
26227
|
"utf8"
|
|
@@ -26153,18 +26231,18 @@ async function startServer({
|
|
|
26153
26231
|
try {
|
|
26154
26232
|
const migrateSources = [
|
|
26155
26233
|
DEFAULT_PROJECTS_DIR,
|
|
26156
|
-
|
|
26234
|
+
path29.join(RUNTIME_DATA_DIR, "..", "tf-design-projects-backup")
|
|
26157
26235
|
];
|
|
26158
26236
|
let migrated = 0;
|
|
26159
26237
|
for (const srcDir of migrateSources) {
|
|
26160
|
-
if (!
|
|
26161
|
-
const entries =
|
|
26238
|
+
if (!fs8.existsSync(srcDir)) continue;
|
|
26239
|
+
const entries = fs8.readdirSync(srcDir, { withFileTypes: true });
|
|
26162
26240
|
for (const entry of entries) {
|
|
26163
26241
|
if (!entry.isDirectory()) continue;
|
|
26164
|
-
const src =
|
|
26165
|
-
const dst =
|
|
26166
|
-
if (
|
|
26167
|
-
|
|
26242
|
+
const src = path29.join(srcDir, entry.name);
|
|
26243
|
+
const dst = path29.join(PROJECTS_DIR, entry.name);
|
|
26244
|
+
if (fs8.existsSync(dst)) continue;
|
|
26245
|
+
fs8.cpSync(src, dst, { recursive: true });
|
|
26168
26246
|
migrated++;
|
|
26169
26247
|
}
|
|
26170
26248
|
}
|
|
@@ -26212,18 +26290,18 @@ async function startServer({
|
|
|
26212
26290
|
if (typeof target !== "string" || !target.trim()) {
|
|
26213
26291
|
return res.status(400).json({ error: "targetDir is required" });
|
|
26214
26292
|
}
|
|
26215
|
-
const expanded = target.startsWith("~/") ?
|
|
26216
|
-
const resolvedTarget =
|
|
26217
|
-
|
|
26293
|
+
const expanded = target.startsWith("~/") ? path29.join(os4.homedir(), target.slice(2)) : target;
|
|
26294
|
+
const resolvedTarget = path29.isAbsolute(expanded) ? expanded : path29.resolve(RUNTIME_DATA_DIR, expanded);
|
|
26295
|
+
fs8.mkdirSync(resolvedTarget, { recursive: true });
|
|
26218
26296
|
const sourceDir = PROJECTS_DIR;
|
|
26219
26297
|
let migrated = 0;
|
|
26220
|
-
const entries =
|
|
26298
|
+
const entries = fs8.readdirSync(sourceDir, { withFileTypes: true });
|
|
26221
26299
|
for (const entry of entries) {
|
|
26222
26300
|
if (!entry.isDirectory()) continue;
|
|
26223
|
-
const src =
|
|
26224
|
-
const dst =
|
|
26225
|
-
if (
|
|
26226
|
-
|
|
26301
|
+
const src = path29.join(sourceDir, entry.name);
|
|
26302
|
+
const dst = path29.join(resolvedTarget, entry.name);
|
|
26303
|
+
if (fs8.existsSync(dst)) continue;
|
|
26304
|
+
fs8.cpSync(src, dst, { recursive: true });
|
|
26227
26305
|
migrated++;
|
|
26228
26306
|
}
|
|
26229
26307
|
res.json({ migrated, targetDir: resolvedTarget });
|
|
@@ -26379,7 +26457,7 @@ async function startServer({
|
|
|
26379
26457
|
const out = [];
|
|
26380
26458
|
for (const f of incoming) {
|
|
26381
26459
|
try {
|
|
26382
|
-
const stat12 = await
|
|
26460
|
+
const stat12 = await fs8.promises.stat(f.path);
|
|
26383
26461
|
out.push({
|
|
26384
26462
|
name: f.filename,
|
|
26385
26463
|
path: f.filename,
|
|
@@ -26411,10 +26489,17 @@ async function startServer({
|
|
|
26411
26489
|
let brandGuidelineBody;
|
|
26412
26490
|
let brandGuidelineTitle;
|
|
26413
26491
|
if (effectiveBrandGuidelineId) {
|
|
26414
|
-
const systems = await listBrandGuidelines(
|
|
26492
|
+
const systems = await listBrandGuidelines(
|
|
26493
|
+
BRAND_GUIDELINES_DIR,
|
|
26494
|
+
USER_BRAND_GUIDELINES_DIR
|
|
26495
|
+
);
|
|
26415
26496
|
const summary = systems.find((s) => s.id === effectiveBrandGuidelineId);
|
|
26416
26497
|
brandGuidelineTitle = summary?.title;
|
|
26417
|
-
brandGuidelineBody = await readBrandGuideline(
|
|
26498
|
+
brandGuidelineBody = await readBrandGuideline(
|
|
26499
|
+
BRAND_GUIDELINES_DIR,
|
|
26500
|
+
USER_BRAND_GUIDELINES_DIR,
|
|
26501
|
+
effectiveBrandGuidelineId
|
|
26502
|
+
) ?? void 0;
|
|
26418
26503
|
}
|
|
26419
26504
|
const template = metadata?.kind === "template" && typeof metadata.templateId === "string" ? getTemplate(db, metadata.templateId) ?? void 0 : void 0;
|
|
26420
26505
|
const prompt = composeSystemPrompt({
|
|
@@ -26487,13 +26572,13 @@ async function startServer({
|
|
|
26487
26572
|
}
|
|
26488
26573
|
if (run.cancelRequested || design.runs.isTerminal(run.status)) return;
|
|
26489
26574
|
const safeImages = imagePaths.filter((p) => {
|
|
26490
|
-
const resolved =
|
|
26491
|
-
return resolved.startsWith(UPLOAD_DIR +
|
|
26575
|
+
const resolved = path29.resolve(p);
|
|
26576
|
+
return resolved.startsWith(UPLOAD_DIR + path29.sep) && fs8.existsSync(resolved);
|
|
26492
26577
|
});
|
|
26493
26578
|
const safeAttachments = cwd ? (Array.isArray(attachments) ? attachments : []).filter((p) => typeof p === "string" && p.length > 0).filter((p) => {
|
|
26494
26579
|
try {
|
|
26495
|
-
const abs =
|
|
26496
|
-
return (abs === cwd || abs.startsWith(cwd +
|
|
26580
|
+
const abs = path29.resolve(cwd, p);
|
|
26581
|
+
return (abs === cwd || abs.startsWith(cwd + path29.sep)) && fs8.existsSync(abs);
|
|
26497
26582
|
} catch {
|
|
26498
26583
|
return false;
|
|
26499
26584
|
}
|
|
@@ -26592,9 +26677,9 @@ Attached project files: ${safeAttachments.map((p) => `\`${p}\``).join(", ")}` :
|
|
|
26592
26677
|
if (cwd && typeof cwd === "string") {
|
|
26593
26678
|
for (const name of names) {
|
|
26594
26679
|
try {
|
|
26595
|
-
const abs =
|
|
26596
|
-
if (abs !== cwd && abs.startsWith(cwd +
|
|
26597
|
-
const content =
|
|
26680
|
+
const abs = path29.resolve(cwd, name);
|
|
26681
|
+
if (abs !== cwd && abs.startsWith(cwd + path29.sep)) {
|
|
26682
|
+
const content = fs8.readFileSync(abs, "utf8");
|
|
26598
26683
|
if (content.length <= MAX_PER_FILE && used + content.length <= MAX_TOTAL) {
|
|
26599
26684
|
used += content.length;
|
|
26600
26685
|
snapshot += `
|
|
@@ -26795,8 +26880,8 @@ ${safeImages.map((p) => `@${p}`).join(" ")}` : ""
|
|
|
26795
26880
|
if (names.length === 0 || !cwd || typeof cwd !== "string") return {};
|
|
26796
26881
|
const abs = names.map((n) => {
|
|
26797
26882
|
try {
|
|
26798
|
-
const resolved =
|
|
26799
|
-
if (resolved === cwd || !resolved.startsWith(cwd +
|
|
26883
|
+
const resolved = path29.resolve(cwd, n);
|
|
26884
|
+
if (resolved === cwd || !resolved.startsWith(cwd + path29.sep))
|
|
26800
26885
|
return null;
|
|
26801
26886
|
return resolved;
|
|
26802
26887
|
} catch {
|
|
@@ -26804,7 +26889,7 @@ ${safeImages.map((p) => `@${p}`).join(" ")}` : ""
|
|
|
26804
26889
|
}
|
|
26805
26890
|
}).filter((p) => typeof p === "string");
|
|
26806
26891
|
if (abs.length === 0) return {};
|
|
26807
|
-
return { OD_MANUAL_EDIT_FILES: abs.join(
|
|
26892
|
+
return { OD_MANUAL_EDIT_FILES: abs.join(path29.delimiter) };
|
|
26808
26893
|
})();
|
|
26809
26894
|
const env = {
|
|
26810
26895
|
...spawnEnvForAgent(
|
|
@@ -26876,7 +26961,7 @@ ${safeImages.map((p) => `@${p}`).join(" ")}` : ""
|
|
|
26876
26961
|
} else {
|
|
26877
26962
|
const critiqueRunId = run.id;
|
|
26878
26963
|
const critiqueProjectKey = typeof projectId === "string" && projectId ? projectId : critiqueRunId;
|
|
26879
|
-
const critiqueArtifactDir =
|
|
26964
|
+
const critiqueArtifactDir = path29.join(
|
|
26880
26965
|
ARTIFACTS_DIR,
|
|
26881
26966
|
critiqueProjectKey,
|
|
26882
26967
|
critiqueRunId
|
|
@@ -27126,10 +27211,10 @@ ${safeImages.map((p) => `@${p}`).join(" ")}` : ""
|
|
|
27126
27211
|
}
|
|
27127
27212
|
});
|
|
27128
27213
|
};
|
|
27129
|
-
const appendVersionedApiPath = (baseUrl,
|
|
27214
|
+
const appendVersionedApiPath = (baseUrl, path30) => {
|
|
27130
27215
|
const url = new URL(baseUrl);
|
|
27131
27216
|
const trimmed = url.pathname.replace(/\/+$/, "");
|
|
27132
|
-
url.pathname = /\/v\d+(\/|$)/.test(trimmed) ? `${trimmed}${
|
|
27217
|
+
url.pathname = /\/v\d+(\/|$)/.test(trimmed) ? `${trimmed}${path30}` : `${trimmed}/v1${path30}`;
|
|
27133
27218
|
return url.toString();
|
|
27134
27219
|
};
|
|
27135
27220
|
const collectSseFrame = (frame) => {
|
|
@@ -27653,6 +27738,8 @@ function isLocalSameOrigin(req, port) {
|
|
|
27653
27738
|
}
|
|
27654
27739
|
|
|
27655
27740
|
export {
|
|
27741
|
+
detectLayout,
|
|
27742
|
+
resolveDataRoot,
|
|
27656
27743
|
resolveProjectRoot,
|
|
27657
27744
|
resolveDaemonCliPath,
|
|
27658
27745
|
composeLiveInstructionPrompt,
|
|
@@ -27664,6 +27751,7 @@ export {
|
|
|
27664
27751
|
renderCommentAttachmentHint,
|
|
27665
27752
|
resolveDaemonResourceRoot,
|
|
27666
27753
|
resolveDataDir,
|
|
27754
|
+
dataRoot,
|
|
27667
27755
|
resolveProjectsDir,
|
|
27668
27756
|
SSE_KEEPALIVE_INTERVAL_MS,
|
|
27669
27757
|
createAgentRuntimeEnv,
|