@inneranimalmedia/agentsam-sdk 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +7 -6
  2. package/docs/AGENTSAM_WORKBENCH.md +30 -0
  3. package/docs/AUTH_IDENTITY_CONTRACT.md +52 -0
  4. package/docs/CAPABILITIES.md +5 -3
  5. package/docs/CLI_SHELL.md +57 -80
  6. package/docs/CMS_STUDIO.md +101 -0
  7. package/docs/CONTEXT.md +170 -0
  8. package/docs/LOCAL_OLLAMA.md +58 -0
  9. package/docs/MERKLE.md +19 -19
  10. package/docs/PORTABLE_CONTEXT.md +4 -3
  11. package/docs/PROJECT_CONFIG.md +72 -0
  12. package/docs/RELEASES.md +26 -2
  13. package/docs/REPOSITORY_INTELLIGENCE.md +1 -1
  14. package/docs/REPOSITORY_KNOWLEDGE.md +114 -0
  15. package/docs/SDK_WORKER.md +86 -0
  16. package/docs/SECURITY.md +59 -22
  17. package/docs/client-cms-editor.md +15 -0
  18. package/docs/local-studio/WORKMODE_DONOR_NOTES.md +485 -0
  19. package/package.json +17 -5
  20. package/packages/identity/package.json +11 -2
  21. package/packages/identity/src/contracts/auth-config.js +98 -0
  22. package/packages/identity/src/index.js +1 -0
  23. package/packages/identity/src/oauth/README.md +2 -2
  24. package/packages/identity/src/oauth/credentials.js +11 -4
  25. package/packages/identity/src/oauth/iam-platform.js +3 -3
  26. package/packages/identity/src/providers/iam/index.js +7 -7
  27. package/packages/identity/src/providers/iam/oauth.js +6 -4
  28. package/packages/identity/src/providers/iam/profile.js +5 -5
  29. package/packages/identity/tests/auth-config.test.mjs +57 -0
  30. package/packages/identity/tests/oauth-credentials.test.mjs +13 -2
  31. package/protocol/FILEMETA_V1.md +95 -0
  32. package/protocol/INSPECT_VIEWS_V1.md +40 -0
  33. package/protocol/MERKLE_PERSISTENCE_V1.md +50 -0
  34. package/protocol/MERKLE_V1.md +3 -1
  35. package/protocol/capabilities/manifest.json +32 -3
  36. package/protocol/capabilities/repository-snapshot.schema.json +1 -0
  37. package/protocol/context/context-budget.schema.json +41 -0
  38. package/protocol/context/context-item.schema.json +20 -0
  39. package/protocol/context/resolved-context-pack.schema.json +42 -0
  40. package/protocol/context/result-policy.schema.json +17 -0
  41. package/protocol/knowledge/context-pack.schema.json +33 -0
  42. package/protocol/knowledge/retrieval-query.schema.json +68 -13
  43. package/python/README.md +15 -7
  44. package/python/agentsam_sdk/cli.py +0 -21
  45. package/python/agentsam_sdk/tui/README.md +17 -12
  46. package/python/agentsam_sdk/tui/bootstrap.py +2 -2
  47. package/python/agentsam_sdk/tui/demo.py +25 -10
  48. package/python/agentsam_sdk/tui/onboarding.py +208 -0
  49. package/python/tests/test_tui_cli.py +7 -6
  50. package/skills/README.md +21 -0
  51. package/skills/agentsam-app-fundamentals/SKILL.md +165 -0
  52. package/skills/agentsam-app-fundamentals/references/graphs-contracts-ast-merkle.md +89 -0
  53. package/skills/agentsam-app-fundamentals/references/trust-credentials-and-destinations.md +99 -0
  54. package/skills/agentsam-jr-dev/SKILL.md +232 -0
  55. package/skills/agentsam-jr-dev/references/real-application-logic.md +156 -0
  56. package/skills/agentsam-jr-dev/references/web-application-fundamentals.md +240 -0
  57. package/skills/agentsam-progression-guard/SKILL.md +197 -0
  58. package/skills/agentsam-progression-guard/references/checkpoint-chain.md +111 -0
  59. package/skills/agentsam-progression-guard/references/hooks-operational-io.md +96 -0
  60. package/skills/catalog.json +53 -0
  61. package/src/capabilities/index.js +7 -0
  62. package/src/capabilities/repository-snapshot-view.js +238 -0
  63. package/src/capabilities/repository-snapshot.js +28 -14
  64. package/src/cli.js +108 -56
  65. package/src/commands/cad.js +56 -6
  66. package/src/commands/context.js +14 -2
  67. package/src/commands/db.js +4 -7
  68. package/src/commands/deploy.js +17 -31
  69. package/src/commands/interactive.js +21 -0
  70. package/src/commands/knowledge.js +27 -4
  71. package/src/commands/merkle-persist.js +118 -0
  72. package/src/commands/merkle.js +32 -17
  73. package/src/commands/models.js +107 -0
  74. package/src/commands/ollama.js +259 -0
  75. package/src/commands/preferences.js +102 -0
  76. package/src/commands/product.js +86 -16
  77. package/src/commands/security.js +3 -3
  78. package/src/commands/shell.js +71 -27
  79. package/src/commands/skills.js +66 -0
  80. package/src/commands/start-local.js +1 -1
  81. package/src/commands/tunnel.js +5 -4
  82. package/src/context/budget.js +58 -0
  83. package/src/context/compact.js +28 -0
  84. package/src/context/index.js +5 -0
  85. package/src/context/resolve.js +84 -0
  86. package/src/context/result-policy.js +66 -0
  87. package/src/index.js +16 -0
  88. package/src/indexing/execution-boundary.js +144 -0
  89. package/src/indexing/index.js +8 -0
  90. package/src/indexing/provider.js +41 -0
  91. package/src/knowledge/config.js +2 -2
  92. package/src/knowledge/context-pack.js +12 -1
  93. package/src/knowledge/contracts.js +9 -4
  94. package/src/knowledge/engine.js +7 -3
  95. package/src/knowledge/service/server.js +1 -1
  96. package/src/lib/auth.js +10 -19
  97. package/src/lib/bridge-client.js +7 -5
  98. package/src/lib/cli-preferences.js +74 -0
  99. package/src/lib/core-client.js +8 -8
  100. package/src/lib/deploy-receipt/index.js +5 -2
  101. package/src/lib/detect-context.js +6 -5
  102. package/src/lib/identity-scaffold.js +1 -1
  103. package/src/lib/local-scaffold.js +35 -33
  104. package/src/lib/local-status.js +9 -17
  105. package/src/lib/merkle/cloudflare-persistence.js +321 -0
  106. package/src/lib/merkle/filemeta.js +43 -0
  107. package/src/lib/merkle/git-ignore.js +24 -0
  108. package/src/lib/merkle/hash.js +1 -0
  109. package/src/lib/merkle/index.js +22 -0
  110. package/src/lib/merkle/persistence.js +72 -0
  111. package/src/lib/merkle/semantic.js +359 -0
  112. package/src/lib/merkle/snapshot.js +9 -3
  113. package/src/lib/merkle/tree.js +11 -6
  114. package/src/lib/open-url.js +66 -0
  115. package/src/lib/project-config.js +227 -0
  116. package/src/lib/project-rules.js +68 -0
  117. package/src/lib/save-sdk-token.js +1 -1
  118. package/src/lib/slash-commands.js +2 -1
  119. package/src/lib/tools.js +11 -5
  120. package/src/security/index.js +1 -0
  121. package/src/security/inventory.js +4 -1
  122. package/src/security/render.js +27 -5
  123. package/src/security/scan.js +24 -9
  124. package/src/security/trust-boundary.js +24 -0
  125. package/src/skills/index.js +64 -0
  126. package/src/tools/index.js +1 -0
  127. package/src/tools/search.js +70 -0
  128. package/src/ui/ansi.js +1 -1
  129. package/src/ui/boot.js +56 -0
  130. package/src/ui/merkle/render.js +1 -0
  131. package/src/ui/runtime-activity.js +192 -0
  132. package/src/ui/theme.js +19 -18
  133. package/test/app-building-skills.test.mjs +61 -0
  134. package/test/apps-scaffold-contract.test.mjs +56 -0
  135. package/test/capabilities.test.mjs +53 -4
  136. package/test/cli-preferences.test.mjs +25 -0
  137. package/test/context.test.mjs +95 -0
  138. package/test/indexing-provider.test.mjs +29 -0
  139. package/test/jr-dev-skill.test.mjs +26 -0
  140. package/test/knowledge-context-pack.test.mjs +19 -0
  141. package/test/knowledge.test.mjs +1 -1
  142. package/test/merkle-persistence.test.mjs +91 -0
  143. package/test/merkle.test.mjs +77 -3
  144. package/test/models.test.mjs +37 -0
  145. package/test/ollama.test.mjs +94 -0
  146. package/test/open-url.test.mjs +64 -0
  147. package/test/project-config.test.mjs +81 -0
  148. package/test/project-rules.test.mjs +44 -0
  149. package/test/release-hygiene.test.mjs +34 -0
  150. package/test/repository-snapshot-view.test.mjs +112 -0
  151. package/test/runtime-activity.test.mjs +98 -0
  152. package/test/sdk-worker-contract.test.mjs +68 -0
  153. package/test/security.test.mjs +46 -0
  154. package/test/shell.test.mjs +8 -1
  155. package/test/skills.test.mjs +22 -0
  156. package/test/smoke.mjs +2 -2
  157. package/test/theme-portability.test.mjs +14 -0
  158. package/test/tools-search.test.mjs +27 -0
  159. package/examples/agentsam-tui-ansi.mjs +0 -149
  160. package/src/commands/tui.js +0 -120
  161. package/src/ui/splash-xterm.js +0 -290
  162. package/src/ui/splash.js +0 -426
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.inneranimalmedia.com/agentsam/context/resolved-context-pack.schema.json",
4
+ "title": "ResolvedContextPack",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["objective", "refs", "items", "budget", "receipt"],
8
+ "properties": {
9
+ "objective": { "type": "string", "minLength": 1 },
10
+ "refs": { "type": "array", "items": { "type": "string" } },
11
+ "rules": { "type": ["object", "null"] },
12
+ "items": {
13
+ "type": "array",
14
+ "items": { "$ref": "./context-item.schema.json" }
15
+ },
16
+ "budget": { "$ref": "./context-budget.schema.json" },
17
+ "receipt": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "required": [
21
+ "chars",
22
+ "evidence_chars",
23
+ "system_chars",
24
+ "estimated_tokens",
25
+ "sources_considered",
26
+ "sources_included",
27
+ "sources_deferred",
28
+ "deferred_refs"
29
+ ],
30
+ "properties": {
31
+ "chars": { "type": "integer", "minimum": 0 },
32
+ "evidence_chars": { "type": "integer", "minimum": 0 },
33
+ "system_chars": { "type": "integer", "minimum": 0 },
34
+ "estimated_tokens": { "type": "integer", "minimum": 0 },
35
+ "sources_considered": { "type": "integer", "minimum": 0 },
36
+ "sources_included": { "type": "integer", "minimum": 0 },
37
+ "sources_deferred": { "type": "integer", "minimum": 0 },
38
+ "deferred_refs": { "type": "array", "items": { "type": "string" } }
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.inneranimalmedia.com/agentsam/context/result-policy.schema.json",
4
+ "title": "ResultPolicy",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["max_items", "max_chars", "detail"],
8
+ "properties": {
9
+ "max_items": { "type": "integer", "minimum": 1, "default": 8 },
10
+ "max_chars": { "type": "integer", "minimum": 1, "default": 24000 },
11
+ "detail": {
12
+ "type": "string",
13
+ "enum": ["metadata", "card", "excerpt", "range", "full"],
14
+ "default": "excerpt"
15
+ }
16
+ }
17
+ }
@@ -32,6 +32,39 @@
32
32
  },
