Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/cli/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ISC License

Copyright (c) 2026 Mathieu Colmon

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4 changes: 1 addition & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"version": "4.0.0-alpha.0",
"description": "Agent-first Miakapp command line: check, build, publish, activate and roll back home components",
"type": "module",
"private": true,
"engines": {
"bun": ">=1.2.23",
"node": ">=22.9"
Expand Down Expand Up @@ -31,8 +30,7 @@
"directory": "packages/cli"
},
"publishConfig": {
"access": "public",
"tag": "next"
"access": "public"
},
"keywords": [
"Miakapp",
Expand Down
19 changes: 14 additions & 5 deletions packages/cli/src/agent-pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Bytes outside those regions are copied through untouched.
*/
import { projectError } from './errors.js';
import { CLI_VERSION, PACKAGE_NAME } from './version.js';

/** Directory the pack owns inside the owner's repository. */
export const PACK_DIRECTORY = '.miakapp';
Expand Down Expand Up @@ -163,15 +164,23 @@ export function mergeInstructions(existing: string | undefined, block: string):
/**
* The server entry, as a client expects to find it.
*
* `command` is the bare binary name: the pack is written into a repository that
* may be opened on another machine, where an absolute path from this one would
* resolve to nothing.
* An absolute path is wrong: the pack is written into a repository that may be
* opened on another machine, where a path from this one resolves to nothing.
* The bare binary name is wrong for the same reason in reverse — it assumes a
* global install nobody performed, so the server simply fails to start in the
* repository the pack was meant to equip. Both were observed: a rehearsal in a
* fresh repository found `command: "miakapp"` unresolvable.
*
* `npx` resolves the published package on any machine with Node, installing it
* on first use. The version is pinned rather than floating because the guide
* written beside this file is the guide of *this* release: a floating spec
* would pair one release's prose with another release's tool surface.
*/
export function serverEntry(): Record<string, unknown> {
return {
type: 'stdio',
command: SERVER_NAME,
args: ['mcp'],
command: 'npx',
args: ['-y', `${PACKAGE_NAME}@${CLI_VERSION}`, 'mcp'],
};
}

Expand Down
3 changes: 2 additions & 1 deletion packages/cli/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* - `--json`, which prints exactly one closed object on stdout.
*/
import { installPack } from './agent-pack.js';
import { CLI_VERSION } from './version.js';
import { prepareArtifact, type Artifact } from './artifact.js';
import { exchangePublisherToken, fetchDiscovery } from './control-plane.js';
import { discoverFlows, inventoryJson, type Inventory } from './discovery.js';
Expand All @@ -38,7 +39,7 @@ import {
type PublicationTarget,
} from './publication.js';

export const CLI_VERSION = '4.0.0-alpha.0';
export { CLI_VERSION };

/**
* The Home Key is read from the environment only. A secret passed as an
Expand Down
15 changes: 15 additions & 0 deletions packages/cli/src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* The package's own identity, in one place.
*
* `main.ts` imports `agent-pack.ts`, so the constants cannot live in `main.ts`
* without a cycle: the pack needs them to write a runnable MCP entry.
*
* Both values are duplicates of `package.json`, which cannot be imported here
* without a JSON import assertion the build does not emit. `test/version.test.ts`
* compares them to the manifest, because the drift is not cosmetic: the pack
* writes `PACKAGE_NAME@CLI_VERSION` into a repository, and a stale version
* would resolve a different release than the guide shipped beside it.
*/
export const PACKAGE_NAME = '@miakapp/cli';

export const CLI_VERSION = '4.0.0-alpha.0';
19 changes: 15 additions & 4 deletions packages/cli/test/agent-pack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { EXIT_CODE } from '../src/errors.js';
import { guideAssetPath, run } from '../src/main.js';
import { TOOLS, buildArgv } from '../src/mcp.js';
import { CLI_VERSION, PACKAGE_NAME } from '../src/version.js';
import { MemoryFiles, PROJECT_ROOT, testHost } from './support/host.js';

const GUIDE_TEXT = '# Building a Miakapp home\n\nThe packaged guide.\n';
Expand Down Expand Up @@ -57,11 +58,21 @@ describe('the pack installs into an empty repository', () => {
expect(config(files)['mcpServers'][SERVER_NAME]).toEqual(serverEntry());
});

test('the server is launched by bare name, so the repository is portable', () => {
// This assertion used to require the bare binary name, on the reasoning that
// a name travels between machines and a path does not. The reasoning held;
// the conclusion did not. Rehearsed in a fresh repository, `command:
// "miakapp"` names a binary nobody installed, so the server never starts.
// Portability is still the property under test — it now has to be satisfied
// by something the repository can actually run.
test('the server is launched by something a fresh repository can run', () => {
const entry = serverEntry();
expect(entry['command']).toBe(SERVER_NAME);
expect(entry['args']).toEqual(['mcp']);
expect(JSON.stringify(entry)).not.toContain('/');
expect(entry['command']).toBe('npx');
expect(entry['args']).toEqual(['-y', `${PACKAGE_NAME}@${CLI_VERSION}`, 'mcp']);
expect(entry['args']).not.toContain(PROJECT_ROOT);
});

test('the entry is keyed by the server name, whatever launches it', () => {
expect(Object.keys({ [SERVER_NAME]: serverEntry() })).toEqual([SERVER_NAME]);
});

test('it installs where --dir points, not where the process happens to be', async () => {
Expand Down
48 changes: 48 additions & 0 deletions packages/cli/test/version.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { describe, expect, test } from 'bun:test';

import { CLI_VERSION, PACKAGE_NAME } from '../src/version.js';
import { serverEntry } from '../src/agent-pack.js';

const manifest = (await Bun.file(new URL('../package.json', import.meta.url)).json()) as {
name: string;
version: string;
};

describe('package identity', () => {
// These two constants are a hand-kept duplicate of the manifest. That is
// tolerable only while something compares them: `agent-pack` writes
// `name@version` into someone else's repository, so a stale constant
// silently pins a release that is not the one shipping the guide next to it.
test('CLI_VERSION matches the published manifest version', () => {
expect(CLI_VERSION).toBe(manifest.version);
});

test('PACKAGE_NAME matches the published manifest name', () => {
expect(PACKAGE_NAME).toBe(manifest.name);
});
});

describe('the MCP entry the pack installs', () => {
// A fresh owner repository has no globally installed `miakapp`; the entry has
// to bring its own tool. This asserts the property, not the spelling.
test('names no bare binary that a fresh repository would lack', () => {
const entry = serverEntry();
expect(entry['command']).not.toBe('miakapp');
});

test('resolves the exact published release through npx', () => {
expect(serverEntry()).toEqual({
type: 'stdio',
command: 'npx',
args: ['-y', `${manifest.name}@${manifest.version}`, 'mcp'],
});
});

test('carries no absolute path from the machine that wrote it', () => {
const entry = serverEntry();
const words = [entry['command'] as string, ...(entry['args'] as string[])];
for (const word of words) {
expect(word.startsWith('/')).toBe(false);
}
});
});
15 changes: 15 additions & 0 deletions packages/component/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ISC License

Copyright (c) 2026 Mathieu Colmon

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4 changes: 1 addition & 3 deletions packages/component/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"version": "4.0.0-alpha.0",
"description": "Guest SDK for Miakapp home components: semantic UI, granted state, calls and events inside the sandboxed Worker",
"type": "module",
"private": true,
"engines": {
"bun": ">=1.2.23",
"node": ">=22.9"
Expand Down Expand Up @@ -32,8 +31,7 @@
"directory": "packages/component"
},
"publishConfig": {
"access": "public",
"tag": "next"
"access": "public"
},
"keywords": [
"Miakapp",
Expand Down
Loading