agents-inc 0.171.0 → 0.172.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 (91) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{chunk-WM2N2D6Q.js → chunk-255DGUCH.js} +2 -2
  3. package/dist/chunk-33JICQD5.js +196 -0
  4. package/dist/chunk-33JICQD5.js.map +1 -0
  5. package/dist/{chunk-ZC6GC66J.js → chunk-3R3LHA4Q.js} +2 -2
  6. package/dist/{chunk-KMOCMVK5.js → chunk-5MGRHS2G.js} +94 -58
  7. package/dist/chunk-5MGRHS2G.js.map +1 -0
  8. package/dist/{chunk-JGPE4RRE.js → chunk-5PPB6HT6.js} +2 -2
  9. package/dist/{chunk-S2SKVJT2.js → chunk-6CRA46YO.js} +14 -14
  10. package/dist/{chunk-TNFYBKVD.js → chunk-6LUTY35Q.js} +25 -14
  11. package/dist/chunk-6LUTY35Q.js.map +1 -0
  12. package/dist/{chunk-24OD7IP4.js → chunk-7OG635DK.js} +26 -4
  13. package/dist/chunk-7OG635DK.js.map +1 -0
  14. package/dist/{chunk-QIR56IDM.js → chunk-7ZOWSCAO.js} +29 -102
  15. package/dist/chunk-7ZOWSCAO.js.map +1 -0
  16. package/dist/{chunk-WDH6HHA3.js → chunk-A3ZAXL5T.js} +4 -5
  17. package/dist/{chunk-WDH6HHA3.js.map → chunk-A3ZAXL5T.js.map} +1 -1
  18. package/dist/chunk-G7NUK3BF.js +253 -0
  19. package/dist/chunk-G7NUK3BF.js.map +1 -0
  20. package/dist/{chunk-7IVLVEHX.js → chunk-KCLBLK3F.js} +3 -3
  21. package/dist/{chunk-AWWCRL5A.js → chunk-LUKDDHSI.js} +8 -6
  22. package/dist/{chunk-AWWCRL5A.js.map → chunk-LUKDDHSI.js.map} +1 -1
  23. package/dist/{chunk-W4KAY26P.js → chunk-MBIOZ5LW.js} +12 -3
  24. package/dist/{chunk-W4KAY26P.js.map → chunk-MBIOZ5LW.js.map} +1 -1
  25. package/dist/{chunk-A6OWEJGC.js → chunk-MHAQWMNJ.js} +35 -5
  26. package/dist/{chunk-A6OWEJGC.js.map → chunk-MHAQWMNJ.js.map} +1 -1
  27. package/dist/{chunk-RDXY4GRO.js → chunk-MOL2J5HS.js} +2 -2
  28. package/dist/{chunk-YLUOGAW7.js → chunk-N33AKFLR.js} +2 -2
  29. package/dist/{chunk-WII6GOPM.js → chunk-NISWBQNS.js} +52 -31
  30. package/dist/chunk-NISWBQNS.js.map +1 -0
  31. package/dist/{chunk-3YYHL76L.js → chunk-VILFCMRN.js} +420 -316
  32. package/dist/chunk-VILFCMRN.js.map +1 -0
  33. package/dist/{chunk-EOKNEGRD.js → chunk-Y23MP2OC.js} +8 -8
  34. package/dist/commands/build/marketplace.js +16 -14
  35. package/dist/commands/build/marketplace.js.map +1 -1
  36. package/dist/commands/build/plugins.js +6 -6
  37. package/dist/commands/compile.js +12 -12
  38. package/dist/commands/doctor.js +64 -81
  39. package/dist/commands/doctor.js.map +1 -1
  40. package/dist/commands/edit.js +150 -152
  41. package/dist/commands/edit.js.map +1 -1
  42. package/dist/commands/eject.js +10 -10
  43. package/dist/commands/init.js +19 -16
  44. package/dist/commands/list.js +14 -17
  45. package/dist/commands/list.js.map +1 -1
  46. package/dist/commands/new/marketplace.js +4 -4
  47. package/dist/commands/search.js +15 -13
  48. package/dist/commands/search.js.map +1 -1
  49. package/dist/commands/share.js +11 -11
  50. package/dist/commands/uninstall.js +109 -98
  51. package/dist/commands/uninstall.js.map +1 -1
  52. package/dist/commands/update.js +6 -6
  53. package/dist/components/common/scroll-affordance.js +2 -2
  54. package/dist/components/common/select-list.js +2 -2
  55. package/dist/components/common/skill-agent-summary.js +3 -4
  56. package/dist/components/common/summary-panel.js +11 -146
  57. package/dist/components/common/summary-panel.js.map +1 -1
  58. package/dist/hooks/init.js +22 -19
  59. package/dist/hooks/init.js.map +1 -1
  60. package/dist/load-agent-defs-54VIKN4T.js +14 -0
  61. package/dist/{recompile-project-agents-IQANWGOP.js → recompile-project-agents-5A44NJRD.js} +8 -8
  62. package/dist/{source-loader-YGG7DY2W.js → source-loader-LQNRI5UZ.js} +4 -4
  63. package/dist/src/agents/tester/web-tester/playbook.md +1 -1
  64. package/package.json +1 -1
  65. package/src/agents/tester/web-tester/playbook.md +1 -1
  66. package/dist/chunk-24OD7IP4.js.map +0 -1
  67. package/dist/chunk-3YYHL76L.js.map +0 -1
  68. package/dist/chunk-4RQKCV6I.js +0 -103
  69. package/dist/chunk-4RQKCV6I.js.map +0 -1
  70. package/dist/chunk-5FM77WKW.js +0 -69
  71. package/dist/chunk-5FM77WKW.js.map +0 -1
  72. package/dist/chunk-KMOCMVK5.js.map +0 -1
  73. package/dist/chunk-QIR56IDM.js.map +0 -1
  74. package/dist/chunk-R572RLTI.js +0 -108
  75. package/dist/chunk-R572RLTI.js.map +0 -1
  76. package/dist/chunk-TNFYBKVD.js.map +0 -1
  77. package/dist/chunk-WII6GOPM.js.map +0 -1
  78. package/dist/components/common/removal-plan-confirm.js +0 -10
  79. package/dist/load-agent-defs-UBWITIEI.js +0 -14
  80. package/dist/source-loader-YGG7DY2W.js.map +0 -1
  81. /package/dist/{chunk-WM2N2D6Q.js.map → chunk-255DGUCH.js.map} +0 -0
  82. /package/dist/{chunk-ZC6GC66J.js.map → chunk-3R3LHA4Q.js.map} +0 -0
  83. /package/dist/{chunk-JGPE4RRE.js.map → chunk-5PPB6HT6.js.map} +0 -0
  84. /package/dist/{chunk-S2SKVJT2.js.map → chunk-6CRA46YO.js.map} +0 -0
  85. /package/dist/{chunk-7IVLVEHX.js.map → chunk-KCLBLK3F.js.map} +0 -0
  86. /package/dist/{chunk-RDXY4GRO.js.map → chunk-MOL2J5HS.js.map} +0 -0
  87. /package/dist/{chunk-YLUOGAW7.js.map → chunk-N33AKFLR.js.map} +0 -0
  88. /package/dist/{chunk-EOKNEGRD.js.map → chunk-Y23MP2OC.js.map} +0 -0
  89. /package/dist/{components/common/removal-plan-confirm.js.map → load-agent-defs-54VIKN4T.js.map} +0 -0
  90. /package/dist/{recompile-project-agents-IQANWGOP.js.map → recompile-project-agents-5A44NJRD.js.map} +0 -0
  91. /package/dist/{load-agent-defs-UBWITIEI.js.map → source-loader-LQNRI5UZ.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ Each release has detailed notes in its own file under [`changelogs/`](./changelo
7
7
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
+ ## [0.172.0] - 2026-10-22
11
+
12
+ **`init --from`, `edit --from` and `uninstall` show the summary panel at the question, the editor names the sub-agents a skill switches and holds a project link's global entries, links are version 7, and agentsinc.sh/ opens the editor**
13
+
14
+ - REPO-44:
15
+ - The editor names the sub-agents a skill switches on or off in a toast, keeps a stack's sub-agents on with no skills, and holds the global entries of a link a bare `edit` mints in a project. Share links are version 7, so earlier links and saves must be made again.
16
+ - Text a link carries prints inert on one line, a marketplace value holding a line break is refused, and a carried file whose path leaves its folder is refused.
17
+ - Agent plugins version by the files they ship, `list` keeps long names whole, a carried skill's name may pass 30 characters, and remedies name the installation they act on.
18
+ - agentsinc.sh/ redirects to the editor, and the landing page is gone.
19
+ - CLI-925: `doctor` fails its marketplace row offline or on a refusal, lists no ejected skill as an orphan, and passes two healthy installations. Sub-agents install without a skill that fails to load. A local `AGENTS_INC_API_URL` selects the local editor and `AGENTS_INC_EDITOR_URL` is gone. `build marketplace` refuses an empty config, a global edit says it recompiles its registered projects, and a no-op `edit --from` without a terminal exits 0.
20
+ - CLI-908: `init --from`, `edit --from` and `uninstall` show the summary panel where they ask, marking a changed sub-agent `~` and a skill written over `↻`.
21
+ - CLI-915: `init --from` in a project writes the link's own description, or none, never the global installation's.
22
+ - EDITOR-97: a link the CLI mints also opens on a signed-in account's save it equals.
23
+ - Five items still fail in one case each (E1-d, E2, F5b, F9, FU2); the detailed notes list them under Backlog.
24
+
25
+ See [changelogs/0.172.0.md](./changelogs/0.172.0.md) for full details.
26
+
10
27
  ## [0.171.0] - 2026-10-22
11
28
 
12
29
  **`doctor` reads each installation, `edit --from` names what it deletes and overwrites, a link's carried skill cannot write outside its folder, and compiled sub-agents carry only the hooks they declare**
@@ -14,7 +14,7 @@ import {
14
14
  readFileOptional,
15
15
  unexpressibleOnCodexMessage,
16
16
  writeFile
17
- } from "./chunk-3YYHL76L.js";
17
+ } from "./chunk-VILFCMRN.js";
18
18
 
19
19
  // src/cli/lib/hosts/claude-project-trust.ts
20
20
  import path from "path";
@@ -235,4 +235,4 @@ async function hostCompileNotices(provider, projectDir) {
235
235
  export {
236
236
  hostCompileNotices
237
237
  };
238
- //# sourceMappingURL=chunk-WM2N2D6Q.js.map
238
+ //# sourceMappingURL=chunk-255DGUCH.js.map
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ScrollAffordance
4
+ } from "./chunk-N33AKFLR.js";
5
+ import {
6
+ SkillAgentSummary
7
+ } from "./chunk-G7NUK3BF.js";
8
+ import {
9
+ ALL_SKILLS_EJECTED_LABEL,
10
+ CLI_COLORS,
11
+ DEFAULT_PUBLIC_SOURCE_NAME,
12
+ EJECT_SOURCE,
13
+ formatSourceDisplayName
14
+ } from "./chunk-MHAQWMNJ.js";
15
+
16
+ // src/cli/components/common/summary-panel.tsx
17
+ import { Box, Text, renderToString } from "ink";
18
+ import "react";
19
+ import { unique } from "remeda";
20
+
21
+ // src/cli/components/hooks/use-panel-scroll.ts
22
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
23
+ import { measureElement as measureElement2, useInput } from "ink";
24
+
25
+ // src/cli/components/hooks/use-measured-height.ts
26
+ import { useRef, useState, useEffect } from "react";
27
+ import { measureElement, useStdout } from "ink";
28
+ function useMeasuredHeight() {
29
+ const ref = useRef(null);
30
+ const [measuredHeight, setMeasuredHeight] = useState(0);
31
+ const { stdout } = useStdout();
32
+ const measure = () => {
33
+ if (ref.current) {
34
+ const { height } = measureElement(ref.current);
35
+ setMeasuredHeight((prev) => prev !== height ? height : prev);
36
+ }
37
+ };
38
+ useEffect(() => {
39
+ measure();
40
+ });
41
+ useEffect(() => {
42
+ const RETRY_DELAYS_MS = [0, 16, 50];
43
+ const timers = [];
44
+ for (const delay of RETRY_DELAYS_MS) {
45
+ timers.push(setTimeout(measure, delay));
46
+ }
47
+ return () => {
48
+ for (const timer of timers) {
49
+ clearTimeout(timer);
50
+ }
51
+ };
52
+ }, []);
53
+ useEffect(() => {
54
+ stdout.on("resize", measure);
55
+ return () => {
56
+ stdout.off("resize", measure);
57
+ };
58
+ }, [stdout]);
59
+ return { ref, measuredHeight };
60
+ }
61
+
62
+ // src/cli/components/hooks/use-panel-scroll.ts
63
+ function usePanelScroll() {
64
+ const { ref: viewportRef, measuredHeight: viewportHeight } = useMeasuredHeight();
65
+ const contentRef = useRef2(null);
66
+ const [contentHeight, setContentHeight] = useState2(0);
67
+ const [scrollOffset, setScrollOffset] = useState2(0);
68
+ useEffect2(() => {
69
+ if (!contentRef.current) return;
70
+ const { height } = measureElement2(contentRef.current);
71
+ setContentHeight((prev) => Math.max(prev, height));
72
+ });
73
+ const maxScroll = Math.max(0, contentHeight - viewportHeight);
74
+ const hiddenBelow = Math.max(0, maxScroll - scrollOffset);
75
+ useInput((_input, key) => {
76
+ if (key.upArrow) setScrollOffset((prev) => Math.max(0, prev - 1));
77
+ if (key.downArrow) setScrollOffset((prev) => Math.min(maxScroll, prev + 1));
78
+ });
79
+ return {
80
+ viewportRef,
81
+ contentRef,
82
+ contentMarginTop: scrollOffset > 0 ? -scrollOffset : 0,
83
+ hiddenAbove: scrollOffset,
84
+ hiddenBelow
85
+ };
86
+ }
87
+
88
+ // src/cli/components/hooks/use-terminal-dimensions.ts
89
+ import { useState as useState3, useEffect as useEffect3 } from "react";
90
+ import { useStdout as useStdout2 } from "ink";
91
+ var DEFAULT_COLUMNS = 80;
92
+ var DEFAULT_ROWS = 24;
93
+ function dimensionsOf(stdout) {
94
+ return {
95
+ columns: stdout.columns || DEFAULT_COLUMNS,
96
+ rows: stdout.rows || DEFAULT_ROWS
97
+ };
98
+ }
99
+ function useTerminalDimensions() {
100
+ const { stdout } = useStdout2();
101
+ const [dimensions, setDimensions] = useState3(() => dimensionsOf(stdout));
102
+ useEffect3(() => {
103
+ const handleResize = () => {
104
+ setDimensions(dimensionsOf(stdout));
105
+ };
106
+ stdout.on("resize", handleResize);
107
+ return () => {
108
+ stdout.off("resize", handleResize);
109
+ };
110
+ }, [stdout]);
111
+ return dimensions;
112
+ }
113
+
114
+ // src/cli/components/common/summary-panel.tsx
115
+ import { jsx, jsxs } from "react/jsx-runtime";
116
+ function skillsTheHeaderNames({
117
+ skillConfigs,
118
+ installedSkillConfigs
119
+ }) {
120
+ return skillConfigs.length > 0 ? skillConfigs : installedSkillConfigs ?? [];
121
+ }
122
+ function formatSkillMarketplaces(skillConfigs) {
123
+ if (skillConfigs.length === 0) return formatSourceDisplayName(DEFAULT_PUBLIC_SOURCE_NAME);
124
+ const marketplaceNames = unique(
125
+ skillConfigs.map((config) => config.origin).filter((origin) => origin !== EJECT_SOURCE)
126
+ );
127
+ if (marketplaceNames.length === 0) return ALL_SKILLS_EJECTED_LABEL;
128
+ return marketplaceNames.map((name) => formatSourceDisplayName(name)).sort().join(" \xB7 ");
129
+ }
130
+ var PanelHeader = ({ sourceNames, stackName }) => /* @__PURE__ */ jsxs(
131
+ Box,
132
+ {
133
+ flexDirection: "column",
134
+ flexShrink: 0,
135
+ borderStyle: "single",
136
+ borderBottom: true,
137
+ borderTop: false,
138
+ borderLeft: false,
139
+ borderRight: false,
140
+ borderColor: CLI_COLORS.NEUTRAL,
141
+ borderBottomDimColor: true,
142
+ paddingBottom: 1,
143
+ marginBottom: 1,
144
+ children: [
145
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", columnGap: 1, children: [
146
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, bold: true, children: "Marketplace" }),
147
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.NEUTRAL, children: sourceNames })
148
+ ] }),
149
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", columnGap: 1, children: [
150
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, bold: true, children: "Stack" }),
151
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.NEUTRAL, children: stackName ?? "none" })
152
+ ] })
153
+ ]
154
+ }
155
+ );
156
+ var SummaryPanel = ({ stackName, ...summary }) => {
157
+ const { viewportRef, contentRef, contentMarginTop, hiddenAbove, hiddenBelow } = usePanelScroll();
158
+ const sourceNames = formatSkillMarketplaces(skillsTheHeaderNames(summary));
159
+ return /* @__PURE__ */ jsxs(
160
+ Box,
161
+ {
162
+ flexDirection: "column",
163
+ flexGrow: 1,
164
+ flexBasis: 0,
165
+ borderStyle: "single",
166
+ borderColor: CLI_COLORS.NEUTRAL,
167
+ paddingX: 2,
168
+ children: [
169
+ /* @__PURE__ */ jsx(Box, { ref: viewportRef, flexDirection: "column", flexGrow: 1, flexBasis: 0, overflow: "hidden", children: /* @__PURE__ */ jsxs(Box, { ref: contentRef, flexDirection: "column", flexShrink: 0, marginTop: contentMarginTop, children: [
170
+ /* @__PURE__ */ jsx(PanelHeader, { sourceNames, stackName }),
171
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(SkillAgentSummary, { ...summary }) })
172
+ ] }) }),
173
+ /* @__PURE__ */ jsx(ScrollAffordance, { hiddenAbove, hiddenBelow })
174
+ ]
175
+ }
176
+ );
177
+ };
178
+ function summaryPanelText(props, columns = dimensionsOf(process.stdout).columns) {
179
+ return renderToString(/* @__PURE__ */ jsx(SummaryPanel, { ...props }), { columns });
180
+ }
181
+ function summaryPanelBlock(panel, linesUnder, statements) {
182
+ return [
183
+ summaryPanelText(panel),
184
+ ...linesUnder,
185
+ ...statements.flatMap((statement) => ["", statement]),
186
+ ""
187
+ ];
188
+ }
189
+
190
+ export {
191
+ useTerminalDimensions,
192
+ SummaryPanel,
193
+ summaryPanelText,
194
+ summaryPanelBlock
195
+ };
196
+ //# sourceMappingURL=chunk-33JICQD5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/common/summary-panel.tsx","../src/cli/components/hooks/use-panel-scroll.ts","../src/cli/components/hooks/use-measured-height.ts","../src/cli/components/hooks/use-terminal-dimensions.ts"],"sourcesContent":["import { Box, Text, renderToString } from \"ink\";\nimport React from \"react\";\nimport { unique } from \"remeda\";\nimport {\n ALL_SKILLS_EJECTED_LABEL,\n CLI_COLORS,\n DEFAULT_PUBLIC_SOURCE_NAME,\n EJECT_SOURCE,\n formatSourceDisplayName,\n} from \"../../consts.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport { usePanelScroll } from \"../hooks/use-panel-scroll.js\";\nimport { dimensionsOf } from \"../hooks/use-terminal-dimensions.js\";\nimport { ScrollAffordance } from \"./scroll-affordance.js\";\nimport { SkillAgentSummary, type SkillAgentSummaryProps } from \"./skill-agent-summary.js\";\n\nexport type SummaryPanelProps = SkillAgentSummaryProps & {\n /** `undefined` when the configuration was built from no stack. */\n stackName: string | undefined;\n};\n\n/**\n * The skills the panel leaves in place; leaving none, as an uninstall does, those it removes. The\n * default marketplace is only for a panel with no skill either way.\n */\nfunction skillsTheHeaderNames({\n skillConfigs,\n installedSkillConfigs,\n}: SkillAgentSummaryProps): SkillConfig[] {\n return skillConfigs.length > 0 ? skillConfigs : (installedSkillConfigs ?? []);\n}\n\n/**\n * No skills shows the default marketplace; all-ejected names none. Tombstoned entries count: the\n * summary below renders them as rows.\n */\nfunction formatSkillMarketplaces(skillConfigs: SkillConfig[]): string {\n if (skillConfigs.length === 0) return formatSourceDisplayName(DEFAULT_PUBLIC_SOURCE_NAME);\n\n const marketplaceNames = unique(\n skillConfigs.map((config) => config.origin).filter((origin) => origin !== EJECT_SOURCE),\n );\n if (marketplaceNames.length === 0) return ALL_SKILLS_EJECTED_LABEL;\n\n return marketplaceNames\n .map((name) => formatSourceDisplayName(name))\n .sort()\n .join(\" · \");\n}\n\ntype PanelHeaderProps = {\n sourceNames: string;\n stackName: string | undefined;\n};\n\n/** `flexShrink={0}`: squeezed by Yoga on a short terminal, its two rows overprint. */\nconst PanelHeader: React.FC<PanelHeaderProps> = ({ sourceNames, stackName }) => (\n <Box\n flexDirection=\"column\"\n flexShrink={0}\n borderStyle=\"single\"\n borderBottom={true}\n borderTop={false}\n borderLeft={false}\n borderRight={false}\n borderColor={CLI_COLORS.NEUTRAL}\n borderBottomDimColor\n paddingBottom={1}\n marginBottom={1}\n >\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Marketplace\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{sourceNames}</Text>\n </Box>\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Stack\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{stackName ?? \"none\"}</Text>\n </Box>\n </Box>\n);\n\n/** Horizontal padding only: unshrinkable vertical padding starves the viewport on a short terminal. */\nexport const SummaryPanel: React.FC<SummaryPanelProps> = ({ stackName, ...summary }) => {\n const { viewportRef, contentRef, contentMarginTop, hiddenAbove, hiddenBelow } = usePanelScroll();\n\n const sourceNames = formatSkillMarketplaces(skillsTheHeaderNames(summary));\n\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n flexBasis={0}\n borderStyle=\"single\"\n borderColor={CLI_COLORS.NEUTRAL}\n paddingX={2}\n >\n <Box ref={viewportRef} flexDirection=\"column\" flexGrow={1} flexBasis={0} overflow=\"hidden\">\n <Box ref={contentRef} flexDirection=\"column\" flexShrink={0} marginTop={contentMarginTop}>\n <PanelHeader sourceNames={sourceNames} stackName={stackName} />\n\n <Box width=\"100%\">\n <SkillAgentSummary {...summary} />\n </Box>\n </Box>\n </Box>\n <ScrollAffordance hiddenAbove={hiddenAbove} hiddenBelow={hiddenBelow} />\n </Box>\n );\n};\n\n/**\n * The whole panel as text, drawn once: printed, it scrolls with the terminal like any other line,\n * and a run with no terminal prints the same thing.\n */\nexport function summaryPanelText(\n props: SummaryPanelProps,\n columns: number = dimensionsOf(process.stdout).columns,\n): string {\n return renderToString(<SummaryPanel {...props} />, { columns });\n}\n\n/**\n * What a question shows, or where none is asked, what prints in its place: the panel, the lines\n * under it marking what it cannot show, then each statement after a blank line, and a blank line\n * before what follows.\n */\nexport function summaryPanelBlock(\n panel: SummaryPanelProps,\n linesUnder: readonly string[],\n statements: readonly string[],\n): string[] {\n return [\n summaryPanelText(panel),\n ...linesUnder,\n ...statements.flatMap((statement) => [\"\", statement]),\n \"\",\n ];\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { Ref, RefObject } from \"react\";\nimport { type DOMElement, measureElement, useInput } from \"ink\";\nimport { useMeasuredHeight } from \"./use-measured-height.js\";\n\nexport type UsePanelScrollResult = {\n /** The `overflow=\"hidden\"` box. */\n viewportRef: Ref<DOMElement>;\n contentRef: RefObject<DOMElement | null>;\n contentMarginTop: number;\n hiddenAbove: number;\n hiddenBelow: number;\n};\n\n/** `↑`/`↓` line scrolling for one clipped viewport; hosts add their own `useInput` for other keys. */\nexport function usePanelScroll(): UsePanelScrollResult {\n const { ref: viewportRef, measuredHeight: viewportHeight } = useMeasuredHeight();\n const contentRef = useRef<DOMElement>(null);\n const [contentHeight, setContentHeight] = useState(0);\n const [scrollOffset, setScrollOffset] = useState(0);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- re-measures every render; layout changes are invisible to React\n useEffect(() => {\n if (!contentRef.current) return;\n const { height } = measureElement(contentRef.current);\n // Yoga under-reports inside a squeezed viewport; trusting that loops the render.\n setContentHeight((prev) => Math.max(prev, height));\n });\n\n // Not returned: gating the clip on contentHeight paints content over the border.\n const maxScroll = Math.max(0, contentHeight - viewportHeight);\n const hiddenBelow = Math.max(0, maxScroll - scrollOffset);\n\n useInput((_input, key) => {\n if (key.upArrow) setScrollOffset((prev) => Math.max(0, prev - 1));\n if (key.downArrow) setScrollOffset((prev) => Math.min(maxScroll, prev + 1));\n });\n\n return {\n viewportRef,\n contentRef,\n contentMarginTop: scrollOffset > 0 ? -scrollOffset : 0,\n hiddenAbove: scrollOffset,\n hiddenBelow,\n };\n}\n","import { useRef, useState, useEffect } from \"react\";\nimport { type DOMElement, measureElement, useStdout } from \"ink\";\n\n/** Attach to a `flexGrow={1}` Box under an ancestor of constrained height; 0 before first layout. */\nexport function useMeasuredHeight(): {\n ref: React.Ref<DOMElement>;\n measuredHeight: number;\n} {\n const ref = useRef<DOMElement>(null);\n const [measuredHeight, setMeasuredHeight] = useState(0);\n const { stdout } = useStdout();\n\n const measure = () => {\n if (ref.current) {\n const { height } = measureElement(ref.current);\n setMeasuredHeight((prev) => (prev !== height ? height : prev));\n }\n };\n\n // Every render, so late-mounted refs are picked up.\n useEffect(() => {\n measure();\n });\n\n // Yoga may not have laid out yet on first render, so retry a few times.\n useEffect(() => {\n const RETRY_DELAYS_MS = [0, 16, 50];\n const timers: ReturnType<typeof setTimeout>[] = [];\n\n for (const delay of RETRY_DELAYS_MS) {\n timers.push(setTimeout(measure, delay));\n }\n\n return () => {\n for (const timer of timers) {\n clearTimeout(timer);\n }\n };\n // Mount-only: listing `measure` would re-arm the timers every render.\n }, []);\n\n useEffect(() => {\n stdout.on(\"resize\", measure);\n return () => {\n stdout.off(\"resize\", measure);\n };\n }, [stdout]);\n\n return { ref, measuredHeight };\n}\n","import { useState, useEffect } from \"react\";\nimport { useStdout } from \"ink\";\n\nconst DEFAULT_COLUMNS = 80;\nconst DEFAULT_ROWS = 24;\n\nexport type TerminalDimensions = {\n columns: number;\n rows: number;\n};\n\n/** A stream that is not a terminal reports no size, so it gets the defaults. */\nexport function dimensionsOf(stdout: NodeJS.WriteStream): TerminalDimensions {\n return {\n columns: stdout.columns || DEFAULT_COLUMNS,\n rows: stdout.rows || DEFAULT_ROWS,\n };\n}\n\nexport function useTerminalDimensions(): TerminalDimensions {\n const { stdout } = useStdout();\n\n const [dimensions, setDimensions] = useState<TerminalDimensions>(() => dimensionsOf(stdout));\n\n useEffect(() => {\n const handleResize = () => {\n setDimensions(dimensionsOf(stdout));\n };\n\n stdout.on(\"resize\", handleResize);\n return () => {\n stdout.off(\"resize\", handleResize);\n };\n }, [stdout]);\n\n return dimensions;\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","measureElement","useRef","useState","useEffect","measureElement","useState","useEffect","useStdout"]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CLI_COLORS,
4
4
  UI_SYMBOLS
