Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license

This commit is contained in:
2026-09-05 13:26:46 +03:00
commit 03634b1ca3
11340 changed files with 3442369 additions and 0 deletions
@@ -0,0 +1,114 @@
// Interactive Counter — a tldraw offline document script.
//
// HOW TO RUN IT ON YOUR MACHINE:
// 1. Open tldraw offline, create or open a document.
// 2. Develop → Reveal Script… (creates script/main.js + a workspace folder)
// 3. Replace the contents of script/main.js with THIS file, and save.
// 4. The app reruns the script automatically. You'll see a "Counter" panel
// with MINUS / RESET / PLUS buttons — click them; the number updates live.
// 5. File → Save to persist the script into the .tldraw file. Now the file
// *is* a little app: reopen it anywhere and the buttons still work.
//
// This is the document-script contract (from the app's script-context.d.ts):
// export default function ({ editor, helpers, signal }) { ... }
// editor — the live tldraw Editor
// helpers — editor-bound conveniences (richTextToPlainText, etc.)
// signal — an AbortSignal fired before the script reruns / on close;
// register ALL cleanup on it so re-saving never leaks listeners.
import { createShapeId, toRichText } from 'tldraw'
export default function ({ editor, helpers, signal }) {
// Stable ids => idempotent: re-running reuses shapes instead of duplicating.
const IDS = {
title: createShapeId('counter-title'),
display: createShapeId('counter-display'),
dec: createShapeId('counter-btn-dec'),
reset: createShapeId('counter-btn-reset'),
inc: createShapeId('counter-btn-inc'),
}
// Create-if-missing helper (leaves user edits intact on rerun).
function ensure(partial) {
if (editor.getShape(partial.id)) return
editor.createShape(partial)
}
editor.run(() => {
ensure({
id: IDS.title, type: 'text', x: 40, y: 20,
props: { richText: toRichText('Counter'), size: 'xl', font: 'draw', color: 'black' },
})
ensure({
id: IDS.display, type: 'geo', x: 40, y: 80,
props: { geo: 'rectangle', w: 360, h: 160, color: 'black', fill: 'none', richText: toRichText('0'), size: 'xl' },
meta: { ui: 'display', count: 0 },
})
// Button labels are load-bearing — the click handler finds buttons by text.
ensure({
id: IDS.dec, type: 'geo', x: 40, y: 270,
props: { geo: 'rectangle', w: 100, h: 80, color: 'red', fill: 'solid', richText: toRichText('MINUS'), size: 'l' },
meta: { ui: 'button', action: 'MINUS' },
})
ensure({
id: IDS.reset, type: 'geo', x: 170, y: 270,
props: { geo: 'rectangle', w: 100, h: 80, color: 'grey', fill: 'solid', richText: toRichText('RESET'), size: 'l' },
meta: { ui: 'button', action: 'RESET' },
})
ensure({
id: IDS.inc, type: 'geo', x: 300, y: 270,
props: { geo: 'rectangle', w: 100, h: 80, color: 'green', fill: 'solid', richText: toRichText('PLUS'), size: 'l' },
meta: { ui: 'button', action: 'PLUS' },
})
})
const STEP = { MINUS: -1, PLUS: +1 }
function displayShape() {
return editor.getCurrentPageShapes().find((s) => s.meta && s.meta.ui === 'display')
}
function setCount(n) {
const d = displayShape()
editor.run(
() =>
editor.updateShape({
id: d.id, type: 'geo',
props: { richText: toRichText(String(n)) },
meta: { ...d.meta, count: n },
}),
{ history: 'ignore' } // keep script writes out of the user's undo stack
)
}
function runAction(label) {
const d = displayShape()
const cur = d.meta && typeof d.meta.count === 'number' ? d.meta.count : 0
if (label === 'RESET') setCount(0)
else if (label in STEP) setCount(cur + STEP[label])
}
function bounds(s) {
return { x: s.x, y: s.y, w: s.props.w ?? 0, h: s.props.h ?? 0 }
}
function inside(b, p) {
return p.x >= b.x && p.x <= b.x + b.w && p.y >= b.y && p.y <= b.y + b.h
}
function onEvent(info) {
if (!info || info.name !== 'pointer_down') return
let p = null
try {
if (info.point && editor.screenToPage) p = editor.screenToPage(info.point)
} catch {}
p = p ?? editor.inputs?.currentPagePoint
if (!p) return
const hit = editor
.getCurrentPageShapes()
.find((s) => s.meta && s.meta.ui === 'button' && inside(bounds(s), p))
if (hit) runAction(hit.meta.action)
}
editor.on('event', onEvent)
signal.addEventListener('abort', () => editor.off('event', onEvent)) // required cleanup
editor.zoomToFit({ animation: { duration: 200 } })
}
@@ -0,0 +1,78 @@
// tldraw offline — document script (script/main.js)
//
// A document script's default export receives a ctx object and runs whenever the
// document loads (and reruns when you save the script). Contract, verified against
// the app's bundled script-context.d.ts:
//
// export default function ({ editor, helpers, signal }) { ... }
//
// editor — the live tldraw Editor for this document
// helpers — editor-bound conveniences: createShapeIfMissing, createShapesIfMissing,
// createArrowBetweenShapes, translateShapes, onShapeTranslate,
// richTextToPlainText, boxShapes, getLints
// signal — an AbortSignal fired before the script reruns and when the board
// closes. Register ALL cleanup on it (this is how you avoid leaks).
//
// Pure tldraw primitives (createShapeId, toRichText, Vec, ...) are imported from
// the `tldraw` app module — NOT globals. react / react-dom are also importable.
// It is not a Node project; only those modules are available.
import { createShapeId, toRichText } from 'tldraw'
export default function ({ editor, helpers, signal }) {
const { createShapeIfMissing, createArrowBetweenShapes } = helpers
// --- 1. Build durable "furniture" idempotently (stable ids, create-if-missing).
// Re-running the script must NOT duplicate or clobber user edits.
const nodes = [
{ id: createShapeId('node-ui'), x: 0, y: 0, color: 'blue', label: 'CLI / Gateway' },
{ id: createShapeId('node-core'), x: 280, y: 0, color: 'violet', label: 'Agent Core' },
{ id: createShapeId('node-tools'), x: 560, y: 0, color: 'green', label: 'Tools' },
]
editor.run(() => {
for (const n of nodes) {
createShapeIfMissing({
id: n.id,
type: 'geo',
x: n.x,
y: n.y,
props: {
geo: 'rectangle',
w: 220,
h: 110,
color: n.color,
fill: 'solid',
richText: toRichText(n.label),
},
})
}
})
// Connect them (arrows bind to the shapes, so they follow when moved).
createArrowBetweenShapes(nodes[0].id, nodes[1].id, { arrowheadEnd: 'arrow' })
createArrowBetweenShapes(nodes[1].id, nodes[2].id, { arrowheadEnd: 'arrow' })
// --- 2. Add reactive behavior: recolor the last node based on arrow count.
// store.listen fires on the tick AFTER a commit — never read state you just
// wrote synchronously and expect the listener to have run yet.
const targetId = nodes[2].id
function update() {
const hasArrows = editor.getCurrentPageShapes().some((s) => s.type === 'arrow')
editor.run(
() =>
editor.updateShape({
id: targetId,
type: 'geo',
props: { fill: hasArrows ? 'solid' : 'none' },
}),
{ history: 'ignore' } // keep script-owned writes out of the user's undo stack
)
}
const stop = editor.store.listen(update)
signal.addEventListener('abort', () => stop()) // <-- the one required cleanup
update() // run once on load
editor.zoomToFit({ animation: { duration: 200 } })
}
@@ -0,0 +1,65 @@
#!/usr/bin/env node
// validate_shapes.mjs — verify that the note/text/frame records this skill
// documents are valid against the real tldraw SDK v5 schema.
//
// Usage:
// npm install @tldraw/tlschema
// node validate_shapes.mjs
//
// Exits 0 when all sample records validate, 1 otherwise. No network, no DOM.
import { createTLSchema, toRichText, createShapeId, PageRecordType } from '@tldraw/tlschema'
const schema = createTLSchema()
const shapeRecord = schema.types.shape
const pageId = PageRecordType.createId()
// Complete default prop sets (required when building raw records outside the editor).
const COMPLETE = {
note: {
richText: toRichText(''), color: 'black', labelColor: 'black', size: 'm',
font: 'draw', align: 'middle', verticalAlign: 'middle', growY: 0,
fontSizeAdjustment: 0, url: '', scale: 1, textLastEditedBy: '',
},
text: {
richText: toRichText(''), color: 'black', size: 'm', font: 'draw',
textAlign: 'start', w: 8, scale: 1, autoSize: true,
},
frame: { w: 300, h: 640, name: '', color: 'black' },
}
function makeRecord(type, props, meta = {}, x = 0, y = 0) {
return {
id: createShapeId(), typeName: 'shape', type, parentId: pageId, index: 'a1',
x, y, rotation: 0, isLocked: false, opacity: 1, meta,
props: { ...COMPLETE[type], ...props },
}
}
const cases = [
['frame', makeRecord('frame', { w: 300, h: 640, name: 'To Do' }, { role: 'column' })],
['text', makeRecord('text', { richText: toRichText('To Do · WIP 2'), size: 's', color: 'grey', font: 'sans' }, { role: 'count' }, 8, -34)],
['note', makeRecord('note', { richText: toRichText('Design the thing'), size: 's' }, { role: 'card' }, 20, 48)],
]
let ok = 0
const validated = []
for (const [name, rec] of cases) {
try {
validated.push(shapeRecord.validate(rec))
console.log(`OK ${name}`)
ok++
} catch (e) {
console.log(`FAIL ${name}: ${String(e.message).split('\n')[0]}`)
}
}
// Round-trip through JSON to mimic file save/load.
let rok = 0
for (const v of validated) {
try { shapeRecord.validate(JSON.parse(JSON.stringify(v))); rok++ } catch { /* counted below */ }
}
console.log(`\n${ok}/${cases.length} shape records valid against the tldraw schema.`)
console.log(`${rok}/${validated.length} survive a JSON round-trip (file save/load).`)
process.exit(ok === cases.length && rok === validated.length ? 0 : 1)