agentful 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +178 -96
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3044,7 +3044,7 @@ var VERSION, brand, useColor, wrap, paint, sym, ui;
|
|
|
3044
3044
|
var init_branding = __esm({
|
|
3045
3045
|
"src/branding.ts"() {
|
|
3046
3046
|
"use strict";
|
|
3047
|
-
VERSION = "0.2.
|
|
3047
|
+
VERSION = "0.2.3" ? "0.2.3" : null.version;
|
|
3048
3048
|
brand = {
|
|
3049
3049
|
name: "agentful",
|
|
3050
3050
|
// the command users type
|
|
@@ -5607,6 +5607,38 @@ function runPreflight(rootDir) {
|
|
|
5607
5607
|
return { framework, issues, warnings };
|
|
5608
5608
|
}
|
|
5609
5609
|
|
|
5610
|
+
// src/lib/backendDecl.ts
|
|
5611
|
+
var import_node_fs6 = require("fs");
|
|
5612
|
+
var import_node_path8 = require("path");
|
|
5613
|
+
function readBackendDeclaration(dir = process.cwd()) {
|
|
5614
|
+
const path = (0, import_node_path8.join)(dir, ".agentful", "backend.json");
|
|
5615
|
+
if (!(0, import_node_fs6.existsSync)(path)) return null;
|
|
5616
|
+
try {
|
|
5617
|
+
const parsed = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf8"));
|
|
5618
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
5619
|
+
const decl = {
|
|
5620
|
+
schema_version: Number(parsed.schema_version) || 1,
|
|
5621
|
+
managed_db: Boolean(parsed.managed_db),
|
|
5622
|
+
actions: Array.isArray(parsed.actions) ? parsed.actions.filter((a) => typeof a === "string") : [],
|
|
5623
|
+
contract_doc: typeof parsed.contract_doc === "string" ? parsed.contract_doc : void 0
|
|
5624
|
+
};
|
|
5625
|
+
if (!decl.managed_db && decl.actions.length === 0) return null;
|
|
5626
|
+
return decl;
|
|
5627
|
+
} catch {
|
|
5628
|
+
return null;
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5631
|
+
function describeBackendDeclaration(decl) {
|
|
5632
|
+
const parts = [];
|
|
5633
|
+
if (decl.managed_db) parts.push("managed DB");
|
|
5634
|
+
if (decl.actions && decl.actions.length > 0) parts.push(`${decl.actions.length} server action(s)`);
|
|
5635
|
+
const base = parts.join(" + ") || "managed backend";
|
|
5636
|
+
return decl.contract_doc ? `${base} (contract: ${decl.contract_doc})` : base;
|
|
5637
|
+
}
|
|
5638
|
+
function backendTabUrl(userId, projectId) {
|
|
5639
|
+
return `${APP_URL}/workspace/${userId}/${projectId}?view=backend`;
|
|
5640
|
+
}
|
|
5641
|
+
|
|
5610
5642
|
// src/lib/buildStatus.ts
|
|
5611
5643
|
init_branding();
|
|
5612
5644
|
var DIAGNOSIS_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
@@ -5732,6 +5764,10 @@ async function pushCommand(opts) {
|
|
|
5732
5764
|
console.log("");
|
|
5733
5765
|
ui.ok(`Live preview: ${ui.url(url)}`);
|
|
5734
5766
|
ui.info(`Manage in the browser: ${ui.url(`https://app.agentful.dev/workspace/${userId}/${projectId}`)}`);
|
|
5767
|
+
const backend = readBackendDeclaration();
|
|
5768
|
+
if (backend) {
|
|
5769
|
+
ui.info(`Declared managed backend: ${describeBackendDeclaration(backend)} \u2014 enable/manage it in the Backend tab: \`agentful backend\` takes you there.`);
|
|
5770
|
+
}
|
|
5735
5771
|
}
|
|
5736
5772
|
async function pollBuild(token, userId, projectId, startedAtMs) {
|
|
5737
5773
|
const deadline = Date.now() + 10 * 60 * 1e3;
|
|
@@ -5817,6 +5853,24 @@ async function buildStatusCommand() {
|
|
|
5817
5853
|
}
|
|
5818
5854
|
}
|
|
5819
5855
|
|
|
5856
|
+
// src/commands/backend.ts
|
|
5857
|
+
init_branding();
|
|
5858
|
+
async function backendCommand() {
|
|
5859
|
+
console.log(banner());
|
|
5860
|
+
const project = requireProject();
|
|
5861
|
+
const decl = readBackendDeclaration();
|
|
5862
|
+
if (decl) {
|
|
5863
|
+
ui.info(`This project declares: ${describeBackendDeclaration(decl)}.`);
|
|
5864
|
+
ui.info("Declared in code is not enabled on the platform \u2014 that happens in the Backend tab.");
|
|
5865
|
+
}
|
|
5866
|
+
const url = backendTabUrl(project.userId, project.projectId);
|
|
5867
|
+
ui.step(`Opening the Backend tab: ${ui.url(url)}`);
|
|
5868
|
+
if (!openInBrowser(url)) {
|
|
5869
|
+
ui.info("Could not launch a browser \u2014 open this URL manually:");
|
|
5870
|
+
ui.info(ui.url(url));
|
|
5871
|
+
}
|
|
5872
|
+
}
|
|
5873
|
+
|
|
5820
5874
|
// src/commands/open.ts
|
|
5821
5875
|
init_branding();
|
|
5822
5876
|
async function openCommand() {
|
|
@@ -5833,15 +5887,15 @@ async function openCommand() {
|
|
|
5833
5887
|
|
|
5834
5888
|
// src/commands/tui.ts
|
|
5835
5889
|
var import_node_child_process5 = require("child_process");
|
|
5836
|
-
var
|
|
5890
|
+
var import_node_path17 = require("path");
|
|
5837
5891
|
|
|
5838
5892
|
// src/lib/binWrapper.ts
|
|
5839
|
-
var
|
|
5840
|
-
var
|
|
5893
|
+
var import_node_fs7 = require("fs");
|
|
5894
|
+
var import_node_path9 = require("path");
|
|
5841
5895
|
var import_node_os3 = require("os");
|
|
5842
5896
|
function ensureCliOnPath() {
|
|
5843
|
-
const binDir = (0,
|
|
5844
|
-
(0,
|
|
5897
|
+
const binDir = (0, import_node_path9.join)((0, import_node_os3.homedir)(), ".local", "share", "agentful", "bin");
|
|
5898
|
+
(0, import_node_fs7.mkdirSync)(binDir, { recursive: true });
|
|
5845
5899
|
const entry = process.argv[1];
|
|
5846
5900
|
if (!entry) return binDir;
|
|
5847
5901
|
const restore = (name) => {
|
|
@@ -5850,8 +5904,8 @@ function ensureCliOnPath() {
|
|
|
5850
5904
|
` : `export ${name}=${JSON.stringify(original)}
|
|
5851
5905
|
`;
|
|
5852
5906
|
};
|
|
5853
|
-
const wrapper = (0,
|
|
5854
|
-
(0,
|
|
5907
|
+
const wrapper = (0, import_node_path9.join)(binDir, "agentful");
|
|
5908
|
+
(0, import_node_fs7.writeFileSync)(
|
|
5855
5909
|
wrapper,
|
|
5856
5910
|
`#!/bin/sh
|
|
5857
5911
|
# Generated by the Agentful CLI so the coding agent can run \`agentful \u2026\`.
|
|
@@ -5861,7 +5915,7 @@ function ensureCliOnPath() {
|
|
|
5861
5915
|
"utf8"
|
|
5862
5916
|
);
|
|
5863
5917
|
try {
|
|
5864
|
-
(0,
|
|
5918
|
+
(0, import_node_fs7.chmodSync)(wrapper, 493);
|
|
5865
5919
|
} catch {
|
|
5866
5920
|
}
|
|
5867
5921
|
return binDir;
|
|
@@ -5871,9 +5925,9 @@ function ensureCliOnPath() {
|
|
|
5871
5925
|
init_branding();
|
|
5872
5926
|
|
|
5873
5927
|
// src/lib/engine.ts
|
|
5874
|
-
var
|
|
5928
|
+
var import_node_fs8 = require("fs");
|
|
5875
5929
|
var import_node_crypto = require("crypto");
|
|
5876
|
-
var
|
|
5930
|
+
var import_node_path10 = require("path");
|
|
5877
5931
|
var import_node_os4 = require("os");
|
|
5878
5932
|
var import_node_child_process3 = require("child_process");
|
|
5879
5933
|
var import_node_stream = require("stream");
|
|
@@ -5914,8 +5968,8 @@ function platformKey() {
|
|
|
5914
5968
|
);
|
|
5915
5969
|
}
|
|
5916
5970
|
function cacheDir(version) {
|
|
5917
|
-
const base = process.env.XDG_CACHE_HOME || (0,
|
|
5918
|
-
return (0,
|
|
5971
|
+
const base = process.env.XDG_CACHE_HOME || (0, import_node_path10.join)((0, import_node_os4.homedir)(), ".cache");
|
|
5972
|
+
return (0, import_node_path10.join)(base, "agentful", "engine", version);
|
|
5919
5973
|
}
|
|
5920
5974
|
async function fetchManifest() {
|
|
5921
5975
|
try {
|
|
@@ -5926,7 +5980,7 @@ async function fetchManifest() {
|
|
|
5926
5980
|
}
|
|
5927
5981
|
async function sha256File(path) {
|
|
5928
5982
|
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
5929
|
-
await (0, import_promises2.pipeline)((0,
|
|
5983
|
+
await (0, import_promises2.pipeline)((0, import_node_fs8.createReadStream)(path), hash);
|
|
5930
5984
|
return hash.digest("hex");
|
|
5931
5985
|
}
|
|
5932
5986
|
async function ensureEngine() {
|
|
@@ -5935,12 +5989,12 @@ async function ensureEngine() {
|
|
|
5935
5989
|
noticeIfOutdated(manifest);
|
|
5936
5990
|
const version = manifest?.engine_version || FALLBACK_ENGINE_VERSION;
|
|
5937
5991
|
const dir = cacheDir(version);
|
|
5938
|
-
const binPath = (0,
|
|
5939
|
-
if ((0,
|
|
5992
|
+
const binPath = (0, import_node_path10.join)(dir, ENGINE_BINARY);
|
|
5993
|
+
if ((0, import_node_fs8.existsSync)(binPath)) return binPath;
|
|
5940
5994
|
const artifact = manifest?.artifacts?.[key];
|
|
5941
5995
|
const url = artifact?.url || `${APP_URL}/cli/engine/${version}/${key}${key.startsWith("darwin") ? ".zip" : ".tar.gz"}`;
|
|
5942
|
-
(0,
|
|
5943
|
-
const archivePath = (0,
|
|
5996
|
+
(0, import_node_fs8.mkdirSync)(dir, { recursive: true });
|
|
5997
|
+
const archivePath = (0, import_node_path10.join)(dir, key.startsWith("darwin") ? "engine.zip" : "engine.tar.gz");
|
|
5944
5998
|
ui.step(`Preparing the ${brand.displayName} engine (first run only)\u2026`);
|
|
5945
5999
|
const resp = await fetch(url, {
|
|
5946
6000
|
redirect: "follow",
|
|
@@ -5954,11 +6008,11 @@ async function ensureEngine() {
|
|
|
5954
6008
|
`Could not download the engine (HTTP ${resp.status}). Check your connection and try again.`
|
|
5955
6009
|
);
|
|
5956
6010
|
}
|
|
5957
|
-
await (0, import_promises2.pipeline)(import_node_stream.Readable.fromWeb(resp.body), (0,
|
|
6011
|
+
await (0, import_promises2.pipeline)(import_node_stream.Readable.fromWeb(resp.body), (0, import_node_fs8.createWriteStream)(archivePath));
|
|
5958
6012
|
if (artifact?.sha256) {
|
|
5959
6013
|
const actual = await sha256File(archivePath);
|
|
5960
6014
|
if (actual !== artifact.sha256) {
|
|
5961
|
-
(0,
|
|
6015
|
+
(0, import_node_fs8.rmSync)(archivePath, { force: true });
|
|
5962
6016
|
throw new ApiError(
|
|
5963
6017
|
0,
|
|
5964
6018
|
"engine_checksum_mismatch",
|
|
@@ -5967,7 +6021,7 @@ async function ensureEngine() {
|
|
|
5967
6021
|
}
|
|
5968
6022
|
}
|
|
5969
6023
|
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" });
|
|
5970
|
-
(0,
|
|
6024
|
+
(0, import_node_fs8.rmSync)(archivePath, { force: true });
|
|
5971
6025
|
if (extract.status !== 0) {
|
|
5972
6026
|
throw new ApiError(
|
|
5973
6027
|
0,
|
|
@@ -5975,24 +6029,24 @@ async function ensureEngine() {
|
|
|
5975
6029
|
`Could not unpack the engine (needs ${archivePath.endsWith(".zip") ? "unzip" : "tar"} on PATH).`
|
|
5976
6030
|
);
|
|
5977
6031
|
}
|
|
5978
|
-
const extracted = (0,
|
|
5979
|
-
if ((0,
|
|
5980
|
-
if (!(0,
|
|
6032
|
+
const extracted = (0, import_node_path10.join)(dir, "opencode");
|
|
6033
|
+
if ((0, import_node_fs8.existsSync)(extracted) && !(0, import_node_fs8.existsSync)(binPath)) (0, import_node_fs8.renameSync)(extracted, binPath);
|
|
6034
|
+
if (!(0, import_node_fs8.existsSync)(binPath)) {
|
|
5981
6035
|
throw new ApiError(0, "engine_extract_failed", "Engine archive did not contain the expected binary.");
|
|
5982
6036
|
}
|
|
5983
|
-
(0,
|
|
6037
|
+
(0, import_node_fs8.chmodSync)(binPath, 493);
|
|
5984
6038
|
ui.ok(`Engine ready.`);
|
|
5985
6039
|
console.log(paint.dim(" powered by opencode (MIT) \xB7 run `agentful licenses` for details"));
|
|
5986
6040
|
return binPath;
|
|
5987
6041
|
}
|
|
5988
6042
|
|
|
5989
6043
|
// src/lib/gatewayToken.ts
|
|
5990
|
-
var
|
|
5991
|
-
var
|
|
5992
|
-
var cachePath = () => (0,
|
|
6044
|
+
var import_node_fs9 = require("fs");
|
|
6045
|
+
var import_node_path11 = require("path");
|
|
6046
|
+
var cachePath = () => (0, import_node_path11.join)(configDir(), "gateway.json");
|
|
5993
6047
|
async function ensureGatewaySession(auth, projectId) {
|
|
5994
6048
|
try {
|
|
5995
|
-
const cached = JSON.parse((0,
|
|
6049
|
+
const cached = JSON.parse((0, import_node_fs9.readFileSync)(cachePath(), "utf8"));
|
|
5996
6050
|
if (cached?.token && cached.expires_at - Date.now() / 1e3 > 3600) {
|
|
5997
6051
|
return cached;
|
|
5998
6052
|
}
|
|
@@ -6003,18 +6057,18 @@ async function ensureGatewaySession(auth, projectId) {
|
|
|
6003
6057
|
body: projectId ? { project_id: projectId } : {},
|
|
6004
6058
|
timeoutMs: 3e4
|
|
6005
6059
|
});
|
|
6006
|
-
(0,
|
|
6007
|
-
(0,
|
|
6060
|
+
(0, import_node_fs9.mkdirSync)(configDir(), { recursive: true });
|
|
6061
|
+
(0, import_node_fs9.writeFileSync)(cachePath(), JSON.stringify(res, null, 2) + "\n", "utf8");
|
|
6008
6062
|
try {
|
|
6009
|
-
(0,
|
|
6063
|
+
(0, import_node_fs9.chmodSync)(cachePath(), 384);
|
|
6010
6064
|
} catch {
|
|
6011
6065
|
}
|
|
6012
6066
|
return res;
|
|
6013
6067
|
}
|
|
6014
6068
|
|
|
6015
6069
|
// src/lib/engineConfig.ts
|
|
6016
|
-
var
|
|
6017
|
-
var
|
|
6070
|
+
var import_node_fs11 = require("fs");
|
|
6071
|
+
var import_node_path13 = require("path");
|
|
6018
6072
|
var import_node_os5 = require("os");
|
|
6019
6073
|
|
|
6020
6074
|
// src/branding/agentful-theme.json
|
|
@@ -6123,6 +6177,10 @@ var SLASH_COMMANDS = {
|
|
|
6123
6177
|
description: `${brand.displayName}: show the last cloud build result`,
|
|
6124
6178
|
template: "Run `agentful build-status` from the project root using the bash tool and report what it prints: status, phase, framework, when it was recorded, and the error/details verbatim if it failed. That record is the only source of truth about the cloud build \u2014 do not speculate beyond it. " + NEEDS_A_PUSH
|
|
6125
6179
|
},
|
|
6180
|
+
backend: {
|
|
6181
|
+
description: `${brand.displayName}: open the Backend tab (managed DB + server actions)`,
|
|
6182
|
+
template: "Run `agentful backend` from the project root using the bash tool and report the URL it opened. If it prints a declared backend (managed DB / server actions), summarize that and remind me that declared-in-code serves nothing until enabled in that tab. " + NEEDS_A_PUSH
|
|
6183
|
+
},
|
|
6126
6184
|
preview: {
|
|
6127
6185
|
description: `${brand.displayName}: open the live preview in the browser`,
|
|
6128
6186
|
template: "Run `agentful open` from the project root using the bash tool and report the URL it opened. Note that `open` neither builds nor uploads. " + NEEDS_A_PUSH
|
|
@@ -6153,22 +6211,22 @@ ${cmd.template}
|
|
|
6153
6211
|
}
|
|
6154
6212
|
|
|
6155
6213
|
// src/lib/tools.ts
|
|
6156
|
-
var
|
|
6157
|
-
var
|
|
6214
|
+
var import_node_fs10 = require("fs");
|
|
6215
|
+
var import_node_path12 = require("path");
|
|
6158
6216
|
function assetsDir() {
|
|
6159
|
-
const here = (0,
|
|
6160
|
-
for (const candidate of [(0,
|
|
6161
|
-
if ((0,
|
|
6217
|
+
const here = (0, import_node_path12.dirname)(process.argv[1] || "");
|
|
6218
|
+
for (const candidate of [(0, import_node_path12.join)(here, "..", "assets"), (0, import_node_path12.join)(here, "assets")]) {
|
|
6219
|
+
if ((0, import_node_fs10.existsSync)((0, import_node_path12.join)(candidate, "tools", "imagegen.ts"))) return candidate;
|
|
6162
6220
|
}
|
|
6163
6221
|
return null;
|
|
6164
6222
|
}
|
|
6165
6223
|
function installEngineTools(configDir2) {
|
|
6166
6224
|
const assets = assetsDir();
|
|
6167
6225
|
if (!assets) return false;
|
|
6168
|
-
const target = (0,
|
|
6169
|
-
(0,
|
|
6226
|
+
const target = (0, import_node_path12.join)(configDir2, "tools");
|
|
6227
|
+
(0, import_node_fs10.mkdirSync)(target, { recursive: true });
|
|
6170
6228
|
try {
|
|
6171
|
-
(0,
|
|
6229
|
+
(0, import_node_fs10.cpSync)((0, import_node_path12.join)(assets, "tools"), target, { recursive: true });
|
|
6172
6230
|
return true;
|
|
6173
6231
|
} catch {
|
|
6174
6232
|
return false;
|
|
@@ -6246,6 +6304,19 @@ statically evaluable; prefer client-side fetch or Managed Server Actions.
|
|
|
6246
6304
|
(b) an external backend called from the client. Never a bundled server
|
|
6247
6305
|
process, and never a script the user must run locally to produce the result.
|
|
6248
6306
|
|
|
6307
|
+
When you design a managed backend (DB schema, server actions), also write the
|
|
6308
|
+
machine-readable declaration \`.agentful/backend.json\`:
|
|
6309
|
+
\`{"schema_version": 1, "managed_db": true, "actions": ["<action-name>", \u2026], "contract_doc": "docs/backend-contract.md"}\`
|
|
6310
|
+
\u2014 \`agentful push\` and \`agentful backend\` use it to tell the user honestly
|
|
6311
|
+
what is declared in code but not yet enabled on the platform.
|
|
6312
|
+
|
|
6313
|
+
When you point the user at the Backend tab, NEVER say "the Backend tab"
|
|
6314
|
+
without an address. Read \`.agentful/project.json\` and give the full URL
|
|
6315
|
+
\`https://app.agentful.dev/workspace/<userId>/<projectId>?view=backend\` \u2014 or
|
|
6316
|
+
simply the command \`agentful backend\`, which opens exactly that page.
|
|
6317
|
+
Declaring a backend never enables it; enabling is the user's conscious step
|
|
6318
|
+
in that tab.
|
|
6319
|
+
|
|
6249
6320
|
## Diagnosing failed pushes and cloud builds (hard rule)
|
|
6250
6321
|
|
|
6251
6322
|
Diagnose **only from evidence**: the preflight output of \`agentful push\`, and
|
|
@@ -6313,11 +6384,11 @@ function buildEngineConfig(opts) {
|
|
|
6313
6384
|
};
|
|
6314
6385
|
}
|
|
6315
6386
|
function engineXdg() {
|
|
6316
|
-
const root = (0,
|
|
6387
|
+
const root = (0, import_node_path13.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful");
|
|
6317
6388
|
return {
|
|
6318
|
-
configHome: (0,
|
|
6319
|
-
dataHome: (0,
|
|
6320
|
-
stateHome: (0,
|
|
6389
|
+
configHome: (0, import_node_path13.join)(root, "engine-config"),
|
|
6390
|
+
dataHome: (0, import_node_path13.join)(root, "engine-data"),
|
|
6391
|
+
stateHome: (0, import_node_path13.join)(root, "engine-state")
|
|
6321
6392
|
};
|
|
6322
6393
|
}
|
|
6323
6394
|
async function resolveTheme() {
|
|
@@ -6336,24 +6407,24 @@ async function resolveTheme() {
|
|
|
6336
6407
|
}
|
|
6337
6408
|
async function writeEngineSession(session, catalog, localProviders = {}, framework = "unknown", skillsInstruction = null) {
|
|
6338
6409
|
const xdg = engineXdg();
|
|
6339
|
-
const configDir2 = (0,
|
|
6340
|
-
const dataDir = (0,
|
|
6341
|
-
const themesDir = (0,
|
|
6342
|
-
const pluginsDir = (0,
|
|
6343
|
-
const commandsDir = (0,
|
|
6344
|
-
for (const dir of [themesDir, pluginsDir, commandsDir, dataDir, (0,
|
|
6345
|
-
(0,
|
|
6410
|
+
const configDir2 = (0, import_node_path13.join)(xdg.configHome, "opencode");
|
|
6411
|
+
const dataDir = (0, import_node_path13.join)(xdg.dataHome, "opencode");
|
|
6412
|
+
const themesDir = (0, import_node_path13.join)(configDir2, "themes");
|
|
6413
|
+
const pluginsDir = (0, import_node_path13.join)(configDir2, "plugins");
|
|
6414
|
+
const commandsDir = (0, import_node_path13.join)(configDir2, "commands");
|
|
6415
|
+
for (const dir of [themesDir, pluginsDir, commandsDir, dataDir, (0, import_node_path13.join)(xdg.stateHome, "opencode")]) {
|
|
6416
|
+
(0, import_node_fs11.mkdirSync)(dir, { recursive: true });
|
|
6346
6417
|
}
|
|
6347
6418
|
const imagegenAvailable = installEngineTools(configDir2) && session.img_on !== false;
|
|
6348
|
-
const cloudInstructionsPath = (0,
|
|
6349
|
-
(0,
|
|
6350
|
-
const skillsPath = (0,
|
|
6419
|
+
const cloudInstructionsPath = (0, import_node_path13.join)(configDir2, CLOUD_INSTRUCTIONS_FILENAME);
|
|
6420
|
+
(0, import_node_fs11.writeFileSync)(cloudInstructionsPath, renderCloudInstructions(framework));
|
|
6421
|
+
const skillsPath = (0, import_node_path13.join)(configDir2, "AGENTFUL_SKILLS.md");
|
|
6351
6422
|
const instructionPaths = [cloudInstructionsPath];
|
|
6352
6423
|
if (skillsInstruction) {
|
|
6353
|
-
(0,
|
|
6424
|
+
(0, import_node_fs11.writeFileSync)(skillsPath, skillsInstruction);
|
|
6354
6425
|
instructionPaths.push(skillsPath);
|
|
6355
6426
|
} else {
|
|
6356
|
-
(0,
|
|
6427
|
+
(0, import_node_fs11.rmSync)(skillsPath, { force: true });
|
|
6357
6428
|
}
|
|
6358
6429
|
const config = buildEngineConfig({
|
|
6359
6430
|
session,
|
|
@@ -6362,24 +6433,24 @@ async function writeEngineSession(session, catalog, localProviders = {}, framewo
|
|
|
6362
6433
|
imagegenAvailable,
|
|
6363
6434
|
instructionPaths
|
|
6364
6435
|
});
|
|
6365
|
-
(0,
|
|
6366
|
-
(0,
|
|
6436
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path13.join)(configDir2, "config.json"), JSON.stringify(config, null, 2));
|
|
6437
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path13.join)(dataDir, "auth.json"), JSON.stringify({
|
|
6367
6438
|
[PROVIDER_ID]: { apiKey: session.token }
|
|
6368
6439
|
}, null, 2));
|
|
6369
6440
|
const { brandingPluginSource: brandingPluginSource2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
|
|
6370
|
-
const pluginPath = (0,
|
|
6371
|
-
(0,
|
|
6372
|
-
(0,
|
|
6441
|
+
const pluginPath = (0, import_node_path13.join)(pluginsDir, "agentful-branding.tsx");
|
|
6442
|
+
(0, import_node_fs11.writeFileSync)(pluginPath, brandingPluginSource2());
|
|
6443
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path13.join)(configDir2, "tui.json"), JSON.stringify({
|
|
6373
6444
|
theme: "agentful",
|
|
6374
6445
|
plugin: [`file://${pluginPath}`]
|
|
6375
6446
|
}, null, 2));
|
|
6376
|
-
(0,
|
|
6447
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path13.join)(themesDir, "agentful.json"), JSON.stringify(await resolveTheme(), null, 2));
|
|
6377
6448
|
for (const name of Object.keys(SLASH_COMMANDS)) {
|
|
6378
|
-
(0,
|
|
6449
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path13.join)(commandsDir, `${name}.md`), commandMarkdown(name));
|
|
6379
6450
|
}
|
|
6380
6451
|
for (const legacy of ["xdg-config", "xdg-data", "xdg-state"]) {
|
|
6381
6452
|
try {
|
|
6382
|
-
(0,
|
|
6453
|
+
(0, import_node_fs11.rmSync)((0, import_node_path13.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful", legacy), { recursive: true, force: true });
|
|
6383
6454
|
} catch {
|
|
6384
6455
|
}
|
|
6385
6456
|
}
|
|
@@ -6387,8 +6458,8 @@ async function writeEngineSession(session, catalog, localProviders = {}, framewo
|
|
|
6387
6458
|
}
|
|
6388
6459
|
|
|
6389
6460
|
// src/lib/skills.ts
|
|
6390
|
-
var
|
|
6391
|
-
var
|
|
6461
|
+
var import_node_fs12 = require("fs");
|
|
6462
|
+
var import_node_path14 = require("path");
|
|
6392
6463
|
|
|
6393
6464
|
// src/generated/skills.json
|
|
6394
6465
|
var skills_default = {
|
|
@@ -6415,7 +6486,7 @@ var SCAFFOLD_BY_FRAMEWORK = {
|
|
|
6415
6486
|
};
|
|
6416
6487
|
function hasVueDependency(rootDir) {
|
|
6417
6488
|
try {
|
|
6418
|
-
const pkg = JSON.parse((0,
|
|
6489
|
+
const pkg = JSON.parse((0, import_node_fs12.readFileSync)((0, import_node_path14.join)(rootDir, "package.json"), "utf8"));
|
|
6419
6490
|
return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }["vue"]);
|
|
6420
6491
|
} catch {
|
|
6421
6492
|
return false;
|
|
@@ -6443,7 +6514,7 @@ function renderSkillsInstruction(names) {
|
|
|
6443
6514
|
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";
|
|
6444
6515
|
}
|
|
6445
6516
|
function skillsInstructionFor(framework, rootDir) {
|
|
6446
|
-
if (!(0,
|
|
6517
|
+
if (!(0, import_node_fs12.existsSync)(rootDir)) return null;
|
|
6447
6518
|
return renderSkillsInstruction(selectSkills(framework, rootDir));
|
|
6448
6519
|
}
|
|
6449
6520
|
|
|
@@ -6558,15 +6629,15 @@ function decideLocalProviders(policy) {
|
|
|
6558
6629
|
}
|
|
6559
6630
|
|
|
6560
6631
|
// src/lib/localProviders.ts
|
|
6561
|
-
var
|
|
6562
|
-
var
|
|
6632
|
+
var import_node_fs13 = require("fs");
|
|
6633
|
+
var import_node_path15 = require("path");
|
|
6563
6634
|
var LOCAL_PROVIDERS_FILE = "local-providers.json";
|
|
6564
6635
|
function localProvidersPath() {
|
|
6565
|
-
return (0,
|
|
6636
|
+
return (0, import_node_path15.join)(configDir(), LOCAL_PROVIDERS_FILE);
|
|
6566
6637
|
}
|
|
6567
6638
|
function readLocalProviders() {
|
|
6568
6639
|
try {
|
|
6569
|
-
const raw = JSON.parse((0,
|
|
6640
|
+
const raw = JSON.parse((0, import_node_fs13.readFileSync)(localProvidersPath(), "utf8"));
|
|
6570
6641
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
6571
6642
|
const map = raw.providers && typeof raw.providers === "object" ? raw.providers : raw;
|
|
6572
6643
|
const usable = {};
|
|
@@ -6601,8 +6672,8 @@ function resolveLocalProviders(policy) {
|
|
|
6601
6672
|
}
|
|
6602
6673
|
function writeLocalProvidersExample() {
|
|
6603
6674
|
const path = localProvidersPath();
|
|
6604
|
-
if ((0,
|
|
6605
|
-
(0,
|
|
6675
|
+
if ((0, import_node_fs13.existsSync)(path)) return path;
|
|
6676
|
+
(0, import_node_fs13.mkdirSync)(configDir(), { recursive: true });
|
|
6606
6677
|
const example = {
|
|
6607
6678
|
_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.',
|
|
6608
6679
|
_anthropic: {
|
|
@@ -6612,21 +6683,21 @@ function writeLocalProvidersExample() {
|
|
|
6612
6683
|
models: { "claude-sonnet-4-5": { name: "Claude Sonnet 4.5 (my key)" } }
|
|
6613
6684
|
}
|
|
6614
6685
|
};
|
|
6615
|
-
(0,
|
|
6686
|
+
(0, import_node_fs13.writeFileSync)(path, JSON.stringify(example, null, 2) + "\n", "utf8");
|
|
6616
6687
|
try {
|
|
6617
|
-
(0,
|
|
6688
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
6618
6689
|
} catch {
|
|
6619
6690
|
}
|
|
6620
6691
|
return path;
|
|
6621
6692
|
}
|
|
6622
6693
|
|
|
6623
6694
|
// src/lib/sessions.ts
|
|
6624
|
-
var
|
|
6625
|
-
var
|
|
6695
|
+
var import_node_fs14 = require("fs");
|
|
6696
|
+
var import_node_path16 = require("path");
|
|
6626
6697
|
var import_node_child_process4 = require("child_process");
|
|
6627
6698
|
function lastSessionForDirectory(cwd = process.cwd()) {
|
|
6628
|
-
const dbPath = (0,
|
|
6629
|
-
if (!(0,
|
|
6699
|
+
const dbPath = (0, import_node_path16.join)(engineXdg().dataHome, "opencode", "opencode.db");
|
|
6700
|
+
if (!(0, import_node_fs14.existsSync)(dbPath)) return null;
|
|
6630
6701
|
const escaped = cwd.replace(/'/g, "''");
|
|
6631
6702
|
const res = (0, import_node_child_process4.spawnSync)(
|
|
6632
6703
|
"sqlite3",
|
|
@@ -6714,7 +6785,7 @@ async function tuiCommand(opts = {}) {
|
|
|
6714
6785
|
...process.env,
|
|
6715
6786
|
// Slash commands run `agentful …` through the agent's bash tool, which
|
|
6716
6787
|
// has no access to the user's shell aliases.
|
|
6717
|
-
PATH: `${binDir}${
|
|
6788
|
+
PATH: `${binDir}${import_node_path17.delimiter}${process.env.PATH || ""}`,
|
|
6718
6789
|
XDG_CONFIG_HOME: xdg.configHome,
|
|
6719
6790
|
XDG_DATA_HOME: xdg.dataHome,
|
|
6720
6791
|
XDG_STATE_HOME: xdg.stateHome,
|
|
@@ -6819,28 +6890,28 @@ async function shareCommand(opts) {
|
|
|
6819
6890
|
}
|
|
6820
6891
|
|
|
6821
6892
|
// src/commands/pull.ts
|
|
6822
|
-
var
|
|
6823
|
-
var
|
|
6893
|
+
var import_node_fs15 = require("fs");
|
|
6894
|
+
var import_node_path18 = require("path");
|
|
6824
6895
|
init_branding();
|
|
6825
6896
|
init_branding();
|
|
6826
6897
|
function isProbablyBase64Binary(path) {
|
|
6827
6898
|
return /\.(png|jpe?g|gif|webp|ico|woff2?|ttf|otf|eot|pdf|zip|mp[34]|webm|avif)$/i.test(path);
|
|
6828
6899
|
}
|
|
6829
6900
|
function writeEntry(root, rel, value) {
|
|
6830
|
-
const target = (0,
|
|
6831
|
-
(0,
|
|
6901
|
+
const target = (0, import_node_path18.join)(root, rel);
|
|
6902
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(target), { recursive: true });
|
|
6832
6903
|
const content = typeof value === "object" && value !== null && "content" in value ? String(value.content) : String(value ?? "");
|
|
6833
6904
|
if (isProbablyBase64Binary(rel)) {
|
|
6834
|
-
(0,
|
|
6905
|
+
(0, import_node_fs15.writeFileSync)(target, Buffer.from(content, "base64"));
|
|
6835
6906
|
} else {
|
|
6836
|
-
(0,
|
|
6907
|
+
(0, import_node_fs15.writeFileSync)(target, content, "utf8");
|
|
6837
6908
|
}
|
|
6838
6909
|
}
|
|
6839
6910
|
async function pullCommand(opts) {
|
|
6840
6911
|
console.log(banner());
|
|
6841
6912
|
const auth = await ensureAuth();
|
|
6842
6913
|
const project = requireProject();
|
|
6843
|
-
const nonHidden = (0,
|
|
6914
|
+
const nonHidden = (0, import_node_fs15.readdirSync)(process.cwd()).filter((n) => n !== ".agentful" && !n.startsWith("."));
|
|
6844
6915
|
if (nonHidden.length > 0 && !opts.force) {
|
|
6845
6916
|
throw new ApiError(
|
|
6846
6917
|
0,
|
|
@@ -6864,9 +6935,9 @@ async function pullCommand(opts) {
|
|
|
6864
6935
|
ui.warn(`Skipped ${rel} (HTTP ${resp.status})`);
|
|
6865
6936
|
continue;
|
|
6866
6937
|
}
|
|
6867
|
-
const target = (0,
|
|
6868
|
-
(0,
|
|
6869
|
-
(0,
|
|
6938
|
+
const target = (0, import_node_path18.join)(process.cwd(), rel);
|
|
6939
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(target), { recursive: true });
|
|
6940
|
+
(0, import_node_fs15.writeFileSync)(target, Buffer.from(await resp.arrayBuffer()));
|
|
6870
6941
|
written++;
|
|
6871
6942
|
}
|
|
6872
6943
|
} else if (data.files) {
|
|
@@ -6957,13 +7028,23 @@ async function upgradeCommand() {
|
|
|
6957
7028
|
console.log(banner());
|
|
6958
7029
|
let latest = "";
|
|
6959
7030
|
try {
|
|
6960
|
-
const
|
|
6961
|
-
|
|
7031
|
+
const registry = await request(
|
|
7032
|
+
`https://registry.npmjs.org/${brand.name}/latest`,
|
|
6962
7033
|
{ timeoutMs: 8e3 }
|
|
6963
7034
|
);
|
|
6964
|
-
latest =
|
|
7035
|
+
latest = registry.version || "";
|
|
6965
7036
|
} catch {
|
|
6966
7037
|
}
|
|
7038
|
+
if (!latest) {
|
|
7039
|
+
try {
|
|
7040
|
+
const manifest = await request(
|
|
7041
|
+
`${APP_URL}/cli/engine-manifest.json`,
|
|
7042
|
+
{ timeoutMs: 8e3 }
|
|
7043
|
+
);
|
|
7044
|
+
latest = manifest.latest_cli_version || "";
|
|
7045
|
+
} catch {
|
|
7046
|
+
}
|
|
7047
|
+
}
|
|
6967
7048
|
if (latest && compareVersions(VERSION, latest) >= 0) {
|
|
6968
7049
|
ui.ok(`Already on the latest version (v${VERSION}).`);
|
|
6969
7050
|
return;
|
|
@@ -7012,6 +7093,7 @@ program2.command("whoami").description("Show the signed-in account").action(run(
|
|
|
7012
7093
|
program2.command("init").description("Create (or link) the Agentful cloud project for this directory").argument("[directory]", "with --template: new folder to scaffold into (created for you)").option("--link <projectId>", "link an existing project instead of creating one").option("--title <title>", "project title (skips the prompt)").option("--template <framework>", "scaffold from a platform starter (nextjs, react, vue, vanilla)").action(run((directory, opts) => initCommand(opts, directory)));
|
|
7013
7094
|
program2.command("push").description("Upload this project and get a live preview URL").option("--prebuilt", "upload a locally built output instead of building in the cloud").option("--dir <path>", "built-output directory for --prebuilt (default: auto-detect)").option("--force", "push even when the pre-upload compatibility check finds blocking issues").action(run((opts) => pushCommand(opts)));
|
|
7014
7095
|
program2.command("build-status").description("Show the cloud's record of the last build (the real error on failures)").action(run(buildStatusCommand));
|
|
7096
|
+
program2.command("backend").description("Open this project's Backend tab (managed DB + server actions) in the browser").action(run(backendCommand));
|
|
7015
7097
|
program2.command("open").description("Open the live preview in the browser").action(run(openCommand));
|
|
7016
7098
|
program2.command("tui").description("Start the Agentful coding TUI with your Agentful account").option("-s, --session <id>", "resume a previous session").action(run((opts) => tuiCommand(opts)));
|
|
7017
7099
|
program2.command("publish <subdomain>").description("Publish the built project at https://<subdomain>.agentful.dev").action(run(publishCommand));
|