@amityco/social-plus-vise 0.14.14 → 0.14.16

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/CHANGELOG.md CHANGED
@@ -4,6 +4,27 @@ All notable changes to `@amityco/social-plus-vise` are documented in this file.
4
4
 
5
5
  The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 0.14.16 — 2026-06-05
8
+
9
+ ### Changed
10
+ - **Android poll composer guidance:** feed-forward guidance now prefers Android's dedicated `createPollPost(targetType, targetId, pollId, ...)` API instead of the deprecated `createPost().poll(pollId)` builder path.
11
+ - **Repeatable host-agent smoke:** agent-flow coverage now creates an Android temp app and runs the full manual loop: design extract, plan question surfacing, answered init, validate, check, sync, and real Gradle sensor execution through a lightweight wrapper.
12
+
13
+ ### Fixed
14
+ - **Native optional post edit sensor:** selected `post-edit` now recognizes Android member-chain usage such as `newPostRepository().editPost(...)`.
15
+ - **Non-UI subscription precision:** `*.feed.ui-states-present` no longer treats Application-level setup/login subscriptions as feed collection rendering that needs loading/empty/error UI states.
16
+
17
+ ### Verified
18
+ - Focused capability/native-idiom tests and the expanded agent-flow smoke pass. The real `music-player-android` smoke app validates cleanly, checks green, and runs Android assemble/tests without the prior deprecated `createPost()` warning.
19
+
20
+ ## 0.14.15 — 2026-06-05
21
+
22
+ ### Fixed
23
+ - **Android Gradle catalog dependency detection:** `android.dependency.sdk` now recognizes `implementation(libs.amity.sdk)` when `gradle/libs.versions.toml` resolves the alias to `co.amity.android:amity-sdk`.
24
+
25
+ ### Verified
26
+ - Added a native-idiom regression fixture for Gradle version catalogs and confirmed the patched validator removes the false dependency warning in `music-player-android`.
27
+
7
28
  ## 0.14.14 — 2026-06-05
8
29
 
9
30
  ### Fixed
@@ -410,7 +410,7 @@ export const OPTIONAL_CAPABILITIES = [
410
410
  },
411
411
  { label: "PollRepository.votePoll", regex: /PollRepository\.votePoll\s*\(|(?<![\w])votePoll\s*\(/ },
412
412
  ],
413
- hint: "If the user opts into polls, implement the platform poll creation -> poll post linking chain, for example createPoll -> createPost({ data: { pollId } }) on TypeScript or createPost().poll(pollId) / createPollPost on native SDKs, plus the votePoll read-side interaction.",
413
+ hint: "If the user opts into polls, implement the platform poll creation -> poll post linking chain, for example createPoll -> createPost({ data: { pollId } }) on TypeScript or createPollPost(targetType, targetId, pollId, ...) on Android/native SDKs, plus the votePoll read-side interaction.",
414
414
  },
