@vxnus/siduri 0.1.10 → 0.1.11

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 (64) hide show
  1. package/README.md +3 -4
  2. package/dist/builtin-manifests.js +2 -2
  3. package/dist/clean-machine-e2e.test.js +1 -1
  4. package/dist/configurators/memory.js +1 -1
  5. package/dist/doctor.d.ts +1 -1
  6. package/dist/doctor.js +24 -0
  7. package/dist/generator.d.ts +0 -1
  8. package/dist/generator.js +16 -67
  9. package/dist/generator.test.js +6 -6
  10. package/dist/index.js +0 -6
  11. package/dist/runtime-parity.test.js +2 -1
  12. package/dist/schema-validator.d.ts +9 -0
  13. package/dist/schema-validator.js +107 -0
  14. package/dist/web-dist/404/index.html +1 -0
  15. package/dist/web-dist/404.html +1 -0
  16. package/dist/web-dist/__next.__PAGE__.txt +35 -0
  17. package/dist/web-dist/__next._full.txt +32 -0
  18. package/dist/web-dist/__next._tree.txt +4 -0
  19. package/dist/web-dist/_next/static/chunks/09y7khbmco_v4.js +1 -0
  20. package/dist/web-dist/_next/static/chunks/0cz1d0mv5g_q7.js +1 -0
  21. package/dist/web-dist/_next/static/chunks/0uwih7sydv413.js +1 -0
  22. package/dist/web-dist/_next/static/chunks/0xhe1hasjan-9.css +1 -0
  23. package/dist/web-dist/_next/static/chunks/1_yae15ffa5f6.js +1 -0
  24. package/dist/web-dist/_next/static/chunks/2_duynll0m51m.js +30 -0
  25. package/dist/web-dist/_next/static/chunks/2kcqevsmv6kh2.js +31 -0
  26. package/dist/web-dist/_next/static/chunks/2s3d1bfr0l4b0.js +1 -0
  27. package/dist/web-dist/_next/static/chunks/32z87id9k6i2z.js +22 -0
  28. package/dist/web-dist/_next/static/chunks/3bx2gs3idjmo1.js +1 -0
  29. package/dist/web-dist/_next/static/chunks/turbopack-3eipe4c-imn5l.js +1 -0
  30. package/dist/web-dist/_next/static/media/apple-icon.2g7-yefdphkmy.png +0 -0
  31. package/dist/web-dist/_next/static/media/favicon.3rlors1ui1gw9.ico +0 -0
  32. package/dist/web-dist/_next/static/media/icon.0580nb9h-ugue.svg +4 -0
  33. package/dist/web-dist/_next/static/pWHUixFDDvANZeAf-shqT/_buildManifest.js +11 -0
  34. package/dist/web-dist/_next/static/pWHUixFDDvANZeAf-shqT/_clientMiddlewareManifest.js +1 -0
  35. package/dist/web-dist/_next/static/pWHUixFDDvANZeAf-shqT/_ssgManifest.js +1 -0
  36. package/dist/web-dist/_not-found/__next._full.txt +17 -0
  37. package/dist/web-dist/_not-found/__next._not-found.__PAGE__.txt +23 -0
  38. package/dist/web-dist/_not-found/__next._tree.txt +3 -0
  39. package/dist/web-dist/_not-found/index.html +1 -0
  40. package/dist/web-dist/_not-found/index.txt +17 -0
  41. package/dist/web-dist/apple-icon.png +0 -0
  42. package/dist/web-dist/apple-touch-icon.png +0 -0
  43. package/dist/web-dist/chat/__next._full.txt +18 -0
  44. package/dist/web-dist/chat/__next._tree.txt +3 -0
  45. package/dist/web-dist/chat/__next.chat.__PAGE__.txt +24 -0
  46. package/dist/web-dist/chat/index.html +1 -0
  47. package/dist/web-dist/chat/index.txt +18 -0
  48. package/dist/web-dist/favicon.ico +0 -0
  49. package/dist/web-dist/favicon.svg +4 -0
  50. package/dist/web-dist/icon.svg +4 -0
  51. package/dist/web-dist/index.html +1 -0
  52. package/dist/web-dist/index.txt +32 -0
  53. package/dist/web-dist/live2d/live2dcubismcore.min.js +9 -0
  54. package/dist/web-dist/logo-circle.png +0 -0
  55. package/dist/web-dist/logo-circle.svg +4 -0
  56. package/dist/web-dist/logo-white.svg +3 -0
  57. package/dist/web-dist/logo.png +0 -0
  58. package/dist/web-dist/logo.svg +3 -0
  59. package/dist/web-dist/operator/__next._full.txt +18 -0
  60. package/dist/web-dist/operator/__next._tree.txt +3 -0
  61. package/dist/web-dist/operator/__next.operator.__PAGE__.txt +24 -0
  62. package/dist/web-dist/operator/index.html +1 -0
  63. package/dist/web-dist/operator/index.txt +18 -0
  64. package/package.json +1 -1
package/README.md CHANGED
@@ -13,15 +13,15 @@ npx @vxnus/siduri create my-companion
13
13
  - **Node.js**: `v20.0.0` or newer
14
14
  - **LLM API Key**: e.g. `OPENROUTER_API_KEY` for Brain organ
15
15
  - **Optional Local Services**:
