infinicode 1.0.0 → 2.1.0

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 (159) hide show
  1. package/.opencode/plugins/home-logo-animation.tsx +120 -0
  2. package/.opencode/plugins/routing-mode-display.tsx +135 -0
  3. package/.opencode/themes/infinibot-gold.json +222 -0
  4. package/.opencode/tui.json +8 -0
  5. package/README.md +564 -72
  6. package/dist/ascii-video-animation.d.ts +2 -0
  7. package/dist/ascii-video-animation.js +243 -0
  8. package/dist/cli.js +199 -50
  9. package/dist/commands/console.d.ts +6 -0
  10. package/dist/commands/console.js +111 -0
  11. package/dist/commands/kernel-setup.d.ts +3 -0
  12. package/dist/commands/kernel-setup.js +303 -0
  13. package/dist/commands/mcp.d.ts +14 -0
  14. package/dist/commands/mcp.js +100 -0
  15. package/dist/commands/mission.d.ts +16 -0
  16. package/dist/commands/mission.js +301 -0
  17. package/dist/commands/models.d.ts +3 -1
  18. package/dist/commands/models.js +111 -55
  19. package/dist/commands/providers.d.ts +6 -0
  20. package/dist/commands/providers.js +95 -0
  21. package/dist/commands/run.d.ts +2 -1
  22. package/dist/commands/run.js +349 -59
  23. package/dist/commands/serve.d.ts +20 -0
  24. package/dist/commands/serve.js +132 -0
  25. package/dist/commands/setup.d.ts +1 -1
  26. package/dist/commands/setup.js +77 -44
  27. package/dist/commands/status.d.ts +2 -1
  28. package/dist/commands/status.js +46 -30
  29. package/dist/commands/workers.d.ts +5 -0
  30. package/dist/commands/workers.js +103 -0
  31. package/dist/kernel/autonomy/goal-loop.d.ts +49 -0
  32. package/dist/kernel/autonomy/goal-loop.js +113 -0
  33. package/dist/kernel/autonomy/index.d.ts +8 -0
  34. package/dist/kernel/autonomy/index.js +7 -0
  35. package/dist/kernel/browser/browser-controller.d.ts +57 -0
  36. package/dist/kernel/browser/browser-controller.js +175 -0
  37. package/dist/kernel/checkpoint-engine.d.ts +17 -0
  38. package/dist/kernel/checkpoint-engine.js +128 -0
  39. package/dist/kernel/command-system.d.ts +37 -0
  40. package/dist/kernel/command-system.js +239 -0
  41. package/dist/kernel/config-schema.d.ts +57 -0
  42. package/dist/kernel/config-schema.js +36 -0
  43. package/dist/kernel/event-bus.d.ts +19 -0
  44. package/dist/kernel/event-bus.js +65 -0
  45. package/dist/kernel/federation/auto-update.d.ts +36 -0
  46. package/dist/kernel/federation/auto-update.js +57 -0
  47. package/dist/kernel/federation/compute-router.d.ts +27 -0
  48. package/dist/kernel/federation/compute-router.js +44 -0
  49. package/dist/kernel/federation/config-sync.d.ts +33 -0
  50. package/dist/kernel/federation/config-sync.js +37 -0
  51. package/dist/kernel/federation/discovery.d.ts +11 -0
  52. package/dist/kernel/federation/discovery.js +44 -0
  53. package/dist/kernel/federation/event-bridge.d.ts +30 -0
  54. package/dist/kernel/federation/event-bridge.js +61 -0
  55. package/dist/kernel/federation/federation-plugin.d.ts +24 -0
  56. package/dist/kernel/federation/federation-plugin.js +35 -0
  57. package/dist/kernel/federation/federation.d.ts +135 -0
  58. package/dist/kernel/federation/federation.js +378 -0
  59. package/dist/kernel/federation/index.d.ts +33 -0
  60. package/dist/kernel/federation/index.js +24 -0
  61. package/dist/kernel/federation/lan-discovery.d.ts +43 -0
  62. package/dist/kernel/federation/lan-discovery.js +135 -0
  63. package/dist/kernel/federation/moltfed-adapter.d.ts +30 -0
  64. package/dist/kernel/federation/moltfed-adapter.js +52 -0
  65. package/dist/kernel/federation/moltfed-connector.d.ts +98 -0
  66. package/dist/kernel/federation/moltfed-connector.js +193 -0
  67. package/dist/kernel/federation/node-identity.d.ts +19 -0
  68. package/dist/kernel/federation/node-identity.js +86 -0
  69. package/dist/kernel/federation/peer-mesh.d.ts +46 -0
  70. package/dist/kernel/federation/peer-mesh.js +117 -0
  71. package/dist/kernel/federation/protocol.d.ts +20 -0
  72. package/dist/kernel/federation/protocol.js +61 -0
  73. package/dist/kernel/federation/role-context.d.ts +5 -0
  74. package/dist/kernel/federation/role-context.js +45 -0
  75. package/dist/kernel/federation/telemetry.d.ts +21 -0
  76. package/dist/kernel/federation/telemetry.js +138 -0
  77. package/dist/kernel/federation/transport-http.d.ts +44 -0
  78. package/dist/kernel/federation/transport-http.js +207 -0
  79. package/dist/kernel/federation/types.d.ts +212 -0
  80. package/dist/kernel/federation/types.js +3 -0
  81. package/dist/kernel/free-providers.d.ts +28 -0
  82. package/dist/kernel/free-providers.js +162 -0
  83. package/dist/kernel/frontend-scoring.d.ts +21 -0
  84. package/dist/kernel/frontend-scoring.js +125 -0
  85. package/dist/kernel/index.d.ts +63 -0
  86. package/dist/kernel/index.js +45 -0
  87. package/dist/kernel/kernel.d.ts +75 -0
  88. package/dist/kernel/kernel.js +223 -0
  89. package/dist/kernel/logger.d.ts +18 -0
  90. package/dist/kernel/logger.js +26 -0
  91. package/dist/kernel/mcp/index.d.ts +9 -0
  92. package/dist/kernel/mcp/index.js +8 -0
  93. package/dist/kernel/mcp/mcp-server.d.ts +27 -0
  94. package/dist/kernel/mcp/mcp-server.js +178 -0
  95. package/dist/kernel/mission-engine.d.ts +42 -0
  96. package/dist/kernel/mission-engine.js +160 -0
  97. package/dist/kernel/orchestrator.d.ts +51 -0
  98. package/dist/kernel/orchestrator.js +226 -0
  99. package/dist/kernel/plugin-manager.d.ts +28 -0
  100. package/dist/kernel/plugin-manager.js +76 -0
  101. package/dist/kernel/plugins/browser-plugin.d.ts +22 -0
  102. package/dist/kernel/plugins/browser-plugin.js +34 -0
  103. package/dist/kernel/plugins/dashboard-plugin.d.ts +17 -0
  104. package/dist/kernel/plugins/dashboard-plugin.js +72 -0
  105. package/dist/kernel/plugins/discord-plugin.d.ts +11 -0
  106. package/dist/kernel/plugins/discord-plugin.js +35 -0
  107. package/dist/kernel/plugins/metrics-plugin.d.ts +33 -0
  108. package/dist/kernel/plugins/metrics-plugin.js +86 -0
  109. package/dist/kernel/plugins/search-plugin.d.ts +17 -0
  110. package/dist/kernel/plugins/search-plugin.js +20 -0
  111. package/dist/kernel/plugins/slack-plugin.d.ts +11 -0
  112. package/dist/kernel/plugins/slack-plugin.js +35 -0
  113. package/dist/kernel/plugins/telegram-plugin.d.ts +20 -0
  114. package/dist/kernel/plugins/telegram-plugin.js +122 -0
  115. package/dist/kernel/policies.d.ts +33 -0
  116. package/dist/kernel/policies.js +105 -0
  117. package/dist/kernel/provider-discovery.d.ts +41 -0
  118. package/dist/kernel/provider-discovery.js +179 -0
  119. package/dist/kernel/provider-manager.d.ts +38 -0
  120. package/dist/kernel/provider-manager.js +206 -0
  121. package/dist/kernel/provider-url.d.ts +18 -0
  122. package/dist/kernel/provider-url.js +45 -0
  123. package/dist/kernel/providers/gemini-provider.d.ts +43 -0
  124. package/dist/kernel/providers/gemini-provider.js +203 -0
  125. package/dist/kernel/providers/ollama-provider.d.ts +44 -0
  126. package/dist/kernel/providers/ollama-provider.js +241 -0
  127. package/dist/kernel/providers/openai-compatible-provider.d.ts +43 -0
  128. package/dist/kernel/providers/openai-compatible-provider.js +233 -0
  129. package/dist/kernel/recovery-manager.d.ts +38 -0
  130. package/dist/kernel/recovery-manager.js +156 -0
  131. package/dist/kernel/router.d.ts +44 -0
  132. package/dist/kernel/router.js +222 -0
  133. package/dist/kernel/sample-missions.d.ts +11 -0
  134. package/dist/kernel/sample-missions.js +132 -0
  135. package/dist/kernel/scheduler.d.ts +30 -0
  136. package/dist/kernel/scheduler.js +147 -0
  137. package/dist/kernel/sdk/harness-sdk.d.ts +37 -0
  138. package/dist/kernel/sdk/harness-sdk.js +48 -0
  139. package/dist/kernel/sdk/plugin-sdk.d.ts +27 -0
  140. package/dist/kernel/sdk/plugin-sdk.js +40 -0
  141. package/dist/kernel/search/search-controller.d.ts +32 -0
  142. package/dist/kernel/search/search-controller.js +141 -0
  143. package/dist/kernel/setup.d.ts +13 -0
  144. package/dist/kernel/setup.js +59 -0
  145. package/dist/kernel/types.d.ts +479 -0
  146. package/dist/kernel/types.js +7 -0
  147. package/dist/kernel/verification-engine.d.ts +33 -0
  148. package/dist/kernel/verification-engine.js +287 -0
  149. package/dist/kernel/worker-runtime.d.ts +66 -0
  150. package/dist/kernel/worker-runtime.js +261 -0
  151. package/dist/kernel/workers/browser-worker.d.ts +6 -0
  152. package/dist/kernel/workers/browser-worker.js +92 -0
  153. package/dist/kernel/workers/builtin-workers.d.ts +20 -0
  154. package/dist/kernel/workers/builtin-workers.js +120 -0
  155. package/dist/kernel/workers/research-worker.d.ts +5 -0
  156. package/dist/kernel/workers/research-worker.js +90 -0
  157. package/dist/prompt-ascii-video-animation.d.ts +2 -0
  158. package/dist/prompt-ascii-video-animation.js +243 -0
  159. package/package.json +43 -9