415
415
  {
416
416
  id: "post-edit",
@@ -421,7 +421,7 @@ export const OPTIONAL_CAPABILITIES = [
421
421
  { label: "SDK post edit/update", symbols: [/\beditPost\b/i, /\bupdatePost\b/i, /\beditTextPost\b/i] },
422
422
  ],
423
423
  sensors: [
424
- { label: "PostRepository.editPost", regex: /PostRepository\.editPost\s*\(|(?<![.\w])editPost\s*\(/ },
424
+ { label: "PostRepository.editPost", regex: /PostRepository\.editPost\s*\(|\.editPost\s*\(|(?<![.\w])editPost\s*\(/ },
425
425
  ],
426
426
  hint: "If the user opts into author management, show edit only for post.postedUserId === currentUserId and call PostRepository.editPost with updated text data.",
427
427
  },
package/dist/outcomes.js CHANGED
@@ -629,7 +629,7 @@ const addFeed = {
629
629
  evidence: ["social-plus-sdk/social/content-management/posts/creation/poll-post"],
630
630
  },
631
631
  {
632
- step: "If the post composer supports poll creation, implement the two-step creation chain: (1) create the poll with the platform SDK poll repository — returns a Poll/pollId; (2) link that poll into a post with the platform post builder, for example `PostRepository.createPost({ targetType, targetId, data: { text: '', pollId } })` on TypeScript/React Native or `createPost().poll(pollId)` / `createPollPost(...)` on native SDKs. Rendering poll answers (votePoll/unvotePoll) is the read-side; without both creation steps the poll composer silently does nothing. Offer a dedicated poll-builder UI (question input + dynamic answer list) so users can author polls inline.",
632
+ step: "If the post composer supports poll creation, implement the two-step creation chain: (1) create the poll with the platform SDK poll repository — returns a Poll/pollId; (2) link that poll into a post with the platform post builder, for example `PostRepository.createPost({ targetType, targetId, data: { text: '', pollId } })` on TypeScript/React Native or Android's dedicated `createPollPost(targetType, targetId, pollId, text, ...)` API. Rendering poll answers (votePoll/unvotePoll) is the read-side; without both creation steps the poll composer silently does nothing. Offer a dedicated poll-builder UI (question input + dynamic answer list) so users can author polls inline.",
633
633
  evidence: [
634
634
  "social-plus-sdk/social/content-management/posts/creation/poll-post",
635
635
  "social-plus-sdk/social/posts",
@@ -189,7 +189,9 @@ async function validateAndroid(root) {
189
189
  ...(await existingFiles(root, ["app/build.gradle", "app/build.gradle.kts", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts"])),
190
190
  ...gradleScripts,
191
191
  ])];
192
+ const versionCatalogFiles = (await findFiles(root, [".toml"], 50)).filter((f) => /(?:^|[\\/])gradle[\\/].*\.versions\.toml$/.test(f));
192
193
  const buildContent = await readMany(buildFiles);
194
+ const versionCatalogContent = await readMany(versionCatalogFiles);
193
195
  const sourceFiles = await findFiles(root, [".kt", ".java"], 300);
194
196
  const sourceContent = await readMany(sourceFiles);
195
197
  const setupFiles = filesMatching(sourceContent, [/AmityCoreClient\s*\.\s*setup/, /AmityClient\s*\.\s*setup/]);
@@ -208,7 +210,7 @@ async function validateAndroid(root) {
208
210
  findings.push(finding("android.application.class", "warning", "No custom Application class is declared in AndroidManifest.xml.", manifestPath, "Initialize social.plus once from an Application class instead of an Activity or composable lifecycle."));
209
211
  }
210
212
  }
211
- if (!containsAny(buildContent, [/co\.amity\.android:amity-sdk/, /Amity-Social-Cloud-Android-SDK/, /com\.github\.AmityCo/])) {
213
+ if (!hasAndroidSdkDependency(buildContent, versionCatalogContent)) {
212
214
  findings.push(finding("android.dependency.sdk", "warning", "No obvious social.plus Android SDK dependency was found in Gradle files.", relativeFile(root, buildFiles[0]), "Add the SDK dependency from the Android quick-start docs and keep all Amity dependencies on compatible versions."));
213
215
  }
214
216
  else if (containsAny(buildContent, [/co\.amity\.android:amity-sdk:\+/, /co\.amity\.android:amity-sdk:latest/i, /version\s*=\s*["']\+["']/])) {
@@ -752,6 +754,9 @@ function validateFeedUiStates(root, platform, sourceContent) {
752
754
  return [];
753
755
  }
754
756
  for (const [file, content] of sourceContent) {
757
+ if (isNonUiSourceFile(file)) {
758
+ continue;
759
+ }
755
760
  const observes = observationPatterns.some((pattern) => pattern.test(content));
756
761
  if (!observes) {
757
762
  continue;
@@ -2159,6 +2164,38 @@ function filesMatching(contents, patterns) {
2159
2164
  }
2160
2165
  return matches;
2161
2166
  }
2167
+ function hasAndroidSdkDependency(buildContent, versionCatalogContent) {
2168
+ if (containsAny(buildContent, [/co\.amity\.android:amity-sdk/, /Amity-Social-Cloud-Android-SDK/, /com\.github\.AmityCo/])) {
2169
+ return true;
2170
+ }
2171
+ const aliases = androidSdkCatalogAliases(versionCatalogContent);
2172
+ if (aliases.length === 0) {
2173
+ return false;
2174
+ }
2175
+ const accessorPatterns = aliases.flatMap((alias) => versionCatalogAccessors(alias).map((accessor) => new RegExp(`\\b(?:api|implementation|compileOnly|runtimeOnly|testImplementation|androidTestImplementation)\\s*\\(\\s*(?:platform\\s*\\(\\s*)?libs\\.${escapeRegExp(accessor)}\\b`)));
2176
+ return containsAny(buildContent, accessorPatterns);
2177
+ }
2178
+ function androidSdkCatalogAliases(contents) {
2179
+ const aliases = new Set();
2180
+ const entryPattern = /^\s*([A-Za-z0-9_.-]+)\s*=\s*(.+)$/gm;
2181
+ for (const content of contents.values()) {
2182
+ for (const match of content.matchAll(entryPattern)) {
2183
+ const alias = match[1];
2184
+ const value = match[2];
2185
+ if (/co\.amity\.android:amity-sdk/.test(value) ||
2186
+ (/group\s*=\s*["']co\.amity\.android["']/.test(value) && /name\s*=\s*["']amity-sdk["']/.test(value))) {
2187
+ aliases.add(alias);
2188
+ }
2189
+ }
2190
+ }
2191
+ return [...aliases];
2192
+ }
2193
+ function versionCatalogAccessors(alias) {
2194
+ return [...new Set([
2195
+ alias,
2196
+ alias.replace(/[-_]/g, "."),
2197
+ ])];
2198
+ }
2162
2199
  function containsAny(contents, patterns) {
2163
2200
  for (const content of contents.values()) {
2164
2201
  if (patterns.some((pattern) => pattern.test(content))) {
@@ -2167,6 +2204,9 @@ function containsAny(contents, patterns) {
2167
2204
  }
2168
2205
  return false;
2169
2206
  }
2207
+ function escapeRegExp(value) {
2208
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2209
+ }
2170
2210
  function containsAnyForFiles(contents, files, patterns) {
2171
2211
  return files.some((file) => {
2172
2212
  const content = contents.get(file) ?? "";
@@ -2489,7 +2529,7 @@ function isNonUiSourceFile(filename) {
2489
2529
  // PascalCase class-named files (Swift, Kotlin, TS): suffix match. Note "Controller"
2490
2530
  // and "View(Model)" are deliberately absent — iOS ViewControllers/SwiftUI Views DO
2491
2531
  // render and must keep firing.
2492
- if (/(?:Manager|Repository|Repo|Service|DataSource|Datasource|Provider|Client|Store|Mapper|Interactor|UseCase|Bloc|Cubit|Notifier|Mock|Fake|Stub|Test|Tests|Spec)$/.test(base))
2532
+ if (/(?:Application|Manager|Repository|Repo|Service|DataSource|Datasource|Provider|Client|Store|Mapper|Interactor|UseCase|Bloc|Cubit|Notifier|Mock|Fake|Stub|Test|Tests|Spec)$/.test(base))
2493
2533
  return true;
2494
2534
  // snake_case files (Dart, sometimes RN): same non-UI layers, plus Flutter's BLoC /
2495
2535
  // Cubit / ChangeNotifier state-management layers. "_page"/"_popup"/"_screen" are UI
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amityco/social-plus-vise",
3
- "version": "0.14.14",
3
+ "version": "0.14.16",
4
4
  "description": "Skill-guided deterministic CLI for social.plus SDK integration assistance.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",