5
- } from "./chunk-A6OWEJGC.js";
5
+ } from "./chunk-MHAQWMNJ.js";
6
6
 
7
7
  // src/cli/components/common/select-list.tsx
8
8
  import { useCallback as useCallback2 } from "react";
@@ -103,4 +103,4 @@ function SelectList({
103
103
  export {
104
104
  SelectList
105
105
  };
106
- //# sourceMappingURL=chunk-ZC6GC66J.js.map
106
+ //# sourceMappingURL=chunk-3R3LHA4Q.js.map
@@ -1,23 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SelectList
4
- } from "./chunk-ZC6GC66J.js";
4
+ } from "./chunk-3R3LHA4Q.js";
5
5
  import {
6
6
  openUrl
7
- } from "./chunk-JGPE4RRE.js";
7
+ } from "./chunk-5PPB6HT6.js";
8
8
  import {
9
9
  fetchSeedConfig
10
- } from "./chunk-WDH6HHA3.js";
10
+ } from "./chunk-A3ZAXL5T.js";
11
+ import {
12
+ Confirm
13
+ } from "./chunk-OZXAJNLA.js";
11
14
  import {
12
15
  promptConfirm,
13
16
  promptValue
14
17
  } from "./chunk-P6CYS4JK.js";
15
18
  import {
16
- Confirm
17
- } from "./chunk-OZXAJNLA.js";
19
+ summaryPanelBlock,
20
+ useTerminalDimensions
21
+ } from "./chunk-33JICQD5.js";
18
22
  import {
19
23
  hostCompileNotices
20
- } from "./chunk-WM2N2D6Q.js";
24
+ } from "./chunk-255DGUCH.js";
21
25
  import {
22
26
  compileAgentsAllScopes,
23
27
  compileProjectScope,
@@ -25,34 +29,38 @@ import {
25
29
  movedGlobalAgentInputs,
26
30
  sayCapturedWarnings,
27
31
  writeProjectConfig
28
- } from "./chunk-S2SKVJT2.js";
32
+ } from "./chunk-6CRA46YO.js";
29
33
  import {
30
34
  copyLocalSkills,
31
35
  discoverInstalledSkills
32
- } from "./chunk-EOKNEGRD.js";
36
+ } from "./chunk-Y23MP2OC.js";
33
37
  import {
34
38
  loadAgentDefs
35
- } from "./chunk-7IVLVEHX.js";
39
+ } from "./chunk-KCLBLK3F.js";
36
40
  import {
37
41
  render
38
42
  } from "./chunk-KIK5EZYD.js";
