@topolo/cli 0.12.33 → 0.13.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/README.md +45 -0
- package/agent-packs/README.md +495 -0
- package/agent-packs/pyproject.toml +16 -0
- package/agent-packs/requirements-test.txt +1 -0
- package/agent-packs/src/topolo_agent_pack/__init__.py +1 -0
- package/agent-packs/src/topolo_agent_pack/blueprint.py +57 -0
- package/agent-packs/src/topolo_agent_pack/claude.py +265 -0
- package/agent-packs/src/topolo_agent_pack/cli.py +443 -0
- package/agent-packs/src/topolo_agent_pack/execution.py +154 -0
- package/agent-packs/src/topolo_agent_pack/fresh.py +158 -0
- package/agent-packs/src/topolo_agent_pack/live.py +403 -0
- package/agent-packs/src/topolo_agent_pack/native.py +645 -0
- package/agent-packs/src/topolo_agent_pack/policy.py +92 -0
- package/agent-packs/src/topolo_agent_pack/storage.py +271 -0
- package/agent-packs/src/topolo_agent_pack/topolo.py +321 -0
- package/agent-packs/templates/career/AGENTS.md +17 -0
- package/agent-packs/templates/career/README.md +14 -0
- package/agent-packs/templates/career/agents/intakes/career-intake/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/application-preparation/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/application-tracker/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/interview-coach/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/opportunity-research/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/profile-cv/AGENTS.md +21 -0
- package/agent-packs/templates/career/pack.json +124 -0
- package/agent-packs/templates/career/shared/PACK.md +22 -0
- package/agent-packs/templates/career/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/career/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/career/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/clients/AGENTS.md +17 -0
- package/agent-packs/templates/clients/README.md +14 -0
- package/agent-packs/templates/clients/agents/intakes/client-intake/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/acceptance-review/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/delivery-planner/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/discovery/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/proposal-writer/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/solution-design/AGENTS.md +21 -0
- package/agent-packs/templates/clients/pack.json +126 -0
- package/agent-packs/templates/clients/shared/PACK.md +22 -0
- package/agent-packs/templates/clients/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/clients/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/clients/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/creative/AGENTS.md +17 -0
- package/agent-packs/templates/creative/README.md +14 -0
- package/agent-packs/templates/creative/agents/intakes/creative-director/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/brand-copy/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/media-production/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/quality-review/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/storytelling/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/visual-design/AGENTS.md +21 -0
- package/agent-packs/templates/creative/pack.json +128 -0
- package/agent-packs/templates/creative/shared/PACK.md +22 -0
- package/agent-packs/templates/creative/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/creative/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/creative/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/founder/AGENTS.md +17 -0
- package/agent-packs/templates/founder/README.md +14 -0
- package/agent-packs/templates/founder/agents/intakes/founder-intake/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/commercial-modelling/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/customer-research/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/decision-review/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/partnerships/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/strategy/AGENTS.md +21 -0
- package/agent-packs/templates/founder/pack.json +126 -0
- package/agent-packs/templates/founder/shared/PACK.md +22 -0
- package/agent-packs/templates/founder/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/founder/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/founder/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/learning/AGENTS.md +17 -0
- package/agent-packs/templates/learning/README.md +14 -0
- package/agent-packs/templates/learning/agents/intakes/learning-intake/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/critical-reviewer/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/curriculum-designer/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/knowledge-steward/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/practice-coach/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/tutor/AGENTS.md +21 -0
- package/agent-packs/templates/learning/pack.json +124 -0
- package/agent-packs/templates/learning/shared/PACK.md +22 -0
- package/agent-packs/templates/learning/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/learning/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/learning/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/personal/AGENTS.md +17 -0
- package/agent-packs/templates/personal/README.md +14 -0
- package/agent-packs/templates/personal/agents/intakes/personal-intake/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/correspondence/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/document-assistant/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/planning/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/research/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/travel-logistics/AGENTS.md +21 -0
- package/agent-packs/templates/personal/pack.json +125 -0
- package/agent-packs/templates/personal/shared/PACK.md +22 -0
- package/agent-packs/templates/personal/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/personal/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/personal/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/research/AGENTS.md +17 -0
- package/agent-packs/templates/research/README.md +14 -0
- package/agent-packs/templates/research/agents/intakes/research-intake/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/adversarial-review/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/data-analysis/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/source-research/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/synthesis/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/technical-research/AGENTS.md +21 -0
- package/agent-packs/templates/research/pack.json +124 -0
- package/agent-packs/templates/research/shared/PACK.md +22 -0
- package/agent-packs/templates/research/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/research/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/research/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/ventures/AGENTS.md +17 -0
- package/agent-packs/templates/ventures/README.md +14 -0
- package/agent-packs/templates/ventures/agents/intakes/venture-intake/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/customer-discovery/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/economics/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/experiment-design/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/market-research/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/product-concept/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/pack.json +126 -0
- package/agent-packs/templates/ventures/shared/PACK.md +22 -0
- package/agent-packs/templates/ventures/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/ventures/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/ventures/skills/topolo/SKILL.md +305 -0
- package/agent-packs/topolo-agent-pack +8 -0
- package/dist/claude-pack-backend-IDQQX3DG.js +555 -0
- package/dist/index.js +143 -58
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -362,3 +362,48 @@ If refresh fails (network, rotated/revoked refresh token), the CLI proceeds
|
|
|
362
362
|
with the stale credential and the request returns `auth_error` — run
|
|
363
363
|
`topolo auth login` to re-authenticate. The stored config is not cleared on
|
|
364
364
|
transient refresh failures.
|
|
365
|
+
|
|
366
|
+
## Topolo Agent Packs
|
|
367
|
+
|
|
368
|
+
`topolo agent-packs` is the public entry point for portable business agent packs.
|
|
369
|
+
The CLI bundles the Codex adapter; Python 3.11+ and the supported Codex desktop
|
|
370
|
+
installation are required for native local switching. No separate pack CLI
|
|
371
|
+
installation is needed. Claude and Cursor adapters are planned and currently
|
|
372
|
+
refused before any mutation. MCP setup for those apps is separate from pack
|
|
373
|
+
switching and does not establish pack adapter support.
|
|
374
|
+
|
|
375
|
+
```sh
|
|
376
|
+
topolo agent-packs add founder --harness codex
|
|
377
|
+
topolo agent-packs add founder --group specialists
|
|
378
|
+
topolo agent-packs add founder --agent strategy
|
|
379
|
+
topolo agent-packs switch founder
|
|
380
|
+
topolo agent-packs status
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
A first add builds the bundled template into a fresh installed instance. Later
|
|
384
|
+
adds and switches resume that instance. `--group` selects the template's set;
|
|
385
|
+
`--agent` selects an unambiguous logical agent. Use `list` to inspect installed
|
|
386
|
+
names. Pack templates retain operating rules, rather than earlier work history.
|
|
387
|
+
The underlying `topolo-agent-pack` adapter contains native switching and recovery.
|
|
388
|
+
|
|
389
|
+
Cloud continuity uses explicit environment and authenticated context pins:
|
|
390
|
+
|
|
391
|
+
```sh
|
|
392
|
+
topolo --env production agent-packs connect founder \
|
|
393
|
+
--environment production --context-key org:customer \
|
|
394
|
+
--agent-workspace DISCOVERED_AGENT_WORKSPACE \
|
|
395
|
+
--bytes-workspace DISCOVERED_BYTES_WORKSPACE \
|
|
396
|
+
--ownership user --bytes-scope private --roles roles.json --confirm
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
`roles.json` maps every `set/agent` to an existing, exactly published
|
|
400
|
+
`agentId` and `agentVersionId`. The hosted Agent and Bytes contracts must be
|
|
401
|
+
released in the selected environment first. The CLI does not create grants,
|
|
402
|
+
choose another customer, invoke model work or silently publish agent versions.
|
|
403
|
+
See the bundled adapter README for memory, artifact and recovery commands.
|
|
404
|
+
|
|
405
|
+
The source quality gate covers the CLI dispatcher and the Python continuity
|
|
406
|
+
adapter separately. `pnpm coverage` creates a local test environment under
|
|
407
|
+
`node_modules/.cache`, installs the pinned test-only coverage tool and requires
|
|
408
|
+
100% line and branch coverage for the cloud connection/recovery adapter.
|
|
409
|
+
These tests use scoped fixtures and do not invoke models or mutate cloud data.
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
# topolo-agent-pack
|
|
2
|
+
|
|
3
|
+
A local CLI for real Codex thread packs. Each pack contains agent sets, native
|
|
4
|
+
thread identities, conversation history, inherited history and portable
|
|
5
|
+
instruction definitions. Storage lives outside Codex in `~/AgentPacks`.
|
|
6
|
+
|
|
7
|
+
Version 0.4.0 supports authored templates and changing packs inside one managed macOS desktop window.
|
|
8
|
+
The window and desktop process stay open. Its idle backend reconnects to the
|
|
9
|
+
incoming native runtime, the sidebar catalog reconciles, and the view reloads.
|
|
10
|
+
This changes the actual backend storage, not just thread visibility.
|
|
11
|
+
|
|
12
|
+
## Build from an authored template
|
|
13
|
+
|
|
14
|
+
Version 0.4.0 adds source-independent construction. A template is a regular
|
|
15
|
+
directory containing `pack.json`, common `AGENTS.md`, individual
|
|
16
|
+
`agents/<set>/<id>/AGENTS.md`, selected `shared/*.md`, and optional public
|
|
17
|
+
`skills/<name>/SKILL.md` instructions. It has no native thread IDs or conversations.
|
|
18
|
+
See the bundled `templates/` catalog for eight examples.
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
topolo-agent-pack build founder-acme --template /path/to/templates/founder
|
|
22
|
+
topolo-agent-pack switch founder-acme
|
|
23
|
+
topolo-agent-pack build creative-acme --template /path/to/templates/creative --set specialists
|
|
24
|
+
topolo-agent-pack build venture-economics --template /path/to/templates/ventures --agent economics
|
|
25
|
+
topolo-agent-pack add venture-economics --agent economics
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Every build creates unique native thread IDs and file-backed workspaces. Existing
|
|
29
|
+
instance names are refused, so build never resets working conversations. Normal
|
|
30
|
+
switching resumes an instance. Build supports the same set and agent selection
|
|
31
|
+
as fresh, add and replace. Template skills contain Markdown instructions only;
|
|
32
|
+
credentials and account integrations must be configured locally. The digest
|
|
33
|
+
covers the portable roster, role guides and references. The schema, role IDs,
|
|
34
|
+
placements, size and symlink checks run before native construction.
|
|
35
|
+
|
|
36
|
+
The initial catalog includes founder, creative, research, clients, career,
|
|
37
|
+
personal, learning and ventures: six roles per pack. These are prepared Codex
|
|
38
|
+
packs. Claude/Cursor adapters, independent customer outcome evaluation and
|
|
39
|
+
clean-machine onboarding are separate product work. No model turns are run
|
|
40
|
+
during construction or protocol verification.
|
|
41
|
+
|
|
42
|
+
## Install and use
|
|
43
|
+
|
|
44
|
+
Python 3.11+; no Python dependencies or API key for pack operations.
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
python3 install.py
|
|
48
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
49
|
+
topolo-agent-pack capture topolo --source-home "$HOME/.codex"
|
|
50
|
+
topolo-agent-pack switch topolo
|
|
51
|
+
topolo-agent-pack switch personal
|
|
52
|
+
topolo-agent-pack switch topolo
|
|
53
|
+
topolo-agent-pack status
|
|
54
|
+
topolo-agent-pack recover
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Capture `personal` from the intended profile before switching to it:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
topolo-agent-pack capture personal --source-home /path/to/personal-codex-home --all
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**One-time setup:** the first switch opens a manager-owned Codex window, using its
|
|
64
|
+
own local desktop profile. Authenticate there if prompted. It can coexist with
|
|
65
|
+
your current window. Subsequent switches replace packs inside that exact managed
|
|
66
|
+
window; Codex does not need to close. The bridge cannot be attached to an
|
|
67
|
+
already-running unmanaged window. The first launch is reported as requested,
|
|
68
|
+
not as a verified frontend activation.
|
|
69
|
+
|
|
70
|
+
`topolo-agent-pack open` reopens a selected managed pack after you have closed its
|
|
71
|
+
window. `--no-open` stages and verifies storage without opening a window. If the
|
|
72
|
+
managed window is already open, this flag still reconnects it so it cannot remain
|
|
73
|
+
attached to stale storage.
|
|
74
|
+
|
|
75
|
+
The CLI refuses switches while agents have active turns. It briefly waits for
|
|
76
|
+
ordinary backend requests to settle. It never force-stops active agents or an
|
|
77
|
+
unmanaged Codex profile. Recovery also checks for active work before reconnecting.
|
|
78
|
+
|
|
79
|
+
## Compose sets and agents
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
topolo-agent-pack add topolo --set specialists
|
|
83
|
+
topolo-agent-pack add topolo --set specialists --agent security
|
|
84
|
+
topolo-agent-pack replace topolo --set operators
|
|
85
|
+
topolo-agent-pack replace topolo --agent security
|
|
86
|
+
topolo-agent-pack replace personal --agent planner --target topolo/intakes/engineering
|
|
87
|
+
topolo-agent-pack plan add topolo --set operator-skills
|
|
88
|
+
topolo-agent-pack list topolo
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Selectors can repeat, and accept semantic IDs, unique aliases or
|
|
92
|
+
`PACK/SET/AGENT`. Ambiguous aliases fail. `add` keeps existing agents and is
|
|
93
|
+
idempotent for the same revision. Conflicting revisions require `replace`.
|
|
94
|
+
`--target PACK[/SET[/AGENT]]` chooses an explicit outgoing scope. An unscoped
|
|
95
|
+
replace replaces the whole composition.
|
|
96
|
+
|
|
97
|
+
Whole-pack switches retain outgoing runtimes and return to each pack's latest
|
|
98
|
+
saved workbench, including subsequent conversation and workspace edits. Use
|
|
99
|
+
`switch NAME --fresh` to deliberately rebuild the captured source instead.
|
|
100
|
+
Add/replace checkpoints the current composition before building a new runtime.
|
|
101
|
+
Old snapshots and runtimes are retained; there is no automatic deletion.
|
|
102
|
+
If you create additional independent threads in the managed window, partial
|
|
103
|
+
composition refuses to omit them. Register them with `capture NAME --all`, then
|
|
104
|
+
`switch NAME --fresh`, before another add/replace. Whole switches retain them.
|
|
105
|
+
|
|
106
|
+
Publish an evolved composition with `capture my-workbench`, then export it.
|
|
107
|
+
Captured source revisions and saved workbenches are distinct: a saved personal
|
|
108
|
+
workbench can contain sets added from Topolo without changing the personal source
|
|
109
|
+
manifest.
|
|
110
|
+
|
|
111
|
+
## Fresh agents with reusable operating context
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
topolo-agent-pack context topolo ./topolo-context
|
|
115
|
+
# Review/edit AGENTS.md, agents/<set>/<agent>/AGENTS.md and shared/*.md.
|
|
116
|
+
topolo-agent-pack fresh topolo topolo-clean --context ./topolo-context
|
|
117
|
+
topolo-agent-pack switch topolo-clean
|
|
118
|
+
topolo-agent-pack fresh topolo sprint-one --context ./topolo-context --set specialists
|
|
119
|
+
topolo-agent-pack fresh topolo design-next --context ./topolo-context --agent design-operator
|
|
120
|
+
topolo-agent-pack add design-next
|
|
121
|
+
topolo-agent-pack replace design-next --target topolo/operators/design-operator
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`context` creates editable role scaffolds and extracts bounded conversation rule
|
|
125
|
+
candidates (including inherited sources) into `review/`, with provenance. Review
|
|
126
|
+
and distill those candidates and relevant existing role guides into operating
|
|
127
|
+
instructions. Candidate extraction is keyword assisted, not an exhaustive semantic
|
|
128
|
+
audit. Raw excerpts, review files and prior work records never enter a fresh pack.
|
|
129
|
+
|
|
130
|
+
`fresh SOURCE NEW-NAME --context DIRECTORY` creates genuine new native thread IDs,
|
|
131
|
+
one per selected role, with no fork ancestors, previous conversations, goals,
|
|
132
|
+
attachments, active tasks or old memory store. Each agent gets common operating
|
|
133
|
+
rules, its role guide, selected `shared/*.md` references and a generated TEAM.md
|
|
134
|
+
containing the fresh team's IDs. Existing authored skills are retained. Optional
|
|
135
|
+
`agents/<set>/<agent>/config.json` selects a reviewed model/reasoning preset:
|
|
136
|
+
`{"model":"gpt-6.1-sol","reasoningEffort":"high"}`. Native permission defaults apply;
|
|
137
|
+
machine-local integrations and credentials remain separately configured.
|
|
138
|
+
|
|
139
|
+
The native backend creates threads and imports a short bootstrap instruction
|
|
140
|
+
without starting model turns. An offline adapter writes the bootstrap user event
|
|
141
|
+
in the stopped private seed so the desktop catalog can discover it. The native
|
|
142
|
+
catalog and zero-turn state are checked before publication. Starting messages
|
|
143
|
+
contain operating/setup context only. Native memory is disabled for seeded roles;
|
|
144
|
+
file-backed instructions provide the reusable context. Creation leaves the current
|
|
145
|
+
window alone. A destination name already in use is rejected to protect its work.
|
|
146
|
+
|
|
147
|
+
Fresh packs use the ordinary export/install/add/replace/switch/recover paths.
|
|
148
|
+
Exporting the fresh pack carries only its new starting context, not source work
|
|
149
|
+
history. Editing a context directory changes future instances; already-created
|
|
150
|
+
instances retain their own files and later conversations. To return to ongoing
|
|
151
|
+
work, switch to its saved pack normally.
|
|
152
|
+
|
|
153
|
+
**`switch NAME --fresh` is different:** it rebuilds NAME's captured snapshot,
|
|
154
|
+
including any captured work history. Use the `fresh` command to create clean agents.
|
|
155
|
+
|
|
156
|
+
## Live capture and portability
|
|
157
|
+
|
|
158
|
+
Capture works while Codex stays open. Read-only SQLite snapshots and complete
|
|
159
|
+
rollout prefixes retain projected history and fork/child dependencies. Work
|
|
160
|
+
started after the snapshot remains in the source profile. The snapshot is not an
|
|
161
|
+
ongoing replica. `--offline` instead requires an idle source and checks that its
|
|
162
|
+
files do not change during capture.
|
|
163
|
+
|
|
164
|
+
`capture topolo` selects Topolo Specialists, Topolo Operators, Topolo Operator
|
|
165
|
+
Skills and Topolo-named pinned intakes. `--all` explicitly selects a whole profile.
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
topolo-agent-pack export topolo ./topolo.pack
|
|
169
|
+
topolo-agent-pack install ./topolo.pack
|
|
170
|
+
topolo-agent-pack install ./topolo.pack --set specialists --agent security
|
|
171
|
+
topolo-agent-pack switch topolo --fresh --map /old/repository=/new/repository
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Bundles contain SHA-256 checked manifests and objects, and install independently
|
|
175
|
+
of the original Codex home. Copy the CLI source archive and pack bundles to a
|
|
176
|
+
clean machine. macOS desktop switching is implemented; Linux supports storage
|
|
177
|
+
and native verification with `--no-open`. Windows is not supported.
|
|
178
|
+
|
|
179
|
+
Default capture copies ordinary workspace files and uncommitted changes.
|
|
180
|
+
Generated directories, Git administration, symlinks, credential files and
|
|
181
|
+
`.env` files are excluded and reported. Repository checkout/setup, worktree
|
|
182
|
+
registration, external services and executable dependencies still need local
|
|
183
|
+
provisioning. Map engineering agents to a local checked-out repository when that
|
|
184
|
+
is their intended environment. Explicit mapping destinations are never overwritten.
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
topolo-agent-pack capture topolo --workspace-mode reference
|
|
188
|
+
topolo-agent-pack capture topolo --include /path/to/workflow-assets
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Reference captures store history and instructions while leaving workspaces as
|
|
192
|
+
external paths. These paths must exist or be mapped on the destination machine.
|
|
193
|
+
Authored skills, agent definitions and global AGENTS.md are portable. MCP/plugin
|
|
194
|
+
requirements are declared; install and authorize those tools locally. Put a full
|
|
195
|
+
machine-local configuration in `AgentPacks/local-config.toml` if needed.
|
|
196
|
+
Authentication stays local to the managed profile and follows rebuilt runtimes;
|
|
197
|
+
accounts, cookies and cloud artifacts are not exported.
|
|
198
|
+
|
|
199
|
+
Conversation history can contain sensitive material. Filename exclusions do not
|
|
200
|
+
scrub conversations. Bundles are private files and are not encrypted.
|
|
201
|
+
|
|
202
|
+
## Desktop moving parts and recovery
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
objects/ immutable content addressed by SHA-256
|
|
206
|
+
packs/ immutable captures and revision heads
|
|
207
|
+
runtimes/ independent native homes and workspace checkpoints
|
|
208
|
+
workbenches/ saved compositions and their latest runtimes
|
|
209
|
+
desktop-home/ stable desktop IPC home; native files route to selected runtime
|
|
210
|
+
desktop-data/ shared machine-local desktop account and preferences
|
|
211
|
+
selected-runtime atomic route to the selected runtime
|
|
212
|
+
launchers/ owned native-backend proxy
|
|
213
|
+
journals/ transaction and recovery receipts
|
|
214
|
+
active.json atomically committed composition
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The desktop starts through an owned backend proxy. A private local control
|
|
218
|
+
socket authenticates CLI requests. The manager pauses only its idle native
|
|
219
|
+
child, builds/verifies the target, commits the active pointer, updates stable
|
|
220
|
+
filesystem routes and frontend state, and requests the app's internal backend
|
|
221
|
+
reconnect. Catalog reconciliation removes unavailable outgoing entries from the
|
|
222
|
+
cache and refreshes incoming native identities. The renderer reloads inside the
|
|
223
|
+
same native window. It reads back catalog counts and identities and checks that
|
|
224
|
+
the managed window still renders the pack.
|
|
225
|
+
|
|
226
|
+
Restored catalogs receive a target-local completed-backfill marker so native
|
|
227
|
+
startup preserves captured thread timestamps, previews and creator metadata.
|
|
228
|
+
Source backfill and migration watermarks are never imported.
|
|
229
|
+
|
|
230
|
+
The library is locked during mutations. Native verification checks SQLite
|
|
231
|
+
integrity, working directories and each agent's readable metadata/history through
|
|
232
|
+
the installed Codex backend. Verification sends no model turns. Imported active
|
|
233
|
+
goals are paused; scheduled automations are not imported.
|
|
234
|
+
|
|
235
|
+
Before-pointer failures retain the previous composition. After-pointer failures
|
|
236
|
+
retain the verified incoming runtime. `recover` reconnects the appropriate
|
|
237
|
+
runtime in the same window, and refuses a concurrent pointer change. Pending
|
|
238
|
+
journals block further mutations. No application bundle is patched.
|
|
239
|
+
|
|
240
|
+
The bridge uses inspected, private desktop internals and local debugging enabled
|
|
241
|
+
only for the managed profile. It is checked against Codex
|
|
242
|
+
`0.162.0-alpha.17.2`, `state_5.sqlite` and `thread_history_1.sqlite`. A desktop
|
|
243
|
+
upgrade can require an adapter update; incompatible layouts/protocols fail
|
|
244
|
+
explicitly. Keep the store on a local filesystem for predictable runtime access;
|
|
245
|
+
iCloud eviction caused source-file hydration delays during this build.
|
|
246
|
+
|
|
247
|
+
## Verification and measured scope
|
|
248
|
+
|
|
249
|
+
```sh
|
|
250
|
+
python3 -m unittest discover -s tests -v
|
|
251
|
+
topolo-agent-pack doctor topolo
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
See `LIVE_DESKTOP_PROOF.json` for a real macOS window pilot covering switches,
|
|
255
|
+
set addition, individual replacement and recovery, with the same desktop PID and
|
|
256
|
+
renderer target throughout. Small-pack switches measured approximately 3–7
|
|
257
|
+
seconds. The full-pack pilot returned to all 70 Topolo agents in 7.76 seconds,
|
|
258
|
+
with the same desktop process and renderer target. See `FULL_PACK_PROOF.json`.
|
|
259
|
+
Initial materialization and partial composition rebuild history/workspaces and
|
|
260
|
+
cost more than returning to a saved runtime. These are measured samples, not
|
|
261
|
+
latency guarantees.
|
|
262
|
+
|
|
263
|
+
A live capture of the user's current Topolo profile contains 70 visible agents
|
|
264
|
+
and 75 history threads, including inherited history. It is a reference-workspace
|
|
265
|
+
snapshot; the original profile was not stopped or switched. The earlier
|
|
266
|
+
`REAL_BACKEND_PROOF.json` records a real fork/ancestor export and clean-store
|
|
267
|
+
restore with all 25 stored items exactly retained. `VERIFICATION.json`
|
|
268
|
+
records the final regression and installation checks. Version 0.4.0 passes 35 tests.
|
|
269
|
+
`CATALOG_PROOF.json` records clean-store import and native role-loading checks
|
|
270
|
+
for the 48 agents; older proof files retain evidence from their original versions.
|
|
271
|
+
`FRESH_PACK_PROOF.json` records the complete 70-agent fresh pack, clean-store
|
|
272
|
+
export/import and native resume for all 70 roles, zero model turns and inherited
|
|
273
|
+
work history, and full same-window switching. Historical Topolo was restored in
|
|
274
|
+
8.74 seconds; all 75 of its rollout files remain byte-identical. The fresh pack
|
|
275
|
+
bundle is approximately 2.7 MB. The full-pack round trip
|
|
276
|
+
read every history page before and after: all 94,565 items and 2,486 turns matched
|
|
277
|
+
across 75 threads. All 455 instruction definitions and 97,150 captured table rows
|
|
278
|
+
also matched. The test caught and fixed a legacy-backfill issue that reset thread
|
|
279
|
+
metadata; version 0.2.1 preserves the authoritative captured metadata.
|
|
280
|
+
|
|
281
|
+
The read-back protocol is documented in the
|
|
282
|
+
[official Codex app-server reference](https://learn.chatgpt.com/docs/app-server).
|
|
283
|
+
The pack format and desktop integration are our own implementation.
|
|
284
|
+
|
|
285
|
+
## Shared Topolo Agent context and Bytes artifacts
|
|
286
|
+
|
|
287
|
+
The public command is `topolo agent-packs`; `topolo-agent-pack` is the local
|
|
288
|
+
adapter. Existing `codex-pack` captures are readable without rewriting their
|
|
289
|
+
thread IDs, history or store. This release supports the tested Codex adapter.
|
|
290
|
+
Claude and Cursor require separate native adapters and acceptance tests.
|
|
291
|
+
|
|
292
|
+
Agent owns scoped memory and installed role identities. Bytes owns artifacts.
|
|
293
|
+
The local runtime holds scratch files and credential-free connection pointers.
|
|
294
|
+
Switching is local; a connected agent refreshes context when beginning work and
|
|
295
|
+
retrieves referenced artifact content only when needed. Cloud calls use a
|
|
296
|
+
separate connection lock so they do not block pack switching.
|
|
297
|
+
|
|
298
|
+
```sh
|
|
299
|
+
topolo-agent-pack connect founder --environment production --context-key org:customer \
|
|
300
|
+
--agent-workspace DISCOVERED_AGENT_WORKSPACE --bytes-workspace DISCOVERED_BYTES_WORKSPACE \
|
|
301
|
+
--ownership user --bytes-scope private --roles roles.json --confirm
|
|
302
|
+
topolo-agent-pack remote-context founder --environment production --context-key org:customer --role specialists/strategy
|
|
303
|
+
topolo-agent-pack remember founder --environment production --context-key org:customer --role specialists/strategy \
|
|
304
|
+
--content approved-decision.json --kind durable --provenance decision-123 --confirm
|
|
305
|
+
topolo-agent-pack artifact founder --environment production --context-key org:customer --role specialists/strategy \
|
|
306
|
+
--file brief.pdf --content-type application/pdf --confirm
|
|
307
|
+
topolo-agent-pack remote-recover founder --environment production --context-key org:customer
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`roles.json` must map each logical `set/agent` to exactly `agentId` and
|
|
311
|
+
`agentVersionId`. Provision, evaluate and publish those hosted Agent identities
|
|
312
|
+
through their existing lifecycle first. Connections are immutable; changed
|
|
313
|
+
published versions require explicit disconnect/reconnect. Organization packs
|
|
314
|
+
require an organization administrator, organization-owned agents and `org`
|
|
315
|
+
Bytes scope. User packs require user-owned agents; private artifacts live in
|
|
316
|
+
the user's subtree of the verified Bytes workspace. Environments and accounts
|
|
317
|
+
are never inferred or silently substituted. Never reuse another environment's
|
|
318
|
+
workspace IDs. Connect each environment independently after the contracts ship.
|
|
319
|
+
Hosted agents need an explicit Agent `knowledge:read` service grant.
|
|
320
|
+
|
|
321
|
+
Fresh context includes relevant active instruction, knowledge and durable
|
|
322
|
+
records, filtered by tenant, workspace, user, role and exact version. It excludes
|
|
323
|
+
other users' private memory, expired records, episodes, task/run/thread records
|
|
324
|
+
and previous assignments. Context is bounded to 50 records/64K characters and
|
|
325
|
+
reports truncation. Memory is source material and cannot grant execution,
|
|
326
|
+
approval, messaging or handover authority. Shared durable memory requires an
|
|
327
|
+
explicit sharing policy. Credentials remain in protected Topolo CLI storage.
|
|
328
|
+
|
|
329
|
+
Artifact upload uses the published SDK URL-session transport, then verifies
|
|
330
|
+
stored bytes through authenticated bounded reads before registering a memory
|
|
331
|
+
reference. Receipts store workspace, scope, key, size, ETag and SHA-256—not upload
|
|
332
|
+
URLs or credentials. Downloads publish a destination only after every chunk and
|
|
333
|
+
the complete digest match. Artifacts up to 100 MiB are supported.
|
|
334
|
+
|
|
335
|
+
Local `recover` handles native switching transactions. `remote-recover` reads
|
|
336
|
+
cloud receipts and reconciles memory by exact identity/provenance/content; it
|
|
337
|
+
never replays an unknown memory create. Missing or ambiguous outcomes remain
|
|
338
|
+
unresolved for explicit reconciliation. An uploaded but unregistered artifact
|
|
339
|
+
remains stored in Bytes and is reported separately. An uncertain connection can
|
|
340
|
+
be retried with the identical immutable connect request. Switching does not
|
|
341
|
+
reset a remote binding or erase Agent memory or Bytes files.
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
## Claude Desktop preview
|
|
345
|
+
|
|
346
|
+
Claude Code Desktop 2.1.289 is qualified for native session import through
|
|
347
|
+
`--desktop --resume`. Each fresh pack role has its own named sidebar session,
|
|
348
|
+
CLAUDE.md, portable context files and persistent Claude session ID. No old Codex
|
|
349
|
+
conversation is copied and import submits no new task.
|
|
350
|
+
|
|
351
|
+
```sh
|
|
352
|
+
topolo-agent-pack add topolo-clean --harness claude --import-only
|
|
353
|
+
topolo-agent-pack add topolo-clean --harness claude --group intakes --import-only
|
|
354
|
+
topolo-agent-pack add topolo-clean --harness claude --agent topolo-clean/intakes/engineering --import-only
|
|
355
|
+
topolo-agent-pack status --harness claude
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
The public CLI source also dispatches `topolo agent-packs add ... --harness claude`;
|
|
359
|
+
this source change has not been published to the registry.
|
|
360
|
+
|
|
361
|
+
The CLI import handoff does not control outgoing membership, groups or pins.
|
|
362
|
+
Switching through that handoff refuses before changes. The experimental native
|
|
363
|
+
connection below provides a separate source implementation for those operations;
|
|
364
|
+
it still requires independent live and customer installation proof.
|
|
365
|
+
The adapter never edits Claude's live metadata, account state or permissions.
|
|
366
|
+
`recover` reads actual Desktop adoption records and reports incomplete imports;
|
|
367
|
+
repeating `add` resumes pending adoption with the same IDs. Workspaces and
|
|
368
|
+
transcripts live under the selected pack library and Claude config respectively.
|
|
369
|
+
Default Claude auto-cleanup still applies to transcripts; this preview is not a
|
|
370
|
+
portable backup of accumulated Claude history. Existing Codex switching is
|
|
371
|
+
unchanged. Role-identity inference, hosted Agent/Bytes shared memory and clean
|
|
372
|
+
machine installation require separate acceptance.
|
|
373
|
+
|
|
374
|
+
## Agent execution policy
|
|
375
|
+
|
|
376
|
+
`topolo agent-packs policy topolo-clean` renders the portable model, reasoning,
|
|
377
|
+
approval and sidebar intent for every role. Use `--group`, `--agent`,
|
|
378
|
+
`--harness codex|claude` and `--output /absolute/path/review.json` to select or
|
|
379
|
+
save a review copy. The command never changes existing sessions or permissions.
|
|
380
|
+
An agent can declare `executionProfile` as `intake`, `analysis`, `review`,
|
|
381
|
+
`build` or `operator`; otherwise the adapter resolves its role default.
|
|
382
|
+
|
|
383
|
+
The initial Claude policy uses Opus 5.5 for reasoning roles and Sonnet 5.5 for
|
|
384
|
+
execution. Haiku 5.5 is not selected for the qualified 2.1.289 host, because it
|
|
385
|
+
requires 2.1.293 or later. Codex uses GPT-6 Astra for reasoning roles and
|
|
386
|
+
GPT-6.1 Sol for execution. These are desired settings, not proof of account
|
|
387
|
+
availability or live session selection.
|
|
388
|
+
|
|
389
|
+
Codex sandboxing and Claude permission modes have separate mappings. Claude
|
|
390
|
+
Manual does not enforce a read-only filesystem sandbox. The policy records
|
|
391
|
+
that extra confinement requirement instead of treating the two controls as
|
|
392
|
+
equivalent. Platform mutations still require the existing scoped authorization.
|
|
393
|
+
|
|
394
|
+
Role context and relevant memory should be loaded on demand, with bounded tool
|
|
395
|
+
results and one evidence-linked handoff. An idle pack should generate no model
|
|
396
|
+
turns or background polling. No token savings are claimed without usage evidence.
|
|
397
|
+
|
|
398
|
+
Claude session adoption is currently verified independently from complete pack
|
|
399
|
+
activation. The external native import command does not provide live group,
|
|
400
|
+
pin, model or outgoing-roster controls. `activationReady` and
|
|
401
|
+
`modelAndPermissionSettingsVerified` remain false until a qualified backend
|
|
402
|
+
transport applies and reads back those settings. UI automation is not part of
|
|
403
|
+
the adapter. Import status is deliberately separate from native activation proof.
|
|
404
|
+
### Experimental Claude live configuration
|
|
405
|
+
|
|
406
|
+
The native import is not pack activation. `configure` can preflight and apply
|
|
407
|
+
an already adopted roster through the running Claude main process. This is an
|
|
408
|
+
internal compatibility adapter qualified for **Claude Desktop 2.31226.1** and
|
|
409
|
+
the exact native module hashes in `src/lib/claude-pack-backend.ts`; it refuses
|
|
410
|
+
other builds. It invokes native session-manager APIs and acknowledged sidebar
|
|
411
|
+
commands. It does not automate the UI or edit cached desktop records.
|
|
412
|
+
|
|
413
|
+
```sh
|
|
414
|
+
topolo agent-packs policy topolo-clean --harness claude --output /absolute/review.json
|
|
415
|
+
topolo agent-packs configure topolo-clean --harness claude \
|
|
416
|
+
--policy /absolute/review.json --pid <Claude-main-PID> \
|
|
417
|
+
--endpoint ws://127.0.0.1:<port>/<inspector-UUID>
|
|
418
|
+
# After reviewing the preflight, repeat the same command with --apply.
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
The endpoint must be enabled separately with the machine owner's explicit
|
|
422
|
+
authorization: a main-process debugger allows local code execution. The
|
|
423
|
+
adapter does not enable debugging, signal/restart Claude, patch its app bundle,
|
|
424
|
+
or leave a background service. Close a temporarily enabled debugger after the
|
|
425
|
+
operation. This experimental connection is not a released customer setup path.
|
|
426
|
+
The inspected 2.31226.1 build disables Electron's `nodeCliInspect` fuse, so
|
|
427
|
+
startup flags and `SIGUSR1` do not enable its inspector. Its native Developer
|
|
428
|
+
Mode setup requires a one-time restart, followed by the Developer menu's
|
|
429
|
+
`Enable Main Process Debugger` setting. Any such setup is separately authorized;
|
|
430
|
+
do not patch fuses or assume a restart flag opens the endpoint.
|
|
431
|
+
|
|
432
|
+
All selected sessions must be idle, have matching titles/workspaces, and use
|
|
433
|
+
models from the native account catalog. Settings use Manual or Accept edits;
|
|
434
|
+
no bypass permission is accepted. An fsynced journal records the baseline and
|
|
435
|
+
each attempted native effect before dispatch. On a disconnect or failed
|
|
436
|
+
acknowledgement, use the explicit read-only native recovery command below before
|
|
437
|
+
retrying; do not assume failure means no effects. Application independently
|
|
438
|
+
reads back groups, pins, models, effort and permission modes and hashes role
|
|
439
|
+
charters/transcripts before and after. It does not claim an inference test,
|
|
440
|
+
read-only filesystem confinement or hosted memory verification. Those remain
|
|
441
|
+
separate acceptance boundaries.
|
|
442
|
+
|
|
443
|
+
### Experimental native Claude switching and recovery
|
|
444
|
+
|
|
445
|
+
First configure and verify the initial adopted pack. Prepare/import the target
|
|
446
|
+
pack independently and render its complete reviewed policy. Then preflight:
|
|
447
|
+
|
|
448
|
+
```sh
|
|
449
|
+
topolo agent-packs switch personal --harness claude \
|
|
450
|
+
--policy /absolute/personal-policy.json --pid <Claude-main-PID> \
|
|
451
|
+
--endpoint ws://127.0.0.1:<port>/<inspector-UUID>
|
|
452
|
+
# Repeat with --apply after reviewing the result.
|
|
453
|
+
topolo agent-packs recover personal --harness claude \
|
|
454
|
+
--policy /absolute/personal-policy.json --pid <Claude-main-PID> \
|
|
455
|
+
--endpoint ws://127.0.0.1:<port>/<inspector-UUID>
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Switching archives only the explicit previously verified outgoing roster and
|
|
459
|
+
unarchives the existing target identities. It does not delete sessions, clean
|
|
460
|
+
worktrees, create model turns or touch unrelated sessions. Live work, remote or
|
|
461
|
+
linked workspaces and nonempty archive cascades refuse before effects. Role
|
|
462
|
+
files and transcripts are hashed inside the native operation and independently
|
|
463
|
+
by the caller. Python imports and native commands share the same library lock;
|
|
464
|
+
the native manager also fences competing operations across libraries.
|
|
465
|
+
|
|
466
|
+
An interrupted native operation blocks further imports or native operations.
|
|
467
|
+
Recovery reads the exact sealed operation plan and native state; it never
|
|
468
|
+
replays effects. A completely verified target can finalize an interrupted
|
|
469
|
+
commit. If the journal proves no effect was attempted, recovery releases that
|
|
470
|
+
operation without changing the previous active composition. Partial effects,
|
|
471
|
+
changed context and a still-running operation remain recovery-required; they
|
|
472
|
+
need supported owner reconciliation. No expiry or PID observation clears a
|
|
473
|
+
pending operation. `status --harness claude` distinguishes adoption readback,
|
|
474
|
+
the last verified active roster and pending recovery; cached proof is not
|
|
475
|
+
reported as current native settings. Use explicit native recovery above rather
|
|
476
|
+
than retrying an uncertain apply.
|
|
477
|
+
|
|
478
|
+
### Managed Codex role execution
|
|
479
|
+
|
|
480
|
+
New managed compositions carry a closed per-role execution policy. The owned
|
|
481
|
+
proxy qualifies the installed executable's exported protocol offline and reads
|
|
482
|
+
its account model catalog. On native `thread/resume` it supplies the selected
|
|
483
|
+
role's model, effort, approval reviewer and local sandbox without starting a
|
|
484
|
+
turn. An effective-settings mismatch blocks subsequent model work. Conflicting
|
|
485
|
+
frontend overrides are reported; the adapter never silently substitutes models
|
|
486
|
+
or expands permissions. Update reviewed policy explicitly to change it.
|
|
487
|
+
Read-only roles have no command network access; workspace writers are confined
|
|
488
|
+
to their role workspace with temporary-directory roots excluded. Platform tool
|
|
489
|
+
authorization remains separate from local command sandboxing.
|
|
490
|
+
|
|
491
|
+
Managed bridge status reports requested policy and which resumes have current
|
|
492
|
+
native readback. It does not claim an inference test or independent app-tool
|
|
493
|
+
approval readback. Existing runtimes without this policy report not-configured
|
|
494
|
+
until explicitly rebuilt. Source fixtures do not establish live desktop or
|
|
495
|
+
three-environment shared-memory acceptance.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "topolo-agent-pack"
|
|
7
|
+
version = "0.5.0"
|
|
8
|
+
description = "Portable Topolo Agent Packs with local adapters and shared hosted continuity"
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
[project.scripts]
|
|
13
|
+
topolo-agent-pack = "topolo_agent_pack.cli:main"
|
|
14
|
+
|
|
15
|
+
[tool.setuptools.packages.find]
|
|
16
|
+
where = ["src"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
coverage==7.16.2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.0"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Strict, source-independent pack templates. No histories or credentials imported."""
|
|
2
|
+
import hashlib,json,pathlib,re
|
|
3
|
+
from . import fresh
|
|
4
|
+
from .storage import PackError,canonical,safe_id
|
|
5
|
+
|
|
6
|
+
def identifier(value):
|
|
7
|
+
if not isinstance(value,str):raise PackError('Template identifiers must be strings')
|
|
8
|
+
return safe_id(value)
|
|
9
|
+
|
|
10
|
+
def load(lib,directory):
|
|
11
|
+
root=pathlib.Path(directory).expanduser()
|
|
12
|
+
if root.is_symlink() or not root.is_dir():raise PackError('Template must be a regular directory')
|
|
13
|
+
root=root.resolve()
|
|
14
|
+
files=list(root.rglob('*'))
|
|
15
|
+
if any(p.is_symlink() for p in files):raise PackError('Template symlinks are not portable')
|
|
16
|
+
document=root/'pack.json'
|
|
17
|
+
if not document.is_file():raise PackError('Template requires pack.json')
|
|
18
|
+
size=sum(p.stat().st_size for p in files if p.is_file())
|
|
19
|
+
if size>16*1024*1024:raise PackError('Template exceeds 16 MiB')
|
|
20
|
+
value=json.loads(document.read_text())
|
|
21
|
+
allowed={'schemaVersion','id','version','name','purpose','agents','dependencies','provenance'}
|
|
22
|
+
if not isinstance(value,dict) or set(value)-allowed or value.get('schemaVersion')!=1:raise PackError('Invalid template schema or unknown fields')
|
|
23
|
+
identifier(value.get('id',''))
|
|
24
|
+
if not isinstance(value.get('version'),str) or not re.fullmatch(r'\d+\.\d+\.\d+',value['version']):raise PackError('Template requires semantic version')
|
|
25
|
+
if not isinstance(value.get('agents'),list) or not 1<=len(value['agents'])<=200:raise PackError('Template requires 1–200 roles')
|
|
26
|
+
roster=[];seen=set();titles=set()
|
|
27
|
+
for n,a in enumerate(value['agents']):
|
|
28
|
+
if not isinstance(a,dict) or set(a)-{'set','id','title','aliases','pinned','position','sectionName'}:raise PackError('Invalid role fields')
|
|
29
|
+
identifier(a.get('set',''));identifier(a.get('id',''))
|
|
30
|
+
key=(a['set'],a['id']);title=a.get('title')
|
|
31
|
+
if key in seen or not isinstance(title,str) or not title.strip() or len(title)>255 or title in titles:raise PackError('Duplicate or invalid role identity/title')
|
|
32
|
+
seen.add(key);titles.add(title)
|
|
33
|
+
if not isinstance(a.get('aliases',[]),list) or any(not isinstance(x,str) or not x for x in a.get('aliases',[])):raise PackError('Invalid role aliases')
|
|
34
|
+
if not isinstance(a.get('pinned',False),bool) or type(a.get('position',n)) is not int or a.get('position',n)<0:raise PackError('Invalid sidebar role placement')
|
|
35
|
+
section=a.get('sectionName',value['id'].title()+' Team')
|
|
36
|
+
if not isinstance(section,str) or not section.strip() or len(section)>100:raise PackError('Invalid section name')
|
|
37
|
+
roster.append({**a,'pack':value['id'],'pinned':a.get('pinned',False),'position':a.get('position',n),'sectionName':'Pinned' if a.get('pinned') else section})
|
|
38
|
+
dependencies=value.get('dependencies',{})
|
|
39
|
+
if not isinstance(dependencies,dict) or set(dependencies)-{'applications','capabilities','integrationNotes'}:raise PackError('Templates declare capabilities, not credentialed server configurations')
|
|
40
|
+
for k,v in dependencies.items():
|
|
41
|
+
if not isinstance(v,list) or any(not isinstance(x,str) for x in v):raise PackError('Dependencies must be string lists')
|
|
42
|
+
definitions=[]
|
|
43
|
+
for p in sorted((root/'skills').rglob('*')):
|
|
44
|
+
if not p.is_file():continue
|
|
45
|
+
if p.suffix!='.md' or p.stat().st_size>1024*1024:raise PackError('Template skills accept Markdown instructions only')
|
|
46
|
+
definitions.append({'relative':p.relative_to(root).as_posix(),'content':lib.put(p)})
|
|
47
|
+
# Digest all portable files, including guides and workflows, not machine paths.
|
|
48
|
+
digest=hashlib.sha256(canonical({p.relative_to(root).as_posix():hashlib.sha256(p.read_bytes()).hexdigest() for p in sorted(files) if p.is_file()})).hexdigest()
|
|
49
|
+
return {'packId':value['id'],'templateVersion':value['version'],'agents':roster,'definitions':definitions,'dependencies':dependencies,'config':{}},digest
|
|
50
|
+
|
|
51
|
+
def build(lib,name,directory,binary,sets=None,agents=None):
|
|
52
|
+
safe_id(name)
|
|
53
|
+
if (lib.root/'packs'/name/'head.json').exists():raise PackError('Destination already exists; choose a new instance name')
|
|
54
|
+
if lib.pending():raise PackError('Recover the pending operation first')
|
|
55
|
+
manifest,digest=load(lib,directory)
|
|
56
|
+
result=fresh.create(lib,'template:'+manifest['packId'],name,directory,binary,sets,agents,authored=(manifest,digest))
|
|
57
|
+
return {**result,'templateId':manifest['packId'],'templateVersion':manifest['templateVersion'],'templateDigest':digest}
|