cortico 0.1.0 → 0.1.2

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 (112) hide show
  1. package/README.md +7 -14
  2. package/package.json +1 -3
  3. package/src/boot.ts +18 -0
  4. package/src/bot.ts +41 -6
  5. package/src/core/README.md +4 -6
  6. package/src/core/blobs.ts +23 -2
  7. package/src/core/config-schema.ts +1 -1
  8. package/src/core/config.ts +2 -16
  9. package/src/core/core.ts +15 -5
  10. package/src/core/loop.ts +55 -27
  11. package/src/core/session.ts +3 -2
  12. package/src/core/timers.ts +8 -6
  13. package/src/core/types.ts +19 -3
  14. package/src/core/util.ts +17 -1
  15. package/src/deploy.ts +4 -1
  16. package/src/extensions/README.md +6 -4
  17. package/src/extensions/dry-mount.ts +23 -2
  18. package/src/extensions/manifest.ts +21 -11
  19. package/src/extensions.ts +147 -23
  20. package/src/launcher.ts +23 -9
  21. package/src/protocol/open-responses/context-log.ts +37 -9
  22. package/src/providers/README.md +32 -8
  23. package/src/providers/base.ts +3 -1
  24. package/src/providers/configuration.ts +2 -1
  25. package/src/providers/console/hub.ts +270 -0
  26. package/src/providers/console/settings.ts +8 -18
  27. package/src/providers/console/types.ts +5 -0
  28. package/src/providers/hub-api.ts +3 -0
  29. package/src/providers/llamacpp/config.ts +8 -6
  30. package/src/providers/llamacpp/console/runtime-panel.ts +5 -1
  31. package/src/providers/llamacpp/console/server.ts +3 -1
  32. package/src/providers/llamacpp/index.ts +3 -1
  33. package/src/providers/llamacpp/native.ts +10 -5
  34. package/src/providers/llamacpp/strings.ts +6 -6
  35. package/src/providers/name.ts +8 -0
  36. package/src/providers/openai-responses-compat/config.ts +13 -0
  37. package/src/providers/openai-responses-compat/console/client.ts +5 -0
  38. package/src/providers/openai-responses-compat/console/reasoning-panel.ts +84 -0
  39. package/src/providers/openai-responses-compat/console/server.ts +127 -0
  40. package/src/providers/openai-responses-compat/index.ts +38 -13
  41. package/src/providers/openai-responses-compat/native.ts +9 -4
  42. package/src/providers/openai-responses-compat/strings.ts +62 -1
  43. package/src/providers/registry.ts +5 -0
  44. package/src/providers/transport/responses-input.ts +59 -10
  45. package/src/web/README.md +11 -6
  46. package/src/web/auth.ts +80 -0
  47. package/src/web/client/console-pages/builtins/llm-settings/panel.ts +5 -4
  48. package/src/web/client/console-pages/builtins/llm-settings/pricing-panel.ts +22 -8
  49. package/src/web/client/console-pages/builtins/llm-settings/strings.ts +6 -8
  50. package/src/web/client/console-pages/host.ts +24 -7
  51. package/src/web/client/core/api.ts +5 -1
  52. package/src/web/client/core/router.ts +15 -0
  53. package/src/web/client/features/core/strings.ts +2 -2
  54. package/src/web/client/features/extensions/index.ts +276 -41
  55. package/src/web/client/features/extensions/strings.ts +84 -10
  56. package/src/web/client/features/feature.ts +2 -2
  57. package/src/web/client/features/live/diagnostics.ts +32 -0
  58. package/src/web/client/features/live/index.ts +34 -11
  59. package/src/web/client/features/live/onboarding.ts +4 -1
  60. package/src/web/client/features/live/protocol.ts +1 -0
  61. package/src/web/client/features/live/strings.ts +20 -14
  62. package/src/web/client/features/live/timeline.ts +2 -1
  63. package/src/web/client/features/providers/detail.ts +262 -0
  64. package/src/web/client/features/providers/drafts.ts +23 -0
  65. package/src/web/client/features/providers/index.ts +173 -87
  66. package/src/web/client/features/providers/strings.ts +44 -17
  67. package/src/web/client/features/providers/types.ts +15 -0
  68. package/src/web/client/features/settings/general.ts +13 -0
  69. package/src/web/client/features/settings/index.ts +1 -0
  70. package/src/web/client/features/settings/strings.ts +6 -0
  71. package/src/web/client/features/worlds/index.ts +1 -0
  72. package/src/web/client/main.ts +4 -0
  73. package/src/web/client/shell/index.ts +28 -48
  74. package/src/web/client/shell/strings.ts +0 -22
  75. package/src/web/client/ui/icons.ts +14 -1
  76. package/src/web/client/ui/prompt-input.tsx +17 -5
  77. package/src/web/client/ui/strings.ts +0 -2
  78. package/src/web/console-pages.ts +1 -1
  79. package/src/web/diagnostics.ts +133 -0
  80. package/src/web/public/login.html +67 -0
  81. package/src/web/public/styles.css +143 -26
  82. package/src/web/server.ts +233 -19
  83. package/src/web/shared/client-panel.ts +4 -1
  84. package/src/web/shared/console-protocol.ts +4 -1
  85. package/src/worlds/bilibili/README.md +1 -1
  86. package/src/worlds/bilibili/overlay/server.ts +4 -2
  87. package/src/worlds/minecraft/ADAPT.md +66 -0
  88. package/src/worlds/minecraft/README.md +69 -11
  89. package/src/worlds/minecraft/cell-facts.ts +226 -0
  90. package/src/worlds/minecraft/chests.ts +5 -0
  91. package/src/worlds/minecraft/containers.ts +325 -0
  92. package/src/worlds/minecraft/entity-facts.ts +31 -5
  93. package/src/worlds/minecraft/executor.ts +283 -10348
  94. package/src/worlds/minecraft/inventory.ts +268 -0
  95. package/src/worlds/minecraft/melee.ts +419 -0
  96. package/src/worlds/minecraft/mineflayer-fixes.ts +55 -1
  97. package/src/worlds/minecraft/placed-ledger.ts +152 -0
  98. package/src/worlds/minecraft/placement.ts +1038 -0
  99. package/src/worlds/minecraft/receipt.ts +340 -0
  100. package/src/worlds/minecraft/skill-context.ts +358 -0
  101. package/src/worlds/minecraft/skills-build.ts +1169 -0
  102. package/src/worlds/minecraft/skills-container.ts +1343 -0
  103. package/src/worlds/minecraft/skills-craft.ts +333 -0
  104. package/src/worlds/minecraft/skills-dig.ts +624 -0
  105. package/src/worlds/minecraft/skills-gather.ts +1230 -0
  106. package/src/worlds/minecraft/skills-interact.ts +1559 -0
  107. package/src/worlds/minecraft/tools.ts +331 -0
  108. package/src/worlds/minecraft/travel.ts +763 -0
  109. package/src/worlds/minecraft/until.ts +75 -0
  110. package/src/worlds/qq/normalize.ts +14 -0
  111. package/src/worlds/qq/world.ts +53 -7
  112. package/src/worlds/terminal/world.ts +5 -3