@@ -0,0 +1,92 @@
1
+ import { BrowserController, actionArtifacts, htmlToMarkdown, } from '../browser/browser-controller.js';
2
+ let sharedController;
3
+ let controllerOptions;
4
+ export function setBrowserController(controller) {
5
+ sharedController = controller;
6
+ }
7
+ export function setBrowserControllerOptions(options) {
8
+ controllerOptions = options;
9
+ }
10
+ function getController() {
11
+ if (!sharedController) {
12
+ sharedController = new BrowserController(controllerOptions ?? {});
13
+ }
14
+ return sharedController;
15
+ }
16
+ async function browserExecute(task, provider, model, ctx) {
17
+ const actions = task.input.context?.actions ?? [];
18
+ if (actions.length === 0) {
19
+ // No actions → fall back to LLM planning of browser steps.
20
+ const request = {
21
+ model: model.id,
22
+ systemPrompt: task.input.context?.systemPrompt,
23
+ prompt: task.input.prompt,
24
+ context: task.input.context,
25
+ maxTokens: 4096,
26
+ temperature: 0.3,
27
+ };
28
+ const result = await provider.complete(request);
29
+ const artifacts = result.content
30
+ ? [{ id: `${task.id}-out`, type: 'document', content: result.content, mimeType: 'text/markdown' }]
31
+ : [];
32
+ return {
33
+ content: result.content,
34
+ artifacts,
35
+ providerId: result.providerId,
36
+ modelId: result.modelId,
37
+ tokensIn: result.tokensIn,
38
+ tokensOut: result.tokensOut,
39
+ durationMs: result.durationMs,
40
+ };
41
+ }
42
+ const controller = getController();
43
+ await controller.init();
44
+ const results = [];
45
+ for (const action of actions) {
46
+ const result = await controller.runAction(action);
47
+ results.push(result);
48
+ ctx.logger.info(`Browser action ${action.type}: ${result.ok ? 'ok' : 'FAIL'} ${result.error ?? ''}`);
49
+ if (!result.ok && result.error) {
50
+ // continue collecting results; the LLM judge / recovery will decide
51
+ }
52
+ }
53
+ const text = results.map(r => r.text ?? '').filter(Boolean).join('\n\n');
54
+ const markdown = results.map(r => r.markdown ?? r.text ?? '').filter(Boolean).join('\n\n');
55
+ const artifacts = actionArtifacts(results);
56
+ // Optional LLM summarization of extracted content.
57
+ let summary = markdown || text;
58
+ if (text && text.length > 4000 && provider) {
59
+ try {
60
+ const request = {
61
+ model: model.id,
62
+ systemPrompt: 'Summarize the following browser-extracted content concisely, preserving key facts and any links.',
63
+ prompt: text.slice(0, 12000),
64
+ maxTokens: 1024,
65
+ temperature: 0.2,
66
+ };
67
+ const result = await provider.complete(request);
68
+ summary = result.content || markdown;
69
+ }
70
+ catch {
71
+ // keep raw extraction
72
+ }
73
+ }
74
+ return {
75
+ content: summary,
76
+ artifacts,
77
+ providerId: provider.info.id,
78
+ modelId: model.id,
79
+ tokensIn: 0,
80
+ tokensOut: 0,
81
+ durationMs: 0,
82
+ };
83
+ }
84
+ export function createBrowserWorker() {
85
+ return {
86
+ type: 'browser',
87
+ capabilities: ['browser', 'crawl', 'search', 'reasoning'],
88
+ preferences: { reasoning: 85, speed: 80, contextLength: 32_000 },
89
+ execute: browserExecute,
90
+ };
91
+ }
92
+ export { htmlToMarkdown };
@@ -0,0 +1,20 @@
1
+ import type { WorkerExecuteFn, WorkerHandler } from '../worker-runtime.js';
2
+ export { createResearchWorker } from './research-worker.js';
3
+ export { createBrowserWorker } from './browser-worker.js';
4
+ export declare function createCodingWorker(): WorkerHandler;
5
+ export declare function createArchitectureWorker(): WorkerHandler;
6
+ export declare function createReviewWorker(): WorkerHandler;
7
+ export declare function createDocumentationWorker(): WorkerHandler;
8
+ export declare function createTranslationWorker(): WorkerHandler;
9
+ export declare function createTerminalWorker(): WorkerHandler;
10
+ export declare function createVerificationWorker(): WorkerHandler;
11
+ export declare function createVisionWorker(): WorkerHandler;
12
+ /**
13
+ * Frontend worker — requests strong reasoning + very large context so the
14
+ * router picks a top model, and declares the frontend capabilities that gate
15
+ * it into the frontend-quality verifier. Produces production-grade UI code
16
+ * (HTML/CSS/vanilla JS). Prompts/briefs are supplied by the harness/task.
17
+ */
18
+ export declare function createFrontendWorker(): WorkerHandler;
19
+ export declare const ALL_BUILTIN_WORKERS: WorkerHandler[];
20
+ export declare const EXECUTE_FN: WorkerExecuteFn;
@@ -0,0 +1,120 @@
1
+ import { createBrowserWorker } from './browser-worker.js';
2
+ import { createResearchWorker } from './research-worker.js';
3
+ async function defaultExecute(task, provider, model, _ctx) {
4
+ const request = {
5
+ model: model.id,
6
+ prompt: task.input.prompt,
7
+ systemPrompt: task.input.context?.systemPrompt,
8
+ context: task.input.context,
9
+ artifacts: task.input.artifacts,
10
+ maxTokens: 4096,
11
+ temperature: 0.3,
12
+ };
13
+ const result = await provider.complete(request);
14
+ const artifacts = result.content
15
+ ? [{ id: `${task.id}-out`, type: 'document', content: result.content, mimeType: 'text/markdown' }]
16
+ : [];
17
+ return {
18
+ content: result.content,
19
+ artifacts,
20
+ providerId: result.providerId,
21
+ modelId: result.modelId,
22
+ tokensIn: result.tokensIn,
23
+ tokensOut: result.tokensOut,
24
+ durationMs: result.durationMs,
25
+ };
26
+ }
27
+ export { createResearchWorker } from './research-worker.js';
28
+ export { createBrowserWorker } from './browser-worker.js';
29
+ export function createCodingWorker() {
30
+ return {
31
+ type: 'coding',
32
+ capabilities: ['coding', 'reasoning', 'filesystem', 'terminal'],
33
+ preferences: { reasoning: 95, speed: 80, contextLength: 32_000 },
34
+ execute: defaultExecute,
35
+ };
36
+ }
37
+ export function createArchitectureWorker() {
38
+ return {
39
+ type: 'architecture',
40
+ capabilities: ['architecture', 'planning', 'reasoning'],
41
+ preferences: { reasoning: 95, contextLength: 64_000 },
42
+ execute: defaultExecute,
43
+ };
44
+ }
45
+ export function createReviewWorker() {
46
+ return {
47
+ type: 'review',
48
+ capabilities: ['review', 'coding', 'reasoning'],
49
+ preferences: { reasoning: 90, contextLength: 32_000 },
50
+ execute: defaultExecute,
51
+ };
52
+ }
53
+ export function createDocumentationWorker() {
54
+ return {
55
+ type: 'documentation',
56
+ capabilities: ['documentation', 'summarize', 'reasoning'],
57
+ preferences: { reasoning: 80, speed: 80, contextLength: 16_000 },
58
+ execute: defaultExecute,
59
+ };
60
+ }
61
+ export function createTranslationWorker() {
62
+ return {
63
+ type: 'translation',
64
+ capabilities: ['translation', 'reasoning'],
65
+ preferences: { reasoning: 85, contextLength: 16_000 },
66
+ execute: defaultExecute,
67
+ };
68
+ }
69
+ export function createTerminalWorker() {
70
+ return {
71
+ type: 'terminal',
72
+ capabilities: ['terminal', 'coding', 'filesystem'],
73
+ preferences: { reasoning: 85, speed: 90, contextLength: 8_000 },
74
+ execute: defaultExecute,
75
+ };
76
+ }
77
+ export function createVerificationWorker() {
78
+ return {
79
+ type: 'verification',
80
+ capabilities: ['verification', 'reasoning', 'review'],
81
+ preferences: { reasoning: 95, contextLength: 16_000 },
82
+ execute: defaultExecute,
83
+ };
84
+ }
85
+ export function createVisionWorker() {
86
+ return {
87
+ type: 'vision',
88
+ capabilities: ['vision', 'ocr', 'reasoning'],
89
+ preferences: { reasoning: 85, vision: true, contextLength: 16_000 },
90
+ execute: defaultExecute,
91
+ };
92
+ }
93
+ /**
94
+ * Frontend worker — requests strong reasoning + very large context so the
95
+ * router picks a top model, and declares the frontend capabilities that gate
96
+ * it into the frontend-quality verifier. Produces production-grade UI code
97
+ * (HTML/CSS/vanilla JS). Prompts/briefs are supplied by the harness/task.
98
+ */
99
+ export function createFrontendWorker() {
100
+ return {
101
+ type: 'frontend',
102
+ capabilities: ['frontend', 'coding', 'design', 'accessibility', 'dataviz', 'animation', 'reasoning', 'architecture'],
103
+ preferences: { reasoning: 95, speed: 60, contextLength: 200_000 },
104
+ execute: defaultExecute,
105
+ };
106
+ }
107
+ export const ALL_BUILTIN_WORKERS = [
108
+ createResearchWorker(),
109
+ createCodingWorker(),
110
+ createArchitectureWorker(),
111
+ createReviewWorker(),
112
+ createDocumentationWorker(),
113
+ createTranslationWorker(),
114
+ createTerminalWorker(),
115
+ createVerificationWorker(),
116
+ createVisionWorker(),
117
+ createFrontendWorker(),
118
+ createBrowserWorker(),
119
+ ];
120
+ export const EXECUTE_FN = defaultExecute;
@@ -0,0 +1,5 @@
1
+ import type { WorkerHandler } from '../worker-runtime.js';
2
+ import { SearchController } from '../search/search-controller.js';
3
+ export declare function setSearchController(controller: SearchController): void;
4
+ export declare function setSearchControllerOptions(options: Record<string, unknown>): void;
5
+ export declare function createResearchWorker(): WorkerHandler;
@@ -0,0 +1,90 @@
1
+ import { SearchController } from '../search/search-controller.js';
2
+ let sharedController;
3
+ let controllerOptions;
4
+ export function setSearchController(controller) {
5
+ sharedController = controller;
6
+ }
7
+ export function setSearchControllerOptions(options) {
8
+ controllerOptions = options;
9
+ }
10
+ function getController() {
11
+ if (!sharedController) {
12
+ sharedController = new SearchController(controllerOptions ?? {});
13
+ }
14
+ return sharedController;
15
+ }
16
+ async function researchExecute(task, provider, model, ctx) {
17
+ const query = task.input.context?.query ?? task.input.prompt;
18
+ if (!query || !query.trim()) {
19
+ return defaultComplete(task, provider, model);
20
+ }
21
+ const controller = getController();
22
+ const results = await controller.search(query);
23
+ ctx.logger.info(`Research: ${results.length} results for "${query.slice(0, 60)}"`);
24
+ if (results.length === 0) {
25
+ return defaultComplete(task, provider, model);
26
+ }
27
+ const sourcesBlock = results
28
+ .map((r, i) => `[${i + 1}] ${r.title}\n ${r.url}\n ${r.snippet}`)
29
+ .join('\n\n');
30
+ const crawledBlock = results
31
+ .filter(r => r.markdown)
32
+ .map((r, i) => `--- Source ${i + 1}: ${r.title} ---\n${r.markdown?.slice(0, 4000)}`)
33
+ .join('\n\n');
34
+ const request = {
35
+ model: model.id,
36
+ systemPrompt: 'You are a research assistant. Using ONLY the provided sources, write a concise summary with inline citations in [n] format. Do not invent facts. List sources at the end.',
37
+ prompt: `Query: ${query}\n\nSources:\n${sourcesBlock}\n\nFull content:\n${crawledBlock.slice(0, 12000)}\n\nSummary:`,
38
+ maxTokens: 2048,
39
+ temperature: 0.2,
40
+ };
41
+ const result = await provider.complete(request);
42
+ const artifacts = [
43
+ { id: `${task.id}-summary`, type: 'document', content: result.content, mimeType: 'text/markdown' },
44
+ ...results.map((r, i) => ({
45
+ id: `${task.id}-src-${i}`,
46
+ type: 'url',
47
+ content: `${r.title}\n${r.url}`,
48
+ mimeType: 'text/plain',
49
+ metadata: { url: r.url, crawledAt: r.crawledAt },
50
+ })),
51
+ ];
52
+ return {
53
+ content: result.content,
54
+ artifacts,
55
+ providerId: result.providerId,
56
+ modelId: result.modelId,
57
+ tokensIn: result.tokensIn,
58
+ tokensOut: result.tokensOut,
59
+ durationMs: result.durationMs,
60
+ };
61
+ }
62
+ async function defaultComplete(task, provider, model) {
63
+ const request = {
64
+ model: model.id,
65
+ systemPrompt: task.input.context?.systemPrompt,
66
+ prompt: task.input.prompt,
67
+ context: task.input.context,
68
+ artifacts: task.input.artifacts,
69
+ maxTokens: 4096,
70
+ temperature: 0.3,
71
+ };
72
+ const result = await provider.complete(request);
73
+ return {
74
+ content: result.content,
75
+ artifacts: [{ id: `${task.id}-out`, type: 'document', content: result.content, mimeType: 'text/markdown' }],
76
+ providerId: result.providerId,
77
+ modelId: result.modelId,
78
+ tokensIn: result.tokensIn,
79
+ tokensOut: result.tokensOut,
80
+ durationMs: result.durationMs,
81
+ };
82
+ }
83
+ export function createResearchWorker() {
84
+ return {
85
+ type: 'research',
86
+ capabilities: ['search', 'crawl', 'summarize', 'citations', 'reasoning'],
87
+ preferences: { reasoning: 90, speed: 70, contextLength: 32_000 },
88
+ execute: researchExecute,
89
+ };
90
+ }
@@ -0,0 +1,2 @@
1
+ export declare const PROMPT_ASCII_VIDEO_FRAMES: string[];
2
+ export declare const PROMPT_ASCII_VIDEO_FPS = 24;