39
43
  import {
44
+ agentChangesAmong
45
+ } from "./chunk-G7NUK3BF.js";
46
+ import {
47
+ installationToName,
40
48
  providerFlag,
41
49
  providerNamedBy,
42
50
  providerNeedsAConfigurationToInstall
43
- } from "./chunk-W4KAY26P.js";
51
+ } from "./chunk-MBIOZ5LW.js";
44
52
  import {
45
53
  BaseCommand,
46
54
  EXIT_CODES,
47
55
  clearTerminalScreen,
48
56
  holdInstalledGlobal,
49
- installPlanLines,
50
57
  installsAtHome,
58
+ joinedStatement,
51
59
  notInstalledGlobally,
52
60
  readInstalledGlobal,
53
61
  registerExternalSkills,
54
62
  writeExternalSkills
55
- } from "./chunk-QIR56IDM.js";
63
+ } from "./chunk-7ZOWSCAO.js";
56
64
  import {
57
65
  ERROR_MESSAGES,
58
66
  INCOMPLETE_WORK_RECOVERY,
@@ -93,54 +101,32 @@ import {
93
101
  seedToInstallSelection,
94
102
  settingsFileSchema,
95
103
  sharedConfigExistingInstall,
104
+ subAgentChanged,
96
105
  warn
97
- } from "./chunk-3YYHL76L.js";
106
+ } from "./chunk-VILFCMRN.js";
98
107
  import {
99
108
  plural
100
- } from "./chunk-24OD7IP4.js";
109
+ } from "./chunk-7OG635DK.js";
101
110
  import {
102
111
  ASCII_LOGO,
103
112
  CLI_COLORS,
104
113
  CLI_INVOKE_COMMAND,
105
114
  DEFAULT_BRANDING,
115
+ EDITOR_ADDRESS,
106
116
  EDITOR_URL,
107
117
  EJECT_SOURCE,
108
118
  MAX_CONFIG_FILE_SIZE,
109
- editorConfigUrl
110
- } from "./chunk-A6OWEJGC.js";
119
+ editorConfigUrl,
120
+ isActiveAt
121
+ } from "./chunk-MHAQWMNJ.js";
111
122
 