@@ -8,7 +8,10 @@
8
8
  * 一律本地换位,原版服务端不换。一次换位两边状态就此分家,之后所有合成都在错的格子上做。
9
9
  *
10
10
  * 光照段随包到来时必须按 nibble 原序落位,prismarine-chunk 把它当长整型数组读了。
11
+ *
12
+ * 水平碰撞停在离方块面 `WALL_GAP` 处:服务端拒绝包围盒恰好贴着方块侧面的位置(见 `installWallGap`)。
11
13
  */
14
+ import { createRequire } from 'node:module';
12
15
  import type { Bot } from 'mineflayer';
13
16
  import type { Logger } from '../../core/types.ts';
14
17
  import type { MinecraftLog } from './log.ts';
@@ -36,6 +39,11 @@ const DIG_CONFIRM_FACTOR = 3;
36
39
  const DIG_GROUND_WAIT_MS = 600;
37
40
  /** 服务端认账比本地定时器晚这么多就记一条:整片挖掘不刷屏,慢的那些留痕 */
38
41
  const DIG_SLOW_ACK_MS = 200;
42
+ /**
43
+ * 水平碰撞停在离方块面这么远的地方。服务端只要缝隙大于零就收(实测 1e-7 也收),
44
+ * 取 1e-5 让坐标到三千万格时的浮点误差也吃不掉它。
45
+ */
46
+ export const WALL_GAP = 1e-5;
39
47
 
40
48
  const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
41
49
 
