@idosgames/mcp 0.1.37 → 0.1.38

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 (43) hide show
  1. package/README.md +6 -0
  2. package/dist/cli.js +2204 -27
  3. package/package.json +4 -1
  4. package/registry/host.json +3 -3
  5. package/registry/index.json +310 -156
  6. package/registry/modules/ai.json +7 -7
  7. package/registry/modules/board-game.json +14 -14
  8. package/registry/modules/boosts.json +3 -3
  9. package/registry/modules/character.json +32 -15
  10. package/registry/modules/chat.json +3 -3
  11. package/registry/modules/collections.json +7 -7
  12. package/registry/modules/coop-events.json +7 -7
  13. package/registry/modules/craft.json +3 -3
  14. package/registry/modules/deals.json +7 -7
  15. package/registry/modules/events.json +8 -8
  16. package/registry/modules/friends.json +9 -9
  17. package/registry/modules/hero-run.json +498 -0
  18. package/registry/modules/idle-rpg.json +69 -17
  19. package/registry/modules/inventory.json +3 -3
  20. package/registry/modules/invite.json +7 -7
  21. package/registry/modules/leaderboard.json +10 -10
  22. package/registry/modules/lootboxes.json +7 -7
  23. package/registry/modules/mailbox.json +8 -8
  24. package/registry/modules/marketplace.json +8 -8
  25. package/registry/modules/mini-game.json +8 -8
  26. package/registry/modules/multiplayer.json +7 -7
  27. package/registry/modules/premium.json +7 -7
  28. package/registry/modules/profile.json +7 -7
  29. package/registry/modules/pvp.json +7 -7
  30. package/registry/modules/quests.json +8 -8
  31. package/registry/modules/rewards.json +8 -8
  32. package/registry/modules/season.json +7 -7
  33. package/registry/modules/store.json +7 -7
  34. package/registry/modules/tutorials.json +7 -7
  35. package/registry/modules/video-studio.json +228 -0
  36. package/registry/modules/voxelcraft.json +42 -125
  37. package/registry/modules/workshop.json +3 -3
  38. package/registry/skills/hero-run.json +6 -0
  39. package/registry/skills/idosgames-module-contract.json +2 -2
  40. package/registry/skills/idosgames-project-structure.json +1 -1
  41. package/registry/skills/idosgames-ui-kit.json +1 -1
  42. package/registry/skills/video-studio.json +6 -0
  43. package/registry/video.json +9800 -0
@@ -27,19 +27,19 @@
27
27
  "name": "iDos Games",
28
28
  "url": "https://idosgames.com"
29
29
  },
30
- "version": "0.1.2"
30
+ "version": "0.1.3"
31
31
  },
32
32
  "dependencies": {
33
- "@idosgames/core": "0.22.1",
34
- "@idosgames/module-sdk": "0.12.0",
35
- "@idosgames/react": "0.5.2",
33
+ "@idosgames/core": "0.23.0",
34
+ "@idosgames/module-sdk": "0.13.0",
35
+ "@idosgames/react": "0.6.0",
36
36
  "react": "19.2.7"
37
37
  },
