@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.
Files changed (119) hide show
  1. package/.github/workflows/release.yml +44 -0
  2. package/.goreleaser.yml +44 -0
  3. package/AGENTS.md +60 -0
  4. package/CLAUDE.md +192 -0
  5. package/README.md +2 -0
  6. package/docs/architecture/awiki-command-v2.md +955 -0
  7. package/docs/architecture/awiki-skill-architecture.md +475 -0
  8. package/docs/architecture/awiki-v2-architecture.md +1063 -0
  9. package/docs/architecture//345/217/202/350/200/203/346/226/207/346/241/243/cli-init.md +1008 -0
  10. package/docs/architecture//345/217/202/350/200/203/346/226/207/346/241/243/output-format.md +407 -0
  11. package/docs/architecture//345/217/202/350/200/203/346/226/207/346/241/243/overall-init.md +741 -0
  12. package/docs/harness/review-spec.md +474 -0
  13. package/docs/installation.md +372 -0
  14. package/docs/plan/awiki-v2-implementation-plan.md +903 -0
  15. package/docs/plan/phase-0/adr-index.md +56 -0
  16. package/docs/plan/phase-0/audit-findings.md +251 -0
  17. package/docs/plan/phase-0/capability-mapping.md +108 -0
  18. package/docs/plan/phase-0/implementation-constraints.md +363 -0
  19. package/docs/publish.md +169 -0
  20. package/go.mod +29 -0
  21. package/go.sum +73 -0
  22. package/internal/anpsdk/registry.go +63 -0
  23. package/internal/authsdk/session.go +351 -0
  24. package/internal/buildinfo/buildinfo.go +34 -0
  25. package/internal/cli/app.go +136 -0
  26. package/internal/cli/app_test.go +88 -0
  27. package/internal/cli/debug.go +104 -0
  28. package/internal/cli/group.go +263 -0
  29. package/internal/cli/id.go +473 -0
  30. package/internal/cli/init.go +134 -0
  31. package/internal/cli/msg.go +228 -0
  32. package/internal/cli/page.go +267 -0
  33. package/internal/cli/root.go +499 -0
  34. package/internal/cli/runtime.go +232 -0
  35. package/internal/cli/upgrade.go +60 -0
  36. package/internal/cmdmeta/catalog.go +203 -0
  37. package/internal/cmdmeta/catalog_test.go +21 -0
  38. package/internal/config/config.go +399 -0
  39. package/internal/config/config_test.go +104 -0
  40. package/internal/config/write.go +37 -0
  41. package/internal/content/service.go +314 -0
  42. package/internal/content/service_test.go +165 -0
  43. package/internal/content/types.go +44 -0
  44. package/internal/docs/topics.go +110 -0
  45. package/internal/doctor/doctor.go +306 -0
  46. package/internal/identity/client.go +267 -0
  47. package/internal/identity/did.go +85 -0
  48. package/internal/identity/did_test.go +50 -0
  49. package/internal/identity/layout.go +206 -0
  50. package/internal/identity/legacy.go +378 -0
  51. package/internal/identity/public.go +70 -0
  52. package/internal/identity/public_test.go +73 -0
  53. package/internal/identity/readiness.go +74 -0
  54. package/internal/identity/service.go +826 -0
  55. package/internal/identity/store.go +385 -0
  56. package/internal/identity/store_test.go +180 -0
  57. package/internal/identity/types.go +204 -0
  58. package/internal/message/auth.go +167 -0
  59. package/internal/message/group_service.go +838 -0
  60. package/internal/message/group_wire.go +350 -0
  61. package/internal/message/group_wire_test.go +67 -0
  62. package/internal/message/helpers.go +61 -0
  63. package/internal/message/http_client.go +334 -0
  64. package/internal/message/proof.go +156 -0
  65. package/internal/message/proof_test.go +61 -0
  66. package/internal/message/service.go +696 -0
  67. package/internal/message/service_test.go +97 -0
  68. package/internal/message/types.go +155 -0
  69. package/internal/message/wire.go +100 -0
  70. package/internal/message/wire_test.go +49 -0
  71. package/internal/message/ws_proxy_client.go +151 -0
  72. package/internal/output/output.go +350 -0
  73. package/internal/output/output_test.go +48 -0
  74. package/internal/runtime/config.go +117 -0
  75. package/internal/runtime/config_test.go +46 -0
  76. package/internal/runtime/listener/files.go +65 -0
  77. package/internal/runtime/listener/manager.go +142 -0
  78. package/internal/runtime/listener/server.go +983 -0
  79. package/internal/runtime/listener/server_test.go +319 -0
  80. package/internal/runtime/listener/sysproc_unix.go +17 -0
  81. package/internal/runtime/listener/sysproc_windows.go +13 -0
  82. package/internal/runtime/listener/types.go +21 -0
  83. package/internal/runtime/listener/wsclient.go +299 -0
  84. package/internal/runtime/listener/wsclient_test.go +41 -0
  85. package/internal/store/dao.go +632 -0
  86. package/internal/store/dao_test.go +87 -0
  87. package/internal/store/helpers.go +197 -0
  88. package/internal/store/import.go +499 -0
  89. package/internal/store/import_test.go +103 -0
  90. package/internal/store/open.go +71 -0
  91. package/internal/store/query.go +151 -0
  92. package/internal/store/schema.go +277 -0
  93. package/internal/store/schema_test.go +56 -0
  94. package/internal/store/types.go +177 -0
  95. package/internal/update/update.go +368 -0
  96. package/package.json +17 -0
  97. package/scripts/install.js +171 -0
  98. package/scripts/release/release-prerelease.sh +86 -0
  99. package/scripts/release/tag-release.sh +66 -0
  100. package/scripts/release/withdraw-release.sh +78 -0
  101. package/scripts/run.js +69 -0
  102. package/skills/README.md +32 -0
  103. package/skills/awiki-bundle/SKILL.md +76 -0
  104. package/skills/awiki-debug/SKILL.md +80 -0
  105. package/skills/awiki-group/SKILL.md +111 -0
  106. package/skills/awiki-id/SKILL.md +123 -0
  107. package/skills/awiki-msg/SKILL.md +131 -0
  108. package/skills/awiki-page/SKILL.md +93 -0
  109. package/skills/awiki-people/SKILL.md +66 -0
  110. package/skills/awiki-runtime/SKILL.md +137 -0
  111. package/skills/awiki-shared/SKILL.md +124 -0
  112. package/skills/awiki-workflow-discovery/SKILL.md +93 -0
  113. package/skills/awiki-workflow-onboarding/SKILL.md +119 -0
  114. package/skills/manifests/skills.yaml +260 -0
  115. package/skills/templates/bundle-skill-template.md +42 -0
  116. package/skills/templates/debug-skill-template.md +44 -0
  117. package/skills/templates/domain-skill-template.md +56 -0
  118. package/skills/templates/shared-skill-template.md +46 -0
  119. package/skills/templates/workflow-skill-template.md +46 -0
