@astrosheep/square 0.3.77 → 0.3.79
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/dist/attention-presentation.d.ts +3 -1
- package/dist/attention-presentation.js +45 -13
- package/dist/automatic-session.js +1 -1
- package/dist/boundary-presentation.js +4 -6
- package/dist/claude-mod.js +1 -1
- package/dist/cli/catch-presentation.d.ts +2 -2
- package/dist/cli/catch-presentation.js +3 -3
- package/dist/cli/context.d.ts +11 -1
- package/dist/cli/context.js +14 -3
- package/dist/cli/express-presentation.d.ts +6 -5
- package/dist/cli/express-presentation.js +35 -30
- package/dist/cli/maintenance-commands.js +8 -8
- package/dist/cli/mcp-server-command.js +1 -1
- package/dist/cli/observation-commands.d.ts +4 -4
- package/dist/cli/observation-commands.js +20 -16
- package/dist/cli/program.d.ts +1 -1
- package/dist/cli/program.js +13 -7
- package/dist/cli/square-commands.js +35 -23
- package/dist/decisions.d.ts +9 -4
- package/dist/decisions.js +17 -8
- package/dist/delivery.d.ts +1 -1
- package/dist/help.js +15 -2
- package/dist/host-ledger-migration.js +2 -6
- package/dist/host-ledger-sqlite.js +2 -2
- package/dist/inbox.js +3 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/ledger-maintenance.d.ts +1 -1
- package/dist/ledger-maintenance.js +1 -1
- package/dist/list.d.ts +3 -3
- package/dist/list.js +1 -1
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +12 -7
- package/dist/mention-parse.d.ts +2 -8
- package/dist/mention-parse.js +6 -9
- package/dist/model.d.ts +5 -1
- package/dist/notifications.js +24 -8
- package/dist/participant-host.js +5 -0
- package/dist/plugins/opencode/index.js +1 -1
- package/dist/square-actions.d.ts +22 -9
- package/dist/square-actions.js +27 -19
- package/dist/square-api.d.ts +43 -0
- package/dist/square-api.js +471 -0
- package/dist/square-facade.d.ts +124 -203
- package/dist/square-sqlite.d.ts +2 -8
- package/dist/square-sqlite.js +3 -11
- package/dist/square-tools.d.ts +4 -3
- package/dist/square-tools.js +22 -16
- package/dist/stream.d.ts +2 -2
- package/dist/views.d.ts +16 -12
- package/dist/views.js +13 -27
- package/guides/application-demand-optimization.md +5 -0
- package/guides/application-facade-delivery-evidence.md +6 -1
- package/guides/claude-native.md +3 -1
- package/guides/mcp-connection-lifetime.md +2 -2
- package/guides/mcp.md +1 -1
- package/guides/migration.md +2 -1
- package/guides/operation-cancellation.md +2 -0
- package/guides/primitive-catch-consolidation.md +5 -0
- package/guides/primitive-history-consolidation.md +5 -0
- package/guides/primitive-status-consolidation.md +5 -0
- package/guides/primitive-storage-consolidation.md +5 -0
- package/guides/row-storage-design.md +2 -2
- package/guides/square-api.md +107 -0
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/square/SKILL.md +3 -3
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/index.ts +1 -1
- package/plugins/paseo/client/markdown.tsx +16 -6
- package/plugins/pi/square-pi.js +70 -30
- package/skills/square/SKILL.md +3 -3
- package/dist/square-application.d.ts +0 -38
- package/dist/square-application.js +0 -683
- package/guides/application-boundary.md +0 -32
- package/guides/application-facade-design.md +0 -98
package/plugins/pi/square-pi.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { Text } from '@earendil-works/pi-tui';
|
|
2
|
+
import { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Square } from '../../dist/square-api.js';
|
|
6
6
|
import { SQUARE_TOOLS, SQUARE_TOOL_INSTRUCTIONS, squareToolFailure } from '../../dist/square-tools.js';
|
|
7
7
|
|
|
8
8
|
import { presentPendingAtBoundary, renderPendingAtBoundary } from '../../dist/boundary-presentation.js';
|
|
9
9
|
import { automaticSessionEnd, automaticSessionStart, operationEnv } from '../../dist/automatic-session.js';
|
|
10
10
|
import { sessionInbox, observeSessionPending } from '../../dist/inbox.js';
|
|
11
11
|
import { previewAttentionBody, renderAttentionDescription, renderAttentionFull } from '../../dist/attention-presentation.js';
|
|
12
|
+
import { formatActivityId } from '../../dist/square-core.js';
|
|
12
13
|
import { createPiReceiver, sendPiMessage } from '../../dist/packages/agent-delivery/src/pi.js';
|
|
13
14
|
|
|
14
15
|
class PiDeliveryDroppedError extends Error {
|
|
@@ -36,15 +37,17 @@ function framePiMessage(content) {
|
|
|
36
37
|
return `\n${content.replace(/^\n+/, '').replace(/\n+$/, '')}\n`;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
/** Renderer-only
|
|
40
|
+
/** Renderer-only card facts for Pi and Paseo; Pi never sends `details` to the model. */
|
|
40
41
|
export function pendingCardDetails(pending) {
|
|
41
42
|
const items = pending.flatMap((membership) => membership.notifications.map((note) => ({
|
|
42
43
|
square: path.basename(membership.squarePath, '.square'),
|
|
43
44
|
actor: note.actor,
|
|
44
45
|
recipient: membership.name,
|
|
45
46
|
route: note.route,
|
|
47
|
+
act: formatActivityId(note.actIndex),
|
|
46
48
|
preview: previewAttentionBody(note.body),
|
|
47
|
-
description: renderAttentionDescription({ actor: note.actor,
|
|
49
|
+
description: renderAttentionDescription({ actor: note.actor, route: note.route }),
|
|
50
|
+
body: note.body,
|
|
48
51
|
})));
|
|
49
52
|
if (items.length === 0) return undefined;
|
|
50
53
|
const fullText = pending.flatMap((membership) => membership.notifications.map((note) => renderAttentionFull({
|
|
@@ -73,31 +76,67 @@ function fitColumns(text, columns) {
|
|
|
73
76
|
return `${out}…`;
|
|
74
77
|
}
|
|
75
78
|
|
|
79
|
+
const fg = (theme, color, text) => theme.fg?.(color, text) ?? text;
|
|
80
|
+
const style = (theme, name) => (text) => theme[name]?.(text) ?? text;
|
|
81
|
+
|
|
82
|
+
function markdownTheme(theme) {
|
|
83
|
+
const color = (name) => (text) => fg(theme, name, text);
|
|
84
|
+
return {
|
|
85
|
+
heading: color('mdHeading'), link: color('mdLink'), linkUrl: color('mdLinkUrl'), code: color('mdCode'),
|
|
86
|
+
codeBlock: color('mdCodeBlock'), codeBlockBorder: color('mdCodeBlockBorder'), quote: color('mdQuote'),
|
|
87
|
+
quoteBorder: color('mdQuoteBorder'), hr: color('mdHr'), listBullet: color('mdListBullet'),
|
|
88
|
+
bold: style(theme, 'bold'), italic: style(theme, 'italic'), underline: style(theme, 'underline'),
|
|
89
|
+
strikethrough: style(theme, 'strikethrough'),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** One styled line that never exceeds the width; truncated lines stay unstyled so escapes are never cut. */
|
|
94
|
+
function fitLine(parts, width) {
|
|
95
|
+
const plain = parts.map(([text]) => text).join('');
|
|
96
|
+
return widthOf(plain) <= width ? parts.map(([text, paint]) => paint(text)).join('') : fitColumns(plain, width);
|
|
97
|
+
}
|
|
98
|
+
|
|
76
99
|
/**
|
|
77
|
-
* Collapsed:
|
|
78
|
-
*
|
|
100
|
+
* Collapsed: who reached you and where, then the first line of what they said.
|
|
101
|
+
* Expanded: each activity as a heading line and its Markdown body; the model's
|
|
102
|
+
* framing and continuation hints are not for human eyes.
|
|
79
103
|
*/
|
|
80
104
|
export function renderSquareCard(message, { expanded, outputPad = 1 }, theme) {
|
|
81
|
-
if (expanded) {
|
|
82
|
-
return typeof message.details?.fullText === 'string'
|
|
83
|
-
? new Text(message.details.fullText, outputPad, 0)
|
|
84
|
-
: undefined;
|
|
85
|
-
}
|
|
86
105
|
const items = message.details?.items;
|
|
87
|
-
if (!Array.isArray(items) || items.length === 0) return undefined;
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
if (!Array.isArray(items) || items.length === 0 || items.some((item) => typeof item.body !== 'string')) return undefined;
|
|
107
|
+
const pad = ' '.repeat(outputPad);
|
|
108
|
+
const dim = (text) => fg(theme, 'dim', text);
|
|
109
|
+
if (!expanded) {
|
|
110
|
+
const [first] = items;
|
|
111
|
+
const more = items.length > 1 ? ` +${items.length - 1}` : '';
|
|
112
|
+
// A glance, not a render: drop the commonest inline markers so the line reads as speech.
|
|
113
|
+
const opening = (first.body.split('\n').find((line) => line.trim() !== '') ?? '')
|
|
114
|
+
.trim().replace(/^(#{1,6}|>|[-*+])\s+/, '').replace(/\*\*|__|`/g, '');
|
|
115
|
+
return {
|
|
116
|
+
invalidate() {},
|
|
117
|
+
render(width) {
|
|
118
|
+
const room = Math.max(1, width - outputPad * 2 - 2);
|
|
119
|
+
return [
|
|
120
|
+
`${pad}${fg(theme, 'customMessageLabel', '■')} ${fitLine([[first.description, (t) => t], [` · ${first.square} · ${first.recipient}${more}`, dim]], room)}`,
|
|
121
|
+
...(opening ? [`${pad} ${fitLine([[opening, dim]], room)}`] : []),
|
|
122
|
+
];
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const card = new Container();
|
|
127
|
+
for (const [index, item] of items.entries()) {
|
|
128
|
+
if (index > 0) card.addChild(new Spacer(1));
|
|
129
|
+
card.addChild({
|
|
130
|
+
invalidate() {},
|
|
131
|
+
render(width) {
|
|
132
|
+
const room = Math.max(1, width - outputPad * 2 - 2);
|
|
133
|
+
return [`${pad}${fg(theme, 'customMessageLabel', '●')} ${fitLine([[item.description, (t) => t], [` ${item.square} · ${item.recipient} · ${item.act}`, dim]], room)}`];
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
card.addChild(new Spacer(1));
|
|
137
|
+
card.addChild(new Markdown(item.body, outputPad + 2, 0, markdownTheme(theme)));
|
|
138
|
+
}
|
|
139
|
+
return card;
|
|
101
140
|
}
|
|
102
141
|
|
|
103
142
|
export default function squarePiExtension(pi) {
|
|
@@ -112,14 +151,15 @@ export default function squarePiExtension(pi) {
|
|
|
112
151
|
namespace: { name: 'square', description: 'Participate in a shared public square.', instructions: SQUARE_TOOL_INSTRUCTIONS },
|
|
113
152
|
async execute(_id, args, signal, _onUpdate, ctx) {
|
|
114
153
|
try {
|
|
115
|
-
const
|
|
154
|
+
const square = await Square.at({
|
|
116
155
|
cwd: ctx.cwd,
|
|
117
156
|
env: operationEnv('pi', ctx.sessionManager.getSessionId(), process.env),
|
|
118
|
-
|
|
157
|
+
path: args.location,
|
|
119
158
|
participant: args.as,
|
|
120
|
-
}, {
|
|
121
|
-
|
|
122
|
-
|
|
159
|
+
}, { signal });
|
|
160
|
+
let data;
|
|
161
|
+
try { data = await tool.run(square, args, { signal }); }
|
|
162
|
+
finally { await square.close(); }
|
|
123
163
|
return { content: [{ type: 'text', text: JSON.stringify(data) }], details: data, structuredContent: data };
|
|
124
164
|
} catch (error) {
|
|
125
165
|
const data = { error: squareToolFailure(error, signal) };
|
package/skills/square/SKILL.md
CHANGED
|
@@ -37,9 +37,9 @@ I disagree — the cache is the wrong layer for this.
|
|
|
37
37
|
|
|
38
38
|
**Reach.** Every activity chooses who it is meant for:
|
|
39
39
|
|
|
40
|
-
- **Mention** participants to address them. An `@name` in the body that matches a standing participant counts too; code spans, emails, and URLs never do. Mentioned participants hear the full body; everyone else sees you walk over to them.
|
|
41
|
-
- **Reply** to an activity to reach its author the
|
|
42
|
-
- **Ring the bell** only when every participant needs it.
|
|
40
|
+
- **Mention** participants to address them. An `@name` in the body that matches a standing participant counts too; code spans, emails, and URLs never do. Unmatched names stay literal, with a notice to you. Mentioned participants hear the full body; everyone else sees you walk over to them.
|
|
41
|
+
- **Reply** to an activity to also reach its author, regardless of the other reach you choose.
|
|
42
|
+
- **Ring the bell** only when every participant needs it. Body `@names` stay literal; explicit mentions cannot combine with a bell.
|
|
43
43
|
- **Land it bare** when it is meant for no one in particular. Only participants listening to you receive it.
|
|
44
44
|
|
|
45
45
|
Addressing is not a secrecy boundary. Everything stays readable through `history`.
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { Activity, ExpressResult, HistoryQuery, OperationControl, Participant, ParticipantStatus, SquareApplication, SquareApplicationContext, SquareAtInput, SquareBuildInput, SquareSnapshot } from './square-facade.js';
|
|
2
|
-
export type * from './square-facade.js';
|
|
3
|
-
export { createSquareResourceOwner } from './open-square.js';
|
|
4
|
-
export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE } from './square-core.js';
|
|
5
|
-
export { CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT } from './catch-decisions.js';
|
|
6
|
-
export { HELD_WAIT_BUDGET_MS } from './runtime.js';
|
|
7
|
-
export { HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
|
|
8
|
-
export { DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from './list.js';
|
|
9
|
-
/** Supported SDK resource. It owns one open artifact; application operations use
|
|
10
|
-
* the same owner functions directly, not an application -> SDK -> application chain. */
|
|
11
|
-
export declare class Square {
|
|
12
|
-
readonly location: string;
|
|
13
|
-
private readonly square;
|
|
14
|
-
private readonly transport;
|
|
15
|
-
private constructor();
|
|
16
|
-
static at(input: SquareAtInput, control?: OperationControl): Promise<Square>;
|
|
17
|
-
static build(input: SquareBuildInput): Promise<Square>;
|
|
18
|
-
static inMemory(input: Omit<SquareBuildInput, 'path'>): Square;
|
|
19
|
-
private handle;
|
|
20
|
-
join(name: string, control?: OperationControl): Promise<Participant>;
|
|
21
|
-
takeover(name: string, control?: OperationControl): Promise<Participant>;
|
|
22
|
-
doneOwnedSession(name: string, body: string, expectedEpoch: number, control?: OperationControl): Promise<ExpressResult>;
|
|
23
|
-
implicitJoin(name: string, control?: OperationControl): Promise<{
|
|
24
|
-
readonly state: 'joined' | 'active' | 'done';
|
|
25
|
-
readonly participant?: Participant;
|
|
26
|
-
}>;
|
|
27
|
-
participants(): Promise<ParticipantStatus[]>;
|
|
28
|
-
snapshot(control?: OperationControl): Promise<SquareSnapshot>;
|
|
29
|
-
history(query?: HistoryQuery, control?: OperationControl): Promise<Activity[]>;
|
|
30
|
-
recognize(env: NodeJS.ProcessEnv): Promise<Participant | null>;
|
|
31
|
-
close(): Promise<void>;
|
|
32
|
-
endOwnedSession(name: string, sessionId: string, expectedEpoch?: number): Promise<ExpressResult | null>;
|
|
33
|
-
retireEndedSessionRoutes(sessionId: string): Promise<void>;
|
|
34
|
-
}
|
|
35
|
-
export declare function createSquareApplication(context: SquareApplicationContext): SquareApplication;
|
|
36
|
-
export declare function createSquareApplication(context: SquareApplicationContext, demand: {
|
|
37
|
-
readonly presentation: false;
|
|
38
|
-
}): SquareApplication<false>;
|