33
33
  "diagnostics": {
34
34
  "type": "object"
35
+ },
36
+ "receipt": {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "required": [
40
+ "chars",
41
+ "estimated_tokens",
42
+ "sources_considered",
43
+ "sources_included",
44
+ "sources_deferred"
45
+ ],
46
+ "properties": {
47
+ "chars": {
48
+ "type": "integer",
49
+ "minimum": 0
50
+ },
51
+ "estimated_tokens": {
52
+ "type": "integer",
53
+ "minimum": 0
54
+ },
55
+ "sources_considered": {
56
+ "type": "integer",
57
+ "minimum": 0
58
+ },
59
+ "sources_included": {
60
+ "type": "integer",
61
+ "minimum": 0
62
+ },
63
+ "sources_deferred": {
64
+ "type": "integer",
65
+ "minimum": 0
66
+ }
67
+ }
35
68
  }
36
69
  }
37
70
  }
@@ -4,19 +4,74 @@
4
4
  "type": "object",
5
5
  "additionalProperties": false,
6
6
  "title": "RetrievalQuery",
7
- "required": ["text"],
7
+ "required": [
8
+ "text"
9
+ ],
8
10
  "properties": {
9
- "text": { "type": "string", "minLength": 1 },
10
- "workspace_id": { "type": "string", "minLength": 1, "deprecated": true, "description": "Legacy compatibility metadata only; repository selection is explicit through repository identity." },
11
- "repositories": { "type": "array", "items": { "type": "string" } },
12
- "product_ids": { "type": "array", "items": { "type": "string" } },
13
- "refs": { "type": "array", "items": { "type": "string" } },
14
- "intent": { "type": "string", "default": "auto" },
15
- "lanes": { "type": "array", "items": { "type": "string" } },
16
- "top_k": { "type": "integer", "minimum": 1, "maximum": 100, "default": 12 },
17
- "token_budget": { "type": "integer", "minimum": 256, "default": 8000 },
18
- "require_current_ref": { "type": "boolean", "default": true },
19
- "include_archived": { "type": "boolean", "default": false },
20
- "explain": { "type": "boolean", "default": true }
11
+ "text": {
12
+ "type": "string",
13
+ "minLength": 1
14
+ },
15
+ "workspace_id": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "deprecated": true,
19
+ "description": "Legacy compatibility metadata only; repository selection is explicit through repository identity."
20
+ },
21
+ "repositories": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "string"
25
+ }
26
+ },
27
+ "product_ids": {
28
+ "type": "array",
29
+ "items": {
30
+ "type": "string"
31
+ }
32
+ },
33
+ "refs": {
34
+ "type": "array",
35
+ "items": {
36
+ "type": "string"
37
+ }
38
+ },
39
+ "intent": {
40
+ "type": "string",
41
+ "default": "auto"
42
+ },
43
+ "lanes": {
44
+ "type": "array",
45
+ "items": {
46
+ "type": "string"
47
+ }
48
+ },
49
+ "top_k": {
50
+ "type": "integer",
51
+ "minimum": 1,
52
+ "maximum": 8,
53
+ "default": 8
54
+ },
55
+ "token_budget": {
56
+ "type": "integer",
57
+ "minimum": 256,
58
+ "default": 6000,
59
+ "maximum": 6000
60
+ },
61
+ "require_current_ref": {
62
+ "type": "boolean",
63
+ "default": true
64
+ },
65
+ "include_archived": {
66
+ "type": "boolean",
67
+ "default": false
68
+ },
69
+ "explain": {
70
+ "type": "boolean",
71
+ "default": true
72
+ },
73
+ "result_policy": {
74
+ "$ref": "../context/result-policy.schema.json"
75
+ }
21
76
  }