@@ -0,0 +1,87 @@
1
+ package store
2
+
3
+ import (
4
+ "context"
5
+ "testing"
6
+ )
7
+
8
+ func TestStoreMessageAndThreadView(t *testing.T) {
9
+ t.Parallel()
10
+
11
+ db := openTestDB(t)
12
+ ctx := context.Background()
13
+ if err := EnsureSchema(ctx, db); err != nil {
14
+ t.Fatalf("EnsureSchema() error = %v", err)
15
+ }
16
+ if err := StoreMessage(ctx, db, MessageRecord{
17
+ MsgID: "msg-1",
18
+ OwnerDID: "did:wba:awiki.ai:user:a",
19
+ ThreadID: MakeThreadID("did:wba:awiki.ai:user:a", "did:wba:awiki.ai:user:b", ""),
20
+ Direction: 0,
21
+ SenderDID: "did:wba:awiki.ai:user:b",
22
+ ReceiverDID: "did:wba:awiki.ai:user:a",
23
+ ContentType: "text",
24
+ Content: "hello",
25
+ IsRead: false,
26
+ CredentialName: "default",
27
+ }); err != nil {
28
+ t.Fatalf("StoreMessage() error = %v", err)
29
+ }
30
+ got, err := GetMessageByID(ctx, db, "msg-1", "did:wba:awiki.ai:user:a", "")
31
+ if err != nil {
32
+ t.Fatalf("GetMessageByID() error = %v", err)
33
+ }
34
+ if got["content"] != "hello" {
35
+ t.Fatalf("unexpected message content: %#v", got)
36
+ }
37
+ rows, err := ExecuteSQL(ctx, db, "SELECT thread_id, unread_count FROM threads")
38
+ if err != nil {
39
+ t.Fatalf("ExecuteSQL() error = %v", err)
40
+ }
41
+ if len(rows) != 1 {
42
+ t.Fatalf("unexpected threads rows: %#v", rows)
43
+ }
44
+ }
45
+
46
+ func TestRebindOwnerDIDAndClearE2EEData(t *testing.T) {
47
+ t.Parallel()
48
+
49
+ db := openTestDB(t)
50
+ ctx := context.Background()
51
+ if err := EnsureSchema(ctx, db); err != nil {
52
+ t.Fatalf("EnsureSchema() error = %v", err)
53
+ }
54
+ if _, err := QueueE2EEOutbox(ctx, db, E2EEOutboxRecord{
55
+ OutboxID: "out-1",
56
+ OwnerDID: "did:old",
57
+ PeerDID: "did:peer",
58
+ Plaintext: "secret",
59
+ LocalStatus: "queued",
60
+ CredentialName: "default",
61
+ }); err != nil {
62
+ t.Fatalf("QueueE2EEOutbox() error = %v", err)
63
+ }
64
+ if _, err := db.ExecContext(ctx, `
65
+ INSERT INTO e2ee_sessions
66
+ (owner_did, peer_did, session_id, is_initiator, send_chain_key, recv_chain_key, send_seq, recv_seq, expires_at, created_at, active_at, peer_confirmed, credential_name, updated_at)
67
+ VALUES ('did:old', 'did:peer', 'sess-1', 1, 'send', 'recv', 0, 0, NULL, '2026-01-01T00:00:00Z', NULL, 0, 'default', '2026-01-01T00:00:00Z')`); err != nil {
68
+ t.Fatalf("insert e2ee session error = %v", err)
69
+ }
70
+ if err := UpsertContact(ctx, db, ContactRecord{OwnerDID: "did:old", DID: "did:peer", Name: "Peer"}); err != nil {
71
+ t.Fatalf("UpsertContact() error = %v", err)
72
+ }
73
+ result, err := RebindOwnerDID(ctx, db, "did:old", "did:new")
74
+ if err != nil {
75
+ t.Fatalf("RebindOwnerDID() error = %v", err)
76
+ }
77
+ if result["contacts"] != 1 {
78
+ t.Fatalf("unexpected rebind counts: %#v", result)
79
+ }
80
+ cleared, err := ClearOwnerE2EEData(ctx, db, "did:old")
81
+ if err != nil {
82
+ t.Fatalf("ClearOwnerE2EEData() error = %v", err)
83
+ }
84
+ if cleared["e2ee_outbox"] != 1 || cleared["e2ee_sessions"] != 1 {
85
+ t.Fatalf("unexpected clear result: %#v", cleared)
86
+ }
87
+ }
@@ -0,0 +1,197 @@
1
+ package store
2
+
3
+ import (
4
+ "context"
5
+ "database/sql"
6
+ "encoding/json"
7
+ "fmt"
8
+ "regexp"
9
+ "sort"
10
+ "strings"
11
+ "time"
12
+ )
13
+
14
+ var (
15
+ forbiddenPatterns = []*regexp.Regexp{
16
+ regexp.MustCompile(`\bDROP\b`),
17
+ regexp.MustCompile(`\bTRUNCATE\b`),
18
+ }
19
+ )
20
+
21
+ func nowUTC() string {
22
+ return time.Now().UTC().Format(time.RFC3339)
23
+ }
24
+
25
+ func MakeThreadID(myDID string, peerDID string, groupID string) string {
26
+ if strings.TrimSpace(groupID) != "" {
27
+ return fmt.Sprintf("group:%s", strings.TrimSpace(groupID))
28
+ }
29
+ if strings.TrimSpace(peerDID) != "" {
30
+ pair := []string{strings.TrimSpace(myDID), strings.TrimSpace(peerDID)}
31
+ sort.Strings(pair)
32
+ return fmt.Sprintf("dm:%s:%s", pair[0], pair[1])
33
+ }
34
+ return fmt.Sprintf("dm:%s:unknown", strings.TrimSpace(myDID))
35
+ }
36
+
37
+ func normalizeOwnerDID(value string) string {
38
+ return strings.TrimSpace(value)
39
+ }
40
+
41
+ func normalizeCredentialName(value string) string {
42
+ return strings.TrimSpace(value)
43
+ }
44
+
45
+ func normalizeOptionalString(value string) any {
46
+ value = strings.TrimSpace(value)
47
+ if value == "" {
48
+ return nil
49
+ }
50
+ return value
51
+ }
52
+
53
+ func normalizeOptionalBool(value *bool) any {
54
+ if value == nil {
55
+ return nil
56
+ }
57
+ if *value {
58
+ return 1
59
+ }
60
+ return 0
61
+ }
62
+
63
+ func normalizeOptionalInt64(value *int64) any {
64
+ if value == nil {
65
+ return nil
66
+ }
67
+ return *value
68
+ }
69
+
70
+ func normalizeOptionalFloat64(value *float64) any {
71
+ if value == nil {
72
+ return nil
73
+ }
74
+ return *value
75
+ }
76
+
77
+ func defaultInt64Ptr(value *int64, fallback *int64) *int64 {
78
+ if value != nil {
79
+ return value
80
+ }
81
+ return fallback
82
+ }
83
+
84
+ func normalizeMetadata(value string) any {
85
+ value = strings.TrimSpace(value)
86
+ if value == "" {
87
+ return nil
88
+ }
89
+ return value
90
+ }
91
+
92
+ func metadataFromAny(value any) string {
93
+ if value == nil {
94
+ return ""
95
+ }
96
+ switch typed := value.(type) {
97
+ case string:
98
+ return typed
99
+ default:
100
+ raw, err := json.Marshal(typed)
101
+ if err != nil {
102
+ return ""
103
+ }
104
+ return string(raw)
105
+ }
106
+ }
107
+
108
+ func queryMaps(ctx context.Context, db *sql.DB, query string, args ...any) ([]map[string]any, error) {
109
+ rows, err := db.QueryContext(ctx, query, args...)
110
+ if err != nil {
111
+ return nil, err
112
+ }
113
+ defer rows.Close()
114
+ columns, err := rows.Columns()
115
+ if err != nil {
116
+ return nil, err
117
+ }
118
+ results := make([]map[string]any, 0)
119
+ for rows.Next() {
120
+ values := make([]any, len(columns))
121
+ pointers := make([]any, len(columns))
122
+ for index := range values {
123
+ pointers[index] = &values[index]
124
+ }
125
+ if err := rows.Scan(pointers...); err != nil {
126
+ return nil, err
127
+ }
128
+ item := make(map[string]any, len(columns))
129
+ for index, column := range columns {
130
+ item[column] = convertSQLiteValue(values[index])
131
+ }
132
+ results = append(results, item)
133
+ }
134
+ return results, rows.Err()
135
+ }
136
+
137
+ func queryOneMap(ctx context.Context, db *sql.DB, query string, args ...any) (map[string]any, error) {
138
+ rows, err := queryMaps(ctx, db, query, args...)
139
+ if err != nil {
140
+ return nil, err
141
+ }
142
+ if len(rows) == 0 {
143
+ return nil, sql.ErrNoRows
144
+ }
145
+ return rows[0], nil
146
+ }
147
+
148
+ func convertSQLiteValue(value any) any {
149
+ switch typed := value.(type) {
150
+ case []byte:
151
+ return string(typed)
152
+ default:
153
+ return typed
154
+ }
155
+ }
156
+
157
+ func tableExists(ctx context.Context, db *sql.DB, tableName string) (bool, error) {
158
+ var exists int
159
+ row := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = ?", tableName)
160
+ if err := row.Scan(&exists); err != nil {
161
+ return false, err
162
+ }
163
+ return exists > 0, nil
164
+ }
165
+
166
+ func viewExists(ctx context.Context, db *sql.DB, viewName string) (bool, error) {
167
+ var exists int
168
+ row := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM sqlite_master WHERE type = 'view' AND name = ?", viewName)
169
+ if err := row.Scan(&exists); err != nil {
170
+ return false, err
171
+ }
172
+ return exists > 0, nil
173
+ }
174
+
175
+ func columnNames(ctx context.Context, db *sql.DB, tableName string) (map[string]struct{}, error) {
176
+ rows, err := queryMaps(ctx, db, fmt.Sprintf("PRAGMA table_info(%s)", tableName))
177
+ if err != nil {
178
+ return nil, err
179
+ }
180
+ columns := make(map[string]struct{}, len(rows))
181
+ for _, row := range rows {
182
+ name, _ := row["name"].(string)
183
+ if name != "" {
184
+ columns[name] = struct{}{}
185
+ }
186
+ }
187
+ return columns, nil
188
+ }
189
+
190
+ func schemaVersion(ctx context.Context, db *sql.DB) (int, error) {
191
+ var version int
192
+ row := db.QueryRowContext(ctx, "PRAGMA user_version")
193
+ if err := row.Scan(&version); err != nil {
194
+ return 0, err
195
+ }
196
+ return version, nil
197
+ }