112
123
  // src/cli/commands/init.tsx
124
+ import os from "os";
113
125
  import "react";
114
126
  import { Flags } from "@oclif/core";
115
127
  import { Box as Box2, Text as Text2, useApp } from "ink";
116
128
  import { partition } from "remeda";
117
129
 
118
- // src/cli/components/hooks/use-terminal-dimensions.ts
119
- import { useState, useEffect } from "react";
120
- import { useStdout } from "ink";
121
- var DEFAULT_COLUMNS = 80;
122
- var DEFAULT_ROWS = 24;
123
- function dimensionsOf(stdout) {
124
- return {
125
- columns: stdout.columns || DEFAULT_COLUMNS,
126
- rows: stdout.rows || DEFAULT_ROWS
127
- };
128
- }
129
- function useTerminalDimensions() {
130
- const { stdout } = useStdout();
131
- const [dimensions, setDimensions] = useState(() => dimensionsOf(stdout));
132
- useEffect(() => {
133
- const handleResize = () => {
134
- setDimensions(dimensionsOf(stdout));
135
- };
136
- stdout.on("resize", handleResize);
137
- return () => {
138
- stdout.off("resize", handleResize);
139
- };
140
- }, [stdout]);
141
- return dimensions;
142
- }
143
-
144
130
  // src/cli/lib/permission-checker.tsx
