@awiki/cli 0.0.1-beta.2
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/.github/workflows/release.yml +44 -0
- package/.goreleaser.yml +44 -0
- package/AGENTS.md +60 -0
- package/CLAUDE.md +192 -0
- package/README.md +2 -0
- package/docs/architecture/awiki-command-v2.md +955 -0
- package/docs/architecture/awiki-skill-architecture.md +475 -0
- package/docs/architecture/awiki-v2-architecture.md +1063 -0
- package/docs/architecture//345/217/202/350/200/203/346/226/207/346/241/243/cli-init.md +1008 -0
- package/docs/architecture//345/217/202/350/200/203/346/226/207/346/241/243/output-format.md +407 -0
- package/docs/architecture//345/217/202/350/200/203/346/226/207/346/241/243/overall-init.md +741 -0
- package/docs/harness/review-spec.md +474 -0
- package/docs/installation.md +372 -0
- package/docs/plan/awiki-v2-implementation-plan.md +903 -0
- package/docs/plan/phase-0/adr-index.md +56 -0
- package/docs/plan/phase-0/audit-findings.md +251 -0
- package/docs/plan/phase-0/capability-mapping.md +108 -0
- package/docs/plan/phase-0/implementation-constraints.md +363 -0
- package/docs/publish.md +169 -0
- package/go.mod +29 -0
- package/go.sum +73 -0
- package/internal/anpsdk/registry.go +63 -0
- package/internal/authsdk/session.go +351 -0
- package/internal/buildinfo/buildinfo.go +34 -0
- package/internal/cli/app.go +136 -0
- package/internal/cli/app_test.go +88 -0
- package/internal/cli/debug.go +104 -0
- package/internal/cli/group.go +263 -0
- package/internal/cli/id.go +473 -0
- package/internal/cli/init.go +134 -0
- package/internal/cli/msg.go +228 -0
- package/internal/cli/page.go +267 -0
- package/internal/cli/root.go +499 -0
- package/internal/cli/runtime.go +232 -0
- package/internal/cli/upgrade.go +60 -0
- package/internal/cmdmeta/catalog.go +203 -0
- package/internal/cmdmeta/catalog_test.go +21 -0
- package/internal/config/config.go +399 -0
- package/internal/config/config_test.go +104 -0
- package/internal/config/write.go +37 -0
- package/internal/content/service.go +314 -0
- package/internal/content/service_test.go +165 -0
- package/internal/content/types.go +44 -0
- package/internal/docs/topics.go +110 -0
- package/internal/doctor/doctor.go +306 -0
- package/internal/identity/client.go +267 -0
- package/internal/identity/did.go +85 -0
- package/internal/identity/did_test.go +50 -0
- package/internal/identity/layout.go +206 -0
- package/internal/identity/legacy.go +378 -0
- package/internal/identity/public.go +70 -0
- package/internal/identity/public_test.go +73 -0
- package/internal/identity/readiness.go +74 -0
- package/internal/identity/service.go +826 -0
- package/internal/identity/store.go +385 -0
- package/internal/identity/store_test.go +180 -0
- package/internal/identity/types.go +204 -0
- package/internal/message/auth.go +167 -0
- package/internal/message/group_service.go +838 -0
- package/internal/message/group_wire.go +350 -0
- package/internal/message/group_wire_test.go +67 -0
- package/internal/message/helpers.go +61 -0
- package/internal/message/http_client.go +334 -0
- package/internal/message/proof.go +156 -0
- package/internal/message/proof_test.go +61 -0
- package/internal/message/service.go +696 -0
- package/internal/message/service_test.go +97 -0
- package/internal/message/types.go +155 -0
- package/internal/message/wire.go +100 -0
- package/internal/message/wire_test.go +49 -0
- package/internal/message/ws_proxy_client.go +151 -0
- package/internal/output/output.go +350 -0
- package/internal/output/output_test.go +48 -0
- package/internal/runtime/config.go +117 -0
- package/internal/runtime/config_test.go +46 -0
- package/internal/runtime/listener/files.go +65 -0
- package/internal/runtime/listener/manager.go +142 -0
- package/internal/runtime/listener/server.go +983 -0
- package/internal/runtime/listener/server_test.go +319 -0
- package/internal/runtime/listener/sysproc_unix.go +17 -0
- package/internal/runtime/listener/sysproc_windows.go +13 -0
- package/internal/runtime/listener/types.go +21 -0
- package/internal/runtime/listener/wsclient.go +299 -0
- package/internal/runtime/listener/wsclient_test.go +41 -0
- package/internal/store/dao.go +632 -0
- package/internal/store/dao_test.go +87 -0
- package/internal/store/helpers.go +197 -0
- package/internal/store/import.go +499 -0
- package/internal/store/import_test.go +103 -0
- package/internal/store/open.go +71 -0
- package/internal/store/query.go +151 -0
- package/internal/store/schema.go +277 -0
- package/internal/store/schema_test.go +56 -0
- package/internal/store/types.go +177 -0
- package/internal/update/update.go +368 -0
- package/package.json +17 -0
- package/scripts/install.js +171 -0
- package/scripts/release/release-prerelease.sh +86 -0
- package/scripts/release/tag-release.sh +66 -0
- package/scripts/release/withdraw-release.sh +78 -0
- package/scripts/run.js +69 -0
- package/skills/README.md +32 -0
- package/skills/awiki-bundle/SKILL.md +76 -0
- package/skills/awiki-debug/SKILL.md +80 -0
- package/skills/awiki-group/SKILL.md +111 -0
- package/skills/awiki-id/SKILL.md +123 -0
- package/skills/awiki-msg/SKILL.md +131 -0
- package/skills/awiki-page/SKILL.md +93 -0
- package/skills/awiki-people/SKILL.md +66 -0
- package/skills/awiki-runtime/SKILL.md +137 -0
- package/skills/awiki-shared/SKILL.md +124 -0
- package/skills/awiki-workflow-discovery/SKILL.md +93 -0
- package/skills/awiki-workflow-onboarding/SKILL.md +119 -0
- package/skills/manifests/skills.yaml +260 -0
- package/skills/templates/bundle-skill-template.md +42 -0
- package/skills/templates/debug-skill-template.md +44 -0
- package/skills/templates/domain-skill-template.md +56 -0
- package/skills/templates/shared-skill-template.md +46 -0
- package/skills/templates/workflow-skill-template.md +46 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
package message
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"strings"
|
|
6
|
+
"time"
|
|
7
|
+
|
|
8
|
+
"github.com/agentconnect/awiki-cli/internal/identity"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
func BuildGroupCreateRPCParams(record *identity.StoredIdentity, manager *identity.Manager, serviceDID string, request GroupCreateRequest) (map[string]any, error) {
|
|
12
|
+
if strings.TrimSpace(serviceDID) == "" {
|
|
13
|
+
return nil, fmt.Errorf("message service did is required")
|
|
14
|
+
}
|
|
15
|
+
auth, err := newAuthContext(record, manager)
|
|
16
|
+
if err != nil {
|
|
17
|
+
return nil, err
|
|
18
|
+
}
|
|
19
|
+
profile := buildGroupProfilePatch(request.Name, request.Description, request.Discoverability, request.Slug, request.Goal, request.Rules, request.MessagePrompt, request.DocURL)
|
|
20
|
+
policy := buildGroupPolicyPatch(request.AdmissionMode, request.AttachmentsAllowed, request.MaxMembers, request.MemberMaxMessages, request.MemberMaxTotalChars)
|
|
21
|
+
if _, ok := profile["display_name"]; !ok {
|
|
22
|
+
return nil, fmt.Errorf("group display name is required")
|
|
23
|
+
}
|
|
24
|
+
if len(policy) == 0 {
|
|
25
|
+
policy = buildGroupPolicyPatch("open-join", boolPtr(true), "500", nil, nil)
|
|
26
|
+
}
|
|
27
|
+
meta := map[string]any{
|
|
28
|
+
"anp_version": "1.0",
|
|
29
|
+
"profile": "anp.group.base.v1",
|
|
30
|
+
"security_profile": "transport-protected",
|
|
31
|
+
"sender_did": record.DID,
|
|
32
|
+
"target": map[string]any{
|
|
33
|
+
"kind": "service",
|
|
34
|
+
"did": serviceDID,
|
|
35
|
+
},
|
|
36
|
+
"operation_id": "op-" + generateOperationID(),
|
|
37
|
+
"created_at": nowRFC3339(),
|
|
38
|
+
"content_type": "application/json",
|
|
39
|
+
}
|
|
40
|
+
body := map[string]any{
|
|
41
|
+
"group_profile": profile,
|
|
42
|
+
"group_policy": policy,
|
|
43
|
+
}
|
|
44
|
+
payload := signedPayload{Method: "group.create", Meta: meta, Body: body}
|
|
45
|
+
actorProof, err := buildActorProof(auth, payload, "anp://service/"+strictPercentEncode(serviceDID)+"/group.create")
|
|
46
|
+
if err != nil {
|
|
47
|
+
return nil, err
|
|
48
|
+
}
|
|
49
|
+
return map[string]any{
|
|
50
|
+
"meta": meta,
|
|
51
|
+
"auth": map[string]any{"scheme": OriginProofScheme, "actor_proof": actorProof},
|
|
52
|
+
"body": body,
|
|
53
|
+
}, nil
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func BuildGroupGetInfoRPCParams(record *identity.StoredIdentity, request GroupInfoRequest) (map[string]any, error) {
|
|
57
|
+
groupDID := strings.TrimSpace(request.Group)
|
|
58
|
+
if groupDID == "" {
|
|
59
|
+
return nil, ErrGroupRequired
|
|
60
|
+
}
|
|
61
|
+
body := map[string]any{}
|
|
62
|
+
if request.IncludePolicy {
|
|
63
|
+
body["include_policy"] = true
|
|
64
|
+
}
|
|
65
|
+
if request.IncludeMemberList {
|
|
66
|
+
body["include_member_list"] = true
|
|
67
|
+
}
|
|
68
|
+
return map[string]any{
|
|
69
|
+
"meta": map[string]any{
|
|
70
|
+
"anp_version": "1.0",
|
|
71
|
+
"profile": "anp.group.base.v1",
|
|
72
|
+
"security_profile": "transport-protected",
|
|
73
|
+
"sender_did": record.DID,
|
|
74
|
+
"target": map[string]any{
|
|
75
|
+
"kind": "group",
|
|
76
|
+
"did": groupDID,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
"body": body,
|
|
80
|
+
}, nil
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func BuildGroupJoinRPCParams(record *identity.StoredIdentity, manager *identity.Manager, request GroupJoinRequest) (map[string]any, error) {
|
|
84
|
+
body := map[string]any{}
|
|
85
|
+
if reason := strings.TrimSpace(request.ReasonText); reason != "" {
|
|
86
|
+
body["reason_text"] = reason
|
|
87
|
+
}
|
|
88
|
+
return buildGroupMutationRPCParams(record, manager, request.Group, "group.join", body)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func BuildGroupAddRPCParams(record *identity.StoredIdentity, manager *identity.Manager, request GroupMemberRequest) (map[string]any, error) {
|
|
92
|
+
memberDID := strings.TrimSpace(request.Member)
|
|
93
|
+
if memberDID == "" {
|
|
94
|
+
return nil, ErrMemberRequired
|
|
95
|
+
}
|
|
96
|
+
body := map[string]any{"member_did": memberDID}
|
|
97
|
+
if role := strings.TrimSpace(request.Role); role != "" {
|
|
98
|
+
body["role"] = role
|
|
99
|
+
}
|
|
100
|
+
if reason := strings.TrimSpace(request.ReasonText); reason != "" {
|
|
101
|
+
body["reason_text"] = reason
|
|
102
|
+
}
|
|
103
|
+
return buildGroupMutationRPCParams(record, manager, request.Group, "group.add", body)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
func BuildGroupRemoveRPCParams(record *identity.StoredIdentity, manager *identity.Manager, request GroupMemberRequest) (map[string]any, error) {
|
|
107
|
+
memberDID := strings.TrimSpace(request.Member)
|
|
108
|
+
if memberDID == "" {
|
|
109
|
+
return nil, ErrMemberRequired
|
|
110
|
+
}
|
|
111
|
+
body := map[string]any{"member_did": memberDID}
|
|
112
|
+
if reason := strings.TrimSpace(request.ReasonText); reason != "" {
|
|
113
|
+
body["reason_text"] = reason
|
|
114
|
+
}
|
|
115
|
+
return buildGroupMutationRPCParams(record, manager, request.Group, "group.remove", body)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func BuildGroupLeaveRPCParams(record *identity.StoredIdentity, manager *identity.Manager, request GroupLeaveRequest) (map[string]any, error) {
|
|
119
|
+
return buildGroupMutationRPCParams(record, manager, request.Group, "group.leave", map[string]any{})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func BuildGroupUpdateProfileRPCParams(record *identity.StoredIdentity, manager *identity.Manager, groupDID string, patch map[string]any) (map[string]any, error) {
|
|
123
|
+
if len(patch) == 0 {
|
|
124
|
+
return nil, fmt.Errorf("group profile patch is required")
|
|
125
|
+
}
|
|
126
|
+
return buildGroupMutationRPCParams(record, manager, groupDID, "group.update_profile", map[string]any{"group_profile_patch": patch})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func BuildGroupUpdatePolicyRPCParams(record *identity.StoredIdentity, manager *identity.Manager, groupDID string, patch map[string]any) (map[string]any, error) {
|
|
130
|
+
if len(patch) == 0 {
|
|
131
|
+
return nil, fmt.Errorf("group policy patch is required")
|
|
132
|
+
}
|
|
133
|
+
return buildGroupMutationRPCParams(record, manager, groupDID, "group.update_policy", map[string]any{"group_policy_patch": patch})
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
func BuildGroupSendRPCParams(record *identity.StoredIdentity, manager *identity.Manager, groupDID string, text string, messageType string) (map[string]any, error) {
|
|
137
|
+
if strings.TrimSpace(groupDID) == "" {
|
|
138
|
+
return nil, ErrGroupRequired
|
|
139
|
+
}
|
|
140
|
+
if strings.TrimSpace(text) == "" {
|
|
141
|
+
return nil, ErrTextRequired
|
|
142
|
+
}
|
|
143
|
+
auth, err := newAuthContext(record, manager)
|
|
144
|
+
if err != nil {
|
|
145
|
+
return nil, err
|
|
146
|
+
}
|
|
147
|
+
contentType := contentTypeForMessageType(messageType)
|
|
148
|
+
meta := map[string]any{
|
|
149
|
+
"anp_version": "1.0",
|
|
150
|
+
"profile": "anp.group.base.v1",
|
|
151
|
+
"security_profile": "transport-protected",
|
|
152
|
+
"sender_did": record.DID,
|
|
153
|
+
"target": map[string]any{
|
|
154
|
+
"kind": "group",
|
|
155
|
+
"did": groupDID,
|
|
156
|
+
},
|
|
157
|
+
"operation_id": "op-" + generateOperationID(),
|
|
158
|
+
"message_id": "msg-" + generateOperationID(),
|
|
159
|
+
"created_at": time.Now().UTC().Format(time.RFC3339),
|
|
160
|
+
"content_type": contentType,
|
|
161
|
+
}
|
|
162
|
+
body := map[string]any{"text": text}
|
|
163
|
+
payload := signedPayload{Method: "group.send", Meta: meta, Body: body}
|
|
164
|
+
actorProof, err := buildActorProof(auth, payload, "anp://group/"+strictPercentEncode(groupDID))
|
|
165
|
+
if err != nil {
|
|
166
|
+
return nil, err
|
|
167
|
+
}
|
|
168
|
+
return map[string]any{
|
|
169
|
+
"meta": meta,
|
|
170
|
+
"auth": map[string]any{"scheme": OriginProofScheme, "actor_proof": actorProof},
|
|
171
|
+
"body": body,
|
|
172
|
+
}, nil
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
func BuildGroupGetRPCParams(record *identity.StoredIdentity, request GroupGetRequest) (map[string]any, error) {
|
|
176
|
+
groupDID := strings.TrimSpace(request.Group)
|
|
177
|
+
if groupDID == "" {
|
|
178
|
+
return nil, ErrGroupRequired
|
|
179
|
+
}
|
|
180
|
+
return map[string]any{
|
|
181
|
+
"meta": map[string]any{
|
|
182
|
+
"anp_version": "1.0",
|
|
183
|
+
"profile": "anp.group.local.v1",
|
|
184
|
+
"security_profile": "transport-protected",
|
|
185
|
+
"sender_did": record.DID,
|
|
186
|
+
"target": map[string]any{
|
|
187
|
+
"kind": "group",
|
|
188
|
+
"did": groupDID,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
"body": map[string]any{"group_did": groupDID},
|
|
192
|
+
}, nil
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
func BuildGroupMembersRPCParams(record *identity.StoredIdentity, request GroupMembersRequest) (map[string]any, error) {
|
|
196
|
+
groupDID := strings.TrimSpace(request.Group)
|
|
197
|
+
if groupDID == "" {
|
|
198
|
+
return nil, ErrGroupRequired
|
|
199
|
+
}
|
|
200
|
+
limit := request.Limit
|
|
201
|
+
if limit <= 0 {
|
|
202
|
+
limit = 100
|
|
203
|
+
}
|
|
204
|
+
return map[string]any{
|
|
205
|
+
"meta": map[string]any{
|
|
206
|
+
"anp_version": "1.0",
|
|
207
|
+
"profile": "anp.group.local.v1",
|
|
208
|
+
"security_profile": "transport-protected",
|
|
209
|
+
"sender_did": record.DID,
|
|
210
|
+
"target": map[string]any{
|
|
211
|
+
"kind": "group",
|
|
212
|
+
"did": groupDID,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
"body": map[string]any{"group_did": groupDID, "limit": limit},
|
|
216
|
+
}, nil
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
func BuildGroupMessagesRPCParams(record *identity.StoredIdentity, request GroupMessagesRequest) (map[string]any, error) {
|
|
220
|
+
groupDID := strings.TrimSpace(request.Group)
|
|
221
|
+
if groupDID == "" {
|
|
222
|
+
return nil, ErrGroupRequired
|
|
223
|
+
}
|
|
224
|
+
limit := request.Limit
|
|
225
|
+
if limit <= 0 {
|
|
226
|
+
limit = 50
|
|
227
|
+
}
|
|
228
|
+
body := map[string]any{"group_did": groupDID, "limit": limit}
|
|
229
|
+
if cursor := strings.TrimSpace(request.Cursor); cursor != "" {
|
|
230
|
+
body["since_seq"] = cursor
|
|
231
|
+
}
|
|
232
|
+
return map[string]any{
|
|
233
|
+
"meta": map[string]any{
|
|
234
|
+
"anp_version": "1.0",
|
|
235
|
+
"profile": "anp.group.local.v1",
|
|
236
|
+
"security_profile": "transport-protected",
|
|
237
|
+
"sender_did": record.DID,
|
|
238
|
+
"target": map[string]any{
|
|
239
|
+
"kind": "group",
|
|
240
|
+
"did": groupDID,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
"body": body,
|
|
244
|
+
}, nil
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
func buildGroupMutationRPCParams(record *identity.StoredIdentity, manager *identity.Manager, groupDID string, method string, body map[string]any) (map[string]any, error) {
|
|
248
|
+
groupDID = strings.TrimSpace(groupDID)
|
|
249
|
+
if groupDID == "" {
|
|
250
|
+
return nil, ErrGroupRequired
|
|
251
|
+
}
|
|
252
|
+
auth, err := newAuthContext(record, manager)
|
|
253
|
+
if err != nil {
|
|
254
|
+
return nil, err
|
|
255
|
+
}
|
|
256
|
+
meta := map[string]any{
|
|
257
|
+
"anp_version": "1.0",
|
|
258
|
+
"profile": "anp.group.base.v1",
|
|
259
|
+
"security_profile": "transport-protected",
|
|
260
|
+
"sender_did": record.DID,
|
|
261
|
+
"target": map[string]any{
|
|
262
|
+
"kind": "group",
|
|
263
|
+
"did": groupDID,
|
|
264
|
+
},
|
|
265
|
+
"operation_id": "op-" + generateOperationID(),
|
|
266
|
+
"created_at": nowRFC3339(),
|
|
267
|
+
"content_type": "application/json",
|
|
268
|
+
}
|
|
269
|
+
payload := signedPayload{Method: method, Meta: meta, Body: body}
|
|
270
|
+
actorProof, err := buildActorProof(auth, payload, "anp://group/"+strictPercentEncode(groupDID))
|
|
271
|
+
if err != nil {
|
|
272
|
+
return nil, err
|
|
273
|
+
}
|
|
274
|
+
return map[string]any{
|
|
275
|
+
"meta": meta,
|
|
276
|
+
"auth": map[string]any{"scheme": OriginProofScheme, "actor_proof": actorProof},
|
|
277
|
+
"body": body,
|
|
278
|
+
}, nil
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
func buildGroupProfilePatch(name string, description string, discoverability string, slug string, goal string, rules string, messagePrompt string, docURL string) map[string]any {
|
|
282
|
+
patch := map[string]any{}
|
|
283
|
+
if value := strings.TrimSpace(name); value != "" {
|
|
284
|
+
patch["display_name"] = value
|
|
285
|
+
}
|
|
286
|
+
if value := strings.TrimSpace(description); value != "" {
|
|
287
|
+
patch["description"] = value
|
|
288
|
+
}
|
|
289
|
+
if value := strings.TrimSpace(discoverability); value != "" {
|
|
290
|
+
patch["discoverability"] = value
|
|
291
|
+
}
|
|
292
|
+
if value := strings.TrimSpace(slug); value != "" {
|
|
293
|
+
patch["slug"] = value
|
|
294
|
+
}
|
|
295
|
+
if value := strings.TrimSpace(goal); value != "" {
|
|
296
|
+
patch["goal"] = value
|
|
297
|
+
}
|
|
298
|
+
if value := strings.TrimSpace(rules); value != "" {
|
|
299
|
+
patch["rules"] = value
|
|
300
|
+
}
|
|
301
|
+
if value := strings.TrimSpace(messagePrompt); value != "" {
|
|
302
|
+
patch["message_prompt"] = value
|
|
303
|
+
}
|
|
304
|
+
if value := strings.TrimSpace(docURL); value != "" {
|
|
305
|
+
patch["doc_url"] = value
|
|
306
|
+
}
|
|
307
|
+
return patch
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
func buildGroupPolicyPatch(admissionMode string, attachmentsAllowed *bool, maxMembers string, memberMaxMessages *int64, memberMaxTotalChars *int64) map[string]any {
|
|
311
|
+
patch := map[string]any{}
|
|
312
|
+
if value := strings.TrimSpace(admissionMode); value != "" {
|
|
313
|
+
patch["admission_mode"] = value
|
|
314
|
+
}
|
|
315
|
+
if attachmentsAllowed != nil {
|
|
316
|
+
patch["attachments_allowed"] = *attachmentsAllowed
|
|
317
|
+
}
|
|
318
|
+
if value := strings.TrimSpace(maxMembers); value != "" {
|
|
319
|
+
patch["max_members"] = value
|
|
320
|
+
}
|
|
321
|
+
if memberMaxMessages != nil {
|
|
322
|
+
patch["member_max_messages"] = *memberMaxMessages
|
|
323
|
+
}
|
|
324
|
+
if memberMaxTotalChars != nil {
|
|
325
|
+
patch["member_max_total_chars"] = *memberMaxTotalChars
|
|
326
|
+
}
|
|
327
|
+
if len(patch) == 0 {
|
|
328
|
+
return patch
|
|
329
|
+
}
|
|
330
|
+
if _, ok := patch["message_security_profile"]; !ok {
|
|
331
|
+
patch["message_security_profile"] = "transport-protected"
|
|
332
|
+
}
|
|
333
|
+
if _, ok := patch["bootstrap_security_profile"]; !ok {
|
|
334
|
+
patch["bootstrap_security_profile"] = "transport-protected"
|
|
335
|
+
}
|
|
336
|
+
if _, ok := patch["permissions"]; !ok {
|
|
337
|
+
patch["permissions"] = map[string]any{
|
|
338
|
+
"send": "member",
|
|
339
|
+
"add": "admin",
|
|
340
|
+
"remove": "admin",
|
|
341
|
+
"update_profile": "admin",
|
|
342
|
+
"update_policy": "owner",
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return patch
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
func boolPtr(value bool) *bool {
|
|
349
|
+
return &value
|
|
350
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package message
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"testing"
|
|
5
|
+
|
|
6
|
+
"github.com/agentconnect/awiki-cli/internal/identity"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
func TestBuildGroupCreateRPCParamsUsesActorProofAndServiceTarget(t *testing.T) {
|
|
10
|
+
t.Parallel()
|
|
11
|
+
|
|
12
|
+
generated, err := identity.GenerateIdentity(identity.GenerateOptions{
|
|
13
|
+
Hostname: "awiki.ai",
|
|
14
|
+
PathPrefix: []string{"user"},
|
|
15
|
+
ProofDomain: "awiki.ai",
|
|
16
|
+
})
|
|
17
|
+
if err != nil {
|
|
18
|
+
t.Fatalf("GenerateIdentity() error = %v", err)
|
|
19
|
+
}
|
|
20
|
+
record := &identity.StoredIdentity{
|
|
21
|
+
IdentityName: "alice",
|
|
22
|
+
DID: generated.DID,
|
|
23
|
+
DIDDocument: generated.DIDDocument,
|
|
24
|
+
Key1PrivatePEM: generated.Key1PrivatePEM,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
params, err := BuildGroupCreateRPCParams(record, nil, "did:wba:awiki.ai:services:message:e1_local", GroupCreateRequest{Name: "Protocol Review"})
|
|
28
|
+
if err != nil {
|
|
29
|
+
t.Fatalf("BuildGroupCreateRPCParams() error = %v", err)
|
|
30
|
+
}
|
|
31
|
+
auth, ok := params["auth"].(map[string]any)
|
|
32
|
+
if !ok {
|
|
33
|
+
t.Fatalf("params[auth] = %#v, want map", params["auth"])
|
|
34
|
+
}
|
|
35
|
+
if got := stringFromAny(auth["scheme"]); got != OriginProofScheme {
|
|
36
|
+
t.Fatalf("auth.scheme = %q, want %q", got, OriginProofScheme)
|
|
37
|
+
}
|
|
38
|
+
meta, ok := params["meta"].(map[string]any)
|
|
39
|
+
if !ok {
|
|
40
|
+
t.Fatalf("params[meta] = %#v, want map", params["meta"])
|
|
41
|
+
}
|
|
42
|
+
target, ok := meta["target"].(map[string]any)
|
|
43
|
+
if !ok {
|
|
44
|
+
t.Fatalf("meta[target] = %#v, want map", meta["target"])
|
|
45
|
+
}
|
|
46
|
+
if got := stringFromAny(target["kind"]); got != "service" {
|
|
47
|
+
t.Fatalf("meta.target.kind = %q, want service", got)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func TestBuildGroupMessagesRPCParamsUsesLocalProfile(t *testing.T) {
|
|
52
|
+
t.Parallel()
|
|
53
|
+
|
|
54
|
+
record := &identity.StoredIdentity{DID: "did:wba:awiki.ai:user:alice:e1_alice"}
|
|
55
|
+
params, err := BuildGroupMessagesRPCParams(record, GroupMessagesRequest{Group: "did:wba:awiki.ai:groups:demo:e1_group", Limit: 25, Cursor: "12"})
|
|
56
|
+
if err != nil {
|
|
57
|
+
t.Fatalf("BuildGroupMessagesRPCParams() error = %v", err)
|
|
58
|
+
}
|
|
59
|
+
meta, _ := params["meta"].(map[string]any)
|
|
60
|
+
if got := stringFromAny(meta["profile"]); got != "anp.group.local.v1" {
|
|
61
|
+
t.Fatalf("meta.profile = %q, want anp.group.local.v1", got)
|
|
62
|
+
}
|
|
63
|
+
body, _ := params["body"].(map[string]any)
|
|
64
|
+
if got := stringFromAny(body["since_seq"]); got != "12" {
|
|
65
|
+
t.Fatalf("body.since_seq = %q, want 12", got)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
package message
|
|
2
|
+
|
|
3
|
+
import "strings"
|
|
4
|
+
|
|
5
|
+
func stringFromAny(value any) string {
|
|
6
|
+
text, _ := value.(string)
|
|
7
|
+
return text
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
func boolFromAny(value any) bool {
|
|
11
|
+
switch typed := value.(type) {
|
|
12
|
+
case bool:
|
|
13
|
+
return typed
|
|
14
|
+
case int:
|
|
15
|
+
return typed != 0
|
|
16
|
+
case int64:
|
|
17
|
+
return typed != 0
|
|
18
|
+
case float64:
|
|
19
|
+
return typed != 0
|
|
20
|
+
case string:
|
|
21
|
+
return typed == "1" || strings.EqualFold(typed, "true")
|
|
22
|
+
default:
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func int64PtrFromAny(value any) *int64 {
|
|
28
|
+
switch typed := value.(type) {
|
|
29
|
+
case int64:
|
|
30
|
+
value := typed
|
|
31
|
+
return &value
|
|
32
|
+
case int:
|
|
33
|
+
value := int64(typed)
|
|
34
|
+
return &value
|
|
35
|
+
case float64:
|
|
36
|
+
value := int64(typed)
|
|
37
|
+
return &value
|
|
38
|
+
default:
|
|
39
|
+
return nil
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func intValueFromAny(value any, fallback int) int {
|
|
44
|
+
switch typed := value.(type) {
|
|
45
|
+
case int:
|
|
46
|
+
return typed
|
|
47
|
+
case int64:
|
|
48
|
+
return int(typed)
|
|
49
|
+
case float64:
|
|
50
|
+
return int(typed)
|
|
51
|
+
default:
|
|
52
|
+
return fallback
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func defaultString(value string, fallback string) string {
|
|
57
|
+
if strings.TrimSpace(value) == "" {
|
|
58
|
+
return fallback
|
|
59
|
+
}
|
|
60
|
+
return value
|
|
61
|
+
}
|