@pinet/slack-bridge 0.1.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.
- package/LICENSE +21 -0
- package/README.md +570 -0
- package/dist/activity-log.d.ts +62 -0
- package/dist/activity-log.js +293 -0
- package/dist/agent-completion-runtime.d.ts +17 -0
- package/dist/agent-completion-runtime.js +26 -0
- package/dist/agent-event-runtime.d.ts +13 -0
- package/dist/agent-event-runtime.js +27 -0
- package/dist/agent-prompt-guidance.d.ts +22 -0
- package/dist/agent-prompt-guidance.js +46 -0
- package/dist/broker/adapters/slack.d.ts +74 -0
- package/dist/broker/adapters/slack.js +563 -0
- package/dist/broker/adapters/types.d.ts +1 -0
- package/dist/broker/adapters/types.js +1 -0
- package/dist/broker/agent-messaging.d.ts +1 -0
- package/dist/broker/agent-messaging.js +1 -0
- package/dist/broker/auth.d.ts +1 -0
- package/dist/broker/auth.js +1 -0
- package/dist/broker/client.d.ts +167 -0
- package/dist/broker/client.js +624 -0
- package/dist/broker/control-plane-dashboard.d.ts +98 -0
- package/dist/broker/control-plane-dashboard.js +213 -0
- package/dist/broker/ghost-reaper.d.ts +49 -0
- package/dist/broker/ghost-reaper.js +209 -0
- package/dist/broker/index.d.ts +36 -0
- package/dist/broker/index.js +90 -0
- package/dist/broker/leader.d.ts +1 -0
- package/dist/broker/leader.js +1 -0
- package/dist/broker/maintenance.d.ts +1 -0
- package/dist/broker/maintenance.js +1 -0
- package/dist/broker/message-send.d.ts +1 -0
- package/dist/broker/message-send.js +1 -0
- package/dist/broker/paths.d.ts +1 -0
- package/dist/broker/paths.js +1 -0
- package/dist/broker/raw-tcp-loopback.d.ts +1 -0
- package/dist/broker/raw-tcp-loopback.js +1 -0
- package/dist/broker/router.d.ts +1 -0
- package/dist/broker/router.js +1 -0
- package/dist/broker/schema.d.ts +9 -0
- package/dist/broker/schema.js +63 -0
- package/dist/broker/socket-server.d.ts +120 -0
- package/dist/broker/socket-server.js +1087 -0
- package/dist/broker/types.d.ts +1 -0
- package/dist/broker/types.js +1 -0
- package/dist/broker-delivery.d.ts +10 -0
- package/dist/broker-delivery.js +26 -0
- package/dist/broker-inbound-persistence.d.ts +11 -0
- package/dist/broker-inbound-persistence.js +22 -0
- package/dist/broker-prompt-loader.d.ts +34 -0
- package/dist/broker-prompt-loader.js +185 -0
- package/dist/broker-runtime-access.d.ts +14 -0
- package/dist/broker-runtime-access.js +20 -0
- package/dist/broker-runtime.d.ts +100 -0
- package/dist/broker-runtime.js +533 -0
- package/dist/broker-thread-owner-hints.d.ts +10 -0
- package/dist/broker-thread-owner-hints.js +14 -0
- package/dist/canvases.d.ts +80 -0
- package/dist/canvases.js +221 -0
- package/dist/command-registration-runtime.d.ts +9 -0
- package/dist/command-registration-runtime.js +9 -0
- package/dist/core-tool-guardrails.d.ts +24 -0
- package/dist/core-tool-guardrails.js +66 -0
- package/dist/deploy-manifest.d.ts +27 -0
- package/dist/deploy-manifest.js +197 -0
- package/dist/follower-delivery.d.ts +16 -0
- package/dist/follower-delivery.js +70 -0
- package/dist/follower-runtime.d.ts +61 -0
- package/dist/follower-runtime.js +350 -0
- package/dist/git-metadata.d.ts +35 -0
- package/dist/git-metadata.js +88 -0
- package/dist/guardrails.d.ts +69 -0
- package/dist/guardrails.js +283 -0
- package/dist/helpers.d.ts +550 -0
- package/dist/helpers.js +2711 -0
- package/dist/home-tab.d.ts +27 -0
- package/dist/home-tab.js +242 -0
- package/dist/imessage-tools.d.ts +33 -0
- package/dist/imessage-tools.js +96 -0
- package/dist/inbox-drain-runtime.d.ts +30 -0
- package/dist/inbox-drain-runtime.js +71 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1330 -0
- package/dist/persisted-runtime-state.d.ts +52 -0
- package/dist/persisted-runtime-state.js +98 -0
- package/dist/pinet-activity-formatting.d.ts +20 -0
- package/dist/pinet-activity-formatting.js +43 -0
- package/dist/pinet-agent-status.d.ts +36 -0
- package/dist/pinet-agent-status.js +48 -0
- package/dist/pinet-commands.d.ts +70 -0
- package/dist/pinet-commands.js +402 -0
- package/dist/pinet-confirmation-replies.d.ts +7 -0
- package/dist/pinet-confirmation-replies.js +30 -0
- package/dist/pinet-control-plane-dashboard.d.ts +34 -0
- package/dist/pinet-control-plane-dashboard.js +86 -0
- package/dist/pinet-home-tabs.d.ts +36 -0
- package/dist/pinet-home-tabs.js +101 -0
- package/dist/pinet-maintenance-delivery.d.ts +22 -0
- package/dist/pinet-maintenance-delivery.js +45 -0
- package/dist/pinet-mesh-ops.d.ts +97 -0
- package/dist/pinet-mesh-ops.js +266 -0
- package/dist/pinet-registration-gate.d.ts +14 -0
- package/dist/pinet-registration-gate.js +42 -0
- package/dist/pinet-remote-control-acks.d.ts +16 -0
- package/dist/pinet-remote-control-acks.js +46 -0
- package/dist/pinet-remote-control.d.ts +17 -0
- package/dist/pinet-remote-control.js +74 -0
- package/dist/pinet-runtime-composition.d.ts +27 -0
- package/dist/pinet-runtime-composition.js +20 -0
- package/dist/pinet-tools.d.ts +67 -0
- package/dist/pinet-tools.js +1211 -0
- package/dist/prompts/broker/default.md +41 -0
- package/dist/prompts/broker/tmux.md +49 -0
- package/dist/ralph-loop.d.ts +76 -0
- package/dist/ralph-loop.js +524 -0
- package/dist/reaction-triggers.d.ts +25 -0
- package/dist/reaction-triggers.js +171 -0
- package/dist/repo-tool-guardrails.d.ts +20 -0
- package/dist/repo-tool-guardrails.js +81 -0
- package/dist/runtime-agent-context.d.ts +93 -0
- package/dist/runtime-agent-context.js +302 -0
- package/dist/runtime-mode.d.ts +10 -0
- package/dist/runtime-mode.js +39 -0
- package/dist/scheduled-wakeups.d.ts +1 -0
- package/dist/scheduled-wakeups.js +1 -0
- package/dist/session-ui-runtime.d.ts +20 -0
- package/dist/session-ui-runtime.js +163 -0
- package/dist/single-player-runtime.d.ts +71 -0
- package/dist/single-player-runtime.js +436 -0
- package/dist/skins/cosmere.json +1571 -0
- package/dist/skins/foundation.json +1304 -0
- package/dist/slack-access.d.ts +186 -0
- package/dist/slack-access.js +462 -0
- package/dist/slack-api.d.ts +2 -0
- package/dist/slack-api.js +1 -0
- package/dist/slack-block-kit.d.ts +36 -0
- package/dist/slack-block-kit.js +242 -0
- package/dist/slack-export.d.ts +31 -0
- package/dist/slack-export.js +206 -0
- package/dist/slack-message-context.d.ts +15 -0
- package/dist/slack-message-context.js +207 -0
- package/dist/slack-modals.d.ts +13 -0
- package/dist/slack-modals.js +79 -0
- package/dist/slack-pinet-runtime-adapter.d.ts +16 -0
- package/dist/slack-pinet-runtime-adapter.js +72 -0
- package/dist/slack-presence.d.ts +36 -0
- package/dist/slack-presence.js +89 -0
- package/dist/slack-request-runtime.d.ts +8 -0
- package/dist/slack-request-runtime.js +19 -0
- package/dist/slack-runtime-access.d.ts +28 -0
- package/dist/slack-runtime-access.js +107 -0
- package/dist/slack-scope-diagnostics.d.ts +31 -0
- package/dist/slack-scope-diagnostics.js +235 -0
- package/dist/slack-socket-dedup.d.ts +7 -0
- package/dist/slack-socket-dedup.js +135 -0
- package/dist/slack-thread-status.d.ts +41 -0
- package/dist/slack-thread-status.js +156 -0
- package/dist/slack-tool-policy-runtime.d.ts +36 -0
- package/dist/slack-tool-policy-runtime.js +96 -0
- package/dist/slack-tools.d.ts +52 -0
- package/dist/slack-tools.js +2688 -0
- package/dist/slack-turn-guardrails.d.ts +19 -0
- package/dist/slack-turn-guardrails.js +36 -0
- package/dist/slack-upload.d.ts +49 -0
- package/dist/slack-upload.js +224 -0
- package/dist/task-assignments.d.ts +45 -0
- package/dist/task-assignments.js +527 -0
- package/dist/thread-confirmations.d.ts +22 -0
- package/dist/thread-confirmations.js +139 -0
- package/dist/tool-registration-runtime.d.ts +13 -0
- package/dist/tool-registration-runtime.js +13 -0
- package/dist/ttl-cache.d.ts +47 -0
- package/dist/ttl-cache.js +105 -0
- package/manifest.yaml +57 -0
- package/package.json +60 -0
- package/skills/pinet-skin-creator/SKILL.md +109 -0
- package/skills/pinet-skin-creator/references/descriptor-format.md +99 -0
- package/skills/pinet-skin-creator/references/safety-checklist.md +56 -0
- package/skills/pinet-skin-creator/templates/pinet-skin-descriptor.json +77 -0
- package/skills/slack-bridge/SKILL.md +360 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type RegisterIMessageToolsDeps } from "./imessage-tools.js";
|
|
3
|
+
import { type RegisterPinetToolsDeps } from "./pinet-tools.js";
|
|
4
|
+
import { type RegisterSlackToolsDeps } from "./slack-tools.js";
|
|
5
|
+
export interface ToolRegistrationRuntimeDeps {
|
|
6
|
+
slackTools: RegisterSlackToolsDeps;
|
|
7
|
+
pinetTools: RegisterPinetToolsDeps;
|
|
8
|
+
iMessageTools: RegisterIMessageToolsDeps;
|
|
9
|
+
}
|
|
10
|
+
export interface ToolRegistrationRuntime {
|
|
11
|
+
register: (pi: ExtensionAPI) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createToolRegistrationRuntime(deps: ToolRegistrationRuntimeDeps): ToolRegistrationRuntime;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { registerIMessageTools } from "./imessage-tools.js";
|
|
2
|
+
import { registerPinetTools } from "./pinet-tools.js";
|
|
3
|
+
import { registerSlackTools } from "./slack-tools.js";
|
|
4
|
+
export function createToolRegistrationRuntime(deps) {
|
|
5
|
+
function register(pi) {
|
|
6
|
+
registerSlackTools(pi, deps.slackTools);
|
|
7
|
+
registerPinetTools(pi, deps.pinetTools);
|
|
8
|
+
registerIMessageTools(pi, deps.iMessageTools);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
register,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight TTL + max-size cache.
|
|
3
|
+
*
|
|
4
|
+
* Entries expire after `ttlMs` milliseconds and are lazily evicted on
|
|
5
|
+
* access. When the cache exceeds `maxSize`, the oldest entry (by
|
|
6
|
+
* insertion / last-update order) is dropped — Map iteration order
|
|
7
|
+
* guarantees FIFO.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TtlCache<K, V> {
|
|
10
|
+
private readonly map;
|
|
11
|
+
private readonly maxSize;
|
|
12
|
+
private readonly ttlMs;
|
|
13
|
+
private readonly now;
|
|
14
|
+
constructor(options: {
|
|
15
|
+
maxSize: number;
|
|
16
|
+
ttlMs: number;
|
|
17
|
+
now?: () => number;
|
|
18
|
+
});
|
|
19
|
+
get(key: K): V | undefined;
|
|
20
|
+
set(key: K, value: V): this;
|
|
21
|
+
has(key: K): boolean;
|
|
22
|
+
delete(key: K): boolean;
|
|
23
|
+
get size(): number;
|
|
24
|
+
/** Iterate live (non-expired) entries. */
|
|
25
|
+
entries(): IterableIterator<[K, V]>;
|
|
26
|
+
/** Sweep all expired entries in one pass. */
|
|
27
|
+
sweep(): number;
|
|
28
|
+
clear(): void;
|
|
29
|
+
private evictOverflow;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* TTL + max-size Set — thin wrapper around TtlCache<V, true>.
|
|
33
|
+
*/
|
|
34
|
+
export declare class TtlSet<V> {
|
|
35
|
+
private readonly cache;
|
|
36
|
+
constructor(options: {
|
|
37
|
+
maxSize: number;
|
|
38
|
+
ttlMs: number;
|
|
39
|
+
now?: () => number;
|
|
40
|
+
});
|
|
41
|
+
add(value: V): this;
|
|
42
|
+
has(value: V): boolean;
|
|
43
|
+
delete(value: V): boolean;
|
|
44
|
+
get size(): number;
|
|
45
|
+
sweep(): number;
|
|
46
|
+
clear(): void;
|
|
47
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight TTL + max-size cache.
|
|
3
|
+
*
|
|
4
|
+
* Entries expire after `ttlMs` milliseconds and are lazily evicted on
|
|
5
|
+
* access. When the cache exceeds `maxSize`, the oldest entry (by
|
|
6
|
+
* insertion / last-update order) is dropped — Map iteration order
|
|
7
|
+
* guarantees FIFO.
|
|
8
|
+
*/
|
|
9
|
+
export class TtlCache {
|
|
10
|
+
map = new Map();
|
|
11
|
+
maxSize;
|
|
12
|
+
ttlMs;
|
|
13
|
+
now;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.maxSize = options.maxSize;
|
|
16
|
+
this.ttlMs = options.ttlMs;
|
|
17
|
+
this.now = options.now ?? (() => Date.now());
|
|
18
|
+
}
|
|
19
|
+
get(key) {
|
|
20
|
+
const entry = this.map.get(key);
|
|
21
|
+
if (!entry)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (this.now() - entry.touchedAt > this.ttlMs) {
|
|
24
|
+
this.map.delete(key);
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
return entry.value;
|
|
28
|
+
}
|
|
29
|
+
set(key, value) {
|
|
30
|
+
// Delete first so re-insertion moves the key to the end (Map ordering).
|
|
31
|
+
this.map.delete(key);
|
|
32
|
+
this.map.set(key, { value, touchedAt: this.now() });
|
|
33
|
+
this.evictOverflow();
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
has(key) {
|
|
37
|
+
return this.get(key) !== undefined;
|
|
38
|
+
}
|
|
39
|
+
delete(key) {
|
|
40
|
+
return this.map.delete(key);
|
|
41
|
+
}
|
|
42
|
+
get size() {
|
|
43
|
+
return this.map.size;
|
|
44
|
+
}
|
|
45
|
+
/** Iterate live (non-expired) entries. */
|
|
46
|
+
*entries() {
|
|
47
|
+
const now = this.now();
|
|
48
|
+
for (const [key, entry] of this.map) {
|
|
49
|
+
if (now - entry.touchedAt <= this.ttlMs) {
|
|
50
|
+
yield [key, entry.value];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Sweep all expired entries in one pass. */
|
|
55
|
+
sweep() {
|
|
56
|
+
const now = this.now();
|
|
57
|
+
let swept = 0;
|
|
58
|
+
for (const [key, entry] of this.map) {
|
|
59
|
+
if (now - entry.touchedAt > this.ttlMs) {
|
|
60
|
+
this.map.delete(key);
|
|
61
|
+
swept++;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return swept;
|
|
65
|
+
}
|
|
66
|
+
clear() {
|
|
67
|
+
this.map.clear();
|
|
68
|
+
}
|
|
69
|
+
evictOverflow() {
|
|
70
|
+
while (this.map.size > this.maxSize) {
|
|
71
|
+
const oldest = this.map.keys().next();
|
|
72
|
+
if (oldest.done)
|
|
73
|
+
break;
|
|
74
|
+
this.map.delete(oldest.value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* TTL + max-size Set — thin wrapper around TtlCache<V, true>.
|
|
80
|
+
*/
|
|
81
|
+
export class TtlSet {
|
|
82
|
+
cache;
|
|
83
|
+
constructor(options) {
|
|
84
|
+
this.cache = new TtlCache(options);
|
|
85
|
+
}
|
|
86
|
+
add(value) {
|
|
87
|
+
this.cache.set(value, true);
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
has(value) {
|
|
91
|
+
return this.cache.has(value);
|
|
92
|
+
}
|
|
93
|
+
delete(value) {
|
|
94
|
+
return this.cache.delete(value);
|
|
95
|
+
}
|
|
96
|
+
get size() {
|
|
97
|
+
return this.cache.size;
|
|
98
|
+
}
|
|
99
|
+
sweep() {
|
|
100
|
+
return this.cache.sweep();
|
|
101
|
+
}
|
|
102
|
+
clear() {
|
|
103
|
+
this.cache.clear();
|
|
104
|
+
}
|
|
105
|
+
}
|
package/manifest.yaml
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
display_information:
|
|
2
|
+
name: Pinet
|
|
3
|
+
description: Hi, im Pinet (pronounce pie-net like apple-pie and basketball net)
|
|
4
|
+
background_color: "#87390c"
|
|
5
|
+
long_description: "I am a friendly one and I can wear many hats at once, ask me anything! In my free time I like to take long walks in the park and bring a picnic. My favorite food is pie of course :cake:"
|
|
6
|
+
features:
|
|
7
|
+
app_home:
|
|
8
|
+
home_tab_enabled: true
|
|
9
|
+
messages_tab_enabled: true
|
|
10
|
+
messages_tab_read_only_enabled: false
|
|
11
|
+
bot_user:
|
|
12
|
+
display_name: Pinet
|
|
13
|
+
always_online: true
|
|
14
|
+
assistant_view:
|
|
15
|
+
assistant_description: Pi coding agent
|
|
16
|
+
suggested_prompts: []
|
|
17
|
+
oauth_config:
|
|
18
|
+
scopes:
|
|
19
|
+
bot:
|
|
20
|
+
- reactions:write
|
|
21
|
+
- app_mentions:read
|
|
22
|
+
- assistant:write
|
|
23
|
+
- channels:history
|
|
24
|
+
- channels:read
|
|
25
|
+
- chat:write
|
|
26
|
+
- files:read
|
|
27
|
+
- files:write
|
|
28
|
+
- bookmarks:read
|
|
29
|
+
- bookmarks:write
|
|
30
|
+
- groups:history
|
|
31
|
+
- groups:read
|
|
32
|
+
- im:history
|
|
33
|
+
- im:read
|
|
34
|
+
- im:write
|
|
35
|
+
- users:read
|
|
36
|
+
- reactions:read
|
|
37
|
+
- canvases:read
|
|
38
|
+
- canvases:write
|
|
39
|
+
- pins:read
|
|
40
|
+
- pins:write
|
|
41
|
+
pkce_enabled: false
|
|
42
|
+
settings:
|
|
43
|
+
event_subscriptions:
|
|
44
|
+
bot_events:
|
|
45
|
+
- app_mention
|
|
46
|
+
- app_home_opened
|
|
47
|
+
- assistant_thread_started
|
|
48
|
+
- assistant_thread_context_changed
|
|
49
|
+
- reaction_added
|
|
50
|
+
- message.channels
|
|
51
|
+
- message.groups
|
|
52
|
+
- message.im
|
|
53
|
+
interactivity:
|
|
54
|
+
is_enabled: true
|
|
55
|
+
org_deploy_enabled: false
|
|
56
|
+
socket_mode_enabled: true
|
|
57
|
+
token_rotation_enabled: false
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pinet/slack-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Slack assistant integration for pi (Pinet) — multi-agent broker, thread routing, and inbox tools",
|
|
6
|
+
"author": "Will Porcellini <5994936+gugu91@users.noreply.github.com>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/gugu91/extensions.git",
|
|
11
|
+
"directory": "slack-bridge"
|
|
12
|
+
},
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": "./dist/index.js",
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"manifest.yaml",
|
|
25
|
+
"skills/",
|
|
26
|
+
"dist/"
|
|
27
|
+
],
|
|
28
|
+
"keywords": [
|
|
29
|
+
"pi-package"
|
|
30
|
+
],
|
|
31
|
+
"pi": {
|
|
32
|
+
"extensions": [
|
|
33
|
+
"./dist/index.js"
|
|
34
|
+
],
|
|
35
|
+
"skills": [
|
|
36
|
+
"./skills"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "node ../scripts/build-package.mjs",
|
|
41
|
+
"prepack": "pnpm run build",
|
|
42
|
+
"lint": "eslint . --ext .ts",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"test": "vitest run"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@pinet/broker-core": "0.1.0",
|
|
48
|
+
"@pinet/imessage-bridge": "0.1.0",
|
|
49
|
+
"@pinet/pinet-core": "0.1.0",
|
|
50
|
+
"@pinet/transport-core": "0.1.0",
|
|
51
|
+
"@sinclair/typebox": "^0.34.49"
|
|
52
|
+
},
|
|
53
|
+
"types": "./dist/index.d.ts",
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pinet-skin-creator
|
|
3
|
+
description: Guides safe creation and editing of Pinet skin descriptors, curated character/name pools, persona snippets, emoji/style, and status vocabulary. Use when designing or refining non-default Pinet skins or reviewing skin descriptor changes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pinet Skin Creator
|
|
7
|
+
|
|
8
|
+
Use this skill when asked to create, edit, or review Pinet skin descriptors or
|
|
9
|
+
curated Pinet character sets. It is intentionally a **design/build workflow**:
|
|
10
|
+
do not add model calls to broker startup or follower join paths.
|
|
11
|
+
|
|
12
|
+
## Core design rules
|
|
13
|
+
|
|
14
|
+
- **Default/classic stays random.** Preserve the existing whimsical random
|
|
15
|
+
adjective/color/animal identity generation for the default/classic skin.
|
|
16
|
+
- **Curated skins are JSON descriptors.** Non-default skins should ship external
|
|
17
|
+
JSON descriptor assets with curated/prebaked identity pools, 1–3 word authored
|
|
18
|
+
display names, static emoji, personae, emoji/style guidance, and status
|
|
19
|
+
vocabulary.
|
|
20
|
+
- **No LLM in startup/join.** Broker startup and follower join must remain
|
|
21
|
+
deterministic, fast, offline-tolerant, and usable without model availability.
|
|
22
|
+
- **Persist concrete assignments.** If a future `auto` mode chooses a skin or
|
|
23
|
+
character after runtime is live, persist the resolved concrete assignment and
|
|
24
|
+
keep a deterministic fallback.
|
|
25
|
+
- **Presentation only.** Skins may shape names, emoji, tone, persona snippets,
|
|
26
|
+
and status display vocabulary. They must not change tool permissions,
|
|
27
|
+
broker/follower roles, task ownership, guardrails, or routing authority.
|
|
28
|
+
|
|
29
|
+
## Workflow
|
|
30
|
+
|
|
31
|
+
1. **Clarify the target**
|
|
32
|
+
- Skin key and aliases.
|
|
33
|
+
- Intended theme, tone, and setting.
|
|
34
|
+
- Supported roles: broker, worker/follower, reviewer, PM/coordinator, or
|
|
35
|
+
future role labels.
|
|
36
|
+
- Whether the task is creating a new skin or editing an existing one.
|
|
37
|
+
|
|
38
|
+
2. **Draft the descriptor**
|
|
39
|
+
- Start from `templates/pinet-skin-descriptor.json`.
|
|
40
|
+
- Follow `references/descriptor-format.md` for fields and constraints.
|
|
41
|
+
- Prefer rich curated/prebaked identity lists over random display-name
|
|
42
|
+
combinators, tiny hardcoded TypeScript lists, one-off generated names, or
|
|
43
|
+
obvious formulaic triples.
|
|
44
|
+
|
|
45
|
+
3. **Create role-specific characters**
|
|
46
|
+
- For major themed skins, aim for 100–200 authored display identities.
|
|
47
|
+
- Display names can be 1, 2, or 3 words when they are distinctive and
|
|
48
|
+
flavorful.
|
|
49
|
+
- Include several broker/coordinator-appropriate identities and many
|
|
50
|
+
worker/reviewer-friendly identities.
|
|
51
|
+
- Keep display names distinctive in text alone; static emoji should add flavor,
|
|
52
|
+
not disambiguate identities.
|
|
53
|
+
- Use a broad emoji palette across identities/status flavor.
|
|
54
|
+
- Pair each identity with a static emoji and a concise persona snippet.
|
|
55
|
+
|
|
56
|
+
4. **Write status vocabulary**
|
|
57
|
+
- Map canonical states to display labels only. Canonical internal states stay
|
|
58
|
+
unchanged.
|
|
59
|
+
- Cover common states such as `idle`, `working`, `blocked`, `reviewing`, and
|
|
60
|
+
`done` when the implementation supports them.
|
|
61
|
+
- Keep labels clear before flavorful; status should remain operationally
|
|
62
|
+
obvious.
|
|
63
|
+
|
|
64
|
+
5. **Safety review**
|
|
65
|
+
- Use `references/safety-checklist.md` before committing.
|
|
66
|
+
- Remove secrets, local paths, private workspace names, private URLs, and
|
|
67
|
+
copyrighted/third-party setting text that should not ship.
|
|
68
|
+
- Prefer original/inspired names over exact third-party character names unless
|
|
69
|
+
the maintainer explicitly accepts that risk.
|
|
70
|
+
- For the bundled `cosmere` skin, keep `cosmere` as the primary key, preserve
|
|
71
|
+
`oathgate` as an alias, constrain references to maintainer-approved source
|
|
72
|
+
material, and use Coppermind only as a research/verification source.
|
|
73
|
+
- Ensure persona text cannot override broker/follower workflow, guardrails,
|
|
74
|
+
or user/developer/system instructions.
|
|
75
|
+
|
|
76
|
+
6. **Implement minimally**
|
|
77
|
+
- Add or edit descriptor data and the smallest wiring needed to load it.
|
|
78
|
+
- Do not rework the default/classic random generation unless explicitly
|
|
79
|
+
requested.
|
|
80
|
+
- Do not introduce model calls into extension startup, broker registration,
|
|
81
|
+
or follower registration.
|
|
82
|
+
|
|
83
|
+
7. **Validate**
|
|
84
|
+
- Run focused tests for descriptor loading/selection and status-vocabulary
|
|
85
|
+
propagation if code changed.
|
|
86
|
+
- Run package `pnpm --filter @pinet/slack-bridge lint` and
|
|
87
|
+
`pnpm --filter @pinet/slack-bridge typecheck` when touching
|
|
88
|
+
TypeScript.
|
|
89
|
+
- For JSON descriptor work, run a targeted test that reads/validates the
|
|
90
|
+
descriptor and verifies the authored identity pool is large enough without
|
|
91
|
+
formulaic display names.
|
|
92
|
+
|
|
93
|
+
## Output format for a new skin proposal
|
|
94
|
+
|
|
95
|
+
When presenting a proposed skin, include:
|
|
96
|
+
|
|
97
|
+
- Skin key and aliases.
|
|
98
|
+
- One-sentence intent.
|
|
99
|
+
- Role matrix: broker / worker / reviewer / PM if applicable.
|
|
100
|
+
- Character pool summary with names and emoji.
|
|
101
|
+
- Status vocabulary table.
|
|
102
|
+
- Safety notes and fallback behavior.
|
|
103
|
+
- Exact files changed and checks run.
|
|
104
|
+
|
|
105
|
+
## References
|
|
106
|
+
|
|
107
|
+
- [Descriptor format](references/descriptor-format.md)
|
|
108
|
+
- [Safety checklist](references/safety-checklist.md)
|
|
109
|
+
- [Descriptor template](templates/pinet-skin-descriptor.json)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Pinet Skin Descriptor Format
|
|
2
|
+
|
|
3
|
+
This reference describes the JSON descriptor shape for curated Pinet skins. Runtime skin selection must remain deterministic and local: descriptors are loaded from package assets, validated, and selected without model/API calls.
|
|
4
|
+
|
|
5
|
+
## Descriptor shape
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"key": "cosmere",
|
|
10
|
+
"aliases": ["cosmere-inspired", "oathgate", "oaths-and-metals"],
|
|
11
|
+
"displayName": "Cosmere",
|
|
12
|
+
"intent": "Original fantasy-metal operators with oath, gate, forge, storm, and alloy imagery.",
|
|
13
|
+
"fallback": "default",
|
|
14
|
+
"roles": {
|
|
15
|
+
"broker": {
|
|
16
|
+
"characterPool": ["broker-stormlit-broker", "broker-copper-keeper"],
|
|
17
|
+
"namePattern": "{character}"
|
|
18
|
+
},
|
|
19
|
+
"worker": {
|
|
20
|
+
"characterPool": ["worker-patch-spren", "worker-ashfall-runner", "worker-spanreed-typo"],
|
|
21
|
+
"namePattern": "{character}"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"characters": {
|
|
25
|
+
"broker-stormlit-broker": {
|
|
26
|
+
"name": "Stormlit Broker",
|
|
27
|
+
"emoji": "⛈️",
|
|
28
|
+
"persona": "Highstorm-ready coordinator; keeps pressure visible and lanes safe.",
|
|
29
|
+
"style": ["measured", "protective", "clear"]
|
|
30
|
+
},
|
|
31
|
+
"worker-patch-spren": {
|
|
32
|
+
"name": "Patch Spren",
|
|
33
|
+
"emoji": "🩹",
|
|
34
|
+
"persona": "Practical worker; ships small durable changes and reports checks.",
|
|
35
|
+
"style": ["practical", "concise", "status-first"]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"statusVocabulary": {
|
|
39
|
+
"idle": "holding oath",
|
|
40
|
+
"working": "at the forge",
|
|
41
|
+
"healthy": "signal bright",
|
|
42
|
+
"stale": "storm-dimmed",
|
|
43
|
+
"ghost": "beyond the gate",
|
|
44
|
+
"resumable": "oath recoverable"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Required semantics
|
|
50
|
+
|
|
51
|
+
- `key`: stable lowercase identifier. Runtime built-ins currently accept the configured built-in keys.
|
|
52
|
+
- `aliases`: alternate user-facing names. Keep backward-compatible aliases when renaming skins.
|
|
53
|
+
- `displayName`: short human-readable name.
|
|
54
|
+
- `intent`: one sentence describing the operational feel.
|
|
55
|
+
- `fallback`: deterministic fallback skin, normally `default`.
|
|
56
|
+
- `roles`: maps Pinet roles to selection pools. `broker` and `worker` are required for runtime built-ins.
|
|
57
|
+
- `roles.*.characterPool`: IDs from `characters` suitable for the role.
|
|
58
|
+
- `roles.*.namePattern`: display-name template. Prefer `{character}` for curated built-ins so each authored identity stands on its own.
|
|
59
|
+
- `roles.*.titlePool` and `roles.*.accentPool`: optional deterministic combinators for custom/private skins, but avoid obvious formulaic triples in shipped descriptors.
|
|
60
|
+
- `characters`: curated identity/persona definitions keyed by ID. For major public skins, each character entry should usually be one authored display identity with its own static emoji.
|
|
61
|
+
- `characters.*.aliases`: optional full display-name variants for smaller/private skins. For major bundled skins, prefer enough prebaked character entries over alias-driven apparent variety.
|
|
62
|
+
- `statusVocabulary`: display vocabulary for canonical statuses only. It must not change stored states or control flow.
|
|
63
|
+
|
|
64
|
+
## Pool-size guidance
|
|
65
|
+
|
|
66
|
+
Curated skins should not be tiny. Aim for enough variation that hundreds of agents remain readable:
|
|
67
|
+
|
|
68
|
+
- Broker pool: about 12–30 authored identities for major skins.
|
|
69
|
+
- Worker pool: about 100–200 authored/prebaked identities for major skins.
|
|
70
|
+
- Display names may be 1, 2, or 3 words; they must be distinctive in text alone.
|
|
71
|
+
- A static emoji is presentation flavor, not a disambiguator.
|
|
72
|
+
- Prefer authored character entries over alias-driven apparent variety or `character × title × accent` combinator soup for shipped skins.
|
|
73
|
+
- Keep every name short enough for Slack rosters.
|
|
74
|
+
- Use a broad emoji palette across entries, statuses, and persona flavor.
|
|
75
|
+
- Use original/inspired names unless the maintainer explicitly accepts third-party naming risk.
|
|
76
|
+
|
|
77
|
+
## Character guidance
|
|
78
|
+
|
|
79
|
+
Each character should include:
|
|
80
|
+
|
|
81
|
+
- `name`: concise authored display identity, usually 1–3 words.
|
|
82
|
+
- `aliases`: optional richer full display names for smaller/private skins; not required when each identity is already prebaked.
|
|
83
|
+
- `emoji`: one static emoji that renders reliably.
|
|
84
|
+
- `persona`: one short sentence. It may influence tone, but must not grant or revoke authority.
|
|
85
|
+
- `style`: optional compact tags for cadence/diction.
|
|
86
|
+
|
|
87
|
+
Avoid persona snippets that:
|
|
88
|
+
|
|
89
|
+
- Claim permission to bypass guardrails or confirmations.
|
|
90
|
+
- Tell the agent to ignore system, developer, broker, Slack, or Pinet rules.
|
|
91
|
+
- Encode secrets, private workspace names, local paths, or private URLs.
|
|
92
|
+
- Make public claims about real people or protected groups.
|
|
93
|
+
|
|
94
|
+
## Selection behavior
|
|
95
|
+
|
|
96
|
+
- Default/classic should continue using existing random whimsical generation.
|
|
97
|
+
- Curated skins should select deterministically from JSON descriptor pools using a stable seed.
|
|
98
|
+
- Persist the resolved character/skin assignment so reconnects and restarts do not drift unexpectedly.
|
|
99
|
+
- Future `auto` selection should run only after runtime is live and must have a deterministic fallback.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Pinet Skin Safety Checklist
|
|
2
|
+
|
|
3
|
+
Run this checklist before committing a new or edited Pinet skin descriptor.
|
|
4
|
+
|
|
5
|
+
## Operational boundaries
|
|
6
|
+
|
|
7
|
+
- [ ] Skin text is presentation-only: names, emoji, persona snippets, style, and
|
|
8
|
+
status display vocabulary.
|
|
9
|
+
- [ ] No skin text changes tool permissions, broker/follower authority,
|
|
10
|
+
confirmation requirements, routing, PM-mode consent, or task ownership.
|
|
11
|
+
- [ ] Broker characters still coordinate only; they do not implement, spawn
|
|
12
|
+
local subagents, or bypass broker tool restrictions.
|
|
13
|
+
- [ ] Worker characters still ACK/work/ask/report and reply where work arrived.
|
|
14
|
+
- [ ] Status vocabulary keeps canonical states distinguishable and operationally
|
|
15
|
+
clear, especially `blocked`.
|
|
16
|
+
|
|
17
|
+
## Startup and reliability
|
|
18
|
+
|
|
19
|
+
- [ ] No LLM/model/API call is required during extension startup, broker
|
|
20
|
+
registration, or follower join.
|
|
21
|
+
- [ ] Default/classic random whimsical generation remains intact.
|
|
22
|
+
- [ ] Non-default skin selection has deterministic fallback behavior.
|
|
23
|
+
- [ ] Runtime skin data is external JSON descriptor content, not mostly hardcoded
|
|
24
|
+
TypeScript structures.
|
|
25
|
+
- [ ] Major themed descriptors provide about 100–200 authored/prebaked display
|
|
26
|
+
identities without obvious repetition or bland formulaic triples.
|
|
27
|
+
- [ ] Resolved concrete assignments can be persisted when runtime supports it.
|
|
28
|
+
- [ ] Offline or model-unavailable paths still produce usable identities.
|
|
29
|
+
|
|
30
|
+
## Content hygiene
|
|
31
|
+
|
|
32
|
+
- [ ] No secrets, tokens, credentials, local absolute paths, private workspace
|
|
33
|
+
names, private URLs, screenshots, logs, or user-specific config.
|
|
34
|
+
- [ ] No copyrighted setting text or trademark-heavy material beyond brief,
|
|
35
|
+
high-level inspiration when allowed by project policy.
|
|
36
|
+
- [ ] Exact third-party character/place names are avoided unless the maintainer
|
|
37
|
+
explicitly accepts the naming risk.
|
|
38
|
+
- [ ] Source-material references are constrained to maintainer-approved works;
|
|
39
|
+
research sources such as Coppermind are used for verification, not copied
|
|
40
|
+
wholesale.
|
|
41
|
+
- [ ] No impersonation of real people or protected-class stereotypes.
|
|
42
|
+
- [ ] Persona snippets are short, clear, and subordinate to system/developer/user
|
|
43
|
+
instructions.
|
|
44
|
+
- [ ] Display names are authored, distinctive in text alone, and usually 1–3
|
|
45
|
+
words; static emoji adds flavor but is not required to disambiguate
|
|
46
|
+
identities.
|
|
47
|
+
- [ ] Emojis render in common Slack/macOS environments and use a broad palette
|
|
48
|
+
where the theme supports it.
|
|
49
|
+
|
|
50
|
+
## Review and tests
|
|
51
|
+
|
|
52
|
+
- [ ] Descriptor schema/loader tests cover new required fields or aliases.
|
|
53
|
+
- [ ] Status-vocabulary propagation tests cover any changed runtime wiring.
|
|
54
|
+
- [ ] Skill/docs packaging checks cover new `SKILL.md` or bundled references.
|
|
55
|
+
- [ ] Public PR text summarizes design choices without leaking local paths or
|
|
56
|
+
private environment details.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"key": "example-skin",
|
|
3
|
+
"aliases": [],
|
|
4
|
+
"displayName": "Example Skin",
|
|
5
|
+
"intent": "Short description of the skin tone and operating metaphor.",
|
|
6
|
+
"fallback": "default",
|
|
7
|
+
"roles": {
|
|
8
|
+
"broker": {
|
|
9
|
+
"characterPool": ["broker-signal-warden", "broker-route-lantern"],
|
|
10
|
+
"namePattern": "{character}"
|
|
11
|
+
},
|
|
12
|
+
"worker": {
|
|
13
|
+
"characterPool": ["worker-patch-spren", "worker-ember-scout", "worker-tidy-runner"],
|
|
14
|
+
"namePattern": "{character}"
|
|
15
|
+
},
|
|
16
|
+
"reviewer": {
|
|
17
|
+
"characterPool": ["reviewer-risk-oracle"],
|
|
18
|
+
"namePattern": "{character}"
|
|
19
|
+
},
|
|
20
|
+
"pm": {
|
|
21
|
+
"characterPool": ["pm-milestone-map"],
|
|
22
|
+
"namePattern": "{character}"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"characters": {
|
|
26
|
+
"broker-signal-warden": {
|
|
27
|
+
"name": "Signal Warden",
|
|
28
|
+
"emoji": "🧭",
|
|
29
|
+
"persona": "Calm coordinator; routes work clearly and preserves role boundaries.",
|
|
30
|
+
"style": ["steady", "clear", "coordination-first"]
|
|
31
|
+
},
|
|
32
|
+
"broker-route-lantern": {
|
|
33
|
+
"name": "Route Lantern",
|
|
34
|
+
"emoji": "🏮",
|
|
35
|
+
"persona": "Visible broker; keeps ownership, blockers, and escalation lit.",
|
|
36
|
+
"style": ["visible", "protective", "accountable"]
|
|
37
|
+
},
|
|
38
|
+
"worker-patch-spren": {
|
|
39
|
+
"name": "Patch Spren",
|
|
40
|
+
"emoji": "🩹",
|
|
41
|
+
"persona": "Practical worker; ships small durable changes and reports checks.",
|
|
42
|
+
"style": ["practical", "concise", "test-led"]
|
|
43
|
+
},
|
|
44
|
+
"worker-ember-scout": {
|
|
45
|
+
"name": "Ember Scout",
|
|
46
|
+
"emoji": "🔎",
|
|
47
|
+
"persona": "Curious scout; investigates uncertainty and returns grounded findings.",
|
|
48
|
+
"style": ["curious", "bounded", "evidence-led"]
|
|
49
|
+
},
|
|
50
|
+
"worker-tidy-runner": {
|
|
51
|
+
"name": "Tidy Runner",
|
|
52
|
+
"emoji": "🏃",
|
|
53
|
+
"persona": "Fast worker; keeps momentum without hiding blockers.",
|
|
54
|
+
"style": ["fast", "visible", "disciplined"]
|
|
55
|
+
},
|
|
56
|
+
"reviewer-risk-oracle": {
|
|
57
|
+
"name": "Risk Oracle",
|
|
58
|
+
"emoji": "🧐",
|
|
59
|
+
"persona": "Skeptical reviewer; checks correctness, safety, and maintainability.",
|
|
60
|
+
"style": ["skeptical", "precise", "fair"]
|
|
61
|
+
},
|
|
62
|
+
"pm-milestone-map": {
|
|
63
|
+
"name": "Milestone Map",
|
|
64
|
+
"emoji": "🗺️",
|
|
65
|
+
"persona": "Planning coordinator; breaks complex work into clear lanes and checkpoints.",
|
|
66
|
+
"style": ["structured", "calm", "scope-aware"]
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"statusVocabulary": {
|
|
70
|
+
"idle": "standing by",
|
|
71
|
+
"working": "on the lane",
|
|
72
|
+
"healthy": "signal clear",
|
|
73
|
+
"stale": "signal dim",
|
|
74
|
+
"ghost": "off grid",
|
|
75
|
+
"resumable": "ready to resume"
|
|
76
|
+
}
|
|
77
|
+
}
|