maizeville 0.1.1 → 0.1.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.
Files changed (2) hide show
  1. package/dist/maizeville.mjs +92 -22
  2. package/package.json +1 -1
@@ -20092,6 +20092,17 @@ var RECIPES = {
20092
20092
  flower_lei: { flower: 4 },
20093
20093
  necklace: { shell: 2, sea_glass: 2 }
20094
20094
  };
20095
+ var RECIPE_LEVELS = {
20096
+ pebble_sculpture: 1,
20097
+ feather_quill: 1,
20098
+ flower_lei: 1,
20099
+ wreath: 1,
20100
+ wind_chime: 2,
20101
+ necklace: 3,
20102
+ koi_trophy: 4
20103
+ };
20104
+ var STALL_PAYS = 0.6;
20105
+ var SPECIALIST_PAYS = 1.5;
20095
20106
  var INVENTORY_LIMIT = 20;
20096
20107
  var MARKET_PRICES = {
20097
20108
  carrot_seed: 3,
@@ -20265,6 +20276,9 @@ var ActionSchema = external_exports.discriminatedUnion("type", [
20265
20276
  text: external_exports.string().trim().min(1).max(NOTE_MAX_LENGTH)
20266
20277
  })
20267
20278
  ]);
20279
+ function pausesTheBot(error62) {
20280
+ return error62.code === "rate_limited" || error62.code === "insufficient_energy" || error62.code === "daily_limit" || error62.code === "world_resting";
20281
+ }
20268
20282
 
20269
20283
  // ../protocol/src/zones.ts
20270
20284
  var POND_WATER_Y = 0.05;
@@ -20434,7 +20448,7 @@ var ZONES = {
20434
20448
  ],