38
- "contentHash": "5f9b6c26d6c6fe550184e636ca1c1f5f1fc426cd54c01277235e93df9a0015c5",
38
+ "contentHash": "8a8b10cdef84bd966f04352c7956d3e6d60f31d7412cec50b4e31aa09c23b33e",
39
39
  "files": [
40
40
  {
41
41
  "path": "AiScreen.tsx",
42
- "content": "import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { AIGenerationView, IDosGamesClient } from \"@idosgames/core\";\nimport type { FeatureScreenProps } from \"@idosgames/module-sdk\";\nimport { useIDosGamesClient, useUserState } from \"@idosgames/react\";\nimport {\n Button,\n canAfford,\n Card,\n Center,\n configSection,\n EmptyState,\n errorText,\n Icon,\n outlined,\n panel,\n ResourceList,\n Spinner,\n Tabs,\n TextArea,\n useCatalog,\n useStagger,\n useToast,\n v,\n} from \"@idosgames/react/ui\";\nimport {\n featureRows,\n resultKind,\n type AISection,\n type FeatureRow,\n type Modality,\n} from \"./model\";\nimport { t } from \"./i18n\";\n\n// AI studio (engine AI): the AI features the publisher opened to players — text, pictures, speech,\n// music, video, 3D. The player writes what they want, pays the feature's price (or nothing), and the\n// result comes back from a job the server runs (polled with waitForGeneration). A feature tagged\n// \"hidden\" is for the game's own code (NPC lines and the like) and does not show here.\n\ntype Tab = \"create\" | \"history\";\n\nexport function AiScreen(_: FeatureScreenProps): ReactNode {\n const client = useIDosGamesClient();\n const catalog = useCatalog();\n const [tab, setTab] = useState<Tab>(\"create\");\n const [picked, setPicked] = useState<string | null>(null);\n const features = featureRows(configSection<AISection>(client, \"AI\"));\n if (features.length === 0)\n return <EmptyState glyph=\"bulb\" text={t(\"noFeatures\")} />;\n const current = features.find((f) => f.key === picked) ?? features[0]!;\n return (\n <div style={{ display: \"grid\", gap: 12 }}>\n <Tabs\n tabs={[\n { id: \"create\", label: t(\"create\") },\n { id: \"history\", label: t(\"history\") },\n ]}\n value={tab}\n onChange={setTab}\n />\n {tab === \"create\" ? (\n <>\n {features.length > 1 ? (\n <div style={{ display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n {features.map((f) => (\n <Button\n key={f.key}\n size=\"sm\"\n tone={f.key === current.key ? \"gold\" : \"grey\"}\n onClick={() => setPicked(f.key)}\n >\n {catalog.localize(f.key)} · {t(`m_${f.modality}`)}\n </Button>\n ))}\n </div>\n ) : null}\n <Create key={current.key} feature={current} />\n </>\n ) : (\n <History />\n )}\n </div>\n );\n}\n\n/** Starts a job for a feature by its modality and waits for the result. */\nfunction run(\n client: IDosGamesClient,\n feature: FeatureRow,\n prompt: string,\n optionID: string | undefined,\n): Promise<\n { ok: true; data: AIGenerationView } | { ok: false; error: string }\n> {\n const options = {\n selectedOptionID: optionID,\n relatedEntityID: crypto.randomUUID(),\n };\n const byModality: Record<\n Modality,\n () => ReturnType<IDosGamesClient[\"ai\"][\"generateText\"]>\n > = {\n Text: () =>\n client.ai.generateText(feature.key, { Prompt: prompt }, options),\n Image: () =>\n client.ai.generateImage(feature.key, { Prompt: prompt }, options),\n Audio: () =>\n client.ai.generateAudio(feature.key, { Text: prompt }, options),\n Music: () =>\n client.ai.generateMusic(feature.key, { Prompt: prompt }, options),\n Video: () =>\n client.ai.generateVideo(feature.key, { Prompt: prompt }, options),\n ThreeD: () =>\n client.ai.generateThreeD(feature.key, { Prompt: prompt }, options),\n };\n return byModality[feature.modality]().then((started) =>\n started.ok\n ? client.ai.waitForGeneration(started.data, { timeoutMs: 10 * 60_000 })\n : started,\n );\n}\n\nfunction Create({ feature }: { feature: FeatureRow }): ReactNode {\n const client = useIDosGamesClient();\n const state = useUserState();\n const toast = useToast();\n const [prompt, setPrompt] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [result, setResult] = useState<AIGenerationView | null>(null);\n const alive = useRef(true);\n useEffect(\n () => () => {\n alive.current = false;\n },\n [],\n );\n const balances = state?.InventoryV2?.VirtualCurrencies as\n Record<string, { Amount?: number }> | undefined;\n const option =\n feature.options.find((o) => canAfford(o.price, balances)) ??\n feature.options[0];\n const affordable = !option || canAfford(option.price, balances);\n\n const go = async () => {\n setBusy(true);\n setResult(null);\n const res = await run(client, feature, prompt.trim(), option?.id);\n if (!alive.current) return;\n setBusy(false);\n if (!res.ok) return toast(errorText(res.error), \"error\");\n if (res.data.Status !== \"completed\")\n return toast(res.data.Error?.Message || t(\"failed\"), \"error\");\n setResult(res.data);\n };\n\n return (\n <div style={{ display: \"grid\", gap: 10 }}>\n <TextArea\n value={prompt}\n maxLength={feature.maxChars > 0 ? feature.maxChars : undefined}\n placeholder={\n feature.modality === \"Audio\" ? t(\"sayWhat\") : t(\"describe\")\n }\n onChange={(e) => setPrompt(e.target.value)}\n rows={4}\n style={{ padding: 12, width: \"100%\" }}\n />\n <Button\n tone=\"gold\"\n size=\"lg\"\n attract={!!prompt.trim() && affordable}\n disabled={!prompt.trim() || !affordable}\n busy={busy}\n onClick={() => void go()}\n data-tutorial-anchor={`ai:${feature.key}`}\n >\n {busy ? t(\"working\") : t(\"generate\")}{\" \"}\n {option ? <ResourceList lines={option.price} size={18} /> : null}\n </Button>\n {busy ? (\n <Center>\n <Spinner />\n </Center>\n ) : null}\n {result ? <Result generation={result} /> : null}\n </div>\n );\n}\n\nfunction Result({ generation }: { generation: AIGenerationView }): ReactNode {\n return (\n <div style={{ ...panel, padding: 12, display: \"grid\", gap: 10 }}>\n {generation.OutputText ? (\n <div style={{ color: v.text, fontSize: 15, whiteSpace: \"pre-wrap\" }}>\n {generation.OutputText}\n </div>\n ) : null}\n {(generation.Assets ?? []).map((a, i) => {\n const kind = resultKind(a.ContentType);\n const url = a.Url ?? \"\";\n return kind === \"image\" ? (\n <img\n key={i}\n src={url}\n alt=\"\"\n style={{ width: \"100%\", borderRadius: 12 }}\n />\n ) : kind === \"audio\" ? (\n <audio key={i} src={url} controls style={{ width: \"100%\" }} />\n ) : kind === \"video\" ? (\n <video\n key={i}\n src={url}\n controls\n style={{ width: \"100%\", borderRadius: 12 }}\n />\n ) : (\n <a\n key={i}\n href={url}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{ ...outlined, color: v.gold, fontSize: 14 }}\n >\n {t(\"download\")}\n </a>\n );\n })}\n </div>\n );\n}\n\nfunction History(): ReactNode {\n const client = useIDosGamesClient();\n const catalog = useCatalog();\n const stagger = useStagger();\n const [items, setItems] = useState<AIGenerationView[] | null>(null);\n const [open, setOpen] = useState<string | null>(null);\n useEffect(() => {\n void client.ai\n .listGenerations({ Limit: 20 })\n .then((r) => setItems(r.ok ? (r.data.Data ?? []) : []));\n }, [client]);\n if (!items)\n return (\n <Center>\n <Spinner />\n </Center>\n );\n if (items.length === 0)\n return <EmptyState glyph=\"bulb\" text={t(\"noHistory\")} />;\n return (\n <div style={{ display: \"grid\", gap: 8 }}>\n {items.map((g, i) => (\n <Card\n key={g.GenerationID}\n onClick={() =>\n setOpen(open === g.GenerationID ? null : g.GenerationID)\n }\n style={{ display: \"grid\", gap: 8, ...stagger(i) }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <Icon glyph=\"bulb\" size={26} />\n <span style={{ ...outlined, fontSize: 14, flex: 1 }}>\n {catalog.localize(g.FeatureKey ?? \"\")}\n </span>\n <span\n style={{\n ...outlined,\n fontSize: 12,\n color:\n g.Status === \"completed\"\n ? v.green\n : g.Status === \"failed\"\n ? v.textDim\n : v.gold,\n }}\n >\n {t(\n `s_${g.Status === \"completed\" || g.Status === \"failed\" ? g.Status : \"running\"}`,\n )}\n </span>\n </div>\n {open === g.GenerationID && g.Status === \"completed\" ? (\n <Result generation={g} />\n ) : null}\n </Card>\n ))}\n </div>\n );\n}\n"
42
+ "content": "import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { AIGenerationView, IDosGamesClient } from \"@idosgames/core\";\nimport type { FeatureScreenProps } from \"@idosgames/module-sdk\";\nimport { useIDosGamesClient, useUserState } from \"@idosgames/react\";\nimport {\n Columns,\n Button,\n canAfford,\n Card,\n Center,\n configSection,\n EmptyState,\n errorText,\n Icon,\n outlined,\n panel,\n ResourceList,\n Spinner,\n Tabs,\n TextArea,\n useCatalog,\n useStagger,\n useToast,\n v,\n} from \"@idosgames/react/ui\";\nimport {\n featureRows,\n resultKind,\n type AISection,\n type FeatureRow,\n type Modality,\n} from \"./model\";\nimport { t } from \"./i18n\";\n\n// AI studio (engine AI): the AI features the publisher opened to players — text, pictures, speech,\n// music, video, 3D. The player writes what they want, pays the feature's price (or nothing), and the\n// result comes back from a job the server runs (polled with waitForGeneration). A feature tagged\n// \"hidden\" is for the game's own code (NPC lines and the like) and does not show here.\n\ntype Tab = \"create\" | \"history\";\n\nexport function AiScreen(_: FeatureScreenProps): ReactNode {\n const client = useIDosGamesClient();\n const catalog = useCatalog();\n const [tab, setTab] = useState<Tab>(\"create\");\n const [picked, setPicked] = useState<string | null>(null);\n const features = featureRows(configSection<AISection>(client, \"AI\"));\n if (features.length === 0)\n return <EmptyState glyph=\"bulb\" text={t(\"noFeatures\")} />;\n const current = features.find((f) => f.key === picked) ?? features[0]!;\n return (\n <div style={{ display: \"grid\", gap: 12 }}>\n <Tabs\n tabs={[\n { id: \"create\", label: t(\"create\") },\n { id: \"history\", label: t(\"history\") },\n ]}\n value={tab}\n onChange={setTab}\n />\n {tab === \"create\" ? (\n <>\n {features.length > 1 ? (\n <div style={{ display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n {features.map((f) => (\n <Button\n key={f.key}\n size=\"sm\"\n tone={f.key === current.key ? \"gold\" : \"grey\"}\n onClick={() => setPicked(f.key)}\n >\n {catalog.localize(f.key)} · {t(`m_${f.modality}`)}\n </Button>\n ))}\n </div>\n ) : null}\n <Create key={current.key} feature={current} />\n </>\n ) : (\n <History />\n )}\n </div>\n );\n}\n\n/** Starts a job for a feature by its modality and waits for the result. */\nfunction run(\n client: IDosGamesClient,\n feature: FeatureRow,\n prompt: string,\n optionID: string | undefined,\n): Promise<\n { ok: true; data: AIGenerationView } | { ok: false; error: string }\n> {\n const options = {\n selectedOptionID: optionID,\n relatedEntityID: crypto.randomUUID(),\n };\n const byModality: Record<\n Modality,\n () => ReturnType<IDosGamesClient[\"ai\"][\"generateText\"]>\n > = {\n Text: () =>\n client.ai.generateText(feature.key, { Prompt: prompt }, options),\n Image: () =>\n client.ai.generateImage(feature.key, { Prompt: prompt }, options),\n Audio: () =>\n client.ai.generateAudio(feature.key, { Text: prompt }, options),\n Music: () =>\n client.ai.generateMusic(feature.key, { Prompt: prompt }, options),\n Video: () =>\n client.ai.generateVideo(feature.key, { Prompt: prompt }, options),\n ThreeD: () =>\n client.ai.generateThreeD(feature.key, { Prompt: prompt }, options),\n };\n return byModality[feature.modality]().then((started) =>\n started.ok\n ? client.ai.waitForGeneration(started.data, { timeoutMs: 10 * 60_000 })\n : started,\n );\n}\n\nfunction Create({ feature }: { feature: FeatureRow }): ReactNode {\n const client = useIDosGamesClient();\n const state = useUserState();\n const toast = useToast();\n const [prompt, setPrompt] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [result, setResult] = useState<AIGenerationView | null>(null);\n const alive = useRef(true);\n useEffect(\n () => () => {\n alive.current = false;\n },\n [],\n );\n const balances = state?.InventoryV2?.VirtualCurrencies as\n Record<string, { Amount?: number }> | undefined;\n const option =\n feature.options.find((o) => canAfford(o.price, balances)) ??\n feature.options[0];\n const affordable = !option || canAfford(option.price, balances);\n\n const go = async () => {\n setBusy(true);\n setResult(null);\n const res = await run(client, feature, prompt.trim(), option?.id);\n if (!alive.current) return;\n setBusy(false);\n if (!res.ok) return toast(errorText(res.error), \"error\");\n if (res.data.Status !== \"completed\")\n return toast(res.data.Error?.Message || t(\"failed\"), \"error\");\n setResult(res.data);\n };\n\n return (\n <div style={{ display: \"grid\", gap: 10 }}>\n <TextArea\n value={prompt}\n maxLength={feature.maxChars > 0 ? feature.maxChars : undefined}\n placeholder={\n feature.modality === \"Audio\" ? t(\"sayWhat\") : t(\"describe\")\n }\n onChange={(e) => setPrompt(e.target.value)}\n rows={4}\n style={{ padding: 12, width: \"100%\" }}\n />\n <Button\n tone=\"gold\"\n size=\"lg\"\n attract={!!prompt.trim() && affordable}\n disabled={!prompt.trim() || !affordable}\n busy={busy}\n onClick={() => void go()}\n data-tutorial-anchor={`ai:${feature.key}`}\n >\n {busy ? t(\"working\") : t(\"generate\")}{\" \"}\n {option ? <ResourceList lines={option.price} size={18} /> : null}\n </Button>\n {busy ? (\n <Center>\n <Spinner />\n </Center>\n ) : null}\n {result ? <Result generation={result} /> : null}\n </div>\n );\n}\n\nfunction Result({ generation }: { generation: AIGenerationView }): ReactNode {\n return (\n <div style={{ ...panel, padding: 12, display: \"grid\", gap: 10 }}>\n {generation.OutputText ? (\n <div style={{ color: v.text, fontSize: 15, whiteSpace: \"pre-wrap\" }}>\n {generation.OutputText}\n </div>\n ) : null}\n {(generation.Assets ?? []).map((a, i) => {\n const kind = resultKind(a.ContentType);\n const url = a.Url ?? \"\";\n return kind === \"image\" ? (\n <img\n key={i}\n src={url}\n alt=\"\"\n style={{ width: \"100%\", borderRadius: 12 }}\n />\n ) : kind === \"audio\" ? (\n <audio key={i} src={url} controls style={{ width: \"100%\" }} />\n ) : kind === \"video\" ? (\n <video\n key={i}\n src={url}\n controls\n style={{ width: \"100%\", borderRadius: 12 }}\n />\n ) : (\n <a\n key={i}\n href={url}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{ ...outlined, color: v.gold, fontSize: 14 }}\n >\n {t(\"download\")}\n </a>\n );\n })}\n </div>\n );\n}\n\nfunction History(): ReactNode {\n const client = useIDosGamesClient();\n const catalog = useCatalog();\n const stagger = useStagger();\n const [items, setItems] = useState<AIGenerationView[] | null>(null);\n const [open, setOpen] = useState<string | null>(null);\n useEffect(() => {\n void client.ai\n .listGenerations({ Limit: 20 })\n .then((r) => setItems(r.ok ? (r.data.Data ?? []) : []));\n }, [client]);\n if (!items)\n return (\n <Center>\n <Spinner />\n </Center>\n );\n if (items.length === 0)\n return <EmptyState glyph=\"bulb\" text={t(\"noHistory\")} />;\n return (\n <Columns gap={8} min={320}>\n {items.map((g, i) => (\n <Card\n key={g.GenerationID}\n onClick={() =>\n setOpen(open === g.GenerationID ? null : g.GenerationID)\n }\n style={{ display: \"grid\", gap: 8, ...stagger(i) }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <Icon glyph=\"bulb\" size={26} />\n <span style={{ ...outlined, fontSize: 14, flex: 1 }}>\n {catalog.localize(g.FeatureKey ?? \"\")}\n </span>\n <span\n style={{\n ...outlined,\n fontSize: 12,\n color:\n g.Status === \"completed\"\n ? v.green\n : g.Status === \"failed\"\n ? v.textDim\n : v.gold,\n }}\n >\n {t(\n `s_${g.Status === \"completed\" || g.Status === \"failed\" ? g.Status : \"running\"}`,\n )}\n </span>\n </div>\n {open === g.GenerationID && g.Status === \"completed\" ? (\n <Result generation={g} />\n ) : null}\n </Card>\n ))}\n </Columns>\n );\n}\n"
43
43
  },
44
44
  {
45
45
  "path": "i18n.ts",
@@ -59,7 +59,7 @@
59
59
  },
60
60
  {
61
61
  "path": "module.meta.json",
62
- "content": "{\n \"id\": \"ai\",\n \"type\": \"feature\",\n \"summary\": \"AI studio for any game: the title's AI features for players — text, pictures, voice, music, video and 3D — with the price and the history.\",\n \"description\": \"A ready AI studio (engine AI, InApp AI) for ANY game, built on the @idosgames/react/ui kit and client.ai. Every AI feature the publisher opened to players (section AI, sanitized by the server: no prompts, no models), grouped by kind — text, picture, voice, music, video, 3D. The player describes what they want, pays the feature's price in in-game resources (or nothing), and the result comes back from a job the server runs (waitForGeneration): text, pictures, a player for sound and video, a download link for 3D. 'My creations' lists the player's generations. A feature tagged 'hidden' is for the game's own code (NPC lines and the like) and is not shown. Registers the 'ai' feature. The money side (publisher credits) is the engine's; see the in-app AI rules.\",\n \"provides\": [\n \"AI studio screen\",\n \"text, image, voice, music, video and 3D generation for players\",\n \"feature price in in-game resources\",\n \"history of the player's generations\"\n ],\n \"tags\": [\"ai\", \"generation\", \"ugc\", \"creative\", \"ui\", \"screen\"],\n \"author\": {\n \"name\": \"iDos Games\",\n \"url\": \"https://idosgames.com\"\n },\n \"version\": \"0.1.2\"\n}\n"
62
+ "content": "{\n \"id\": \"ai\",\n \"type\": \"feature\",\n \"summary\": \"AI studio for any game: the title's AI features for players — text, pictures, voice, music, video and 3D — with the price and the history.\",\n \"description\": \"A ready AI studio (engine AI, InApp AI) for ANY game, built on the @idosgames/react/ui kit and client.ai. Every AI feature the publisher opened to players (section AI, sanitized by the server: no prompts, no models), grouped by kind — text, picture, voice, music, video, 3D. The player describes what they want, pays the feature's price in in-game resources (or nothing), and the result comes back from a job the server runs (waitForGeneration): text, pictures, a player for sound and video, a download link for 3D. 'My creations' lists the player's generations. A feature tagged 'hidden' is for the game's own code (NPC lines and the like) and is not shown. Registers the 'ai' feature. The money side (publisher credits) is the engine's; see the in-app AI rules.\",\n \"provides\": [\n \"AI studio screen\",\n \"text, image, voice, music, video and 3D generation for players\",\n \"feature price in in-game resources\",\n \"history of the player's generations\"\n ],\n \"tags\": [\"ai\", \"generation\", \"ugc\", \"creative\", \"ui\", \"screen\"],\n \"author\": {\n \"name\": \"iDos Games\",\n \"url\": \"https://idosgames.com\"\n },\n \"version\": \"0.1.3\"\n}\n"
63
63
  }
64
64
  ]
65
65
  }