16
- - **Docker**: For running local PostgreSQL database (`docker compose up -d` / `npm run services:up`) and/or VOICEVOX engine.
17
- - *Non-Docker Alternatives*: Cloud databases (Supabase, Neon) or standalone [VOICEVOX Desktop App](https://voicevox.hiroshiba.jp/).
16
+ - **PostgreSQL**: Required if PostgreSQL memory organ is enabled (local PostgreSQL server or cloud Supabase/Neon).
17
+ - **VOICEVOX**: For voice synthesis (auto-downloaded at runtime by default, or connect to standalone app).
18
18
 
19
19
  ## Features
20
20
 
21
21
  - **Manifest-Driven Organ Discovery**: Dynamically discovers installed `@siduri-x/*` organs and generates custom, standalone ESM instance code.
22
22
  - **Interactive Configuration Wizard**: Model catalog discovery for OpenRouter, manifest inspection for E Knowledge Hub, and guided organ parameters.
23
23
  - **Zero Monolithic Bundling**: Scaffolds standard Node.js ESM projects with explicit dependency trees.
24
- - **Diagnostics (`siduri doctor`)**: Runs environment variable validation, external service checks, database health probes, and organ-specific assertions.
24
+ - **Diagnostics (`siduri doctor`)**: Runs environment variable validation, schema conformance checks, external service checks, database health probes, and organ-specific assertions.
25
25
  - **Database Migrations (`siduri db push`)**: Inspects database-owning organs (such as `@siduri-x/memory`) and executes SQL migrations with SHA-256 integrity checksums.
26
26
 
27
27
  ## CLI Usage
@@ -41,7 +41,6 @@ my-companion/
41
41
  ├── siduri.schema.json # Composed JSON Schema from organ manifests
42
42
  ├── .env.example # Only environment variables required by selected organs
43
43
  ├── README.md # Instance-specific guide
44
- ├── docker-compose.yml # Scaffolds PostgreSQL / VOICEVOX when selected
45
44
  └── src/
46
45
  └── index.js # Direct runtime bootstrapping with explicit organ factories
47
46
  ```
@@ -153,7 +153,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
153
153
  {
154
154
  name: '@siduri-x/hands',
155
155
  organType: 'hands',
156
- version: '1.0.2',
156
+ version: '1.0.4',
157
157
  displayName: 'Hands (MCP Tool Execution)',
158
158
  description: 'Model Context Protocol tool management and cryptographically authorized action execution',
159
159
  entrypoint: './dist/index.js',
@@ -272,7 +272,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
272
272
  {
273
273
  name: '@siduri-x/memory',
274
274
  organType: 'memory',
275
- version: '1.0.6',
275
+ version: '1.0.7',
276
276
  displayName: 'Memory (PostgreSQL FTS Claims)',
277
277
  description: 'Relational semantic claims with Full-Text Search and companion isolation',
278
278
  entrypoint: './dist/index.js',
@@ -92,7 +92,7 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
92
92
  }
93
93
  });
94
94
  test('memory organ tarball packages migrations/001_initial_schema.sql', () => {
95
- const memoryTarPath = node_path_1.default.join(tempPackDir, 'siduri-x-memory-1.0.4.tgz');
95
+ const memoryTarPath = getTarPath('@siduri-x/memory');
96
96
  const listing = (0, node_child_process_1.execSync)(`tar -tzf ${memoryTarPath}`, { encoding: 'utf8' });
97
97
  expect(listing).toContain('package/migrations/001_initial_schema.sql');
98
98
  });
@@ -21,7 +21,7 @@ async function configureMemory(_context) {
21
21
  choices: [
22
22
  { name: 'Supabase (Hosted Postgres with connection pooling)', value: 'supabase' },
23
23
  { name: 'Neon (Serverless Postgres with branch-per-companion)', value: 'neon' },
24
- { name: 'Local PostgreSQL (Docker or system service)', value: 'local' },
24
+ { name: 'Local PostgreSQL (System service or local installation)', value: 'local' },
25
25
  { name: 'Other PostgreSQL URL', value: 'other' },
26
26
  ],
27
27
  });
package/dist/doctor.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export interface DoctorCheckResult {
2
- category: 'Environment' | 'Services' | 'Database' | 'Health Probe';
2
+ category: 'Environment' | 'Services' | 'Database' | 'Health Probe' | 'Configuration';
3
3
  name: string;
4
4
  status: 'PASS' | 'FAIL' | 'OPTIONAL_MISSING' | 'SKIPPED';
5
5
  organName?: string;
package/dist/doctor.js CHANGED
@@ -8,6 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const discovery_1 = require("./discovery");
10
10
  const pg_1 = require("pg");
11
+ const schema_validator_1 = require("./schema-validator");
11
12
  async function runDoctor(options = {}) {
12
13
  const projectDir = options.projectDir ? node_path_1.default.resolve(options.projectDir) : process.cwd();
13
14
  const configPath = node_path_1.default.join(projectDir, 'siduri.config.json');
@@ -46,6 +47,29 @@ async function runDoctor(options = {}) {
46
47
  ]);
47
48
  const selectedManifests = [];
48
49
  const results = [];
50
+ // 0. Schema Validation Check
51
+ const schemaPath = node_path_1.default.join(projectDir, 'siduri.schema.json');
52
+ if (node_fs_1.default.existsSync(schemaPath)) {
53
+ try {
54
+ const schema = JSON.parse(node_fs_1.default.readFileSync(schemaPath, 'utf8'));
55
+ (0, schema_validator_1.validateCompanionConfig)(config, schema);
56
+ results.push({
57
+ category: 'Configuration',
58
+ name: 'Schema Conformance',
59
+ status: 'PASS',
60
+ message: 'siduri.config.json conforms to siduri.schema.json',
61
+ });
62
+ }
63
+ catch (err) {
64
+ results.push({
65
+ category: 'Configuration',
66
+ name: 'Schema Conformance',
67
+ status: 'FAIL',
68
+ message: err.message,
69
+ remediation: 'Update siduri.config.json to conform to the generated schema.',
70
+ });
71
+ }
72
+ }
49
73
  // 1. Resolve manifests for selected organs
50
74
  for (const organKey of organKeys) {
51
75
  const m = registry.get(organKey) || registry.getAll().find((item) => item.configKey === organKey || item.organType === organKey);
@@ -7,7 +7,6 @@ export interface GeneratedInstanceFiles {
7
7
  'README.md': string;
8
8
  'src/index.js': string;
9
9
  'public/index.html': string;
10
- 'docker-compose.yml'?: string;
11
10
  createAssetsBodyDir?: boolean;
12
11
  createAssetsDirs?: string[];
13
12
  }
package/dist/generator.js CHANGED
@@ -72,7 +72,7 @@ function getDefaultConfigForManifest(manifest) {
72
72
  function generateInstanceFiles(options) {
73
73
  const instanceName = options.name || 'my-siduri';
74
74
  const instanceId = options.id || 'default';
75
- const coreVersion = options.coreVersion || '^1.0.8';
75
+ const coreVersion = options.coreVersion || '^1.0.9';
76
76
  const manifests = options.selectedManifests;
77
77
  const hasMemory = manifests.some((m) => m.organType === 'memory');
78
78
  const hasVoice = manifests.some((m) => m.organType === 'voice');
@@ -82,56 +82,7 @@ function generateInstanceFiles(options) {
82
82
  const isVoicevox = hasVoice && (!voiceConfig || voiceConfig.provider === 'voicevox');
83
83
  const memoryConfig = options.organConfigs?.memory || options.organConfigs?.['@siduri-x/memory'];
84
84
  const isPostgresLocal = hasMemory && (!memoryConfig || memoryConfig.deployment === 'local' || memoryConfig.provider === 'postgres');
85
- // 1. Optional docker-compose.yml
86
- let dockerComposeYaml;
87
- const dockerServices = [];
88
- const dockerVolumes = [];
89
- if (hasMemory && isPostgresLocal) {
90
- dockerServices.push([
91
- ' db:',
92
- ' image: postgres:15',
93
- ' environment:',
94
- ' POSTGRES_USER: postgres',
95
- ' POSTGRES_PASSWORD: password',
96
- ' POSTGRES_DB: siduri',
97
- ' ports:',
98
- ' - "5432:5432"',
99
- ' volumes:',
100
- ' - postgres_data:/var/lib/postgresql/data',
101
- ' healthcheck:',
102
- ' test: ["CMD-SHELL", "pg_isready -U postgres"]',
103
- ' interval: 2s',
104
- ' timeout: 5s',
105
- ' retries: 5',
106
- ].join('\n'));
107
- dockerVolumes.push(' postgres_data:');
108
- }
109
- if (hasVoice && voiceConfig?.rvc?.enabled) {
110
- dockerServices.push([
111
- ' rvc:',
112
- ' image: ghcr.io/vxnus-studio/rvc-headless:latest',
113
- ' ports:',
114
- ' - "50055:50055"',
115
- ' volumes:',
116
- ' - ./assets/voice:/app/models',
117
- ' environment:',
118
- ' - RVC_MODELS_DIR=/app/models',
119
- ].join('\n'));
120
- }
121
- if (dockerServices.length > 0) {
122
- const composeLines = [
123
- 'version: "3.8"',
124
- '',
125
- 'services:',
126
- ...dockerServices,
127
- ];
128
- if (dockerVolumes.length > 0) {
129
- composeLines.push('', 'volumes:', ...dockerVolumes);
130
- }
131
- composeLines.push('');
132
- dockerComposeYaml = composeLines.join('\n');
133
- }
134
- // 2. package.json
85
+ // 1. package.json
135
86
  const dependencies = {
136
87
  '@siduri-x/core': coreVersion,
137
88
  };
@@ -144,11 +95,6 @@ function generateInstanceFiles(options) {
144
95
  doctor: 'siduri doctor',
145
96
  db: 'siduri db',
146
97
  };
147
- if (dockerComposeYaml) {
148
- scripts['services:up'] = 'docker compose up -d';
149
- scripts['services:down'] = 'docker compose down';
150
- scripts['services:logs'] = 'docker compose logs -f';
151
- }
152
98
  const packageJsonObj = {
153
99
  name: instanceName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'my-siduri',
154
100
  private: true,
@@ -215,7 +161,7 @@ function generateInstanceFiles(options) {
215
161
  `import { readFile, stat, readdir } from 'node:fs/promises';`,
216
162
  `import path from 'node:path';`,
217
163
  `import { fileURLToPath } from 'node:url';`,
218
- `import { SiduriRuntime, dispatchCompanionChat } from '@siduri-x/core';`,
164
+ `import { SiduriRuntime, dispatchCompanionChat, validateCompanionConfig } from '@siduri-x/core';`,
219
165
  ];
220
166
  for (const m of manifests) {
221
167
  importLines.push(`import { ${m.factory} } from '${m.name}';`);
@@ -241,6 +187,16 @@ function generateInstanceFiles(options) {
241
187
  `const config = JSON.parse(`,
242
188
  ` await readFile(path.join(rootDir, 'siduri.config.json'), 'utf8')`,
243
189
  `);`,
190
+ `const schemaPath = path.join(rootDir, 'siduri.schema.json');`,
191
+ `try {`,
192
+ ` const schema = JSON.parse(await readFile(schemaPath, 'utf8'));`,
193
+ ` validateCompanionConfig(config, schema);`,
194
+ `} catch (err) {`,
195
+ ` if (err?.code !== 'ENOENT') {`,
196
+ ` console.error('Config validation failed:', err.message);`,
197
+ ` throw err;`,
198
+ ` }`,
199
+ `}`,
244
200
  '',
245
201
  ...instantiationLines,
246
202
  '',
@@ -621,20 +577,16 @@ function generateInstanceFiles(options) {
621
577
  '- **Environment**: Valid `.env` file (configured from `.env.example`)',
622
578
  ];
623
579
  if (hasMemory) {
624
- readmeLines.push('- **Local Services (Optional)**: Docker (or standalone alternatives):');
625
- readmeLines.push(' - **PostgreSQL**: Required for memory claims & durable state (or use cloud Supabase/Neon)');
580
+ readmeLines.push('- **PostgreSQL (Optional)**: Required if PostgreSQL memory organ is enabled (local PostgreSQL server or cloud Supabase/Neon).');
626
581
  }
627
582
  if (isVoicevox) {
628
583
  readmeLines.push('- **VOICEVOX**: Note: The Voicevox engine executable will be securely auto-downloaded at runtime by Siduri if no local URL is provided.');
629
584
  }
630
585
  readmeLines.push('', '## Getting Started', '', '### 1. Install Dependencies', '```bash', 'npm install', '```', '', '### 2. Configure Environment', '```bash', 'cp .env.example .env', '```', 'Fill in your LLM API key (e.g. `OPENROUTER_API_KEY`) and any other service credentials in `.env`.');
631
- if (dockerComposeYaml) {
632
- readmeLines.push('', '### 3. Start Local Services (Docker)', '```bash', 'npm run services:up', '```', '*(To stop services later, run `npm run services:down`)*');
633
- }
634
586
  if (hasMemory) {
635
- readmeLines.push('', `### ${dockerComposeYaml ? '4' : '3'}. Database Migrations`, 'Ensure `DATABASE_URL` in `.env` is reachable, then push the memory organ PostgreSQL schema:', '```bash', 'npx @vxnus/siduri db push', '```');
587
+ readmeLines.push('', '### 3. Database Migrations', 'Ensure `DATABASE_URL` in `.env` is reachable, then push the memory organ PostgreSQL schema:', '```bash', 'npx @vxnus/siduri db push', '```');
636
588
  }
