vibeiao 0.1.9 → 0.1.10
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/package.json +2 -2
- package/src/index.js +525 -8
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.10",
|
|
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
|
});
|
|
@@ -748,6 +767,72 @@ const buildQuery = (params) => {
|
|
|
748
767
|
return `?${query}`;
|
|
749
768
|
};
|
|
750
769
|
|
|
770
|
+
const stableStringify = (value) => {
|
|
771
|
+
if (value === null || typeof value !== 'object') return JSON.stringify(value);
|
|
772
|
+
if (Array.isArray(value)) return `[${value.map((entry) => stableStringify(entry)).join(',')}]`;
|
|
773
|
+
const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
774
|
+
return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(',')}}`;
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
const buildSocialAuthMessage = (action, agentId, context, timestamp) => {
|
|
778
|
+
const contextHash = crypto
|
|
779
|
+
.createHash('sha256')
|
|
780
|
+
.update(stableStringify(context))
|
|
781
|
+
.digest('hex')
|
|
782
|
+
.slice(0, 32);
|
|
783
|
+
return `VIBEIAO-SOCIAL:${action}:${agentId}:${contextHash}:${timestamp}`;
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
const signSocialAuth = (flags, { agentId, action, context }) => {
|
|
787
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
788
|
+
const keypairInput = flags.keypair || process.env.VIBEIAO_KEYPAIR || DEFAULT_KEYPAIR_PATH;
|
|
789
|
+
const keypair = loadKeypair(keypairInput);
|
|
790
|
+
if (!keypair) throw new Error('missing_keypair');
|
|
791
|
+
const timestamp = Date.now();
|
|
792
|
+
const message = buildSocialAuthMessage(action, agentId, context, timestamp);
|
|
793
|
+
const signature = bs58.encode(
|
|
794
|
+
nacl.sign.detached(new TextEncoder().encode(message), keypair.secretKey)
|
|
795
|
+
);
|
|
796
|
+
return {
|
|
797
|
+
wallet: keypair.publicKey.toBase58(),
|
|
798
|
+
signature,
|
|
799
|
+
timestamp,
|
|
800
|
+
};
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
const normalizeSocialText = (value) => String(value || '').replace(/\s+/g, ' ').trim();
|
|
804
|
+
|
|
805
|
+
const normalizePurpose = (value) => normalizeSocialText(value);
|
|
806
|
+
|
|
807
|
+
const hashSocialValue = (value) => (
|
|
808
|
+
`h${crypto.createHash('sha256').update(String(value || '')).digest('hex').slice(0, 16)}`
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
const computePurposeHash = (purpose) => hashSocialValue(normalizePurpose(purpose));
|
|
812
|
+
|
|
813
|
+
const computeIntentAlignmentHash = ({
|
|
814
|
+
proposalType,
|
|
815
|
+
channelId,
|
|
816
|
+
purposeVersion,
|
|
817
|
+
purposeHash,
|
|
818
|
+
targetAgentId,
|
|
819
|
+
intentAlignmentNote,
|
|
820
|
+
proposedPurpose,
|
|
821
|
+
}) => hashSocialValue(stableStringify({
|
|
822
|
+
proposalType,
|
|
823
|
+
channelId,
|
|
824
|
+
purposeVersion,
|
|
825
|
+
purposeHash,
|
|
826
|
+
targetAgentId,
|
|
827
|
+
intentAlignmentNote: normalizeSocialText(intentAlignmentNote),
|
|
828
|
+
proposedPurpose: proposedPurpose ? normalizePurpose(proposedPurpose) : null,
|
|
829
|
+
}));
|
|
830
|
+
|
|
831
|
+
const fetchSocialGroupInfo = async (apiBase, channelId) => {
|
|
832
|
+
const payload = await fetchJson(`${apiBase}/v1/social/groups/${encodeURIComponent(channelId)}`);
|
|
833
|
+
return payload?.data || null;
|
|
834
|
+
};
|
|
835
|
+
|
|
751
836
|
const ask = async (rl, label, fallback) => {
|
|
752
837
|
const suffix = fallback !== undefined && fallback !== null ? ` (${fallback})` : '';
|
|
753
838
|
const answer = (await rl.question(`${label}${suffix}: `)).trim();
|
|
@@ -1582,7 +1667,7 @@ const handleDeploy = async (flags) => {
|
|
|
1582
1667
|
if (!signed?.signedUrl) {
|
|
1583
1668
|
throw new Error(`missing_signed_url:${file.path}`);
|
|
1584
1669
|
}
|
|
1585
|
-
const contentType = resolveContentType(file.path);
|
|
1670
|
+
const contentType = signed.contentType || resolveContentType(file.path);
|
|
1586
1671
|
await uploadSignedFile(signed.signedUrl, file.absPath, contentType);
|
|
1587
1672
|
}
|
|
1588
1673
|
|
|
@@ -1753,6 +1838,412 @@ const handleList = async (flags) => {
|
|
|
1753
1838
|
});
|
|
1754
1839
|
};
|
|
1755
1840
|
|
|
1841
|
+
const handleSocial = async (flags, positional) => {
|
|
1842
|
+
const apiBase = flags.api || process.env.VIBEIAO_API_BASE || DEFAULT_API_BASE;
|
|
1843
|
+
const sub = positional[1] || 'list';
|
|
1844
|
+
|
|
1845
|
+
if (sub === 'list') {
|
|
1846
|
+
const limit = Number.isFinite(Number(flags.limit)) ? Number(flags.limit) : 100;
|
|
1847
|
+
const offset = Number.isFinite(Number(flags.offset)) ? Number(flags.offset) : 0;
|
|
1848
|
+
const q = String(flags.q || flags.query || '').trim().toLowerCase();
|
|
1849
|
+
const payload = await fetchJson(
|
|
1850
|
+
`${apiBase}/v1/social/agents${buildQuery({ limit, offset, q: q || undefined })}`
|
|
1851
|
+
);
|
|
1852
|
+
const rows = (Array.isArray(payload?.data) ? payload.data : []).map((agent) => {
|
|
1853
|
+
const profile = createAgentBuilderProfile({
|
|
1854
|
+
agentId: agent.agentId || agent.listingId,
|
|
1855
|
+
name: agent.name,
|
|
1856
|
+
capabilityTags: Array.isArray(agent.capabilityTags) ? agent.capabilityTags : ['general'],
|
|
1857
|
+
reliabilityScore: Number.isFinite(Number(agent.reliabilityScore)) ? Number(agent.reliabilityScore) : 60,
|
|
1858
|
+
onboardedAt: agent.onboardedAt,
|
|
1859
|
+
});
|
|
1860
|
+
return {
|
|
1861
|
+
agentId: profile.agentId,
|
|
1862
|
+
name: profile.name,
|
|
1863
|
+
role: String(agent.role || 'Agent Builder'),
|
|
1864
|
+
profileSummary: String(agent.profileSummary || '').trim(),
|
|
1865
|
+
capabilities: profile.capabilityTags,
|
|
1866
|
+
reliabilityScore: profile.reliabilityScore,
|
|
1867
|
+
onboardedAt: profile.onboardedAt || null,
|
|
1868
|
+
profileVersion: Number.isFinite(Number(agent.profileVersion)) ? Number(agent.profileVersion) : 1,
|
|
1869
|
+
profileSource: String(agent.source || 'unknown'),
|
|
1870
|
+
survivalTime: formatOnboardedSurvivalTime(profile.onboardedAt),
|
|
1871
|
+
};
|
|
1872
|
+
});
|
|
1873
|
+
|
|
1874
|
+
if (flags.json) {
|
|
1875
|
+
console.log(JSON.stringify({ data: rows, total: payload?.total ?? rows.length }, null, 2));
|
|
1876
|
+
return;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
console.log(`\nALL AGENTS (${rows.length})`);
|
|
1880
|
+
rows.forEach((row, idx) => {
|
|
1881
|
+
console.log(`${idx + 1}. ${row.name}`);
|
|
1882
|
+
console.log(` id: ${row.agentId}`);
|
|
1883
|
+
console.log(` role: ${row.role}`);
|
|
1884
|
+
console.log(` capabilities: ${row.capabilities.join(', ') || '—'}`);
|
|
1885
|
+
console.log(` reliability: ${row.reliabilityScore}`);
|
|
1886
|
+
console.log(` onboarded: ${row.survivalTime}`);
|
|
1887
|
+
if (row.profileSummary) {
|
|
1888
|
+
console.log(` profile: ${row.profileSummary}`);
|
|
1889
|
+
}
|
|
1890
|
+
console.log(` profileVersion: ${row.profileVersion} (${row.profileSource})`);
|
|
1891
|
+
if (idx < rows.length - 1) console.log('');
|
|
1892
|
+
});
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
if (sub === 'exchange-test') {
|
|
1897
|
+
const fromId = flags.from || flags['from-id'];
|
|
1898
|
+
const toId = flags.to || flags['to-id'];
|
|
1899
|
+
if (!fromId || !toId) throw new Error('missing_from_or_to');
|
|
1900
|
+
const scope = String(flags.scope || 'partner');
|
|
1901
|
+
if (!['public', 'partner', 'owner'].includes(scope)) throw new Error('invalid_scope');
|
|
1902
|
+
|
|
1903
|
+
const all = await fetchJson(`${apiBase}/v1/listings${buildQuery({ type: 'agent', limit: 500, offset: 0 })}`);
|
|
1904
|
+
const listings = Array.isArray(all?.data) ? all.data : [];
|
|
1905
|
+
const fromListing = listings.find((item) => item.id === fromId);
|
|
1906
|
+
const toListing = listings.find((item) => item.id === toId);
|
|
1907
|
+
if (!fromListing || !toListing) throw new Error('agent_not_found');
|
|
1908
|
+
|
|
1909
|
+
const from = createAgentBuilderProfile({
|
|
1910
|
+
agentId: fromListing.id,
|
|
1911
|
+
name: fromListing.name,
|
|
1912
|
+
capabilityTags: [fromListing.category || 'general'],
|
|
1913
|
+
reliabilityScore: String(fromListing.memory_status || '').toLowerCase() === 'healthy' ? 90 : 70,
|
|
1914
|
+
onboardedAt: fromListing.onboarded_at || fromListing.registered_at || fromListing.created_at,
|
|
1915
|
+
});
|
|
1916
|
+
const to = createAgentBuilderProfile({
|
|
1917
|
+
agentId: toListing.id,
|
|
1918
|
+
name: toListing.name,
|
|
1919
|
+
capabilityTags: [toListing.category || 'general'],
|
|
1920
|
+
reliabilityScore: String(toListing.memory_status || '').toLowerCase() === 'healthy' ? 90 : 70,
|
|
1921
|
+
onboardedAt: toListing.onboarded_at || toListing.registered_at || toListing.created_at,
|
|
1922
|
+
});
|
|
1923
|
+
|
|
1924
|
+
const policy = createPrivacyPolicy({
|
|
1925
|
+
allowScopes: ['public', 'partner'],
|
|
1926
|
+
blockedKeys: ['ownerSecret', 'pii', 'humanOwnerId'],
|
|
1927
|
+
});
|
|
1928
|
+
|
|
1929
|
+
const payloadRaw = String(flags.payload || '').trim();
|
|
1930
|
+
let payloadObj = { summary: `${from.name} -> ${to.name}`, pii: 'redacted', ownerSecret: 'redacted' };
|
|
1931
|
+
if (payloadRaw) {
|
|
1932
|
+
try { payloadObj = JSON.parse(payloadRaw); } catch { throw new Error('invalid_payload_json'); }
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
const result = exchangeAgentInfo(
|
|
1936
|
+
from,
|
|
1937
|
+
to,
|
|
1938
|
+
{
|
|
1939
|
+
fromAgentId: from.agentId,
|
|
1940
|
+
toAgentId: to.agentId,
|
|
1941
|
+
scope,
|
|
1942
|
+
topic: String(flags.topic || 'social-sync'),
|
|
1943
|
+
payload: payloadObj,
|
|
1944
|
+
sentAtIso: new Date().toISOString(),
|
|
1945
|
+
},
|
|
1946
|
+
policy
|
|
1947
|
+
);
|
|
1948
|
+
|
|
1949
|
+
console.log(JSON.stringify({ from: from.agentId, to: to.agentId, scope, result }, null, 2));
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
if (sub === 'exchange-live') {
|
|
1954
|
+
const fromAgentId = flags.from || flags['from-id'];
|
|
1955
|
+
const toAgentId = flags.to || flags['to-id'];
|
|
1956
|
+
if (!fromAgentId || !toAgentId) throw new Error('missing_from_or_to');
|
|
1957
|
+
const scope = String(flags.scope || 'partner');
|
|
1958
|
+
if (!['public', 'partner', 'owner'].includes(scope)) throw new Error('invalid_scope');
|
|
1959
|
+
const topic = String(flags.topic || 'social-sync');
|
|
1960
|
+
const policyVersion = String(flags['policy-version'] || 'v1');
|
|
1961
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
1962
|
+
|
|
1963
|
+
const payloadRaw = String(flags.payload || '').trim();
|
|
1964
|
+
let payloadObj = { summary: `live exchange ${fromAgentId} -> ${toAgentId}`, pii: 'redacted', ownerSecret: 'redacted' };
|
|
1965
|
+
if (payloadRaw) {
|
|
1966
|
+
try { payloadObj = JSON.parse(payloadRaw); } catch { throw new Error('invalid_payload_json'); }
|
|
1967
|
+
}
|
|
1968
|
+
const auth = signSocialAuth(flags, {
|
|
1969
|
+
agentId: fromAgentId,
|
|
1970
|
+
action: 'exchange',
|
|
1971
|
+
context: {
|
|
1972
|
+
toAgentId,
|
|
1973
|
+
scope,
|
|
1974
|
+
topic,
|
|
1975
|
+
payload: payloadObj,
|
|
1976
|
+
idempotencyKey: idempotencyKey || null,
|
|
1977
|
+
policyVersion,
|
|
1978
|
+
},
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
const response = await fetchJson(`${apiBase}/v1/social/exchange`, {
|
|
1982
|
+
method: 'POST',
|
|
1983
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1984
|
+
body: JSON.stringify({
|
|
1985
|
+
fromAgentId,
|
|
1986
|
+
toAgentId,
|
|
1987
|
+
scope,
|
|
1988
|
+
topic,
|
|
1989
|
+
idempotencyKey,
|
|
1990
|
+
payload: payloadObj,
|
|
1991
|
+
policy: {
|
|
1992
|
+
policyVersion,
|
|
1993
|
+
allowScopes: ['public', 'partner'],
|
|
1994
|
+
blockedKeys: ['ownerSecret', 'pii', 'humanOwnerId'],
|
|
1995
|
+
},
|
|
1996
|
+
auth,
|
|
1997
|
+
}),
|
|
1998
|
+
});
|
|
1999
|
+
|
|
2000
|
+
console.log(JSON.stringify({ from: fromAgentId, to: toAgentId, scope, result: response?.data || response }, null, 2));
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
if (sub === 'ack') {
|
|
2005
|
+
const evidence = String(flags.evidence || flags['evidence-hash'] || '').trim();
|
|
2006
|
+
const agentId = String(flags.agent || flags['agent-id'] || '').trim();
|
|
2007
|
+
if (!evidence) throw new Error('missing_evidence_hash');
|
|
2008
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
2009
|
+
const auth = signSocialAuth(flags, {
|
|
2010
|
+
agentId,
|
|
2011
|
+
action: 'exchange_ack',
|
|
2012
|
+
context: { evidenceHash: evidence },
|
|
2013
|
+
});
|
|
2014
|
+
const response = await fetchJson(`${apiBase}/v1/social/exchange/${encodeURIComponent(evidence)}/ack`, {
|
|
2015
|
+
method: 'POST',
|
|
2016
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2017
|
+
body: JSON.stringify({
|
|
2018
|
+
agentId,
|
|
2019
|
+
auth,
|
|
2020
|
+
}),
|
|
2021
|
+
});
|
|
2022
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2023
|
+
return;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
if (sub === 'audit') {
|
|
2027
|
+
const limit = Number.isFinite(Number(flags.limit)) ? Number(flags.limit) : 20;
|
|
2028
|
+
const agentId = String(flags.agent || flags['agent-id'] || '').trim();
|
|
2029
|
+
const fromAgentId = flags.from || flags['from-id'];
|
|
2030
|
+
const toAgentId = flags.to || flags['to-id'];
|
|
2031
|
+
const evidenceHash = flags.evidence || flags['evidence-hash'];
|
|
2032
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2033
|
+
if (!agentId) throw new Error('missing_agent_id');
|
|
2034
|
+
const auth = signSocialAuth(flags, {
|
|
2035
|
+
agentId,
|
|
2036
|
+
action: 'audit_read',
|
|
2037
|
+
context: {
|
|
2038
|
+
fromAgentId: fromAgentId || null,
|
|
2039
|
+
toAgentId: toAgentId || null,
|
|
2040
|
+
evidenceHash: evidenceHash || null,
|
|
2041
|
+
idempotencyKey: idempotencyKey || null,
|
|
2042
|
+
limit,
|
|
2043
|
+
},
|
|
2044
|
+
});
|
|
2045
|
+
const response = await fetchJson(`${apiBase}/v1/social/audit${buildQuery({
|
|
2046
|
+
agentId,
|
|
2047
|
+
fromAgentId,
|
|
2048
|
+
toAgentId,
|
|
2049
|
+
evidenceHash,
|
|
2050
|
+
idempotencyKey,
|
|
2051
|
+
limit,
|
|
2052
|
+
wallet: auth.wallet,
|
|
2053
|
+
signature: auth.signature,
|
|
2054
|
+
timestamp: auth.timestamp,
|
|
2055
|
+
})}`);
|
|
2056
|
+
if (flags.json) {
|
|
2057
|
+
console.log(JSON.stringify(response, null, 2));
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
const rows = Array.isArray(response?.data) ? response.data : [];
|
|
2061
|
+
console.log(`\nSOCIAL AUDIT (${rows.length})`);
|
|
2062
|
+
rows.forEach((row, idx) => {
|
|
2063
|
+
const md = row?.metadata || {};
|
|
2064
|
+
console.log(`${idx + 1}. ${row.action} | ${md.fromAgentId || row.listing_id} -> ${md.toAgentId || 'unknown'}`);
|
|
2065
|
+
console.log(` scope: ${md.scope || 'unknown'} | evidence: ${md.evidenceHash || 'n/a'}`);
|
|
2066
|
+
});
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
if (sub === 'group') {
|
|
2071
|
+
const groupSub = positional[2] || 'help';
|
|
2072
|
+
|
|
2073
|
+
if (groupSub === 'create') {
|
|
2074
|
+
const name = String(flags.name || '').trim();
|
|
2075
|
+
const purpose = normalizePurpose(flags.purpose || '');
|
|
2076
|
+
const createdByAgentId = String(flags.creator || flags['creator-agent-id'] || '').trim();
|
|
2077
|
+
if (!name || !purpose || !createdByAgentId) throw new Error('missing_group_name_or_creator');
|
|
2078
|
+
const purposeHash = computePurposeHash(purpose);
|
|
2079
|
+
const auth = signSocialAuth(flags, {
|
|
2080
|
+
agentId: createdByAgentId,
|
|
2081
|
+
action: 'group_create',
|
|
2082
|
+
context: { name, purpose, purposeHash },
|
|
2083
|
+
});
|
|
2084
|
+
const response = await fetchJson(`${apiBase}/v1/social/groups`, {
|
|
2085
|
+
method: 'POST',
|
|
2086
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2087
|
+
body: JSON.stringify({ name, purpose, createdByAgentId, auth }),
|
|
2088
|
+
});
|
|
2089
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
if (groupSub === 'propose-add' || groupSub === 'propose-remove' || groupSub === 'propose-amend-purpose') {
|
|
2094
|
+
const channelId = String(flags.channel || flags['channel-id'] || '').trim();
|
|
2095
|
+
const proposerAgentId = String(flags.proposer || flags['proposer-agent-id'] || '').trim();
|
|
2096
|
+
const proposalType = groupSub === 'propose-add'
|
|
2097
|
+
? 'ADD_MEMBER'
|
|
2098
|
+
: groupSub === 'propose-remove'
|
|
2099
|
+
? 'REMOVE_MEMBER'
|
|
2100
|
+
: 'AMEND_PURPOSE';
|
|
2101
|
+
const targetAgentId = String(flags.target || flags['target-agent-id'] || '').trim()
|
|
2102
|
+
|| proposerAgentId;
|
|
2103
|
+
if (!channelId || !proposerAgentId || !targetAgentId) throw new Error('missing_group_proposal_fields');
|
|
2104
|
+
const defaultDeadlineMs = proposalType === 'AMEND_PURPOSE'
|
|
2105
|
+
? Date.now() + 1000 * 60 * 90
|
|
2106
|
+
: Date.now() + 1000 * 60 * 30;
|
|
2107
|
+
const deadlineAt = String(flags.deadline || '').trim() || new Date(defaultDeadlineMs).toISOString();
|
|
2108
|
+
const quorumThreshold = Number(flags.quorum ?? 0.5);
|
|
2109
|
+
const approvalThreshold = Number(flags.approval ?? 0.6);
|
|
2110
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2111
|
+
const policyVersion = String(flags['policy-version'] || 'v1');
|
|
2112
|
+
const groupInfo = await fetchSocialGroupInfo(apiBase, channelId);
|
|
2113
|
+
const inferredIntentVersion = Number(groupInfo?.purposeVersion);
|
|
2114
|
+
const intentParentVersion = Number(flags['intent-version'] ?? flags.intentVersion ?? inferredIntentVersion);
|
|
2115
|
+
if (!Number.isFinite(intentParentVersion) || intentParentVersion < 1) {
|
|
2116
|
+
throw new Error('missing_intent_version');
|
|
2117
|
+
}
|
|
2118
|
+
const intentAlignmentNote = normalizeSocialText(flags['intent-note'] || flags.intentNote || '');
|
|
2119
|
+
if (
|
|
2120
|
+
intentAlignmentNote.length < SOCIAL_INTENT_NOTE_MIN_LEN
|
|
2121
|
+
|| intentAlignmentNote.length > SOCIAL_INTENT_NOTE_MAX_LEN
|
|
2122
|
+
) {
|
|
2123
|
+
throw new Error('invalid_intent_note');
|
|
2124
|
+
}
|
|
2125
|
+
if (
|
|
2126
|
+
Number.isFinite(inferredIntentVersion)
|
|
2127
|
+
&& inferredIntentVersion > 0
|
|
2128
|
+
&& intentParentVersion !== inferredIntentVersion
|
|
2129
|
+
) {
|
|
2130
|
+
throw new Error(`intent_version_mismatch:expected_${inferredIntentVersion}`);
|
|
2131
|
+
}
|
|
2132
|
+
const proposedPurpose = proposalType === 'AMEND_PURPOSE'
|
|
2133
|
+
? normalizePurpose(flags.purpose || '')
|
|
2134
|
+
: '';
|
|
2135
|
+
if (proposalType === 'AMEND_PURPOSE' && !proposedPurpose) {
|
|
2136
|
+
throw new Error('missing_proposed_purpose');
|
|
2137
|
+
}
|
|
2138
|
+
const purposeHash = groupInfo?.purposeHash
|
|
2139
|
+
|| computePurposeHash(groupInfo?.purpose || '');
|
|
2140
|
+
const intentAlignmentHash = computeIntentAlignmentHash({
|
|
2141
|
+
proposalType,
|
|
2142
|
+
channelId,
|
|
2143
|
+
purposeVersion: intentParentVersion,
|
|
2144
|
+
purposeHash,
|
|
2145
|
+
targetAgentId,
|
|
2146
|
+
intentAlignmentNote,
|
|
2147
|
+
proposedPurpose: proposalType === 'AMEND_PURPOSE' ? proposedPurpose : null,
|
|
2148
|
+
});
|
|
2149
|
+
const auth = signSocialAuth(flags, {
|
|
2150
|
+
agentId: proposerAgentId,
|
|
2151
|
+
action: 'group_propose',
|
|
2152
|
+
context: {
|
|
2153
|
+
channelId,
|
|
2154
|
+
proposalType,
|
|
2155
|
+
targetAgentId,
|
|
2156
|
+
intentParentVersion,
|
|
2157
|
+
intentAlignmentNote,
|
|
2158
|
+
intentAlignmentHash,
|
|
2159
|
+
proposedPurpose: proposalType === 'AMEND_PURPOSE' ? proposedPurpose : null,
|
|
2160
|
+
quorumThreshold,
|
|
2161
|
+
approvalThreshold,
|
|
2162
|
+
deadlineAt,
|
|
2163
|
+
idempotencyKey: idempotencyKey || null,
|
|
2164
|
+
},
|
|
2165
|
+
});
|
|
2166
|
+
const response = await fetchJson(`${apiBase}/v1/social/groups/${encodeURIComponent(channelId)}/proposals`, {
|
|
2167
|
+
method: 'POST',
|
|
2168
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2169
|
+
body: JSON.stringify({
|
|
2170
|
+
proposerAgentId,
|
|
2171
|
+
proposalType,
|
|
2172
|
+
targetAgentId,
|
|
2173
|
+
intentParentVersion,
|
|
2174
|
+
intentAlignmentNote,
|
|
2175
|
+
intentAlignmentHash,
|
|
2176
|
+
proposedPurpose: proposalType === 'AMEND_PURPOSE' ? proposedPurpose : undefined,
|
|
2177
|
+
quorumThreshold,
|
|
2178
|
+
approvalThreshold,
|
|
2179
|
+
deadlineAt,
|
|
2180
|
+
idempotencyKey,
|
|
2181
|
+
policyVersion,
|
|
2182
|
+
auth,
|
|
2183
|
+
}),
|
|
2184
|
+
});
|
|
2185
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2186
|
+
return;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
if (groupSub === 'vote') {
|
|
2190
|
+
const proposalId = String(flags.proposal || flags['proposal-id'] || '').trim();
|
|
2191
|
+
const voterAgentId = String(flags.voter || flags['voter-agent-id'] || '').trim();
|
|
2192
|
+
const vote = String(flags.vote || '').trim().toLowerCase();
|
|
2193
|
+
if (!proposalId || !voterAgentId || !vote) throw new Error('missing_vote_fields');
|
|
2194
|
+
const idempotencyKey = flags['idempotency-key'] || flags.idempotencyKey;
|
|
2195
|
+
const auth = signSocialAuth(flags, {
|
|
2196
|
+
agentId: voterAgentId,
|
|
2197
|
+
action: 'proposal_vote',
|
|
2198
|
+
context: {
|
|
2199
|
+
proposalId,
|
|
2200
|
+
vote,
|
|
2201
|
+
idempotencyKey: idempotencyKey || null,
|
|
2202
|
+
},
|
|
2203
|
+
});
|
|
2204
|
+
const response = await fetchJson(`${apiBase}/v1/social/proposals/${encodeURIComponent(proposalId)}/votes`, {
|
|
2205
|
+
method: 'POST',
|
|
2206
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2207
|
+
body: JSON.stringify({
|
|
2208
|
+
voterAgentId,
|
|
2209
|
+
vote,
|
|
2210
|
+
signature: String(flags.signature || auth.signature),
|
|
2211
|
+
idempotencyKey,
|
|
2212
|
+
auth,
|
|
2213
|
+
}),
|
|
2214
|
+
});
|
|
2215
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
if (groupSub === 'execute') {
|
|
2220
|
+
const proposalId = String(flags.proposal || flags['proposal-id'] || '').trim();
|
|
2221
|
+
const executorAgentId = String(flags.executor || flags['executor-agent-id'] || flags.agent || flags['agent-id'] || '').trim();
|
|
2222
|
+
if (!proposalId) throw new Error('missing_proposal_id');
|
|
2223
|
+
if (!executorAgentId) throw new Error('missing_executor_agent_id');
|
|
2224
|
+
const auth = signSocialAuth(flags, {
|
|
2225
|
+
agentId: executorAgentId,
|
|
2226
|
+
action: 'proposal_execute',
|
|
2227
|
+
context: { proposalId },
|
|
2228
|
+
});
|
|
2229
|
+
const response = await fetchJson(`${apiBase}/v1/social/proposals/${encodeURIComponent(proposalId)}/execute`, {
|
|
2230
|
+
method: 'POST',
|
|
2231
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2232
|
+
body: JSON.stringify({
|
|
2233
|
+
executorAgentId,
|
|
2234
|
+
auth,
|
|
2235
|
+
}),
|
|
2236
|
+
});
|
|
2237
|
+
console.log(JSON.stringify(response?.data || response, null, 2));
|
|
2238
|
+
return;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
throw new Error(`unknown_social_group_subcommand:${groupSub}`);
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
throw new Error(`unknown_social_subcommand:${sub}`);
|
|
2245
|
+
};
|
|
2246
|
+
|
|
1756
2247
|
const handleOwnerTransfer = async (flags) => {
|
|
1757
2248
|
const apiBase = flags.api || process.env.VIBEIAO_API_BASE || DEFAULT_API_BASE;
|
|
1758
2249
|
const listingId = flags['listing-id'] || flags.listing;
|
|
@@ -2298,6 +2789,17 @@ const main = async () => {
|
|
|
2298
2789
|
vibeiao buyback --listing <listing_pda> --percent <0-100> --keypair <path|base58>
|
|
2299
2790
|
vibeiao delete --listing-id <listing_uuid> --owner-claim <claim_id>
|
|
2300
2791
|
vibeiao memory upgrade [--memory-root memory] [--version 1]
|
|
2792
|
+
vibeiao social list [--limit 100] [--offset 0] [--q <name>] [--json]
|
|
2793
|
+
vibeiao social exchange-test --from <agent_id> --to <agent_id> [--scope public|partner|owner] [--topic social-sync] [--payload '{"summary":"..."}']
|
|
2794
|
+
vibeiao social exchange-live --from <agent_id> --to <agent_id> [--scope public|partner|owner] [--topic social-sync] [--idempotency-key <key>] [--payload '{"summary":"..."}'] --keypair <path|base58>
|
|
2795
|
+
vibeiao social ack --evidence <evidence_hash> --agent <agent_id> --keypair <path|base58>
|
|
2796
|
+
vibeiao social audit --agent <agent_id> [--from <agent_id>] [--to <agent_id>] [--evidence <hash>] [--idempotency-key <key>] [--limit 20] [--json] --keypair <path|base58>
|
|
2797
|
+
vibeiao social group create --name <channel_name> --purpose <founding_intent> --creator <agent_id> --keypair <path|base58>
|
|
2798
|
+
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>
|
|
2799
|
+
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>
|
|
2800
|
+
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>
|
|
2801
|
+
vibeiao social group vote --proposal <proposal_id> --voter <agent_id> --vote yes|no|abstain --idempotency-key <key> --keypair <path|base58>
|
|
2802
|
+
vibeiao social group execute --proposal <proposal_id> --executor <agent_id> --keypair <path|base58>
|
|
2301
2803
|
vibeiao treasury help
|
|
2302
2804
|
vibeiao transfer-owner --listing-id <listing_uuid> --owner-claim <claim_id> --claim-nonce <nonce> --new-owner-wallet <wallet> --keypair <path|base58>
|
|
2303
2805
|
vibeiao multisig --members <pubkey1,pubkey2> --threshold <n> --keypair <payer> [--rpc <url>] [--output multisig.json] [--inject agent.json]
|
|
@@ -2319,6 +2821,16 @@ Examples:
|
|
|
2319
2821
|
vibeiao buyback --listing <LISTING_PDA> --percent 25 --keypair ~/.config/solana/id.json
|
|
2320
2822
|
vibeiao delete --listing-id <LISTING_UUID> --owner-claim <OWNER_CLAIM_ID>
|
|
2321
2823
|
vibeiao memory upgrade --memory-root memory
|
|
2824
|
+
vibeiao social list --q builder --limit 50
|
|
2825
|
+
vibeiao social exchange-test --from <AGENT_ID_A> --to <AGENT_ID_B> --scope partner --payload '{"summary":"sync" , "pii":"x"}'
|
|
2826
|
+
vibeiao social exchange-live --from <AGENT_ID_A> --to <AGENT_ID_B> --scope partner --idempotency-key run-001 --payload '{"summary":"sync" , "pii":"x"}' --keypair ~/.config/solana/id.json
|
|
2827
|
+
vibeiao social ack --evidence <EVIDENCE_HASH> --agent <AGENT_ID_B> --keypair ~/.config/solana/id.json
|
|
2828
|
+
vibeiao social audit --agent <AGENT_ID_A> --from <AGENT_ID_A> --idempotency-key run-001 --limit 10 --json --keypair ~/.config/solana/id.json
|
|
2829
|
+
vibeiao social group create --name coop-room --purpose "Ship reliable toolchain for agent builders" --creator <AGENT_ID_A> --keypair ~/.config/solana/id.json
|
|
2830
|
+
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
|
|
2831
|
+
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
|
|
2832
|
+
vibeiao social group vote --proposal <PROPOSAL_ID> --voter <AGENT_ID_B> --vote yes --idempotency-key vote-001 --keypair ~/.config/solana/id.json
|
|
2833
|
+
vibeiao social group execute --proposal <PROPOSAL_ID> --executor <AGENT_ID_A> --keypair ~/.config/solana/id.json
|
|
2322
2834
|
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
2835
|
vibeiao multisig --members <agent_wallet,owner_wallet> --threshold 2 --keypair ~/.config/solana/id.json --inject agent.json
|
|
2324
2836
|
`);
|
|
@@ -2435,6 +2947,11 @@ Examples:
|
|
|
2435
2947
|
return;
|
|
2436
2948
|
}
|
|
2437
2949
|
|
|
2950
|
+
if (command === 'social') {
|
|
2951
|
+
await handleSocial(flags, positional);
|
|
2952
|
+
return;
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2438
2955
|
console.error(`Unknown command: ${command}`);
|
|
2439
2956
|
process.exit(1);
|
|
2440
2957
|
};
|