{"id":30692940,"url":"https://github.com/magicoflolis/magiccards","last_synced_at":"2025-10-06T14:53:17.638Z","repository":{"id":310127007,"uuid":"1038092404","full_name":"magicoflolis/MagicCards","owner":"magicoflolis","description":"[AI Dungeon] Automatically generate setting-appropriate Story Cards, similar to AutoCards.","archived":false,"fork":false,"pushed_at":"2025-08-18T00:08:24.000Z","size":96,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-30T03:33:38.315Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magicoflolis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-14T15:54:09.000Z","updated_at":"2025-08-18T22:22:12.000Z","dependencies_parsed_at":"2025-08-16T15:30:40.590Z","dependency_job_id":null,"html_url":"https://github.com/magicoflolis/MagicCards","commit_stats":null,"previous_names":["magicoflolis/magiccards"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/magicoflolis/MagicCards","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicoflolis%2FMagicCards","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicoflolis%2FMagicCards/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicoflolis%2FMagicCards/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicoflolis%2FMagicCards/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magicoflolis","download_url":"https://codeload.github.com/magicoflolis/MagicCards/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicoflolis%2FMagicCards/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273233235,"owners_count":25068731,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-02T05:07:14.191Z","updated_at":"2025-10-06T14:53:17.631Z","avatar_url":"https://github.com/magicoflolis.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n\u003csub\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/magicoflolis/MagicCards/refs/heads/main/assets/logo.png\" height=\"38\" width=\"38\"\u003e\n\u003c/sub\u003e\nMagicCards\n\u003c/h1\u003e\n\nAutomatically generate setting-appropriate Story Cards for [AI Dungeon](https://play.aidungeon.com), similar to [AutoCards](https://github.com/LewdLeah/Auto-Cards).\n\n## **Install**\n\n\u003e [!IMPORTANT]\n\u003e If you don't know how to install scenario scripts =\u003e [Scenario Script Installation Guide](https://help.aidungeon.com/what-are-scripts-and-how-do-you-install-them#block-215105b8a632801882a1ea599052b0ac)\n\u003e\n\u003e **Not compatible with AutoCards/SmartCards/etc. or any other automatic Story Card scripts!**\n\n`Library`:\n\n- Copy and paste into your `Library` section =\u003e [MagicCards/dist/Library.js](https://raw.githubusercontent.com/magicoflolis/MagicCards/refs/heads/main/dist/Library.js)\n\nExample:\n\n```js\n//#region Magic Cards\n\n// ...\n\n//#endregion\n```\n\n**BEFORE YOU CONTINUE:**\n\n\u003e Ensure each hook script does not contain `modifier = (text) =\u003e {...}` function!\n\u003e\n\u003e Read [FAQ](#faq) section for additional help!\n\nBefore:\n\n```js\n\n// Checkout the Guidebook examples to get an idea of other ways you can use scripting\n// https://help.aidungeon.com/scripting\n\n// Every script needs a modifier function\nconst modifier = (text) =\u003e {\n  return { text }\n}\n\n// Don't modify this part\nmodifier(text)\n```\n\nAfter:\n\n```js\n\n// Checkout the Guidebook examples to get an idea of other ways you can use scripting\n// https://help.aidungeon.com/scripting\n\n\n// Don't modify this part\n```\n\n---\n\n`Input`:\n\n- Copy and paste into your `Input` section\n- Reference: [MagicCards/dist/Input.js](https://raw.githubusercontent.com/magicoflolis/MagicCards/refs/heads/main/dist/Input.js)\n\n```js\n/// \u003creference no-default-lib=\"true\"/\u003e\n/// \u003creference lib=\"es2022\"/\u003e\n\n/**\n * - Scripting API: https://help.aidungeon.com/scripting\n * - Scripting Guidebook: https://github.com/magicoflolis/aidungeon.js/blob/main/Scripting%20Guidebook.md\n * @template {\u003cT extends string | null, S extends boolean\u003e(text: T, stop: S, hookType: \"input\") =\u003e { text: T; stop?: S; }} ModifierFN\n */\nconst hook = ((currentHook = 'input') =\u003e {\n  if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;\n  /**\n   * ---\n   *\n   * - Add your modifier functions into this function\n   * - **Modifier functions are not called when `mc.cache.generating === true`**\n   *\n   * ---\n   *\n   * _Examples:_\n   *\n   * ```js\n   * hook((text, stop, hookType) =\u003e {\n   *   // For 'Story Arc Engine' by Yi1i1i\n   *   text = onInput_SAE(text);\n   *\n   *   return { text }\n   * })\n   * ```\n   * @param {...ModifierFN} modifiers\n   */\n  const fn = (...modifiers) =\u003e {\n    mc.modifiers.push(...modifiers);\n    return mc;\n  };\n  return fn;\n})();\n\n/* This is your modifier function */\nhook((text) =\u003e {\n  if (typeof text === 'string') {\n    /* Your Script's code goes here */\n  }\n  return { text };\n});\n\n/* Don't modify this part */\nvoid 0;\n```\n\n`Context`:\n\n- Copy and paste into your `Context` section\n- Reference: [MagicCards/dist/Context.js](https://raw.githubusercontent.com/magicoflolis/MagicCards/refs/heads/main/dist/Context.js)\n\n```js\n/// \u003creference no-default-lib=\"true\"/\u003e\n/// \u003creference lib=\"es2022\"/\u003e\n\n/**\n * - Scripting API: https://help.aidungeon.com/scripting\n * - Scripting Guidebook: https://github.com/magicoflolis/aidungeon.js/blob/main/Scripting%20Guidebook.md\n * @template {\u003cT extends string | null, S extends boolean\u003e(text: T, stop: S, hookType: \"context\") =\u003e { text: T; stop?: S; }} ModifierFN\n */\nconst hook = ((currentHook = 'context') =\u003e {\n  if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;\n  /**\n   * ---\n   *\n   * - Add your modifier functions into this function\n   * - **Modifier functions are not called when `mc.cache.generating === true`**\n   *\n   * ---\n   *\n   * _Examples:_\n   *\n   * ```js\n   * hook((text, stop, hookType) =\u003e {\n   *   // For 'Story Arc Engine' by Yi1i1i\n   *   text = onContext_SAE(text);\n   *\n   *   return { text }\n   *   // Or return { text, stop }\n   * })\n   * ```\n   * @param {...ModifierFN} modifiers\n   */\n  const fn = (...modifiers) =\u003e {\n    mc.modifiers.push(...modifiers);\n    return mc;\n  };\n  return fn;\n})();\n\n/* This is your modifier function */\nhook((text) =\u003e {\n  if (typeof text === 'string') {\n    /* Your Script's code goes here */\n  }\n  return { text };\n});\n\n/* Don't modify this part */\nvoid 0;\n```\n\n`Output`:\n\n- Copy and paste into your `Output` section\n- Reference: [MagicCards/dist/Output.js](https://raw.githubusercontent.com/magicoflolis/MagicCards/refs/heads/main/dist/Output.js)\n\n```js\n/// \u003creference no-default-lib=\"true\"/\u003e\n/// \u003creference lib=\"es2022\"/\u003e\n\n/**\n * - Scripting API: https://help.aidungeon.com/scripting\n * - Scripting Guidebook: https://github.com/magicoflolis/aidungeon.js/blob/main/Scripting%20Guidebook.md\n * @template {\u003cT extends string | null, S extends boolean\u003e(text: T, stop: S, hookType: \"output\") =\u003e { text: T; stop?: S; }} ModifierFN\n */\nconst hook = ((currentHook = 'output') =\u003e {\n  if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;\n  /**\n   * ---\n   *\n   * - Add your modifier functions into this function\n   * - **Modifier functions are not called when `mc.cache.generating === true`**\n   *\n   * ---\n   *\n   * _Examples:_\n   *\n   * ```js\n   * hook((text, stop, hookType) =\u003e {\n   *   // For 'Story Arc Engine' by Yi1i1i\n   *   text = onOutput_SAE(text);\n   *\n   *   return { text }\n   * })\n   * ```\n   * @param {...ModifierFN} modifiers\n   */\n  const fn = (...modifiers) =\u003e {\n    mc.modifiers.push(...modifiers);\n    return mc;\n  };\n  return fn;\n})();\n\n/* This is your modifier function */\nhook((text) =\u003e {\n  if (typeof text === 'string') {\n    /* Your Script's code goes here */\n  }\n  return { text };\n});\n\n/* Don't modify this part */\nvoid 0;\n```\n\n## Features\n\n- General:\n  - Slash commands: `/MC`, `/AC`, `/mc`, `/ac`\n  - Works for any character or location\n  - Compatible with _most_ AI models\n- Automation:\n  - Create story card after `x` amount of turns (default: 22)\n  - Summarize created story cards after `x` amount of turns (default: 22)\n- Settings:\n  - `autoHistory`: summarize prior events of Story Cards (default: false)\n  - `autoRetrieve`: retrieve Character and Location names from context + memory (default: false)\n  - `cooldown`: number of turns until `autoRetrieve` or `autoHistory` are triggered (default: 22)\n  - `enabled`: toggle on/off MagicCards (default: true)\n  - `hiddenCards`: toggle additional cards\n    - `characters`: AI instructions\n    - `compress`: AI instructions\n    - `debug`: debug card (readonly)\n    - `locations`: AI instructions\n    - `retrieve`: AI instructions\n    - `*`: Your custom AI instructions (not implemented)\n  - `useSmallModel`: toggle on/off use of large AI models (default: true)\n\n## Slash Commands\n\n\u003e [!IMPORTANT]\n\u003e Does not follow original AutoCards syntax\n\n- `/MC Name; [Details]`\n- `/AC Name; [Details]`\n\n**Example:**\n\n```txt\n/MC Aaron; creator of MagicCards\n/AC Leah; creator of AutoCards\n\n\"Details\" is optional\n/MC Veyne\n```\n\n**Input Commands:**\n\n```txt\n/MC [Input Command]\n/AC [Input Command]\n\nExample\n/MC retrieve\n```\n\n- `retrieve` / `get` =\u003e force entry check (`retrieve`)\n- `toggle` / `enable` / `disable` =\u003e toggle MagicCards\n- `reset` / `restart` / `restore` =\u003e restore to default settings\n- `clear` / `clr` / `cls` =\u003e clear the current entry being generated (debug command), _use if you encounter any errors during generation_\n- `summarize` / `compress` =\u003e force summarize all created story cards (`compress`)\n\n## API / Scripting\n\n\u003e [!IMPORTANT]\n\u003e During card generation **all modifier functions are not called**\n\u003e\n\u003e _This should not cause any issues as long as you don't rely on scripts which need to be called every turn_\n\nAll functions are exposed and can be easily used.\n\n```js\n// Constant should already exist once installed\nconst mc = new MagicCards(); // or globalThis.mc\n\n// Array of created StoryCards\nfor (const card of mc.magicCards()) {\n  console.log( card ); // StoryCard\n}\n\n// Create a new story card\nconst sc = mc.StoryCard({keys: 'foo', entry: 'bar'});\n// { card: StoryCard }\nconsole.log( sc.card );\n```\n\n---\n\nCheck if \"MagicCards\" is installed:\n\n\u003e [!IMPORTANT]\n\u003e This value is not cached:\n\u003e\n\u003e 1. `info.actionCount` is 3 =\u003e `mc.installed` is **true**\n\u003e 2. User rewinds action below 3 =\u003e `mc.installed` is **false**\n\n```js\n// Constant should already exist once installed\nconst mc = new MagicCards(); // or globalThis.mc\n\nconsole.log( mc.installed ); // boolean\n```\n\n---\n\nTemporarily disable:\n\n- This disables MagicCards for the **entire turn**\n- You can set this value anytime to halt MagicCards\n\n```js\n// Constant should already exist once installed\nconst mc = new MagicCards(); // or globalThis.mc\n\n// Not required but recommended\nif ( mc.installed ) {\n  // Stored settings and `state.MagicCards`\n  const cache = mc.cache;\n  cache.disabled = true;\n}\n\n// or\n\n// Stored settings and `state.MagicCards`\nconst cache = mc.cache;\ncache.disabled = true;\n```\n\n---\n\nGet \"calculated\" actionCount:\n\n```js\n// Constant should already exist once installed\nconst mc = new MagicCards(); // or globalThis.mc\n\nconsole.log( mc.actionCount );\n```\n\n---\n\nCheck if \"MagicCards\" exists:\n\n```js\nif ( typeof globalThis.MagicCards !== 'undefined' || typeof globalThis.mc !== 'undefined' ) {\n  // Your code goes here\n}\n\n// or\n\nif ( globalThis.MagicCards || globalThis.mc ) {\n  // Your code goes here\n}\n```\n\n## FAQ\n\n**Do I have to remove the `modifier` functions?**\n\nAs strongly I recommend you do, _technically_ you do not if you are willing to edit MagicCards code base.\n\n**IMPORTANT:** Doing this removes MagicCards control on each hooks modifier function\n\n- Find (Ctrl + F) the `#modifier()` function in your `Library`\n- Make the following changes\n\n```js\n#modifier() {\n  const modifier = () =\u003e { /* ... */ };\n  //#region Edit this region\n\n  // BEFORE\n  globalThis.modifier = modifier;\n  Object.freeze(globalThis.modifier);\n\n  // AFTER\n  globalThis.mcModifier = modifier;\n  Object.freeze(globalThis.mcModifier);\n\n  //#endregion\n\n  return this;\n}\n```\n\n- In your `modifier()` functions, make the following changes:\n\n```js\nconst modifier = (text) =\u003e {\n  globalThis.mcModifier(); // or whatever name you gave it\n  // self-repair\n  const currentHook = 'input'; // edit to correspond with the current hook\n  if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;\n\n  /* Your Script's code goes here */\n\n  return { text, stop }\n}\n```\n\n---\n\n**Can I remove the modifier functions in general?**\n\n\u003e [!IMPORTANT]\n\u003e This removes MagicCards \"self-repair\" feature\n\nYes! Simply copy + paste this code into each hook:\n\n```js\n/* Yup, it's just one line */\nvoid 0;\n```\n\n---\n\n**How do I enable autoRetrieve + autoHistory globally?**\n\nMake the following changes in the \"SETTINGS\" Story Card:\n\n```txt\nautoHistory: true\nautoRetrieve: true\nuseSmallModel: false\n```\n\n---\n\n**How do I change \"X\" setting for \"Y\" Story Card?**\n\nIn the \"Notes\" section of the created Story Card.\n\nAvailable options:\n\n```txt\nsync: boolean\nautoHistory: boolean\ndefaultCooldown: number\n```\n\nAll options:\n\n```txt\nsync: boolean\nautoHistory: boolean\ndefaultCooldown: number\ncooldown: number\nsummary: string\n```\n\n- `sync`: automatically sync `autoHistory` / `defaultCooldown` with `autoHistory` / `cooldown` found in the SETTINGS card\n- `autoHistory`: toggle `compress` for this card, must have `useSmallModel` set to false\n- `defaultCooldown`: default number of turns until `compress` is triggered\n- `cooldown`: number of turns until `compress` is triggered\n- `summary`: prior events, automatically added at the end of triggered Story Cards as `Events: ...`\n\n---\n\n**When is MagicCards disabled?**\n\n- If `info.actionCount` is below 3\n- If `mc.cache.disabled` is true, _can be programmatically changed / set_\n- If user inputs an AI instruction (not case sensitive): `[system: ...]`, `\u003cs\u003e ... \u003c/s\u003e`, `\u003csystem\u003e ... \u003c/system\u003e`, `## ...`, `**...**`\n\n---\n\n**Which modifier functions are UNSUPPORTED by hook function?**\n\n- Functions named `AutoCards`, `SmartCards`, or `MagicCards`\n- `Async`, `Generator`, or `Promise` type functions\n\n```js\n// All will throw an error\n\nhook(async () =\u003e { /* ... */ });\n\nhook(() =\u003e {\n  return Promise.resolve().then(() =\u003e text)\n});\n\nhook(AutoCards);\n\nhook(MagicCards);\n\nhook(SmartCards);\n```\n\n---\n\n**What return values are SUPPORTED by hook function?**\n\n- `Objects`, `Arrays`, or `Functions` which return either or\n\n```js\nhook((text, stop) =\u003e {\n  return { text, stop }\n});\n\nhook((text, stop) =\u003e {\n  return [ text, stop ]\n});\n\nhook((text, stop) =\u003e {\n  return () =\u003e {\n    // or [ text, stop ]\n    return { text, stop }\n  }\n});\n\n// Not recommended\nhook('Hello World!'); // will change text to this value\n```\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagicoflolis%2Fmagiccards","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagicoflolis%2Fmagiccards","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagicoflolis%2Fmagiccards/lists"}