637
- readmeLines.push('', `### ${hasMemory ? (dockerComposeYaml ? '5' : '4') : (dockerComposeYaml ? '4' : '3')}. Diagnostics & Health Probe`, 'Verify all environment variables, services, and organ connections:', '```bash', 'npm run doctor', '```', '', `### ${hasMemory ? (dockerComposeYaml ? '6' : '5') : (dockerComposeYaml ? '5' : '4')}. Start Companion & Web Console`, 'Launch your companion runtime and Web UI / Memory Control Panel:', '```bash', 'npm start', '```', 'Then open `http://localhost:3000` in your browser.');
589
+ readmeLines.push('', `### ${hasMemory ? '4' : '3'}. Diagnostics & Health Probe`, 'Verify all environment variables, schema conformance, services, and organ connections:', '```bash', 'npm run doctor', '```', '', `### ${hasMemory ? '5' : '4'}. Start Companion & Web Console`, 'Launch your companion runtime and Web UI / Memory Control Panel:', '```bash', 'npm start', '```', 'Then open `http://localhost:3000` in your browser.');
638
590
  const companionSlug = instanceName.toLowerCase().replace(/[^a-z0-9_-]/g, '') || 'default';
639
591
  const createAssetsDirs = [];
640
592
  if (hasBody) {
@@ -659,8 +611,5 @@ function generateInstanceFiles(options) {
659
611
  createAssetsBodyDir: hasBody,
660
612
  createAssetsDirs,
661
613
  };
662
- if (dockerComposeYaml) {
663
- result['docker-compose.yml'] = dockerComposeYaml;
664
- }
665
614
  return result;
666
615
  }