@@ -136,7 +144,53 @@ export function installMineflayerFixes(
136
144
  installConfirmedCraft(bot, diag, trace, (n) => { tracing += n; }, showTempo);
137
145
  installLightRelay(bot, log, diag);
138
146
  installDismountFix(bot, diag);
139
- log.info(`mineflayer 修补已装上:合成取服务端产物、放置短超时重发、附魔按组件格式计入挖掘、挖掘等服务端改掉那一格、stateId 认当前窗口、光照段重新落位${diag ? '' : '(没给 World 日志,包流不留痕)'}`);
147
+ installWallGap();
148
+ log.info(`mineflayer 修补已装上:合成取服务端产物、放置短超时重发、附魔按组件格式计入挖掘、挖掘等服务端改掉那一格、stateId 认当前窗口、光照段重新落位、水平碰撞留缝${diag ? '' : '(没给 World 日志,包流不留痕)'}`);
149
+ }
150
+
151
+ /** 原型上的标记:同一进程里多个连接、多份模块实例只改一次 */
152
+ const WALL_GAP_MARK = Symbol.for('cortico.minecraft.wallGap');
153
+
154
+ interface PhysicsBox {
155
+ minX: number; minY: number; minZ: number; maxX: number; maxY: number; maxZ: number;
156
+ computeOffsetX(other: PhysicsBox, offset: number): number;
157
+ computeOffsetZ(other: PhysicsBox, offset: number): number;
158
+ }
159
+
160
+ /**
161
+ * 1.21.11 的服务端把「包围盒恰好贴着方块侧面」的位置当成撞进方块:不打 moved wrongly,
162
+ * 静默把人传送回上一个好位置(1.21.10 及更早照收)。prismarine-physics 的碰撞解算恰好停在
163
+ * 贴面处,于是贴墙、上台阶、贴墙起跳每一拍都被打回,人钉在原地。竖直方向贴面照收,这里只改 X/Z:
164
+ * 朝方块走的那一步停在离面 `WALL_GAP` 处;已经贴着(服务端传送来的位置就是贴面的)
165
+ * 再往里走时退开同样的距离。bot 的物理与寻路器的模拟共用这一个类,一处改两处生效。
166
+ */
167
+ export function installWallGap(): void {
168
+ const mfRequire = createRequire(createRequire(import.meta.url).resolve('mineflayer/package.json'));
169
+ const AABB = mfRequire('prismarine-physics/lib/aabb.js') as { prototype: PhysicsBox & { [WALL_GAP_MARK]?: true } };
170
+ const proto = AABB.prototype;
171
+ if (proto[WALL_GAP_MARK]) return;
172
+ // this 是方块的盒子,other 是正在挪的实体的盒子(prismarine-physics 这么调)
173
+ proto.computeOffsetX = function (this: PhysicsBox, other: PhysicsBox, offsetX: number): number {
174
+ if (other.maxY > this.minY && other.minY < this.maxY && other.maxZ > this.minZ && other.minZ < this.maxZ) {
175
+ if (offsetX > 0 && other.maxX <= this.minX + WALL_GAP) {
176
+ offsetX = Math.min(this.minX - other.maxX - WALL_GAP, offsetX);
177
+ } else if (offsetX < 0 && other.minX >= this.maxX - WALL_GAP) {
178
+ offsetX = Math.max(this.maxX - other.minX + WALL_GAP, offsetX);
179
+ }
180
+ }
181
+ return offsetX;
182
+ };
183
+ proto.computeOffsetZ = function (this: PhysicsBox, other: PhysicsBox, offsetZ: number): number {
184
+ if (other.maxX > this.minX && other.minX < this.maxX && other.maxY > this.minY && other.minY < this.maxY) {
185
+ if (offsetZ > 0 && other.maxZ <= this.minZ + WALL_GAP) {
186
+ offsetZ = Math.min(this.minZ - other.maxZ - WALL_GAP, offsetZ);
187
+ } else if (offsetZ < 0 && other.minZ >= this.maxZ - WALL_GAP) {
188
+ offsetZ = Math.max(this.maxZ - other.minZ + WALL_GAP, offsetZ);
189
+ }
190
+ }
191
+ return offsetZ;
192
+ };
193
+ proto[WALL_GAP_MARK] = true;
140
194
  }
141
195
 