22
77
  }
package/python/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # agentsam_sdk (Python) — npm mirror
2
2
 
3
3
  Core repository/data commands remain **stdlib-only** (`dependencies = []`).
4
- The Rich terminal UI is an optional `tui` extra and lives with the SDK CLI,
5
- not in the application tool catalog.
4
+ Rich is an optional renderer dependency used by the SDK's internal terminal preview lab;
5
+ it is not exposed as an installed-user renderer command.
6
6
 
7
7
  ```bash
8
8
  cd python && pip install -e .
@@ -20,14 +20,22 @@ Protocol: [`../protocol/README.md`](../protocol/README.md). Do not advance this
20
20
  | `agentsam-site-scrape` | [`../packages/agentsam-site-scrape/`](../packages/agentsam-site-scrape/) | Optional/network (`requests`); crawl→R2. Dual-homed with IAM `tools/agentsam-site-scrape/`. Does **not** fold into `agentsam_sdk`. |
21
21
 
22
22
 
23
- ## Optional terminal UI
23
+ ## Internal Rich renderer preview
24
+
25
+ The npm SDK owns the public interactive experience. For renderer development only:
26
+
27
+ ```bash
28
+ cd ..
29
+ npm run ui:preview -- tour
30
+ npm run ui:preview -- thinking
31
+ ```
32
+
33
+ The Python module can also be invoked directly after installing the optional extra:
24
34
 
25
35
  ```bash