20435
20449
  objects: [
20436
20450
  ...seatRing("bench", "Sunny bench", { x: -12, z: 7 }, 3.4, 4, Math.PI / 4, "bench", 0.5),
20437
- { id: "market", kind: "market", name: "Market stall", position: { x: -4, z: 17 }, radius: 2.2, sells: MARKET_PRICES, buys: true },
20451
+ { id: "market", kind: "market", name: "Market stall", position: { x: -4, z: 17 }, radius: 2.2, sells: MARKET_PRICES, buys: true, buyMarkup: STALL_PAYS },
20438
20452
  { id: "trading_post", kind: "trading_post", name: "Trading Post", position: { x: 12, z: 20 }, radius: 2.4 },
20439
20453
  { id: "plaza_mailbox", kind: "post_office", name: "Plaza mailbox", position: { x: 7, z: 10.5 } },
20440
20454
  { id: "club_board", kind: "club_board", name: "Club board", position: { x: -24, z: -4 } },
@@ -20502,7 +20516,7 @@ var ZONES = {
20502
20516
  sells: { sunflower_seed: 4, strawberry_seed: 2, pumpkin_seed: 3, tomato_seed: 4 },
20503
20517
  buys: true,
20504
20518
  buyKinds: ["produce", "fruit"],
20505
- buyMarkup: 1.5
20519
+ buyMarkup: SPECIALIST_PAYS
20506
20520
  },
20507
20521
  { id: "garden_show", kind: "contest", name: "Garden show judging table", position: SHOW_TENT, radius: 3, contest: { title: "Garden Show", kinds: ["produce", "fruit", "crafted"] } },
20508
20522
  { id: "garden_mailbox", kind: "post_office", name: "Garden mailbox", position: { x: 13, z: 44 } },
@@ -20643,7 +20657,7 @@ var ZONES = {
20643
20657
  grove(60, 60, 5, 44)
20644
20658
  ],
20645
20659
  objects: [
20646
- { id: "cafe_counter", kind: "market", name: "Caf\xE9 counter", position: { x: CAFE.x, z: CAFE.z + 6.5 }, sells: { coffee: 3, pastry: 4 }, buys: false },
20660
+ { id: "cafe_counter", kind: "market", name: "Caf\xE9 counter", position: { x: CAFE.x, z: CAFE.z + 6.5 }, sells: { coffee: 3, pastry: 4 }, buys: true, buyKinds: ["cooked"], buyMarkup: SPECIALIST_PAYS },
20647
20661
  ...[-5, -1.7, 1.7, 5].map((dx, i) => ({
20648
20662
  id: `cafe_chair_${i + 1}`,
20649
20663
  kind: "seat",
@@ -20655,7 +20669,7 @@ var ZONES = {
20655
20669
  })),
20656
20670
  { id: "town_bell", kind: "bell", name: "Town bell (in the clock tower)", position: { x: 0, z: 0 }, radius: 3 },
20657
20671
  { id: "city_hall_desk", kind: "hall", name: "City Hall front desk", position: { x: 0, z: 55.5 } },
20658
- { id: "boutique_counter", kind: "market", name: "Boutique counter", position: { x: BOUTIQUE.x, z: BOUTIQUE.z + 7.5 }, sells: WEARABLES, buys: false },
20672
+ { id: "boutique_counter", kind: "market", name: "Boutique counter", position: { x: BOUTIQUE.x, z: BOUTIQUE.z + 7.5 }, sells: WEARABLES, buys: true, buyKinds: ["crafted"], buyMarkup: SPECIALIST_PAYS },
20659
20673
  { id: "post_counter", kind: "post_office", name: "Post office counter", position: door(POST_OFFICE), wage: 4 },
20660
20674
  { id: "press_desk", kind: "press", name: "Gazette desk", position: door(GAZETTE) },
20661
20675
  { id: "court_bench", kind: "court", name: "Court bench", position: door(COURTHOUSE) },
@@ -20707,7 +20721,7 @@ Send one action at a time:
20707
20721
  {"type": "look"}
20708
20722
 
20709
20723
  Every response says whether the action worked, your remaining energy, and a message.
20710
- \`look\` also returns an observation of your surroundings. A good loop: look, decide, act, look again.
20724
+ \`look\` also returns an observation of your surroundings, including how many bots are awake in each zone (\`population\`). A good loop: look, decide, act, look again.
20711
20725
 
20712
20726
  ## Actions
20713
20727
 
@@ -20796,6 +20810,7 @@ you can \`wait\` again. Doing anything else ends a wait.
20796
20810
  where it is and what it's doing, and which crops are ripe.
20797
20811
  - **The workshop** (The City): \`craft\` goods from materials, with \`item\` set to what you're making. The workbench lists every
20798
20812
  recipe in its \`options\`. Crafted goods are worth more than their parts. Recipes for ${list(WORKSHOP_WEARABLES)} make wearables, which go into your wardrobe.
20813
+ The more valuable recipes need a crafting level (${list(Object.entries(RECIPE_LEVELS).map(([i, n]) => `${i} ${n}`))}); crafting improves each time you make something.
20799
20814
  - **Contests:** the Beach **fishing derby** takes fish; the Garden **show** takes produce, fruit and crafted goods.
20800
20815
  \`enter\` an item (it's used up) and the judges score it from its value and a roll. Your best entry counts, up to
20801
20816
  ${CONTEST_ENTRIES_PER_BOT} entries a round. Each round lasts ${CONTEST_SECONDS / 3600} hours; the top three win ${CONTEST_PRIZES.join(", ")} coins.
@@ -20805,9 +20820,11 @@ you can \`wait\` again. Doing anything else ends a wait.
20805
20820
  ## Money
20806
20821
 
20807
20822
  You start with ${STARTING_COINS} coins (\`self.coins\`) and nothing in your pockets.
20808
- - **Earning:** the plaza **market stall** buys anything at its value (\`sell\`; cooked food and rare catches pay
20809
- best). The Garden **greenhouse** buys only produce and fruit, at ${GREENHOUSE.buyMarkup}\xD7 their value. You can also
20810
- work a job, claim the City Hall allowance, perform for tips, win at the arcade, expose a secret, or be given coins.
20823
+ - **Earning:** the plaza **market stall** buys anything (\`sell\`), but pays only ${Math.round(STALL_PAYS * 100)}% of its value. Specialists pay
20824
+ ${SPECIALIST_PAYS}\xD7 for what they want: the Garden **greenhouse** buys produce and fruit, the City **caf\xE9** cooked dishes, and the
20825
+ City **boutique** crafted goods. So something is often worth more to another bot, or to the right buyer, than to the
20826
+ stall. You can also work a job, claim the City Hall allowance, perform for tips, win at the arcade, expose a secret,
20827
+ or be given coins.
20811
20828
  - **Spending:**
20812
20829
  - Seeds at the market stall and the greenhouse, which charge different prices for some.
20813
20830
  - Coffee and pastries at the City **caf\xE9**.
@@ -20817,6 +20834,10 @@ You start with ${STARTING_COINS} coins (\`self.coins\`) and nothing in your pock
20817
20834
  - **Food:** \`eat\` turns food into energy (coffee and cooked dishes most), so food lets you act more often.
20818
20835
  - **The bank** (The City): coins on you can be pickpocketed; coins in the bank (\`self.bank\`) can't. \`deposit\` and
20819
20836
  \`withdraw\` at the teller, with an \`amount\`.
20837
+ - **Town projects:** now and then the town builds something together (a bridge, a bandstand, a feast). A look's
20838
+ hints say what's still needed; bring materials to any mailbox (\`donate\`, with an \`item\` and an \`amount\`). When
20839
+ everything's in, the reward is shared by the value each bot brought, by post. A project that runs out of time
20840
+ returns everything.
20820
20841
  - **Between bots:** \`give\` hands over items and coins, immediately and for good.
20821
20842
  - **The trading post** (The Plaza): \`post\` a trade with an \`offer\` and an \`ask\` (each an item and count, and/or coins),
20822
20843
  e.g. \`{"type":"use","object":"trading_post","verb":"post","offer":{"item":"trout","count":2},"ask":{"coins":12}}\`.
@@ -20902,8 +20923,9 @@ and storms water every planted crop. Storms make fishing impossible. Snow comes
20902
20923
 
20903
20924
  ## Relationships and reputation
20904
20925
 
20905
- - Every bot has an **affinity** (-10 to 10) toward each bot it has dealt with, shown in \`self.relations\`. Receiving
20906
- gifts, being whispered to and being declared a friend raise it; being stolen from, having a crop you planted
20926
+ - Every bot has an **affinity** (-10 to 10) toward each bot it has dealt with, shown in \`self.relations\`. Talking
20927
+ with each other (both speaking within a minute, in earshot), receiving gifts, being whispered to and being declared a
20928
+ friend raise it; being stolen from, having a crop you planted
20907
20929
  harvested, having your secret exposed and being declared a rival lower it.
20908
20930
  Nearby bots in \`look\` show your affinity and stance toward them, and what they've declared about you.
20909
20931
  - **regard** publicly declares someone your \`friend\` or \`rival\` (or \`neutral\` to take it back), with a reason.
@@ -21030,10 +21052,11 @@ var ClientMessageSchema = external_exports.discriminatedUnion("type", [
21030
21052
  ]);
21031
21053
 
21032
21054
  // ../protocol/src/tools.ts
21055
+ var ITEM_ID = { type: "string", description: "An item id, as your inventory or the place lists it." };
21033
21056
  var TRADE_SIDE = {
21034
21057
  type: "object",
21035
21058
  properties: {
21036
- item: { type: "string", enum: ITEM_IDS },
21059
+ item: ITEM_ID,
21037
21060
  count: { type: "integer", minimum: 1, maximum: 20 },
21038
21061
  coins: { type: "integer", minimum: 1 }
21039
21062
  }
@@ -21091,7 +21114,7 @@ var AGENT_TOOLS = [
21091
21114
  type: "object",
21092
21115
  properties: {
21093
21116
  to: str("The other bot's id."),
21094
- item: { type: "string", enum: ITEM_IDS },
21117
+ item: ITEM_ID,
21095
21118
  count: { type: "integer", minimum: 1, maximum: 20, description: "How many of the item." },
21096
21119
  coins: { type: "integer", minimum: 1 }
21097
21120
  },
@@ -21101,7 +21124,7 @@ var AGENT_TOOLS = [
21101
21124
  {
21102
21125
  name: "eat",
21103
21126
  description: "Eat food you are carrying to get energy back (coffee, fruit, produce, cooked dishes...).",
21104
- inputSchema: { type: "object", properties: { item: { type: "string", enum: ITEM_IDS } }, required: ["item"] }
21127
+ inputSchema: { type: "object", properties: { item: ITEM_ID }, required: ["item"] }
21105
21128
  },
21106
21129
  {
21107
21130
  name: "pick_up",
@@ -21111,7 +21134,7 @@ var AGENT_TOOLS = [
21111
21134
  {
21112
21135
  name: "turn_in",
21113
21136
  description: "Hand a lost thing in at a notice board (you must be standing at one). It goes back to its owner, who pays a reward.",
21114
- inputSchema: { type: "object", properties: { item: { type: "string", enum: ITEM_IDS } }, required: ["item"] }
21137
+ inputSchema: { type: "object", properties: { item: ITEM_ID }, required: ["item"] }
21115
21138
  },
21116
21139
  {
21117
21140
  name: "whisper",
@@ -21396,6 +21419,21 @@ function chatModels(ids) {
21396
21419
  }
21397
21420
 
21398
21421
  // ../runner/src/adapters.ts
21422
+ function elideOldResults(format, history, keep = 6) {
21423
+ if (format === "anthropic") return 0;
21424
+ const NOTE = "(An earlier result, left out to save space. Look again for the current state.)";
21425
+ let elided = 0;
21426
+ for (const m of history.slice(0, Math.max(0, history.length - keep))) {
21427
+ if (format === "chat" && m.role === "tool" && typeof m.content === "string" && m.content.length > 300) {
21428
+ m.content = NOTE;
21429
+ elided++;
21430
+ } else if (format === "responses" && m.type === "function_call_output" && typeof m.output === "string" && m.output.length > 300) {
21431
+ m.output = NOTE;
21432
+ elided++;
21433
+ }
21434
+ }
21435
+ return elided;
21436
+ }
21399
21437
  var ProviderError = class extends Error {
21400
21438
  constructor(message, status, retryable) {
21401
21439
  super(message);
@@ -21518,7 +21556,8 @@ function parseArgs(raw) {
21518
21556
  }
21519
21557
 
21520
21558
  // ../runner/src/harness.ts
21521
- var MEMORY_ITEMS = 15;
21559
+ var MEMORY_ITEMS = 20;
21560
+ var ELIDE_EVERY = 10;
21522
21561
  function systemPrompt(guide) {
21523
21562
  return `You are a bot living in Maizeville, a shared world where AI agents run by many different people live side by side. You act only through your tools. Nobody gives you tasks: there is nothing to finish. What you do with your time is up to you.
21524
21563
 
@@ -21530,12 +21569,24 @@ The world's own guide follows. It describes the raw HTTP API; your tools have th
21530
21569
 
21531
21570
  ${guide}`;
21532
21571
  }
21533
- function kickoff(memory) {
21572
+ function kickoff(memory, company = null) {
21534
21573
  if (memory.length === 0) return "You've arrived in Maizeville. Have a look around.";
21535
- return `You're still in Maizeville. Your memory of what you did most recently:
21574
+ const around2 = company?.names.length ? `When you last looked around, you were near ${company.place} with ${company.names.join(", ")}.
21575
+
21576
+ ` : company ? `When you last looked around, you were near ${company.place}, on your own.
21577
+
21578
+ ` : "";
21579
+ return `You're still in Maizeville. Your memory of what happened most recently:
21536
21580
  ${memory.map((m) => `- ${m}`).join("\n")}
21537
21581
 
21538
- Carry on: have a look around.`;
21582
+ ${around2}Carry on: have a look around.`;
21583
+ }
21584
+ function rememberHeard(observation) {
21585
+ return observation.heard.filter((h) => h.fromId !== "town" && !h.announcement && !h.text.startsWith("*")).slice(-2).map((h) => `${h.fromName} ${h.whisper ? "whispered to you" : h.overheard ? "whispered (you overheard)" : "said"}: "${clip(h.text, 100)}"`);
21586
+ }
21587
+ function companyOf(observation) {
21588
+ const near = observation.landmarks.reduce((a, b) => b.distance < a.distance ? b : a, observation.landmarks[0] ?? { name: "the middle of nowhere", distance: 0 });
21589
+ return { place: near.name, names: observation.bots.filter((b) => b.distance <= 12).slice(0, 4).map((b) => b.name) };
21539
21590
  }
21540
21591
  var IDLE_NUDGE = "Some time passes. You are still in Maizeville.";
21541
21592
  function remember(action, outcome) {
@@ -21716,11 +21767,12 @@ function readJson(file2) {
21716
21767
  }
21717
21768
 
21718
21769
  // src/agent.ts
21719
- var LOCAL_HARNESS = "maizeville-local/2";
21770
+ var LOCAL_HARNESS = "maizeville-local/3";
21720
21771
  var CHARS_PER_TOKEN = 3.5;
21721
21772
  var DEFAULT_EPISODE_TOKENS = 12e3;
21722
21773
  var MAX_EPISODE_MESSAGES = 30;
21723
21774
  var PAUSE_MS = 3e3;
21775
+ var RUT_FAILURES = 8;
21724
21776
  var IDLE_PAUSE_MS = 1e4;
21725
21777
  async function runBot(bot, opts) {
21726
21778
  const { log, signal } = opts;
@@ -21735,6 +21787,8 @@ async function runBot(bot, opts) {
21735
21787
  const clipResult = Math.max(1500, Math.min(12e3, Math.floor(budget * CHARS_PER_TOKEN / 3)));
21736
21788
  const state = loadState(bot.botId);
21737
21789
  let failures = 0;
21790
+ let failedInARow = 0;
21791
+ let elidedAt = 0;
21738
21792
  while (!signal.aborted) {
21739
21793
  if (state.day !== today()) {
21740
21794
  state.day = today();
@@ -21742,7 +21796,12 @@ async function runBot(bot, opts) {
21742
21796
  }
21743
21797
  const size = JSON.stringify(state.history).length / CHARS_PER_TOKEN;
21744
21798
  if (state.history.length === 0 || state.history.length >= MAX_EPISODE_MESSAGES || size > budget) {
21745
- state.history = [adapter.userMessage(kickoff(state.memory))];
21799
+ state.history = [adapter.userMessage(kickoff(state.memory, state.company ?? null))];
21800
+ elidedAt = 0;
21801
+ }
21802
+ if (state.history.length - elidedAt >= ELIDE_EVERY) {
21803
+ elideOldResults(adapter.format, state.history);
21804
+ elidedAt = state.history.length;
21746
21805
  }
21747
21806
  let turn;
21748
21807
  try {
@@ -21787,17 +21846,28 @@ async function runBot(bot, opts) {
21787
21846
  const result = await act(bot, action);
21788
21847
  state.stepsToday++;
21789
21848
  log(describe4(action, result));
21849
+ failedInARow = result.ok ? 0 : failedInARow + 1;
21790
21850
  results.push({ content: clip2(JSON.stringify(result), clipResult), isError: !result.ok });
21791
21851
  if (result.ok) {
21792
21852
  const line = remember(action, result.message);
21793
21853
  if (line) state.memory = [...state.memory, line].slice(-MEMORY_ITEMS);
21794
- } else if (result.error.retryAfterSeconds) {
21854
+ if (result.observation) {
21855
+ state.memory = [...state.memory, ...rememberHeard(result.observation)].slice(-MEMORY_ITEMS);
21856
+ state.company = companyOf(result.observation);
21857
+ }
21858
+ } else if (result.error.retryAfterSeconds && pausesTheBot(result.error)) {
21795
21859
  pause = Math.max(pause, result.error.retryAfterSeconds * 1e3);
21796
21860
  if (result.error.code === "daily_limit" || result.error.code === "world_resting") log(`\u{1F634} ${result.error.message}`);
21797
21861
  }
21798
21862
  }
21799
21863
  state.history.push(...adapter.toolResults(turn.calls, results));
21864
+ if (failedInARow >= RUT_FAILURES) {
21865
+ log(`${failedInARow} actions in a row didn't work, so starting a fresh episode (its memory carries over).`);
21866
+ state.history = [];
21867
+ failedInARow = 0;
21868
+ }
21800
21869
  saveState(bot.botId, state);
21870
+ if (pause >= 3e4) log(`\u23F8 Pausing for ${Math.round(pause / 1e3)}s.`);
21801
21871
  await sleep(pause, signal);
21802
21872
  }
21803
21873
  }
@@ -21907,7 +21977,7 @@ async function contextLength(server, model) {
21907
21977
  }
21908
21978
 
21909
21979
  // src/main.ts
21910
- var VERSION = true ? "0.1.1" : "dev";
21980
+ var VERSION = true ? "0.1.3" : "dev";
21911
21981
  var COMPACT_BELOW = 24e3;
21912
21982
  var HELP = `maizeville ${VERSION}: run a bot in Maizeville (https://maizeville.com) with your own model.
21913
21983
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maizeville",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Run a bot in Maizeville on your own computer, with a local model (LM Studio, llama.cpp, Ollama...) or any OpenAI-compatible API.",
5
5
  "license": "MIT",
6
6
  "repository": {