145
131
  import "react";
146
132
  import "zod";
@@ -316,7 +302,7 @@ var Init = class _Init extends BaseCommand {
316
302
  /** Resolved once in {@link install}; the closing line is printed several calls below. */
317
303
  brandingName = DEFAULT_BRANDING.NAME;
318
304
  static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;
319
- static description = "Build a configuration in agentsinc.sh/editor, or install one by id with --from. Over an existing installation, shows its dashboard.";
305
+ static description = `Build a configuration in ${EDITOR_ADDRESS}, or install one by id with --from. Over an existing installation, shows its dashboard.`;
320
306
  static examples = [
321
307
  {
322
308
  description: "Open the editor to build a configuration",
@@ -342,7 +328,7 @@ var Init = class _Init extends BaseCommand {
342
328
  helpValue: "<id>"
343
329
  }),
344
330
  ui: Flags.boolean({
345
- description: "Open agentsinc.sh/editor on the id --from names, or on the catalogue \u2014 what a bare init does where nothing is installed",
331
+ description: `Open ${EDITOR_ADDRESS} on the id --from names, or on the catalogue \u2014 what a bare init does where nothing is installed`,
346
332
  default: false
347
333
  }),
348
334
  provider: providerFlag()
@@ -356,9 +342,11 @@ var Init = class _Init extends BaseCommand {
356
342
  async openEditor(projectDir, provider, id, marketplace) {
357
343
  const url = id === void 0 ? EDITOR_URL : editorConfigUrl(id);
358
344
  const marketplaceLine = marketplace === void 0 ? void 0 : this.addMarketplaceLineOrFail(marketplace);
345
+ const installedHere = await holdsItsOwnInstallation(projectDir);
346
+ const toName = installedHere ? await installationToName(projectDir, provider) : provider;
359
347
  this.log(id === void 0 ? `Build it at ${url}` : `Open it at ${url}`);
360
348
  if (marketplaceLine !== void 0) this.log(marketplaceLine);
361
- this.log(applySharedConfigHere(id, await holdsItsOwnInstallation(projectDir), provider));
349
+ this.log(applySharedConfigHere(id, installedHere, toName));
362
350
  if (!process.stdin.isTTY) return;
363
351
  const opened = await openUrl(url);
364
352
  if (!opened.ok) this.warn(opened.error);
@@ -419,8 +407,9 @@ var Init = class _Init extends BaseCommand {
419
407
  );
420
408
  const mapping = this.decodeSeedOrFail(payload, sourceResult.matrix);
421
409
  const { result } = mapping;
422
- this.refuseProjectScopedContentAtHome(result, projectDir);
423
- const held = holdInstalledGlobal(result, await installedGlobalToHold(projectDir));
410
+ this.refuseProjectScopedContentAtHome(result, projectDir, false);
411
+ const installedGlobal = await installedGlobalToHold(projectDir);
412
+ const held = holdInstalledGlobal(result, installedGlobal);
424
413
  const arrivingCarried = notInstalledGlobally(carriedSkills, held);
425
414
  await this.refuseSharedConfigBeforeAsking(
426
415
  held.result,
@@ -429,9 +418,13 @@ var Init = class _Init extends BaseCommand {
429
418
  sourceResult
430
419
  );
431
420
  sayCapturedWarnings(startupMessages);
432
- this.warnOfSkippedEntries(mapping, held.result.selectedAgents);
421
+ this.warnOfSkippedEntries(mapping);
433
422
  this.refuseAnEmptySelection(held.result, id);
434
- this.logWhatGoesWhere(held, installsAtHome(result) ? id : void 0);
423
+ const stackName = await this.stackNameOf(result.selectedStackId, sourceResult);
424
+ this.logWhatGoesWhere(held, installedGlobal, stackName, {
425
+ id: installsAtHome(result) ? id : void 0,
426
+ provider: providerToNameAt(os.homedir(), providerInUse(projectDir))
427
+ });
435
428
  if (process.stdin.isTTY && !await this.confirmInstall()) {
436
429
  this.log("Setup cancelled");
437
430
  return null;
@@ -445,16 +438,20 @@ var Init = class _Init extends BaseCommand {
445
438
  installedAlready: new Set(held.installed.skillIds)
446
439
  };
447
440
  }
448
- /** `idAppliedAtHome` is the id only where a run from home would take the configuration. */
449
- logWhatGoesWhere(held, idAppliedAtHome) {
450
- for (const line of installPlanLines(held)) {
441
+ /**
442
+ * The panel where the question is asked, or where it would be: the project against the whole
443
+ * global install it inherits. `runFromHome.id` is the id only where home would take it.
444
+ */
445
+ logWhatGoesWhere(held, installedGlobal, stackName, runFromHome) {
446
+ const joined = joinedGlobalAgents(held, installedGlobal);
447
+ const lines = summaryPanelBlock(
448
+ installPanel(held, installedGlobal, joined, stackName),
449
+ joined.map(subAgentChanged),
450
+ [...joinedStatement(held), ...keptAsInstalledStatement(held, runFromHome)]
451
+ );
452
+ for (const line of lines) {
451
453
  this.log(line);
452
454
  }
453
- const { skillIds, agentNames } = held.keptAsInstalled;
454
- if (skillIds.length > 0 || agentNames.length > 0) {
455
- this.log(keptAsInstalledGlobally(skillIds, agentNames, idAppliedAtHome));
456
- }
457
- this.log("");
458
455
  }
459
456
  refuseAnEmptySelection(result, id) {
460
457
  if (!selectsNothing(result)) return;
@@ -704,6 +701,45 @@ async function installedGlobalToHold(projectDir) {
704
701
  if (isHomeDirectory(projectDir)) return null;
705
702
  return await readInstalledGlobal(projectDir);
706
703
  }
704
+ function keptAsInstalledStatement(held, runFromHome) {
705
+ const { skillIds, agentNames } = held.keptAsInstalled;
706
+ if (skillIds.length === 0 && agentNames.length === 0) return [];
707
+ return [keptAsInstalledGlobally(skillIds, agentNames, runFromHome.id, runFromHome.provider)];
708
+ }
709
+ function inheritedGlobal(held, installedGlobal) {
710
+ if (installedGlobal === null) return { skills: [], agents: [] };
711
+ const namedSkills = new Set(held.result.skills.filter(isGlobal).map(({ id }) => id));
712
+ const namedAgents = new Set(held.result.agentConfigs.filter(isGlobal).map(({ name }) => name));
713
+ return {
714
+ skills: installedGlobal.skills.filter((skill) => isGlobal(skill) && !namedSkills.has(skill.id)),
715
+ agents: installedGlobal.agents.filter(
716
+ (agent) => isGlobal(agent) && !namedAgents.has(agent.name)
717
+ )
718
+ };
719
+ }
720
+ function isGlobal(entry) {
721
+ return isActiveAt(entry, "global");
722
+ }
723
+ function installPanel(held, installedGlobal, joined, stackName) {
724
+ const inherited = inheritedGlobal(held, installedGlobal);
725
+ return {
726
+ skillConfigs: [...held.result.skills, ...inherited.skills],
727
+ agentConfigs: [...held.result.agentConfigs, ...inherited.agents],
728
+ installedSkillConfigs: installedGlobal?.skills ?? null,
729
+ installedAgentConfigs: installedGlobal?.agents ?? null,
730
+ isInitMode: true,
731
+ changedAgentNames: new Set(joined.map(({ name }) => name)),
732
+ stackName
733
+ };
734
+ }
735
+ function joinedGlobalAgents(held, installedGlobal) {
736
+ if (installedGlobal === null) return [];
737
+ return agentChangesAmong(
738
+ held.joined.map(({ agentName }) => agentName),
739
+ installedGlobal,
740
+ { agents: held.result.agentConfigs, stack: held.result.assignedStack }
741
+ );
742
+ }
707
743
  function planInstall(result, installedAlready) {
708
744
  const toInstall = result.skills.filter(
709
745
  (skill) => !skill.excluded && !installedAlready.has(skill.id)
@@ -815,4 +851,4 @@ export {
815
851
  runDashboardFlow,
816
852
  Init
817
853
  };
818
- //# sourceMappingURL=chunk-KMOCMVK5.js.map
854
+ //# sourceMappingURL=chunk-5MGRHS2G.js.map