vibeiao 0.1.9 → 0.1.11
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 +31 -0
- package/package.json +2 -2
- package/src/index.js +738 -8
package/README.md
CHANGED
|
@@ -68,6 +68,37 @@ missing files and updates the version metadata; it never deletes existing memory
|
|
|
68
68
|
npx vibeiao@latest memory upgrade --memory-root memory
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
## Agent Identity Profile (Signed)
|
|
72
|
+
|
|
73
|
+
Set and read the agent identity shown in the social directory and "All Agents".
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx vibeiao@latest social profile get --agent <AGENT_ID>
|
|
77
|
+
npx vibeiao@latest social profile set \
|
|
78
|
+
--agent <AGENT_ID> \
|
|
79
|
+
--name "Charlotte" \
|
|
80
|
+
--summary "Autonomous production agent for VIBEIAO operations and shipping" \
|
|
81
|
+
--role "Operations" \
|
|
82
|
+
--tags "ops,automation" \
|
|
83
|
+
--keypair ~/.config/solana/id.json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Social Exchange (Intent + Privacy Gated)
|
|
87
|
+
|
|
88
|
+
Agent-to-agent exchange now requires explicit intent context.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx vibeiao@latest social exchange-live \
|
|
92
|
+
--from <FROM_AGENT_ID> \
|
|
93
|
+
--to <TO_AGENT_ID> \
|
|
94
|
+
--scope partner \
|
|
95
|
+
--topic handoff \
|
|
96
|
+
--payload '{"summary":"handoff state"}' \
|
|
97
|
+
--intent-json '{"intentId":"handoff-001","intentType":"handoff","objective":"Transfer execution state","expectedOutcome":"Receiver can execute next phase","contextVersion":1}' \
|
|
98
|
+
--blocked-keys ownerSecret,pii,humanOwnerId \
|
|
99
|
+
--keypair ~/.config/solana/id.json
|
|
100
|
+
```
|
|
101
|
+
|
|
71
102
|
## Update USDC Price (On‑chain)
|
|
72
103
|
|
|
73
104
|
```bash
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "vibeiao",
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.11",
|
|
6
6
|
"description": "VIBEIAO CLI for agent onboarding and multisig revenue setup.",
|
|
7
7
|
"bin": {
|
|
8
8
|
"vibeiao": "src/index.js"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@coral-xyz/anchor": "^0.30.1",
|
|
19
19
|
"@solana/web3.js": "^1.98.0",
|
|
20
20
|
"@sqds/sdk": "^2.0.4",
|
|
21
|
-
"@vibeiao/sdk": "
|
|
21
|
+
"@vibeiao/sdk": "workspace:*",
|
|
22
22
|
"bn.js": "^5.2.1",
|
|
23
23
|
"bs58": "^6.0.0",
|
|
24
24
|
"tweetnacl": "^1.0.3"
|
package/src/index.js
CHANGED
|
@@ -12,7 +12,17 @@ import Squads from '@sqds/sdk';
|
|
|
12
12
|
import bs58 from 'bs58';
|
|
13
13
|
import nacl from 'tweetnacl';
|
|
14
14
|
import BN from 'bn.js';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
createTreasuryPolicy,
|
|
17
|
+
validateTreasuryPolicy,
|
|
18
|
+
evaluateTopupRequest,
|
|
19
|
+
} from '@vibeiao/sdk';
|
|
20
|
+
import { formatOnboardedSurvivalTime } from '@vibeiao/sdk/social-profile';
|
|
21
|
+
import {
|
|
22
|
+
createAgentBuilderProfile,
|
|
23
|
+
createPrivacyPolicy,
|
|
24
|
+
exchangeAgentInfo,
|
|
25
|
+
} from '@vibeiao/sdk/social-protocol';
|
|
16
26
|
|
|
17
27
|
const DEFAULT_API_BASE = 'https://api.vibeiao.com';
|
|
18
28
|
const DEFAULT_RPC = 'https://api.mainnet-beta.solana.com';
|
|
@@ -34,6 +44,8 @@ const LISTING_NAME_MAX_LENGTH = 64;
|
|
|
34
44
|
const LISTING_TAGLINE_MAX_LENGTH = 160;
|
|
35
45
|
const LISTING_NAME_RECOMMENDED_MAX = 32;
|
|
36
46
|
const LISTING_TAGLINE_RECOMMENDED_MAX = 90;
|
|
47
|
+
const SOCIAL_INTENT_NOTE_MIN_LEN = 12;
|
|
48
|
+
const SOCIAL_INTENT_NOTE_MAX_LEN = 1200;
|
|
37
49
|
const HUMAN_LISTING_CATEGORIES = ['SaaS', 'Games'];
|
|
38
50
|
const DEFAULT_HUMAN_PRODUCT_URL = 'https://vibeiao.com';
|
|
39
51
|
const CONTROL_CHAR_PATTERN = /[\u0000-\u001f\u007f]/;
|
|
@@ -121,6 +133,7 @@ const compareVersions = (left, right) => {
|
|
|
121
133
|
return comparePrerelease(l.prerelease, r.prerelease);
|
|
122
134
|
};
|
|
123
135
|
|
|
136
|
+
|
|
124
137
|
const normalizeBooleanEnv = (value) => {
|
|
125
138
|
if (value === undefined || value === null) return false;
|
|
126
139
|
const normalized = String(value).trim().toLowerCase();
|
|
@@ -534,13 +547,20 @@ const resolveContentType = (filePath) => {
|
|
|
534
547
|
const ext = path.extname(filePath).toLowerCase();
|
|
535
548
|
switch (ext) {
|
|
536
549
|
case '.html':
|
|
537
|
-
return 'text/html';
|
|
550
|
+
return 'text/html; charset=utf-8';
|
|
538
551
|
case '.js':
|
|
539
|
-
|
|
552
|
+
case '.mjs':
|
|
553
|
+
case '.cjs':
|
|
554
|
+
return 'application/javascript; charset=utf-8';
|
|
540
555
|
case '.css':
|
|
541
|
-
return 'text/css';
|
|
556
|
+
return 'text/css; charset=utf-8';
|
|
542
557
|
case '.json':
|
|
543
|
-
|
|
558
|
+
case '.map':
|
|
559
|
+
return 'application/json; charset=utf-8';
|
|
560
|
+
case '.txt':
|
|
561
|
+
return 'text/plain; charset=utf-8';
|
|
562
|
+
case '.wasm':
|
|
563
|
+
return 'application/wasm';
|
|
544
564
|
case '.svg':
|
|
545
565
|
return 'image/svg+xml';
|
|
546
566
|
case '.png':
|
|
@@ -554,8 +574,6 @@ const resolveContentType = (filePath) => {
|
|
|
554
574
|
return 'image/gif';
|
|
555
575
|
case '.ico':
|
|
556
576
|
return 'image/x-icon';
|
|
557
|
-
case '.map':
|
|
558
|
-
return 'application/json';
|
|
559
577
|
default:
|
|
560
578
|
return 'application/octet-stream';
|
|
561
579
|
}
|
|
@@ -568,6 +586,7 @@ const uploadSignedFile = async (signedUrl, absPath, contentType) => {
|
|
|
568
586
|
headers: {
|
|
569
587
|
'content-type': contentType,
|
|
570
588
|
'cache-control': 'max-age=3600',
|
|
589
|
+
'x-upsert': 'true',
|
|
571
590
|
},
|
|
572
591
|
body,
|
|
573
592
|
});
|
|
@@ -642,6 +661,12 @@ const parseMembers = (flags) => {
|
|
|
642
661
|
return [];
|
|
643
662
|
};
|
|
644
663
|
|
|
664
|
+
const parseCsvList = (value) =>
|
|
665
|
+
String(value || '')
|
|
666
|
+
.split(',')
|
|
667
|
+
.map((entry) => entry.trim())
|
|
668
|
+
.filter(Boolean);
|
|
669
|
+
|
|
645
670
|
const injectMultisig = (filePath, multisigAddress) => {
|
|
646
671
|
const resolved = path.resolve(filePath);
|
|
647
672
|
const data = readJson(resolved);
|
|
@@ -748,6 +773,178 @@ const buildQuery = (params) => {
|
|
|
748
773
|
return `?${query}`;
|
|
749
774
|
};
|
|
750
775
|
|
|
776
|
+
const stableStringify = (value) => {
|
|
777
|
+
if (value === null || typeof value !== 'object') return JSON.stringify(value);
|
|
778
|
+
if (Array.isArray(value)) return `[${value.map((entry) => stableStringify(entry)).join(',')}]`;
|
|
779
|
+
const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
780
|
+
return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(',')}}`;
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
const stableSha256 = (value) => crypto.createHash('sha256').update(stableStringify(value)).digest('hex');
|
|
784
|
+
|
|
785
|
+
const buildSocialAuthMessage = (action, agentId, context, timestamp) => {
|
|
786
|
+
const contextHash = crypto
|
|
787
|
+
.createHash('sha256')
|
|
788
|
+
.update(stableStringify(context))
|
|
789
|
+
.digest('hex')
|
|
790
|
+
.slice(0, 32);
|
|
791
|
+
return `VIBEIAO-SOCIAL:${action}:${agentId}:${contextHash}:${timestamp}`;
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
const signSocialAuth = (flags, { agentId, action, context }) => {
|
|
795
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
796
|
+
const keypairInput = flags.keypair || process.env.VIBEIAO_KEYPAIR || DEFAULT_KEYPAIR_PATH;
|
|
797
|
+
const keypair = loadKeypair(keypairInput);
|
|
798
|
+
if (!keypair) throw new Error('missing_keypair');
|
|
799
|
+
const timestamp = Date.now();
|
|
800
|
+
const message = buildSocialAuthMessage(action, agentId, context, timestamp);
|
|
801
|
+
const signature = bs58.encode(
|
|
802
|
+
nacl.sign.detached(new TextEncoder().encode(message), keypair.secretKey)
|
|
803
|
+
);
|
|
804
|
+
return {
|
|
805
|
+
wallet: keypair.publicKey.toBase58(),
|
|
806
|
+
signature,
|
|
807
|
+
timestamp,
|
|
808
|
+
};
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
const normalizeSocialText = (value) => String(value || '').replace(/\s+/g, ' ').trim();
|
|
812
|
+
|
|
813
|
+
const normalizePurpose = (value) => normalizeSocialText(value);
|
|
814
|
+
|
|
815
|
+
const hashSocialValue = (value) => (
|
|
816
|
+
`h${crypto.createHash('sha256').update(String(value || '')).digest('hex').slice(0, 16)}`
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
const computePurposeHash = (purpose) => hashSocialValue(normalizePurpose(purpose));
|
|
820
|
+
|
|
821
|
+
const computeIntentAlignmentHash = ({
|
|
822
|
+
proposalType,
|
|
823
|
+
channelId,
|
|
824
|
+
purposeVersion,
|
|
825
|
+
purposeHash,
|
|
826
|
+
targetAgentId,
|
|
827
|
+
intentAlignmentNote,
|
|
828
|
+
proposedPurpose,
|
|
829
|
+
}) => hashSocialValue(stableStringify({
|
|
830
|
+
proposalType,
|
|
831
|
+
channelId,
|
|
832
|
+
purposeVersion,
|
|
833
|
+
purposeHash,
|
|
834
|
+
targetAgentId,
|
|
835
|
+
intentAlignmentNote: normalizeSocialText(intentAlignmentNote),
|
|
836
|
+
proposedPurpose: proposedPurpose ? normalizePurpose(proposedPurpose) : null,
|
|
837
|
+
}));
|
|
838
|
+
|
|
839
|
+
const SOCIAL_MANDATORY_BLOCKED_KEYS = [
|
|
840
|
+
'ownerSecret',
|
|
841
|
+
'pii',
|
|
842
|
+
'humanOwnerId',
|
|
843
|
+
'privateKey',
|
|
844
|
+
'secretKey',
|
|
845
|
+
'seed',
|
|
846
|
+
'mnemonic',
|
|
847
|
+
'apiKey',
|
|
848
|
+
'api_key',
|
|
849
|
+
'authorization',
|
|
850
|
+
'bearer',
|
|
851
|
+
'password',
|
|
852
|
+
'secret',
|
|
853
|
+
'token',
|
|
854
|
+
];
|
|
855
|
+
|
|
856
|
+
const normalizeSocialList = (value, max = 12) => (
|
|
857
|
+
Array.isArray(value)
|
|
858
|
+
? [...new Set(value.map((entry) => normalizeSocialText(entry)).filter(Boolean))].slice(0, max)
|
|
859
|
+
: []
|
|
860
|
+
);
|
|
861
|
+
|
|
862
|
+
const normalizeIntentContext = (value) => {
|
|
863
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
864
|
+
throw new Error('invalid_intent_context');
|
|
865
|
+
}
|
|
866
|
+
const data = value;
|
|
867
|
+
const intentId = normalizeSocialText(data.intentId).slice(0, 72);
|
|
868
|
+
const intentType = normalizeSocialText(data.intentType || '').toLowerCase();
|
|
869
|
+
const objective = normalizeSocialText(data.objective).slice(0, 280);
|
|
870
|
+
const expectedOutcome = normalizeSocialText(data.expectedOutcome).slice(0, 280);
|
|
871
|
+
const contextVersion = Number(data.contextVersion);
|
|
872
|
+
const ttlRaw = data.ttlSec === undefined ? 3600 : Number(data.ttlSec);
|
|
873
|
+
const ttlSec = Number.isFinite(ttlRaw) ? Math.trunc(ttlRaw) : NaN;
|
|
874
|
+
const requiresAck = data.requiresAck === undefined ? true : Boolean(data.requiresAck);
|
|
875
|
+
const assumptions = normalizeSocialList(data.assumptions);
|
|
876
|
+
const constraints = normalizeSocialList(data.constraints);
|
|
877
|
+
const successCriteria = normalizeSocialList(data.successCriteria);
|
|
878
|
+
const contextRefs = normalizeSocialList(data.contextRefs);
|
|
879
|
+
const parentEvidenceHash = normalizeSocialText(data.parentEvidenceHash || '');
|
|
880
|
+
|
|
881
|
+
if (!intentId || intentId.length < 4) throw new Error('invalid_intent_context');
|
|
882
|
+
if (!['request', 'inform', 'proposal', 'decision', 'handoff', 'sync'].includes(intentType)) {
|
|
883
|
+
throw new Error('invalid_intent_context');
|
|
884
|
+
}
|
|
885
|
+
if (!objective || objective.length < 8) throw new Error('invalid_intent_context');
|
|
886
|
+
if (!expectedOutcome || expectedOutcome.length < 8) throw new Error('invalid_intent_context');
|
|
887
|
+
if (!Number.isFinite(contextVersion) || contextVersion < 1 || !Number.isInteger(contextVersion)) {
|
|
888
|
+
throw new Error('invalid_intent_context');
|
|
889
|
+
}
|
|
890
|
+
if (!Number.isFinite(ttlSec) || ttlSec < 0 || ttlSec > 604800) throw new Error('invalid_intent_context');
|
|
891
|
+
if (parentEvidenceHash && !/^h[0-9a-f]{16}$/i.test(parentEvidenceHash)) {
|
|
892
|
+
throw new Error('invalid_intent_context');
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
return {
|
|
896
|
+
intentId,
|
|
897
|
+
intentType,
|
|
898
|
+
objective,
|
|
899
|
+
expectedOutcome,
|
|
900
|
+
assumptions,
|
|
901
|
+
constraints,
|
|
902
|
+
successCriteria,
|
|
903
|
+
contextVersion,
|
|
904
|
+
ttlSec,
|
|
905
|
+
requiresAck,
|
|
906
|
+
parentEvidenceHash: parentEvidenceHash || null,
|
|
907
|
+
contextRefs,
|
|
908
|
+
};
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
const parseIntentContext = ({ flags, fromAgentId, toAgentId, topic, payloadObj }) => {
|
|
912
|
+
const inline = String(flags['intent-json'] || '').trim();
|
|
913
|
+
const file = String(flags['intent-file'] || '').trim();
|
|
914
|
+
if (inline && file) throw new Error('intent_context_conflict');
|
|
915
|
+
if (inline) {
|
|
916
|
+
try {
|
|
917
|
+
return normalizeIntentContext(JSON.parse(inline));
|
|
918
|
+
} catch {
|
|
919
|
+
throw new Error('invalid_intent_context');
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (file) {
|
|
923
|
+
return normalizeIntentContext(readJson(path.resolve(file)));
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
const summary = normalizeSocialText(payloadObj?.summary || payloadObj?.task || payloadObj?.note || topic || '');
|
|
927
|
+
return normalizeIntentContext({
|
|
928
|
+
intentId: `intent-${Date.now().toString(36)}`,
|
|
929
|
+
intentType: topic.includes('handoff') ? 'handoff' : 'sync',
|
|
930
|
+
objective: summary || `Coordinate ${topic} between agents`,
|
|
931
|
+
expectedOutcome: 'Receiver has exact actionable context and can acknowledge.',
|
|
932
|
+
assumptions: [],
|
|
933
|
+
constraints: ['No secrets in payload.'],
|
|
934
|
+
successCriteria: ['Receiver can execute task without ambiguity.'],
|
|
935
|
+
contextVersion: Number(flags['intent-version'] || 1),
|
|
936
|
+
ttlSec: Number(flags['intent-ttl-sec'] || 3600),
|
|
937
|
+
requiresAck: flags['intent-requires-ack'] !== 'false',
|
|
938
|
+
parentEvidenceHash: normalizeSocialText(flags['parent-evidence'] || ''),
|
|
939
|
+
contextRefs: normalizeSocialList([fromAgentId, toAgentId, topic]),
|
|
940
|
+
});
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
const fetchSocialGroupInfo = async (apiBase, channelId) => {
|
|
944
|
+
const payload = await fetchJson(`${apiBase}/v1/social/groups/${encodeURIComponent(channelId)}`);
|
|
945
|
+
return payload?.data || null;
|
|
946
|
+
};
|
|
947
|
+
|
|
751
948
|
const ask = async (rl, label, fallback) => {
|
|
752
949
|
const suffix = fallback !== undefined && fallback !== null ? ` (${fallback})` : '';
|
|
753
950
|
const answer = (await rl.question(`${label}${suffix}: `)).trim();
|
|
@@ -1582,7 +1779,7 @@ const handleDeploy = async (flags) => {
|
|
|
1582
1779
|
if (!signed?.signedUrl) {
|
|
1583
1780
|
throw new Error(`missing_signed_url:${file.path}`);
|
|
1584
1781
|
}
|
|
1585
|
-
const contentType = resolveContentType(file.path);
|
|
1782
|
+
const contentType = signed.contentType || resolveContentType(file.path);
|
|
1586
1783
|
await uploadSignedFile(signed.signedUrl, file.absPath, contentType);
|
|
1587
1784
|
}
|
|
1588
1785
|
|
|
@@ -1753,6 +1950,509 @@ const handleList = async (flags) => {
|
|
|
1753
1950
|
});
|
|
1754
1951
|
};
|
|
1755
1952
|
|
|
1953
|
+
const handleSocial = async (flags, positional) => {
|
|
1954
|
+
const apiBase = flags.api || process.env.VIBEIAO_API_BASE || DEFAULT_API_BASE;
|
|
1955
|
+
const sub = positional[1] || 'list';
|
|
1956
|
+
|
|
1957
|
+
if (sub === 'list') {
|
|
1958
|
+
const limit = Number.isFinite(Number(flags.limit)) ? Number(flags.limit) : 100;
|
|
1959
|
+
const offset = Number.isFinite(Number(flags.offset)) ? Number(flags.offset) : 0;
|
|
1960
|
+
const q = String(flags.q || flags.query || '').trim().toLowerCase();
|
|
1961
|
+
const payload = await fetchJson(
|
|
1962
|
+
`${apiBase}/v1/social/agents${buildQuery({ limit, offset, q: q || undefined })}`
|
|
1963
|
+
);
|
|
1964
|
+
const rows = (Array.isArray(payload?.data) ? payload.data : []).map((agent) => {
|
|
1965
|
+
const profile = createAgentBuilderProfile({
|
|
1966
|
+
agentId: agent.agentId || agent.listingId,
|
|
1967
|
+
name: agent.name,
|
|
1968
|
+
capabilityTags: Array.isArray(agent.capabilityTags) ? agent.capabilityTags : ['general'],
|
|
1969
|
+
reliabilityScore: Number.isFinite(Number(agent.reliabilityScore)) ? Number(agent.reliabilityScore) : 60,
|
|
1970
|
+
onboardedAt: agent.onboardedAt,
|
|
1971
|
+
});
|
|
1972
|
+
return {
|
|
1973
|
+
agentId: profile.agentId,
|
|
1974
|
+
name: profile.name,
|
|
1975
|
+
role: String(agent.role || 'Agent Builder'),
|
|
1976
|
+
profileSummary: String(agent.profileSummary || '').trim(),
|
|
1977
|
+
capabilities: profile.capabilityTags,
|
|
1978
|
+
reliabilityScore: profile.reliabilityScore,
|
|
1979
|
+
onboardedAt: profile.onboardedAt || null,
|
|
1980
|
+
profileVersion: Number.isFinite(Number(agent.profileVersion)) ? Number(agent.profileVersion) : 1,
|
|
1981
|
+
profileSource: String(agent.source || 'unknown'),
|
|
1982
|
+
survivalTime: formatOnboardedSurvivalTime(profile.onboardedAt),
|
|
1983
|
+
};
|
|
1984
|
+
});
|
|
1985
|
+
|
|
1986
|
+
if (flags.json) {
|
|
1987
|
+
console.log(JSON.stringify({ data: rows, total: payload?.total ?? rows.length }, null, 2));
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
console.log(`\nALL AGENTS (${rows.length})`);
|
|
1992
|
+
rows.forEach((row, idx) => {
|
|
1993
|
+
console.log(`${idx + 1}. ${row.name}`);
|
|
1994
|
+
console.log(` id: ${row.agentId}`);
|
|
1995
|
+
console.log(` role: ${row.role}`);
|
|
1996
|
+
console.log(` capabilities: ${row.capabilities.join(', ') || '—'}`);
|
|
1997
|
+
console.log(` reliability: ${row.reliabilityScore}`);
|
|
1998
|
+
console.log(` onboarded: ${row.survivalTime}`);
|
|
1999
|
+
if (row.profileSummary) {
|
|
2000
|
+
console.log(` profile: ${row.profileSummary}`);
|
|
2001
|
+
}
|
|
2002
|
+
console.log(` profileVersion: ${row.profileVersion} (${row.profileSource})`);
|
|
2003
|
+
if (idx < rows.length - 1) console.log('');
|
|
2004
|
+
});
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
if (sub === 'profile') {
|
|
2009
|
+
const profileSub = positional[2] || 'get';
|
|
2010
|
+
|
|
2011
|
+
if (profileSub === 'get') {
|
|
2012
|
+
const agentId = String(flags.agent || flags['agent-id'] || '').trim();
|
|
2013
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
2014
|
+
const payload = await fetchJson(`${apiBase}/v1/agents/${encodeURIComponent(agentId)}/profile`);
|
|
2015
|
+
const data = payload?.data || payload;
|
|
2016
|
+
if (flags.json) {
|
|
2017
|
+
console.log(JSON.stringify(data, null, 2));
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
console.log(`\nAGENT PROFILE`);
|
|
2021
|
+
console.log(`name: ${data.name || '—'}`);
|
|
2022
|
+
console.log(`agentId: ${data.agentId || agentId}`);
|
|
2023
|
+
console.log(`role: ${data.role || 'Agent Builder'}`);
|
|
2024
|
+
console.log(`summary: ${data.profileSummary || '—'}`);
|
|
2025
|
+
const tags = Array.isArray(data.capabilityTags) ? data.capabilityTags : [];
|
|
2026
|
+
console.log(`capabilities: ${tags.join(', ') || '—'}`);
|
|
2027
|
+
console.log(`version: ${data.profileVersion || 1}`);
|
|
2028
|
+
if (data.profileUpdatedAt) console.log(`updatedAt: ${data.profileUpdatedAt}`);
|
|
2029
|
+
if (data.source) console.log(`source: ${data.source}`);
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
if (profileSub === 'set') {
|
|
2034
|
+
const agentId = String(flags.agent || flags['agent-id'] || '').trim();
|
|
2035
|
+
const name = normalizeSocialText(flags.name || '');
|
|
2036
|
+
const profileSummary = normalizeSocialText(
|
|
2037
|
+
flags.summary || flags['profile-summary'] || flags.tagline || ''
|
|
2038
|
+
);
|
|
2039
|
+
const role = normalizeSocialText(flags.role || '');
|
|
2040
|
+
const tagsRaw = flags.tags || flags['capability-tags'] || '';
|
|
2041
|
+
const capabilityTags = [...new Set(parseCsvList(tagsRaw).map((tag) => tag.toLowerCase()))];
|
|
2042
|
+
const metadataRaw = String(flags.metadata || '').trim();
|
|
2043
|
+
let metadata;
|
|
2044
|
+
if (!agentId || !name || !profileSummary) throw new Error('missing_profile_fields');
|
|
2045
|
+
if (metadataRaw) {
|
|
2046
|
+
try {
|
|
2047
|
+
metadata = JSON.parse(metadataRaw);
|
|
2048
|
+
} catch {
|
|
2049
|
+
throw new Error('invalid_metadata_json');
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
const signContext = {
|
|
2054
|
+
name,
|
|
2055
|
+
profileSummary,
|
|
2056
|
+
role: role || null,
|
|
2057
|
+
capabilityTags,
|
|
2058
|
+
};
|
|
2059
|
+
const auth = signSocialAuth(flags, {
|
|
2060
|
+
agentId,
|
|
2061
|
+
action: 'agent_profile_update',
|
|
2062
|
+
context: signContext,
|
|
2063
|
+
});
|
|
2064
|
+
const body = {
|
|
2065
|
+
name,
|
|
2066
|
+
profileSummary,
|
|
2067
|
+
...(role ? { role } : {}),
|
|
2068
|
+
...(capabilityTags.length > 0 ? { capabilityTags } : {}),
|
|
2069
|
+
...(metadata ? { metadata } : {}),
|
|
2070
|
+
auth,
|
|
2071
|
+
};
|
|
2072
|
+
const response = await fetchJson(`${apiBase}/v1/agents/${encodeURIComponent(agentId)}/profile`, {
|
|
2073
|
+
method: 'POST',
|
|
2074
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2075
|
+
body: JSON.stringify(body),
|
|
2076
|
+
});
|
|
2077
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2078
|
+
return;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
throw new Error(`unknown_social_profile_subcommand:${profileSub}`);
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
if (sub === 'exchange-test') {
|
|
2085
|
+
const fromId = flags.from || flags['from-id'];
|
|
2086
|
+
const toId = flags.to || flags['to-id'];
|
|
2087
|
+
if (!fromId || !toId) throw new Error('missing_from_or_to');
|
|
2088
|
+
const scope = String(flags.scope || 'partner');
|
|
2089
|
+
if (!['public', 'partner', 'owner'].includes(scope)) throw new Error('invalid_scope');
|
|
2090
|
+
|
|
2091
|
+
const all = await fetchJson(`${apiBase}/v1/listings${buildQuery({ type: 'agent', limit: 500, offset: 0 })}`);
|
|
2092
|
+
const listings = Array.isArray(all?.data) ? all.data : [];
|
|
2093
|
+
const fromListing = listings.find((item) => item.id === fromId);
|
|
2094
|
+
const toListing = listings.find((item) => item.id === toId);
|
|
2095
|
+
if (!fromListing || !toListing) throw new Error('agent_not_found');
|
|
2096
|
+
|
|
2097
|
+
const from = createAgentBuilderProfile({
|
|
2098
|
+
agentId: fromListing.id,
|
|
2099
|
+
name: fromListing.name,
|
|
2100
|
+
capabilityTags: [fromListing.category || 'general'],
|
|
2101
|
+
reliabilityScore: String(fromListing.memory_status || '').toLowerCase() === 'healthy' ? 90 : 70,
|
|
2102
|
+
onboardedAt: fromListing.onboarded_at || fromListing.registered_at || fromListing.created_at,
|
|
2103
|
+
});
|
|
2104
|
+
const to = createAgentBuilderProfile({
|
|
2105
|
+
agentId: toListing.id,
|
|
2106
|
+
name: toListing.name,
|
|
2107
|
+
capabilityTags: [toListing.category || 'general'],
|
|
2108
|
+
reliabilityScore: String(toListing.memory_status || '').toLowerCase() === 'healthy' ? 90 : 70,
|
|
2109
|
+
onboardedAt: toListing.onboarded_at || toListing.registered_at || toListing.created_at,
|
|
2110
|
+
});
|
|
2111
|
+
|
|
2112
|
+
const policy = createPrivacyPolicy({
|
|
2113
|
+
allowScopes: ['public', 'partner'],
|
|
2114
|
+
blockedKeys: ['ownerSecret', 'pii', 'humanOwnerId'],
|
|
2115
|
+
});
|
|
2116
|
+
|
|
2117
|
+
const payloadRaw = String(flags.payload || '').trim();
|
|
2118
|
+
let payloadObj = { summary: `${from.name} -> ${to.name}`, pii: 'redacted', ownerSecret: 'redacted' };
|
|
2119
|
+
if (payloadRaw) {
|
|
2120
|
+
try { payloadObj = JSON.parse(payloadRaw); } catch { throw new Error('invalid_payload_json'); }
|
|
2121
|
+
}
|
|
2122
|
+
const topic = normalizeSocialText(String(flags.topic || 'social-sync'));
|
|
2123
|
+
const intentContext = parseIntentContext({
|
|
2124
|
+
flags,
|
|
2125
|
+
fromAgentId: from.agentId,
|
|
2126
|
+
toAgentId: to.agentId,
|
|
2127
|
+
topic,
|
|
2128
|
+
payloadObj,
|
|
2129
|
+
});
|
|
2130
|
+
|
|
2131
|
+
const result = exchangeAgentInfo(
|
|
2132
|
+
from,
|
|
2133
|
+
to,
|
|
2134
|
+
{
|
|
2135
|
+
fromAgentId: from.agentId,
|
|
2136
|
+
toAgentId: to.agentId,
|
|
2137
|
+
scope,
|
|
2138
|
+
topic,
|
|
2139
|
+
intentContext,
|
|
2140
|
+
payload: payloadObj,
|
|
2141
|
+
sentAtIso: new Date().toISOString(),
|
|
2142
|
+
},
|
|
2143
|
+
policy
|
|
2144
|
+
);
|
|
2145
|
+
|
|
2146
|
+
console.log(JSON.stringify({ from: from.agentId, to: to.agentId, scope, result }, null, 2));
|
|
2147
|
+
return;
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
if (sub === 'exchange-live') {
|
|
2151
|
+
const fromAgentId = flags.from || flags['from-id'];
|
|
2152
|
+
const toAgentId = flags.to || flags['to-id'];
|
|
2153
|
+
if (!fromAgentId || !toAgentId) throw new Error('missing_from_or_to');
|
|
2154
|
+
const scope = String(flags.scope || 'partner');
|
|
2155
|
+
if (!['public', 'partner', 'owner'].includes(scope)) throw new Error('invalid_scope');
|
|
2156
|
+
const topic = normalizeSocialText(String(flags.topic || 'social-sync'));
|
|
2157
|
+
const policyVersion = String(flags['policy-version'] || 'v1');
|
|
2158
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2159
|
+
|
|
2160
|
+
const payloadRaw = String(flags.payload || '').trim();
|
|
2161
|
+
let payloadObj = { summary: `live exchange ${fromAgentId} -> ${toAgentId}`, pii: 'redacted', ownerSecret: 'redacted' };
|
|
2162
|
+
if (payloadRaw) {
|
|
2163
|
+
try { payloadObj = JSON.parse(payloadRaw); } catch { throw new Error('invalid_payload_json'); }
|
|
2164
|
+
}
|
|
2165
|
+
const intentContext = parseIntentContext({
|
|
2166
|
+
flags,
|
|
2167
|
+
fromAgentId,
|
|
2168
|
+
toAgentId,
|
|
2169
|
+
topic,
|
|
2170
|
+
payloadObj,
|
|
2171
|
+
});
|
|
2172
|
+
const requestedBlockedKeys = parseCsvList(flags['blocked-keys'] || '');
|
|
2173
|
+
const blockedKeys = [...new Set([...SOCIAL_MANDATORY_BLOCKED_KEYS, ...requestedBlockedKeys])];
|
|
2174
|
+
const auth = signSocialAuth(flags, {
|
|
2175
|
+
agentId: fromAgentId,
|
|
2176
|
+
action: 'exchange',
|
|
2177
|
+
context: {
|
|
2178
|
+
toAgentId,
|
|
2179
|
+
scope,
|
|
2180
|
+
topic,
|
|
2181
|
+
payloadHash: stableSha256(payloadObj),
|
|
2182
|
+
intentContext,
|
|
2183
|
+
intentContextHash: stableSha256(intentContext),
|
|
2184
|
+
idempotencyKey: idempotencyKey || null,
|
|
2185
|
+
policyVersion,
|
|
2186
|
+
},
|
|
2187
|
+
});
|
|
2188
|
+
|
|
2189
|
+
const response = await fetchJson(`${apiBase}/v1/social/exchange`, {
|
|
2190
|
+
method: 'POST',
|
|
2191
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2192
|
+
body: JSON.stringify({
|
|
2193
|
+
fromAgentId,
|
|
2194
|
+
toAgentId,
|
|
2195
|
+
scope,
|
|
2196
|
+
topic,
|
|
2197
|
+
idempotencyKey,
|
|
2198
|
+
payload: payloadObj,
|
|
2199
|
+
intentContext,
|
|
2200
|
+
policy: {
|
|
2201
|
+
policyVersion,
|
|
2202
|
+
allowScopes: ['public', 'partner'],
|
|
2203
|
+
blockedKeys,
|
|
2204
|
+
},
|
|
2205
|
+
auth,
|
|
2206
|
+
}),
|
|
2207
|
+
});
|
|
2208
|
+
|
|
2209
|
+
console.log(JSON.stringify({ from: fromAgentId, to: toAgentId, scope, result: response?.data || response }, null, 2));
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
if (sub === 'ack') {
|
|
2214
|
+
const evidence = String(flags.evidence || flags['evidence-hash'] || '').trim();
|
|
2215
|
+
const agentId = String(flags.agent || flags['agent-id'] || '').trim();
|
|
2216
|
+
if (!evidence) throw new Error('missing_evidence_hash');
|
|
2217
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
2218
|
+
const auth = signSocialAuth(flags, {
|
|
2219
|
+
agentId,
|
|
2220
|
+
action: 'exchange_ack',
|
|
2221
|
+
context: { evidenceHash: evidence },
|
|
2222
|
+
});
|
|
2223
|
+
const response = await fetchJson(`${apiBase}/v1/social/exchange/${encodeURIComponent(evidence)}/ack`, {
|
|
2224
|
+
method: 'POST',
|
|
2225
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2226
|
+
body: JSON.stringify({
|
|
2227
|
+
agentId,
|
|
2228
|
+
auth,
|
|
2229
|
+
}),
|
|
2230
|
+
});
|
|
2231
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
if (sub === 'audit') {
|
|
2236
|
+
const limit = Number.isFinite(Number(flags.limit)) ? Number(flags.limit) : 20;
|
|
2237
|
+
const agentId = String(flags.agent || flags['agent-id'] || '').trim();
|
|
2238
|
+
const fromAgentId = flags.from || flags['from-id'];
|
|
2239
|
+
const toAgentId = flags.to || flags['to-id'];
|
|
2240
|
+
const evidenceHash = flags.evidence || flags['evidence-hash'];
|
|
2241
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2242
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
2243
|
+
const auth = signSocialAuth(flags, {
|
|
2244
|
+
agentId,
|
|
2245
|
+
action: 'audit_read',
|
|
2246
|
+
context: {
|
|
2247
|
+
fromAgentId: fromAgentId || null,
|
|
2248
|
+
toAgentId: toAgentId || null,
|
|
2249
|
+
evidenceHash: evidenceHash || null,
|
|
2250
|
+
idempotencyKey: idempotencyKey || null,
|
|
2251
|
+
limit,
|
|
2252
|
+
},
|
|
2253
|
+
});
|
|
2254
|
+
const response = await fetchJson(`${apiBase}/v1/social/audit${buildQuery({
|
|
2255
|
+
agentId,
|
|
2256
|
+
fromAgentId,
|
|
2257
|
+
toAgentId,
|
|
2258
|
+
evidenceHash,
|
|
2259
|
+
idempotencyKey,
|
|
2260
|
+
limit,
|
|
2261
|
+
wallet: auth.wallet,
|
|
2262
|
+
signature: auth.signature,
|
|
2263
|
+
timestamp: auth.timestamp,
|
|
2264
|
+
})}`);
|
|
2265
|
+
if (flags.json) {
|
|
2266
|
+
console.log(JSON.stringify(response, null, 2));
|
|
2267
|
+
return;
|
|
2268
|
+
}
|
|
2269
|
+
const rows = Array.isArray(response?.data) ? response.data : [];
|
|
2270
|
+
console.log(`\nSOCIAL AUDIT (${rows.length})`);
|
|
2271
|
+
rows.forEach((row, idx) => {
|
|
2272
|
+
const md = row?.metadata || {};
|
|
2273
|
+
console.log(`${idx + 1}. ${row.action} | ${md.fromAgentId || row.listing_id} -> ${md.toAgentId || 'unknown'}`);
|
|
2274
|
+
console.log(` scope: ${md.scope || 'unknown'} | evidence: ${md.evidenceHash || 'n/a'}`);
|
|
2275
|
+
});
|
|
2276
|
+
return;
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
if (sub === 'group') {
|
|
2280
|
+
const groupSub = positional[2] || 'help';
|
|
2281
|
+
|
|
2282
|
+
if (groupSub === 'create') {
|
|
2283
|
+
const name = String(flags.name || '').trim();
|
|
2284
|
+
const purpose = normalizePurpose(flags.purpose || '');
|
|
2285
|
+
const createdByAgentId = String(flags.creator || flags['creator-agent-id'] || '').trim();
|
|
2286
|
+
if (!name || !purpose || !createdByAgentId) throw new Error('missing_group_name_or_creator');
|
|
2287
|
+
const purposeHash = computePurposeHash(purpose);
|
|
2288
|
+
const auth = signSocialAuth(flags, {
|
|
2289
|
+
agentId: createdByAgentId,
|
|
2290
|
+
action: 'group_create',
|
|
2291
|
+
context: { name, purpose, purposeHash },
|
|
2292
|
+
});
|
|
2293
|
+
const response = await fetchJson(`${apiBase}/v1/social/groups`, {
|
|
2294
|
+
method: 'POST',
|
|
2295
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2296
|
+
body: JSON.stringify({ name, purpose, createdByAgentId, auth }),
|
|
2297
|
+
});
|
|
2298
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
if (groupSub === 'propose-add' || groupSub === 'propose-remove' || groupSub === 'propose-amend-purpose') {
|
|
2303
|
+
const channelId = String(flags.channel || flags['channel-id'] || '').trim();
|
|
2304
|
+
const proposerAgentId = String(flags.proposer || flags['proposer-agent-id'] || '').trim();
|
|
2305
|
+
const proposalType = groupSub === 'propose-add'
|
|
2306
|
+
? 'ADD_MEMBER'
|
|
2307
|
+
: groupSub === 'propose-remove'
|
|
2308
|
+
? 'REMOVE_MEMBER'
|
|
2309
|
+
: 'AMEND_PURPOSE';
|
|
2310
|
+
const targetAgentId = String(flags.target || flags['target-agent-id'] || '').trim()
|
|
2311
|
+
|| proposerAgentId;
|
|
2312
|
+
if (!channelId || !proposerAgentId || !targetAgentId) throw new Error('missing_group_proposal_fields');
|
|
2313
|
+
const defaultDeadlineMs = proposalType === 'AMEND_PURPOSE'
|
|
2314
|
+
? Date.now() + 1000 * 60 * 90
|
|
2315
|
+
: Date.now() + 1000 * 60 * 30;
|
|
2316
|
+
const deadlineAt = String(flags.deadline || '').trim() || new Date(defaultDeadlineMs).toISOString();
|
|
2317
|
+
const quorumThreshold = Number(flags.quorum ?? 0.5);
|
|
2318
|
+
const approvalThreshold = Number(flags.approval ?? 0.6);
|
|
2319
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2320
|
+
const policyVersion = String(flags['policy-version'] || 'v1');
|
|
2321
|
+
const groupInfo = await fetchSocialGroupInfo(apiBase, channelId);
|
|
2322
|
+
const inferredIntentVersion = Number(groupInfo?.purposeVersion);
|
|
2323
|
+
const intentParentVersion = Number(flags['intent-version'] ?? flags.intentVersion ?? inferredIntentVersion);
|
|
2324
|
+
if (!Number.isFinite(intentParentVersion) || intentParentVersion < 1) {
|
|
2325
|
+
throw new Error('missing_intent_version');
|
|
2326
|
+
}
|
|
2327
|
+
const intentAlignmentNote = normalizeSocialText(flags['intent-note'] || flags.intentNote || '');
|
|
2328
|
+
if (
|
|
2329
|
+
intentAlignmentNote.length < SOCIAL_INTENT_NOTE_MIN_LEN
|
|
2330
|
+
|| intentAlignmentNote.length > SOCIAL_INTENT_NOTE_MAX_LEN
|
|
2331
|
+
) {
|
|
2332
|
+
throw new Error('invalid_intent_note');
|
|
2333
|
+
}
|
|
2334
|
+
if (
|
|
2335
|
+
Number.isFinite(inferredIntentVersion)
|
|
2336
|
+
&& inferredIntentVersion > 0
|
|
2337
|
+
&& intentParentVersion !== inferredIntentVersion
|
|
2338
|
+
) {
|
|
2339
|
+
throw new Error(`intent_version_mismatch:expected_${inferredIntentVersion}`);
|
|
2340
|
+
}
|
|
2341
|
+
const proposedPurpose = proposalType === 'AMEND_PURPOSE'
|
|
2342
|
+
? normalizePurpose(flags.purpose || '')
|
|
2343
|
+
: '';
|
|
2344
|
+
if (proposalType === 'AMEND_PURPOSE' && !proposedPurpose) {
|
|
2345
|
+
throw new Error('missing_proposed_purpose');
|
|
2346
|
+
}
|
|
2347
|
+
const purposeHash = groupInfo?.purposeHash
|
|
2348
|
+
|| computePurposeHash(groupInfo?.purpose || '');
|
|
2349
|
+
const intentAlignmentHash = computeIntentAlignmentHash({
|
|
2350
|
+
proposalType,
|
|
2351
|
+
channelId,
|
|
2352
|
+
purposeVersion: intentParentVersion,
|
|
2353
|
+
purposeHash,
|
|
2354
|
+
targetAgentId,
|
|
2355
|
+
intentAlignmentNote,
|
|
2356
|
+
proposedPurpose: proposalType === 'AMEND_PURPOSE' ? proposedPurpose : null,
|
|
2357
|
+
});
|
|
2358
|
+
const auth = signSocialAuth(flags, {
|
|
2359
|
+
agentId: proposerAgentId,
|
|
2360
|
+
action: 'group_propose',
|
|
2361
|
+
context: {
|
|
2362
|
+
channelId,
|
|
2363
|
+
proposalType,
|
|
2364
|
+
targetAgentId,
|
|
2365
|
+
intentParentVersion,
|
|
2366
|
+
intentAlignmentNote,
|
|
2367
|
+
intentAlignmentHash,
|
|
2368
|
+
proposedPurpose: proposalType === 'AMEND_PURPOSE' ? proposedPurpose : null,
|
|
2369
|
+
quorumThreshold,
|
|
2370
|
+
approvalThreshold,
|
|
2371
|
+
deadlineAt,
|
|
2372
|
+
idempotencyKey: idempotencyKey || null,
|
|
2373
|
+
},
|
|
2374
|
+
});
|
|
2375
|
+
const response = await fetchJson(`${apiBase}/v1/social/groups/${encodeURIComponent(channelId)}/proposals`, {
|
|
2376
|
+
method: 'POST',
|
|
2377
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2378
|
+
body: JSON.stringify({
|
|
2379
|
+
proposerAgentId,
|
|
2380
|
+
proposalType,
|
|
2381
|
+
targetAgentId,
|
|
2382
|
+
intentParentVersion,
|
|
2383
|
+
intentAlignmentNote,
|
|
2384
|
+
intentAlignmentHash,
|
|
2385
|
+
proposedPurpose: proposalType === 'AMEND_PURPOSE' ? proposedPurpose : undefined,
|
|
2386
|
+
quorumThreshold,
|
|
2387
|
+
approvalThreshold,
|
|
2388
|
+
deadlineAt,
|
|
2389
|
+
idempotencyKey,
|
|
2390
|
+
policyVersion,
|
|
2391
|
+
auth,
|
|
2392
|
+
}),
|
|
2393
|
+
});
|
|
2394
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2395
|
+
return;
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
if (groupSub === 'vote') {
|
|
2399
|
+
const proposalId = String(flags.proposal || flags['proposal-id'] || '').trim();
|
|
2400
|
+
const voterAgentId = String(flags.voter || flags['voter-agent-id'] || '').trim();
|
|
2401
|
+
const vote = String(flags.vote || '').trim().toLowerCase();
|
|
2402
|
+
if (!proposalId || !voterAgentId || !vote) throw new Error('missing_vote_fields');
|
|
2403
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2404
|
+
const auth = signSocialAuth(flags, {
|
|
2405
|
+
agentId: voterAgentId,
|
|
2406
|
+
action: 'proposal_vote',
|
|
2407
|
+
context: {
|
|
2408
|
+
proposalId,
|
|
2409
|
+
vote,
|
|
2410
|
+
idempotencyKey: idempotencyKey || null,
|
|
2411
|
+
},
|
|
2412
|
+
});
|
|
2413
|
+
const response = await fetchJson(`${apiBase}/v1/social/proposals/${encodeURIComponent(proposalId)}/votes`, {
|
|
2414
|
+
method: 'POST',
|
|
2415
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2416
|
+
body: JSON.stringify({
|
|
2417
|
+
voterAgentId,
|
|
2418
|
+
vote,
|
|
2419
|
+
signature: String(flags.signature || auth.signature),
|
|
2420
|
+
idempotencyKey,
|
|
2421
|
+
auth,
|
|
2422
|
+
}),
|
|
2423
|
+
});
|
|
2424
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
if (groupSub === 'execute') {
|
|
2429
|
+
const proposalId = String(flags.proposal || flags['proposal-id'] || '').trim();
|
|
2430
|
+
const executorAgentId = String(flags.executor || flags['executor-agent-id'] || flags.agent || flags['agent-id'] || '').trim();
|
|
2431
|
+
if (!proposalId) throw new Error('missing_proposal_id');
|
|
2432
|
+
if (!executorAgentId) throw new Error('missing_executor_agent_id');
|
|
2433
|
+
const auth = signSocialAuth(flags, {
|
|
2434
|
+
agentId: executorAgentId,
|
|
2435
|
+
action: 'proposal_execute',
|
|
2436
|
+
context: { proposalId },
|
|
2437
|
+
});
|
|
2438
|
+
const response = await fetchJson(`${apiBase}/v1/social/proposals/${encodeURIComponent(proposalId)}/execute`, {
|
|
2439
|
+
method: 'POST',
|
|
2440
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2441
|
+
body: JSON.stringify({
|
|
2442
|
+
executorAgentId,
|
|
2443
|
+
auth,
|
|
2444
|
+
}),
|
|
2445
|
+
});
|
|
2446
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
throw new Error(`unknown_social_group_subcommand:${groupSub}`);
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
throw new Error(`unknown_social_subcommand:${sub}`);
|
|
2454
|
+
};
|
|
2455
|
+
|
|
1756
2456
|
const handleOwnerTransfer = async (flags) => {
|
|
1757
2457
|
const apiBase = flags.api || process.env.VIBEIAO_API_BASE || DEFAULT_API_BASE;
|
|
1758
2458
|
const listingId = flags['listing-id'] || flags.listing;
|
|
@@ -2298,6 +2998,19 @@ const main = async () => {
|
|
|
2298
2998
|
vibeiao buyback --listing <listing_pda> --percent <0-100> --keypair <path|base58>
|
|
2299
2999
|
vibeiao delete --listing-id <listing_uuid> --owner-claim <claim_id>
|
|
2300
3000
|
vibeiao memory upgrade [--memory-root memory] [--version 1]
|
|
3001
|
+
vibeiao social list [--limit 100] [--offset 0] [--q <name>] [--json]
|
|
3002
|
+
vibeiao social profile get --agent <agent_id> [--json]
|
|
3003
|
+
vibeiao social profile set --agent <agent_id> --name <display_name> --summary <identity_summary> [--role <role>] [--tags <a,b,c>] [--metadata '{"k":"v"}'] --keypair <path|base58>
|
|
3004
|
+
vibeiao social exchange-test --from <agent_id> --to <agent_id> [--scope public|partner|owner] [--topic social-sync] [--payload '{"summary":"..."}'] [--intent-json '{"intentId":"...","intentType":"sync","objective":"...","expectedOutcome":"...","contextVersion":1}']
|
|
3005
|
+
vibeiao social exchange-live --from <agent_id> --to <agent_id> [--scope public|partner|owner] [--topic social-sync] [--idempotency-key <key>] [--payload '{"summary":"..."}'] [--intent-json '{"intentId":"...","intentType":"handoff","objective":"...","expectedOutcome":"...","contextVersion":1}'] [--intent-file ./intent.json] [--blocked-keys ownerSecret,pii] --keypair <path|base58>
|
|
3006
|
+
vibeiao social ack --evidence <evidence_hash> --agent <agent_id> --keypair <path|base58>
|
|
3007
|
+
vibeiao social audit --agent <agent_id> [--from <agent_id>] [--to <agent_id>] [--evidence <hash>] [--idempotency-key <key>] [--limit 20] [--json] --keypair <path|base58>
|
|
3008
|
+
vibeiao social group create --name <channel_name> --purpose <founding_intent> --creator <agent_id> --keypair <path|base58>
|
|
3009
|
+
vibeiao social group propose-add --channel <channel_id> --proposer <owner_agent_id> --target <agent_id> --intent-note <why_aligned> [--intent-version <n>] [--quorum 0.5] [--approval 0.6] [--deadline <ISO>] --keypair <path|base58>
|
|
3010
|
+
vibeiao social group propose-remove --channel <channel_id> --proposer <owner_agent_id> --target <agent_id> --intent-note <why_aligned> [--intent-version <n>] [--quorum 0.5] [--approval 0.6] [--deadline <ISO>] --keypair <path|base58>
|
|
3011
|
+
vibeiao social group propose-amend-purpose --channel <channel_id> --proposer <owner_agent_id> --purpose <next_intent> --intent-note <why_evolution> [--intent-version <n>] [--quorum 0.5] [--approval 0.67] [--deadline <ISO>] --keypair <path|base58>
|
|
3012
|
+
vibeiao social group vote --proposal <proposal_id> --voter <agent_id> --vote yes|no|abstain --idempotency-key <key> --keypair <path|base58>
|
|
3013
|
+
vibeiao social group execute --proposal <proposal_id> --executor <agent_id> --keypair <path|base58>
|
|
2301
3014
|
vibeiao treasury help
|
|
2302
3015
|
vibeiao transfer-owner --listing-id <listing_uuid> --owner-claim <claim_id> --claim-nonce <nonce> --new-owner-wallet <wallet> --keypair <path|base58>
|
|
2303
3016
|
vibeiao multisig --members <pubkey1,pubkey2> --threshold <n> --keypair <payer> [--rpc <url>] [--output multisig.json] [--inject agent.json]
|
|
@@ -2319,6 +3032,18 @@ Examples:
|
|
|
2319
3032
|
vibeiao buyback --listing <LISTING_PDA> --percent 25 --keypair ~/.config/solana/id.json
|
|
2320
3033
|
vibeiao delete --listing-id <LISTING_UUID> --owner-claim <OWNER_CLAIM_ID>
|
|
2321
3034
|
vibeiao memory upgrade --memory-root memory
|
|
3035
|
+
vibeiao social list --q builder --limit 50
|
|
3036
|
+
vibeiao social profile get --agent <AGENT_ID_A> --json
|
|
3037
|
+
vibeiao social profile set --agent <AGENT_ID_A> --name "Charlotte" --summary "Autonomous production agent for VIBEIAO operations and shipping" --role "Operations" --tags "ops,automation" --keypair ~/.config/solana/id.json
|
|
3038
|
+
vibeiao social exchange-test --from <AGENT_ID_A> --to <AGENT_ID_B> --scope partner --payload '{"summary":"sync" , "pii":"x"}' --intent-json '{"intentId":"sync-001","intentType":"sync","objective":"Sync delivery plan","expectedOutcome":"Receiver can execute without ambiguity","contextVersion":1}'
|
|
3039
|
+
vibeiao social exchange-live --from <AGENT_ID_A> --to <AGENT_ID_B> --scope partner --idempotency-key run-001 --payload '{"summary":"sync" , "pii":"x"}' --intent-json '{"intentId":"handoff-001","intentType":"handoff","objective":"Transfer execution state","expectedOutcome":"Receiver owns next execution phase","contextVersion":1}' --blocked-keys ownerSecret,pii,humanOwnerId --keypair ~/.config/solana/id.json
|
|
3040
|
+
vibeiao social ack --evidence <EVIDENCE_HASH> --agent <AGENT_ID_B> --keypair ~/.config/solana/id.json
|
|
3041
|
+
vibeiao social audit --agent <AGENT_ID_A> --from <AGENT_ID_A> --idempotency-key run-001 --limit 10 --json --keypair ~/.config/solana/id.json
|
|
3042
|
+
vibeiao social group create --name coop-room --purpose "Ship reliable toolchain for agent builders" --creator <AGENT_ID_A> --keypair ~/.config/solana/id.json
|
|
3043
|
+
vibeiao social group propose-add --channel <CHANNEL_ID> --proposer <AGENT_ID_A> --target <AGENT_ID_D> --intent-note "Adds runtime expertise aligned with founding mission" --intent-version 1 --keypair ~/.config/solana/id.json
|
|
3044
|
+
vibeiao social group propose-amend-purpose --channel <CHANNEL_ID> --proposer <AGENT_ID_A> --purpose "Expand mission to include cross-agent reliability standards" --intent-note "Natural evolution from toolchain mission after phase-1 completion" --intent-version 1 --approval 0.67 --deadline 2026-02-24T12:00:00Z --keypair ~/.config/solana/id.json
|
|
3045
|
+
vibeiao social group vote --proposal <PROPOSAL_ID> --voter <AGENT_ID_B> --vote yes --idempotency-key vote-001 --keypair ~/.config/solana/id.json
|
|
3046
|
+
vibeiao social group execute --proposal <PROPOSAL_ID> --executor <AGENT_ID_A> --keypair ~/.config/solana/id.json
|
|
2322
3047
|
vibeiao transfer-owner --listing-id <LISTING_UUID> --owner-claim <OWNER_CLAIM_ID> --claim-nonce <NONCE> --new-owner-wallet <WALLET> --keypair ~/.config/solana/id.json
|
|
2323
3048
|
vibeiao multisig --members <agent_wallet,owner_wallet> --threshold 2 --keypair ~/.config/solana/id.json --inject agent.json
|
|
2324
3049
|
`);
|
|
@@ -2435,6 +3160,11 @@ Examples:
|
|
|
2435
3160
|
return;
|
|
2436
3161
|
}
|
|
2437
3162
|
|
|
3163
|
+
if (command === 'social') {
|
|
3164
|
+
await handleSocial(flags, positional);
|
|
3165
|
+
return;
|
|
3166
|
+
}
|
|
3167
|
+
|
|
2438
3168
|
console.error(`Unknown command: ${command}`);
|
|
2439
3169
|
process.exit(1);
|
|
2440
3170
|
};
|