agentful 0.4.6 → 0.4.7
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/README.md +9 -3
- package/dist/index.cjs +382 -195
- package/package.json +1 -1
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/example.d.ts +0 -2
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/example.js +0 -16
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/index.d.ts +0 -267
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/index.js +0 -1
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/shell.d.ts +0 -109
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/shell.js +0 -1
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/tool.d.ts +0 -46
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/tool.js +0 -5
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/tui.d.ts +0 -429
- package/assets/tools/node_modules/@opencode-ai/plugin/dist/tui.js +0 -1
- package/assets/tools/node_modules/@opencode-ai/plugin/package.json +0 -52
package/dist/index.cjs
CHANGED
|
@@ -33,9 +33,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
33
|
mod
|
|
34
34
|
));
|
|
35
35
|
|
|
36
|
-
// node_modules/commander/lib/error.js
|
|
36
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/error.js
|
|
37
37
|
var require_error = __commonJS({
|
|
38
|
-
"node_modules/commander/lib/error.js"(exports2) {
|
|
38
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/error.js"(exports2) {
|
|
39
39
|
"use strict";
|
|
40
40
|
var CommanderError2 = class extends Error {
|
|
41
41
|
/**
|
|
@@ -69,9 +69,9 @@ var require_error = __commonJS({
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
// node_modules/commander/lib/argument.js
|
|
72
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/argument.js
|
|
73
73
|
var require_argument = __commonJS({
|
|
74
|
-
"node_modules/commander/lib/argument.js"(exports2) {
|
|
74
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/argument.js"(exports2) {
|
|
75
75
|
"use strict";
|
|
76
76
|
var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
|
|
77
77
|
var Argument2 = class {
|
|
@@ -197,9 +197,9 @@ var require_argument = __commonJS({
|
|
|
197
197
|
}
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
-
// node_modules/commander/lib/help.js
|
|
200
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/help.js
|
|
201
201
|
var require_help = __commonJS({
|
|
202
|
-
"node_modules/commander/lib/help.js"(exports2) {
|
|
202
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/help.js"(exports2) {
|
|
203
203
|
"use strict";
|
|
204
204
|
var { humanReadableArgName } = require_argument();
|
|
205
205
|
var Help2 = class {
|
|
@@ -612,9 +612,9 @@ var require_help = __commonJS({
|
|
|
612
612
|
}
|
|
613
613
|
});
|
|
614
614
|
|
|
615
|
-
// node_modules/commander/lib/option.js
|
|
615
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/option.js
|
|
616
616
|
var require_option = __commonJS({
|
|
617
|
-
"node_modules/commander/lib/option.js"(exports2) {
|
|
617
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/option.js"(exports2) {
|
|
618
618
|
"use strict";
|
|
619
619
|
var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
|
|
620
620
|
var Option2 = class {
|
|
@@ -885,9 +885,9 @@ var require_option = __commonJS({
|
|
|
885
885
|
}
|
|
886
886
|
});
|
|
887
887
|
|
|
888
|
-
// node_modules/commander/lib/suggestSimilar.js
|
|
888
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/suggestSimilar.js
|
|
889
889
|
var require_suggestSimilar = __commonJS({
|
|
890
|
-
"node_modules/commander/lib/suggestSimilar.js"(exports2) {
|
|
890
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/suggestSimilar.js"(exports2) {
|
|
891
891
|
"use strict";
|
|
892
892
|
var maxDistance = 3;
|
|
893
893
|
function editDistance(a, b) {
|
|
@@ -966,9 +966,9 @@ var require_suggestSimilar = __commonJS({
|
|
|
966
966
|
}
|
|
967
967
|
});
|
|
968
968
|
|
|
969
|
-
// node_modules/commander/lib/command.js
|
|
969
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/command.js
|
|
970
970
|
var require_command = __commonJS({
|
|
971
|
-
"node_modules/commander/lib/command.js"(exports2) {
|
|
971
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/lib/command.js"(exports2) {
|
|
972
972
|
"use strict";
|
|
973
973
|
var EventEmitter = require("events").EventEmitter;
|
|
974
974
|
var childProcess = require("child_process");
|
|
@@ -3010,9 +3010,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3010
3010
|
}
|
|
3011
3011
|
});
|
|
3012
3012
|
|
|
3013
|
-
// node_modules/commander/index.js
|
|
3013
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/index.js
|
|
3014
3014
|
var require_commander = __commonJS({
|
|
3015
|
-
"node_modules/commander/index.js"(exports2) {
|
|
3015
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/index.js"(exports2) {
|
|
3016
3016
|
"use strict";
|
|
3017
3017
|
var { Argument: Argument2 } = require_argument();
|
|
3018
3018
|
var { Command: Command2 } = require_command();
|
|
@@ -3044,7 +3044,7 @@ var VERSION, brand, useColor, wrap, paint, tuiDesign, sym, ui;
|
|
|
3044
3044
|
var init_branding = __esm({
|
|
3045
3045
|
"src/branding.ts"() {
|
|
3046
3046
|
"use strict";
|
|
3047
|
-
VERSION = "0.4.
|
|
3047
|
+
VERSION = "0.4.7" ? "0.4.7" : null.version;
|
|
3048
3048
|
brand = {
|
|
3049
3049
|
name: "agentful",
|
|
3050
3050
|
// the command users type
|
|
@@ -3103,9 +3103,9 @@ var init_branding = __esm({
|
|
|
3103
3103
|
}
|
|
3104
3104
|
});
|
|
3105
3105
|
|
|
3106
|
-
// node_modules/ignore/index.js
|
|
3106
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/ignore/index.js
|
|
3107
3107
|
var require_ignore = __commonJS({
|
|
3108
|
-
"node_modules/ignore/index.js"(exports2, module2) {
|
|
3108
|
+
"../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/ignore/index.js"(exports2, module2) {
|
|
3109
3109
|
"use strict";
|
|
3110
3110
|
function makeArray(subject) {
|
|
3111
3111
|
return Array.isArray(subject) ? subject : [subject];
|
|
@@ -3824,7 +3824,7 @@ var init_plugin = __esm({
|
|
|
3824
3824
|
}
|
|
3825
3825
|
});
|
|
3826
3826
|
|
|
3827
|
-
// node_modules/commander/esm.mjs
|
|
3827
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/commander/esm.mjs
|
|
3828
3828
|
var import_index = __toESM(require_commander(), 1);
|
|
3829
3829
|
var {
|
|
3830
3830
|
program,
|
|
@@ -4785,7 +4785,7 @@ init_branding();
|
|
|
4785
4785
|
var import_node_fs4 = require("fs");
|
|
4786
4786
|
var import_node_path6 = require("path");
|
|
4787
4787
|
|
|
4788
|
-
// node_modules/fflate/esm/index.mjs
|
|
4788
|
+
// ../../../../../../../../Users/gn/Labor/mainmvp/cli/node_modules/fflate/esm/index.mjs
|
|
4789
4789
|
var import_module = require("module");
|
|
4790
4790
|
var require2 = (0, import_module.createRequire)("/");
|
|
4791
4791
|
var _a;
|
|
@@ -5597,18 +5597,28 @@ function detectDistDir(rootDir, override) {
|
|
|
5597
5597
|
}
|
|
5598
5598
|
|
|
5599
5599
|
// src/lib/preflight.ts
|
|
5600
|
-
var
|
|
5601
|
-
var
|
|
5600
|
+
var import_node_fs6 = require("fs");
|
|
5601
|
+
var import_node_path8 = require("path");
|
|
5602
5602
|
|
|
5603
5603
|
// ../platform-contract/contract.json
|
|
5604
5604
|
var contract_default = {
|
|
5605
5605
|
$comment: "Single source of truth for the platform publish contract (PRD AP6a, planned/cli-push-to-workspace-transition-findings-and-prd-2026-08-17.md). Consumers: cli/src/lib/preflight.ts renders directly from this file; build engine (infrastructure/lambda/build-engine/handler.ts) and executor (opencode-lambda/executor/runtime/opencode_runner.py) are parity-checked against it by ./check-parity.py until AP4/AP5 move them onto it; AP0 instructions/skills render from it later. Bump schema_version on breaking shape changes. See README.md.",
|
|
5606
5606
|
schema_version: 1,
|
|
5607
|
-
contract_statement: "This platform publishes static files. Your app has no server process of its own \u2014 server-side logic runs as Managed Server Actions (short request/response functions) or on an API of your own that you connect. You cannot set build-time env vars or secrets:
|
|
5607
|
+
contract_statement: "This platform publishes static files. Your app has no server process of its own \u2014 server-side logic runs as Managed Server Actions (short request/response functions) or on an API of your own that you connect. You cannot set build-time env vars or secrets: every cloud build injects the same fixed allowlist of public client values, and nothing else.",
|
|
5608
5608
|
publish: {
|
|
5609
5609
|
server_process: false,
|
|
5610
5610
|
build_env_vars: false,
|
|
5611
|
-
$comment_build_env: "false = nobody can SET a build variable or build secret. Two build paths exist and
|
|
5611
|
+
$comment_build_env: "false = nobody can SET a build variable or build secret. Two build paths exist \u2014 the workspace executor (end of an agent turn) and the build engine (the workspace's Build button and `agentful push`) \u2014 and both inject the SAME fixed allowlist of PUBLIC client values, listed under build_env. The values come from one function on both paths (aws-services/workspace-manager/client_config.py); check-parity.py (check 13) pins the names. Until 2026-09 the build engine injected nothing, so an app that read import.meta.env.VITE_SUPABASE_URL worked after the agent's turn and lost its database on the next Build click \u2014 without a build error. A public value outside the allowlist still belongs in an ordinary source constant.",
|
|
5612
|
+
build_env: {
|
|
5613
|
+
$comment: "What a cloud build defines, and nothing else. `injected` = suffix x prefixes; `when: byo_supabase` means only while the project's Backend tab has an own Supabase database connected (URL + publishable key; a secret key stored in that slot is refused, never shipped). A read of <public prefix><injected suffix> that the build does NOT define fails the build (422 undefined_build_env): undefined there is a broken app, not a default. Any other read of a public-prefixed name that nothing defines is a warning, because `import.meta.env.VITE_API_BASE ?? '/api'` is a legitimate pattern. `bundler_builtins` are set by the framework itself and are never reported.",
|
|
5614
|
+
public_prefixes: ["VITE_", "PUBLIC_", "NEXT_PUBLIC_"],
|
|
5615
|
+
injected: [
|
|
5616
|
+
{ suffix: "PROJECT_ID", prefixes: ["VITE_", "PUBLIC_"], when: "always" },
|
|
5617
|
+
{ suffix: "SUPABASE_URL", prefixes: ["VITE_", "PUBLIC_", "NEXT_PUBLIC_"], when: "byo_supabase" },
|
|
5618
|
+
{ suffix: "SUPABASE_ANON_KEY", prefixes: ["VITE_", "PUBLIC_", "NEXT_PUBLIC_"], when: "byo_supabase" }
|
|
5619
|
+
],
|
|
5620
|
+
bundler_builtins: ["PUBLIC_URL"]
|
|
5621
|
+
},
|
|
5612
5622
|
published_prefix: "dist/",
|
|
5613
5623
|
canonical_output_check: "root_index_html",
|
|
5614
5624
|
$comment_output: "Canonical end-to-end contract (AP4): a root-level index.html inside the framework's output dir. Deliberately stricter than the executor's historical index.htm/200.html acceptance \u2014 both builders converge on THIS, not on each other (deployment gate and publish self-heal require dist/index.html)."
|
|
@@ -5806,7 +5816,7 @@ var contract_default = {
|
|
|
5806
5816
|
build_attempt_schema: {
|
|
5807
5817
|
file: "deployments/latest-build.json",
|
|
5808
5818
|
status_values: ["running", "success", "failed"],
|
|
5809
|
-
phase_codes: ["unsupported_project_type", "install", "build", "missing_output", "upload"],
|
|
5819
|
+
phase_codes: ["unsupported_project_type", "client_env", "install", "build", "missing_output", "upload"],
|
|
5810
5820
|
fields: {
|
|
5811
5821
|
schema_version: "int \u2014 copy of this contract's schema_version",
|
|
5812
5822
|
build_id: "string \u2014 unique per attempt",
|
|
@@ -5826,6 +5836,154 @@ var contract_default = {
|
|
|
5826
5836
|
}
|
|
5827
5837
|
};
|
|
5828
5838
|
|
|
5839
|
+
// ../platform-contract/buildEnv.ts
|
|
5840
|
+
var import_node_fs5 = require("fs");
|
|
5841
|
+
var import_node_path7 = require("path");
|
|
5842
|
+
var BUILD_ENV = contract_default.publish.build_env;
|
|
5843
|
+
var PUBLIC_PREFIXES = BUILD_ENV.public_prefixes;
|
|
5844
|
+
var BUILTINS = new Set(BUILD_ENV.bundler_builtins);
|
|
5845
|
+
var INJECTABLE_NAMES = new Set(
|
|
5846
|
+
BUILD_ENV.injected.flatMap((e) => e.prefixes.map((p) => `${p}${e.suffix}`))
|
|
5847
|
+
);
|
|
5848
|
+
var ALWAYS_DEFINED_NAMES = new Set(
|
|
5849
|
+
BUILD_ENV.injected.filter((e) => e.when === "always").flatMap((e) => e.prefixes.map((p) => `${p}${e.suffix}`))
|
|
5850
|
+
);
|
|
5851
|
+
var splitName = (name) => {
|
|
5852
|
+
const prefix = PUBLIC_PREFIXES.find((p) => name.startsWith(p));
|
|
5853
|
+
return prefix ? { prefix, suffix: name.slice(prefix.length) } : null;
|
|
5854
|
+
};
|
|
5855
|
+
var injectedEntry = (suffix) => BUILD_ENV.injected.find((e) => e.suffix === suffix);
|
|
5856
|
+
var SCAN_FILE = /\.(js|jsx|ts|tsx|mjs|cjs|vue|svelte|astro)$/;
|
|
5857
|
+
var SKIP_FILE = /\.d\.ts$|\.(test|spec)\.[a-z]+$/;
|
|
5858
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".next", ".git", "dist", "build", "out", ".nuxt", ".output", "coverage"]);
|
|
5859
|
+
var SCAN_FILE_BUDGET = 5e3;
|
|
5860
|
+
var MAX_SCAN_BYTES = 1024 * 1024;
|
|
5861
|
+
var ENV_OBJECT = String.raw`(?:import\.meta\.env|process\.env)`;
|
|
5862
|
+
var MEMBER_READ = new RegExp(
|
|
5863
|
+
String.raw`\b${ENV_OBJECT}\s*(?:\??\.\s*([A-Z][A-Z0-9_]*)|\[\s*['"]([A-Z][A-Z0-9_]*)['"]\s*\])(\s*(?:\?\?|\|\|))?`,
|
|
5864
|
+
"g"
|
|
5865
|
+
);
|
|
5866
|
+
var DESTRUCTURED_READ = new RegExp(String.raw`\{([^{}]*)\}\s*=\s*${ENV_OBJECT}\b`, "g");
|
|
5867
|
+
var QUOTED = /'(?:[^'\\\n]|\\.)*'|"(?:[^"\\\n]|\\.)*"/g;
|
|
5868
|
+
var MENTIONS_ENV = /\benv\s*[.[]/;
|
|
5869
|
+
var stripNonCode = (text) => text.replace(QUOTED, (quoted) => MENTIONS_ENV.test(quoted) ? "''" : quoted).replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:'"`\\])\/\/[^\n]*/g, "$1");
|
|
5870
|
+
var isReportable = (name) => !BUILTINS.has(name) && splitName(name) !== null;
|
|
5871
|
+
function collectFiles2(dir, out, budget) {
|
|
5872
|
+
if (budget.left <= 0 || !(0, import_node_fs5.existsSync)(dir)) return;
|
|
5873
|
+
for (const entry of (0, import_node_fs5.readdirSync)(dir, { withFileTypes: true })) {
|
|
5874
|
+
if (budget.left <= 0) return;
|
|
5875
|
+
const abs = (0, import_node_path7.join)(dir, entry.name);
|
|
5876
|
+
if (entry.isDirectory()) {
|
|
5877
|
+
if (!SKIP_DIRS.has(entry.name)) collectFiles2(abs, out, budget);
|
|
5878
|
+
} else if (entry.isFile() && SCAN_FILE.test(entry.name) && !SKIP_FILE.test(entry.name)) {
|
|
5879
|
+
budget.left--;
|
|
5880
|
+
out.push(abs);
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
function scanEnvReads(rootDir) {
|
|
5885
|
+
const files = [];
|
|
5886
|
+
collectFiles2(rootDir, files, { left: SCAN_FILE_BUDGET });
|
|
5887
|
+
const reads = [];
|
|
5888
|
+
for (const abs of files) {
|
|
5889
|
+
let text;
|
|
5890
|
+
try {
|
|
5891
|
+
text = (0, import_node_fs5.readFileSync)(abs, "utf8");
|
|
5892
|
+
} catch {
|
|
5893
|
+
continue;
|
|
5894
|
+
}
|
|
5895
|
+
if (text.length > MAX_SCAN_BYTES || !/\benv\b/.test(text)) continue;
|
|
5896
|
+
text = stripNonCode(text);
|
|
5897
|
+
const inFile = /* @__PURE__ */ new Map();
|
|
5898
|
+
const note = (name, hasFallback) => {
|
|
5899
|
+
if (isReportable(name)) inFile.set(name, (inFile.get(name) ?? true) && hasFallback);
|
|
5900
|
+
};
|
|
5901
|
+
for (const m of text.matchAll(MEMBER_READ)) note(m[1] || m[2], Boolean(m[3]));
|
|
5902
|
+
for (const m of text.matchAll(DESTRUCTURED_READ)) {
|
|
5903
|
+
for (const part of m[1].split(",")) {
|
|
5904
|
+
const field = /^\s*([A-Z][A-Z0-9_]*)\s*(?::\s*[A-Za-z_$][\w$]*\s*)?(=)?/.exec(part);
|
|
5905
|
+
if (field) note(field[1], Boolean(field[2]));
|
|
5906
|
+
}
|
|
5907
|
+
}
|
|
5908
|
+
const file = (0, import_node_path7.relative)(rootDir, abs).split(import_node_path7.sep).join("/");
|
|
5909
|
+
for (const [name, hasFallback] of inFile) reads.push({ name, file, hasFallback });
|
|
5910
|
+
}
|
|
5911
|
+
return reads;
|
|
5912
|
+
}
|
|
5913
|
+
function envFileNames(rootDir) {
|
|
5914
|
+
const names = /* @__PURE__ */ new Set();
|
|
5915
|
+
if (!(0, import_node_fs5.existsSync)(rootDir)) return names;
|
|
5916
|
+
for (const entry of (0, import_node_fs5.readdirSync)(rootDir, { withFileTypes: true })) {
|
|
5917
|
+
if (!entry.isFile() || !(entry.name === ".env" || entry.name.startsWith(".env."))) continue;
|
|
5918
|
+
let text;
|
|
5919
|
+
try {
|
|
5920
|
+
text = (0, import_node_fs5.readFileSync)((0, import_node_path7.join)(rootDir, entry.name), "utf8");
|
|
5921
|
+
} catch {
|
|
5922
|
+
continue;
|
|
5923
|
+
}
|
|
5924
|
+
for (const line of text.split("\n")) {
|
|
5925
|
+
const m = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
|
|
5926
|
+
if (m) names.add(m[1]);
|
|
5927
|
+
}
|
|
5928
|
+
}
|
|
5929
|
+
return names;
|
|
5930
|
+
}
|
|
5931
|
+
var sampleFiles = (files) => files.slice(0, 3).join(", ") + (files.length > 3 ? ", \u2026" : "");
|
|
5932
|
+
var prefixList = (prefixes) => prefixes.map((p) => `${p}*`).join("/");
|
|
5933
|
+
function platformHint(name, opts) {
|
|
5934
|
+
const { prefix, suffix } = splitName(name);
|
|
5935
|
+
const entry = injectedEntry(suffix);
|
|
5936
|
+
if (!entry.prefixes.includes(prefix)) {
|
|
5937
|
+
return `The platform defines ${suffix} only as ${entry.prefixes.map((p) => `${p}${suffix}`).join(" and ")} \u2014 read one of those, or keep the value in an ordinary source constant.`;
|
|
5938
|
+
}
|
|
5939
|
+
if (entry.when === "byo_supabase") {
|
|
5940
|
+
if ((opts.rejected || []).includes(suffix)) {
|
|
5941
|
+
return "The key stored for this database looks like a Supabase SECRET key. The platform refuses to put it into a public bundle \u2014 store the publishable (anon) key as `database.anon_key` in the Backend tab instead.";
|
|
5942
|
+
}
|
|
5943
|
+
if (opts.provider === "supabase" && (opts.missing || []).includes(suffix)) {
|
|
5944
|
+
return suffix === "SUPABASE_URL" ? "Your own Supabase database is connected, but no https project URL is stored \u2014 set it in the Backend tab (Database)." : "Your own Supabase database is connected, but no publishable key is stored \u2014 add it in the Backend tab as `database.anon_key`.";
|
|
5945
|
+
}
|
|
5946
|
+
return `The platform defines ${suffix} (as ${prefixList(entry.prefixes)}) only while your own Supabase database is connected in the Backend tab (Database \u2192 own Supabase). Connect it there, or keep the public value in an ordinary source constant.`;
|
|
5947
|
+
}
|
|
5948
|
+
return "Keep the public value in an ordinary source constant.";
|
|
5949
|
+
}
|
|
5950
|
+
function judgeEnvReads(reads, opts) {
|
|
5951
|
+
const byName = /* @__PURE__ */ new Map();
|
|
5952
|
+
for (const read of reads) {
|
|
5953
|
+
if (opts.defined.has(read.name)) continue;
|
|
5954
|
+
byName.set(read.name, [...byName.get(read.name) || [], read]);
|
|
5955
|
+
}
|
|
5956
|
+
const verdict = { errors: [], warnings: [] };
|
|
5957
|
+
const build = opts.backendUnknown ? "the cloud build" : "this build";
|
|
5958
|
+
for (const name of [...byName.keys()].sort()) {
|
|
5959
|
+
const group = byName.get(name);
|
|
5960
|
+
const files = sampleFiles(group.map((r) => r.file).sort());
|
|
5961
|
+
const { prefix, suffix } = splitName(name);
|
|
5962
|
+
const entry = injectedEntry(suffix);
|
|
5963
|
+
const taught = entry !== void 0;
|
|
5964
|
+
const bare = group.filter((r) => !r.hasFallback);
|
|
5965
|
+
const local = opts.localOnly?.has(name) ? " Your local .env defines it, but .env files never leave this machine." : "";
|
|
5966
|
+
if (opts.backendUnknown && entry && entry.when === "byo_supabase" && entry.prefixes.includes(prefix)) {
|
|
5967
|
+
verdict.warnings.push(
|
|
5968
|
+
`${name} is read in ${files}. The cloud build defines it only while your own Supabase database is connected in the Backend tab (Database \u2192 own Supabase)` + (bare.length > 0 ? " \u2014 without that it rejects the build, because the value would compile to `undefined` without any build error." : "; without that the app runs on its own fallback.") + local
|
|
5969
|
+
);
|
|
5970
|
+
} else if (taught && bare.length > 0) {
|
|
5971
|
+
verdict.errors.push(
|
|
5972
|
+
`${name} is read in ${sampleFiles(bare.map((r) => r.file).sort())}, but ${build} does not define it \u2014 it would compile to \`undefined\` without any build error. ${platformHint(name, opts)}${local}`
|
|
5973
|
+
);
|
|
5974
|
+
} else if (taught) {
|
|
5975
|
+
verdict.warnings.push(
|
|
5976
|
+
`${name} is read in ${files} and ${build} does not define it \u2014 the app runs on its own fallback. ${platformHint(name, opts)}${local}`
|
|
5977
|
+
);
|
|
5978
|
+
} else {
|
|
5979
|
+
verdict.warnings.push(
|
|
5980
|
+
`${name} is read in ${files}, but no cloud build defines it \u2014 it compiles to \`undefined\`. This platform sets no build variables of your own: keep public values in an ordinary source constant (a fallback such as \`?? '/api'\` is fine).${local}`
|
|
5981
|
+
);
|
|
5982
|
+
}
|
|
5983
|
+
}
|
|
5984
|
+
return verdict;
|
|
5985
|
+
}
|
|
5986
|
+
|
|
5829
5987
|
// src/lib/preflight.ts
|
|
5830
5988
|
function feature(id) {
|
|
5831
5989
|
const found = contract_default.forbidden_server_features.find((f) => f.id === id);
|
|
@@ -5853,14 +6011,14 @@ var STATIC_EXPORT = /output\s*:\s*['"]export['"]/;
|
|
|
5853
6011
|
var SOURCE_FILE = /\.(js|jsx|ts|tsx|mjs)$/;
|
|
5854
6012
|
var GET_SERVER_SIDE_PROPS = /export\s+(?:async\s+)?(?:function|const|let|var)\s+getServerSideProps\b|export\s*\{[^}]*\bgetServerSideProps\b[^}]*\}/;
|
|
5855
6013
|
var USE_SERVER = /^\s*(['"])use server\1\s*;?\s*$/m;
|
|
5856
|
-
var
|
|
5857
|
-
var
|
|
6014
|
+
var SKIP_DIRS2 = /* @__PURE__ */ new Set(["node_modules", ".next", ".git", "dist", "build", "out"]);
|
|
6015
|
+
var SCAN_FILE_BUDGET2 = 5e3;
|
|
5858
6016
|
function detectFramework(rootDir) {
|
|
5859
|
-
const pkgPath = (0,
|
|
5860
|
-
if (!(0,
|
|
6017
|
+
const pkgPath = (0, import_node_path8.join)(rootDir, "package.json");
|
|
6018
|
+
if (!(0, import_node_fs6.existsSync)(pkgPath)) return "vanilla";
|
|
5861
6019
|
let pkg;
|
|
5862
6020
|
try {
|
|
5863
|
-
pkg = JSON.parse((0,
|
|
6021
|
+
pkg = JSON.parse((0, import_node_fs6.readFileSync)(pkgPath, "utf8"));
|
|
5864
6022
|
} catch {
|
|
5865
6023
|
return "unknown";
|
|
5866
6024
|
}
|
|
@@ -5870,32 +6028,32 @@ function detectFramework(rootDir) {
|
|
|
5870
6028
|
}
|
|
5871
6029
|
function readDeps(rootDir) {
|
|
5872
6030
|
try {
|
|
5873
|
-
const pkg = JSON.parse((0,
|
|
6031
|
+
const pkg = JSON.parse((0, import_node_fs6.readFileSync)((0, import_node_path8.join)(rootDir, "package.json"), "utf8"));
|
|
5874
6032
|
return { ...pkg.dependencies, ...pkg.devDependencies };
|
|
5875
6033
|
} catch {
|
|
5876
6034
|
return {};
|
|
5877
6035
|
}
|
|
5878
6036
|
}
|
|
5879
6037
|
function findFiles(rootDir, dir, pattern, out, cap = 20) {
|
|
5880
|
-
if (out.length >= cap || !(0,
|
|
5881
|
-
for (const entry of (0,
|
|
6038
|
+
if (out.length >= cap || !(0, import_node_fs6.existsSync)(dir)) return;
|
|
6039
|
+
for (const entry of (0, import_node_fs6.readdirSync)(dir, { withFileTypes: true })) {
|
|
5882
6040
|
if (out.length >= cap) return;
|
|
5883
|
-
const abs = (0,
|
|
6041
|
+
const abs = (0, import_node_path8.join)(dir, entry.name);
|
|
5884
6042
|
if (entry.isDirectory()) {
|
|
5885
|
-
if (!
|
|
6043
|
+
if (!SKIP_DIRS2.has(entry.name)) findFiles(rootDir, abs, pattern, out, cap);
|
|
5886
6044
|
} else if (entry.isFile() && pattern.test(entry.name)) {
|
|
5887
|
-
out.push((0,
|
|
6045
|
+
out.push((0, import_node_path8.relative)(rootDir, abs).split(import_node_path8.sep).join("/"));
|
|
5888
6046
|
}
|
|
5889
6047
|
}
|
|
5890
6048
|
}
|
|
5891
6049
|
var sample = (list) => list.slice(0, 3).join(", ") + (list.length > 3 ? ", \u2026" : "");
|
|
5892
6050
|
function collectSourceFiles(dir, out, budget) {
|
|
5893
|
-
if (budget.left <= 0 || !(0,
|
|
5894
|
-
for (const entry of (0,
|
|
6051
|
+
if (budget.left <= 0 || !(0, import_node_fs6.existsSync)(dir)) return;
|
|
6052
|
+
for (const entry of (0, import_node_fs6.readdirSync)(dir, { withFileTypes: true })) {
|
|
5895
6053
|
if (budget.left <= 0) return;
|
|
5896
|
-
const abs = (0,
|
|
6054
|
+
const abs = (0, import_node_path8.join)(dir, entry.name);
|
|
5897
6055
|
if (entry.isDirectory()) {
|
|
5898
|
-
if (!
|
|
6056
|
+
if (!SKIP_DIRS2.has(entry.name)) collectSourceFiles(abs, out, budget);
|
|
5899
6057
|
} else if (entry.isFile() && SOURCE_FILE.test(entry.name)) {
|
|
5900
6058
|
budget.left--;
|
|
5901
6059
|
out.push(abs);
|
|
@@ -5905,10 +6063,10 @@ function collectSourceFiles(dir, out, budget) {
|
|
|
5905
6063
|
function checkNextjs(rootDir) {
|
|
5906
6064
|
const issues = [];
|
|
5907
6065
|
const warnings = [];
|
|
5908
|
-
const configName = NEXT_CONFIG_BASENAMES.find((name) => (0,
|
|
6066
|
+
const configName = NEXT_CONFIG_BASENAMES.find((name) => (0, import_node_fs6.existsSync)((0, import_node_path8.join)(rootDir, name)));
|
|
5909
6067
|
let hasStaticExport = true;
|
|
5910
6068
|
if (configName) {
|
|
5911
|
-
const config = (0,
|
|
6069
|
+
const config = (0, import_node_fs6.readFileSync)((0, import_node_path8.join)(rootDir, configName), "utf8");
|
|
5912
6070
|
hasStaticExport = STATIC_EXPORT.test(config);
|
|
5913
6071
|
if (!hasStaticExport) {
|
|
5914
6072
|
issues.push(
|
|
@@ -5922,31 +6080,31 @@ function checkNextjs(rootDir) {
|
|
|
5922
6080
|
const hard = [];
|
|
5923
6081
|
const pagesApi = [];
|
|
5924
6082
|
for (const apiDir of PAGES_API_DIRS) {
|
|
5925
|
-
findFiles(rootDir, (0,
|
|
6083
|
+
findFiles(rootDir, (0, import_node_path8.join)(rootDir, apiDir), /\.(js|ts|jsx|tsx|mjs)$/, pagesApi);
|
|
5926
6084
|
}
|
|
5927
6085
|
if (pagesApi.length > 0) hard.push(`pages/api/* routes (${pagesApi.length} file(s))`);
|
|
5928
6086
|
const middlewareFiles = [];
|
|
5929
6087
|
for (const base of ["", "src"]) {
|
|
5930
|
-
const dir = base ? (0,
|
|
5931
|
-
if (!(0,
|
|
5932
|
-
for (const entry of (0,
|
|
5933
|
-
if (MIDDLEWARE_FILE.test(entry)) middlewareFiles.push((0,
|
|
6088
|
+
const dir = base ? (0, import_node_path8.join)(rootDir, base) : rootDir;
|
|
6089
|
+
if (!(0, import_node_fs6.existsSync)(dir)) continue;
|
|
6090
|
+
for (const entry of (0, import_node_fs6.readdirSync)(dir)) {
|
|
6091
|
+
if (MIDDLEWARE_FILE.test(entry)) middlewareFiles.push((0, import_node_path8.join)(base, entry).split(import_node_path8.sep).join("/"));
|
|
5934
6092
|
}
|
|
5935
6093
|
}
|
|
5936
6094
|
hard.push(...middlewareFiles);
|
|
5937
6095
|
const sourceFiles = [];
|
|
5938
|
-
collectSourceFiles(rootDir, sourceFiles, { left:
|
|
6096
|
+
collectSourceFiles(rootDir, sourceFiles, { left: SCAN_FILE_BUDGET2 });
|
|
5939
6097
|
const gssp = [];
|
|
5940
6098
|
const useServer = [];
|
|
5941
6099
|
for (const abs of sourceFiles) {
|
|
5942
6100
|
if (gssp.length >= 20 && useServer.length >= 20) break;
|
|
5943
6101
|
let text;
|
|
5944
6102
|
try {
|
|
5945
|
-
text = (0,
|
|
6103
|
+
text = (0, import_node_fs6.readFileSync)(abs, "utf8");
|
|
5946
6104
|
} catch {
|
|
5947
6105
|
continue;
|
|
5948
6106
|
}
|
|
5949
|
-
const rel = (0,
|
|
6107
|
+
const rel = (0, import_node_path8.relative)(rootDir, abs).split(import_node_path8.sep).join("/");
|
|
5950
6108
|
if (gssp.length < 20 && GET_SERVER_SIDE_PROPS.test(text)) gssp.push(rel);
|
|
5951
6109
|
if (useServer.length < 20 && USE_SERVER.test(text)) useServer.push(rel);
|
|
5952
6110
|
}
|
|
@@ -5954,7 +6112,7 @@ function checkNextjs(rootDir) {
|
|
|
5954
6112
|
if (useServer.length > 0) hard.push(`'use server' actions (${sample(useServer)})`);
|
|
5955
6113
|
const routeFiles = [];
|
|
5956
6114
|
for (const appDir of APP_DIRS) {
|
|
5957
|
-
findFiles(rootDir, (0,
|
|
6115
|
+
findFiles(rootDir, (0, import_node_path8.join)(rootDir, appDir), ROUTE_HANDLER_FILE, routeFiles);
|
|
5958
6116
|
}
|
|
5959
6117
|
if (routeFiles.length > 0) {
|
|
5960
6118
|
const label = `${routeFiles.length} route handler(s) (${sample(routeFiles)})`;
|
|
@@ -5988,6 +6146,17 @@ function checkNextjs(rootDir) {
|
|
|
5988
6146
|
}
|
|
5989
6147
|
return { issues, warnings };
|
|
5990
6148
|
}
|
|
6149
|
+
function checkBuildEnv(rootDir) {
|
|
6150
|
+
const verdict = judgeEnvReads(scanEnvReads(rootDir), {
|
|
6151
|
+
defined: ALWAYS_DEFINED_NAMES,
|
|
6152
|
+
backendUnknown: true,
|
|
6153
|
+
localOnly: envFileNames(rootDir)
|
|
6154
|
+
});
|
|
6155
|
+
return [
|
|
6156
|
+
...verdict.errors.map((e) => `The cloud build will reject this project: ${e}`),
|
|
6157
|
+
...verdict.warnings
|
|
6158
|
+
];
|
|
6159
|
+
}
|
|
5991
6160
|
function runPreflight(rootDir) {
|
|
5992
6161
|
const framework = detectFramework(rootDir);
|
|
5993
6162
|
const issues = [];
|
|
@@ -6002,17 +6171,18 @@ function runPreflight(rootDir) {
|
|
|
6002
6171
|
issues.push(...next.issues);
|
|
6003
6172
|
warnings.push(...next.warnings);
|
|
6004
6173
|
}
|
|
6174
|
+
if (framework !== "vanilla") warnings.push(...checkBuildEnv(rootDir));
|
|
6005
6175
|
return { framework, issues, warnings };
|
|
6006
6176
|
}
|
|
6007
6177
|
|
|
6008
6178
|
// src/lib/backendDecl.ts
|
|
6009
|
-
var
|
|
6010
|
-
var
|
|
6179
|
+
var import_node_fs7 = require("fs");
|
|
6180
|
+
var import_node_path9 = require("path");
|
|
6011
6181
|
function readBackendDeclaration(dir = process.cwd()) {
|
|
6012
|
-
const path = (0,
|
|
6013
|
-
if (!(0,
|
|
6182
|
+
const path = (0, import_node_path9.join)(dir, ".agentful", "backend.json");
|
|
6183
|
+
if (!(0, import_node_fs7.existsSync)(path)) return null;
|
|
6014
6184
|
try {
|
|
6015
|
-
const parsed = JSON.parse((0,
|
|
6185
|
+
const parsed = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf8"));
|
|
6016
6186
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
6017
6187
|
const collections = Array.isArray(parsed.collections) ? parsed.collections.filter((c) => c && typeof c === "object" && !Array.isArray(c)) : [];
|
|
6018
6188
|
const secrets = Array.isArray(parsed.secrets) ? parsed.secrets.filter((s) => s && typeof s === "object" && !Array.isArray(s)) : [];
|
|
@@ -6056,19 +6226,19 @@ function describeBackendDeclaration(decl) {
|
|
|
6056
6226
|
function backendTabUrl(userId, projectId) {
|
|
6057
6227
|
return `${APP_URL}/workspace/${userId}/${projectId}?view=backend`;
|
|
6058
6228
|
}
|
|
6059
|
-
var ACTIONS_DIR = (0,
|
|
6229
|
+
var ACTIONS_DIR = (0, import_node_path9.join)(".server", "actions");
|
|
6060
6230
|
var ACTION_NAME = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
6061
6231
|
function checkBackendDeclaration(rootDir = process.cwd()) {
|
|
6062
6232
|
const issues = [];
|
|
6063
6233
|
const warnings = [];
|
|
6064
|
-
const actionsDir = (0,
|
|
6234
|
+
const actionsDir = (0, import_node_path9.join)(rootDir, ACTIONS_DIR);
|
|
6065
6235
|
const presentFiles = /* @__PURE__ */ new Set();
|
|
6066
|
-
if ((0,
|
|
6067
|
-
for (const entry of (0,
|
|
6068
|
-
const abs = (0,
|
|
6236
|
+
if ((0, import_node_fs7.existsSync)(actionsDir)) {
|
|
6237
|
+
for (const entry of (0, import_node_fs7.readdirSync)(actionsDir)) {
|
|
6238
|
+
const abs = (0, import_node_path9.join)(actionsDir, entry);
|
|
6069
6239
|
let isDir = false;
|
|
6070
6240
|
try {
|
|
6071
|
-
isDir = (0,
|
|
6241
|
+
isDir = (0, import_node_fs7.statSync)(abs).isDirectory();
|
|
6072
6242
|
} catch {
|
|
6073
6243
|
continue;
|
|
6074
6244
|
}
|
|
@@ -6285,8 +6455,8 @@ function describeBackendState(state) {
|
|
|
6285
6455
|
}
|
|
6286
6456
|
|
|
6287
6457
|
// src/lib/backendConsent.ts
|
|
6288
|
-
var
|
|
6289
|
-
var
|
|
6458
|
+
var import_node_fs8 = require("fs");
|
|
6459
|
+
var import_node_path10 = require("path");
|
|
6290
6460
|
var import_promises2 = require("readline/promises");
|
|
6291
6461
|
function declaresManagedDatabase(decl) {
|
|
6292
6462
|
if (!decl) return false;
|
|
@@ -6312,10 +6482,10 @@ function consentQuestion(decl) {
|
|
|
6312
6482
|
'It is the same switch as the Backend tab; this push then applies the declaration. A "no" is remembered for this project (`agentful push --yes` or `agentful backend` enables it later).'
|
|
6313
6483
|
].join("\n");
|
|
6314
6484
|
}
|
|
6315
|
-
var consentFile = () => (0,
|
|
6485
|
+
var consentFile = () => (0, import_node_path10.join)(configDir(), "backend-consent.json");
|
|
6316
6486
|
function readConsentFile() {
|
|
6317
6487
|
try {
|
|
6318
|
-
const raw = JSON.parse((0,
|
|
6488
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(consentFile(), "utf8"));
|
|
6319
6489
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
6320
6490
|
} catch {
|
|
6321
6491
|
return {};
|
|
@@ -6327,15 +6497,15 @@ function hasRememberedDecline(projectId) {
|
|
|
6327
6497
|
function rememberDecline(projectId) {
|
|
6328
6498
|
const all = readConsentFile();
|
|
6329
6499
|
all[projectId] = { declined_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
6330
|
-
(0,
|
|
6331
|
-
(0,
|
|
6500
|
+
(0, import_node_fs8.mkdirSync)(configDir(), { recursive: true });
|
|
6501
|
+
(0, import_node_fs8.writeFileSync)(consentFile(), JSON.stringify(all, null, 2) + "\n", "utf8");
|
|
6332
6502
|
}
|
|
6333
6503
|
function forgetDecline(projectId) {
|
|
6334
|
-
if (!(0,
|
|
6504
|
+
if (!(0, import_node_fs8.existsSync)(consentFile())) return;
|
|
6335
6505
|
const all = readConsentFile();
|
|
6336
6506
|
if (!(projectId in all)) return;
|
|
6337
6507
|
delete all[projectId];
|
|
6338
|
-
(0,
|
|
6508
|
+
(0, import_node_fs8.writeFileSync)(consentFile(), JSON.stringify(all, null, 2) + "\n", "utf8");
|
|
6339
6509
|
}
|
|
6340
6510
|
async function enableManagedDatabase(auth, userId, projectId) {
|
|
6341
6511
|
try {
|
|
@@ -6543,13 +6713,14 @@ async function pushCommand(opts) {
|
|
|
6543
6713
|
ui.step("Building in the cloud (this can take a few minutes)\u2026");
|
|
6544
6714
|
const buildStartedAt = Date.now();
|
|
6545
6715
|
try {
|
|
6546
|
-
await request(`${PB_URL}/api/workspaces/${userId}/${projectId}/build`, {
|
|
6716
|
+
const built = await request(`${PB_URL}/api/workspaces/${userId}/${projectId}/build`, {
|
|
6547
6717
|
method: "POST",
|
|
6548
6718
|
token: auth.pb_token,
|
|
6549
6719
|
body: {},
|
|
6550
6720
|
timeoutMs: 66e4
|
|
6551
6721
|
});
|
|
6552
6722
|
ui.info("Build finished");
|
|
6723
|
+
for (const warning of built?.warnings ?? []) ui.warn(warning);
|
|
6553
6724
|
} catch (err2) {
|
|
6554
6725
|
if (err2 instanceof ApiError && err2.code === "network_error") {
|
|
6555
6726
|
ui.warn("Connection dropped during the build \u2014 polling for the result\u2026");
|
|
@@ -6712,15 +6883,15 @@ async function openCommand() {
|
|
|
6712
6883
|
// src/commands/tui.ts
|
|
6713
6884
|
var import_node_child_process6 = require("child_process");
|
|
6714
6885
|
var import_promises4 = require("readline/promises");
|
|
6715
|
-
var
|
|
6886
|
+
var import_node_path21 = require("path");
|
|
6716
6887
|
|
|
6717
6888
|
// src/lib/binWrapper.ts
|
|
6718
|
-
var
|
|
6719
|
-
var
|
|
6889
|
+
var import_node_fs9 = require("fs");
|
|
6890
|
+
var import_node_path11 = require("path");
|
|
6720
6891
|
var import_node_os3 = require("os");
|
|
6721
6892
|
function ensureCliOnPath() {
|
|
6722
|
-
const binDir = (0,
|
|
6723
|
-
(0,
|
|
6893
|
+
const binDir = (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".local", "share", "agentful", "bin");
|
|
6894
|
+
(0, import_node_fs9.mkdirSync)(binDir, { recursive: true });
|
|
6724
6895
|
const entry = process.argv[1];
|
|
6725
6896
|
if (!entry) return binDir;
|
|
6726
6897
|
const restore = (name) => {
|
|
@@ -6729,8 +6900,8 @@ function ensureCliOnPath() {
|
|
|
6729
6900
|
` : `export ${name}=${JSON.stringify(original)}
|
|
6730
6901
|
`;
|
|
6731
6902
|
};
|
|
6732
|
-
const wrapper = (0,
|
|
6733
|
-
(0,
|
|
6903
|
+
const wrapper = (0, import_node_path11.join)(binDir, "agentful");
|
|
6904
|
+
(0, import_node_fs9.writeFileSync)(
|
|
6734
6905
|
wrapper,
|
|
6735
6906
|
`#!/bin/sh
|
|
6736
6907
|
# Generated by the Agentful CLI so the coding agent can run \`agentful \u2026\`.
|
|
@@ -6740,7 +6911,7 @@ function ensureCliOnPath() {
|
|
|
6740
6911
|
"utf8"
|
|
6741
6912
|
);
|
|
6742
6913
|
try {
|
|
6743
|
-
(0,
|
|
6914
|
+
(0, import_node_fs9.chmodSync)(wrapper, 493);
|
|
6744
6915
|
} catch {
|
|
6745
6916
|
}
|
|
6746
6917
|
return binDir;
|
|
@@ -6750,9 +6921,9 @@ function ensureCliOnPath() {
|
|
|
6750
6921
|
init_branding();
|
|
6751
6922
|
|
|
6752
6923
|
// src/lib/engine.ts
|
|
6753
|
-
var
|
|
6924
|
+
var import_node_fs10 = require("fs");
|
|
6754
6925
|
var import_node_crypto = require("crypto");
|
|
6755
|
-
var
|
|
6926
|
+
var import_node_path12 = require("path");
|
|
6756
6927
|
var import_node_os4 = require("os");
|
|
6757
6928
|
var import_node_child_process3 = require("child_process");
|
|
6758
6929
|
var import_node_stream = require("stream");
|
|
@@ -6797,8 +6968,8 @@ function platformKey() {
|
|
|
6797
6968
|
);
|
|
6798
6969
|
}
|
|
6799
6970
|
function cacheDir(version) {
|
|
6800
|
-
const base = process.env.XDG_CACHE_HOME || (0,
|
|
6801
|
-
return (0,
|
|
6971
|
+
const base = process.env.XDG_CACHE_HOME || (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".cache");
|
|
6972
|
+
return (0, import_node_path12.join)(base, "agentful", "engine", version);
|
|
6802
6973
|
}
|
|
6803
6974
|
async function fetchManifest() {
|
|
6804
6975
|
try {
|
|
@@ -6809,7 +6980,7 @@ async function fetchManifest() {
|
|
|
6809
6980
|
}
|
|
6810
6981
|
async function sha256File(path) {
|
|
6811
6982
|
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
6812
|
-
await (0, import_promises3.pipeline)((0,
|
|
6983
|
+
await (0, import_promises3.pipeline)((0, import_node_fs10.createReadStream)(path), hash);
|
|
6813
6984
|
return hash.digest("hex");
|
|
6814
6985
|
}
|
|
6815
6986
|
async function ensureEngine() {
|
|
@@ -6818,12 +6989,12 @@ async function ensureEngine() {
|
|
|
6818
6989
|
noticeIfOutdated(manifest);
|
|
6819
6990
|
const version = manifest?.engine_version || FALLBACK_ENGINE_VERSION;
|
|
6820
6991
|
const dir = cacheDir(version);
|
|
6821
|
-
const binPath = (0,
|
|
6822
|
-
if ((0,
|
|
6992
|
+
const binPath = (0, import_node_path12.join)(dir, ENGINE_BINARY);
|
|
6993
|
+
if ((0, import_node_fs10.existsSync)(binPath)) return binPath;
|
|
6823
6994
|
const artifact = manifest?.artifacts?.[key];
|
|
6824
6995
|
const url = artifact?.url || `${APP_URL}/cli/engine/${version}/${key}${key.startsWith("darwin") ? ".zip" : ".tar.gz"}`;
|
|
6825
|
-
(0,
|
|
6826
|
-
const archivePath = (0,
|
|
6996
|
+
(0, import_node_fs10.mkdirSync)(dir, { recursive: true });
|
|
6997
|
+
const archivePath = (0, import_node_path12.join)(dir, key.startsWith("darwin") ? "engine.zip" : "engine.tar.gz");
|
|
6827
6998
|
ui.step(`Preparing the ${brand.displayName} engine (first run only)\u2026`);
|
|
6828
6999
|
const resp = await fetch(url, {
|
|
6829
7000
|
redirect: "follow",
|
|
@@ -6837,11 +7008,11 @@ async function ensureEngine() {
|
|
|
6837
7008
|
`Could not download the engine (HTTP ${resp.status}). Check your connection and try again.`
|
|
6838
7009
|
);
|
|
6839
7010
|
}
|
|
6840
|
-
await (0, import_promises3.pipeline)(import_node_stream.Readable.fromWeb(resp.body), (0,
|
|
7011
|
+
await (0, import_promises3.pipeline)(import_node_stream.Readable.fromWeb(resp.body), (0, import_node_fs10.createWriteStream)(archivePath));
|
|
6841
7012
|
if (artifact?.sha256) {
|
|
6842
7013
|
const actual = await sha256File(archivePath);
|
|
6843
7014
|
if (actual !== artifact.sha256) {
|
|
6844
|
-
(0,
|
|
7015
|
+
(0, import_node_fs10.rmSync)(archivePath, { force: true });
|
|
6845
7016
|
throw new ApiError(
|
|
6846
7017
|
0,
|
|
6847
7018
|
"engine_checksum_mismatch",
|
|
@@ -6850,7 +7021,7 @@ async function ensureEngine() {
|
|
|
6850
7021
|
}
|
|
6851
7022
|
}
|
|
6852
7023
|
const extract = archivePath.endsWith(".zip") ? (0, import_node_child_process3.spawnSync)("unzip", ["-oq", archivePath], { cwd: dir, stdio: "ignore" }) : (0, import_node_child_process3.spawnSync)("tar", ["-xzf", archivePath], { cwd: dir, stdio: "ignore" });
|
|
6853
|
-
(0,
|
|
7024
|
+
(0, import_node_fs10.rmSync)(archivePath, { force: true });
|
|
6854
7025
|
if (extract.status !== 0) {
|
|
6855
7026
|
throw new ApiError(
|
|
6856
7027
|
0,
|
|
@@ -6858,24 +7029,24 @@ async function ensureEngine() {
|
|
|
6858
7029
|
`Could not unpack the engine (needs ${archivePath.endsWith(".zip") ? "unzip" : "tar"} on PATH).`
|
|
6859
7030
|
);
|
|
6860
7031
|
}
|
|
6861
|
-
const extracted = (0,
|
|
6862
|
-
if ((0,
|
|
6863
|
-
if (!(0,
|
|
7032
|
+
const extracted = (0, import_node_path12.join)(dir, "opencode");
|
|
7033
|
+
if ((0, import_node_fs10.existsSync)(extracted) && !(0, import_node_fs10.existsSync)(binPath)) (0, import_node_fs10.renameSync)(extracted, binPath);
|
|
7034
|
+
if (!(0, import_node_fs10.existsSync)(binPath)) {
|
|
6864
7035
|
throw new ApiError(0, "engine_extract_failed", "Engine archive did not contain the expected binary.");
|
|
6865
7036
|
}
|
|
6866
|
-
(0,
|
|
7037
|
+
(0, import_node_fs10.chmodSync)(binPath, 493);
|
|
6867
7038
|
ui.ok(`Engine ready.`);
|
|
6868
7039
|
console.log(paint.dim(" powered by opencode (MIT) \xB7 run `agentful licenses` for details"));
|
|
6869
7040
|
return binPath;
|
|
6870
7041
|
}
|
|
6871
7042
|
|
|
6872
7043
|
// src/lib/gatewayToken.ts
|
|
6873
|
-
var
|
|
6874
|
-
var
|
|
6875
|
-
var cachePath = () => (0,
|
|
7044
|
+
var import_node_fs11 = require("fs");
|
|
7045
|
+
var import_node_path13 = require("path");
|
|
7046
|
+
var cachePath = () => (0, import_node_path13.join)(configDir(), "gateway.json");
|
|
6876
7047
|
async function ensureGatewaySession(auth, projectId) {
|
|
6877
7048
|
try {
|
|
6878
|
-
const cached = JSON.parse((0,
|
|
7049
|
+
const cached = JSON.parse((0, import_node_fs11.readFileSync)(cachePath(), "utf8"));
|
|
6879
7050
|
if (cached?.token && cached.expires_at - Date.now() / 1e3 > 3600) {
|
|
6880
7051
|
return cached;
|
|
6881
7052
|
}
|
|
@@ -6886,18 +7057,18 @@ async function ensureGatewaySession(auth, projectId) {
|
|
|
6886
7057
|
body: projectId ? { project_id: projectId } : {},
|
|
6887
7058
|
timeoutMs: 3e4
|
|
6888
7059
|
});
|
|
6889
|
-
(0,
|
|
6890
|
-
(0,
|
|
7060
|
+
(0, import_node_fs11.mkdirSync)(configDir(), { recursive: true });
|
|
7061
|
+
(0, import_node_fs11.writeFileSync)(cachePath(), JSON.stringify(res, null, 2) + "\n", "utf8");
|
|
6891
7062
|
try {
|
|
6892
|
-
(0,
|
|
7063
|
+
(0, import_node_fs11.chmodSync)(cachePath(), 384);
|
|
6893
7064
|
} catch {
|
|
6894
7065
|
}
|
|
6895
7066
|
return res;
|
|
6896
7067
|
}
|
|
6897
7068
|
|
|
6898
7069
|
// src/lib/engineConfig.ts
|
|
6899
|
-
var
|
|
6900
|
-
var
|
|
7070
|
+
var import_node_fs13 = require("fs");
|
|
7071
|
+
var import_node_path15 = require("path");
|
|
6901
7072
|
var import_node_os5 = require("os");
|
|
6902
7073
|
|
|
6903
7074
|
// src/branding/agentful-theme.json
|
|
@@ -7040,22 +7211,22 @@ ${cmd.template}
|
|
|
7040
7211
|
}
|
|
7041
7212
|
|
|
7042
7213
|
// src/lib/tools.ts
|
|
7043
|
-
var
|
|
7044
|
-
var
|
|
7214
|
+
var import_node_fs12 = require("fs");
|
|
7215
|
+
var import_node_path14 = require("path");
|
|
7045
7216
|
function assetsDir() {
|
|
7046
|
-
const here = (0,
|
|
7047
|
-
for (const candidate of [(0,
|
|
7048
|
-
if ((0,
|
|
7217
|
+
const here = (0, import_node_path14.dirname)(process.argv[1] || "");
|
|
7218
|
+
for (const candidate of [(0, import_node_path14.join)(here, "..", "assets"), (0, import_node_path14.join)(here, "assets")]) {
|
|
7219
|
+
if ((0, import_node_fs12.existsSync)((0, import_node_path14.join)(candidate, "tools", "imagegen.ts"))) return candidate;
|
|
7049
7220
|
}
|
|
7050
7221
|
return null;
|
|
7051
7222
|
}
|
|
7052
7223
|
function installEngineTools(configDir2) {
|
|
7053
7224
|
const assets = assetsDir();
|
|
7054
7225
|
if (!assets) return false;
|
|
7055
|
-
const target = (0,
|
|
7056
|
-
(0,
|
|
7226
|
+
const target = (0, import_node_path14.join)(configDir2, "tools");
|
|
7227
|
+
(0, import_node_fs12.mkdirSync)(target, { recursive: true });
|
|
7057
7228
|
try {
|
|
7058
|
-
(0,
|
|
7229
|
+
(0, import_node_fs12.cpSync)((0, import_node_path14.join)(assets, "tools"), target, { recursive: true });
|
|
7059
7230
|
return true;
|
|
7060
7231
|
} catch {
|
|
7061
7232
|
return false;
|
|
@@ -7125,6 +7296,14 @@ function managedServerLine(backend) {
|
|
|
7125
7296
|
const ownApi = backend.serverMode === "byo" ? "Server: the owner connected **an API of their own** \u2014 `/api/*` on the app's domain is forwarded to it, and the platform adds no secret and authorizes nobody. " : "";
|
|
7126
7297
|
return `${ownApi}Managed server: **not switched on** in the Backend tab. **Action files you push are stored, but every call to them answers \`404 server_not_enabled\`** until the owner switches the managed server on (\`agentful backend\` opens the tab; the CLI can enable the database, NOT the server). Switching on takes effect on the next call. Never tell the user an action works before the server is on.`;
|
|
7127
7298
|
}
|
|
7299
|
+
function buildEnvList() {
|
|
7300
|
+
const entries = contract_default.publish.build_env.injected;
|
|
7301
|
+
const when = {
|
|
7302
|
+
always: "always",
|
|
7303
|
+
byo_supabase: "only while the owner's own Supabase database is connected in the Backend tab"
|
|
7304
|
+
};
|
|
7305
|
+
return entries.map((e) => ` - ${e.prefixes.map((p) => `\`${p}${e.suffix}\``).join(", ")} \u2014 ${when[e.when] ?? e.when}`).join("\n");
|
|
7306
|
+
}
|
|
7128
7307
|
var bytes = (n) => n >= 1024 * 1024 ? `${n / (1024 * 1024)} MB` : `${n / 1024} KB`;
|
|
7129
7308
|
function serverSideSection() {
|
|
7130
7309
|
const tracks = contract_default.server_side;
|
|
@@ -7180,18 +7359,26 @@ is fine \u2014 but then say clearly that \`agentful push\` cannot deploy it.
|
|
|
7180
7359
|
Server-side logic has its own place \u2014 see "Where server logic belongs".
|
|
7181
7360
|
- The canonical build output is a root-level \`index.html\` inside the
|
|
7182
7361
|
framework's output directory.
|
|
7183
|
-
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
cloud \u2014 the CLI
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7362
|
+
- You **cannot set build-time env vars**, and there is no settings tab for
|
|
7363
|
+
build secrets \u2014 do not invent one. Backend-tab secrets are runtime-only for
|
|
7364
|
+
Managed Server Actions and never reach a build. Every cloud build \u2014 the
|
|
7365
|
+
workspace build and the \`agentful push\` build alike \u2014 defines the same
|
|
7366
|
+
fixed allowlist of PUBLIC client values, and nothing else:
|
|
7367
|
+
${buildEnvList()}
|
|
7368
|
+
Never rely on \`.env*\` files reaching the cloud \u2014 the CLI never uploads
|
|
7369
|
+
them.
|
|
7370
|
+
- A cloud build **rejects** a read of one of those names while nothing defines
|
|
7371
|
+
it (e.g. \`import.meta.env.VITE_SUPABASE_URL\` with no own Supabase database
|
|
7372
|
+
connected): it would compile to \`undefined\` without any build error and the
|
|
7373
|
+
app would fail to reach its database. A read of any OTHER
|
|
7374
|
+
\`VITE_\`/\`PUBLIC_\`/\`NEXT_PUBLIC_\` name is never defined by the platform; the
|
|
7375
|
+
build warns and inlines \`undefined\`.
|
|
7376
|
+
- So PUBLIC client values of your own go into an ordinary source constant, not
|
|
7377
|
+
into \`import.meta.env\`/\`process.env\`. For the project ID (below) and, when
|
|
7378
|
+
the app talks to the owner's own Supabase, its project URL and **publishable
|
|
7379
|
+
(anon) key**, a source constant is also the form that works in local
|
|
7380
|
+
development: on this machine nothing defines the names above unless the user
|
|
7381
|
+
keeps a local \`.env\`, which never leaves it.
|
|
7195
7382
|
Never put a Supabase **secret / service-role key** in source: that one
|
|
7196
7383
|
belongs in Backend-tab secrets and is only readable from a Managed Server
|
|
7197
7384
|
Action.
|
|
@@ -7342,7 +7529,7 @@ var CLOUD_AGENT_PROMPT = `You are the Agentful Cloud build agent: everything you
|
|
|
7342
7529
|
var LOCAL_AGENT_PROMPT = `You are in local-only mode: free local development with no cloud deployment target \u2014 any stack is fine. Be clear that this directory will NOT be deployable with \`agentful push\` unless it satisfies the platform contract in AGENTFUL_CLOUD.md (${SERVER_SIDE_IN_ONE_SENTENCE}). If the user asks to deploy or push, check the contract first and say honestly whether the project can ship on the platform; never claim cloud deployability without evidence.`;
|
|
7343
7530
|
function readAuthFile(path) {
|
|
7344
7531
|
try {
|
|
7345
|
-
return (0,
|
|
7532
|
+
return (0, import_node_fs13.readFileSync)(path, "utf8");
|
|
7346
7533
|
} catch {
|
|
7347
7534
|
return null;
|
|
7348
7535
|
}
|
|
@@ -7407,11 +7594,11 @@ function buildEngineConfig(opts) {
|
|
|
7407
7594
|
};
|
|
7408
7595
|
}
|
|
7409
7596
|
function engineXdg() {
|
|
7410
|
-
const root = (0,
|
|
7597
|
+
const root = (0, import_node_path15.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful");
|
|
7411
7598
|
return {
|
|
7412
|
-
configHome: (0,
|
|
7413
|
-
dataHome: (0,
|
|
7414
|
-
stateHome: (0,
|
|
7599
|
+
configHome: (0, import_node_path15.join)(root, "engine-config"),
|
|
7600
|
+
dataHome: (0, import_node_path15.join)(root, "engine-data"),
|
|
7601
|
+
stateHome: (0, import_node_path15.join)(root, "engine-state")
|
|
7415
7602
|
};
|
|
7416
7603
|
}
|
|
7417
7604
|
async function resolveTheme() {
|
|
@@ -7430,24 +7617,24 @@ async function resolveTheme() {
|
|
|
7430
7617
|
}
|
|
7431
7618
|
async function writeEngineSession(session, catalog, localProviders = {}, framework = "unknown", skillsInstruction = null, backendState, model) {
|
|
7432
7619
|
const xdg = engineXdg();
|
|
7433
|
-
const configDir2 = (0,
|
|
7434
|
-
const dataDir = (0,
|
|
7435
|
-
const themesDir = (0,
|
|
7436
|
-
const pluginsDir = (0,
|
|
7437
|
-
const commandsDir = (0,
|
|
7438
|
-
for (const dir of [themesDir, pluginsDir, commandsDir, dataDir, (0,
|
|
7439
|
-
(0,
|
|
7620
|
+
const configDir2 = (0, import_node_path15.join)(xdg.configHome, "opencode");
|
|
7621
|
+
const dataDir = (0, import_node_path15.join)(xdg.dataHome, "opencode");
|
|
7622
|
+
const themesDir = (0, import_node_path15.join)(configDir2, "themes");
|
|
7623
|
+
const pluginsDir = (0, import_node_path15.join)(configDir2, "plugins");
|
|
7624
|
+
const commandsDir = (0, import_node_path15.join)(configDir2, "commands");
|
|
7625
|
+
for (const dir of [themesDir, pluginsDir, commandsDir, dataDir, (0, import_node_path15.join)(xdg.stateHome, "opencode")]) {
|
|
7626
|
+
(0, import_node_fs13.mkdirSync)(dir, { recursive: true });
|
|
7440
7627
|
}
|
|
7441
7628
|
const imagegenAvailable = installEngineTools(configDir2) && session.img_on !== false;
|
|
7442
|
-
const cloudInstructionsPath = (0,
|
|
7443
|
-
(0,
|
|
7444
|
-
const skillsPath = (0,
|
|
7629
|
+
const cloudInstructionsPath = (0, import_node_path15.join)(configDir2, CLOUD_INSTRUCTIONS_FILENAME);
|
|
7630
|
+
(0, import_node_fs13.writeFileSync)(cloudInstructionsPath, renderCloudInstructions(framework, backendState));
|
|
7631
|
+
const skillsPath = (0, import_node_path15.join)(configDir2, "AGENTFUL_SKILLS.md");
|
|
7445
7632
|
const instructionPaths = [cloudInstructionsPath];
|
|
7446
7633
|
if (skillsInstruction) {
|
|
7447
|
-
(0,
|
|
7634
|
+
(0, import_node_fs13.writeFileSync)(skillsPath, skillsInstruction);
|
|
7448
7635
|
instructionPaths.push(skillsPath);
|
|
7449
7636
|
} else {
|
|
7450
|
-
(0,
|
|
7637
|
+
(0, import_node_fs13.rmSync)(skillsPath, { force: true });
|
|
7451
7638
|
}
|
|
7452
7639
|
const config = buildEngineConfig({
|
|
7453
7640
|
session,
|
|
@@ -7457,13 +7644,13 @@ async function writeEngineSession(session, catalog, localProviders = {}, framewo
|
|
|
7457
7644
|
instructionPaths,
|
|
7458
7645
|
model
|
|
7459
7646
|
});
|
|
7460
|
-
(0,
|
|
7461
|
-
const authPath2 = (0,
|
|
7462
|
-
(0,
|
|
7647
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path15.join)(configDir2, "config.json"), JSON.stringify(config, null, 2));
|
|
7648
|
+
const authPath2 = (0, import_node_path15.join)(dataDir, "auth.json");
|
|
7649
|
+
(0, import_node_fs13.writeFileSync)(authPath2, mergedAuthJson(readAuthFile(authPath2), session.token));
|
|
7463
7650
|
const { brandingPluginSource: brandingPluginSource2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
|
|
7464
|
-
const pluginPath = (0,
|
|
7465
|
-
(0,
|
|
7466
|
-
(0,
|
|
7651
|
+
const pluginPath = (0, import_node_path15.join)(pluginsDir, "agentful-branding.tsx");
|
|
7652
|
+
(0, import_node_fs13.writeFileSync)(pluginPath, brandingPluginSource2());
|
|
7653
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path15.join)(configDir2, "tui.json"), JSON.stringify({
|
|
7467
7654
|
theme: "agentful",
|
|
7468
7655
|
plugin: [`file://${pluginPath}`],
|
|
7469
7656
|
// The engine's own sidebar sections are plugins with fixed ids, and
|
|
@@ -7475,13 +7662,13 @@ async function writeEngineSession(session, catalog, localProviders = {}, framewo
|
|
|
7475
7662
|
// state over this map.
|
|
7476
7663
|
plugin_enabled: DISABLED_ENGINE_PLUGINS
|
|
7477
7664
|
}, null, 2));
|
|
7478
|
-
(0,
|
|
7665
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path15.join)(themesDir, "agentful.json"), JSON.stringify(await resolveTheme(), null, 2));
|
|
7479
7666
|
for (const name of Object.keys(SLASH_COMMANDS)) {
|
|
7480
|
-
(0,
|
|
7667
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path15.join)(commandsDir, `${name}.md`), commandMarkdown(name));
|
|
7481
7668
|
}
|
|
7482
7669
|
for (const legacy of ["xdg-config", "xdg-data", "xdg-state"]) {
|
|
7483
7670
|
try {
|
|
7484
|
-
(0,
|
|
7671
|
+
(0, import_node_fs13.rmSync)((0, import_node_path15.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful", legacy), { recursive: true, force: true });
|
|
7485
7672
|
} catch {
|
|
7486
7673
|
}
|
|
7487
7674
|
}
|
|
@@ -7489,8 +7676,8 @@ async function writeEngineSession(session, catalog, localProviders = {}, framewo
|
|
|
7489
7676
|
}
|
|
7490
7677
|
|
|
7491
7678
|
// src/lib/skills.ts
|
|
7492
|
-
var
|
|
7493
|
-
var
|
|
7679
|
+
var import_node_fs14 = require("fs");
|
|
7680
|
+
var import_node_path16 = require("path");
|
|
7494
7681
|
|
|
7495
7682
|
// src/generated/skills.json
|
|
7496
7683
|
var skills_default = {
|
|
@@ -7559,7 +7746,7 @@ var SCAFFOLD_BY_FRAMEWORK = {
|
|
|
7559
7746
|
};
|
|
7560
7747
|
function hasVueDependency(rootDir) {
|
|
7561
7748
|
try {
|
|
7562
|
-
const pkg = JSON.parse((0,
|
|
7749
|
+
const pkg = JSON.parse((0, import_node_fs14.readFileSync)((0, import_node_path16.join)(rootDir, "package.json"), "utf8"));
|
|
7563
7750
|
return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }["vue"]);
|
|
7564
7751
|
} catch {
|
|
7565
7752
|
return false;
|
|
@@ -7589,7 +7776,7 @@ function renderSkillsInstruction(names) {
|
|
|
7589
7776
|
return "# Platform deployment skills (mandatory)\n\nThese are the same skills the cloud build agent loads for this stack.\nFollow them when scaffolding or editing \u2014 they are not optional hints.\n\n" + sections.join("\n\n---\n\n") + "\n";
|
|
7590
7777
|
}
|
|
7591
7778
|
function skillsInstructionFor(framework, rootDir) {
|
|
7592
|
-
if (!(0,
|
|
7779
|
+
if (!(0, import_node_fs14.existsSync)(rootDir)) return null;
|
|
7593
7780
|
return renderSkillsInstruction(selectSkills(framework, rootDir));
|
|
7594
7781
|
}
|
|
7595
7782
|
|
|
@@ -7737,15 +7924,15 @@ function decideLocalProviders(policy) {
|
|
|
7737
7924
|
}
|
|
7738
7925
|
|
|
7739
7926
|
// src/lib/localProviders.ts
|
|
7740
|
-
var
|
|
7741
|
-
var
|
|
7927
|
+
var import_node_fs15 = require("fs");
|
|
7928
|
+
var import_node_path17 = require("path");
|
|
7742
7929
|
var LOCAL_PROVIDERS_FILE = "local-providers.json";
|
|
7743
7930
|
function localProvidersPath() {
|
|
7744
|
-
return (0,
|
|
7931
|
+
return (0, import_node_path17.join)(configDir(), LOCAL_PROVIDERS_FILE);
|
|
7745
7932
|
}
|
|
7746
7933
|
function readLocalProviders() {
|
|
7747
7934
|
try {
|
|
7748
|
-
const raw = JSON.parse((0,
|
|
7935
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(localProvidersPath(), "utf8"));
|
|
7749
7936
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
7750
7937
|
const map = raw.providers && typeof raw.providers === "object" ? raw.providers : raw;
|
|
7751
7938
|
const usable = {};
|
|
@@ -7780,8 +7967,8 @@ function resolveLocalProviders(policy) {
|
|
|
7780
7967
|
}
|
|
7781
7968
|
function writeLocalProvidersExample() {
|
|
7782
7969
|
const path = localProvidersPath();
|
|
7783
|
-
if ((0,
|
|
7784
|
-
(0,
|
|
7970
|
+
if ((0, import_node_fs15.existsSync)(path)) return path;
|
|
7971
|
+
(0, import_node_fs15.mkdirSync)(configDir(), { recursive: true });
|
|
7785
7972
|
const example = {
|
|
7786
7973
|
_comment: 'Providers with your own API key, running locally. Requests go directly to the provider \u2014 no Agentful credits, no platform region guarantee. Remove the leading underscore from "_anthropic" and fill in your key to enable it.',
|
|
7787
7974
|
_anthropic: {
|
|
@@ -7791,17 +7978,17 @@ function writeLocalProvidersExample() {
|
|
|
7791
7978
|
models: { "claude-sonnet-4-5": { name: "Claude Sonnet 4.5 (my key)" } }
|
|
7792
7979
|
}
|
|
7793
7980
|
};
|
|
7794
|
-
(0,
|
|
7981
|
+
(0, import_node_fs15.writeFileSync)(path, JSON.stringify(example, null, 2) + "\n", "utf8");
|
|
7795
7982
|
try {
|
|
7796
|
-
(0,
|
|
7983
|
+
(0, import_node_fs15.chmodSync)(path, 384);
|
|
7797
7984
|
} catch {
|
|
7798
7985
|
}
|
|
7799
7986
|
return path;
|
|
7800
7987
|
}
|
|
7801
7988
|
|
|
7802
7989
|
// src/lib/sessions.ts
|
|
7803
|
-
var
|
|
7804
|
-
var
|
|
7990
|
+
var import_node_fs16 = require("fs");
|
|
7991
|
+
var import_node_path18 = require("path");
|
|
7805
7992
|
var import_node_child_process4 = require("child_process");
|
|
7806
7993
|
function parseSessionModel(raw) {
|
|
7807
7994
|
if (!raw) return null;
|
|
@@ -7818,8 +8005,8 @@ function parseSessionModel(raw) {
|
|
|
7818
8005
|
}
|
|
7819
8006
|
}
|
|
7820
8007
|
function modelForSession(sessionID) {
|
|
7821
|
-
const dbPath = (0,
|
|
7822
|
-
if (!(0,
|
|
8008
|
+
const dbPath = (0, import_node_path18.join)(engineXdg().dataHome, "opencode", "opencode.db");
|
|
8009
|
+
if (!(0, import_node_fs16.existsSync)(dbPath)) return null;
|
|
7823
8010
|
const escaped = sessionID.replace(/'/g, "''");
|
|
7824
8011
|
const res = (0, import_node_child_process4.spawnSync)(
|
|
7825
8012
|
"sqlite3",
|
|
@@ -7840,8 +8027,8 @@ function modelForSession(sessionID) {
|
|
|
7840
8027
|
}
|
|
7841
8028
|
}
|
|
7842
8029
|
function lastSessionForDirectory(cwd = process.cwd()) {
|
|
7843
|
-
const dbPath = (0,
|
|
7844
|
-
if (!(0,
|
|
8030
|
+
const dbPath = (0, import_node_path18.join)(engineXdg().dataHome, "opencode", "opencode.db");
|
|
8031
|
+
if (!(0, import_node_fs16.existsSync)(dbPath)) return null;
|
|
7845
8032
|
const escaped = cwd.replace(/'/g, "''");
|
|
7846
8033
|
const res = (0, import_node_child_process4.spawnSync)(
|
|
7847
8034
|
"sqlite3",
|
|
@@ -7867,9 +8054,9 @@ function lastSessionForDirectory(cwd = process.cwd()) {
|
|
|
7867
8054
|
}
|
|
7868
8055
|
|
|
7869
8056
|
// src/lib/modelPin.ts
|
|
7870
|
-
var
|
|
7871
|
-
var
|
|
7872
|
-
var PROJECT_MODEL_PIN = (0,
|
|
8057
|
+
var import_node_fs17 = require("fs");
|
|
8058
|
+
var import_node_path19 = require("path");
|
|
8059
|
+
var PROJECT_MODEL_PIN = (0, import_node_path19.join)(".agentful", "model.json");
|
|
7873
8060
|
function isCanonicalModel(value) {
|
|
7874
8061
|
const slash = value.indexOf("/");
|
|
7875
8062
|
return slash > 0 && slash < value.length - 1 && !/\s/.test(value);
|
|
@@ -7889,10 +8076,10 @@ function assertModelPin(pin, source) {
|
|
|
7889
8076
|
return pin;
|
|
7890
8077
|
}
|
|
7891
8078
|
function readProjectModelPin(cwd = process.cwd()) {
|
|
7892
|
-
const path = (0,
|
|
8079
|
+
const path = (0, import_node_path19.join)(cwd, PROJECT_MODEL_PIN);
|
|
7893
8080
|
let raw;
|
|
7894
8081
|
try {
|
|
7895
|
-
raw = (0,
|
|
8082
|
+
raw = (0, import_node_fs17.readFileSync)(path, "utf8");
|
|
7896
8083
|
} catch (error) {
|
|
7897
8084
|
const code = error.code;
|
|
7898
8085
|
if (code === "ENOENT") return null;
|
|
@@ -7919,7 +8106,7 @@ function readProjectModelPin(cwd = process.cwd()) {
|
|
|
7919
8106
|
function readEngineVariants(xdg) {
|
|
7920
8107
|
try {
|
|
7921
8108
|
const parsed = JSON.parse(
|
|
7922
|
-
(0,
|
|
8109
|
+
(0, import_node_fs17.readFileSync)((0, import_node_path19.join)(xdg.stateHome, "opencode", "model.json"), "utf8")
|
|
7923
8110
|
);
|
|
7924
8111
|
if (!parsed.variant || typeof parsed.variant !== "object" || Array.isArray(parsed.variant)) return {};
|
|
7925
8112
|
return Object.fromEntries(
|
|
@@ -7931,17 +8118,17 @@ function readEngineVariants(xdg) {
|
|
|
7931
8118
|
}
|
|
7932
8119
|
function writeEngineVariant(xdg, model, variant) {
|
|
7933
8120
|
assertModelPin({ model, variant }, "Selected");
|
|
7934
|
-
const path = (0,
|
|
8121
|
+
const path = (0, import_node_path19.join)(xdg.stateHome, "opencode", "model.json");
|
|
7935
8122
|
let state = {};
|
|
7936
8123
|
try {
|
|
7937
|
-
const parsed = JSON.parse((0,
|
|
8124
|
+
const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path, "utf8"));
|
|
7938
8125
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) state = parsed;
|
|
7939
8126
|
} catch {
|
|
7940
8127
|
}
|
|
7941
8128
|
const existing = state.variant;
|
|
7942
8129
|
const variants = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
7943
8130
|
state.variant = { ...variants, [model]: variant };
|
|
7944
|
-
(0,
|
|
8131
|
+
(0, import_node_fs17.writeFileSync)(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
7945
8132
|
}
|
|
7946
8133
|
function resolveModelPin(opts) {
|
|
7947
8134
|
const cliPin = opts.cliModel ? assertModelPin({ model: opts.cliModel, variant: opts.cliVariant }, "CLI") : null;
|
|
@@ -7990,8 +8177,8 @@ function resolveModelPin(opts) {
|
|
|
7990
8177
|
// src/lib/engineModels.ts
|
|
7991
8178
|
var import_node_child_process5 = require("child_process");
|
|
7992
8179
|
var import_node_util = require("util");
|
|
7993
|
-
var
|
|
7994
|
-
var
|
|
8180
|
+
var import_node_fs18 = require("fs");
|
|
8181
|
+
var import_node_path20 = require("path");
|
|
7995
8182
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
7996
8183
|
function parseEngineModelsOutput(output) {
|
|
7997
8184
|
return Array.from(new Set(
|
|
@@ -8042,7 +8229,7 @@ async function assertEngineModelAvailable(binPath, xdg, model, listModels = list
|
|
|
8042
8229
|
function readConnectedEngineProviders(xdg) {
|
|
8043
8230
|
try {
|
|
8044
8231
|
const parsed = JSON.parse(
|
|
8045
|
-
(0,
|
|
8232
|
+
(0, import_node_fs18.readFileSync)((0, import_node_path20.join)(xdg.dataHome, "opencode", "auth.json"), "utf8")
|
|
8046
8233
|
);
|
|
8047
8234
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
|
|
8048
8235
|
return Object.keys(parsed).filter((id) => id !== "agentful").sort();
|
|
@@ -8470,7 +8657,7 @@ async function tuiCommand(opts = {}) {
|
|
|
8470
8657
|
...process.env,
|
|
8471
8658
|
// Slash commands run `agentful …` through the agent's bash tool, which
|
|
8472
8659
|
// has no access to the user's shell aliases.
|
|
8473
|
-
PATH: `${binDir}${
|
|
8660
|
+
PATH: `${binDir}${import_node_path21.delimiter}${process.env.PATH || ""}`,
|
|
8474
8661
|
XDG_CONFIG_HOME: xdg.configHome,
|
|
8475
8662
|
XDG_DATA_HOME: xdg.dataHome,
|
|
8476
8663
|
XDG_STATE_HOME: xdg.stateHome,
|
|
@@ -8601,38 +8788,38 @@ async function shareCommand(opts) {
|
|
|
8601
8788
|
}
|
|
8602
8789
|
|
|
8603
8790
|
// src/commands/pull.ts
|
|
8604
|
-
var
|
|
8605
|
-
var
|
|
8791
|
+
var import_node_fs20 = require("fs");
|
|
8792
|
+
var import_node_path23 = require("path");
|
|
8606
8793
|
init_branding();
|
|
8607
8794
|
init_branding();
|
|
8608
8795
|
|
|
8609
8796
|
// src/lib/pullFiles.ts
|
|
8610
|
-
var
|
|
8611
|
-
var
|
|
8797
|
+
var import_node_fs19 = require("fs");
|
|
8798
|
+
var import_node_path22 = require("path");
|
|
8612
8799
|
var INLINE_BASE64_EXTENSIONS = /\.(?:png|jpe?g|gif|webp|avif|svg|ico|bmp|tiff?|woff2?|ttf|otf|eot|pdf|docx?|xlsx?|pptx?|zip|tar|gz|7z|rar|bz2|mp[34]|m4a|wav|ogg|avi|mov|mkv|flac|webm|exe|dll|so|dylib|bin|wasm)$/i;
|
|
8613
8800
|
function inlineContent(value) {
|
|
8614
8801
|
return typeof value === "object" && value !== null && "content" in value ? String(value.content) : String(value ?? "");
|
|
8615
8802
|
}
|
|
8616
8803
|
function writePulledWorkspaceEntry(root, rel, value) {
|
|
8617
|
-
const target = (0,
|
|
8618
|
-
(0,
|
|
8804
|
+
const target = (0, import_node_path22.join)(root, rel);
|
|
8805
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path22.dirname)(target), { recursive: true });
|
|
8619
8806
|
const content = inlineContent(value);
|
|
8620
8807
|
if (INLINE_BASE64_EXTENSIONS.test(rel)) {
|
|
8621
|
-
(0,
|
|
8808
|
+
(0, import_node_fs19.writeFileSync)(target, Buffer.from(content, "base64"));
|
|
8622
8809
|
return;
|
|
8623
8810
|
}
|
|
8624
|
-
(0,
|
|
8811
|
+
(0, import_node_fs19.writeFileSync)(target, content, "utf8");
|
|
8625
8812
|
}
|
|
8626
8813
|
function writePulledBackendDeclaration(root, declaration) {
|
|
8627
|
-
const target = (0,
|
|
8628
|
-
(0,
|
|
8814
|
+
const target = (0, import_node_path22.join)(root, ".agentful", "backend.json");
|
|
8815
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path22.dirname)(target), { recursive: true });
|
|
8629
8816
|
const {
|
|
8630
8817
|
source: _source,
|
|
8631
8818
|
received_at: _receivedAt,
|
|
8632
8819
|
last_sync: _lastSync,
|
|
8633
8820
|
...portableDeclaration
|
|
8634
8821
|
} = declaration;
|
|
8635
|
-
(0,
|
|
8822
|
+
(0, import_node_fs19.writeFileSync)(target, `${JSON.stringify(portableDeclaration, null, 2)}
|
|
8636
8823
|
`, "utf8");
|
|
8637
8824
|
}
|
|
8638
8825
|
|
|
@@ -8641,7 +8828,7 @@ async function pullCommand(opts) {
|
|
|
8641
8828
|
console.log(banner());
|
|
8642
8829
|
const auth = await ensureAuth();
|
|
8643
8830
|
const project = requireProject();
|
|
8644
|
-
const nonHidden = (0,
|
|
8831
|
+
const nonHidden = (0, import_node_fs20.readdirSync)(process.cwd()).filter((n) => n !== ".agentful" && !n.startsWith("."));
|
|
8645
8832
|
if (nonHidden.length > 0 && !opts.force) {
|
|
8646
8833
|
throw new ApiError(
|
|
8647
8834
|
0,
|
|
@@ -8668,9 +8855,9 @@ async function pullCommand(opts) {
|
|
|
8668
8855
|
ui.warn(`Skipped ${rel} (HTTP ${resp.status})`);
|
|
8669
8856
|
continue;
|
|
8670
8857
|
}
|
|
8671
|
-
const target = (0,
|
|
8672
|
-
(0,
|
|
8673
|
-
(0,
|
|
8858
|
+
const target = (0, import_node_path23.join)(process.cwd(), rel);
|
|
8859
|
+
(0, import_node_fs20.mkdirSync)((0, import_node_path23.dirname)(target), { recursive: true });
|
|
8860
|
+
(0, import_node_fs20.writeFileSync)(target, Buffer.from(await resp.arrayBuffer()));
|
|
8674
8861
|
written++;
|
|
8675
8862
|
}
|
|
8676
8863
|
} else if (data.files) {
|