26
36
  cd python
27
37
  pip install -e '.[tui]'
28
- agentsam tui
29
- agentsam tui --scene dashboard
30
- agentsam tui --check
38
+ PYTHONPATH=. python -m agentsam_sdk.tui --scene dashboard --check
31
39
  ```
32
40
 
33
- `agentsam_sdk.tui` is presentation-only. It does not define tools or execution policy.
41
+ `agentsam_sdk.tui` is presentation-only. It does not define tools, execution policy, or public CLI vocabulary.
@@ -153,31 +153,10 @@ def _cmd_repository_inspect(args: argparse.Namespace) -> int:
153
153
  return repo_inspect.main_cli(argv)
154
154
 
155
155
 
156
- def _cmd_tui(args: argparse.Namespace) -> int:
157
- from agentsam_sdk.tui.demo import main as tui_main
158
-
159
- argv = ["--scene", args.scene, "--ticks", str(args.ticks)]
160
- if args.check:
161
- argv.append("--check")
162
- if args.force_color:
163
- argv.append("--force-color")
164
- return tui_main(argv)
165
-
166
-
167
156
  def build_parser() -> argparse.ArgumentParser:
168
157
  ap = argparse.ArgumentParser(prog="agentsam", description="agentsam_sdk CLI")
169
158
  sub = ap.add_subparsers(dest="group", required=True)
170
159
 
171
- tui = sub.add_parser("tui", help="optional Rich terminal UI / live CLI renderables")
172
- tui.add_argument(
173
- "--scene",
174
- choices=("all", "card", "progress", "dashboard", "events", "sprite", "logs", "ship"),
175
- default="all",
176
- )
177
- tui.add_argument("--ticks", type=int, default=48)
178
- tui.add_argument("--check", action="store_true", help="render quickly for smoke/CI")
179
- tui.add_argument("--force-color", action="store_true")
180
- tui.set_defaults(func=_cmd_tui)
181
160
 
182
161
  data = sub.add_parser("data", help="D1 data audits")
183
162
  data_sub = data.add_subparsers(dest="cmd", required=True)
@@ -1,22 +1,27 @@
1
- # Agent Sam TUI
1
+ # Agent Sam Rich renderer lab
2
2
 
3
- Optional terminal presentation for the Python `agentsam` CLI.
3
+ Internal high-fidelity terminal presentation experiments for Agent Sam. This package is a renderer/design surface, not a public user command, tool registry, execution adapter, workflow, or permission boundary.
4
4
 
5
- **Ownership:** UI only. This package is not an Agent Sam tool, tool registry,
6
- execution adapter, workflow, or permission boundary. It renders state produced
7
- by real SDK commands.
5
+ The installed npm CLI owns the product lifecycle. Users type `agentsam`; they do not select ANSI versus Rich.
8
6
 
9
- Migrated from `inneranimalmedia/tools_py/agentsam_tui` so the product repo no
10
- longer presents a TUI prototype as a reusable runtime tool.
7
+ From the SDK repository, preview scenes with:
8
+
9
+ ```bash
10
+ npm run ui:preview -- tour
11
+ npm run ui:preview -- boot
12
+ npm run ui:preview -- setup
13
+ npm run ui:preview -- thinking
14
+ npm run ui:preview -- ready
15
+ ```
16
+
17
+ The Node script selects the renderer internally. For direct Python renderer work:
11
18
 
12
19
  ```bash
