@lapxo/head 0.1.0 → 0.1.4
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 +24 -0
- package/TARGET.bound +517 -54
- package/dist/src/access/contract.d.ts +2 -0
- package/dist/src/access/obtain.d.ts +7 -1
- package/dist/src/access/obtain.js +6 -6
- package/dist/src/adopt/adopt.js +5 -2
- package/dist/src/compile/pin.js +5 -5
- package/dist/src/core/act.d.ts +1 -0
- package/dist/src/core/act.js +1 -0
- package/dist/src/core/answer.d.ts +18 -4
- package/dist/src/core/answer.js +7 -4
- package/dist/src/core/lock.d.ts +2 -0
- package/dist/src/core/lock.js +2 -0
- package/dist/src/core/package.d.ts +54 -0
- package/dist/src/core/package.js +65 -0
- package/dist/src/core/read.d.ts +3 -0
- package/dist/src/core/read.js +8 -4
- package/dist/src/core/surface.d.ts +1 -40
- package/dist/src/core/surface.js +4 -29
- package/dist/src/core/trust.d.ts +7 -0
- package/dist/src/core/trust.js +19 -0
- package/dist/src/flows/call.d.ts +1 -3
- package/dist/src/flows/call.js +3 -6
- package/dist/src/flows/device.js +1 -6
- package/dist/src/flows/read.js +24 -11
- package/dist/src/flows/world.js +3 -3
- package/dist/src/index.js +45 -21
- package/dist/src/onboard/first.d.ts +9 -0
- package/dist/src/onboard/first.js +38 -0
- package/dist/src/onboard/owed.d.ts +10 -0
- package/dist/src/onboard/owed.js +28 -0
- package/dist/src/onboard/site.d.ts +12 -0
- package/dist/src/onboard/site.js +22 -0
- package/dist/src/places/admit.js +1 -1
- package/dist/src/places/found.d.ts +1 -0
- package/dist/src/places/found.js +8 -7
- package/dist/src/ports/access/authorizer.d.ts +10 -0
- package/dist/src/ports/access/authorizer.js +34 -0
- package/dist/src/ports/access/flow.js +13 -3
- package/dist/src/ports/access/person.d.ts +3 -2
- package/dist/src/ports/access/person.js +12 -5
- package/dist/src/ports/adapters/request.d.ts +3 -0
- package/dist/src/ports/adapters/request.js +5 -3
- package/dist/src/ports/bound.d.ts +12 -2
- package/dist/src/ports/bound.js +30 -13
- package/dist/src/ports/documents.d.ts +34 -0
- package/dist/src/ports/documents.js +64 -0
- package/dist/src/ports/keychain.d.ts +2 -1
- package/dist/src/ports/keychain.js +3 -2
- package/dist/src/ports/place.d.ts +1 -0
- package/dist/src/ports/place.js +7 -1
- package/dist/src/ports/process.d.ts +9 -0
- package/dist/src/ports/process.js +5 -3
- package/dist/src/ports/spare.d.ts +1 -0
- package/dist/src/ports/spare.js +33 -0
- package/dist/src/ports/surface.d.ts +130 -0
- package/dist/src/ports/surface.js +50 -0
- package/dist/src/ports/warm.d.ts +19 -0
- package/dist/src/ports/warm.js +46 -0
- package/dist/src/signer.js +1 -1
- package/dist/src/sources/access.d.ts +10 -1
- package/dist/src/sources/access.js +15 -10
- package/dist/src/sources/connect.d.ts +13 -2
- package/dist/src/sources/connect.js +69 -38
- package/dist/src/sources/refused.d.ts +7 -0
- package/dist/src/sources/refused.js +16 -0
- package/dist/src/tools/ask.d.ts +1 -0
- package/dist/src/tools/ask.js +1 -0
- package/dist/src/tools/card.d.ts +1 -1
- package/dist/src/tools/card.js +5 -4
- package/dist/src/tools/do.d.ts +1 -0
- package/dist/src/tools/do.js +1 -0
- package/dist/src/tools/look.d.ts +5 -4
- package/dist/src/tools/look.js +15 -13
- package/dist/src/tools/places.d.ts +7 -0
- package/dist/src/tools/places.js +32 -0
- package/dist/src/tools/share.d.ts +1 -0
- package/dist/src/tools/share.js +1 -0
- package/dist/src/verbs/ask.d.ts +11 -0
- package/dist/src/verbs/ask.js +35 -0
- package/dist/src/verbs/card.d.ts +11 -0
- package/dist/src/verbs/card.js +16 -0
- package/dist/src/verbs/do.d.ts +8 -0
- package/dist/src/verbs/do.js +28 -0
- package/package.json +6 -5
- /package/dist/src/{core → ports}/keys.d.ts +0 -0
- /package/dist/src/{core → ports}/keys.js +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { LOCK } from '@lapxo/topos/wire';
|
|
3
|
+
import { answerOf, placeOf } from "../core/answer.js";
|
|
4
|
+
import { valueOf } from "../core/lock.js";
|
|
5
|
+
import { sayIn } from "../core/surface.js";
|
|
6
|
+
import { paidIn } from "../onboard/owed.js";
|
|
7
|
+
import { pendingIn } from "../sources/refused.js";
|
|
8
|
+
import { cardAt } from "./card.js";
|
|
9
|
+
/**
|
|
10
|
+
* What a person asks, answered by the question it is. A view, or the region of a source or of one operation in it (what
|
|
11
|
+
* it offers, one read of it, why that answer stands, what was kept of it), is answered by look; drafted lines by plan;
|
|
12
|
+
* what is open by card; anything else by places. Each form is read with no resolution unless the lock declares one for a
|
|
13
|
+
* person; asked why, at the one it declares to explain, and where it declares none, the same answer, said so. Nothing
|
|
14
|
+
* here writes one. An answer about one place ends with its card, taken off the fold the answer reads, valid from it.
|
|
15
|
+
* With no place at all, nothing is founded: it says so, and that connecting an API founds the person's place, the question
|
|
16
|
+
* carried along. A place still owing a source's bytes is answered only once they arrive.
|
|
17
|
+
*/
|
|
18
|
+
export const asked = async (asked, context) => {
|
|
19
|
+
const why = asked['why'] === 'true', at = (form) => valueOf(context.lock, `resolution/${form}/${why ? 'why' : 'person'}`) || undefined;
|
|
20
|
+
const read = async (form, tool, more = {}) => [...(why && at(form) === undefined ? [sayIn(context.lock)('why-undeclared', { form })] : []),
|
|
21
|
+
...await (await answerOf('tools', tool))({ ...asked, ...more, at: at(form) }, context)];
|
|
22
|
+
const place = await placeOf(asked, context), founded = place !== undefined && context.files.has(place, LOCK), carded = asked['card'] === 'true';
|
|
23
|
+
if (place === undefined && !carded && !context.files.has(context.home(), LOCK))
|
|
24
|
+
return [sayIn(context.lock)('unborn', { dir: join(context.personal(), valueOf(context.lock, 'first-run/folder')), source: asked['source'], operation: asked['operation'], args: asked['args'] })];
|
|
25
|
+
const held = founded || carded ? await cardAt(context, place) : undefined;
|
|
26
|
+
if (carded && held !== undefined && 'said' in held)
|
|
27
|
+
return held.said;
|
|
28
|
+
const owed = asked['source'] && founded ? await paidIn(asked, context, place) : undefined;
|
|
29
|
+
if (owed !== undefined && !owed.answer)
|
|
30
|
+
return owed.said;
|
|
31
|
+
const answer = asked['lines'] ? await read('plan', 'plan') : asked['view'] ? await read('view', 'look') : asked['source'] ? await read('offers', 'look')
|
|
32
|
+
: !carded ? await read('places', 'places') : founded ? [...await read('card', 'card', { place }), ...await pendingIn(context, place)] : [];
|
|
33
|
+
const after = held === undefined || 'said' in held || place === undefined || !context.moved(place) ? held : await cardAt(context, place);
|
|
34
|
+
return [...(owed?.said ?? []), ...answer, ...(after === undefined || 'said' in after ? [] : [sayIn(context.lock)('card', { place: place ?? '', card: after.card, from: 'ask' })])];
|
|
35
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context } from '../core/answer.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The card an act is made on: the place's standing as bound folds it, with the reads it kept set aside, and the keys this
|
|
4
|
+
* device acts with. Anything landed, a grant withdrawn or a key admitted or changed moves it; a read never does. A folder
|
|
5
|
+
* that holds no place yet has the card of nothing.
|
|
6
|
+
*/
|
|
7
|
+
export declare const cardAt: (context: Context, place: string | undefined) => Promise<{
|
|
8
|
+
readonly card: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly said: readonly string[];
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { LOCK } from '@lapxo/topos/wire';
|
|
3
|
+
import { baseOf, standingOr } from "../core/answer.js";
|
|
4
|
+
import { valueOf } from "../core/lock.js";
|
|
5
|
+
/**
|
|
6
|
+
* The card an act is made on: the place's standing as bound folds it, with the reads it kept set aside, and the keys this
|
|
7
|
+
* device acts with. Anything landed, a grant withdrawn or a key admitted or changed moves it; a read never does. A folder
|
|
8
|
+
* that holds no place yet has the card of nothing.
|
|
9
|
+
*/
|
|
10
|
+
export const cardAt = async (context, place) => {
|
|
11
|
+
const held = place === undefined || !context.files.has(place, LOCK) ? { lines: [] } : await standingOr(context, place);
|
|
12
|
+
if ('said' in held)
|
|
13
|
+
return held;
|
|
14
|
+
const read = `${valueOf(context.lock, 'receipt/at')}:`, keys = ['head', 'person'].map((role) => context.device(role) ?? '');
|
|
15
|
+
return { card: createHash('sha256').update([baseOf(held.lines.filter((l) => !l.at?.startsWith(read))), ...keys].join('\n')).digest('hex').slice(0, 16) };
|
|
16
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Answer } from '../core/answer.ts';
|
|
2
|
+
/**
|
|
3
|
+
* What a person does, carried out by the action it names and only on the card it was asked on: an act on a place that
|
|
4
|
+
* moved since is refused before anything is done. An action the place does not allow is said not to be in the card, by
|
|
5
|
+
* bound's own refusals, and by head's words for its own checks only until bound folds the card. The answer ends with the
|
|
6
|
+
* card valid from this act: the same one where nothing but a read's receipts landed, folded again where more did.
|
|
7
|
+
*/
|
|
8
|
+
export declare const done: Answer;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { answerOf, placeOf } from "../core/answer.js";
|
|
2
|
+
import { members, valueOf } from "../core/lock.js";
|
|
3
|
+
import { sayIn } from "../core/surface.js";
|
|
4
|
+
import { cardAt } from "./card.js";
|
|
5
|
+
/**
|
|
6
|
+
* What a person does, carried out by the action it names and only on the card it was asked on: an act on a place that
|
|
7
|
+
* moved since is refused before anything is done. An action the place does not allow is said not to be in the card, by
|
|
8
|
+
* bound's own refusals, and by head's words for its own checks only until bound folds the card. The answer ends with the
|
|
9
|
+
* card valid from this act: the same one where nothing but a read's receipts landed, folded again where more did.
|
|
10
|
+
*/
|
|
11
|
+
export const done = async (asked, context) => {
|
|
12
|
+
const [say, word] = [sayIn(context.lock), (scope) => valueOf(context.lock, scope)];
|
|
13
|
+
const action = asked['action'] ?? '';
|
|
14
|
+
if (!members(word('do/actions')).includes(action))
|
|
15
|
+
return [say('unknown-action', { action, actions: word('do/actions') })];
|
|
16
|
+
const place = asked['place'] || asked['dir'] || await placeOf(asked, context), held = await cardAt(context, place);
|
|
17
|
+
if ('said' in held)
|
|
18
|
+
return held.said;
|
|
19
|
+
if (held.card !== asked['card'])
|
|
20
|
+
return [say('card-stale', { action, place: place ?? '', card: asked['card'] ?? '' })];
|
|
21
|
+
const answer = await (await answerOf('tools', action))(asked, context);
|
|
22
|
+
const [bound, own] = [members(word('do/not-in-card/bound')), members(word('do/not-in-card/head'))];
|
|
23
|
+
const refusal = (line) => ((r) => (r && [r[1], ...r[2].split(' ')].some((w) => bound.includes(w)) ? r[0] : undefined))(/REFUSE·([\w-]+)([^"]*)/.exec(line));
|
|
24
|
+
const check = (line) => ((c) => ((code) => (code && own.includes(code) ? `head/${code}` : undefined))(c?.[1] ?? c?.[2]))(/^said\/head\/([\w-]+) |head="head\/([\w-]+)"/.exec(line));
|
|
25
|
+
const why = answer.map((line) => refusal(line) ?? check(line)).find(Boolean);
|
|
26
|
+
const after = place === undefined || !context.moved(place) ? held : await cardAt(context, place);
|
|
27
|
+
return [...(why === undefined ? [] : [say('not-in-card', { action, place: place ?? '', why })]), ...answer, ...(place === undefined || 'said' in after ? [] : [say('card', { place, card: after.card, from: `do ${action}` })])];
|
|
28
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lapxo/head",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "An MCP server that folds: it runs bound as a process, hands a model what bound printed, and lands what it read as receipts.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,15 +22,16 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "tsc -p . --incremental false --tsBuildInfoFile null",
|
|
25
|
-
"prepack": "npm run build",
|
|
26
|
-
"test": "node --test test/*.test.ts"
|
|
25
|
+
"prepack": "npm run build && node --test test/pack.test.ts",
|
|
26
|
+
"test": "node --test test/*.test.ts && node --test --test-concurrency=1 test/time/*.test.ts"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@lapxo/bound": "0.1
|
|
30
|
-
"@lapxo/topos": "0.
|
|
29
|
+
"@lapxo/bound": "0.2.1",
|
|
30
|
+
"@lapxo/topos": "0.2.0",
|
|
31
31
|
"@modelcontextprotocol/sdk": "1.32.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
+
"@anthropic-ai/mcpb": "2.1.2",
|
|
34
35
|
"@types/node": "22.20.5",
|
|
35
36
|
"typescript": "5.9.3"
|
|
36
37
|
}
|
|
File without changes
|
|
File without changes
|