@misterscan/sesi 1.1.1
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/LICENSE +21 -0
- package/README.md +191 -0
- package/bin/sesi.js +56 -0
- package/dist/ai-runtime.d.ts +15 -0
- package/dist/ai-runtime.d.ts.map +1 -0
- package/dist/ai-runtime.js +214 -0
- package/dist/ai-runtime.js.map +1 -0
- package/dist/builtins.d.ts +7 -0
- package/dist/builtins.d.ts.map +1 -0
- package/dist/builtins.js +473 -0
- package/dist/builtins.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/interpreter.d.ts +36 -0
- package/dist/interpreter.d.ts.map +1 -0
- package/dist/interpreter.js +495 -0
- package/dist/interpreter.js.map +1 -0
- package/dist/lexer.d.ts +26 -0
- package/dist/lexer.d.ts.map +1 -0
- package/dist/lexer.js +340 -0
- package/dist/lexer.js.map +1 -0
- package/dist/parser.d.ts +55 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +1022 -0
- package/dist/parser.js.map +1 -0
- package/dist/types.d.ts +304 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +63 -0
- package/dist/types.js.map +1 -0
- package/docs/ARCHITECTURE.md +430 -0
- package/docs/BUILTINS.md +577 -0
- package/docs/COMPARISON.md +334 -0
- package/docs/DISTRIBUTED_SYSTEMS.md +71 -0
- package/docs/IMAGE_GENERATION.md +76 -0
- package/docs/IMPLEMENTATION_SUMMARY.md +533 -0
- package/docs/QUICKSTART.md +351 -0
- package/docs/README.md +191 -0
- package/docs/ROADMAP.md +408 -0
- package/docs/SPECIFICATION.md +462 -0
- package/docs/SYSTEMS_REASONING.md +522 -0
- package/examples/01_hello.sesi +2 -0
- package/examples/02_variables.sesi +11 -0
- package/examples/03_functions.sesi +6 -0
- package/examples/04_conditionals.sesi +6 -0
- package/examples/05_loops.sesi +12 -0
- package/examples/06_arrays_objects.sesi +18 -0
- package/examples/07_prompts.sesi +10 -0
- package/examples/08_model_call.sesi +5 -0
- package/examples/09_structured_output.sesi +7 -0
- package/examples/10_code_generation.sesi +5 -0
- package/examples/11_memory_conversation.sesi +16 -0
- package/examples/12_classification.sesi +8 -0
- package/examples/13_data_pipeline.sesi +35 -0
- package/examples/14_folder_explainer.sesi +58 -0
- package/examples/15_image_generation.sesi +17 -0
- package/main/atm_deposit.sesi +37 -0
- package/main/atm_withdraw.sesi +37 -0
- package/main/data.txt +1 -0
- package/main/math_aggregator.sesi +15 -0
- package/main/math_generator.sesi +7 -0
- package/main/math_processor.sesi +23 -0
- package/main/orchestrator.sesi +15 -0
- package/main/playground.sesi +1 -0
- package/main/setup_swarm.sesi +5 -0
- package/main/start.sesi +13 -0
- package/main/tax_calculator.sesi +15 -0
- package/main/tests/compare.sesi +23 -0
- package/main/tests/compare.ts +104 -0
- package/main/tests/debug.sesi +1 -0
- package/main/tests/demo.sesi +24 -0
- package/main/tests/primitive_validation.sesi +18 -0
- package/main/tests/test_connection.sesi +4 -0
- package/main/tests/test_failure_debug.sesi +2 -0
- package/main/tests/test_image.sesi +3 -0
- package/main/tests/test_parser_config.sesi +2 -0
- package/main/tests/test_syntax.sesi +3 -0
- package/main/tests/test_tool_call.sesi +14 -0
- package/main/tests/try.sesi +7 -0
- package/main/vault.sesi +15 -0
- package/package.json +50 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# The Sesi Advantage: Why We Built a Systems & Orchestration Language
|
|
2
|
+
|
|
3
|
+
Integrating Large Language Models (LLMs) into traditional applications today is painful. Standard programming languages treat AI as an external service requiring SDKs, manual prompt string concatenation, complex schema definitions, and fragile JSON parsing.
|
|
4
|
+
|
|
5
|
+
**Sesi treats Reasoning as a first-class language primitive.**
|
|
6
|
+
|
|
7
|
+
This document demonstrates exactly how much boilerplate and complexity Sesi eliminates compared to traditional languages like TypeScript, Python, and Go.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📊 The Cost of Boilerplate: A Data Comparison
|
|
12
|
+
|
|
13
|
+
When building a simple AI-powered data pipeline (structured data extraction + conditional function calling), traditional languages spend more than half their code managing the SDK rather than executing business logic.
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
xychart-beta
|
|
17
|
+
title "Lines of Code (LOC) for an AI Data Pipeline"
|
|
18
|
+
x-axis ["Sesi", "Python", "TypeScript", "Go"]
|
|
19
|
+
y-axis "Lines of Code" 0 --> 140
|
|
20
|
+
bar [16, 45, 105, 130]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Where do the lines go?
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
pie title TypeScript Pipeline Breakdown (105 LOC)
|
|
27
|
+
"Business Logic" : 45
|
|
28
|
+
"Schema Declarations" : 25
|
|
29
|
+
"SDK & Config Boilerplate" : 15
|
|
30
|
+
"Manual JSON Parsing/Try-Catch" : 10
|
|
31
|
+
"Empty Lines" : 10
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
pie title Sesi Pipeline Breakdown (16 LOC)
|
|
36
|
+
"Business Logic" : 16
|
|
37
|
+
"SDK Setup (Native)" : 0
|
|
38
|
+
"Schema Boilerplate (Native)" : 0
|
|
39
|
+
"JSON Parsing (Native)" : 0
|
|
40
|
+
"Comments" : 0
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## đź’» The Side-by-Side Comparison
|
|
46
|
+
|
|
47
|
+
We tasked four languages with building the same script:
|
|
48
|
+
|
|
49
|
+
1. Loop over customer feedback.
|
|
50
|
+
2. Extract structured data (Sentiment, Category, Urgency).
|
|
51
|
+
3. If urgent, execute a local function (`escalateTicket`).
|
|
52
|
+
|
|
53
|
+
### 1. The Sesi Implementation (16 Lines)
|
|
54
|
+
|
|
55
|
+
In Sesi, there are no SDK imports, no manual API key initializations, no complex schema builder libraries, mininmal to no comments, and no manual response parsing.
|
|
56
|
+
|
|
57
|
+
```sesi
|
|
58
|
+
fn escalateTicket(customerId: string, reason: string) {
|
|
59
|
+
print "ESCALATION: Customer" customerId "for" reason
|
|
60
|
+
return "Escalation logged."
|
|
61
|
+
}
|
|
62
|
+
memory processingLog {"Pipeline Start:"}
|
|
63
|
+
let rawFeedback = ["My account was charged twice for the pro plan! Fix this now!", "The new dashboard is really clean, great job team.", "I can't figure out how to export my data to CSV, it just spins."]
|
|
64
|
+
for feedback in rawFeedback
|
|
65
|
+
{processingLog = processingLog + "Processing:" + feedback
|
|
66
|
+
let analysis = structured_output({sentiment: string, category: string, isUrgent: bool, summary: string})
|
|
67
|
+
(model("gemini-3.1-flash-lite") {"Analyze the customer feedback. Category should be Billing, UI, or Technical. Feedback:" feedback})
|
|
68
|
+
print "Result for:" analysis["summary"]
|
|
69
|
+
if analysis["isUrgent"]
|
|
70
|
+
{let resolution = tool_call(escalateTicket)(model("gemini-3.1-flash-lite") {"Call escalateTicket for customer '1234' with an exact reason based on:" feedback})
|
|
71
|
+
processingLog = processingLog + "Urgent action taken:" + resolution} else {processingLog = processingLog + "Logged routinely."}}
|
|
72
|
+
print "--- Final Processing Log ---"
|
|
73
|
+
print processingLog
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. The TypeScript Implementation (105 Lines)
|
|
77
|
+
|
|
78
|
+
TypeScript requires the official Google Gen AI SDK. Notice how much code is dedicated just to telling the model _what_ we want it to do (Schemas, Tool Declarations) and _handling_ what it gives back (JSON.parse).
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { GoogleGenAI, Type } from "@google/genai";
|
|
82
|
+
|
|
83
|
+
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
|
|
84
|
+
|
|
85
|
+
// The tool we want the model to call
|
|
86
|
+
function escalateTicket(customerId: string, reason: string): string {
|
|
87
|
+
console.log(`ESCALATION: Customer ${customerId} for ${reason}`);
|
|
88
|
+
return "Escalation logged.";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 1. Tool Declaration for the SDK (Boilerplate)
|
|
92
|
+
const escalateToolDeclaration = {
|
|
93
|
+
functionDeclarations: [
|
|
94
|
+
{
|
|
95
|
+
name: "escalateTicket",
|
|
96
|
+
description: "Escalate an urgent customer ticket",
|
|
97
|
+
parameters: {
|
|
98
|
+
type: Type.OBJECT,
|
|
99
|
+
properties: {
|
|
100
|
+
customerId: { type: Type.STRING, description: "ID of the customer" },
|
|
101
|
+
reason: { type: Type.STRING, description: "Reason for escalation" },
|
|
102
|
+
},
|
|
103
|
+
required: ["customerId", "reason"],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
async function processFeedback() {
|
|
110
|
+
let processingLog = "Pipeline Start:\n";
|
|
111
|
+
|
|
112
|
+
const rawFeedback = [
|
|
113
|
+
"My account was charged twice for the pro plan! Fix this now!",
|
|
114
|
+
"The new dashboard is really clean, great job team.",
|
|
115
|
+
"I can't figure out how to export my data to CSV, it just spins.",
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
for (const feedback of rawFeedback) {
|
|
119
|
+
processingLog += `Processing: ${feedback}\n`;
|
|
120
|
+
|
|
121
|
+
// 2. Structured Data Extraction (Boilerplate Schema)
|
|
122
|
+
const schema = {
|
|
123
|
+
type: Type.OBJECT,
|
|
124
|
+
properties: {
|
|
125
|
+
sentiment: { type: Type.STRING },
|
|
126
|
+
category: {
|
|
127
|
+
type: Type.STRING,
|
|
128
|
+
description: "Billing, UI, or Technical",
|
|
129
|
+
},
|
|
130
|
+
isUrgent: { type: Type.BOOLEAN },
|
|
131
|
+
summary: { type: Type.STRING },
|
|
132
|
+
},
|
|
133
|
+
required: ["sentiment", "category", "isUrgent", "summary"],
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const analysisResponse = await ai.models.generateContent({
|
|
137
|
+
model: "gemini-3.1-flash-lite",
|
|
138
|
+
contents: `Analyze the customer feedback. Category should be Billing, UI, or Technical.\nFeedback: ${feedback}`,
|
|
139
|
+
config: {
|
|
140
|
+
responseMimeType: "application/json",
|
|
141
|
+
responseSchema: schema,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// 3. Manual JSON parsing and error handling
|
|
146
|
+
let analysis;
|
|
147
|
+
try {
|
|
148
|
+
analysis = JSON.parse(analysisResponse.text || "{}");
|
|
149
|
+
} catch (e) {
|
|
150
|
+
console.error("Failed to parse JSON");
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log(`Result for: ${analysis.summary}`);
|
|
155
|
+
|
|
156
|
+
// 4. Conditional Tool Calling & Response Handling
|
|
157
|
+
if (analysis.isUrgent) {
|
|
158
|
+
const escalationResponse = await ai.models.generateContent({
|
|
159
|
+
model: "gemini-3.1-flash-lite",
|
|
160
|
+
contents: `Call escalateTicket for customer '1234' with an exact reason based on:\n${feedback}`,
|
|
161
|
+
config: {
|
|
162
|
+
tools: [escalateToolDeclaration],
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// 5. Manual extraction of the function call from the response object
|
|
167
|
+
if (
|
|
168
|
+
escalationResponse.functionCalls &&
|
|
169
|
+
escalationResponse.functionCalls.length > 0
|
|
170
|
+
) {
|
|
171
|
+
const call = escalationResponse.functionCalls[0];
|
|
172
|
+
if (call.name === "escalateTicket") {
|
|
173
|
+
const args = call.args as any;
|
|
174
|
+
// Manual invocation of our local function using the args
|
|
175
|
+
const resolution = escalateTicket(args.customerId, args.reason);
|
|
176
|
+
processingLog += `Urgent action taken: ${resolution}\n`;
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
processingLog += `Urgent action failed to trigger tool.\n`;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
processingLog += "Logged routinely.\n";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
console.log("\n--- Final Processing Log ---");
|
|
187
|
+
console.log(processingLog);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
processFeedback().catch(console.error);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 3. The Python Implementation (45 Lines)
|
|
194
|
+
|
|
195
|
+
Python is cleaner than TypeScript thanks to `Pydantic`, but still requires significant setup for function calling and schema extraction.
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import os
|
|
199
|
+
import json
|
|
200
|
+
from google import genai
|
|
201
|
+
from pydantic import BaseModel
|
|
202
|
+
|
|
203
|
+
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
|
|
204
|
+
|
|
205
|
+
def escalate_ticket(customer_id: str, reason: str) -> str:
|
|
206
|
+
print(f"ESCALATION: Customer {customer_id} for {reason}")
|
|
207
|
+
return "Escalation logged."
|
|
208
|
+
|
|
209
|
+
# BOILERPLATE: Pydantic Schema Definition
|
|
210
|
+
class FeedbackAnalysis(BaseModel):
|
|
211
|
+
sentiment: str
|
|
212
|
+
category: str
|
|
213
|
+
is_urgent: bool
|
|
214
|
+
summary: str
|
|
215
|
+
|
|
216
|
+
def process_feedback():
|
|
217
|
+
raw_feedback = ["My account was charged twice..."]
|
|
218
|
+
|
|
219
|
+
for feedback in raw_feedback:
|
|
220
|
+
response = client.models.generate_content(
|
|
221
|
+
model='gemini-3.1-flash-lite',
|
|
222
|
+
contents=f'Analyze the customer feedback.\nFeedback: {feedback}',
|
|
223
|
+
config={'response_mime_type': 'application/json', 'response_schema': FeedbackAnalysis}
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Parse Pydantic object
|
|
227
|
+
analysis = FeedbackAnalysis.model_validate_json(response.text)
|
|
228
|
+
|
|
229
|
+
if analysis.is_urgent:
|
|
230
|
+
escalation_response = client.models.generate_content(
|
|
231
|
+
model='gemini-3.1-flash-lite',
|
|
232
|
+
contents=f"Call escalate_ticket for customer '1234' based on:\n{feedback}",
|
|
233
|
+
config={'tools': [escalate_ticket]}
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# BOILERPLATE: Manual Tool Routing
|
|
237
|
+
for tool_call in escalation_response.function_calls:
|
|
238
|
+
if tool_call.name == "escalate_ticket":
|
|
239
|
+
escalate_ticket(**tool_call.args)
|
|
240
|
+
|
|
241
|
+
if __name__ == "__main__":
|
|
242
|
+
process_feedback()
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 4. The Go Implementation (130+ Lines)
|
|
246
|
+
|
|
247
|
+
In Go, statically typed strictness combined with AI responses creates massive struct-defining overhead. You must define deeply nested JSON structs, handle raw byte marshaling/unmarshaling, and manually map AI function call payloads to Go reflection or manual switch statements. Sesi replaces all 130 lines of this with just its native 16 lines.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Showcase 3: Distributed Orchestration Swarm
|
|
252
|
+
|
|
253
|
+
This example demonstrates a complex distributed task: Spawning a background researcher, polling for completion with fault tolerance, and synthesizing results with AI.
|
|
254
|
+
|
|
255
|
+
### TypeScript (Systems Boilerplate)
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { spawn } from "child_process";
|
|
259
|
+
import { readFile, writeFile } from "fs/promises";
|
|
260
|
+
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
261
|
+
|
|
262
|
+
async function run() {
|
|
263
|
+
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
|
|
264
|
+
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
|
|
265
|
+
|
|
266
|
+
const worker = spawn("node", ["dist/index.js", "researcher.sesi"], {
|
|
267
|
+
detached: true,
|
|
268
|
+
});
|
|
269
|
+
worker.unref();
|
|
270
|
+
|
|
271
|
+
let research = null;
|
|
272
|
+
while (!research) {
|
|
273
|
+
try {
|
|
274
|
+
const status = await readFile("status.txt", "utf8");
|
|
275
|
+
if (status.trim() === "done") {
|
|
276
|
+
research = await readFile("output.txt", "utf8");
|
|
277
|
+
}
|
|
278
|
+
} catch (e) {
|
|
279
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const result = await model.generateContent(`Synthesize: ${research}`);
|
|
284
|
+
console.log(result.response.text());
|
|
285
|
+
}
|
|
286
|
+
run();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Sesi (Agentic Systems Native)
|
|
290
|
+
|
|
291
|
+
```sesi
|
|
292
|
+
spawn("researcher.sesi")
|
|
293
|
+
let research = ""
|
|
294
|
+
while research == "" {
|
|
295
|
+
try {
|
|
296
|
+
if read_file("status.txt") == "done" {
|
|
297
|
+
research = read_file("output.txt")
|
|
298
|
+
}
|
|
299
|
+
} catch (e) {
|
|
300
|
+
let i = 0 while i < 1000 { i = i + 1 }
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
print model("gemini-3.1-flash-lite") {"Synthesize: " research}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Analysis**:
|
|
307
|
+
|
|
308
|
+
- **Conciseness**: Sesi achieves in 12 lines of native logic what requires 30+ lines of asynchronous boilerplate in TypeScript.
|
|
309
|
+
- **Orchestration**: `spawn` and `model` are first-class primitives in Sesi, removing the need for manual process management and SDK initialization.
|
|
310
|
+
- **Fault Tolerance**: Sesi's native `try/catch` handles filesystem contention with zero external library overhead.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## The Verdict
|
|
315
|
+
|
|
316
|
+
Sesi isn't just syntactic sugar. By embedding the AI runtime directly into the parser and interpreter, Sesi understands _intent_:
|
|
317
|
+
|
|
318
|
+
- You don't serialize schemas; Sesi builds the JSONSchema dynamically from your literal `{ key: type }` maps.
|
|
319
|
+
- You don't parse responses; Sesi validates and hydrates the objects for you.
|
|
320
|
+
- You don't route tool calls; Sesi pauses execution and handles the function reference automatically.
|
|
321
|
+
|
|
322
|
+
**Less boilerplate. Fewer bugs. Faster development.**
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## See Also
|
|
327
|
+
|
|
328
|
+
- [Quickstart](../QUICKSTART.md)
|
|
329
|
+
- [Language Specification](SPECIFICATION.md)
|
|
330
|
+
- [Image Generation](IMAGE_GENERATION.md)
|
|
331
|
+
- [Built-in Functions](BUILTINS.md)
|
|
332
|
+
- [Architecture](ARCHITECTURE.md)
|
|
333
|
+
- [Reasoning Features](SYSTEMS_REASONING.md)
|
|
334
|
+
- [Distributed Systems](DISTRIBUTED_SYSTEMS.md)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Distributed Systems with Sesi
|
|
2
|
+
|
|
3
|
+
Sesi is a robust systems-level environment capable of orchestrating complex, multi-process agent swarms. This document details how Sesi handles concurrency, race conditions, and distributed state.
|
|
4
|
+
|
|
5
|
+
## The "Bank Swarm" Case Study
|
|
6
|
+
|
|
7
|
+
In this experiment, Sesi was used to solve a classic distributed systems problem: **Concurrent Mutual Exclusion.**
|
|
8
|
+
|
|
9
|
+
### The Challenge
|
|
10
|
+
|
|
11
|
+
Five independent Sesi agents (3 Deposits, 2 Withdrawals) were launched simultaneously. All agents needed to update a single `balance.txt` file without causing data loss through race conditions.
|
|
12
|
+
|
|
13
|
+
### The Sesi Solution (The "Double-Check Write" Pattern)
|
|
14
|
+
|
|
15
|
+
Sesi solves this using a high-level implementation of a filesystem lock. Even without low-level semaphores, Sesi's `try/catch` and file I/O builtins allow for an "indestructible" locking logic.
|
|
16
|
+
|
|
17
|
+
#### 1. Unique Identity
|
|
18
|
+
|
|
19
|
+
Each agent generates a globally unique ID using Sesi's native `time()` and `random()` builtins.
|
|
20
|
+
|
|
21
|
+
```sesi
|
|
22
|
+
let id = "Agent_" + str(time()) + "_" + str(random())
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
#### 2. Mutual Exclusion Loop
|
|
26
|
+
|
|
27
|
+
The agent "polls" the lock file. If it finds it "unlocked," it attempts to claim it. Crucially, it then **verifies** its own claim after a micro-delay to ensure it wasn't overwritten by a simultaneous process.
|
|
28
|
+
|
|
29
|
+
```sesi
|
|
30
|
+
while locked {
|
|
31
|
+
if read_file("lock.txt") == "unlocked" {
|
|
32
|
+
write_file("lock.txt", id)
|
|
33
|
+
// Settle delay
|
|
34
|
+
let i = 0 while i < 500 { i = i + 1 }
|
|
35
|
+
// Verification
|
|
36
|
+
if read_file("lock.txt") == id { locked = false }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### 3. Critical Section Resilience
|
|
42
|
+
|
|
43
|
+
Using `try/catch`, Sesi agents gracefully handle filesystem contention (when the OS prevents two processes from reading the same file at the exact same micro-second).
|
|
44
|
+
|
|
45
|
+
```sesi
|
|
46
|
+
try {
|
|
47
|
+
write_file("balance.txt", str(num(read_file("balance.txt")) + 100))
|
|
48
|
+
write_file("lock.txt", "unlocked") // Release
|
|
49
|
+
} catch (e) {
|
|
50
|
+
write_file("lock.txt", "unlocked") // Emergency release
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Concurrency via `spawn()`
|
|
55
|
+
|
|
56
|
+
Sesi v1.1+ introduces the `spawn()` builtin, allowing a single **Master Orchestrator** to launch an entire swarm of agents from one file.
|
|
57
|
+
|
|
58
|
+
```sesi
|
|
59
|
+
// Master: Launching 5-Agent Swarm
|
|
60
|
+
spawn("main/atm_deposit.sesi")
|
|
61
|
+
spawn("main/atm_withdraw.sesi")
|
|
62
|
+
spawn("main/atm_deposit.sesi")
|
|
63
|
+
spawn("main/atm_withdraw.sesi")
|
|
64
|
+
spawn("main/atm_deposit.sesi")
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Why This Matters
|
|
68
|
+
|
|
69
|
+
Sesi's approach to distributed systems is **Concise** and **Readable**. What would take dozens of lines of boilerplate in C or Java (handling threads, mutexes, and I/O exceptions) is expressed in Sesi as a series of intuitive blocks.
|
|
70
|
+
|
|
71
|
+
This enables developers to build **Agent Swarms** that can work in parallel on large-scale datasets, research tasks, or code generation pipelines with guaranteed state integrity.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Image Generation in Sesi
|
|
2
|
+
|
|
3
|
+
Sesi provides a native, language-level primitive for generating images using AI models. This primitive is designed to interoperate seamlessly with Sesi's file system builtins, allowing you to generate and persist images with minimal boilerplate.
|
|
4
|
+
|
|
5
|
+
## The `image` Primitive
|
|
6
|
+
|
|
7
|
+
To generate an image, use the `image` keyword followed by the model name, an optional configuration block, and a prompt block.
|
|
8
|
+
|
|
9
|
+
### Syntax
|
|
10
|
+
|
|
11
|
+
The syntax parallels standard `model` calls:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
image("model-name") {"configKey": "configValue"} {"Prompt text"}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Basic Example
|
|
18
|
+
|
|
19
|
+
Here is a simple example demonstrating how to generate a single image and save it to disk directly:
|
|
20
|
+
|
|
21
|
+
```sesi
|
|
22
|
+
// 1. Define the generation prompt natively
|
|
23
|
+
prompt request {"A simple minimalist company logo for a bakery"}
|
|
24
|
+
|
|
25
|
+
// 2. Call the image generation primitive
|
|
26
|
+
let imageData = image("gemini-3.1-flash-image-preview") {"ratio": "1:1", "size": "1K"} {request}
|
|
27
|
+
|
|
28
|
+
// 3. Write the payload to disk
|
|
29
|
+
try
|
|
30
|
+
{let success = write_image("bakery_logo.png", imageData)
|
|
31
|
+
if success {print "Saved bakery_logo.png successfully."}}
|
|
32
|
+
catch (e) {print "Failed to generate image:"
|
|
33
|
+
print e}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Advanced Example: Batch Asset Generation Workflow
|
|
37
|
+
|
|
38
|
+
Here is a practical script demonstrating how to iterate over a data set, generate assets, and save them to a specific directory. This is useful for building automated pipelines like generating UI placeholders or product catalog images.
|
|
39
|
+
|
|
40
|
+
```sesi
|
|
41
|
+
// Set up output directory
|
|
42
|
+
let outputDir = "assets/products/"
|
|
43
|
+
make_dir(outputDir)
|
|
44
|
+
let products = ["coffee_mug", "desk_lamp", "notebook"]
|
|
45
|
+
|
|
46
|
+
// Iterate through the list and generate a file for each
|
|
47
|
+
for product in products
|
|
48
|
+
{print "Generating asset for:" product
|
|
49
|
+
|
|
50
|
+
// Construct the instruction for the model
|
|
51
|
+
prompt request {"A clean studio presentation photograph of a " product " on a solid white background."}
|
|
52
|
+
prompt filename { outputDir product ".png" }
|
|
53
|
+
try
|
|
54
|
+
{let imageData = image("gemini-3.1-flash-image-preview") {"ratio": '1:1', "size": "1K"} {request}
|
|
55
|
+
|
|
56
|
+
// Attempt local file write
|
|
57
|
+
let success = write_image(filename, imageData)
|
|
58
|
+
if success {print "Saved:" filename}}
|
|
59
|
+
catch (e) {print "Failed processing" product ":"
|
|
60
|
+
print e}}
|
|
61
|
+
print "Asset generation complete."
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Configuration Options
|
|
65
|
+
|
|
66
|
+
When configuring the `image` call (specifically for models like `gemini-3.1-flash-image-preview`), the configuration block maps directly to backend SDK capabilities:
|
|
67
|
+
|
|
68
|
+
- `"ratio"`: The aspect ratio of the image (e.g., `"1:1"`, `"16:9"`, `"9:16"`).
|
|
69
|
+
- `"size"`: Dimensional sizing constraints (Must be `"512"`, `"1K"`, `"2K"`, or `"4K"`).
|
|
70
|
+
- `"temperature"`: Controls variance (e.g., `0.3`).
|
|
71
|
+
|
|
72
|
+
## File I/O Integration: `write_image`
|
|
73
|
+
|
|
74
|
+
The `image()` call evaluates to a `string` (specifically, base64-encoded image data). To convert this into a standard image file on disk, you must use the `write_image(path, base64_content)` builtin.
|
|
75
|
+
|
|
76
|
+
**Important:** Do *not* use `write_file` for image payloads—`write_image` is explicitly implemented in the Sesi engine (`src/builtins.ts`) to handle `Buffer.from(content, 'base64')` decoding for writing safe binary formats.
|