142
196
  /**
@@ -0,0 +1,152 @@
1
+ /**
2
+ * 挂在 bot 实例上的几本小账:这一场放过哪些格、锄过哪几格、放了三次还没上去的那些格。
3
+ *
4
+ * 跟着连接走,换实例即清;跨任务跨场次的成果登记在 works.ts。
5
+ */
6
+ import type { Bot } from 'mineflayer';
7
+ import { type SkillCall } from './skills.ts';
8
+ import { type SkillContext } from './skill-context.ts';
9
+ import { type Cell } from './geometry.ts';
10
+ import { blockAtCell, cellKeyOf, dimensionOf } from './cell-facts.ts';
11
+ import { HOE_TILLED } from './blueprint-registry.ts';
12
+ import { zhName } from './names.ts';
13
+ import { FURNACE_BLOCKS } from './chests.ts';
14
+
15
+ /** 这些技能的放置整段是本意,回执自己会说;其余步骤里的放置都是寻路垫脚/搭路 */
16
+ export const INTENTIONAL_PLACERS = new Set<SkillCall['skill']>(['craft', 'use']);
17
+
18
+ export function placedLedgerOf(bot: Bot): Array<{ name: string; x: number; y: number; z: number }> {
19
+ const b = bot as unknown as { placedLedger?: Array<{ name: string; x: number; y: number; z: number }> };
20
+ return (b.placedLedger ??= []);
21
+ }
22
+
23
+ /**
24
+ * 这一场锄成过耕地的那些格(内存,换 bot 实例即清)。
25
+ *
26
+ * 同一格再锄一次成功 = 那块耕地已经被踩回泥土:站在耕地上跳一下 60% 踩坏,
27
+ * 落差 ≥2 格必坏。它是「反复重锄」的成因,不是掉墒。
28
+ */
29
+ export function tilledOf(bot: Bot): Set<string> {
30
+ const b = bot as unknown as { tilledCells?: Set<string> };
31
+ return (b.tilledCells ??= new Set<string>());
32
+ }
33
+
34
+ /**
35
+ * 一次成功的右键落进成果登记:锄成的耕地记这一格,种下的作物记它上面那一格
36
+ * (作物长在耕地上面,不在被点的那一格)。别的右键不进登记。
37
+ */
38
+ export function noteWork(bot: Bot, ctx: SkillContext, item: string | null, cell: Cell, target: string): void {
39
+ if (!ctx.works || item === null) return;
40
+ const dim = dimensionOf(bot);
41
+ if (item.endsWith('_hoe') && HOE_TILLED[target] === 'farmland') {
42
+ ctx.works.note(dim, cell.x, cell.y, cell.z, { kind: 'farmland', block: 'farmland', site: null });
43
+ return;
44
+ }
45
+ const crop = SEED_CROP[item] ?? (item === 'nether_wart' ? 'nether_wart' : undefined);
46
+ if (crop !== undefined) {
47
+ ctx.works.note(dim, cell.x, cell.y + 1, cell.z, { kind: 'crop', block: crop, site: null });
48
+ }
49
+ }
50
+
51
+ /** 这一场上次真吃进去的时刻(内存,换 bot 实例即清);`[口粮]` 那行的四个数之一 */
52
+ export function lastAteOf(bot: Bot): number | null {
53
+ return (bot as unknown as { lastAteAt?: number }).lastAteAt ?? null;
54
+ }
55
+
56
+ export function noteAte(bot: Bot): void {
57
+ (bot as unknown as { lastAteAt?: number }).lastAteAt = Date.now();
58
+ }
59
+
60
+ /** 记下这一格锄成了耕地;记过一次的补一句事实,不拦 */
61
+ export function noteTilled(bot: Bot, cell: Cell): string {
62
+ const key = `${dimensionOf(bot)}:${cellKeyOf(cell)}`;
63
+ const seen = tilledOf(bot);
64
+ if (!seen.has(key)) {
65
+ seen.add(key);
66
+ return '';
67
+ }
68
+ return ';这格之前翻过,是被踩回泥土的;种上作物或别在上面跳';
69
+ }
70
+
71
+ /** 放了三次回读还是老样子的那些格(mineflayer-fixes 记的另一半台账) */
72
+ export function placeMissesOf(bot: Bot): Array<{ was: string; x: number; y: number; z: number }> {
73
+ const b = bot as unknown as { placeMisses?: Array<{ was: string; x: number; y: number; z: number }> };
74
+ return (b.placeMisses ??= []);
75
+ }
76
+
77
+ /** 一步开工时两本台账各记到哪一条:回执报的是这一步之内的那一段 */
78
+ export interface PlaceMarks { placed: number; missed: number }
79
+
80
+ export function placeMarksOf(bot: Bot): PlaceMarks {
81
+ return { placed: placedLedgerOf(bot).length, missed: placeMissesOf(bot).length };
82
+ }
83
+
84
+ /** 从寻路耗材台账摘除技能有意放置的格,由该技能回报;同一步的其他垫脚仍记耗材。 */
85
+ export function forgetPlaced(bot: Bot, at: { x: number; y: number; z: number }): void {
86
+ const ledger = placedLedgerOf(bot);
87
+ for (let i = ledger.length - 1; i >= 0; i--) {
88
+ if (ledger[i].x === at.x && ledger[i].y === at.y && ledger[i].z === at.z) {
89
+ ledger.splice(i, 1);
90
+ return;
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * 回报寻路垫脚的成功与未确认放置;服务端拒绝放置时客户端仍可能扣物品。
97
+ * 成功项按 INTENTIONAL_PLACERS 与 intended 豁免,未确认项只豁免逐格回报的 build。
98
+ * 寻路承重失败另由 pathSupportFailure 裁决。
99
+ */
100
+ export function placedNote(
101
+ bot: Bot, mark: PlaceMarks, skill: SkillCall['skill'], intended: ReadonlySet<string>,
102
+ ): string {
103
+ const placed = INTENTIONAL_PLACERS.has(skill)
104
+ ? []
105
+ : placedLedgerOf(bot).slice(mark.placed).filter((p) => !intended.has(cellKeyOf(p)));
106
+ const missed = skill === 'build' ? [] : placeMissesOf(bot).slice(mark.missed);
107
+ let out = '';
108
+ if (placed.length > 0) {
109
+ const byName = new Map<string, number>();
110
+ for (const p of placed) byName.set(p.name, (byName.get(p.name) ?? 0) + 1);
111
+ const last = placed[placed.length - 1];
112
+ out += `;路上垫脚/搭路用掉了 ${[...byName].map(([n, c]) => `${zhName(n)}×${c}`).join('、')}` +
113
+ `(最后一块在 (${last.x}, ${last.y}, ${last.z}))`;
114
+ }
115
+ if (missed.length > 0) {
116
+ const last = missed[missed.length - 1];
117
+ out += `;路上还有 ${missed.length} 次放置服务端没认` +
118
+ `(最后一次在 (${last.x}, ${last.y}, ${last.z}),那一格还是${zhName(last.was)})`;
119
+ }
120
+ return out;
121
+ }
122
+
123
+ /** 这一格是不是账本上还记着有东西的容器;是就给出一句点名现场事实(tunnel 停步用) */
124
+ export function ledgerBlockFact(bot: Bot, ctx: SkillContext, c: Cell): string | null {
125
+ const rec = ctx.chests?.get(dimensionOf(bot), c);
126
+ if (!rec || rec.items.length === 0) return null;
127
+ const b = blockAtCell(bot, c);
128
+ if (!b || !LEDGER_GUARD_BLOCKS.has(b.name)) return null;
129
+ const inside = rec.items.slice(0, 3).map((i) => `${zhName(i.name)}×${i.count}`).join('、');
130
+ return `(${c.x}, ${c.y}, ${c.z}) 的${zhName(b.name)}(账本记着里头有 ${inside})`;
131
+ }
132
+
133
+ /**
134
+ * 种子种下去长出来的是哪种作物。**作物在耕地上面那一格**,不在被点的那一格。
135
+ * (把握:前六种确定;torchflower_seeds/pitcher_pod 比较确定。)
136
+ */
137
+ export const SEED_CROP: Record<string, string> = {
138
+ wheat_seeds: 'wheat',
139
+ beetroot_seeds: 'beetroots',
140
+ carrot: 'carrots',
141
+ potato: 'potatoes',
142
+ melon_seeds: 'melon_stem',
143
+ pumpkin_seeds: 'pumpkin_stem',
144
+ torchflower_seeds: 'torchflower_crop',
145
+ pitcher_pod: 'pitcher_crop',
146
+ };
147
+
148
+ /** 账本保护容器:excavate 跳过,tunnel 停步回报;拆除前先取空内容再 collect 点名。 */
149
+ export const LEDGER_GUARD_BLOCKS = new Set<string>([
150
+ ...FURNACE_BLOCKS, 'chest', 'trapped_chest', 'barrel', 'ender_chest', 'crafting_table',
151
+ ]);
152
+