agentful 0.4.14 → 0.4.15
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 +6 -2
- package/dist/index.cjs +263 -77
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ agentful open # open the preview
|
|
|
26
26
|
| `login` / `logout` / `whoami` | Browser-based sign-in; the token is kept in the macOS Keychain (on Linux: a `0600` file under `~/.config/agentful/`) |
|
|
27
27
|
| `init [--link <id>] [--title <t>]` | Create a cloud project or link an existing one (`.agentful/project.json`) |
|
|
28
28
|
| `push [--prebuilt [--dir <path>]]` | Upload the source and build in the cloud; `--prebuilt` uploads a local build |
|
|
29
|
-
| `push --dry-run [--json]` | Analyse what a push would upload and what would block it — uploads nothing |
|
|
29
|
+
| `push --dry-run [--json [--summary]]` | Analyse what a push would upload and what would block it — uploads nothing |
|
|
30
30
|
| `open` | Open the live preview |
|
|
31
31
|
| `share [--private]` | Make the preview public, or private again |
|
|
32
32
|
| `publish <subdomain>` | Publish at `https://<subdomain>.agentful.page` |
|
|
@@ -39,6 +39,9 @@ agentful open # open the preview
|
|
|
39
39
|
|
|
40
40
|
Inside the interface, `/` lists the Agentful commands (`/setup`, `/push`,
|
|
41
41
|
`/preview`, `/publish`, `/share`, `/status`) alongside the built-in ones.
|
|
42
|
+
`/push` checks before it uploads: the agent reads the same analysis as
|
|
43
|
+
`push --dry-run`, explains what would block the upload or go missing on the
|
|
44
|
+
site, and asks you before it changes a file or pushes.
|
|
42
45
|
|
|
43
46
|
`push` respects your `.gitignore` and always excludes `.git`, `node_modules`,
|
|
44
47
|
build output and every `.env` file. A push carries at most about 4.4 MiB
|
|
@@ -51,7 +54,8 @@ and what is left out, the largest files, identical copies, media embedded in
|
|
|
51
54
|
HTML, and every reason the upload would be rejected. It uploads nothing,
|
|
52
55
|
creates no project and changes no file; it exits with 1 when the push would be
|
|
53
56
|
blocked. `--dry-run --json` prints the same analysis as one JSON document
|
|
54
|
-
(`"schema": "agentful.push-analysis"`) for scripts and agents
|
|
57
|
+
(`"schema": "agentful.push-analysis"`) for scripts and agents; with `--summary`
|
|
58
|
+
it leaves out the list of every file and keeps totals, limits and findings.
|
|
55
59
|
|
|
56
60
|
## What you can deploy
|
|
57
61
|
|
package/dist/index.cjs
CHANGED
|
@@ -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.15" ? "0.4.15" : null.version;
|
|
3048
3048
|
brand = {
|
|
3049
3049
|
name: "agentful",
|
|
3050
3050
|
// the command users type
|
|
@@ -6606,6 +6606,7 @@ function failedAnalysis(mode, projectDir, blocker) {
|
|
|
6606
6606
|
schema: ANALYSIS_SCHEMA,
|
|
6607
6607
|
schema_version: ANALYSIS_SCHEMA_VERSION,
|
|
6608
6608
|
cli_version: VERSION,
|
|
6609
|
+
view: "full",
|
|
6609
6610
|
mode,
|
|
6610
6611
|
root: null,
|
|
6611
6612
|
ok: false,
|
|
@@ -6911,6 +6912,7 @@ function analyzePush(options) {
|
|
|
6911
6912
|
schema: ANALYSIS_SCHEMA,
|
|
6912
6913
|
schema_version: ANALYSIS_SCHEMA_VERSION,
|
|
6913
6914
|
cli_version: VERSION,
|
|
6915
|
+
view: "full",
|
|
6914
6916
|
mode,
|
|
6915
6917
|
root: rootDir,
|
|
6916
6918
|
ok: blockers.length === 0,
|
|
@@ -6947,6 +6949,81 @@ function analyzePush(options) {
|
|
|
6947
6949
|
fingerprint: `sha256:${fingerprint}`
|
|
6948
6950
|
};
|
|
6949
6951
|
}
|
|
6952
|
+
var SUMMARY_LISTS = {
|
|
6953
|
+
largest_files: 8,
|
|
6954
|
+
by_top_level: 8,
|
|
6955
|
+
duplicates: 8,
|
|
6956
|
+
duplicate_paths: 8,
|
|
6957
|
+
embedded_media: 8,
|
|
6958
|
+
entry_candidates: 20,
|
|
6959
|
+
excluded_entries: 30,
|
|
6960
|
+
dropped_by_platform: 20,
|
|
6961
|
+
finding_paths: 8
|
|
6962
|
+
};
|
|
6963
|
+
var SUMMARY_MAX_BYTES = 24 * 1024;
|
|
6964
|
+
var printAnalysis = (analysis) => `${JSON.stringify(analysis, null, 2)}
|
|
6965
|
+
`;
|
|
6966
|
+
function summarize(analysis, divisor) {
|
|
6967
|
+
const shortened = {};
|
|
6968
|
+
const cut = (name, list, cap, alreadyOmitted = 0) => {
|
|
6969
|
+
const keep = Math.max(1, Math.floor(cap / divisor));
|
|
6970
|
+
const omitted = Math.max(0, list.length - keep) + alreadyOmitted;
|
|
6971
|
+
if (omitted > 0) shortened[name] = (shortened[name] ?? 0) + omitted;
|
|
6972
|
+
return list.slice(0, keep);
|
|
6973
|
+
};
|
|
6974
|
+
const finding = (kind) => (item) => item.paths ? { ...item, paths: cut(`${kind}.paths`, item.paths, SUMMARY_LISTS.finding_paths) } : item;
|
|
6975
|
+
if (analysis.totals.files > 0) shortened.files = analysis.totals.files;
|
|
6976
|
+
const excludedEntries = cut(
|
|
6977
|
+
"excluded.entries",
|
|
6978
|
+
analysis.excluded.entries,
|
|
6979
|
+
SUMMARY_LISTS.excluded_entries,
|
|
6980
|
+
analysis.excluded.omitted
|
|
6981
|
+
);
|
|
6982
|
+
return {
|
|
6983
|
+
schema: analysis.schema,
|
|
6984
|
+
schema_version: analysis.schema_version,
|
|
6985
|
+
cli_version: analysis.cli_version,
|
|
6986
|
+
view: "summary",
|
|
6987
|
+
shortened,
|
|
6988
|
+
mode: analysis.mode,
|
|
6989
|
+
root: analysis.root,
|
|
6990
|
+
ok: analysis.ok,
|
|
6991
|
+
framework: analysis.framework,
|
|
6992
|
+
project: analysis.project,
|
|
6993
|
+
limits: analysis.limits,
|
|
6994
|
+
totals: analysis.totals,
|
|
6995
|
+
blockers: analysis.blockers.map(finding("blockers")),
|
|
6996
|
+
// The note about the cap of the full file list describes a list that is not here.
|
|
6997
|
+
warnings: analysis.warnings.filter((warning) => warning.code !== "file_list_truncated").map(finding("warnings")),
|
|
6998
|
+
suggestions: analysis.suggestions.map(finding("suggestions")),
|
|
6999
|
+
entry: {
|
|
7000
|
+
...analysis.entry,
|
|
7001
|
+
candidates: cut("entry.candidates", analysis.entry.candidates, SUMMARY_LISTS.entry_candidates)
|
|
7002
|
+
},
|
|
7003
|
+
flattened_prefix: analysis.flattened_prefix,
|
|
7004
|
+
largest_files: cut("largest_files", analysis.largest_files, SUMMARY_LISTS.largest_files),
|
|
7005
|
+
by_class: analysis.by_class,
|
|
7006
|
+
by_top_level: cut("by_top_level", analysis.by_top_level, SUMMARY_LISTS.by_top_level),
|
|
7007
|
+
duplicates: cut("duplicates", analysis.duplicates, SUMMARY_LISTS.duplicates).map((group) => ({ ...group, paths: cut("duplicates.paths", group.paths, SUMMARY_LISTS.duplicate_paths) })),
|
|
7008
|
+
embedded_media: cut("embedded_media", analysis.embedded_media, SUMMARY_LISTS.embedded_media),
|
|
7009
|
+
excluded: {
|
|
7010
|
+
...analysis.excluded,
|
|
7011
|
+
entries: excludedEntries,
|
|
7012
|
+
omitted: analysis.excluded.omitted + analysis.excluded.entries.length - excludedEntries.length
|
|
7013
|
+
},
|
|
7014
|
+
dropped_by_platform: cut("dropped_by_platform", analysis.dropped_by_platform, SUMMARY_LISTS.dropped_by_platform),
|
|
7015
|
+
files: [],
|
|
7016
|
+
files_omitted: analysis.totals.files,
|
|
7017
|
+
fingerprint: analysis.fingerprint
|
|
7018
|
+
};
|
|
7019
|
+
}
|
|
7020
|
+
function summarizeAnalysis(analysis) {
|
|
7021
|
+
let summary = summarize(analysis, 1);
|
|
7022
|
+
for (let divisor = 2; divisor <= 32 && Buffer.byteLength(printAnalysis(summary), "utf8") > SUMMARY_MAX_BYTES; divisor *= 2) {
|
|
7023
|
+
summary = summarize(analysis, divisor);
|
|
7024
|
+
}
|
|
7025
|
+
return summary;
|
|
7026
|
+
}
|
|
6950
7027
|
function wouldUpload(analysis, force = false) {
|
|
6951
7028
|
return analysis.blockers.every((blocker) => blocker.overridable && force);
|
|
6952
7029
|
}
|
|
@@ -7425,6 +7502,13 @@ async function pushCommand(opts) {
|
|
|
7425
7502
|
"--json belongs to --dry-run: `agentful push --dry-run --json` prints the upload analysis and uploads nothing."
|
|
7426
7503
|
);
|
|
7427
7504
|
}
|
|
7505
|
+
if (opts.summary && !opts.json) {
|
|
7506
|
+
throw new ApiError(
|
|
7507
|
+
0,
|
|
7508
|
+
"invalid_options",
|
|
7509
|
+
"--summary belongs to --dry-run --json: it prints the analysis without the list of every file."
|
|
7510
|
+
);
|
|
7511
|
+
}
|
|
7428
7512
|
if (!opts.json) console.log(banner());
|
|
7429
7513
|
const mode = opts.prebuilt ? "dist" : "source";
|
|
7430
7514
|
const cwd = process.cwd();
|
|
@@ -7438,8 +7522,7 @@ async function pushCommand(opts) {
|
|
|
7438
7522
|
analysis = failedAnalysis(mode, cwd, { code: err2.code, message: err2.message });
|
|
7439
7523
|
}
|
|
7440
7524
|
if (opts.dryRun) {
|
|
7441
|
-
if (opts.json) process.stdout.write(
|
|
7442
|
-
`);
|
|
7525
|
+
if (opts.json) process.stdout.write(printAnalysis(opts.summary ? summarizeAnalysis(analysis) : analysis));
|
|
7443
7526
|
else for (const line of renderAnalysis(analysis, { force: opts.force, dryRun: true })) console.log(line);
|
|
7444
7527
|
if (!wouldUpload(analysis, opts.force)) process.exitCode = 1;
|
|
7445
7528
|
return;
|
|
@@ -7968,75 +8051,6 @@ var agentful_theme_default = {
|
|
|
7968
8051
|
|
|
7969
8052
|
// src/branding/commands.ts
|
|
7970
8053
|
init_branding();
|
|
7971
|
-
var NEEDS_A_PUSH = 'If the command reports "No Agentful project here", nothing has been deployed from this directory yet \u2014 run `agentful push` first (it creates the project and a preview), then retry.';
|
|
7972
|
-
var SLASH_COMMANDS = {
|
|
7973
|
-
setup: {
|
|
7974
|
-
description: `${brand.displayName}: create or link the cloud project for this directory`,
|
|
7975
|
-
template: 'Check whether .agentful/project.json exists. If it does, report the linked project title and id and stop. Otherwise run `agentful init --title "<name>"` using the bash tool, where <name> is $ARGUMENTS if I gave one, otherwise the current directory name. Report what it created and mention the title I can change it to. Do not modify any other project files.'
|
|
7976
|
-
},
|
|
7977
|
-
push: {
|
|
7978
|
-
description: `${brand.displayName}: deploy this project and get a preview URL`,
|
|
7979
|
-
template: "Run `agentful push` from the project root using the bash tool. It creates the project automatically if this directory is not linked yet. Stream what it prints, and when it finishes report the preview URL on its own line. If it fails: quote the printed error verbatim, and if the failure happened in the cloud (not in the pre-upload preflight), also run `agentful build-status` and quote its phase/error/details as the cause. Diagnose ONLY from those records \u2014 never invent causes, env vars, or settings they do not show. Do not modify project files unless I ask."
|
|
7980
|
-
},
|
|
7981
|
-
"build-status": {
|
|
7982
|
-
description: `${brand.displayName}: show the last cloud build result`,
|
|
7983
|
-
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
|
|
7984
|
-
},
|
|
7985
|
-
backend: {
|
|
7986
|
-
description: `${brand.displayName}: open the Backend tab (managed DB + server actions)`,
|
|
7987
|
-
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
|
|
7988
|
-
},
|
|
7989
|
-
preview: {
|
|
7990
|
-
description: `${brand.displayName}: open the live preview in the browser`,
|
|
7991
|
-
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
|
|
7992
|
-
},
|
|
7993
|
-
publish: {
|
|
7994
|
-
description: `${brand.displayName}: publish on a public subdomain`,
|
|
7995
|
-
template: "Ask me for the subdomain if I did not provide one in $ARGUMENTS, then run `agentful publish <subdomain>` from the project root using the bash tool and report the public URL. " + NEEDS_A_PUSH
|
|
7996
|
-
},
|
|
7997
|
-
share: {
|
|
7998
|
-
description: `${brand.displayName}: make the live preview public (or private again)`,
|
|
7999
|
-
template: "Run `agentful share` from the project root using the bash tool (add `--private` if $ARGUMENTS says private) and report the resulting visibility and URL. " + NEEDS_A_PUSH
|
|
8000
|
-
},
|
|
8001
|
-
status: {
|
|
8002
|
-
description: `${brand.displayName}: show the linked project and account`,
|
|
8003
|
-
template: "Run `agentful whoami` using the bash tool. Then read .agentful/project.json and report the linked project title and id, plus the preview URL https://preview-<projectId>.agentful.page/. If the file does not exist, say that this directory is not linked yet and that `/setup` creates the link."
|
|
8004
|
-
}
|
|
8005
|
-
};
|
|
8006
|
-
function commandMarkdown(name) {
|
|
8007
|
-
const cmd = SLASH_COMMANDS[name];
|
|
8008
|
-
const description = JSON.stringify(cmd.description);
|
|
8009
|
-
return `---
|
|
8010
|
-
description: ${description}
|
|
8011
|
-
agent: ${cmd.agent ?? "agentful-build"}
|
|
8012
|
-
---
|
|
8013
|
-
|
|
8014
|
-
${cmd.template}
|
|
8015
|
-
`;
|
|
8016
|
-
}
|
|
8017
|
-
|
|
8018
|
-
// src/lib/tools.ts
|
|
8019
|
-
var import_node_fs13 = require("fs");
|
|
8020
|
-
var import_node_path15 = require("path");
|
|
8021
|
-
function assetsDir() {
|
|
8022
|
-
const here = (0, import_node_path15.dirname)(process.argv[1] || "");
|
|
8023
|
-
for (const candidate of [(0, import_node_path15.join)(here, "..", "assets"), (0, import_node_path15.join)(here, "assets")]) {
|
|
8024
|
-
if ((0, import_node_fs13.existsSync)((0, import_node_path15.join)(candidate, "tools", "imagegen.ts"))) return candidate;
|
|
8025
|
-
}
|
|
8026
|
-
return null;
|
|
8027
|
-
}
|
|
8028
|
-
function installEngineTools(configDir2) {
|
|
8029
|
-
const assets = assetsDir();
|
|
8030
|
-
if (!assets) return false;
|
|
8031
|
-
const target = (0, import_node_path15.join)(configDir2, "tools");
|
|
8032
|
-
(0, import_node_fs13.mkdirSync)(target, { recursive: true });
|
|
8033
|
-
try {
|
|
8034
|
-
(0, import_node_fs13.cpSync)((0, import_node_path15.join)(assets, "tools"), target, { recursive: true });
|
|
8035
|
-
return true;
|
|
8036
|
-
} catch {
|
|
8037
|
-
return false;
|
|
8038
|
-
}
|
|
8039
|
-
}
|
|
8040
8054
|
|
|
8041
8055
|
// src/lib/cloudTarget.ts
|
|
8042
8056
|
var CLOUD_INSTRUCTIONS_FILENAME = "AGENTFUL_CLOUD.md";
|
|
@@ -8146,6 +8160,87 @@ function serverSideSection() {
|
|
|
8146
8160
|
)
|
|
8147
8161
|
].join("\n\n");
|
|
8148
8162
|
}
|
|
8163
|
+
var PUSH_ANALYSIS_COMMAND = "agentful push --dry-run --json --summary";
|
|
8164
|
+
function pushSection() {
|
|
8165
|
+
const excludedDirs = [...ALWAYS_EXCLUDE_DIRS].filter((name) => /^[a-z]/.test(name)).map((name) => `\`${name}\``).join(", ");
|
|
8166
|
+
return `## Pushing to the platform (\`agentful push\`)
|
|
8167
|
+
|
|
8168
|
+
Two ways to upload. Every push replaces the previous upload completely, so a
|
|
8169
|
+
site can never be uploaded in several parts.
|
|
8170
|
+
|
|
8171
|
+
- **Source push**, \`agentful push\`: uploads this directory, then builds it in
|
|
8172
|
+
the cloud. Never uploaded: paths listed in \`.gitignore\`, \`.env*\` files,
|
|
8173
|
+
symlinks, tool folders such as \`.git\` or \`.next\`, and any folder named
|
|
8174
|
+
${excludedDirs}, at any depth.
|
|
8175
|
+
The cloud build runs \`npm ci\` (with a \`package-lock.json\`, otherwise
|
|
8176
|
+
\`npm install\`) and then the build command from the table above. Nothing
|
|
8177
|
+
else runs: no other package manager, no separate data or prepare script, no
|
|
8178
|
+
CI workflow step.
|
|
8179
|
+
- **Prebuilt push**, \`agentful push --prebuilt --dir <folder>\`: uploads a
|
|
8180
|
+
finished output folder and serves it as it is. No cloud build, \`.gitignore\`
|
|
8181
|
+
is not applied, and \`index.html\` must sit at the top of that folder. It
|
|
8182
|
+
carries the website only: the project source in the cloud stays as it was (a
|
|
8183
|
+
later build in the cloud workspace replaces the site with a build of that
|
|
8184
|
+
source), and Managed Server Actions and \`.agentful/backend.json\` are NOT
|
|
8185
|
+
deployed by it.
|
|
8186
|
+
|
|
8187
|
+
Limits of one push, either way: about ${formatBytes(maxZipBytesForUpload(), "down")} compressed, ${formatBytes(MAX_UNPACKED_BYTES)} of files, ${MAX_UPLOAD_FILES.toLocaleString("en-US")} files.
|
|
8188
|
+
\`--force\` lifts none of them: it only lets the cloud build try despite a
|
|
8189
|
+
compatibility finding.
|
|
8190
|
+
|
|
8191
|
+
**The analysis decides, not an estimate.** \`${PUSH_ANALYSIS_COMMAND}\`
|
|
8192
|
+
(with \`--prebuilt --dir <folder>\` for a prebuilt push) reads the files and
|
|
8193
|
+
reports what a push would upload: no sign-in, no project, no upload, nothing
|
|
8194
|
+
written. Sizes, limits, what is left out and what blocks the upload come from
|
|
8195
|
+
that report and from nowhere else: quote its figures, never estimate or
|
|
8196
|
+
recompute them (\`limits.max_zip_bytes\` is the exact limit for this push).
|
|
8197
|
+
Run it before the first push of a session, after a push was stopped, and after
|
|
8198
|
+
you changed what gets uploaded. In between, \`agentful push\` applies the same
|
|
8199
|
+
check itself and stops before sign-in when something blocks. A blocker with
|
|
8200
|
+
\`"overridable": false\` is final, the platform rejects that upload: do not
|
|
8201
|
+
retry, do not add \`--force\`, do not look for another route.
|
|
8202
|
+
|
|
8203
|
+
Every change to the user's files for a push (including \`.gitignore\`) and every
|
|
8204
|
+
project script you run for it needs the user's OK first: name the concrete
|
|
8205
|
+
change, ask, wait for the answer.
|
|
8206
|
+
|
|
8207
|
+
- **No start page** (\`entry_missing\`): the platform serves \`index.html\` from
|
|
8208
|
+
the top level. With \`entry.candidates\`: show them (path and title;
|
|
8209
|
+
\`same_content_as\` marks copies) and ask which page opens first. A candidate
|
|
8210
|
+
at the top level can be renamed to \`index.html\`, or copied, which keeps the
|
|
8211
|
+
old address and adds the file's size to the upload: ask which. A candidate
|
|
8212
|
+
in a subfolder must not be copied up, its relative links would break. If
|
|
8213
|
+
that folder is the whole site, push the folder (\`suggestions\` carries the
|
|
8214
|
+
command); otherwise adjust the links and show the diff. Without candidates,
|
|
8215
|
+
ask which folder holds the site.
|
|
8216
|
+
- **Too large or too many files** (\`zip_too_large\`, \`unpacked_too_large\`,
|
|
8217
|
+
\`too_many_files\`): explain where the size is, from \`largest_files\`,
|
|
8218
|
+
\`by_top_level\`, \`duplicates\` and \`embedded_media\` (media stored inside text
|
|
8219
|
+
files as \`data:\` URLs). The ways out that exist: leave out files the site
|
|
8220
|
+
does not load (\`.gitignore\`, source push), or push only the finished output
|
|
8221
|
+
folder (prebuilt). Before proposing to leave a file out, search the sources
|
|
8222
|
+
for references to it and say what you checked: identical content does not
|
|
8223
|
+
make a copy unused. Never shrink, re-encode, move or delete the user's files
|
|
8224
|
+
on your own. If what the site needs stays above the limits, say plainly that
|
|
8225
|
+
it cannot be pushed yet. Larger uploads are not available.
|
|
8226
|
+
- **Compatibility findings** (\`"overridable": true\`): fix the cause in the
|
|
8227
|
+
code. \`--force\` only when the user asks to try the cloud build anyway.
|
|
8228
|
+
- **Files that would be missing on the site:** the warnings
|
|
8229
|
+
\`dropped_by_platform\` and \`excluded_static_directory\`, and entries of
|
|
8230
|
+
\`excluded.entries\` with reason \`gitignore\` that the site loads at runtime
|
|
8231
|
+
(generated data under \`public/\`, for example). The build can succeed and the
|
|
8232
|
+
site still be broken: tell the user before pushing and ask.
|
|
8233
|
+
- **Steps the cloud build does not run:** before the first push of a project
|
|
8234
|
+
you did not create in this session, read the \`package.json\` scripts, the
|
|
8235
|
+
README and the CI workflows for data generation, code generation or another
|
|
8236
|
+
package manager. If the site needs such a step, a source push is the wrong
|
|
8237
|
+
way: build locally with the project's own commands and its real data, keep
|
|
8238
|
+
its checks, and push the output folder prebuilt. Never put sample data in
|
|
8239
|
+
place of real data to get a push through.
|
|
8240
|
+
|
|
8241
|
+
A finished build or upload does not prove that the site works: say what you
|
|
8242
|
+
verified and what you did not.`;
|
|
8243
|
+
}
|
|
8149
8244
|
function renderCloudInstructions(framework, backend) {
|
|
8150
8245
|
return `# Agentful Cloud target (platform contract)
|
|
8151
8246
|
|
|
@@ -8300,6 +8395,8 @@ user's conscious step \u2014 in that tab, or by answering the question
|
|
|
8300
8395
|
\`agentful push\` asks once (it names both consequences; a non-interactive
|
|
8301
8396
|
push never enables anything).
|
|
8302
8397
|
|
|
8398
|
+
${pushSection()}
|
|
8399
|
+
|
|
8303
8400
|
## Diagnosing failed pushes and cloud builds (hard rule)
|
|
8304
8401
|
|
|
8305
8402
|
Diagnose **only from evidence**: the preflight output of \`agentful push\`, and
|
|
@@ -8318,6 +8415,93 @@ ${backendSessionLines(backend)}
|
|
|
8318
8415
|
`;
|
|
8319
8416
|
}
|
|
8320
8417
|
|
|
8418
|
+
// src/branding/commands.ts
|
|
8419
|
+
var PUSH_TOOL_TIMEOUT_MS = 9e5;
|
|
8420
|
+
var NEEDS_A_PUSH = 'If the command reports "No Agentful project here", nothing has been deployed from this directory yet \u2014 run `agentful push` first (it creates the project and a preview), then retry.';
|
|
8421
|
+
var SLASH_COMMANDS = {
|
|
8422
|
+
setup: {
|
|
8423
|
+
description: `${brand.displayName}: create or link the cloud project for this directory`,
|
|
8424
|
+
template: 'Check whether .agentful/project.json exists. If it does, report the linked project title and id and stop. Otherwise run `agentful init --title "<name>"` using the bash tool, where <name> is $ARGUMENTS if I gave one, otherwise the current directory name. Report what it created and mention the title I can change it to. Do not modify any other project files.'
|
|
8425
|
+
},
|
|
8426
|
+
// The analysis comes first (upload plan AP7): the report, not the model,
|
|
8427
|
+
// says what would be uploaded, how large it is and what blocks it, and the
|
|
8428
|
+
// rules for acting on it are in AGENTFUL_CLOUD.md. Two things the agent's
|
|
8429
|
+
// shell tool forces on this template: `--summary`, because the tool cuts
|
|
8430
|
+
// output after 2,000 lines or 50 KB and the full report lists every file;
|
|
8431
|
+
// and an explicit timeout, because the tool ends a command after two
|
|
8432
|
+
// minutes by default and a cloud build takes longer (engine 1.18.32).
|
|
8433
|
+
push: {
|
|
8434
|
+
description: `${brand.displayName}: check, deploy and get a preview URL`,
|
|
8435
|
+
template: `Deploy this project, following "Pushing to the platform" in AGENTFUL_CLOUD.md. Run every command from the project root using the bash tool. What I typed after the command (may be empty): "$ARGUMENTS". If it names \`--prebuilt\`, a folder for \`--dir\`, or \`--force\`, pass that on to both commands below.
|
|
8436
|
+
|
|
8437
|
+
1. Run \`${PUSH_ANALYSIS_COMMAND}\`. It only reads files: no sign-in, no upload. Its JSON report is the only source for sizes, limits and what blocks the upload: quote its figures, never estimate them.
|
|
8438
|
+
2. If the report or the project calls for a decision (a blocker, a file the site needs that would not be uploaded, a build step the cloud does not run), explain the finding in plain words with the figures of the report and ask me how to proceed. One question at a time, then wait for my answer. Until then do not change any file, do not run project scripts and do not push.
|
|
8439
|
+
3. After a change I approved, run the analysis again.
|
|
8440
|
+
4. When nothing blocks, run \`agentful push\` with the bash tool's \`timeout\` set to ${PUSH_TOOL_TIMEOUT_MS} (milliseconds): the cloud build takes minutes and the default timeout would cut the push off halfway. The command never waits for input. It creates the project automatically if this directory is not linked yet.
|
|
8441
|
+
5. Report the preview URL on its own line and what the push printed about the backend. If it fails: quote the printed error verbatim, and if the failure happened in the cloud (not before the upload), also run \`agentful build-status\` and quote its phase/error/details as the cause. Diagnose ONLY from those records \u2014 never invent causes, env vars, or settings they do not show.
|
|
8442
|
+
|
|
8443
|
+
Apart from a change I approved in step 2, do not modify project files.`
|
|
8444
|
+
},
|
|
8445
|
+
"build-status": {
|
|
8446
|
+
description: `${brand.displayName}: show the last cloud build result`,
|
|
8447
|
+
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
|
|
8448
|
+
},
|
|
8449
|
+
backend: {
|
|
8450
|
+
description: `${brand.displayName}: open the Backend tab (managed DB + server actions)`,
|
|
8451
|
+
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
|
|
8452
|
+
},
|
|
8453
|
+
preview: {
|
|
8454
|
+
description: `${brand.displayName}: open the live preview in the browser`,
|
|
8455
|
+
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
|
|
8456
|
+
},
|
|
8457
|
+
publish: {
|
|
8458
|
+
description: `${brand.displayName}: publish on a public subdomain`,
|
|
8459
|
+
template: "Ask me for the subdomain if I did not provide one in $ARGUMENTS, then run `agentful publish <subdomain>` from the project root using the bash tool and report the public URL. " + NEEDS_A_PUSH
|
|
8460
|
+
},
|
|
8461
|
+
share: {
|
|
8462
|
+
description: `${brand.displayName}: make the live preview public (or private again)`,
|
|
8463
|
+
template: "Run `agentful share` from the project root using the bash tool (add `--private` if $ARGUMENTS says private) and report the resulting visibility and URL. " + NEEDS_A_PUSH
|
|
8464
|
+
},
|
|
8465
|
+
status: {
|
|
8466
|
+
description: `${brand.displayName}: show the linked project and account`,
|
|
8467
|
+
template: "Run `agentful whoami` using the bash tool. Then read .agentful/project.json and report the linked project title and id, plus the preview URL https://preview-<projectId>.agentful.page/. If the file does not exist, say that this directory is not linked yet and that `/setup` creates the link."
|
|
8468
|
+
}
|
|
8469
|
+
};
|
|
8470
|
+
function commandMarkdown(name) {
|
|
8471
|
+
const cmd = SLASH_COMMANDS[name];
|
|
8472
|
+
const description = JSON.stringify(cmd.description);
|
|
8473
|
+
return `---
|
|
8474
|
+
description: ${description}
|
|
8475
|
+
agent: ${cmd.agent ?? "agentful-build"}
|
|
8476
|
+
---
|
|
8477
|
+
|
|
8478
|
+
${cmd.template}
|
|
8479
|
+
`;
|
|
8480
|
+
}
|
|
8481
|
+
|
|
8482
|
+
// src/lib/tools.ts
|
|
8483
|
+
var import_node_fs13 = require("fs");
|
|
8484
|
+
var import_node_path15 = require("path");
|
|
8485
|
+
function assetsDir() {
|
|
8486
|
+
const here = (0, import_node_path15.dirname)(process.argv[1] || "");
|
|
8487
|
+
for (const candidate of [(0, import_node_path15.join)(here, "..", "assets"), (0, import_node_path15.join)(here, "assets")]) {
|
|
8488
|
+
if ((0, import_node_fs13.existsSync)((0, import_node_path15.join)(candidate, "tools", "imagegen.ts"))) return candidate;
|
|
8489
|
+
}
|
|
8490
|
+
return null;
|
|
8491
|
+
}
|
|
8492
|
+
function installEngineTools(configDir2) {
|
|
8493
|
+
const assets = assetsDir();
|
|
8494
|
+
if (!assets) return false;
|
|
8495
|
+
const target = (0, import_node_path15.join)(configDir2, "tools");
|
|
8496
|
+
(0, import_node_fs13.mkdirSync)(target, { recursive: true });
|
|
8497
|
+
try {
|
|
8498
|
+
(0, import_node_fs13.cpSync)((0, import_node_path15.join)(assets, "tools"), target, { recursive: true });
|
|
8499
|
+
return true;
|
|
8500
|
+
} catch {
|
|
8501
|
+
return false;
|
|
8502
|
+
}
|
|
8503
|
+
}
|
|
8504
|
+
|
|
8321
8505
|
// src/lib/engineConfig.ts
|
|
8322
8506
|
var PROVIDER_ID = "agentful";
|
|
8323
8507
|
var DISABLED_ENGINE_PLUGINS = {
|
|
@@ -8555,18 +8739,20 @@ var SCAFFOLD_BY_FRAMEWORK = {
|
|
|
8555
8739
|
// cra/nuxt get no scaffold skill: the react/vue skills are Vite-specific
|
|
8556
8740
|
// and would teach the wrong shape — the template contract still applies.
|
|
8557
8741
|
};
|
|
8558
|
-
function
|
|
8742
|
+
function dependencies(rootDir) {
|
|
8559
8743
|
try {
|
|
8560
8744
|
const pkg = JSON.parse((0, import_node_fs15.readFileSync)((0, import_node_path17.join)(rootDir, "package.json"), "utf8"));
|
|
8561
|
-
return
|
|
8745
|
+
return { ...pkg.dependencies, ...pkg.devDependencies };
|
|
8562
8746
|
} catch {
|
|
8563
|
-
return
|
|
8747
|
+
return {};
|
|
8564
8748
|
}
|
|
8565
8749
|
}
|
|
8566
8750
|
function selectSkills(framework, rootDir) {
|
|
8567
8751
|
const names = [CONTRACT_SKILL];
|
|
8568
8752
|
if (framework === "vite") {
|
|
8569
|
-
|
|
8753
|
+
const deps = dependencies(rootDir);
|
|
8754
|
+
if (deps.vue) names.push("vue-scaffold");
|
|
8755
|
+
else if (deps.react) names.push("react-scaffold");
|
|
8570
8756
|
} else {
|
|
8571
8757
|
const scaffold = SCAFFOLD_BY_FRAMEWORK[framework];
|
|
8572
8758
|
if (scaffold) names.push(scaffold);
|
|
@@ -9895,7 +10081,7 @@ program2.command("login").description("Sign in to your Agentful account (device
|
|
|
9895
10081
|
program2.command("logout").description("Remove the stored credentials").action(run(logoutCommand));
|
|
9896
10082
|
program2.command("whoami").description("Show the signed-in account").action(run(whoamiCommand));
|
|
9897
10083
|
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)));
|
|
9898
|
-
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").option("-y, --yes", "enable the declared managed database without asking (CI); a non-interactive push never enables it").option("--dry-run", "analyse only: what would be uploaded, how large, and what would block it \u2014 no sign-in, no project, no upload").option("--json", "with --dry-run: print the analysis as JSON (for scripts and agents)").action(run((opts) => pushCommand(opts)));
|
|
10084
|
+
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").option("-y, --yes", "enable the declared managed database without asking (CI); a non-interactive push never enables it").option("--dry-run", "analyse only: what would be uploaded, how large, and what would block it \u2014 no sign-in, no project, no upload").option("--json", "with --dry-run: print the analysis as JSON (for scripts and agents)").option("--summary", "with --dry-run --json: totals and findings without the list of every file").action(run((opts) => pushCommand(opts)));
|
|
9899
10085
|
program2.command("build-status").description("Show the cloud's record of the last build (the real error on failures)").action(run(buildStatusCommand));
|
|
9900
10086
|
program2.command("backend").description("Open this project's Backend tab (managed DB + server actions) in the browser").action(run(backendCommand));
|
|
9901
10087
|
program2.command("open").description("Open the live preview in the browser").action(run(openCommand));
|