@@ -158,14 +158,13 @@ describe('Instance Generator Composition Invariants (Phase 3)', () => {
158
158
  expect(files['README.md']).toContain('assets/body/companion-full');
159
159
  expect(files['README.md']).toContain('assets/voice/companion-full');
160
160
  expect(files['README.md']).toContain('Prerequisites');
161
- // Docker compose generated for memory (voicevox is auto-downloaded at runtime)
162
- expect(files['docker-compose.yml']).toBeDefined();
163
- expect(files['docker-compose.yml']).toContain('postgres:15');
161
+ // No docker compose generated (Docker completely removed, host-native runtime)
162
+ expect(files['docker-compose.yml']).toBeUndefined();
164
163
  expect(files['README.md']).toContain('Voicevox engine executable will be securely auto-downloaded');
165
- expect(pkg.scripts['services:up']).toBe('docker compose up -d');
166
- expect(pkg.scripts['services:down']).toBe('docker compose down');
164
+ expect(pkg.scripts['services:up']).toBeUndefined();
165
+ expect(pkg.scripts['services:down']).toBeUndefined();
167
166
  });
168
- test('Composition E: Brain only has no docker-compose.yml', () => {
167
+ test('Composition E: Standalone companion never generates docker-compose.yml and validates config', () => {
169
168
  const files = (0, generator_1.generateInstanceFiles)({
170
169
  name: 'brain-solo',
171
170
  selectedManifests: [MOCK_MANIFESTS.brain],
@@ -173,6 +172,7 @@ describe('Instance Generator Composition Invariants (Phase 3)', () => {
173
172
  expect(files['docker-compose.yml']).toBeUndefined();
174
173
  const pkg = JSON.parse(files['package.json']);
175
174
  expect(pkg.scripts['services:up']).toBeUndefined();
175
+ expect(files['src/index.js']).toContain('validateCompanionConfig');
176
176
  expect(files['public/index.html']).toBeDefined();
177
177
  expect(files['public/index.html']).toContain('Memory Console');
178
178
  expect(files['public/index.html']).toContain('Companion Chat');
package/dist/index.js CHANGED
@@ -241,9 +241,6 @@ async function runCreateWizard(targetDir) {
241
241
  else {
242
242
  await (0, promises_1.writeFile)(node_path_1.default.join(publicDir, 'index.html'), files['public/index.html'], 'utf8');
243
243
  }
244
- if (files['docker-compose.yml']) {
245
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'docker-compose.yml'), files['docker-compose.yml'], 'utf8');
246
- }
247
244
  if (files.createAssetsDirs && files.createAssetsDirs.length > 0) {
248
245
  for (const dir of files.createAssetsDirs) {
249
246
  await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, dir), { recursive: true });
@@ -267,9 +264,6 @@ async function runCreateWizard(targetDir) {
267
264
  console.log(`Your Siduri companion is ready! Next steps:\n`);
268
265
  console.log(` cd ${node_path_1.default.relative(process.cwd(), projectDir) || '.'}`);
269
266
  console.log(` cp .env.example .env ${exports.colors.dim}# Fill in required API keys/credentials${exports.colors.reset}`);
270
- if (files['docker-compose.yml']) {
271
- console.log(` npm run services:up ${exports.colors.dim}# Start local Docker services (PostgreSQL / VOICEVOX)${exports.colors.reset}`);
272
- }
273
267
  const hasMemory = selectedManifests.some((m) => m.organType === 'memory');
274
268
  if (hasMemory) {
275
269
  console.log(` npx @vxnus/siduri db push ${exports.colors.dim}# Push PostgreSQL memory schema${exports.colors.reset}`);
@@ -131,7 +131,8 @@ describe('Localweb and CLI Standalone 1:1 Runtime & Chat Parity', () => {
131
131
  });
132
132
  const srcIndexJs = files['src/index.js'];
133
133
  // Ensures single source of truth import
134
- expect(srcIndexJs).toContain("import { SiduriRuntime, dispatchCompanionChat } from '@siduri-x/core';");
134
+ expect(srcIndexJs).toContain("import { SiduriRuntime, dispatchCompanionChat, validateCompanionConfig } from '@siduri-x/core';");
135
+ expect(srcIndexJs).toContain('validateCompanionConfig(config, schema);');
135
136
  // Ensures /chat uses dispatchCompanionChat directly without ad-hoc runtimeResult envelope
136
137
  expect(srcIndexJs).toContain('const response = await dispatchCompanionChat(runtime,');
137
138
  expect(srcIndexJs).toContain('res.end(JSON.stringify(response));');
@@ -0,0 +1,9 @@
1
+ export declare class ConfigValidationError extends Error {
2
+ errors: string[];
3
+ constructor(errors: string[]);
4
+ }
5
+ /**
6
+ * Validates a companion configuration object against a JSON schema (draft-07 compatible).
7
+ * Throws ConfigValidationError if validation errors are detected.
8
+ */
9
+ export declare function validateCompanionConfig(config: unknown, schema: any, path?: string): void;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigValidationError = void 0;
4
+ exports.validateCompanionConfig = validateCompanionConfig;
5
+ class ConfigValidationError extends Error {
6
+ errors;
7
+ constructor(errors) {
8
+ super(`Siduri configuration validation failed:\n${errors.map((e) => ` - ${e}`).join('\n')}`);
9
+ this.name = 'ConfigValidationError';
10
+ this.errors = errors;
11
+ }
12
+ }
13
+ exports.ConfigValidationError = ConfigValidationError;
14
+ /**
15
+ * Validates a companion configuration object against a JSON schema (draft-07 compatible).
16
+ * Throws ConfigValidationError if validation errors are detected.
17
+ */
18
+ function validateCompanionConfig(config, schema, path = '$') {
19
+ const errors = [];
20
+ function validateNode(value, nodeSchema, curPath) {
21
+ if (!nodeSchema || typeof nodeSchema !== 'object')
22
+ return;
23
+ // Type validation
24
+ if (nodeSchema.type !== undefined) {
25
+ const type = nodeSchema.type;
26
+ if (type === 'object') {
27
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
28
+ errors.push(`${curPath}: expected object, received ${value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value}`);
29
+ return;
30
+ }
31
+ }
32
+ else if (type === 'array') {
33
+ if (!Array.isArray(value)) {
34
+ errors.push(`${curPath}: expected array, received ${typeof value}`);
35
+ return;
36
+ }
37
+ }
38
+ else if (type === 'string') {
39
+ if (typeof value !== 'string') {
40
+ errors.push(`${curPath}: expected string, received ${typeof value}`);
41
+ return;
42
+ }
43
+ }
44
+ else if (type === 'number') {
45
+ if (typeof value !== 'number' || Number.isNaN(value)) {
46
+ errors.push(`${curPath}: expected number, received ${typeof value}`);
47
+ return;
48
+ }
49
+ }
50
+ else if (type === 'integer') {
51
+ if (typeof value !== 'number' || !Number.isInteger(value)) {
52
+ errors.push(`${curPath}: expected integer, received ${typeof value}`);
53
+ return;
54
+ }
55
+ }
56
+ else if (type === 'boolean') {
57
+ if (typeof value !== 'boolean') {
58
+ errors.push(`${curPath}: expected boolean, received ${typeof value}`);
59
+ return;
60
+ }
61
+ }
62
+ }
63
+ // Enum validation
64
+ if (Array.isArray(nodeSchema.enum)) {
65
+ if (!nodeSchema.enum.includes(value)) {
66
+ errors.push(`${curPath}: invalid value ${JSON.stringify(value)}, expected one of: ${nodeSchema.enum.map((v) => JSON.stringify(v)).join(', ')}`);
67
+ return;
68
+ }
69
+ }
70
+ // Object properties validation
71
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
72
+ if (Array.isArray(nodeSchema.required)) {
73
+ for (const reqKey of nodeSchema.required) {
74
+ if (value[reqKey] === undefined) {
75
+ errors.push(`${curPath}.${reqKey}: is required`);
76
+ }
77
+ }
78
+ }
79
+ const definedProps = nodeSchema.properties || {};
80
+ if (nodeSchema.additionalProperties === false) {
81
+ for (const key of Object.keys(value)) {
82
+ // Allow $schema property at root level
83
+ if (curPath === '$' && key === '$schema')
84
+ continue;
85
+ if (!(key in definedProps)) {
86
+ errors.push(`${curPath}.${key}: unexpected property is not allowed`);
87
+ }
88
+ }
89
+ }
90
+ for (const [propName, propSchema] of Object.entries(definedProps)) {
91
+ if (value[propName] !== undefined) {
92
+ validateNode(value[propName], propSchema, `${curPath}.${propName}`);
93
+ }
94
+ }
95
+ }
96
+ // Array items validation
97
+ if (Array.isArray(value) && nodeSchema.items) {
98
+ value.forEach((item, index) => {
99
+ validateNode(item, nodeSchema.items, `${curPath}[${index}]`);
100
+ });
101
+ }
102
+ }
103
+ validateNode(config, schema, path);
104
+ if (errors.length > 0) {
105
+ throw new ConfigValidationError(errors);
106
+ }
107
+ }
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html lang="en" class="h-full antialiased dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/0xhe1hasjan-9.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/2kcqevsmv6kh2.js"/><script src="/_next/static/chunks/1_yae15ffa5f6.js" async=""></script><script src="/_next/static/chunks/3bx2gs3idjmo1.js" async=""></script><script src="/_next/static/chunks/32z87id9k6i2z.js" async=""></script><script src="/_next/static/chunks/turbopack-3eipe4c-imn5l.js" async=""></script><script src="/_next/static/chunks/0uwih7sydv413.js" async="" crossorigin=""></script><link rel="preload" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&amp;family=Noto+Sans+JP:wght@400;500;700&amp;family=Noto+Serif+JP:wght@400;500;700&amp;display=swap" as="style"/><meta name="robots" content="noindex"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/><title>404: This page could not be found.</title><title>Siduri — Local-First Companion</title><meta name="description" content="Siduri — a local-first companion with explicit memory, grounded knowledge, and optional presence."/><link rel="icon" href="/favicon.ico?favicon.3rlors1ui1gw9.ico" sizes="256x256" type="image/x-icon"/><link rel="icon" href="/favicon.ico"/><link rel="icon" href="/favicon.svg" type="image/svg+xml"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&amp;family=Noto+Sans+JP:wght@400;500;700&amp;family=Noto+Serif+JP:wght@400;500;700&amp;display=swap" rel="stylesheet"/><script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body class="min-h-full flex flex-col bg-[#0b0b0e] text-[#eee8df] selection:bg-[#d99a68]/30 selection:text-[#f4c28d]"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/2kcqevsmv6kh2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[81869,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"default\"]\n3:I[57830,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"default\"]\n4:I[44101,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n8:I[44101,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"ViewportBoundary\"]\na:I[44101,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"MetadataBoundary\"]\nc:I[4626,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0xhe1hasjan-9.css\",\"style\"]\n:HL[\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500\u0026family=Noto+Sans+JP:wght@400;500;700\u0026family=Noto+Serif+JP:wght@400;500;700\u0026display=swap\",\"style\"]\n7:X\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_not-found\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0xhe1hasjan-9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0uwih7sydv413.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"h-full antialiased dark\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"link\",null,{\"rel\":\"preconnect\",\"href\":\"https://fonts.googleapis.com\"}],[\"$\",\"link\",null,{\"rel\":\"preconnect\",\"href\":\"https://fonts.gstatic.com\",\"crossOrigin\":\"anonymous\"}],[\"$\",\"link\",null,{\"href\":\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500\u0026family=Noto+Sans+JP:wght@400;500;700\u0026family=Noto+Serif+JP:wght@400;500;700\u0026display=swap\",\"rel\":\"stylesheet\"}]]}],[\"$\",\"body\",null,{\"className\":\"min-h-full flex flex-col bg-[#0b0b0e] text-[#eee8df] selection:bg-[#d99a68]/30 selection:text-[#f4c28d]\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,null]},null,false,\"$7\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0xhe1hasjan-9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"pWHUixFDDvANZeAf-shqT\"}\n"])</script><script>self.__next_f.push([1,"7:C\n9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"d:I[89236,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"IconMark\"]\n6:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"Siduri — Local-First Companion\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Siduri — a local-first companion with explicit memory, grounded knowledge, and optional presence.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.3rlors1ui1gw9.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon.svg\",\"type\":\"image/svg+xml\"}],[\"$\",\"link\",\"5\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$Ld\",\"6\",{}]]\n"])</script></body></html>
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html lang="en" class="h-full antialiased dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/0xhe1hasjan-9.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/2kcqevsmv6kh2.js"/><script src="/_next/static/chunks/1_yae15ffa5f6.js" async=""></script><script src="/_next/static/chunks/3bx2gs3idjmo1.js" async=""></script><script src="/_next/static/chunks/32z87id9k6i2z.js" async=""></script><script src="/_next/static/chunks/turbopack-3eipe4c-imn5l.js" async=""></script><script src="/_next/static/chunks/0uwih7sydv413.js" async="" crossorigin=""></script><link rel="preload" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&amp;family=Noto+Sans+JP:wght@400;500;700&amp;family=Noto+Serif+JP:wght@400;500;700&amp;display=swap" as="style"/><meta name="robots" content="noindex"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/><title>404: This page could not be found.</title><title>Siduri — Local-First Companion</title><meta name="description" content="Siduri — a local-first companion with explicit memory, grounded knowledge, and optional presence."/><link rel="icon" href="/favicon.ico?favicon.3rlors1ui1gw9.ico" sizes="256x256" type="image/x-icon"/><link rel="icon" href="/favicon.ico"/><link rel="icon" href="/favicon.svg" type="image/svg+xml"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&amp;family=Noto+Sans+JP:wght@400;500;700&amp;family=Noto+Serif+JP:wght@400;500;700&amp;display=swap" rel="stylesheet"/><script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body class="min-h-full flex flex-col bg-[#0b0b0e] text-[#eee8df] selection:bg-[#d99a68]/30 selection:text-[#f4c28d]"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/2kcqevsmv6kh2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[81869,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"default\"]\n3:I[57830,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"default\"]\n4:I[44101,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n8:I[44101,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"ViewportBoundary\"]\na:I[44101,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"MetadataBoundary\"]\nc:I[4626,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0xhe1hasjan-9.css\",\"style\"]\n:HL[\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500\u0026family=Noto+Sans+JP:wght@400;500;700\u0026family=Noto+Serif+JP:wght@400;500;700\u0026display=swap\",\"style\"]\n7:X\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_not-found\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0xhe1hasjan-9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0uwih7sydv413.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"h-full antialiased dark\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"link\",null,{\"rel\":\"preconnect\",\"href\":\"https://fonts.googleapis.com\"}],[\"$\",\"link\",null,{\"rel\":\"preconnect\",\"href\":\"https://fonts.gstatic.com\",\"crossOrigin\":\"anonymous\"}],[\"$\",\"link\",null,{\"href\":\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500\u0026family=Noto+Sans+JP:wght@400;500;700\u0026family=Noto+Serif+JP:wght@400;500;700\u0026display=swap\",\"rel\":\"stylesheet\"}]]}],[\"$\",\"body\",null,{\"className\":\"min-h-full flex flex-col bg-[#0b0b0e] text-[#eee8df] selection:bg-[#d99a68]/30 selection:text-[#f4c28d]\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,null]},null,false,\"$7\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0xhe1hasjan-9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"pWHUixFDDvANZeAf-shqT\"}\n"])</script><script>self.__next_f.push([1,"7:C\n9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"d:I[89236,[\"/_next/static/chunks/0uwih7sydv413.js\"],\"IconMark\"]\n6:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"Siduri — Local-First Companion\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Siduri — a local-first companion with explicit memory, grounded knowledge, and optional presence.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.3rlors1ui1gw9.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon.svg\",\"type\":\"image/svg+xml\"}],[\"$\",\"link\",\"5\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$Ld\",\"6\",{}]]\n"])</script></body></html>
@@ -0,0 +1,35 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[80413,["/_next/static/chunks/0uwih7sydv413.js","/_next/static/chunks/2s3d1bfr0l4b0.js"],""]
3
+ :HL["/logo-circle.svg","image"]
4
+ c:X
5
+ 0:{"buildId":"pWHUixFDDvANZeAf-shqT","data":[{"rsc":["$","$1","c",{"children":[["$","div",null,{"className":"home-page bg-[#09090c] min-h-screen text-[var(--siduri-text-primary)] font-sans","children":[["$","header",null,{"className":"home-nav","children":["$","div",null,{"className":"home-container home-nav-inner flex items-center justify-between py-4","children":[["$","$L2",null,{"href":"/","className":"brand-link flex items-center gap-2","aria-label":"Siduri Home","children":[["$","img",null,{"src":"/logo-circle.svg","alt":"Siduri-X Logo","className":"w-6 h-6 rounded-full shrink-0","width":24,"height":24}],["$","span",null,{"className":"font-bold tracking-widest text-sm","children":"SIDURI-X"}]]}],["$","nav",null,{"className":"nav-links flex gap-6 text-sm text-[var(--siduri-text-muted)]","aria-label":"Main Navigation","children":[["$","$L2",null,{"href":"/chat","className":"hover:text-[var(--siduri-text-primary)] transition-colors","children":"Chat"}],["$","$L2",null,{"href":"/operator","className":"hover:text-[var(--siduri-text-primary)] transition-colors","children":"Operator Console"}]]}],["$","div",null,{"children":["$","$L2",null,{"href":"/chat","className":"nav-cta inline-flex items-center gap-2 text-xs font-mono border border-[var(--siduri-border-subtle)] px-4 py-2 rounded-full hover:bg-[var(--siduri-surface)] transition-all","children":["Open Chat ",["$","span",null,{"children":"→"}]]}]}]]}]}],["$","main",null,{"children":[["$","section",null,{"className":"py-24 md:py-32 border-b border-[var(--siduri-border-subtle)] relative overflow-hidden","children":["$","div",null,{"className":"home-container relative z-10 text-center flex flex-col items-center","children":[["$","div",null,{"className":"inline-flex items-center gap-2 px-3 py-1 rounded-full border border-[var(--siduri-border-ember)] bg-[var(--siduri-tint-low)] text-[var(--siduri-ember-light)] text-[10px] font-mono tracking-widest uppercase mb-8","children":[["$","span",null,{"className":"w-1.5 h-1.5 rounded-full bg-[var(--siduri-online)] shadow-[0_0_8px_rgba(127,199,154,0.6)]"}],"Standalone Companion Framework · Version 1.0"]}],["$","h1",null,{"className":"text-4xl sm:text-5xl md:text-6xl font-normal font-serif text-[var(--siduri-text-primary)] tracking-tight leading-[1.15] mb-6 max-w-4xl","children":"A companion grown from memory, powered by modular cognition."}],["$","p",null,{"className":"text-base sm:text-lg text-[var(--siduri-text-secondary)] font-sans leading-relaxed mb-10 max-w-2xl font-light","children":"Siduri-X is an intelligent companion designed with authoritative memory, atomic behavioral gating, and a strict 10-organ architecture. She starts as a blank slate and forms her identity entirely through your interactions."}],["$","div",null,{"className":"flex flex-wrap justify-center items-center gap-4","children":[["$","$L2",null,{"href":"/chat","className":"inline-flex items-center gap-3 px-6 py-3.5 rounded-xl bg-[var(--siduri-ember)] text-[#1b1619] font-sans font-semibold text-sm tracking-wide transition-all hover:brightness-110 shadow-[0_4px_20px_rgba(217,154,104,0.2)]","children":["Launch Companion",["$","span",null,{"className":"font-mono text-base","children":"→"}]]}],["$","$L2",null,{"href":"/operator","className":"inline-flex items-center gap-2.5 px-6 py-3.5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] text-[var(--siduri-text-primary)] font-sans font-medium text-sm transition-all hover:border-[var(--siduri-border-ember)] hover:bg-[var(--siduri-tint-low)]","children":[["$","span",null,{"children":"⌘"}],"Operator Console"]}]]}]]}]}],["$","section",null,{"className":"py-20 md:py-28 border-b border-[var(--siduri-border-subtle)] bg-[#0e0e12]","children":["$","div",null,{"className":"home-container","children":[["$","div",null,{"className":"mb-14 text-center max-w-3xl mx-auto","children":[["$","p",null,{"className":"text-[10px] font-mono uppercase tracking-widest text-[var(--siduri-ember)] mb-2","children":"Decoupled Philosophy"}],"$L3","$L4"]}],"$L5"]}]}],"$L6","$L7"]}],"$L8"]}],["$L9"],"$La"]}],"isPartial":"$@b","staleTime":"$c","varyParams":null},{"rsc":"$Ld","isPartial":"$@e","staleTime":"$c","varyParams":null},{"rsc":"$Lf","isPartial":"$@10","staleTime":"$c","varyParams":null}],"isUpgradeableISRFallback":false,"a":"$@11","rootVaryParams":null,"needsRuntimeRequest":"$@12"}
6
+ 16:I[44101,["/_next/static/chunks/0uwih7sydv413.js"],"OutletBoundary"]
7
+ 17:"$Sreact.suspense"
8
+ 19:I[44101,["/_next/static/chunks/0uwih7sydv413.js"],"ViewportBoundary"]
9
+ 1a:I[44101,["/_next/static/chunks/0uwih7sydv413.js"],"MetadataBoundary"]
10
+ 1b:I[89236,["/_next/static/chunks/0uwih7sydv413.js"],"IconMark"]
11
+ 1c:I[81869,["/_next/static/chunks/0uwih7sydv413.js"],"default"]
12
+ 1d:I[57830,["/_next/static/chunks/0uwih7sydv413.js"],"default"]
13
+ :HL["/_next/static/chunks/0xhe1hasjan-9.css","style"]
14
+ :HL["https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Noto+Sans+JP:wght@400;500;700&family=Noto+Serif+JP:wght@400;500;700&display=swap","style"]
15
+ 3:["$","h2",null,{"className":"text-2xl sm:text-3xl font-serif font-normal text-[var(--siduri-text-primary)] mb-4","children":"The 10-Organ Architecture"}]
16
+ 4:["$","p",null,{"className":"text-sm text-[var(--siduri-text-secondary)] leading-relaxed","children":"Siduri is not a chatbot. She is a cognition runtime composed of independent organs. Every decision originates from the Brain, while other organs perceive, remember, act, and embody."}]
17
+ 5:["$","div",null,{"className":"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-4","children":[["$","div","Brain",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Brain"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Cognition, planning, and authoritative decision making."}]]}],["$","div","Memory",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Memory"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"PostgreSQL-backed authoritative storage of claims and preferences."}]]}],["$","div","Behavior",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Behavior"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Atomic directive state machine and personality projection."}]]}],["$","div","Knowledge",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Knowledge"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"External factual context and verifiable E-compatible packs."}]]}],["$","div","Hands",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Hands"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Tool execution and strict cryptographic action policy capabilities."}]]}],["$","div","Ear",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Ear"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Audio transcription, perception, and sensory input ingestion."}]]}],["$","div","Vision",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Vision"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Visual observation, cropping, and OCR interpretation."}]]}],["$","div","Voice",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Voice"}],"$L13"]}],"$L14","$L15"]}]
18
+ 6:["$","section",null,{"className":"py-20 md:py-28 border-b border-[var(--siduri-border-subtle)]","children":["$","div",null,{"className":"home-container grid grid-cols-1 lg:grid-cols-2 gap-16 items-center","children":[["$","div",null,{"children":[["$","p",null,{"className":"text-[10px] font-mono uppercase tracking-widest text-[var(--siduri-ember)] mb-2","children":"Authoritative State"}],["$","h2",null,{"className":"text-3xl font-serif font-normal text-[var(--siduri-text-primary)] mb-5","children":"Blank Slate Identity"}],["$","p",null,{"className":"text-sm text-[var(--siduri-text-secondary)] leading-relaxed mb-6","children":"Unlike standard conversational agents, Siduri starts with no pre-baked persona. She learns, remembers, and adapts over time. When you share preferences, they are staged as structured candidates. You decide what enters her long-term memory with explicit single-click approval."}],["$","ul",null,{"className":"space-y-3 text-xs text-[var(--siduri-text-muted)] font-mono","children":[["$","li",null,{"className":"flex items-center gap-2.5","children":[["$","span",null,{"className":"text-[var(--siduri-online)]","children":"✓"}],"No hidden relationship assumptions"]}],["$","li",null,{"className":"flex items-center gap-2.5","children":[["$","span",null,{"className":"text-[var(--siduri-online)]","children":"✓"}],"Structured episodic and semantic memory"]}],["$","li",null,{"className":"flex items-center gap-2.5","children":[["$","span",null,{"className":"text-[var(--siduri-online)]","children":"✓"}],"Full revocation and override controls"]}]]}]]}],["$","div",null,{"className":"p-8 rounded-2xl border border-[var(--siduri-border-ember)] bg-[var(--siduri-surface)] shadow-[0_10px_35px_rgba(0,0,0,0.4)] relative","children":[["$","div",null,{"className":"absolute top-0 right-8 -translate-y-1/2 bg-[var(--siduri-bg)] px-3 text-[10px] font-mono text-[var(--siduri-ember)] tracking-widest uppercase","children":"Operator View"}],["$","div",null,{"className":"space-y-4 font-mono text-xs","children":["$","div",null,{"className":"p-3 border border-[var(--siduri-border-subtle)] rounded bg-[#13131a]","children":[["$","div",null,{"className":"text-[var(--siduri-text-muted)] mb-1","children":"Incoming Claim"}],["$","div",null,{"className":"text-[var(--siduri-online)] font-bold","children":"\"User prefers concise, technical explanations.\""}],["$","div",null,{"className":"flex gap-2 mt-3","children":[["$","span",null,{"className":"bg-[var(--siduri-online)] text-black px-2 py-0.5 rounded font-bold cursor-pointer","children":"APPROVE"}],["$","span",null,{"className":"border border-[var(--siduri-border-subtle)] text-[var(--siduri-text-muted)] px-2 py-0.5 rounded cursor-pointer","children":"REJECT"}]]}]]}]}]]}]]}]}]
19
+ 7:["$","section",null,{"className":"py-20 md:py-28 bg-[#09090c]","children":["$","div",null,{"className":"home-container text-center max-w-2xl mx-auto","children":[["$","h2",null,{"className":"text-3xl sm:text-4xl font-serif font-normal text-[var(--siduri-text-primary)] mb-5","children":"Private, local, and yours."}],["$","p",null,{"className":"text-sm text-[var(--siduri-text-secondary)] leading-relaxed mb-8","children":"Siduri is designed for local-first operations and explicit consent. The CLI dynamically generates a standalone companion instance leveraging only the organ packages you need. Run it completely on your own machine."}],["$","div",null,{"className":"bg-[#13131a] p-4 rounded-xl border border-[var(--siduri-border-subtle)] inline-block text-left text-sm font-mono text-[var(--siduri-text-primary)] shadow-lg mx-auto","children":[["$","span",null,{"className":"text-emerald-400","children":"$$"}]," npx @vxnus/siduri create my-companion"]}]]}]}]
20
+ 8:["$","footer",null,{"className":"py-14 border-t border-[var(--siduri-border-subtle)] bg-[#0e0e12]","children":["$","div",null,{"className":"home-container flex flex-col sm:flex-row items-center justify-between gap-6","children":[["$","div",null,{"className":"flex items-center gap-3","children":[["$","img",null,{"src":"/logo-circle.svg","alt":"Siduri-X Logo","className":"w-5 h-5 rounded-full shrink-0","width":20,"height":20}],["$","span",null,{"className":"font-bold tracking-widest text-xs text-[var(--siduri-text-primary)]","children":"SIDURI-X"}]]}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-dim)] font-sans text-center sm:text-left","children":"Local-first AI companion framework."}],["$","div",null,{"className":"flex items-center gap-5 text-xs text-[var(--siduri-text-muted)]","children":[["$","$L2",null,{"href":"/chat","className":"hover:text-[var(--siduri-text-primary)]","children":"Chat"}],["$","$L2",null,{"href":"/operator","className":"hover:text-[var(--siduri-text-primary)]","children":"Operator"}]]}]]}]}]
21
+ 9:["$","script","script-0",{"src":"/_next/static/chunks/2s3d1bfr0l4b0.js","async":true}]
22
+ a:["$","$L16",null,{"children":["$","$17",null,{"name":"Next.MetadataOutlet","children":"$@18"}]}]
23
+ d:["$","$1","h",{"children":[null,["$","$L19",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L1a",null,{"children":["$","$17",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"Siduri — Local-First Companion"}],["$","meta","1",{"name":"description","content":"Siduri — a local-first companion with explicit memory, grounded knowledge, and optional presence."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.3rlors1ui1gw9.ico","sizes":"256x256","type":"image/x-icon"}],["$","link","3",{"rel":"icon","href":"/favicon.ico"}],["$","link","4",{"rel":"icon","href":"/favicon.svg","type":"image/svg+xml"}],["$","link","5",{"rel":"apple-touch-icon","href":"/apple-touch-icon.png"}],["$","$L1b","6",{}]]}]}]}],null]}]
24
+ f:["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0xhe1hasjan-9.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/0uwih7sydv413.js","async":true}]],["$","html",null,{"lang":"en","className":"h-full antialiased dark","children":[["$","head",null,{"children":[["$","link",null,{"rel":"preconnect","href":"https://fonts.googleapis.com"}],["$","link",null,{"rel":"preconnect","href":"https://fonts.gstatic.com","crossOrigin":"anonymous"}],["$","link",null,{"href":"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Noto+Sans+JP:wght@400;500;700&family=Noto+Serif+JP:wght@400;500;700&display=swap","rel":"stylesheet"}]]}],["$","body",null,{"className":"min-h-full flex flex-col bg-[#0b0b0e] text-[#eee8df] selection:bg-[#d99a68]/30 selection:text-[#f4c28d]","children":["$","$L1c",null,{"parallelRouterKey":"children","template":["$","$L1d",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]]}]]}]
25
+ 13:["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Queued speech synthesis (Edge-TTS, Piper, VOICEVOX) and auditory expression."}]
26
+ 14:["$","div","Body",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Body"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Renderer-agnostic avatar expression (Live2D) and embodiment."}]]}]
27
+ 15:["$","div","Observation",{"className":"p-5 rounded-xl border border-[var(--siduri-border-subtle)] bg-[var(--siduri-surface)] transition-all hover:border-[var(--siduri-border-ember)]","children":[["$","h3",null,{"className":"text-sm font-bold font-mono text-[var(--siduri-ember-light)] mb-2","children":"Observation"}],["$","p",null,{"className":"text-xs text-[var(--siduri-text-secondary)] leading-relaxed","children":"Event frame deduplication and real-time evidence extraction."}]]}]
28
+ 18:null
29
+ 12:true
30
+ c:300
31
+ c:C
32
+ 11:0
33
+ e:"$undefined"
34
+ 10:"$undefined"
35
+ b:"$undefined"