openagentflow 0.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.
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/adapters/langgraph/demo_template.js +104 -0
- package/adapters/langgraph/index.js +363 -0
- package/adapters/langgraph/templates.js +502 -0
- package/cli/env.js +193 -0
- package/cli/index.js +580 -0
- package/compiler/compiler.js +134 -0
- package/compiler/index.js +7 -0
- package/compiler/ir-generator.js +142 -0
- package/compiler/validator.js +594 -0
- package/examples/hello.oaf +14 -0
- package/examples/software-dev.oaf +60 -0
- package/examples/summarize-input.json +3 -0
- package/examples/summarize.oaf +28 -0
- package/examples/support-triage-input.json +3 -0
- package/examples/support-triage.oaf +49 -0
- package/package.json +44 -0
- package/parser/ast.js +240 -0
- package/parser/index.js +9 -0
- package/parser/lexer.js +376 -0
- package/parser/parser.js +505 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AbdulRahman Elzahaby (egyjs) and OpenAgentFlow Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/oaf-logo.svg" alt="OpenAgentFlow Logo" width="160"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# OpenAgentFlow
|
|
6
|
+
|
|
7
|
+
**An Open, Portable Specification for Executable Multi-Agent Workflows**
|
|
8
|
+
|
|
9
|
+
[](#testing--quality-assurance)
|
|
10
|
+
[](#project-structure)
|
|
11
|
+
[](#multi-llm--runtime-integration)
|
|
12
|
+
[](#multi-llm--runtime-integration)
|
|
13
|
+
[](https://marketplace.visualstudio.com/items?itemName=OpenAgentFlow.openagentflow-support)
|
|
14
|
+
[](docs/index.md)
|
|
15
|
+
[](https://opensource.org/licenses/MIT)
|
|
16
|
+
|
|
17
|
+
> *What OpenAPI is for REST APIs, OpenAgentFlow (`.oaf`) is for AI agent workflows.*
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<img src="docs/assets/demo.gif" alt="OpenAgentFlow Demo" width="800"/>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
### β‘ The 60-Second Example
|
|
24
|
+
Define your multi-agent workflow in clean, human-readable `.oaf` textβcompletely decoupled from Python/Node boilerplate:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
workflow "Quick Summarize" {
|
|
28
|
+
|
|
29
|
+
state {
|
|
30
|
+
source_text: string @required
|
|
31
|
+
extracted_points: string
|
|
32
|
+
summary: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
agent Extractor {
|
|
36
|
+
instructions: "Read the `source_text` and extract the most important facts into a concise bulleted list."
|
|
37
|
+
model: "gemini-2.0-flash"
|
|
38
|
+
inputs: [source_text]
|
|
39
|
+
outputs: [extracted_points]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
agent Synthesizer {
|
|
43
|
+
instructions: "Take the extracted points and weave them into a clear, cohesive summary paragraph."
|
|
44
|
+
model: "gpt-4o"
|
|
45
|
+
inputs: [extracted_points]
|
|
46
|
+
outputs: [summary]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
flow {
|
|
50
|
+
start -> Extractor
|
|
51
|
+
Extractor -> Synthesizer
|
|
52
|
+
Synthesizer -> end
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Install the CLI globally and execute your workflow immediately (or clone our [Starter Repository](https://github.com/OpenAgentFlow/OpenAgentFlow-starter)):
|
|
58
|
+
```bash
|
|
59
|
+
# Option A: Save the block above to summarize.oaf and run directly
|
|
60
|
+
npm install -g openagentflow
|
|
61
|
+
oaf run summarize.oaf
|
|
62
|
+
|
|
63
|
+
# Option B: Clone our official starter repository with pre-built workflows & inputs
|
|
64
|
+
git clone https://github.com/OpenAgentFlow/OpenAgentFlow-starter.git my-agents
|
|
65
|
+
cd my-agents && npm run setup && npm run triage
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## π Why OpenAgentFlow?
|
|
71
|
+
|
|
72
|
+
Modern AI agent frameworks (like LangGraph, AutoGen, and CrewAI) each introduce distinct concepts, Python/Node boilerplate, and proprietary APIs. **OpenAgentFlow** introduces a neutral, human-readable authoring language (`.oaf`) that separates workflow definition from execution runtimes.
|
|
73
|
+
|
|
74
|
+
### β¨ Key Features
|
|
75
|
+
- **Write Once, Run Anywhere**: Define multi-agent topologies, state schemas, and agent instructions once in pure `.oaf` text and compile deterministically to production-ready Python code.
|
|
76
|
+
- **Strict Semantic Validation**: Three-phase checking catches dead ends, unreachable agents, and missing fields *before* running expensive LLM calls.
|
|
77
|
+
- **Zero-Config Multi-LLM**: Auto-detects and adapts to Gemini, OpenAI, and Anthropic endpoints without changing your `.oaf` code.
|
|
78
|
+
- **4-Tier Env Hierarchy & Auth**: Seamlessly resolve API keys across CLI flags, local `.env` files, system variables, and global `~/.oaf/.env` credentials (`oaf auth`).
|
|
79
|
+
- **Push-Model State Injection**: Inject JSON payloads (`--input data.json`) directly into workflows for easy backend/API integration.
|
|
80
|
+
- **Zero Core Dependencies**: Pure Node.js compiler (`lexer`, `parser`, `validator`, `IR generator`, and `LangGraph adapter`).
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## π Quick Start
|
|
85
|
+
|
|
86
|
+
### Option 1: Using the Starter Repository (Recommended β 60 Seconds)
|
|
87
|
+
The fastest way to start building executable multi-agent workflows without manual setup or missing file errors is using our official template repository:
|
|
88
|
+
|
|
89
|
+
1. **Clone the Starter Project:**
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/OpenAgentFlow/OpenAgentFlow-starter.git my-agents
|
|
92
|
+
cd my-agents
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
2. **Run Automated Environment Setup:**
|
|
96
|
+
Our cross-platform setup script (`setup.js`) checks your system, creates your Python virtual environment (`venv`), installs LangGraph dependencies, and initializes your `.env` configuration automatically across Windows, macOS, and Linux:
|
|
97
|
+
```bash
|
|
98
|
+
npm install
|
|
99
|
+
npm run setup
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
3. **Configure API Keys (`oaf auth`):**
|
|
103
|
+
Set your keys interactively via CLI (or edit the `.env` file generated in your project root):
|
|
104
|
+
```bash
|
|
105
|
+
npx openagentflow auth
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
4. **Run Your First Workflow Live!**
|
|
109
|
+
Execute pre-built multi-agent topologies immediately:
|
|
110
|
+
```bash
|
|
111
|
+
# Run Customer Support Triage Workflow with injected JSON state
|
|
112
|
+
npm run triage
|
|
113
|
+
|
|
114
|
+
# Or compile directly to a LangGraph Python application
|
|
115
|
+
npm run compile-triage
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### Option 2: Standalone Global CLI
|
|
121
|
+
If you prefer creating workflows from scratch in your own workspace without cloning a template:
|
|
122
|
+
|
|
123
|
+
1. **Install Prerequisites & CLI:**
|
|
124
|
+
Ensure **Node.js** (v18+) and **Python** (v3.10+) are installed, then install the CLI globally:
|
|
125
|
+
```bash
|
|
126
|
+
npm install -g openagentflow
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
2. **Set Your API Keys (`oaf auth`):**
|
|
130
|
+
Configure credentials securely in `~/.oaf/.env` (`0o600` permissions):
|
|
131
|
+
```bash
|
|
132
|
+
oaf auth
|
|
133
|
+
# Or set manually: export GOOGLE_API_KEY="your-key" / $env:GOOGLE_API_KEY="your-key"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
3. **Set Up Python Runtime & Virtual Environment:**
|
|
137
|
+
To execute compiled `.oaf` workflows live via LangGraph against real LLM endpoints:
|
|
138
|
+
```bash
|
|
139
|
+
# Create and activate Python virtual environment
|
|
140
|
+
python -m venv venv
|
|
141
|
+
source venv/bin/activate # Windows PowerShell: .\venv\Scripts\Activate.ps1
|
|
142
|
+
|
|
143
|
+
# Install LangGraph and multi-provider LangChain drivers
|
|
144
|
+
pip install langgraph langchain-google-genai langchain-openai langchain-anthropic pydantic
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
4. **Create & Execute Workflows Live:**
|
|
148
|
+
Create a `.oaf` workflow file (e.g., `my-workflow.oaf`) along with your JSON data (`data.json`) and run:
|
|
149
|
+
```bash
|
|
150
|
+
oaf run my-workflow.oaf --input data.json
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
> π **For the full guide, see [Documentation](docs/index.md)**.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## π Documentation
|
|
158
|
+
|
|
159
|
+
The complete documentation is available in the `docs/` directory, including:
|
|
160
|
+
* **[Language Reference](docs/language/oaf-language.md):** Complete `.oaf` syntax.
|
|
161
|
+
* **[Formal Specs](spec/SPEC.md):** EBNF grammar, semantic rules, and IR schema.
|
|
162
|
+
* **[API & CLI Ref](docs/cli/cli-reference.md):** Programmatic API and command-line flags.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## π The `.oaf` Language at a Glance
|
|
167
|
+
|
|
168
|
+
OpenAgentFlow provides a clean, declarative syntax for describing stateful multi-agent workflows:
|
|
169
|
+
|
|
170
|
+
```oaf
|
|
171
|
+
workflow "Quick Summarize" {
|
|
172
|
+
|
|
173
|
+
config {
|
|
174
|
+
max_iterations: 5
|
|
175
|
+
timeout_seconds: 60
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
state {
|
|
179
|
+
request: string
|
|
180
|
+
source_text: string
|
|
181
|
+
key_points: list[string]
|
|
182
|
+
summary: string
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
agent Analyst {
|
|
186
|
+
instructions: """
|
|
187
|
+
Analyze the request and source text.
|
|
188
|
+
Identify the most important facts.
|
|
189
|
+
"""
|
|
190
|
+
model: "gpt-4"
|
|
191
|
+
temperature: 0.2
|
|
192
|
+
inputs: [request, source_text]
|
|
193
|
+
outputs: [key_points]
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
agent Writer {
|
|
197
|
+
instructions: """
|
|
198
|
+
Write a clear, concise summary from the key points.
|
|
199
|
+
"""
|
|
200
|
+
model: "gpt-4"
|
|
201
|
+
temperature: 0.7
|
|
202
|
+
inputs: [key_points]
|
|
203
|
+
outputs: [summary]
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
flow {
|
|
207
|
+
start -> Analyst
|
|
208
|
+
Analyst -> Writer
|
|
209
|
+
Writer -> end
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## βοΈ Compilation & Execution Pipeline
|
|
217
|
+
|
|
218
|
+
The OpenAgentFlow compiler transforms raw `.oaf` source code into validated Intermediate Representation (IR) JSON, which runtime adapters then transform into executable source code:
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
βββββββββββββββ βββββββββββββ ββββββββββββββ βββββββββββββββββββββ
|
|
222
|
+
β Source Code β βββΆ β Lexer β βββΆ β Parser β βββΆ β AST (JSON) β
|
|
223
|
+
β (.oaf file)β β (lexer.js)β β(parser.js) β β (ast.js) β
|
|
224
|
+
βββββββββββββββ βββββββββββββ ββββββββββββββ βββββββββββ¬ββββββββββ
|
|
225
|
+
β
|
|
226
|
+
βββββββββββββββ βββββββββββββ ββββββββββββββ βββββββββββΌββββββββββ
|
|
227
|
+
β Execution β βββ β LangGraph β βββ β Compiler β βββ β Semantic Validatorβ
|
|
228
|
+
β (Live Subproc) β Adapter β β (IR Gen) β β (validator.js) β
|
|
229
|
+
βββββββββββββββ βββββββββββββ ββββββββββββββ βββββββββββββββββββββ
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## π§ Multi-LLM & Runtime Integration
|
|
235
|
+
|
|
236
|
+
When compiling to LangGraph, the runtime automatically manages providers. You can specify `model: "gpt-4o"` or `model: "gemini-2.0-flash"` in your `.oaf` file, and the compiled Python script will auto-detect your API keys (via `.env`, system vars, or `~/.oaf/.env`) and route the request to the correct provider.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## πΊοΈ Roadmap & Project Status
|
|
241
|
+
|
|
242
|
+
| Phase | Deliverables | Status |
|
|
243
|
+
| :--- | :--- | :--- |
|
|
244
|
+
| **Phase 1** β Specification | Language spec (`SPEC.md`), EBNF grammar, examples, IR definition | β
Complete |
|
|
245
|
+
| **Phase 2** β Compiler MVP | Zero-dependency Lexer, Parser, 3-Phase Validator, IR Generator, CLI | β
Complete |
|
|
246
|
+
| **Phase 3** β Runtime Integration | LangGraph Python Adapter, Dual-LLM (`get_llm()`), Live `run` CLI, E2E Demo | β
Complete |
|
|
247
|
+
| **Phase 4** β State Initialization (`--input`) | File-based state injection (`--input data.json`), runtime override (`OAF_INPUT_FILE`) | β
Complete |
|
|
248
|
+
| **Phase 4.5** β Multi-Provider, Auth & Tooling | Anthropic (`claude-*`) & Google (`gemma-*`) inference, `oaf auth`, VS Code syntax extension (`.oaf`) | β
Complete |
|
|
249
|
+
| **Phase 5** β Additional Adapters | AutoGen Adapter, CrewAI Adapter, Formal `Adapter` base contract | π² Planned |
|
|
250
|
+
| **Phase 6** β Developer CLI Tooling | `oaf fmt` (auto-formatter), `oaf init` (project scaffolding) | π² Planned |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## π€ Contributing
|
|
255
|
+
|
|
256
|
+
We welcome contributions from developers, researchers, and engineers! Whether you want to pick up a [`good first issue`](https://github.com/OpenAgentFlow/openagentflow/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22), help build our planned Phase 5 target adapters (**Microsoft AutoGen** or **CrewAI**), or propose language enhancements, please check out our detailed [Contributing Guide](CONTRIBUTING.md) to get started.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## π License
|
|
261
|
+
|
|
262
|
+
This project is open-source and licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAgentFlow β Isolated Demo Helper Template Module
|
|
3
|
+
*
|
|
4
|
+
* This module generates self-contained Python code (`_DemoChatModel`, `_maybe_get_demo_llm`,
|
|
5
|
+
* `_format_demo_state`) used strictly when `--demo` (OAF_DEMO=1) is active.
|
|
6
|
+
*
|
|
7
|
+
* It can be cleanly deleted from the codebase if demo simulation mode is ever removed.
|
|
8
|
+
* See: llm/handover/2026-07-20-screencast-and-demo-removal-guide.md
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export function generateDemoHelperTemplate() {
|
|
12
|
+
const lines = [
|
|
13
|
+
`# βββ DEMO HOOK MODULE (Cleanly removable) βββββββββββββββββββββββββββββββββββ`,
|
|
14
|
+
`import hashlib, json, os`,
|
|
15
|
+
`class _DemoChatModel:`,
|
|
16
|
+
` def __init__(self, model, temperature=0, provider="demo"):`,
|
|
17
|
+
` self.model = model`,
|
|
18
|
+
` self.temperature = temperature`,
|
|
19
|
+
` self._oaf_provider = provider`,
|
|
20
|
+
``,
|
|
21
|
+
` def invoke(self, messages, *args, **kwargs):`,
|
|
22
|
+
` cache_dir = os.path.join(os.path.expanduser("~"), ".oaf")`,
|
|
23
|
+
` cache_file = os.path.join(cache_dir, "demo_cache.json")`,
|
|
24
|
+
` prompt_parts = []`,
|
|
25
|
+
` sys_prompt = ""`,
|
|
26
|
+
` for m in messages:`,
|
|
27
|
+
` if isinstance(m, dict):`,
|
|
28
|
+
` role = m.get("role", "")`,
|
|
29
|
+
` content_str = str(m.get("content", ""))`,
|
|
30
|
+
` if role == "system": sys_prompt = content_str`,
|
|
31
|
+
` prompt_parts.append(f"{role}:{content_str}")`,
|
|
32
|
+
` elif hasattr(m, "type"):`,
|
|
33
|
+
` content_str = str(getattr(m, "content", ""))`,
|
|
34
|
+
` if m.type == "system": sys_prompt = content_str`,
|
|
35
|
+
` prompt_parts.append(f"{m.type}:{content_str}")`,
|
|
36
|
+
` else:`,
|
|
37
|
+
` prompt_parts.append(str(m))`,
|
|
38
|
+
``,
|
|
39
|
+
` full_prompt = "|".join(prompt_parts)`,
|
|
40
|
+
` cache_key = f"{self.model}:{hashlib.sha256(full_prompt.encode('utf-8')).hexdigest()}"`,
|
|
41
|
+
``,
|
|
42
|
+
` if os.path.exists(cache_file):`,
|
|
43
|
+
` try:`,
|
|
44
|
+
` with open(cache_file, "r", encoding="utf-8") as f:`,
|
|
45
|
+
` cache_data = json.load(f)`,
|
|
46
|
+
` if cache_key in cache_data:`,
|
|
47
|
+
` class _AIMessage:`,
|
|
48
|
+
` def __init__(self, text): self.content = text`,
|
|
49
|
+
` return _AIMessage(cache_data[cache_key])`,
|
|
50
|
+
` except Exception:`,
|
|
51
|
+
` pass`,
|
|
52
|
+
``,
|
|
53
|
+
` if "extract the most important facts" in sys_prompt.lower() or "extractor" in sys_prompt.lower():`,
|
|
54
|
+
` content = (`,
|
|
55
|
+
` "- Monolithic LLMs are transitioning to multi-agent pipelines where specialized agents handle distinct sub-tasks.\\n"`,
|
|
56
|
+
` "- Robust state management and clear communication protocols are critical to prevent information loss and infinite loops.\\n"`,
|
|
57
|
+
` "- Standardized open-source frameworks provide unified syntax and configurations, lowering the engineering barrier."`,
|
|
58
|
+
` )`,
|
|
59
|
+
` elif "weave them into a clear, cohesive summary" in sys_prompt.lower() or "synthesizer" in sys_prompt.lower():`,
|
|
60
|
+
` content = (`,
|
|
61
|
+
` "Modern AI is rapidly evolving from monolithic models to collaborative multi-agent pipelines where specialized models execute modular sub-tasks. "`,
|
|
62
|
+
` "While this approach improves reliability and performance, it introduces orchestration challenges requiring robust state management and structured communication protocols. "`,
|
|
63
|
+
` "Standardized open-source frameworks address these bottlenecks by offering a unified syntax and automated state coordination, making multi-agent deployment as seamless as containerizing a web application."`,
|
|
64
|
+
` )`,
|
|
65
|
+
` else:`,
|
|
66
|
+
` content = f"[Demo Output for {self.model}]: Successfully processed workflow input."`,
|
|
67
|
+
``,
|
|
68
|
+
` class _AIMessage:`,
|
|
69
|
+
` def __init__(self, text):`,
|
|
70
|
+
` self.content = text`,
|
|
71
|
+
``,
|
|
72
|
+
` try:`,
|
|
73
|
+
` os.makedirs(cache_dir, exist_ok=True)`,
|
|
74
|
+
` cache_data = {}`,
|
|
75
|
+
` if os.path.exists(cache_file):`,
|
|
76
|
+
` with open(cache_file, "r", encoding="utf-8") as f:`,
|
|
77
|
+
` cache_data = json.load(f)`,
|
|
78
|
+
` cache_data[cache_key] = content`,
|
|
79
|
+
` with open(cache_file, "w", encoding="utf-8") as f:`,
|
|
80
|
+
` json.dump(cache_data, f, indent=2, ensure_ascii=False)`,
|
|
81
|
+
` except Exception:`,
|
|
82
|
+
` pass`,
|
|
83
|
+
``,
|
|
84
|
+
` return _AIMessage(content)`,
|
|
85
|
+
``,
|
|
86
|
+
`def _maybe_get_demo_llm(target_model, temperature, target_provider):`,
|
|
87
|
+
` if os.environ.get("OAF_DEMO") == "1" or target_provider == "demo":`,
|
|
88
|
+
` return _DemoChatModel(model=target_model, temperature=temperature, provider=target_provider or "demo")`,
|
|
89
|
+
` return None`,
|
|
90
|
+
``,
|
|
91
|
+
`def _format_demo_state(result, initial_state):`,
|
|
92
|
+
` if os.environ.get("OAF_DEMO") != "1":`,
|
|
93
|
+
` return result`,
|
|
94
|
+
` display_state = {}`,
|
|
95
|
+
` for k, v in result.items():`,
|
|
96
|
+
` if k in initial_state and isinstance(v, str) and len(v) > 100 and result[k] == initial_state[k]:`,
|
|
97
|
+
` display_state[k] = f"{v[:80]}... ({len(v)} chars abbreviated)"`,
|
|
98
|
+
` else:`,
|
|
99
|
+
` display_state[k] = v`,
|
|
100
|
+
` return display_state`,
|
|
101
|
+
`# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ`,
|
|
102
|
+
];
|
|
103
|
+
return lines.join('\n');
|
|
104
|
+
}
|