lightnode-sdk 0.8.1 → 0.8.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.
- package/dist/add.d.ts +1 -1
- package/dist/add.js +139 -72
- package/dist/cli.js +4 -0
- package/package.json +1 -1
package/dist/add.d.ts
CHANGED
|
@@ -119,7 +119,7 @@ export interface LayoutPatch {
|
|
|
119
119
|
* Returns what happened so the CLI can report it; never throws.
|
|
120
120
|
*/
|
|
121
121
|
export declare function patchLayoutWithProviders(cwd?: string): LayoutPatch;
|
|
122
|
-
export declare const SCAFFOLD_GLOBALS_CSS = "@import \"tailwindcss\";\n\n/* dark mode via .dark class (we default the app to dark) */\n@custom-variant dark (&:is(.dark, .dark *));\n\n/* design tokens (light) - ported from lcai-chat-v2 */\n:root {\n font-family: var(--font-inter), ui-sans-serif, system-ui, sans-serif;\n\n --background: #ffffff;\n --primary: #6767e9;\n --primary-600: #5a4fd8;\n --foreground: #09090b;\n --card: #ffffff;\n --card-foreground: #09090b;\n --popover: #ffffff;\n --popover-foreground: hsl(240 10% 3.9%);\n --primary-foreground: #fafafa;\n --secondary: hsl(240 4.8% 95.9%);\n --secondary-foreground: hsl(240 5.9% 10%);\n --muted: hsl(240 4.8% 95.9%);\n --muted-foreground: hsl(240 3.8% 46.1%);\n --accent: hsl(240 4.8% 95.9%);\n --accent-foreground: hsl(240 5.9% 10%);\n --destructive: #ef4d6a;\n --destructive-foreground: hsl(0 0% 98%);\n --success: #15bd77;\n --warning: #eaa53d;\n --border: hsl(240 5.9% 90%);\n --input: hsl(240 5.9% 90%);\n --ring: hsl(240 10% 3.9%);\n --radius: 0.625rem;\n\n --surface-base-subtle: rgba(34, 35, 42, 0.02);\n --surface-base-faint: rgba(14, 18, 27, 0.04);\n --surface-base-light: rgba(204, 206, 239, 0.16);\n --surface-elevation-light: #ffffff;\n\n --content-primary: #0f0f14;\n --content-default: #373842;\n --content-soft: #656678;\n --content-extraLight: #9798b6;\n\n --border-soft: rgba(14, 18, 27, 0.08);\n --border-light: rgba(14, 18, 27, 0.06);\n}\n\n/* design tokens (dark) */\n.dark {\n --background: #070710;\n --foreground: hsl(0 0% 98%);\n --card: #0f0f14;\n --card-foreground: hsl(0 0% 98%);\n --popover: #0f0f14;\n --popover-foreground: hsl(0 0% 98%);\n --primary: #7064e9;\n --primary-600: #8c71f6;\n --primary-foreground: hsl(0 0% 98%);\n --secondary: hsl(240 3.7% 15.9%);\n --secondary-foreground: hsl(0 0% 98%);\n --muted: hsl(240 3.7% 15.9%);\n --muted-foreground: hsl(240 5% 64.9%);\n --accent: hsl(240 3.7% 15.9%);\n --accent-foreground: hsl(0 0% 98%);\n --destructive: #fb5a76;\n --destructive-foreground: hsl(0 0% 98%);\n --success: #22d68a;\n --warning: #f5be5c;\n --border: hsl(240 3.7% 15.9%);\n --input: hsl(240 3.7% 15.9%);\n --ring: hsl(240 4.9% 83.9%);\n\n --surface-base-subtle: rgba(204, 206, 239, 0.02);\n --surface-base-faint: rgba(204, 206, 239, 0.04);\n --surface-base-light: rgba(204, 206, 239, 0.08);\n --surface-elevation-light: #0f0f14;\n\n --content-primary: #cccef0;\n --content-default: #9798b6;\n --content-soft: rgba(154, 156, 207, 0.8);\n --content-extraLight: #9798b6;\n\n --border-soft: rgba(204, 206, 239, 0.12);\n --border-light: rgba(204, 206, 239, 0.08);\n}\n\n/* theme mapping (Tailwind v4 @theme) */\n@theme inline {\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-lg: var(--radius);\n\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-600: var(--primary-600);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-destructive-foreground: var(--destructive-foreground);\n --color-success: var(--success);\n --color-warning: var(--warning);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n\n --color-surface-base-subtle: var(--surface-base-subtle);\n --color-surface-base-faint: var(--surface-base-faint);\n --color-surface-base-light: var(--surface-base-light);\n --color-surface-elevation-light: var(--surface-elevation-light);\n --color-surface-base-brand-default: #693ee0;\n --color-surface-base-brand-strong: #8c71f6;\n\n --color-content-primary: var(--content-primary);\n --color-content-default: var(--content-default);\n --color-content-soft: var(--content-soft);\n --color-content-extraLight: var(--content-extraLight);\n\n --color-bdr-soft: var(--border-soft);\n --color-bdr-light: var(--border-light);\n\n --color-gradient-primary: linear-gradient(270deg, #7064e9 0%, #dd00ac 100%);\n}\n\n@layer base {\n * {\n border-color: var(--border);\n }\n body {\n background-color: var(--background);\n color: var(--foreground);\n overflow-x: hidden;\n }\n html {\n overflow-x: hidden;\n }\n button {\n cursor: pointer;\n }\n button:disabled {\n cursor: not-allowed;\n }\n /* visible keyboard focus across interactive elements */\n a:focus-visible,\n button:focus-visible,\n input:focus-visible,\n select:focus-visible,\n textarea:focus-visible {\n outline: 2px solid var(--primary);\n outline-offset: 2px;\n border-radius: 6px;\n }\n}\n\n/* respect reduced-motion: kill non-essential animation */\n@media (prefers-reduced-motion: reduce) {\n *,\n ::before,\n ::after {\n animation-duration: 0.001ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.001ms !important;\n scroll-behavior: auto !important;\n }\n}\n\n/* ambient app background (gradient mesh behind everything) */\nbody::before {\n content: \"\";\n position: fixed;\n inset: 0;\n z-index: -1;\n pointer-events: none;\n background:\n radial-gradient(60% 50% at 50% -6%, rgba(221, 0, 172, 0.10), transparent 60%),\n radial-gradient(55% 45% at 12% -8%, rgba(112, 100, 233, 0.14), transparent 60%),\n radial-gradient(50% 40% at 88% -2%, rgba(112, 100, 233, 0.12), transparent 60%),\n radial-gradient(45% 45% at 50% 115%, rgba(112, 100, 233, 0.07), transparent 60%);\n}\n.dark body::before {\n background:\n radial-gradient(60% 50% at 50% -6%, rgba(221, 0, 172, 0.12), transparent 60%),\n radial-gradient(55% 45% at 12% -8%, rgba(112, 100, 233, 0.18), transparent 60%),\n radial-gradient(50% 40% at 88% -2%, rgba(112, 100, 233, 0.14), transparent 60%),\n radial-gradient(45% 45% at 50% 118%, rgba(112, 100, 233, 0.10), transparent 60%);\n}\n\n/* minimal scrollbar */\n::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n}\n::-webkit-scrollbar-track {\n background: transparent;\n}\n::-webkit-scrollbar-thumb {\n background: var(--border);\n border-radius: 3px;\n}\n* {\n scrollbar-width: thin;\n scrollbar-color: var(--border) transparent;\n}\n";
|
|
122
|
+
export declare const SCAFFOLD_GLOBALS_CSS = "@import \"tailwindcss\";\n\n/* dark mode via .dark class (we default the app to dark) */\n@custom-variant dark (&:is(.dark, .dark *));\n\n/* design tokens (light) - ported from lcai-chat-v2 */\n:root {\n font-family: var(--font-inter), ui-sans-serif, system-ui, sans-serif;\n\n --background: #ffffff;\n --primary: #6767e9;\n --primary-600: #5a4fd8;\n --foreground: #09090b;\n --card: #ffffff;\n --card-foreground: #09090b;\n --popover: #ffffff;\n --popover-foreground: hsl(240 10% 3.9%);\n --primary-foreground: #fafafa;\n --secondary: hsl(240 4.8% 95.9%);\n --secondary-foreground: hsl(240 5.9% 10%);\n --muted: hsl(240 4.8% 95.9%);\n --muted-foreground: hsl(240 3.8% 46.1%);\n --accent: hsl(240 4.8% 95.9%);\n --accent-foreground: hsl(240 5.9% 10%);\n --destructive: #ef4d6a;\n --destructive-foreground: hsl(0 0% 98%);\n --success: #15bd77;\n --warning: #eaa53d;\n --border: hsl(240 5.9% 90%);\n --input: hsl(240 5.9% 90%);\n --ring: hsl(240 10% 3.9%);\n --radius: 0.625rem;\n\n --surface-base-subtle: rgba(34, 35, 42, 0.02);\n --surface-base-faint: rgba(14, 18, 27, 0.04);\n --surface-base-light: rgba(204, 206, 239, 0.16);\n --surface-elevation-light: #ffffff;\n\n --content-primary: #0f0f14;\n --content-default: #373842;\n --content-soft: #656678;\n --content-extraLight: #9798b6;\n\n --border-soft: rgba(14, 18, 27, 0.08);\n --border-light: rgba(14, 18, 27, 0.06);\n}\n\n/* design tokens (dark) */\n.dark {\n --background: #070710;\n --foreground: hsl(0 0% 98%);\n --card: #0f0f14;\n --card-foreground: hsl(0 0% 98%);\n --popover: #0f0f14;\n --popover-foreground: hsl(0 0% 98%);\n --primary: #7064e9;\n --primary-600: #8c71f6;\n --primary-foreground: hsl(0 0% 98%);\n --secondary: hsl(240 3.7% 15.9%);\n --secondary-foreground: hsl(0 0% 98%);\n --muted: hsl(240 3.7% 15.9%);\n --muted-foreground: hsl(240 5% 64.9%);\n --accent: hsl(240 3.7% 15.9%);\n --accent-foreground: hsl(0 0% 98%);\n --destructive: #fb5a76;\n --destructive-foreground: hsl(0 0% 98%);\n --success: #22d68a;\n --warning: #f5be5c;\n --border: hsl(240 3.7% 15.9%);\n --input: hsl(240 3.7% 15.9%);\n --ring: hsl(240 4.9% 83.9%);\n\n --surface-base-subtle: rgba(204, 206, 239, 0.02);\n --surface-base-faint: rgba(204, 206, 239, 0.04);\n --surface-base-light: rgba(204, 206, 239, 0.08);\n --surface-elevation-light: #0f0f14;\n\n --content-primary: #cccef0;\n --content-default: #9798b6;\n --content-soft: rgba(154, 156, 207, 0.8);\n --content-extraLight: #9798b6;\n\n --border-soft: rgba(204, 206, 239, 0.12);\n --border-light: rgba(204, 206, 239, 0.08);\n}\n\n/* theme mapping (Tailwind v4 @theme) */\n@theme inline {\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-lg: var(--radius);\n\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-600: var(--primary-600);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-destructive-foreground: var(--destructive-foreground);\n --color-success: var(--success);\n --color-warning: var(--warning);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n\n --color-surface-base-subtle: var(--surface-base-subtle);\n --color-surface-base-faint: var(--surface-base-faint);\n --color-surface-base-light: var(--surface-base-light);\n --color-surface-elevation-light: var(--surface-elevation-light);\n --color-surface-base-brand-default: #693ee0;\n --color-surface-base-brand-strong: #8c71f6;\n\n --color-content-primary: var(--content-primary);\n --color-content-default: var(--content-default);\n --color-content-soft: var(--content-soft);\n --color-content-extraLight: var(--content-extraLight);\n\n --color-bdr-soft: var(--border-soft);\n --color-bdr-light: var(--border-light);\n\n --color-gradient-primary: linear-gradient(270deg, #7064e9 0%, #dd00ac 100%);\n}\n\n@layer base {\n * {\n border-color: var(--border);\n }\n body {\n background-color: var(--background);\n color: var(--foreground);\n overflow-x: hidden;\n }\n html {\n overflow-x: hidden;\n }\n button {\n cursor: pointer;\n }\n button:disabled {\n cursor: not-allowed;\n }\n /* visible keyboard focus across interactive elements */\n a:focus-visible,\n button:focus-visible,\n input:focus-visible,\n select:focus-visible,\n textarea:focus-visible {\n outline: 2px solid var(--primary);\n outline-offset: 2px;\n border-radius: 6px;\n }\n}\n\n/* respect reduced-motion: kill non-essential animation */\n@media (prefers-reduced-motion: reduce) {\n *,\n ::before,\n ::after {\n animation-duration: 0.001ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.001ms !important;\n scroll-behavior: auto !important;\n }\n}\n\n/* ambient app background (gradient mesh behind everything) */\nbody::before {\n content: \"\";\n position: fixed;\n inset: 0;\n z-index: -1;\n pointer-events: none;\n background:\n radial-gradient(60% 50% at 50% -6%, rgba(221, 0, 172, 0.10), transparent 60%),\n radial-gradient(55% 45% at 12% -8%, rgba(112, 100, 233, 0.14), transparent 60%),\n radial-gradient(50% 40% at 88% -2%, rgba(112, 100, 233, 0.12), transparent 60%),\n radial-gradient(45% 45% at 50% 115%, rgba(112, 100, 233, 0.07), transparent 60%);\n}\n.dark body::before {\n background:\n radial-gradient(60% 50% at 50% -6%, rgba(221, 0, 172, 0.12), transparent 60%),\n radial-gradient(55% 45% at 12% -8%, rgba(112, 100, 233, 0.18), transparent 60%),\n radial-gradient(50% 40% at 88% -2%, rgba(112, 100, 233, 0.14), transparent 60%),\n radial-gradient(45% 45% at 50% 118%, rgba(112, 100, 233, 0.10), transparent 60%);\n}\n\n/* signature lcai gradient (primary buttons / accents) */\n.bg-gradient-primary {\n background-image: var(--color-gradient-primary);\n}\n.text-gradient {\n background: linear-gradient(94deg, #dd00ac 10%, #7130c3 53%, #7064e9 96%);\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n\n/* minimal scrollbar */\n::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n}\n::-webkit-scrollbar-track {\n background: transparent;\n}\n::-webkit-scrollbar-thumb {\n background: var(--border);\n border-radius: 3px;\n}\n* {\n scrollbar-width: thin;\n scrollbar-color: var(--border) transparent;\n}\n";
|
|
123
123
|
export interface ScaffoldWiring {
|
|
124
124
|
written: WrittenFile[];
|
|
125
125
|
/** The route now also served at `/` (e.g. "/chat-web3"), or null if nothing was wired. */
|
package/dist/add.js
CHANGED
|
@@ -1074,83 +1074,99 @@ export default function ChatWeb3() {
|
|
|
1074
1074
|
}
|
|
1075
1075
|
|
|
1076
1076
|
return (
|
|
1077
|
-
<main
|
|
1078
|
-
<
|
|
1079
|
-
<
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
<div style={{ border: "1px solid #ddd", borderRadius: 8, padding: 12, margin: "12px 0", display: "flex", alignItems: "center", gap: 12 }}>
|
|
1089
|
-
<span>Connect a wallet to start chatting.</span>
|
|
1090
|
-
<ConnectButton />
|
|
1077
|
+
<main className="mx-auto flex min-h-screen w-full max-w-2xl flex-col px-4 py-6">
|
|
1078
|
+
<header className="flex items-center justify-between gap-3 border-b border-border pb-4">
|
|
1079
|
+
<div className="min-w-0">
|
|
1080
|
+
<h1 className="text-base font-semibold text-foreground">Chat</h1>
|
|
1081
|
+
<p className="truncate text-xs text-muted-foreground">
|
|
1082
|
+
{network ? (
|
|
1083
|
+
<>Signed from your wallet on {network} · {feeLcai != null ? feeLcai + " LCAI" : "..."}/turn + gas</>
|
|
1084
|
+
) : (
|
|
1085
|
+
"Connect a wallet on LightChain to start"
|
|
1086
|
+
)}
|
|
1087
|
+
</p>
|
|
1091
1088
|
</div>
|
|
1092
|
-
|
|
1089
|
+
<ConnectButton />
|
|
1090
|
+
</header>
|
|
1093
1091
|
|
|
1094
|
-
<div
|
|
1095
|
-
{turns.
|
|
1096
|
-
<div
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
>
|
|
1106
|
-
<div style={{ whiteSpace: "pre-wrap", wordBreak: "break-word" }}>{t.text}</div>
|
|
1107
|
-
{t.role === "assistant" && t.submitTx ? (
|
|
1108
|
-
<div style={{ marginTop: 6, fontSize: 11, color: "#666", display: "flex", gap: 8, flexWrap: "wrap" }}>
|
|
1109
|
-
{t.worker && (
|
|
1110
|
-
<a href={\`https://\${network}.lightscan.app/address/\${t.worker}\`} target="_blank" rel="noopener noreferrer">
|
|
1111
|
-
worker
|
|
1112
|
-
</a>
|
|
1113
|
-
)}
|
|
1114
|
-
{t.jobId && <span>job #{t.jobId}</span>}
|
|
1115
|
-
{t.submitTx && (
|
|
1116
|
-
<a href={\`https://\${network}.lightscan.app/tx/\${t.submitTx}\`} target="_blank" rel="noopener noreferrer">
|
|
1117
|
-
submitJob
|
|
1118
|
-
</a>
|
|
1119
|
-
)}
|
|
1120
|
-
{t.jobCompletedTx && (
|
|
1121
|
-
<a href={\`https://\${network}.lightscan.app/tx/\${t.jobCompletedTx}\`} target="_blank" rel="noopener noreferrer">
|
|
1122
|
-
completed
|
|
1123
|
-
</a>
|
|
1124
|
-
)}
|
|
1092
|
+
<div className="flex flex-1 flex-col gap-3 overflow-y-auto py-6">
|
|
1093
|
+
{turns.length === 0 ? (
|
|
1094
|
+
<div className="flex flex-1 flex-col items-center justify-center gap-3 text-center">
|
|
1095
|
+
<h2 className="text-2xl font-medium text-foreground">How can I help?</h2>
|
|
1096
|
+
<p className="max-w-sm text-sm text-muted-foreground">
|
|
1097
|
+
Connect your wallet and send a message. Each turn is signed and paid from your
|
|
1098
|
+
own wallet, no backend required.
|
|
1099
|
+
</p>
|
|
1100
|
+
{!address && (
|
|
1101
|
+
<div className="mt-2">
|
|
1102
|
+
<ConnectButton />
|
|
1125
1103
|
</div>
|
|
1126
|
-
)
|
|
1104
|
+
)}
|
|
1127
1105
|
</div>
|
|
1128
|
-
)
|
|
1106
|
+
) : (
|
|
1107
|
+
turns.map((t, i) => (
|
|
1108
|
+
<div
|
|
1109
|
+
key={i}
|
|
1110
|
+
className={
|
|
1111
|
+
"max-w-[85%] whitespace-pre-wrap break-words rounded-2xl px-4 py-2.5 text-sm " +
|
|
1112
|
+
(t.role === "user"
|
|
1113
|
+
? "self-end rounded-br-md bg-primary text-primary-foreground"
|
|
1114
|
+
: "self-start rounded-bl-md border border-border bg-card text-foreground")
|
|
1115
|
+
}
|
|
1116
|
+
>
|
|
1117
|
+
<div>{t.text}</div>
|
|
1118
|
+
{t.role === "assistant" && t.submitTx ? (
|
|
1119
|
+
<div className="mt-2 flex flex-wrap gap-3 text-[11px] text-muted-foreground">
|
|
1120
|
+
{t.worker && (
|
|
1121
|
+
<a className="hover:text-foreground hover:underline" href={\`https://\${network}.lightscan.app/address/\${t.worker}\`} target="_blank" rel="noopener noreferrer">
|
|
1122
|
+
worker
|
|
1123
|
+
</a>
|
|
1124
|
+
)}
|
|
1125
|
+
{t.jobId && <span>job #{t.jobId}</span>}
|
|
1126
|
+
{t.submitTx && (
|
|
1127
|
+
<a className="hover:text-foreground hover:underline" href={\`https://\${network}.lightscan.app/tx/\${t.submitTx}\`} target="_blank" rel="noopener noreferrer">
|
|
1128
|
+
submitJob
|
|
1129
|
+
</a>
|
|
1130
|
+
)}
|
|
1131
|
+
{t.jobCompletedTx && (
|
|
1132
|
+
<a className="hover:text-foreground hover:underline" href={\`https://\${network}.lightscan.app/tx/\${t.jobCompletedTx}\`} target="_blank" rel="noopener noreferrer">
|
|
1133
|
+
completed
|
|
1134
|
+
</a>
|
|
1135
|
+
)}
|
|
1136
|
+
</div>
|
|
1137
|
+
) : null}
|
|
1138
|
+
</div>
|
|
1139
|
+
))
|
|
1140
|
+
)}
|
|
1129
1141
|
</div>
|
|
1130
1142
|
|
|
1131
|
-
<
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1143
|
+
<div className="border-t border-border pt-4">
|
|
1144
|
+
<div className="flex items-end gap-2 rounded-2xl border border-border bg-card p-2 transition focus-within:ring-2 focus-within:ring-primary">
|
|
1145
|
+
<textarea
|
|
1146
|
+
value={input}
|
|
1147
|
+
onChange={(e) => setInput(e.target.value)}
|
|
1148
|
+
onKeyDown={(e) => {
|
|
1149
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); if (!busy && input.trim()) send(); }
|
|
1150
|
+
}}
|
|
1151
|
+
rows={1}
|
|
1152
|
+
placeholder={turns.length === 0 ? "Say hello (cmd+enter to send)" : "Reply... (cmd+enter)"}
|
|
1153
|
+
className="max-h-40 min-h-[40px] flex-1 resize-none bg-transparent px-2 py-2 text-sm text-foreground outline-none placeholder:text-muted-foreground"
|
|
1154
|
+
/>
|
|
1155
|
+
<button
|
|
1156
|
+
type="button"
|
|
1157
|
+
onClick={() => send()}
|
|
1158
|
+
disabled={busy || !input.trim() || !address || !network}
|
|
1159
|
+
className="shrink-0 rounded-xl bg-gradient-primary px-4 py-2 text-sm font-medium text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40"
|
|
1160
|
+
>
|
|
1161
|
+
{busy ? (busyStage || "Sending...") : "Send"}
|
|
1162
|
+
</button>
|
|
1163
|
+
</div>
|
|
1164
|
+
{err && (
|
|
1165
|
+
<p className="mt-2 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">
|
|
1166
|
+
{err}
|
|
1167
|
+
</p>
|
|
1168
|
+
)}
|
|
1169
|
+
</div>
|
|
1154
1170
|
</main>
|
|
1155
1171
|
);
|
|
1156
1172
|
}
|
|
@@ -2268,6 +2284,17 @@ body::before {
|
|
|
2268
2284
|
radial-gradient(45% 45% at 50% 118%, rgba(112, 100, 233, 0.10), transparent 60%);
|
|
2269
2285
|
}
|
|
2270
2286
|
|
|
2287
|
+
/* signature lcai gradient (primary buttons / accents) */
|
|
2288
|
+
.bg-gradient-primary {
|
|
2289
|
+
background-image: var(--color-gradient-primary);
|
|
2290
|
+
}
|
|
2291
|
+
.text-gradient {
|
|
2292
|
+
background: linear-gradient(94deg, #dd00ac 10%, #7130c3 53%, #7064e9 96%);
|
|
2293
|
+
-webkit-background-clip: text;
|
|
2294
|
+
background-clip: text;
|
|
2295
|
+
color: transparent;
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2271
2298
|
/* minimal scrollbar */
|
|
2272
2299
|
::-webkit-scrollbar {
|
|
2273
2300
|
width: 6px;
|
|
@@ -2344,6 +2371,44 @@ function setDarkDefaultOnLayout(cwd) {
|
|
|
2344
2371
|
}
|
|
2345
2372
|
return true;
|
|
2346
2373
|
}
|
|
2374
|
+
/** One-line description of what each scaffold target gives the dev. */
|
|
2375
|
+
const SCAFFOLD_README_WHAT = {
|
|
2376
|
+
"chat-web3": "A self-contained, wallet-signed chat you can drop into any project - for example, to give an agent a chat UI.",
|
|
2377
|
+
"inference-web3": "A self-contained, wallet-signed one-shot inference page you can drop into any project.",
|
|
2378
|
+
"judge-web3": "A self-contained, wallet-signed pass/fail evaluator page you can drop into any project.",
|
|
2379
|
+
};
|
|
2380
|
+
/** A real README for a freshly scaffolded app, replacing the create-next-app
|
|
2381
|
+
* default so the dev knows what they got and how to use it. */
|
|
2382
|
+
function scaffoldReadme(target, dir) {
|
|
2383
|
+
const what = SCAFFOLD_README_WHAT[target] ?? "A self-contained, wallet-signed page.";
|
|
2384
|
+
return `# LightNode ${dir}
|
|
2385
|
+
|
|
2386
|
+
Generated by \`lightnode add ${target}\`. ${what}
|
|
2387
|
+
No backend, no database, no API keys: each visitor signs and pays for their own
|
|
2388
|
+
turns from their own wallet on LightChain.
|
|
2389
|
+
|
|
2390
|
+
## Run it
|
|
2391
|
+
|
|
2392
|
+
npm run dev
|
|
2393
|
+
|
|
2394
|
+
Open http://localhost:3000 and click **Connect wallet** (LightChain mainnet
|
|
2395
|
+
9200 or testnet 8200). Free testnet LCAI: https://lightfaucet.ai
|
|
2396
|
+
|
|
2397
|
+
## Where things live
|
|
2398
|
+
|
|
2399
|
+
- \`app/page.tsx\` - re-exports the page below as the homepage
|
|
2400
|
+
- \`app/${dir}/page.tsx\` - the UI (also served at /${dir}). Edit this.
|
|
2401
|
+
- \`app/providers.tsx\` + \`lib/wagmi.ts\` - wagmi + React Query setup
|
|
2402
|
+
- \`components/connect-button.tsx\` - the Connect wallet button
|
|
2403
|
+
- \`app/globals.css\` - the theme (light + dark design tokens)
|
|
2404
|
+
|
|
2405
|
+
## Customize
|
|
2406
|
+
|
|
2407
|
+
It is a normal React client component using \`lightnode-sdk\` wired to the
|
|
2408
|
+
connected wallet. Change the model or system prompt, restyle it, or call it
|
|
2409
|
+
from your own agent. Builder docs: https://lightnode.app/build
|
|
2410
|
+
`;
|
|
2411
|
+
}
|
|
2347
2412
|
/**
|
|
2348
2413
|
* Wire a freshly scaffolded Next.js app so the generated -web3 page is the
|
|
2349
2414
|
* homepage and the LightChain theme + dark default are in place. No-op for any
|
|
@@ -2359,7 +2424,9 @@ export function wireFreshScaffold(target, opts = {}) {
|
|
|
2359
2424
|
written.push(writeFile(path.join(cwd, "app/globals.css"), SCAFFOLD_GLOBALS_CSS, true));
|
|
2360
2425
|
// 2. Make the generated page the homepage (replaces the starter page.tsx).
|
|
2361
2426
|
written.push(writeFile(path.join(cwd, "app/page.tsx"), homepageReexport(dir, target), true));
|
|
2362
|
-
// 3.
|
|
2427
|
+
// 3. Replace create-next-app's default README with one about this scaffold.
|
|
2428
|
+
written.push(writeFile(path.join(cwd, "README.md"), scaffoldReadme(target, dir), true));
|
|
2429
|
+
// 4. Keep dark as the default theme (matches lightnode.app).
|
|
2363
2430
|
const darkDefault = setDarkDefaultOnLayout(cwd);
|
|
2364
2431
|
return { written, homepageRoute: `/${dir}`, darkDefault };
|
|
2365
2432
|
}
|
package/dist/cli.js
CHANGED
|
@@ -47,6 +47,10 @@ function scaffoldNextApp(cwd, target) {
|
|
|
47
47
|
"--yes", "create-next-app@latest", stageName,
|
|
48
48
|
"--ts", "--app", "--no-src-dir", "--eslint", "--tailwind",
|
|
49
49
|
"--use-npm", "--no-turbopack", "--import-alias", "@/*",
|
|
50
|
+
// Don't dump create-next-app's AGENTS.md (the nextjs-agent-rules block)
|
|
51
|
+
// into the user's project. Supported by current create-next-app, which is
|
|
52
|
+
// what `@latest` resolves to here.
|
|
53
|
+
"--no-agents-md",
|
|
50
54
|
];
|
|
51
55
|
const r = spawnSync("npx", args, { cwd, stdio: "inherit" });
|
|
52
56
|
if (r.status !== 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightnode-sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Read-only TypeScript client for LightChain AI: workers, jobs, models, on-chain registration, and per-model network analytics. Independent, community-built (not an official LightChain package).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|