13
20
  cd python
14
21
  pip install -e '.[tui]'
15
- agentsam tui
16
- agentsam tui --scene dashboard
17
- agentsam tui --check
22
+ PYTHONPATH=. python -m agentsam_sdk.tui --scene dashboard --check
18
23
  ```
19
24
 
20
- The core Python SDK remains stdlib-only; `rich` is an optional extra.
25
+ The core Python SDK remains stdlib-only; `rich` is an optional extra. The intended product progression is small: **brand/boot → detect project context → first-run keyboard choices when needed → quiet ready prompt**.
21
26
 
22
- For a zero-dependency Node/ANSI rendering reference, see `../../../../examples/agentsam-tui-ansi.mjs`.
27
+ For the zero-dependency Node/ANSI animation lab, see `../../../../scripts/internal/ansi-ui-preview.mjs`.
@@ -2,9 +2,9 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  _MISSING = (
5
- "Python package 'rich' is required for the Agent Sam TUI.\n"
5
+ "Python package 'rich' is required for the internal Agent Sam Rich preview.\n"
6
6
  " pip install -e './python[tui]'\n"
7
- " agentsam tui\n"
7
+ " python -m agentsam_sdk.tui --scene boot\n"
8
8
  )
9
9
 
10
10
 
@@ -1,11 +1,15 @@
1
- """Agent Sam Rich TUI demos — six reusable terminal patterns.
1
+ """Internal Agent Sam Rich render previews.
2
2
 
3
- Run from repo root:
3
+ Run from repo root through the SDK design lane:
4
+
5
+ npm run ui:preview -- tour
6
+ npm run ui:preview -- boot
7
+ npm run ui:preview -- thinking
8
+
9
+ Or invoke the renderer module directly after installing the optional Rich extra:
4
10
 
5
11
  pip install -e './python[tui]'
6
- agentsam tui
7
- agentsam tui --scene dashboard
8
- agentsam tui --check
12
+ PYTHONPATH=python python -m agentsam_sdk.tui --scene dashboard --check
9
13
  """
10
14
 
11
15
  from __future__ import annotations
@@ -33,6 +37,7 @@ from rich.text import Text
33
37
 
34
38
  from .frames import COMET, THINK, WALKER
35
39
  from .theme import CYAN
40
+ from .onboarding import preview_boot, preview_ready, preview_setup, preview_thinking, preview_tour
36
41
  from .widgets import (
37
42
  IndexDashboard,
38
43
  IndexState,
@@ -45,7 +50,8 @@ from .widgets import (
45
50
  tty_hint,
46
51
  )
47
52
 
48
- SCENES = ("card", "progress", "dashboard", "events", "sprite", "logs", "ship")
53
+ SCENES = ("boot", "setup", "ready", "thinking", "card", "progress", "dashboard", "events", "sprite", "logs", "ship")
54
+ PREVIEW_SCENES = ("tour", *SCENES)
49
55
 
50
56
 
51
57
  def _sleep(seconds: float, *, fast: bool) -> None:
@@ -182,7 +188,7 @@ def demo_ship_lane(console, *, ticks: int = 24, fast: bool = False) -> None:
182
188
  steps = [
183
189
  ("validate", "python tests"),
184
190
  ("package", "agentsam-sdk"),
185
- ("cli", "agentsam tui"),
191
+ ("cli", "internal UI preview"),
186
192
  ("run", "operator action"),
187
193
  ("receipt", "status captured"),
188
194
  ("done", "command complete"),
@@ -219,6 +225,10 @@ def demo_ship_lane(console, *, ticks: int = 24, fast: bool = False) -> None:
219
225
 
220
226
 
221
227
  SCENE_FNS = {
228
+ "boot": preview_boot,
229
+ "setup": preview_setup,
230
+ "ready": preview_ready,
231
+ "thinking": preview_thinking,
222
232
  "card": demo_status_card,
223
233
  "progress": demo_progress,
224
234
  "dashboard": demo_live_dashboard,
@@ -230,11 +240,16 @@ SCENE_FNS = {
230
240
 
231
241
 
232
242
  def run_scene(name: str, console, *, ticks: int, fast: bool) -> None:
243
+ if name == "tour":
244
+ console.print()
245
+ console.print(Rule("[bold iam.cyan]guided CLI tour[/]"))
246
+ preview_tour(console, fast=fast, ticks=ticks)
247
+ return
233
248
  fn = SCENE_FNS[name]
234
249
  console.print()
235
250
  console.print(Rule(f"[bold iam.cyan]{name}[/]"))
236
251
  kwargs = {"fast": fast}
237
- if name in {"progress", "dashboard", "sprite", "ship"}:
252
+ if name in {"boot", "setup", "ready", "thinking", "progress", "dashboard", "sprite", "ship"}:
238
253
  kwargs["ticks"] = ticks
239
254
  fn(console, **kwargs)
240
255
 
@@ -246,7 +261,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
246
261
  )
247
262
  parser.add_argument(
248
263
  "--scene",
249
- choices=("all", *SCENES),
264
+ choices=("all", *PREVIEW_SCENES),
250
265
  default="all",
251
266
  help="Which demo to run (default: all)",
252
267
  )
@@ -283,7 +298,7 @@ def main(argv: list[str] | None = None) -> int:
283
298
  run_scene(name, console, ticks=ticks, fast=fast)
284
299
 
285
300
  console.print()
286
- console.print("[bold iam.green]Done.[/] Next: wire these renderables into real SDK CLI commands.")
301
+ console.print("[bold iam.green]Preview complete.[/] Internal renderer lab; bare `agentsam` owns the product boot flow.")
287
302
  return 0
288
303
 
289
304
 
@@ -0,0 +1,208 @@
1
+ """Preview-only startup and onboarding compositions for the Agent Sam CLI.
2
+
3
+ These scenes intentionally do not perform setup or mutate local state. They let us
4
+ judge the terminal UX before wiring the same presentation primitives into
5
+ `agentsam`, `agentsam init`, and `agentsam shell`.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import time
10
+ from dataclasses import dataclass
11
+
12
+ from .bootstrap import require_rich
13
+
14
+ require_rich()
15
+
16
+ from rich.align import Align
17
+ from rich.console import Group
18
+ from rich.live import Live
19
+ from rich.panel import Panel
20
+ from rich.table import Table
21
+ from rich.text import Text
22
+
23
+ from .frames import BRAILLE, MOON, THINK
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class PreviewContext:
28
+ project: str = "agentsam-sdk"
29
+ cwd: str = "~/agentsam-sdk"
30
+ shell: str = "zsh"
31
+ platform: str = "macOS"
32
+ version: str = "2.5.0"
33
+
34
+
35
+ def _sleep(seconds: float, *, fast: bool) -> None:
36
+ time.sleep(0.0 if fast else seconds)
37
+
38
+
39
+ def _brand_header(ctx: PreviewContext, *, tick: int = 0) -> Group:
40
+ pulse = MOON[tick % len(MOON)]
41
+ title = Text()
42
+ title.append(" Agent Sam", style="bold iam.heading")
43
+ title.append(f" {pulse}", style="bold iam.cyan")
44
+ meta = Text(
45
+ f" SDK {ctx.version} · {ctx.platform} · {ctx.shell}",
46
+ style="iam.muted",
47
+ )
48
+ return Group(title, meta)
49
+
50
+
51
+ def _boot_card(ctx: PreviewContext, *, tick: int, phase: int) -> Panel:
52
+ states = (
53
+ ("environment", "Detecting terminal", phase >= 1),
54
+ ("project", ctx.project, phase >= 2),
55
+ ("shell", f"{ctx.shell} · {ctx.cwd}", phase >= 3),
56
+ ("runtime", "Local-first", phase >= 4),
57
+ )
58
+ rows = Table.grid(padding=(0, 2))
59
+ rows.add_column(style="iam.muted", justify="right", min_width=12)
60
+ rows.add_column(min_width=34)
61
+ for index, (label, value, ready) in enumerate(states):
62
+ if ready:
63
+ mark = "[iam.green]✓[/]"
64
+ body = f"[iam.text]{value}[/]"
65
+ elif index == phase:
66
+ mark = f"[bold iam.cyan]{BRAILLE[tick % len(BRAILLE)]}[/]"
67
+ body = f"[iam.muted]{value}[/]"
68
+ else:
69
+ mark = "[dim]·[/]"
70
+ body = f"[dim]{value}[/]"
71
+ rows.add_row(label, f"{mark} {body}")
72
+ return Panel(
73
+ Group(_brand_header(ctx, tick=tick), Text(""), rows),
74
+ border_style="iam.cyan",
75
+ padding=(1, 2),
76
+ subtitle="[iam.muted]starting locally — no cloud required[/]",
77
+ width=62,
78
+ )
79
+
80
+
81
+ def preview_boot(console, *, fast: bool = False, ticks: int = 24) -> None:
82
+ """Compact cold-start sequence: identity, environment, cwd, then handoff."""
83
+ ctx = PreviewContext()
84
+ frames = max(8, min(ticks, 28))
85
+ with Live(console=console, refresh_per_second=18, transient=False) as live:
86
+ for i in range(frames):
87
+ phase = min(4, i // max(1, frames // 5))
88
+ live.update(_boot_card(ctx, tick=i, phase=phase))
89
+ _sleep(0.055, fast=fast)
90
+ live.update(_boot_card(ctx, tick=frames, phase=4))
91
+ console.print(" [iam.green]✓[/] Ready [iam.muted]· type [bold]/help[/] when you want the map[/]")
92
+
93
+
94
+ def _setup_panel(step: int, tick: int, ctx: PreviewContext) -> Panel:
95
+ steps = [
96
+ ("Project", "Use this folder", ctx.cwd),
97
+ ("Local runtime", "Keep execution on this machine", "recommended"),
98
+ ("Terminal", "Use your existing shell", ctx.shell),
99
+ ("Agent", "Enable Agent Sam when you need it", "optional"),
100
+ ("Done", "Open the guided shell", "agentsam shell"),
101
+ ]
102
+ grid = Table.grid(padding=(0, 2))
103
+ grid.add_column(width=3, justify="center")
104
+ grid.add_column(min_width=15)
105
+ grid.add_column(min_width=29)
106
+ for i, (label, description, answer) in enumerate(steps):
107
+ if i < step:
108
+ marker = "[iam.green]✓[/]"
109
+ label_style = "iam.text"
110
+ detail = f"[iam.muted]{answer}[/]"
111
+ elif i == step:
112
+ marker = f"[bold iam.cyan]{MOON[tick % len(MOON)]}[/]"
113
+ label_style = "bold iam.heading"
114
+ detail = f"[iam.cyan]{description}[/]\n[dim] {answer}[/]"
115
+ else:
116
+ marker = "[dim]○[/]"
117
+ label_style = "dim"
118
+ detail = f"[dim]{description}[/]"
119
+ grid.add_row(marker, f"[{label_style}]{label}[/]", detail)
120
+ footer = "Enter choose · ↑↓ move · Esc back" if step < len(steps) - 1 else "Enter open shell · setup can be changed later"
121
+ return Panel(
122
+ grid,
123
+ title="[bold iam.heading]Set up Agent Sam[/]",
124
+ subtitle=f"[iam.muted]{footer}[/]",
125
+ border_style="iam.cyan",
126
+ padding=(1, 2),
127
+ width=68,
128
+ )
129
+
130
+
131
+ def preview_setup(console, *, fast: bool = False, ticks: int = 30) -> None:
132
+ """Progressive-discovery wizard mock: one decision at a time, no wall of text."""
133
+ ctx = PreviewContext()
134
+ console.print(_brand_header(ctx))
135
+ console.print(" [iam.muted]First run · five small choices. Nothing is uploaded.[/]")
136
+ console.print()
137
+ steps = 5
138
+ with Live(console=console, refresh_per_second=12, transient=False) as live:
139
+ for step in range(steps):
140
+ loops = 1 if fast else max(2, min(5, ticks // steps))
141
+ for tick in range(loops):
142
+ live.update(_setup_panel(step, tick, ctx))
143
+ _sleep(0.12, fast=fast)
144
+ live.update(_setup_panel(steps - 1, 4, ctx))
145
+
146
+
147
+ def _ready_panel(ctx: PreviewContext, *, tick: int) -> Panel:
148
+ hint = Table.grid(padding=(0, 2))
149
+ hint.add_column(style="iam.cyan", min_width=14)
150
+ hint.add_column(style="iam.muted")
151
+ hint.add_row("/help", "show the command map")
152
+ hint.add_row("/status", "check project + local services")
153
+ hint.add_row("/agent <goal>", "ask Agent Sam to work with you")
154
+ hint.add_row("regular shell", "git, npm, python, etc. stay normal")
155
+
156
+ prompt = Text()
157
+ prompt.append("sam", style="bold iam.cyan")
158
+ prompt.append(f" {ctx.cwd}", style="iam.muted")
159
+ prompt.append(" › ", style="bold iam.heading")
160
+ prompt.append("_" if tick % 2 == 0 else " ", style="iam.cyan")
161
+
162
+ return Panel(
163
+ Group(_brand_header(ctx, tick=tick), Text(""), hint, Text(""), prompt),
164
+ title="[bold iam.heading]Ready[/]",
165
+ border_style="iam.green",
166
+ padding=(1, 2),
167
+ width=68,
168
+ )
169
+
170
+
171
+ def preview_ready(console, *, fast: bool = False, ticks: int = 12) -> None:
172
+ """The final quiet landing state: useful hints, then get out of the way."""
173
+ ctx = PreviewContext()
174
+ loops = 2 if fast else max(4, min(ticks, 16))
175
+ with Live(console=console, refresh_per_second=4, transient=False) as live:
176
+ for i in range(loops):
177
+ live.update(_ready_panel(ctx, tick=i))
178
+ _sleep(0.22, fast=fast)
179
+
180
+
181
+ def preview_thinking(console, *, fast: bool = False, ticks: int = 18) -> None:
182
+ """Small assistant activity animation intended for inline use, not a full screen."""
183
+ loops = 3 if fast else max(6, min(ticks, 24))
184
+ with Live(console=console, refresh_per_second=14, transient=False) as live:
185
+ for i in range(loops):
186
+ frame = THINK[i % len(THINK)]
187
+ body = Text(frame, style="bold iam.cyan", no_wrap=True)
188
+ live.update(
189
+ Panel(
190
+ Align.center(body),
191
+ title="[bold iam.heading]Agent Sam[/]",
192
+ subtitle="[iam.muted]thinking · working locally[/]",
193
+ border_style="iam.cyan",
194
+ width=34,
195
+ padding=(0, 1),
196
+ )
197
+ )
198
+ _sleep(0.09, fast=fast)
199
+
200
+
201
+ def preview_tour(console, *, fast: bool = False, ticks: int = 24) -> None:
202
+ preview_boot(console, fast=fast, ticks=ticks)
203
+ console.print()
204
+ preview_setup(console, fast=fast, ticks=ticks)
205
+ console.print()
206
+ preview_thinking(console, fast=fast, ticks=ticks)
207
+ console.print()
208
+ preview_ready(console, fast=fast, ticks=ticks)
@@ -1,5 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
4
+ import io
3
5
  import unittest
4
6
 
5
7
  from agentsam_sdk.cli import build_parser
@@ -7,13 +9,12 @@ from agentsam_sdk.tui.frames import BRAILLE, COMET, MOON, THINK, WALKER
7
9
 
8
10
 
9
11
  class TuiCliTests(unittest.TestCase):
10
- def test_tui_command_is_registered_without_importing_rich(self):
11
- args = build_parser().parse_args(["tui", "--scene", "card", "--check"])
12
- self.assertEqual(args.group, "tui")
13
- self.assertEqual(args.scene, "card")
14
- self.assertTrue(args.check)
12
+ def test_tui_is_not_a_public_python_cli_command(self):
13
+ with contextlib.redirect_stderr(io.StringIO()):
14
+ with self.assertRaises(SystemExit):
15
+ build_parser().parse_args(["tui"])
15
16
 
16
- def test_animation_frames_are_available_without_rich(self):
17
+ def test_animation_frames_remain_available_to_internal_renderers(self):
17
18
  self.assertGreater(len(BRAILLE), 0)
18
19
  self.assertGreater(len(MOON), 0)
19
20
  self.assertGreater(len(WALKER), 0)
@@ -0,0 +1,21 @@
1
+ # AgentSam Skills
2
+
3
+ Portable, on-demand AgentSam behavior modules. Skills keep specialized guidance
4
+ out of the permanent system prompt and load deeper `references/` only when the
5
+ current task calls for them.
6
+
7
+ ## Canonical skills
8
+
9
+ - `agentsam-jr-dev/` — explain, inspect, build, and revise real software using
10
+ beginner-friendly language grounded in the actual repository and runtime.
11
+
12
+ - `agentsam-app-fundamentals/` — quick application-building laws for trust,
13
+ contracts, credentials, dependency graphs, AST evidence, and Merkle evidence.
14
+ - `agentsam-progression-guard/` — checkpoint/hook discipline for local work, CI,
15
+ deploy, postdeploy verification, promotion, runtime observation, and rollback.
16
+
17
+ List or open them with `agentsam skills`; aliases such as `quick-bytes` and
18
+ `no-regress` are intentionally short enough for terminal use.
19
+
20
+ Apps may contain host-specific skill directories of their own. Those do not
21
+ replace the portable SDK skills in this directory.