2026-03-16 13:34:05 -05:00
|
|
|
#!/usr/bin/env node
|
2026-03-19 08:38:50 -05:00
|
|
|
const { spawnSync } = require('child_process');
|
|
|
|
|
const { copyFileSync, mkdirSync, readdirSync, rmSync } = require('fs');
|
|
|
|
|
const { dirname, join } = require('path');
|
|
|
|
|
|
|
|
|
|
function copyNonTsFiles(srcDir, destDir) {
|
|
|
|
|
for (const entry of readdirSync(srcDir, { withFileTypes: true })) {
|
|
|
|
|
const srcPath = join(srcDir, entry.name);
|
|
|
|
|
const destPath = join(destDir, entry.name);
|
|
|
|
|
|
|
|
|
|
if (entry.isDirectory()) {
|
|
|
|
|
copyNonTsFiles(srcPath, destPath);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mkdirSync(dirname(destPath), { recursive: true });
|
fix: apply pi manifest opt-out to extension-discovery.ts (#1545)
* fix: apply pi manifest opt-out to extension-discovery.ts (#1537 follow-up)
The cmux fix in #1537 patched resolveExtensionEntries() in
packages/pi-coding-agent/src/core/extensions/loader.ts to honor
"pi": {} as an opt-out from auto-discovery. However, there is a
second copy of resolveExtensionEntries() in src/extension-discovery.ts
that was not updated. This is the version actually used at startup
by loader.js via discoverExtensionEntryPaths().
As a result, cmux/index.js is still discovered and loaded as an
extension on startup, producing:
Extension does not export a valid factory function: .../cmux/index.js
Fix: Apply the same authoritative-manifest logic to the
extension-discovery.ts copy. When a package.json has a "pi" field,
treat it as authoritative and return early — either with declared
extension paths or an empty array for library opt-out.
Tests: 7 new tests covering resolveExtensionEntries and
discoverExtensionEntryPaths behavior for opt-out, declared
extensions, and fallback discovery.
* fix: apply pi manifest opt-out to package-manager.ts (third copy)
There are THREE copies of resolveExtensionEntries():
1. packages/pi-coding-agent/src/core/extensions/loader.ts (fixed in #1537)
2. src/extension-discovery.ts (fixed in previous commit)
3. packages/pi-coding-agent/src/core/package-manager.ts (THIS commit)
Copy #3 is used by collectAutoExtensionEntries() which is called from
addAutoDiscoveredResources() during DefaultPackageManager.resolve().
This is the actual code path that discovers ~/.gsd/agent/extensions/cmux
and passes it to loadExtensions(), producing the factory function error.
* fix: rewrite pi.extensions .ts paths to .js during resource copy
copy-resources.cjs compiles .ts → .js via tsc but copies package.json
files verbatim. Extensions with pi.extensions: ["./index.ts"] end up
in dist/ pointing to a .ts file that doesn't exist (only .js does).
This causes resolveExtensionEntries() to find no valid entry points,
silently skipping the extension. Affected: gsd, browser-tools, context7,
google-search, universal-config — all extensions with pi manifests.
Fix: When copying package.json files, rewrite .ts/.tsx extensions in
pi.extensions arrays to .js so they match the compiled output.
* fix: add missing commands to /gsd description and rate sub-completions
- Add 9 missing commands to the description string: widget, rate, park,
unpark, init, setup, logs, inspect, extensions
- Add sub-completions for /gsd rate (over/ok/under)
* feat: grid layout for parallel cmux splits and completion trailing-space fix
CmuxClient.createGridLayout(count) pre-creates a tiled grid of surfaces
before launching parallel agents, instead of the previous approach of
creating splits per-agent with alternating right/down directions.
Grid layout strategy:
1 agent: [gsd | A]
2 agents: [gsd | A] (A split down)
[ | B]
3 agents: [gsd | A] (2x2 grid)
[ C | B]
4 agents: [gsd | A] (additional splits from bottom-right)
[ C | B]
[ | D]
Changes:
- Add CmuxClient.createSplitFrom(sourceSurfaceId, direction) to split
from a specific surface rather than always the gsd surface
- Add CmuxClient.createGridLayout(count) that builds the grid and
returns surface IDs in order
- Update runSingleAgentInCmuxSplit to accept a pre-created surface ID
(string) or a direction for backward compatibility
- Parallel dispatch pre-creates grid, assigns each agent a surface
- Fix getArgumentCompletions trailing-space handling so sub-completions
work (e.g., /gsd cmux <tab> now shows status/on/off/etc.)
- 5 new tests for grid layout logic
2026-03-20 09:11:51 -05:00
|
|
|
|
|
|
|
|
// Rewrite pi.extensions paths from .ts to .js in package.json files
|
|
|
|
|
// so they match the compiled output (tsc compiles index.ts → index.js
|
|
|
|
|
// but package.json is copied as-is).
|
|
|
|
|
if (entry.name === 'package.json') {
|
|
|
|
|
try {
|
|
|
|
|
const pkg = JSON.parse(require('fs').readFileSync(srcPath, 'utf-8'));
|
|
|
|
|
if (Array.isArray(pkg?.pi?.extensions)) {
|
|
|
|
|
pkg.pi.extensions = pkg.pi.extensions.map(ext =>
|
|
|
|
|
ext.replace(/\.ts$/, '.js').replace(/\.tsx$/, '.js')
|
|
|
|
|
);
|
|
|
|
|
require('fs').writeFileSync(destPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} catch { /* fall through to plain copy */ }
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 08:38:50 -05:00
|
|
|
copyFileSync(srcPath, destPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 13:34:05 -05:00
|
|
|
rmSync('dist/resources', { recursive: true, force: true });
|
2026-03-19 08:38:50 -05:00
|
|
|
|
|
|
|
|
const tscBin = require.resolve('typescript/bin/tsc');
|
|
|
|
|
const compile = spawnSync(process.execPath, [tscBin, '--project', 'tsconfig.resources.json'], {
|
|
|
|
|
stdio: 'inherit',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (compile.status !== 0) {
|
|
|
|
|
process.exit(compile.status ?? 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copyNonTsFiles('src/resources', 'dist/resources');
|