agentful 0.1.2 → 0.1.4

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.
Files changed (2) hide show
  1. package/dist/index.cjs +114 -98
  2. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -3432,7 +3432,7 @@ var {
3432
3432
  } = import_index.default;
3433
3433
 
3434
3434
  // src/branding.ts
3435
- var VERSION = "0.1.2" ? "0.1.2" : null.version;
3435
+ var VERSION = "0.1.4" ? "0.1.4" : null.version;
3436
3436
  var brand = {
3437
3437
  name: "agentful",
3438
3438
  // the command users type
@@ -3770,12 +3770,13 @@ async function whoamiCommand() {
3770
3770
  }
3771
3771
 
3772
3772
  // src/commands/init.ts
3773
- var import_node_path3 = require("path");
3773
+ var import_node_path4 = require("path");
3774
3774
  var import_promises = require("readline/promises");
3775
3775
 
3776
3776
  // src/lib/project.ts
3777
3777
  var import_node_fs2 = require("fs");
3778
3778
  var import_node_path2 = require("path");
3779
+ var import_node_path3 = require("path");
3779
3780
  var projectConfigPath = (cwd) => (0, import_node_path2.join)(cwd, ".agentful", "project.json");
3780
3781
  function readProjectConfig(cwd = process.cwd()) {
3781
3782
  try {
@@ -3800,6 +3801,16 @@ function requireProject(cwd = process.cwd()) {
3800
3801
  }
3801
3802
  return config;
3802
3803
  }
3804
+ async function createProject(auth, title, cwd = process.cwd()) {
3805
+ const name = (title || "").trim() || (0, import_node_path3.basename)(cwd);
3806
+ const record = await request(`${PB_URL}/api/collections/projects/records`, {
3807
+ token: auth.pb_token,
3808
+ body: { title: name, description: "Created with the Agentful CLI", user_id: auth.user_id, status: "draft", environment: "Auto" }
3809
+ });
3810
+ const config = { projectId: record.id, userId: auth.user_id, title: name, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
3811
+ writeProjectConfig(config, cwd);
3812
+ return config;
3813
+ }
3803
3814
 
3804
3815
  // src/commands/init.ts
3805
3816
  async function initCommand(opts) {
@@ -3817,7 +3828,7 @@ async function initCommand(opts) {
3817
3828
  writeProjectConfig({
3818
3829
  projectId: opts.link,
3819
3830
  userId: auth.user_id,
3820
- title: opts.title || (0, import_node_path3.basename)(process.cwd()),
3831
+ title: opts.title || (0, import_node_path4.basename)(process.cwd()),
3821
3832
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
3822
3833
  });
3823
3834
  ui.ok(`Linked. \`agentful push\` now deploys to project ${opts.link}.`);
@@ -3826,33 +3837,18 @@ async function initCommand(opts) {
3826
3837
  let title = opts.title?.trim() || "";
3827
3838
  if (!title) {
3828
3839
  const rl = (0, import_promises.createInterface)({ input: process.stdin, output: process.stdout });
3829
- title = (await rl.question(`Project title [${(0, import_node_path3.basename)(process.cwd())}]: `)).trim() || (0, import_node_path3.basename)(process.cwd());
3840
+ title = (await rl.question(`Project title [${(0, import_node_path4.basename)(process.cwd())}]: `)).trim() || (0, import_node_path4.basename)(process.cwd());
3830
3841
  rl.close();
3831
3842
  }
3832
3843
  ui.step(`Creating project "${title}"\u2026`);
3833
- const record = await request(`${PB_URL}/api/collections/projects/records`, {
3834
- token: auth.pb_token,
3835
- body: {
3836
- title,
3837
- description: "Created with the Agentful CLI",
3838
- user_id: auth.user_id,
3839
- status: "draft",
3840
- environment: "Auto"
3841
- }
3842
- });
3843
- writeProjectConfig({
3844
- projectId: record.id,
3845
- userId: auth.user_id,
3846
- title,
3847
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
3848
- });
3849
- ui.ok(`Project created (${record.id}). Next: \`agentful push\``);
3844
+ const config = await createProject(auth, title);
3845
+ ui.ok(`Project created (${config.projectId}). Next: \`agentful push\``);
3850
3846
  ui.info("Tip: commit .agentful/project.json to keep the mapping with the repo.");
3851
3847
  }
3852
3848
 
3853
3849
  // src/lib/zip.ts
3854
3850
  var import_node_fs3 = require("fs");
3855
- var import_node_path4 = require("path");
3851
+ var import_node_path5 = require("path");
3856
3852
 
3857
3853
  // node_modules/fflate/esm/index.mjs
3858
3854
  var import_module = require("module");
@@ -4595,7 +4591,7 @@ var isEnvFile = (name) => name === ".env" || name.startsWith(".env.");
4595
4591
  function collectFiles(rootDir, mode) {
4596
4592
  const ig = (0, import_ignore.default)();
4597
4593
  if (mode === "source") {
4598
- const gitignorePath = (0, import_node_path4.join)(rootDir, ".gitignore");
4594
+ const gitignorePath = (0, import_node_path5.join)(rootDir, ".gitignore");
4599
4595
  if ((0, import_node_fs3.existsSync)(gitignorePath)) {
4600
4596
  ig.add((0, import_node_fs3.readFileSync)(gitignorePath, "utf8"));
4601
4597
  }
@@ -4603,8 +4599,8 @@ function collectFiles(rootDir, mode) {
4603
4599
  const results = [];
4604
4600
  const walk = (dir) => {
4605
4601
  for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
4606
- const abs = (0, import_node_path4.join)(dir, entry.name);
4607
- const rel = (0, import_node_path4.relative)(rootDir, abs).split(import_node_path4.sep).join("/");
4602
+ const abs = (0, import_node_path5.join)(dir, entry.name);
4603
+ const rel = (0, import_node_path5.relative)(rootDir, abs).split(import_node_path5.sep).join("/");
4608
4604
  const lower = entry.name.toLowerCase();
4609
4605
  if (entry.isSymbolicLink()) continue;
4610
4606
  if (entry.isDirectory()) {
@@ -4648,15 +4644,15 @@ function zipToBase64(files) {
4648
4644
  }
4649
4645
  function detectDistDir(rootDir, override) {
4650
4646
  if (override) {
4651
- const dir = (0, import_node_path4.join)(rootDir, override);
4647
+ const dir = (0, import_node_path5.join)(rootDir, override);
4652
4648
  if (!(0, import_node_fs3.existsSync)(dir) || !(0, import_node_fs3.statSync)(dir).isDirectory()) {
4653
4649
  throw new ApiError(0, "dist_not_found", `--dir ${override} does not exist or is not a directory.`);
4654
4650
  }
4655
4651
  return dir;
4656
4652
  }
4657
- for (const candidate of ["dist", "build", "out", (0, import_node_path4.join)(".output", "public")]) {
4658
- const dir = (0, import_node_path4.join)(rootDir, candidate);
4659
- if ((0, import_node_fs3.existsSync)((0, import_node_path4.join)(dir, "index.html"))) return dir;
4653
+ for (const candidate of ["dist", "build", "out", (0, import_node_path5.join)(".output", "public")]) {
4654
+ const dir = (0, import_node_path5.join)(rootDir, candidate);
4655
+ if ((0, import_node_fs3.existsSync)((0, import_node_path5.join)(dir, "index.html"))) return dir;
4660
4656
  }
4661
4657
  throw new ApiError(
4662
4658
  0,
@@ -4682,7 +4678,12 @@ function brandPreviewUrl(previewUrl, projectId) {
4682
4678
  async function pushCommand(opts) {
4683
4679
  console.log(banner());
4684
4680
  const auth = await ensureAuth();
4685
- const project = requireProject();
4681
+ let project = readProjectConfig();
4682
+ if (!project) {
4683
+ ui.step("No project linked here yet \u2014 creating one\u2026");
4684
+ project = await createProject(auth);
4685
+ ui.ok(`Project "${project.title}" created (${project.projectId}).`);
4686
+ }
4686
4687
  const { userId, projectId } = { userId: project.userId, projectId: project.projectId };
4687
4688
  if (userId !== auth.user_id) {
4688
4689
  throw new ApiError(
@@ -4759,23 +4760,26 @@ async function pollBuild(token, userId, projectId) {
4759
4760
  // src/commands/open.ts
4760
4761
  async function openCommand() {
4761
4762
  const project = requireProject();
4762
- const url = `https://preview-${project.projectId}.${PREVIEW_DOMAIN}/`;
4763
- ui.step(`Opening ${ui.url(url)}`);
4763
+ const auth = await ensureAuth();
4764
+ const url = `https://preview-${project.projectId}.${PREVIEW_DOMAIN}/?token=${encodeURIComponent(auth.pb_token)}`;
4765
+ const shown = `https://preview-${project.projectId}.${PREVIEW_DOMAIN}/`;
4766
+ ui.step(`Opening ${ui.url(shown)}`);
4764
4767
  if (!openInBrowser(url)) {
4765
- ui.info("Could not launch a browser \u2014 open the URL above manually.");
4768
+ ui.info(`Could not launch a browser \u2014 open this URL manually:`);
4769
+ ui.info(ui.url(url));
4766
4770
  }
4767
4771
  }
4768
4772
 
4769
4773
  // src/commands/tui.ts
4770
4774
  var import_node_child_process5 = require("child_process");
4771
- var import_node_path12 = require("path");
4775
+ var import_node_path13 = require("path");
4772
4776
 
4773
4777
  // src/lib/binWrapper.ts
4774
4778
  var import_node_fs4 = require("fs");
4775
- var import_node_path5 = require("path");
4779
+ var import_node_path6 = require("path");
4776
4780
  var import_node_os3 = require("os");
4777
4781
  function ensureCliOnPath() {
4778
- const binDir = (0, import_node_path5.join)((0, import_node_os3.homedir)(), ".local", "share", "agentful", "bin");
4782
+ const binDir = (0, import_node_path6.join)((0, import_node_os3.homedir)(), ".local", "share", "agentful", "bin");
4779
4783
  (0, import_node_fs4.mkdirSync)(binDir, { recursive: true });
4780
4784
  const entry = process.argv[1];
4781
4785
  if (!entry) return binDir;
@@ -4785,7 +4789,7 @@ function ensureCliOnPath() {
4785
4789
  ` : `export ${name}=${JSON.stringify(original)}
4786
4790
  `;
4787
4791
  };
4788
- const wrapper = (0, import_node_path5.join)(binDir, "agentful");
4792
+ const wrapper = (0, import_node_path6.join)(binDir, "agentful");
4789
4793
  (0, import_node_fs4.writeFileSync)(
4790
4794
  wrapper,
4791
4795
  `#!/bin/sh
@@ -4805,7 +4809,7 @@ function ensureCliOnPath() {
4805
4809
  // src/lib/engine.ts
4806
4810
  var import_node_fs5 = require("fs");
4807
4811
  var import_node_crypto = require("crypto");
4808
- var import_node_path6 = require("path");
4812
+ var import_node_path7 = require("path");
4809
4813
  var import_node_os4 = require("os");
4810
4814
  var import_node_child_process3 = require("child_process");
4811
4815
  var import_node_stream = require("stream");
@@ -4845,8 +4849,8 @@ function platformKey() {
4845
4849
  );
4846
4850
  }
4847
4851
  function cacheDir(version) {
4848
- const base = process.env.XDG_CACHE_HOME || (0, import_node_path6.join)((0, import_node_os4.homedir)(), ".cache");
4849
- return (0, import_node_path6.join)(base, "agentful", "engine", version);
4852
+ const base = process.env.XDG_CACHE_HOME || (0, import_node_path7.join)((0, import_node_os4.homedir)(), ".cache");
4853
+ return (0, import_node_path7.join)(base, "agentful", "engine", version);
4850
4854
  }
4851
4855
  async function fetchManifest() {
4852
4856
  try {
@@ -4866,12 +4870,12 @@ async function ensureEngine() {
4866
4870
  noticeIfOutdated(manifest);
4867
4871
  const version = manifest?.engine_version || FALLBACK_ENGINE_VERSION;
4868
4872
  const dir = cacheDir(version);
4869
- const binPath = (0, import_node_path6.join)(dir, ENGINE_BINARY);
4873
+ const binPath = (0, import_node_path7.join)(dir, ENGINE_BINARY);
4870
4874
  if ((0, import_node_fs5.existsSync)(binPath)) return binPath;
4871
4875
  const artifact = manifest?.artifacts?.[key];
4872
4876
  const url = artifact?.url || `${APP_URL}/cli/engine/${version}/${key}${key.startsWith("darwin") ? ".zip" : ".tar.gz"}`;
4873
4877
  (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
4874
- const archivePath = (0, import_node_path6.join)(dir, key.startsWith("darwin") ? "engine.zip" : "engine.tar.gz");
4878
+ const archivePath = (0, import_node_path7.join)(dir, key.startsWith("darwin") ? "engine.zip" : "engine.tar.gz");
4875
4879
  ui.step(`Preparing the ${brand.displayName} engine (first run only)\u2026`);
4876
4880
  const resp = await fetch(url, {
4877
4881
  redirect: "follow",
@@ -4906,7 +4910,7 @@ async function ensureEngine() {
4906
4910
  `Could not unpack the engine (needs ${archivePath.endsWith(".zip") ? "unzip" : "tar"} on PATH).`
4907
4911
  );
4908
4912
  }
4909
- const extracted = (0, import_node_path6.join)(dir, "opencode");
4913
+ const extracted = (0, import_node_path7.join)(dir, "opencode");
4910
4914
  if ((0, import_node_fs5.existsSync)(extracted) && !(0, import_node_fs5.existsSync)(binPath)) (0, import_node_fs5.renameSync)(extracted, binPath);
4911
4915
  if (!(0, import_node_fs5.existsSync)(binPath)) {
4912
4916
  throw new ApiError(0, "engine_extract_failed", "Engine archive did not contain the expected binary.");
@@ -4919,8 +4923,8 @@ async function ensureEngine() {
4919
4923
 
4920
4924
  // src/lib/gatewayToken.ts
4921
4925
  var import_node_fs6 = require("fs");
4922
- var import_node_path7 = require("path");
4923
- var cachePath = () => (0, import_node_path7.join)(configDir(), "gateway.json");
4926
+ var import_node_path8 = require("path");
4927
+ var cachePath = () => (0, import_node_path8.join)(configDir(), "gateway.json");
4924
4928
  async function ensureGatewaySession(auth, projectId) {
4925
4929
  try {
4926
4930
  const cached = JSON.parse((0, import_node_fs6.readFileSync)(cachePath(), "utf8"));
@@ -4945,7 +4949,7 @@ async function ensureGatewaySession(auth, projectId) {
4945
4949
 
4946
4950
  // src/lib/engineConfig.ts
4947
4951
  var import_node_fs8 = require("fs");
4948
- var import_node_path9 = require("path");
4952
+ var import_node_path10 = require("path");
4949
4953
  var import_node_os5 = require("os");
4950
4954
 
4951
4955
  // src/branding/agentful-theme.json
@@ -5092,27 +5096,27 @@ export default plugin
5092
5096
  }
5093
5097
 
5094
5098
  // src/branding/commands.ts
5095
- var IF_NOT_LINKED = 'If the command reports "No Agentful project here", this directory is not linked yet: ask me for a project title, run `agentful init --title "<title>"`, then run the original command again and report its result.';
5099
+ 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.';
5096
5100
  var SLASH_COMMANDS = {
5097
5101
  setup: {
5098
5102
  description: `${brand.displayName}: create or link the cloud project for this directory`,
5099
- template: 'Check whether .agentful/project.json exists. If it does, report the linked project title and id and stop. Otherwise ask me for a project title, then run `agentful init --title "<title>"` using the bash tool and report what it created. Do not modify any other project files.'
5103
+ 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.'
5100
5104
  },
5101
5105
  push: {
5102
5106
  description: `${brand.displayName}: deploy this project and get a preview URL`,
5103
- template: "Run `agentful push` from the project root using the bash tool. Stream what it prints, and when it finishes report the preview URL on its own line. " + IF_NOT_LINKED + " If it fails for another reason, show the error and suggest the fix \u2014 do not modify project files unless I ask."
5107
+ 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, show the error and suggest the fix \u2014 do not modify project files unless I ask."
5104
5108
  },
5105
5109
  preview: {
5106
5110
  description: `${brand.displayName}: open the live preview in the browser`,
5107
- 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 \u2014 if I have not pushed yet, say so and offer to run `agentful push` first. " + IF_NOT_LINKED
5111
+ 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
5108
5112
  },
5109
5113
  publish: {
5110
5114
  description: `${brand.displayName}: publish on a public subdomain`,
5111
- 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. " + IF_NOT_LINKED
5115
+ 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
5112
5116
  },
5113
5117
  share: {
5114
5118
  description: `${brand.displayName}: make the live preview public (or private again)`,
5115
- 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. " + IF_NOT_LINKED
5119
+ 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
5116
5120
  },
5117
5121
  status: {
5118
5122
  description: `${brand.displayName}: show the linked project and account`,
@@ -5133,21 +5137,21 @@ ${cmd.template}
5133
5137
 
5134
5138
  // src/lib/tools.ts
5135
5139
  var import_node_fs7 = require("fs");
5136
- var import_node_path8 = require("path");
5140
+ var import_node_path9 = require("path");
5137
5141
  function assetsDir() {
5138
- const here = (0, import_node_path8.dirname)(process.argv[1] || "");
5139
- for (const candidate of [(0, import_node_path8.join)(here, "..", "assets"), (0, import_node_path8.join)(here, "assets")]) {
5140
- if ((0, import_node_fs7.existsSync)((0, import_node_path8.join)(candidate, "tools", "imagegen.ts"))) return candidate;
5142
+ const here = (0, import_node_path9.dirname)(process.argv[1] || "");
5143
+ for (const candidate of [(0, import_node_path9.join)(here, "..", "assets"), (0, import_node_path9.join)(here, "assets")]) {
5144
+ if ((0, import_node_fs7.existsSync)((0, import_node_path9.join)(candidate, "tools", "imagegen.ts"))) return candidate;
5141
5145
  }
5142
5146
  return null;
5143
5147
  }
5144
5148
  function installEngineTools(configDir2) {
5145
5149
  const assets = assetsDir();
5146
5150
  if (!assets) return false;
5147
- const target = (0, import_node_path8.join)(configDir2, "tools");
5151
+ const target = (0, import_node_path9.join)(configDir2, "tools");
5148
5152
  (0, import_node_fs7.mkdirSync)(target, { recursive: true });
5149
5153
  try {
5150
- (0, import_node_fs7.cpSync)((0, import_node_path8.join)(assets, "tools"), target, { recursive: true });
5154
+ (0, import_node_fs7.cpSync)((0, import_node_path9.join)(assets, "tools"), target, { recursive: true });
5151
5155
  return true;
5152
5156
  } catch {
5153
5157
  return false;
@@ -5157,11 +5161,11 @@ function installEngineTools(configDir2) {
5157
5161
  // src/lib/engineConfig.ts
5158
5162
  var PROVIDER_ID = "agentful";
5159
5163
  function engineXdg() {
5160
- const root = (0, import_node_path9.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful");
5164
+ const root = (0, import_node_path10.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful");
5161
5165
  return {
5162
- configHome: (0, import_node_path9.join)(root, "engine-config"),
5163
- dataHome: (0, import_node_path9.join)(root, "engine-data"),
5164
- stateHome: (0, import_node_path9.join)(root, "engine-state")
5166
+ configHome: (0, import_node_path10.join)(root, "engine-config"),
5167
+ dataHome: (0, import_node_path10.join)(root, "engine-data"),
5168
+ stateHome: (0, import_node_path10.join)(root, "engine-state")
5165
5169
  };
5166
5170
  }
5167
5171
  async function resolveTheme() {
@@ -5180,12 +5184,12 @@ async function resolveTheme() {
5180
5184
  }
5181
5185
  async function writeEngineSession(session, catalog, localProviders = {}) {
5182
5186
  const xdg = engineXdg();
5183
- const configDir2 = (0, import_node_path9.join)(xdg.configHome, "opencode");
5184
- const dataDir = (0, import_node_path9.join)(xdg.dataHome, "opencode");
5185
- const themesDir = (0, import_node_path9.join)(configDir2, "themes");
5186
- const pluginsDir = (0, import_node_path9.join)(configDir2, "plugins");
5187
- const commandsDir = (0, import_node_path9.join)(configDir2, "commands");
5188
- for (const dir of [themesDir, pluginsDir, commandsDir, dataDir, (0, import_node_path9.join)(xdg.stateHome, "opencode")]) {
5187
+ const configDir2 = (0, import_node_path10.join)(xdg.configHome, "opencode");
5188
+ const dataDir = (0, import_node_path10.join)(xdg.dataHome, "opencode");
5189
+ const themesDir = (0, import_node_path10.join)(configDir2, "themes");
5190
+ const pluginsDir = (0, import_node_path10.join)(configDir2, "plugins");
5191
+ const commandsDir = (0, import_node_path10.join)(configDir2, "commands");
5192
+ for (const dir of [themesDir, pluginsDir, commandsDir, dataDir, (0, import_node_path10.join)(xdg.stateHome, "opencode")]) {
5189
5193
  (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
5190
5194
  }
5191
5195
  const models = {};
@@ -5210,23 +5214,23 @@ async function writeEngineSession(session, catalog, localProviders = {}) {
5210
5214
  }
5211
5215
  }
5212
5216
  };
5213
- (0, import_node_fs8.writeFileSync)((0, import_node_path9.join)(configDir2, "config.json"), JSON.stringify(config, null, 2));
5214
- (0, import_node_fs8.writeFileSync)((0, import_node_path9.join)(dataDir, "auth.json"), JSON.stringify({
5217
+ (0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(configDir2, "config.json"), JSON.stringify(config, null, 2));
5218
+ (0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(dataDir, "auth.json"), JSON.stringify({
5215
5219
  [PROVIDER_ID]: { apiKey: session.token }
5216
5220
  }, null, 2));
5217
- const pluginPath = (0, import_node_path9.join)(pluginsDir, "agentful-branding.tsx");
5221
+ const pluginPath = (0, import_node_path10.join)(pluginsDir, "agentful-branding.tsx");
5218
5222
  (0, import_node_fs8.writeFileSync)(pluginPath, brandingPluginSource());
5219
- (0, import_node_fs8.writeFileSync)((0, import_node_path9.join)(configDir2, "tui.json"), JSON.stringify({
5223
+ (0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(configDir2, "tui.json"), JSON.stringify({
5220
5224
  theme: "agentful",
5221
5225
  plugin: [`file://${pluginPath}`]
5222
5226
  }, null, 2));
5223
- (0, import_node_fs8.writeFileSync)((0, import_node_path9.join)(themesDir, "agentful.json"), JSON.stringify(await resolveTheme(), null, 2));
5227
+ (0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(themesDir, "agentful.json"), JSON.stringify(await resolveTheme(), null, 2));
5224
5228
  for (const name of Object.keys(SLASH_COMMANDS)) {
5225
- (0, import_node_fs8.writeFileSync)((0, import_node_path9.join)(commandsDir, `${name}.md`), commandMarkdown(name));
5229
+ (0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(commandsDir, `${name}.md`), commandMarkdown(name));
5226
5230
  }
5227
5231
  for (const legacy of ["xdg-config", "xdg-data", "xdg-state"]) {
5228
5232
  try {
5229
- (0, import_node_fs8.rmSync)((0, import_node_path9.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful", legacy), { recursive: true, force: true });
5233
+ (0, import_node_fs8.rmSync)((0, import_node_path10.join)((0, import_node_os5.homedir)(), ".local", "share", "agentful", legacy), { recursive: true, force: true });
5230
5234
  } catch {
5231
5235
  }
5232
5236
  }
@@ -5235,6 +5239,8 @@ async function writeEngineSession(session, catalog, localProviders = {}) {
5235
5239
 
5236
5240
  // src/lib/models.ts
5237
5241
  async function fetchModelCatalog(auth, fallback) {
5242
+ const regionDefaultsToBedrock = fallback.ai_region === "eu" || fallback.ai_region === "de";
5243
+ const isAgenticCapable = (id) => id !== "auto" && !id.includes("bedrock");
5238
5244
  let catalog = null;
5239
5245
  try {
5240
5246
  catalog = await request(`${PB_URL}/api/llm/available-models`, {
@@ -5292,7 +5298,11 @@ async function fetchModelCatalog(auth, fallback) {
5292
5298
  }
5293
5299
  }
5294
5300
  const ids = new Set(entries.map((e) => e.id));
5295
- const defaultModel = catalog.default_model && ids.has(catalog.default_model) ? catalog.default_model : ids.has("auto") ? "auto" : entries[0]?.id || fallback.default_model;
5301
+ let defaultModel = catalog.default_model && ids.has(catalog.default_model) ? catalog.default_model : ids.has("auto") ? "auto" : entries[0]?.id || fallback.default_model;
5302
+ if (regionDefaultsToBedrock && !isAgenticCapable(defaultModel)) {
5303
+ const working = entries.find((e) => isAgenticCapable(e.id));
5304
+ if (working) defaultModel = working.id;
5305
+ }
5296
5306
  return {
5297
5307
  models: entries,
5298
5308
  defaultModel,
@@ -5339,10 +5349,10 @@ function decideLocalProviders(policy) {
5339
5349
 
5340
5350
  // src/lib/localProviders.ts
5341
5351
  var import_node_fs9 = require("fs");
5342
- var import_node_path10 = require("path");
5352
+ var import_node_path11 = require("path");
5343
5353
  var LOCAL_PROVIDERS_FILE = "local-providers.json";
5344
5354
  function localProvidersPath() {
5345
- return (0, import_node_path10.join)(configDir(), LOCAL_PROVIDERS_FILE);
5355
+ return (0, import_node_path11.join)(configDir(), LOCAL_PROVIDERS_FILE);
5346
5356
  }
5347
5357
  function readLocalProviders() {
5348
5358
  try {
@@ -5402,27 +5412,33 @@ function writeLocalProvidersExample() {
5402
5412
 
5403
5413
  // src/lib/sessions.ts
5404
5414
  var import_node_fs10 = require("fs");
5405
- var import_node_path11 = require("path");
5415
+ var import_node_path12 = require("path");
5406
5416
  var import_node_child_process4 = require("child_process");
5407
- var SEP = "";
5408
- function sqlite(dbPath, sql) {
5409
- const res = (0, import_node_child_process4.spawnSync)("sqlite3", ["-readonly", dbPath, sql], { encoding: "utf8" });
5410
- if (res.status !== 0 || !res.stdout) return null;
5411
- return res.stdout.trim().split("\n").filter(Boolean);
5412
- }
5413
5417
  function lastSessionForDirectory(cwd = process.cwd()) {
5414
- const dbPath = (0, import_node_path11.join)(engineXdg().dataHome, "opencode", "opencode.db");
5418
+ const dbPath = (0, import_node_path12.join)(engineXdg().dataHome, "opencode", "opencode.db");
5415
5419
  if (!(0, import_node_fs10.existsSync)(dbPath)) return null;
5416
5420
  const escaped = cwd.replace(/'/g, "''");
5417
- const rows = sqlite(
5418
- dbPath,
5419
- `SELECT id || char(31) || COALESCE(title, slug, '') FROM session
5421
+ const res = (0, import_node_child_process4.spawnSync)(
5422
+ "sqlite3",
5423
+ [
5424
+ "-readonly",
5425
+ "-json",
5426
+ dbPath,
5427
+ `SELECT id, COALESCE(title, slug, '') AS title FROM session
5420
5428
  WHERE directory = '${escaped}' AND time_archived IS NULL
5421
5429
  ORDER BY COALESCE(time_updated, time_created) DESC LIMIT 1;`
5430
+ ],
5431
+ { encoding: "utf8" }
5422
5432
  );
5423
- if (!rows?.length) return null;
5424
- const [id, title] = rows[0].split(SEP);
5425
- return id ? { id, title: title || "" } : null;
5433
+ if (res.status !== 0 || !res.stdout.trim()) return null;
5434
+ try {
5435
+ const rows = JSON.parse(res.stdout);
5436
+ const row = rows[0];
5437
+ if (!row?.id) return null;
5438
+ return { id: row.id, title: row.title || "" };
5439
+ } catch {
5440
+ return null;
5441
+ }
5426
5442
  }
5427
5443
 
5428
5444
  // src/commands/tui.ts
@@ -5477,7 +5493,7 @@ async function tuiCommand(opts = {}) {
5477
5493
  ...process.env,
5478
5494
  // Slash commands run `agentful …` through the agent's bash tool, which
5479
5495
  // has no access to the user's shell aliases.
5480
- PATH: `${binDir}${import_node_path12.delimiter}${process.env.PATH || ""}`,
5496
+ PATH: `${binDir}${import_node_path13.delimiter}${process.env.PATH || ""}`,
5481
5497
  XDG_CONFIG_HOME: xdg.configHome,
5482
5498
  XDG_DATA_HOME: xdg.dataHome,
5483
5499
  XDG_STATE_HOME: xdg.stateHome,
@@ -5581,13 +5597,13 @@ async function shareCommand(opts) {
5581
5597
 
5582
5598
  // src/commands/pull.ts
5583
5599
  var import_node_fs11 = require("fs");
5584
- var import_node_path13 = require("path");
5600
+ var import_node_path14 = require("path");
5585
5601
  function isProbablyBase64Binary(path) {
5586
5602
  return /\.(png|jpe?g|gif|webp|ico|woff2?|ttf|otf|eot|pdf|zip|mp[34]|webm|avif)$/i.test(path);
5587
5603
  }
5588
5604
  function writeEntry(root, rel, value) {
5589
- const target = (0, import_node_path13.join)(root, rel);
5590
- (0, import_node_fs11.mkdirSync)((0, import_node_path13.dirname)(target), { recursive: true });
5605
+ const target = (0, import_node_path14.join)(root, rel);
5606
+ (0, import_node_fs11.mkdirSync)((0, import_node_path14.dirname)(target), { recursive: true });
5591
5607
  const content = typeof value === "object" && value !== null && "content" in value ? String(value.content) : String(value ?? "");
5592
5608
  if (isProbablyBase64Binary(rel)) {
5593
5609
  (0, import_node_fs11.writeFileSync)(target, Buffer.from(content, "base64"));
@@ -5623,8 +5639,8 @@ async function pullCommand(opts) {
5623
5639
  ui.warn(`Skipped ${rel} (HTTP ${resp.status})`);
5624
5640
  continue;
5625
5641
  }
5626
- const target = (0, import_node_path13.join)(process.cwd(), rel);
5627
- (0, import_node_fs11.mkdirSync)((0, import_node_path13.dirname)(target), { recursive: true });
5642
+ const target = (0, import_node_path14.join)(process.cwd(), rel);
5643
+ (0, import_node_fs11.mkdirSync)((0, import_node_path14.dirname)(target), { recursive: true });
5628
5644
  (0, import_node_fs11.writeFileSync)(target, Buffer.from(await resp.arrayBuffer()));
5629
5645
  written++;
5630
5646
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentful",
3
- "version": "0.1.2",
4
- "description": "Agentful in your terminal \u2014 local development with push-to-cloud previews",
3
+ "version": "0.1.4",
4
+ "description": "Agentful in your terminal local development with push-to-cloud previews",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://agentful.dev",
7
7
  "bin": {