lampson 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +394 -382
- package/bin/lampson.js +8 -2
- package/chat.syn +1029 -799
- package/lampson.cmd +4 -4
- package/lampson.ps1 +88 -88
- package/lampson.sh +42 -42
- package/lib/agents.syn +471 -471
- package/lib/diff.syn +142 -0
- package/lib/lamps.syn +386 -386
- package/lib/line.syn +365 -0
- package/lib/lsp.syn +503 -503
- package/lib/mcp.syn +403 -403
- package/lib/md.syn +171 -0
- package/lib/permission.syn +189 -154
- package/lib/prompt.syn +75 -75
- package/lib/session.syn +111 -111
- package/lib/skills.syn +179 -179
- package/lib/tools/bash.syn +105 -105
- package/lib/tools/edit.syn +35 -32
- package/lib/tools/memo.syn +148 -148
- package/lib/tools/process.syn +46 -46
- package/lib/tools/write.syn +4 -0
- package/lib/tools.syn +198 -198
- package/lib/tree.syn +59 -59
- package/package.json +2 -2
- package/public/index.html +1268 -1268
- package/skills/lampson/SKILL.md +117 -117
- package/skills/synsema/SKILL.md +15 -2
- package/web.syn +468 -468
package/skills/lampson/SKILL.md
CHANGED
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: lampson
|
|
3
|
-
description: How this harness works — tools, workspace mount, permissions, agents, sessions. Load when asked about Lampson itself or when a tool behaves unexpectedly.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Lampson (the harness you are running in)
|
|
7
|
-
|
|
8
|
-
## Where you are
|
|
9
|
-
- Your tools only reach `workspace/` — the user's project, mounted as a junction/symlink by
|
|
10
|
-
`lampson.ps1 <path>` / `lampson.sh <path>`. All paths you pass are relative to that root.
|
|
11
|
-
- Anything outside (absolute paths, `..`, sibling dirs) fails with `Capability not granted`.
|
|
12
|
-
That is by design (Synsema deny-by-default + `call_tool` least-privilege). Do not try to work
|
|
13
|
-
around it; tell the user if you genuinely need something outside the workspace.
|
|
14
|
-
- `bash` runs with cwd = workspace root and a hard timeout (default 120 s): when it expires the command AND
|
|
15
|
-
its child processes are killed. Never run servers/watchers/REPLs in `bash`; use the `process` tool:
|
|
16
|
-
`process(start, name="web", command="npm run dev")`, then `process(logs, name="web")`, and
|
|
17
|
-
`process(stop, name="web")` when done. New log lines of every managed process are appended to each
|
|
18
|
-
`bash` result automatically — you SEE the server's console (errors, requests, crashes) without asking.
|
|
19
|
-
The user sees the same logs live in the web UI ("Procesos" panel). Its child process is NOT confined by Synsema; dangerous
|
|
20
|
-
commands are screened by `permission.syn` (hardline = always denied; dangerous = needs the user's
|
|
21
|
-
approval in `ask` mode, denied in `strict`, allowed in `yolo`).
|
|
22
|
-
|
|
23
|
-
## Tool behavior worth knowing
|
|
24
|
-
- `edit` needs an exact, unique `old_string`; if it fails, `read` the region again and retry with
|
|
25
|
-
more context. `replace_all=true` for intentional multi-replace.
|
|
26
|
-
- `read` returns up to 2000 lines; use `offset`/`limit` for big files. Outputs > 30k chars are truncated.
|
|
27
|
-
- `find` is a simple glob (`*.ts`, `test_*`, `*config*`), `grep` is regex by default (`regex=false` for literals).
|
|
28
|
-
- `lsp(op=symbols, path)` is the cheapest way to understand a big file: every function/class/variable
|
|
29
|
-
with its line range — then `read` only the range you need. `definition` / `references` / `hover` /
|
|
30
|
-
`implementation` take 1-based `line` + `character` ON the identifier. If no server is configured for
|
|
31
|
-
that extension, propose `lsp(op=add, server=<preset>)` (typescript, python, rust, go, css, html) — it
|
|
32
|
-
always asks the user and needs nothing installed (`npx` fetches it); `op=list` shows what is configured.
|
|
33
|
-
Do not install language servers with bash yourself.
|
|
34
|
-
- Calling the same tool with identical args 3 times in a row is blocked (doom loop) — change approach.
|
|
35
|
-
- After 8 tool errors in a turn the harness asks you to stop and report.
|
|
36
|
-
- `delegate(tasks=[{agent, brief, context}…])` runs sub-agents (`explore` / `plan` / `review` /
|
|
37
|
-
`worker`) IN PARALLEL, each with a fresh context and a restricted toolset, and returns their reports
|
|
38
|
-
consolidated. `background=true` returns ids at once and each report arrives later as a message in
|
|
39
|
-
your context (do not poll); `action=list|steer|stop|result` manages them. Give a self-contained
|
|
40
|
-
brief — a child does not see this conversation, cannot ask the user and cannot delegate. Reports are
|
|
41
|
-
self-reports: verify before claiming success. Live logs: `.lampson/agents/<id>.log`.
|
|
42
|
-
|
|
43
|
-
## When you need the USER to run something
|
|
44
|
-
The user can run any command themselves from the chat by prefixing it with `!` — e.g. `!npm run dev`,
|
|
45
|
-
`!cat .env`, `!git push`. Their command runs without the permission policy and its output is added to
|
|
46
|
-
your context automatically. In the terminal REPL, `!` runs inside a real pseudo-terminal: prompts
|
|
47
|
-
(`y/N`, passwords, `npm init`) work — the user answers them inline. In the web UI there is also a
|
|
48
|
-
**full interactive terminal** (header button `>_ terminal`, a shell with cwd = workspace, opens in the
|
|
49
|
-
center pane like a file). Offer these when: a command needs an interactive terminal (logins, TUIs,
|
|
50
|
-
watching a dev server), when something is denied for you (secrets, dangerous commands), or when they
|
|
51
|
-
should verify a result with their own eyes. Say exactly what to type, e.g. "run `!npm run dev` (or open
|
|
52
|
-
the terminal button and run `npm run dev`), then tell me the URL".
|
|
53
|
-
|
|
54
|
-
## Provider, model, keys, images
|
|
55
|
-
- Provider/model/API keys live in `lampson/.lampson/config.json` (local); the user changes them with
|
|
56
|
-
`/setup`, `/provider`, or the `provider · model` pill in the web header. Never ask the user to paste a
|
|
57
|
-
key into the chat; point them there. Keys are sealed secrets: you cannot read or print them.
|
|
58
|
-
- The user can paste images in the web UI, or in the terminal with `/paste` (clipboard) and
|
|
59
|
-
`/image <path>`. If they say "look at this screenshot" in the terminal, tell them to copy it and type
|
|
60
|
-
`/paste`, then send their message. If your model has no vision, the image arrives as a text
|
|
61
|
-
note `[Image N WxHpx attached, but this model does not accept image input …]` — say so and suggest
|
|
62
|
-
a vision model instead of guessing what the image shows.
|
|
63
|
-
- Sessions can be deleted (`/delete <id>`, or ✕ in the web sidebar).
|
|
64
|
-
|
|
65
|
-
## Network exposure
|
|
66
|
-
- The web server listens on all interfaces but every `/api/*` route (and the terminal socket) only
|
|
67
|
-
accepts loopback clients; others get 401 unless they present `LAMPSON_WEB_TOKEN`. If the user asks
|
|
68
|
-
to use Lampson from another machine, point them to that token — never suggest removing the check.
|
|
69
|
-
|
|
70
|
-
## Agents / modes
|
|
71
|
-
- `build` (default): all tools. `plan`: read-only, produce a numbered plan. `review`: read + run
|
|
72
|
-
tests, never edit. `explore`: read-only search. The user switches with `/agent <name>`.
|
|
73
|
-
|
|
74
|
-
## Project memory (persistent notes)
|
|
75
|
-
- `memory(write, name, content)` saves a Markdown note about THIS project in Lampson's `memory/<project>/`
|
|
76
|
-
folder (outside the repo). The system prompt lists your notes; `memory(read, name)` loads one.
|
|
77
|
-
- Save what you would otherwise rediscover: how to run/test, env quirks, decisions, where things live,
|
|
78
|
-
root causes of bugs. Update notes instead of contradicting them. The user can read and edit them.
|
|
79
|
-
|
|
80
|
-
## Sessions and memory
|
|
81
|
-
- The whole history — including every tool result, error and DENIED message — is persisted in
|
|
82
|
-
`.lampson/sessions/<id>.json` and resent to you each turn, so you know exactly what happened.
|
|
83
|
-
- When the context grows past the compaction threshold, older turns are replaced by a summary that
|
|
84
|
-
keeps goals, files touched, current state, pending work and errors seen.
|
|
85
|
-
|
|
86
|
-
## Updating Lampson
|
|
87
|
-
- Lampson is installed as a git clone (`~/lampson`), so updating is a fast-forward pull. Both UIs
|
|
88
|
-
check `origin/main` on start and show a notice when a newer version exists (terminal banner, web
|
|
89
|
-
header button). The user updates with **`lampson --update`** in any terminal, `/update` in the REPL,
|
|
90
|
-
or the header button in the web UI — then restarts Lampson. Re-running the installer does the same.
|
|
91
|
-
- If asked "how do I update Lampson?", answer exactly that. If the pull fails because of local edits
|
|
92
|
-
in the lampson folder, suggest `git -C ~/lampson stash` first. (When the distribution changes —
|
|
93
|
-
desktop app, single binary — this section is the place that gets rewritten.)
|
|
94
|
-
|
|
95
|
-
## Extending the harness (if the user asks you to)
|
|
96
|
-
- One tool = one file `lib/tools/<name>.syn` exporting `task tool(...)` (its `require` lines at the
|
|
97
|
-
top of the body) and `let SPEC` (JSON Schema). Register it in `lib/tools.syn` (`use`, `registry()`,
|
|
98
|
-
`CATALOG`) and in the profiles of `lib/agents.syn`. `synsema check chat.syn` validates everything.
|
|
99
|
-
- Providers are raw HTTP (`lib/provider.syn`): OpenAI wire (`/chat/completions`) and Anthropic wire
|
|
100
|
-
(`/messages`). Config via `.env` (`LAMPSON_PROVIDER`, `LAMPSON_API_KEY`, `LAMPSON_MODEL`, `LAMPSON_BASE_URL`).
|
|
101
|
-
- Skills: `skills/<name>/SKILL.md` (harness), `workspace/skills/<name>/SKILL.md` (project),
|
|
102
|
-
`workspace/.lampson/skills/<name>/SKILL.md` (local), plus external ones installed with `npx skills add`
|
|
103
|
-
(`workspace/.agents/skills`, `workspace/.claude/skills`, and the global `~/.agents/skills` / `~/.claude/skills`
|
|
104
|
-
mounted as `.lampson/skills-global` / `.lampson/skills-claude`). Frontmatter `name:` + `description:`.
|
|
105
|
-
`skill(action=install, source=owner/repo, name=x, scope=global|project)` installs one (always asks the user).
|
|
106
|
-
- **Lamps** = tool plugins you can create for this project without touching the harness:
|
|
107
|
-
`lamp(action=create, name, manifest, files={"lamp.syn": "…"})` writes `workspace/.lampson/lamps/<name>/`,
|
|
108
|
-
validates the manifest and runs `synsema check` on a syn entry (it does not run or enable anything —
|
|
109
|
-
like dsh's cordis_define). Then `lamp(action=enable, name)` — the user must approve (a lamp is off until
|
|
110
|
-
a human turns it on). Build one when a task needs a reusable project-specific tool. Manifest:
|
|
111
|
-
`{"name", "description", "kind": "syn"|"exec", "entry": "lamp.syn" (syn) | "command": "python lamp.py" (exec),
|
|
112
|
-
"caps": "file.read=workspace/*" (syn, optional extra ceiling over stdout,time,env=LAMP_*), "timeout": 60,
|
|
113
|
-
"tools": [{"name", "description", "parameters": {JSON Schema}, "readonly": bool}]}`. Lamp names: letters,
|
|
114
|
-
digits, `-` (no `_`). Each call runs the lamp as ONE child process: `synsema run --cap-set <ceiling> entry`
|
|
115
|
-
for `syn`, the command for `exec`. Inside, read `LAMP_TOOL` and `LAMP_ARGS` (JSON) from env
|
|
116
|
-
(`require env("LAMP_*")` in a .syn) and print the result to stdout. A syn lamp cannot use more than its
|
|
117
|
-
manifest's `caps`; ask only for what the tool needs. Once on, its tools are `lamp_<name>_<tool>`.
|
|
1
|
+
---
|
|
2
|
+
name: lampson
|
|
3
|
+
description: How this harness works — tools, workspace mount, permissions, agents, sessions. Load when asked about Lampson itself or when a tool behaves unexpectedly.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lampson (the harness you are running in)
|
|
7
|
+
|
|
8
|
+
## Where you are
|
|
9
|
+
- Your tools only reach `workspace/` — the user's project, mounted as a junction/symlink by
|
|
10
|
+
`lampson.ps1 <path>` / `lampson.sh <path>`. All paths you pass are relative to that root.
|
|
11
|
+
- Anything outside (absolute paths, `..`, sibling dirs) fails with `Capability not granted`.
|
|
12
|
+
That is by design (Synsema deny-by-default + `call_tool` least-privilege). Do not try to work
|
|
13
|
+
around it; tell the user if you genuinely need something outside the workspace.
|
|
14
|
+
- `bash` runs with cwd = workspace root and a hard timeout (default 120 s): when it expires the command AND
|
|
15
|
+
its child processes are killed. Never run servers/watchers/REPLs in `bash`; use the `process` tool:
|
|
16
|
+
`process(start, name="web", command="npm run dev")`, then `process(logs, name="web")`, and
|
|
17
|
+
`process(stop, name="web")` when done. New log lines of every managed process are appended to each
|
|
18
|
+
`bash` result automatically — you SEE the server's console (errors, requests, crashes) without asking.
|
|
19
|
+
The user sees the same logs live in the web UI ("Procesos" panel). Its child process is NOT confined by Synsema; dangerous
|
|
20
|
+
commands are screened by `permission.syn` (hardline = always denied; dangerous = needs the user's
|
|
21
|
+
approval in `ask` mode, denied in `strict`, allowed in `yolo`).
|
|
22
|
+
|
|
23
|
+
## Tool behavior worth knowing
|
|
24
|
+
- `edit` needs an exact, unique `old_string`; if it fails, `read` the region again and retry with
|
|
25
|
+
more context. `replace_all=true` for intentional multi-replace.
|
|
26
|
+
- `read` returns up to 2000 lines; use `offset`/`limit` for big files. Outputs > 30k chars are truncated.
|
|
27
|
+
- `find` is a simple glob (`*.ts`, `test_*`, `*config*`), `grep` is regex by default (`regex=false` for literals).
|
|
28
|
+
- `lsp(op=symbols, path)` is the cheapest way to understand a big file: every function/class/variable
|
|
29
|
+
with its line range — then `read` only the range you need. `definition` / `references` / `hover` /
|
|
30
|
+
`implementation` take 1-based `line` + `character` ON the identifier. If no server is configured for
|
|
31
|
+
that extension, propose `lsp(op=add, server=<preset>)` (typescript, python, rust, go, css, html) — it
|
|
32
|
+
always asks the user and needs nothing installed (`npx` fetches it); `op=list` shows what is configured.
|
|
33
|
+
Do not install language servers with bash yourself.
|
|
34
|
+
- Calling the same tool with identical args 3 times in a row is blocked (doom loop) — change approach.
|
|
35
|
+
- After 8 tool errors in a turn the harness asks you to stop and report.
|
|
36
|
+
- `delegate(tasks=[{agent, brief, context}…])` runs sub-agents (`explore` / `plan` / `review` /
|
|
37
|
+
`worker`) IN PARALLEL, each with a fresh context and a restricted toolset, and returns their reports
|
|
38
|
+
consolidated. `background=true` returns ids at once and each report arrives later as a message in
|
|
39
|
+
your context (do not poll); `action=list|steer|stop|result` manages them. Give a self-contained
|
|
40
|
+
brief — a child does not see this conversation, cannot ask the user and cannot delegate. Reports are
|
|
41
|
+
self-reports: verify before claiming success. Live logs: `.lampson/agents/<id>.log`.
|
|
42
|
+
|
|
43
|
+
## When you need the USER to run something
|
|
44
|
+
The user can run any command themselves from the chat by prefixing it with `!` — e.g. `!npm run dev`,
|
|
45
|
+
`!cat .env`, `!git push`. Their command runs without the permission policy and its output is added to
|
|
46
|
+
your context automatically. In the terminal REPL, `!` runs inside a real pseudo-terminal: prompts
|
|
47
|
+
(`y/N`, passwords, `npm init`) work — the user answers them inline. In the web UI there is also a
|
|
48
|
+
**full interactive terminal** (header button `>_ terminal`, a shell with cwd = workspace, opens in the
|
|
49
|
+
center pane like a file). Offer these when: a command needs an interactive terminal (logins, TUIs,
|
|
50
|
+
watching a dev server), when something is denied for you (secrets, dangerous commands), or when they
|
|
51
|
+
should verify a result with their own eyes. Say exactly what to type, e.g. "run `!npm run dev` (or open
|
|
52
|
+
the terminal button and run `npm run dev`), then tell me the URL".
|
|
53
|
+
|
|
54
|
+
## Provider, model, keys, images
|
|
55
|
+
- Provider/model/API keys live in `lampson/.lampson/config.json` (local); the user changes them with
|
|
56
|
+
`/setup`, `/provider`, or the `provider · model` pill in the web header. Never ask the user to paste a
|
|
57
|
+
key into the chat; point them there. Keys are sealed secrets: you cannot read or print them.
|
|
58
|
+
- The user can paste images in the web UI, or in the terminal with `/paste` (clipboard) and
|
|
59
|
+
`/image <path>`. If they say "look at this screenshot" in the terminal, tell them to copy it and type
|
|
60
|
+
`/paste`, then send their message. If your model has no vision, the image arrives as a text
|
|
61
|
+
note `[Image N WxHpx attached, but this model does not accept image input …]` — say so and suggest
|
|
62
|
+
a vision model instead of guessing what the image shows.
|
|
63
|
+
- Sessions can be deleted (`/delete <id>`, or ✕ in the web sidebar).
|
|
64
|
+
|
|
65
|
+
## Network exposure
|
|
66
|
+
- The web server listens on all interfaces but every `/api/*` route (and the terminal socket) only
|
|
67
|
+
accepts loopback clients; others get 401 unless they present `LAMPSON_WEB_TOKEN`. If the user asks
|
|
68
|
+
to use Lampson from another machine, point them to that token — never suggest removing the check.
|
|
69
|
+
|
|
70
|
+
## Agents / modes
|
|
71
|
+
- `build` (default): all tools. `plan`: read-only, produce a numbered plan. `review`: read + run
|
|
72
|
+
tests, never edit. `explore`: read-only search. The user switches with `/agent <name>`.
|
|
73
|
+
|
|
74
|
+
## Project memory (persistent notes)
|
|
75
|
+
- `memory(write, name, content)` saves a Markdown note about THIS project in Lampson's `memory/<project>/`
|
|
76
|
+
folder (outside the repo). The system prompt lists your notes; `memory(read, name)` loads one.
|
|
77
|
+
- Save what you would otherwise rediscover: how to run/test, env quirks, decisions, where things live,
|
|
78
|
+
root causes of bugs. Update notes instead of contradicting them. The user can read and edit them.
|
|
79
|
+
|
|
80
|
+
## Sessions and memory
|
|
81
|
+
- The whole history — including every tool result, error and DENIED message — is persisted in
|
|
82
|
+
`.lampson/sessions/<id>.json` and resent to you each turn, so you know exactly what happened.
|
|
83
|
+
- When the context grows past the compaction threshold, older turns are replaced by a summary that
|
|
84
|
+
keeps goals, files touched, current state, pending work and errors seen.
|
|
85
|
+
|
|
86
|
+
## Updating Lampson
|
|
87
|
+
- Lampson is installed as a git clone (`~/lampson`), so updating is a fast-forward pull. Both UIs
|
|
88
|
+
check `origin/main` on start and show a notice when a newer version exists (terminal banner, web
|
|
89
|
+
header button). The user updates with **`lampson --update`** in any terminal, `/update` in the REPL,
|
|
90
|
+
or the header button in the web UI — then restarts Lampson. Re-running the installer does the same.
|
|
91
|
+
- If asked "how do I update Lampson?", answer exactly that. If the pull fails because of local edits
|
|
92
|
+
in the lampson folder, suggest `git -C ~/lampson stash` first. (When the distribution changes —
|
|
93
|
+
desktop app, single binary — this section is the place that gets rewritten.)
|
|
94
|
+
|
|
95
|
+
## Extending the harness (if the user asks you to)
|
|
96
|
+
- One tool = one file `lib/tools/<name>.syn` exporting `task tool(...)` (its `require` lines at the
|
|
97
|
+
top of the body) and `let SPEC` (JSON Schema). Register it in `lib/tools.syn` (`use`, `registry()`,
|
|
98
|
+
`CATALOG`) and in the profiles of `lib/agents.syn`. `synsema check chat.syn` validates everything.
|
|
99
|
+
- Providers are raw HTTP (`lib/provider.syn`): OpenAI wire (`/chat/completions`) and Anthropic wire
|
|
100
|
+
(`/messages`). Config via `.env` (`LAMPSON_PROVIDER`, `LAMPSON_API_KEY`, `LAMPSON_MODEL`, `LAMPSON_BASE_URL`).
|
|
101
|
+
- Skills: `skills/<name>/SKILL.md` (harness), `workspace/skills/<name>/SKILL.md` (project),
|
|
102
|
+
`workspace/.lampson/skills/<name>/SKILL.md` (local), plus external ones installed with `npx skills add`
|
|
103
|
+
(`workspace/.agents/skills`, `workspace/.claude/skills`, and the global `~/.agents/skills` / `~/.claude/skills`
|
|
104
|
+
mounted as `.lampson/skills-global` / `.lampson/skills-claude`). Frontmatter `name:` + `description:`.
|
|
105
|
+
`skill(action=install, source=owner/repo, name=x, scope=global|project)` installs one (always asks the user).
|
|
106
|
+
- **Lamps** = tool plugins you can create for this project without touching the harness:
|
|
107
|
+
`lamp(action=create, name, manifest, files={"lamp.syn": "…"})` writes `workspace/.lampson/lamps/<name>/`,
|
|
108
|
+
validates the manifest and runs `synsema check` on a syn entry (it does not run or enable anything —
|
|
109
|
+
like dsh's cordis_define). Then `lamp(action=enable, name)` — the user must approve (a lamp is off until
|
|
110
|
+
a human turns it on). Build one when a task needs a reusable project-specific tool. Manifest:
|
|
111
|
+
`{"name", "description", "kind": "syn"|"exec", "entry": "lamp.syn" (syn) | "command": "python lamp.py" (exec),
|
|
112
|
+
"caps": "file.read=workspace/*" (syn, optional extra ceiling over stdout,time,env=LAMP_*), "timeout": 60,
|
|
113
|
+
"tools": [{"name", "description", "parameters": {JSON Schema}, "readonly": bool}]}`. Lamp names: letters,
|
|
114
|
+
digits, `-` (no `_`). Each call runs the lamp as ONE child process: `synsema run --cap-set <ceiling> entry`
|
|
115
|
+
for `syn`, the command for `exec`. Inside, read `LAMP_TOOL` and `LAMP_ARGS` (JSON) from env
|
|
116
|
+
(`require env("LAMP_*")` in a .syn) and print the result to stdout. A syn lamp cannot use more than its
|
|
117
|
+
manifest's `caps`; ask only for what the tool needs. Once on, its tools are `lamp_<name>_<tool>`.
|
package/skills/synsema/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: synsema
|
|
|
3
3
|
description: Writing, checking, running and testing Synsema (.syn) code — syntax reflexes, capabilities, live processes / pseudo-terminals, and the runtime traps that cost hours. Load before touching any .syn file.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Synsema quick reference (v0.6.
|
|
6
|
+
# Synsema quick reference (v0.6.11)
|
|
7
7
|
|
|
8
8
|
> Curated 10 KB summary for the agent (the full reference is ~450 KB and lives in the user's editor
|
|
9
9
|
> skill). Kept in sync by hand with each `synsema update`; if `synsema --version` is newer than the
|
|
@@ -22,6 +22,11 @@ description: Writing, checking, running and testing Synsema (.syn) code — synt
|
|
|
22
22
|
- `try` … `recover err` (recover SWALLOWS; `raise(err)` to re-throw) · `raise("msg")`
|
|
23
23
|
- `contains(xs, x)` (on maps checks KEYS) · `append(xs, x)` returns a NEW list → `set xs to append(xs, x)`
|
|
24
24
|
- `apply(f, xs)`, `where(xs, p)`, `sort_by(xs, f)`, `slice(xs, a, b)`, `split/join/trim/lower/upper`
|
|
25
|
+
- Text/regex: `replace_text(t, old, new)` (literal), `replace_re(t, re, rep)` (`\1` backrefs), `capture(t, re)`
|
|
26
|
+
(first match; with groups → list), `find_all`, `matches` (**full match** only — not a search).
|
|
27
|
+
There is NO `replace`, `regex_replace`, `chars`, `repeat`. Rust regex: no lookahead/lookbehind.
|
|
28
|
+
In `"..."` strings backslashes are literal: write `"\d"`, `"\*"` (`"\\d"` is a literal `\d`).
|
|
29
|
+
Anonymous functions: `(x) => expr` only (no inline `task(x)`).
|
|
25
30
|
- `json_encode / json_decode` · `length` · `text(x)` · `number(s)` (ALWAYS float → `floor()` for ints)
|
|
26
31
|
- Modules: `use "./m.syn" as m` (local only, never `../`), `export task/let`. A module cannot have
|
|
27
32
|
top-level `require` or `serve` — the ENTRY file grants capabilities.
|
|
@@ -50,6 +55,12 @@ description: Writing, checking, running and testing Synsema (.syn) code — synt
|
|
|
50
55
|
`proc_spawn` in a handler is gone when the handler returns. A process that must outlive requests lives
|
|
51
56
|
inside an `agent` spawned from the handler (own lifecycle; blackboard `share/observe` + `bus_*` are shared
|
|
52
57
|
with handlers). That is how lampson's `process` tool works (`lib/tools/proc.syn`).
|
|
58
|
+
- **Own terminal / raw keys (v0.6.11+)**: `let h be term_open({"ctrl_c": "exit"})` → `nothing` without a
|
|
59
|
+
TTY / under `test`/`serve` (fall back to `read_line`); `term_recv(h, secs)` → `{type: "key", key, text,
|
|
60
|
+
ctrl, alt, shift}` (`key` = `"char"|"enter"|"tab"|"backspace"|"up"|…`), `paste`, `resize`, `eof`;
|
|
61
|
+
draw with `term_write(h, ansi)` (**`print` stays buffered**); `term_size(h)`; `term_close(h)`. Alt+Enter
|
|
62
|
+
always arrives (Shift+Enter needs kitty protocol). `ask/approve` still work while open. Lampson's line
|
|
63
|
+
editor is `lib/line.syn`; drive a terminal UI in tests via `proc_spawn(…, {pty: true})` (`tty_test.syn`).
|
|
53
64
|
- **File watch (v0.6.9+)**: `let w be watch("src", {"interval": 0.2, "ignore": ["*.tmp"]})` → events
|
|
54
65
|
`{type: "create"|"modify"|"delete", path, is_dir}` via `watch_recv(w, secs)` or `select`; polling with a
|
|
55
66
|
snapshot (latency = interval), `watch_close(w)`. Gate: `file("src")` + `file("src/*")`.
|
|
@@ -67,7 +78,9 @@ description: Writing, checking, running and testing Synsema (.syn) code — synt
|
|
|
67
78
|
- `localhost` resolves to IPv6; use `127.0.0.1`.
|
|
68
79
|
- `run("bash", ...)` hangs on Windows (WSL bash) → `C:\Program Files\Git\bin\bash.exe` or `cmd /c`.
|
|
69
80
|
- A task named `run` shadows the builtin `run` (infinite recursion).
|
|
70
|
-
- Reserved words that break variable/param names: `reason task ask stop decide analyze generate show approve confirm`.
|
|
81
|
+
- Reserved words that break variable/param names: `reason task ask stop type run decide analyze generate show approve confirm`.
|
|
82
|
+
- Reading a MISSING map key is a runtime error (`Map has no key 'x'`), not `nothing` → `contains(m, "x")` first.
|
|
83
|
+
- Maps are passed by reference: `set m["k"] to v` inside a task IS visible to the caller (lists via `append` are not — it returns a new list).
|
|
71
84
|
- `and`/`or` do NOT short-circuit → nest `when` before indexing.
|
|
72
85
|
- No `merge`: add a key with `set m["k"] to v`. No `append_file`: read + write (atomic; parents created).
|
|
73
86
|
- Runtime error messages are Capitalized (`Not a directory: …`) and `contains` is case-sensitive → compare `lower(text(err))`.
|